/*********************************************** * Ising.java * * ----------------------------------- * * Created by Bernd Nottelmann in 1996 * * Last update (by Peter Young): March 25, 1997* ***********************************************/ import java.lang.*; import java.awt.*; import java.awt.image.*; public class Ising extends java.applet.Applet implements Runnable { /* Gitterparameter und Feldinhalt */ int dim; // Dimension des Modells int[] ndim; // Ausdehnung in jede Raumrichtung int period; // Zeitvariablen public IsingLattice lattice; // Eigentliches Gitter, hier spielt // sich alles Physikalische ab /* Oeffentliche Parameter */ public int n; // Gitterausdehnung in jede Richtung /* Physikalische Parameter des Modells */ public double Temp; /* Java-Objekte und -Parameter */ Thread is; public boolean stopped=false; // Halte-Flag short plotValue=1; // Spin-Wert boolean plotFlag=false; // Plot-Flag BorderLayout IsLay; // Layout IsingCanvas can; // Hier kommt das Gitter hin ... IsingPanel pan; // ... und hier die Bedienleiste // int[] Panxy={100,70,100,60}; // Platz fuer die Bedienelemente int[] Panxy={100,15,50,10}; // Platz fuer die Bedienelemente // muss auch sein int timeout=50; // Pause-Intervall fuer die // Bilderzeugung in ms public int t; // Zeitvariable public void init() { int j; // Indexvariable dim=2; // Quadratisch, praktisch, ... n=Integer.valueOf(getParameter("latt")).intValue(); // Gitterausdehnung holen Temp=Double.valueOf(getParameter("temp")).doubleValue(); // Temp. aus dem Applet Tag holen ndim=new int[dim]; for (j=0; j<dim; j++) ndim[j]=n; period=2*n; /* Gitter installieren */ lattice=new IsingLattice(dim,ndim,period,Temp); lattice.initHot(); t=0; /* Java-Initialisierungsteil */ setLayout(IsLay=new BorderLayout()); can=new IsingCanvas(this,Panxy); pan=new IsingPanel(this,can); can.init(); pan.init(); add("Center",can); add("South",pan); } public void start() { if (!stopped) { is=new Thread(this); is.start(); } pan.enable(); } public void stop() { pan.disable(); if (is.isAlive()) { is.stop(); System.gc(); } } public void brk() { is.stop(); stopped=true; System.gc(); } public void cont() { stopped=false; is=new Thread(this); is.start(); } public void setTemp(double Temp) { lattice.setTemp(Temp); pan.TempText.setText(new Double(lattice.Temp).toString()); pan.TempText.show(); can.redraw(true,false,false,false); } public void run() { while (true) { lattice.ssdUpdate(); ++t; can.Hamilton.addValue(lattice.Hamilton(lattice.t)); can.Magnetization.addValue(lattice.Magnetization(lattice.t)); try{ Thread.currentThread().sleep(timeout); } catch (InterruptedException e) {} { can.redraw(true,true,true,true); } } } public void paint() { lattice.ssdUpdate(); ++t; can.Hamilton.addValue(lattice.Hamilton(lattice.t)); can.Magnetization.addValue(lattice.Magnetization(lattice.t)); can.redraw(false,true,true,true); } public boolean handleEvent(Event ev) { switch (ev.id) { case Event.WINDOW_DESTROY: System.exit(0); case Event.MOUSE_DRAG: if (can.Tempxy[0]<=ev.x && ev.x<=can.Tempxy[2] && can.Tempxy[1]<=ev.y && ev.y<=can.Tempxy[3]) { setTemp((double)(can.Tempxy[3]-ev.y)/ (double)(can.Tempxy[3]-can.Tempxy[1])* (lattice.TempMax-lattice.TempMin)); return true; } else if (can.TempCritxy[0]<=ev.x && ev.x<=can.TempCritxy[2] && can.TempCritxy[1]<=ev.y && ev.y<=can.TempCritxy[3]) { setTemp(lattice.TempCrit); return true; } else if (Panxy[0]<=ev.x && ev.x<Panxy[0]+can.wh && Panxy[1]<=ev.y && ev.y<Panxy[1]+can.wh) { can.plot((int)((ev.x-Panxy[0])/can.dxy), (int)((ev.y-Panxy[1])/can.dxy),plotValue); can.redraw(false,true,false,false); } break; case Event.MOUSE_DOWN: if (Panxy[0]<=ev.x && ev.x<Panxy[0]+can.wh && Panxy[1]<=ev.y && ev.y<Panxy[1]+can.wh) { plotFlag=true; plotValue=(short)-lattice.getValue((int)((ev.x-Panxy[0])/can.dxy), (int)((ev.y-Panxy[1])/can.dxy)); return true; } break; case Event.MOUSE_UP: if (Panxy[0]<=ev.x && ev.x<Panxy[0]+can.wh && Panxy[1]<=ev.y && ev.y<Panxy[1]+can.wh) { plotFlag=false; return true; } break; case Event.KEY_PRESS: if (ev.key == 10) { setTemp(Double.valueOf(pan.TempText.getText().trim()).doubleValue()); return true; } break; case Event.KEY_RELEASE: break; default: if (ev.target instanceof Button) { String label=(String)ev.arg; if (label.equals("Init cold")) { if (is.isAlive()) brk(); lattice.initCold(-1); t=0; can.reset(); can.redraw(false,true,true,true); } else if (label.equals("Init hot")) { if (is.isAlive()) brk(); lattice.initHot(); t=0; can.reset(); can.redraw(false,true,true,true); } else if (label.equals("Init warm")) { if (is.isAlive()) brk(); lattice.initWarm(); t=0; can.reset(); can.redraw(false,true,true,true); } else if (label.equals("Start")) { if (!is.isAlive()) cont(); } else if (label.equals("Stop")) { brk(); can.SpinsDrawn=false; can.redraw(false,true,true,true); } else if (label.equals("Step")) { if (is.isAlive()) brk(); paint(); } else return false; return true; } else if (ev.target instanceof Checkbox) { if (!is.isAlive()) can.redraw(false,true,false,false); return true; } } return false; } public static void main(String args[]) { //System.out.println("Here is main!"); Frame frame=new Frame("Ising-Modell"); Ising ising=new Ising(); ising.init(); ising.start(); frame.add("Center",ising); frame.resize(frame.preferredSize()); frame.show(); } } /** Index-Klasse (wird fuers Permutieren benoetigt) **/ class IsingIntIndex { public int[] value; // Feldwert public int[] prev, next; // Vorheriger/naechster Index int n, filled; // Feldgroesse, Fuellstand int first, last; // Erstes/letztes Element int i, actual; // Indexvariablen int[] retval; // Rueckgabefeld public IsingIntIndex(int n) { // Konstruktor, n: Feldgroesse value=new int[n]; prev=new int[n]; next=new int[n]; this.n=n; first=last=-1; filled=0; retval=new int[n]; } public void init(int val) { // Mit erstem Eintrag initialisieren value[0]=val; prev[0]=next[0]=-1; first=last=0; filled=1; } public void insert(int val, int k) { // Element val an Stelle k einfuegen actual=first; for (i=0; i<k; ++i) if (actual > -1) actual=next[actual]; value[filled]=val; if (actual > -1) { if (actual!=first) { next[prev[actual]]=filled; prev[filled]=prev[actual]; } else first=filled; prev[actual]=filled; } else { prev[filled]=last; next[last]=filled; last=filled; } next[filled++]=actual; } public int[] get() { // Feld holen actual=first; for (i=0; i<filled; ++i) { retval[i]=value[actual]; actual=next[actual]; } return retval; } } /** Gitter-Klasse fuers Ising-Modell **/ final class IsingLattice { /* Gitterparameter und Feldinhalt */ public int dim=2; // Quadratisch, praktisch, ... public int[] ndim; // Ausdehnung in jede Raumrichtung public int nind; // Volumen des Spinfeldes public int[][] index; // Feld benachbarter Indizes private int[] index0, index1, index2, index3; // Verbessert hoffentlich Zeitverhalten /* Weitere oeffentliche Parameter */ public short[][] sigma; // Spinfeld public int n=0; // dito, nur in einer Variable public int t=0; // Aktuelle Zeit; /* Physikalische Parameter des Modells */ public static final double TempMin=0.01; public static final double TempMax=6; public static final double TempCrit=2.2691; // TempCrit=2/ln(1+sqrt 2) public double Temp; public double beta; double[] tabexp = new double [9]; int[] randindex; // Zufallspermutiertes Indexfeld IsingIntIndex helpIndex; // Hilfsindexfeld fuer die Perms int t0=t, period; // Zeitvariablen public IsingLattice(int dim, int[] ndim, int period, double Temp) { int i, j; // Indexvariable /* Gitter initialisieren */ this.dim=dim; this.ndim=ndim; this.period=period; if (Temp >= TempMin && Temp < TempMax) this.Temp=Temp; else this.Temp=(TempMin+TempMax)/2; // Die goldene Mitte beta=1/this.Temp; tabexp[8] = Math.exp(-8*beta) / (Math.exp(-8*beta) + 1. ); tabexp[6] = Math.exp(-4*beta) / (Math.exp(-4*beta) + 1. ); tabexp[4] = 0.5; tabexp[2] = 1. / (Math.exp(-4*beta) + 1.); tabexp[0] = 1. / (Math.exp(-8*beta) + 1.); nind=1; // Volumen des Feldes berechnen for (j=0; j<dim; j++) nind*=ndim[j]; sigma=new short[period][nind]; // T=2*n: Ausdehnung in Zeitrichtung index=new int[2*dim][nind]; randindex=new int[nind]; for (i=0; i<nind; i++) // Zufallsindex erst einmal mit randindex[i]=i; // 0..nind initialisieren helpIndex=new IsingIntIndex(nind); calcIndex(); index0=index[0]; index1=index[1]; index2=index[2]; index3=index[3]; } /** Kaltstart value: Initialisierungswert **/ public void initCold(int value) { int i; for (i=0; i<nind; i++) sigma[t][i]=(short)value; } /** Hotstart **/ public void initHot() { int i, j, m, digit, v, sgn; for (i=0; i<nind; i++) { v=1; m=i; sgn=0; for (j=0; j<dim; j++) { digit=m%ndim[j]; sgn^=digit&1; m=(m-digit)/ndim[j]; v*=ndim[j]; } sigma[t][i]=(short)(2*sgn-1); } } /** Warmstart **/ public void initWarm() { int i; for (i=0; i<nind; i++) sigma[t][i]=(short)(2*(short)(2*Math.random())-1); } /** Funktion F mit F(z)/F(1/z)=z **/ private double F(double z) { return (z < 1) ? z : 1; } /** Indexfelder initialisieren (mit periodischen Randbedingungen) **/ private void calcIndex() { int i, j, m, digit, v; for (i=0; i<nind; i++) { // Lineare Nachbarindizes bestimmen v=1; m=i; // v: "Zwischen"volumen for (j=0; j<dim; j++) { digit=m%ndim[j]; index[j][i]=i-(digit-(ndim[j]+digit-1)%ndim[j])*v; index[j+dim][i]=i-(digit-(digit+1)%ndim[j])*v; m=(m-digit)/ndim[j]; v*=ndim[j]; } } } /** Wert holen **/ public short getValue(int x, int y) { if (0 <= x && x < ndim[0] && 0 <= y && y < ndim[1]) return sigma[t][x+ndim[0]*y]; else return 0; } /** Temperatur setzen Temp: na ratet mal! **/ public void setTemp(double Temp) { if (TempMin <= Temp && Temp < TempMax) { this.Temp=Temp; beta=1/Temp; tabexp[8] = Math.exp(-8*beta) / (Math.exp(-8*beta) + 1. ); tabexp[6] = Math.exp(-4*beta) / (Math.exp(-4*beta) + 1. ); tabexp[4] = 0.5; tabexp[2] = 1. / (Math.exp(-4*beta) + 1.); tabexp[0] = 1. / (Math.exp(-8*beta) + 1.); } else if (Temp >= TempMax) { this.Temp=TempMax; beta=0; tabexp[8] = Math.exp(-8*beta) / (Math.exp(-8*beta) + 1. ); tabexp[6] = Math.exp(-4*beta) / (Math.exp(-4*beta) + 1. ); tabexp[4] = 0.5; tabexp[2] = 1. / (Math.exp(-4*beta) + 1.); tabexp[0] = 1. / (Math.exp(-8*beta) + 1.); } } /** 2 dim-Hamiltonian des Ising-Modells t: Zeit (ist doch offensichtlich! :-) **/ public double Hamilton(int t) { int i; double sum=0; for (i=0; i<nind; ++i) sum+=sigma[t][i]*(sigma[t][index0[i]]+sigma[t][index1[i]]); // return -2*sum; return -sum/nind; } public double HamiltonMin() { // return -2*dim*nind; return -dim; } public double HamiltonMax() { // return 2*dim*nind; return dim; } public double Magnetization(int t) { int i; int sum=0; for (i=0; i<nind; ++i) sum+=sigma[t][i]; return (double)sum/nind; } /** Indexfeld zufaellig permutieren **/ private void perm() { int i, k; helpIndex.init(randindex[0]); for (i=1; i<nind; ++i) { k=(int)((i+1)*Math.random()); helpIndex.insert(randindex[i],k); } randindex=helpIndex.get(); } /** Spinkonfiguration updaten fuer Single-spin-flip dynamics **/ public synchronized int ssdUpdate() { int i, k, de; int flag; double abuf, rand; int sigmasum=0; t0=t; // Zeit urspruengliche Spinkofiguration t=++t%period; // Zeit aktuelle Spinkonfiguration for (i=0; i<nind; ++i) sigmasum+=sigma[t][i]=sigma[t0][i]; for (i=0; i<nind; ++i) { de = 4 + sigma[t][i] * (sigma[t][index0[i]] + sigma[t][index1[i]] +sigma[t][index2[i]] + sigma[t][index3[i]]); rand=Math.random(); if ( rand < tabexp[de] ) { sigma[t][i]=(short)-sigma[t][i]; sigmasum+=2*sigma[t][i]; } } return sigmasum; } } class IsingFever { String title; // Titel (:-) double[] y; // y-Werte der "Fieberkurven"; public int n; // Zahl der Werte int width, height; // Breite und Hoehe int offset, top, bottom; // y-Offset, Begrenzungslinien int range; // Zeichenbereich double xScale, yScale; // Skalierungsfaktoren int index, length; // Aktuelle Kennwerte der Kurven double yMin, yMax, yMean; // Extremwerte + deren Mittelwert public Image img; Graphics g; public Color color; public IsingFever(String title, int n) { //System.out.println("IsingFever(int n)"); this.title=title; this.n=n; y=new double[n]; index=-1; length=0; } public void init(double value, double yMin, double yMax) { index=0; length=1; y[index]=value; if (value < yMin || value > yMax || yMin > yMax) yMean=this.yMin=this.yMax=value; else { this.yMin=yMin; this.yMax=yMax; yMean=(yMin+yMax)/2; } } public void initGraphics(ImageObserver imgObs, Image img, Color color) { this.img=img; this.g=img.getGraphics(); this.color=color; width=img.getWidth(imgObs); height=img.getHeight(imgObs); bottom=(int)(0.95*height+0.5)-1; top=(int)(0.05*height+0.5)-1; range=(int)(0.9*height); offset=height/2; xScale=(double)width/n; g.setColor(Color.black); g.fillRect(0,0,width,height); drawLines(); draw(color); } private void draw(Color color) { int i, j, k; if (yMax > yMin) yScale=range/(yMax-yMin); else yScale=1; if (g != null) { g.setColor(color); i=index; k=length; while (--k > 0) { j=(n+i-1)%n; g.drawLine((int)(xScale*k), offset-(int)((y[i]-yMean)*yScale+0.5), (int)(xScale*(k-1)), offset-(int)((y[j]-yMean)*yScale+0.5)); i=j; } } } private void drawLines() { if (g != null) { g.setColor(Color.lightGray); g.drawLine(0,offset,width-1,offset); g.setColor(Color.darkGray); g.drawLine(0,top,width-1,top); g.drawLine(0,bottom,width-1,bottom); } } /* Wert hinzufuegen und gleichzeitig neue Kurve zeichnen */ public synchronized void addValue(double value) { //System.out.println("addValue(double value)"); draw(Color.black); // Erstmal alte Kurve loeschen drawLines(); index=(++index)%n; y[index]=value; if (value < yMin) yMin=value; else if (value > yMax) yMax=value; yMean=(yMin+yMax)/2; if (length < n) ++length; draw(color); // Neue Kurve zeichnen } /* Beschriftung */ public void drawParams(Graphics g, int x, int y) { Font f; FontMetrics fm; int x0, y0; String s1, s2; int w1, w2, wMax; f=new Font("TimesRoman",Font.PLAIN,17); g.setFont(f); fm=g.getFontMetrics(); s1=new Double(yMax).toString(); s2=new Double(yMin).toString(); w1=fm.stringWidth(s1); w2=fm.stringWidth(s2); wMax=(w1 <= w2) ? w1 : w2; g.setColor(Color.black); x0=x+width+8+wMax-w1; y0=y+top+f.getSize()/2; g.drawString(s1,x0,y0); x0=x+width+8+wMax-w2; y0=y+bottom+f.getSize()/2; g.drawString(s2,x0,y0); x0=x+width+8; y0=y+offset+f.getSize()/2; g.drawString(title,x0,y0); } } final class IsingCanvas extends Canvas implements ImageObserver { Ising is; int n; public int[] Panxy; public double dx, dy, dxy; public int wh; Rectangle Rect; Image img, HamiltonImg, MagnetizationImg; Graphics imgGra; public IsingFever Hamilton, Magnetization; boolean GridForbidden=false; public boolean GridFlag=true; //public boolean GridFlag=false; boolean ThermoFlag=true, sigmaFlag=true, FeverFlag=true, TimeFlag=true; public boolean SpinsDrawn=false; short[] Spin; public int[] Tempxy=new int[4]; public int[] TempCritxy=new int[4]; public IsingCanvas(Ising is, int[] Panxy) { this.is=is; n=is.n; this.Panxy=Panxy; Hamilton=new IsingFever("Energy per spin",(int)(0.8*Panxy[2])); Magnetization=new IsingFever("Magnetization",(int)(0.8*Panxy[2])); Spin=new short[is.lattice.nind]; } public void init() { Hamilton.init(is.lattice.Hamilton(is.lattice.t), is.lattice.HamiltonMin(),is.lattice.HamiltonMax()); Magnetization.init(is.lattice.Magnetization(is.lattice.t),-1,1); SpinsDrawn=false; } public void reset() { init(); Hamilton.initGraphics(this, createImage(Hamilton.width, Hamilton.height), Hamilton.color); Magnetization.initGraphics(this, createImage(Magnetization.width, Magnetization.height), Magnetization.color); SpinsDrawn=false; } public void setGridFlag(boolean GridFlag) { if (!GridForbidden) { this.GridFlag=GridFlag; if (GridFlag) { img.flush(); img=createImage(wh+1,wh+1); imgGra=img.getGraphics(); paintGrid(imgGra); } else { img.flush(); img=createImage(wh,wh); imgGra=img.getGraphics(); } } SpinsDrawn=false; } public void plot(int x, int y, short value) { if (x >= 0 && x < n && y >=0 && y < n) { Spin[x+n*y]=is.lattice.sigma[is.lattice.t][x+n*y]=value; imgGra.setColor(Color.blue); if (GridFlag) if (value > 0) imgGra.fillRect((int)(x*dxy)+1,(int)(y*dxy)+1, (int)dxy-1,(int)dxy-1); else imgGra.clearRect((int)(x*dxy)+1,(int)(y*dxy)+1, (int)dxy-1,(int)dxy-1); else if (value > 0) imgGra.fillRect((int)(x*dxy),(int)(y*dxy), (int)dxy,(int)dxy); else imgGra.clearRect((int)(x*dxy),(int)(y*dxy), (int)dxy,(int)dxy); } } private void drawSpins() { int i, j, t, pos=0; imgGra.setColor(Color.blue); t=is.lattice.t; if (GridFlag) if (!SpinsDrawn) for (j=0; j<n; ++j) for (i=0; i<n; ++i) if (is.lattice.sigma[t][pos++] > 0) imgGra.fillRect((int)(i*dxy)+1,(int)(j*dxy)+1, (int)dxy-1,(int)dxy-1); else imgGra.clearRect((int)(i*dxy)+1,(int)(j*dxy)+1, (int)dxy-1,(int)dxy-1); else for (j=0; j<n; ++j) for (i=0; i<n; ++i) { if (is.lattice.sigma[t][pos] != Spin[pos]) if (is.lattice.sigma[t][pos] > 0) imgGra.fillRect((int)(i*dxy)+1,(int)(j*dxy)+1, (int)dxy-1,(int)dxy-1); else imgGra.clearRect((int)(i*dxy)+1,(int)(j*dxy)+1, (int)dxy-1,(int)dxy-1); ++pos; } else { imgGra.clearRect(0,0,wh+1,wh+1); for (j=0; j<n; ++j) for (i=0; i<n; ++i) if (is.lattice.sigma[t][pos++] > 0) imgGra.fillRect((int)(i*dxy),(int)(j*dxy), (int)dxy,(int)dxy); } Spin=is.lattice.sigma[t]; SpinsDrawn=true; } private void paintGrid(Graphics g) { int i; g.setColor(Color.black); for (i=0; i<=n; i++) { g.drawLine(0,(int)(i*dxy),wh,(int)(i*dxy)); g.drawLine((int)(i*dxy),0,(int)(i*dxy),wh); } } /* Thermometer zeichnen */ private void paintThermo(Graphics g) { double x,y,r1,r2,h; double factor=Math.PI/180; int x0,y0,x1,y1,h0,alpha,gamma; r1=0.1*Panxy[0]; r2=0.05*Panxy[0]; h=0.8*wh; x=Panxy[0]/2; y=Panxy[1]+wh-(wh-(h+r1+r2))/2; Tempxy[0]=(int)(x-r2); // Koordinaten des Steuerbereichs Tempxy[1]=(int)(y-h); // des Thermometers festlegen Tempxy[2]=(int)(x+r2); Tempxy[3]=(int)y; alpha=90+(int)(Math.asin(r2/r1)/factor); gamma=360-2*(alpha-90); x0=(int)(x-r1); y0=(int)(y-(r1-r1*Math.cos(factor*(alpha-90)))); g.setColor(Color.red); g.fillArc(x0,y0,(int)(2*r1),(int)(2*r1),alpha,gamma); g.setColor(Color.black); g.drawArc(x0,y0,(int)(2*r1),(int)(2*r1),alpha,gamma); x0=(int)(x-r2); y0=(int)(y-h*is.lattice.Temp/is.lattice.TempMax); h0=(int)(h*is.lattice.Temp/is.lattice.TempMax+ r1*Math.cos(factor*(alpha-90))); g.setColor(Color.red); g.fillRect(x0,y0,(int)(2*r2),h0); y0=(int)(y-h); h0=(int)(h-h*is.lattice.Temp/is.lattice.TempMax); g.setColor(Color.lightGray); g.fillRect(x0,y0,(int)(2*r2),h0); g.setColor(Color.black); g.drawLine(x0,y0,x0,(int)(y0+h)); g.drawLine(x0+(int)(2*r2),y0,x0+(int)(2*r2),(int)(y0+h)); y0=(int)(y-h-r2); g.setColor(Color.lightGray); g.fillArc(x0,y0,(int)(2*r2),(int)(2*r2),0,180); g.setColor(Color.black); g.drawArc(x0,y0,(int)(2*r2),(int)(2*r2),0,180); } private void drawTitle(Graphics g, String s, int x, int y, int fs) { int red, green, blue; Font f; FontMetrics fm; int i; String subs; red=(int)(Math.random()*150); green=(int)(Math.random()*100); blue=(int)(Math.random()*50); f=new Font("TimesRoman",Font.ITALIC,fs); g.setFont(f); fm=g.getFontMetrics(); y+=f.getSize(); for (i=0; i<s.length(); i++) { subs=s.substring(i,i+1); g.setColor(new Color((red+x/2)%256,(green+x)%256,(blue+x/4)%256)); g.drawString(subs,x,y); x+=fm.stringWidth(subs); } } private void drawTime(Graphics g) { Font f; FontMetrics fm; String s="t="+new Integer(is.t).toString(); int x, y; f=new Font("TimesRoman",Font.PLAIN,17); g.setFont(f); fm=g.getFontMetrics(); x=Panxy[0]+(wh-fm.stringWidth(s))/2; y=Panxy[1]-4; g.setColor(Color.black); g.clearRect(Panxy[0],Panxy[1]-f.getSize()-4,wh,f.getSize()); g.drawString(s,x,y); } private void drawTempCrit(Graphics g) { Font f; FontMetrics fm; int x, y; String s1="T", s2="Crit"; f=new Font("TimesRoman",Font.PLAIN,17); g.setFont(f); fm=g.getFontMetrics(); x=Tempxy[2]+6; y=Tempxy[3]- (int)(is.lattice.TempCrit/(is.lattice.TempMax-is.lattice.TempMin)* (Tempxy[3]-Tempxy[1])); TempCritxy[0]=Tempxy[2]; TempCritxy[1]=y-f.getSize()/2; g.setColor(new Color(127,0,127)); g.drawLine(Tempxy[2]+1,y,Tempxy[2]+4,y); y+=f.getSize()/2; g.drawString(s1,x,y); x+=fm.stringWidth(s1); f=new Font("TimesRoman",Font.PLAIN,12); g.setFont(f); fm=g.getFontMetrics(); y+=f.getSize()/2; g.drawString(s2,x,y); x+=fm.stringWidth(s2); TempCritxy[2]=x; TempCritxy[3]=y; } public void paint(Graphics g) { Rect=bounds(); dx=(Rect.width-Panxy[0]-Panxy[2])/n; dy=(Rect.height-Panxy[1]-Panxy[3])/n; dxy=(dx <= dy) ? dx : dy; wh=(int)(n*dxy); if (dxy<=2) { GridForbidden=true; GridFlag=false; } if (GridFlag) { img=createImage(wh+1,wh+1); imgGra=img.getGraphics(); paintGrid(imgGra); } else { img=createImage(wh,wh); imgGra=img.getGraphics(); } Hamilton.initGraphics(this, createImage(Hamilton.n,(int)(0.9*wh/2)), Color.cyan); Magnetization.initGraphics(this, createImage(Magnetization.n,(int)(0.9*wh/2)), Color.cyan); SpinsDrawn=false; drawSpins(); paintThermo(g); drawTempCrit(g); // drawTitle(g,"Simple Ising Model v1.0", // Panxy[0],(int)(0.05*Panxy[1]),(int)(0.4*Panxy[1])); drawTime(g); g.drawImage(img,Panxy[0],Panxy[1],this); g.drawImage(Hamilton.img, Panxy[0]+wh+(int)(0.2*Panxy[2]),Panxy[1], this); g.drawImage(Magnetization.img, Panxy[0]+wh+(int)(0.2*Panxy[2]),Panxy[1]+wh/2, this); Hamilton.drawParams(g,Panxy[0]+wh+(int)(0.2*Panxy[2]),Panxy[1]); Magnetization.drawParams(g,Panxy[0]+wh+(int)(0.2*Panxy[2]),Panxy[1]+wh/2); } public void update(Graphics g) { // Weg mit dem Flackern!!! if (ThermoFlag || !is.stopped) paintThermo(g); if (sigmaFlag || !is.stopped) { drawSpins(); img.flush(); g.drawImage(img,Panxy[0],Panxy[1],this); } if (TimeFlag || !is.stopped) drawTime(g); if (FeverFlag || !is.stopped) { Hamilton.img.flush(); g.drawImage(Hamilton.img, Panxy[0]+wh+(int)(0.2*Panxy[2]),Panxy[1], this); Magnetization.img.flush(); g.drawImage(Magnetization.img, Panxy[0]+wh+(int)(0.2*Panxy[2]),Panxy[1]+wh/2, this); } } public synchronized void redraw(boolean ThermoFlag, boolean sigmaFlag, boolean FeverFlag, boolean TimeFlag) { this.ThermoFlag=ThermoFlag; this.sigmaFlag=sigmaFlag; this.FeverFlag=FeverFlag; this.TimeFlag=TimeFlag; repaint(); } } class EnterTextField extends TextField { Component parent; public EnterTextField(Component parent, String text, int cols) { super(text,cols); this.parent=parent; } public boolean keyDown(Event ev, int key) { if (key == 10) { parent.postEvent(ev); return true; } return false; } public boolean keyUp(Event ev, int key) { if (key == 10) return true; return false; } } class TextOutField extends Canvas { String text; Font font; Color color; public TextOutField(String text, Font font, Color color) { super(); this.text=text; this.font=font; this.color=color; } public void paint(Graphics g) { g.setFont(font); g.setColor(color); g.drawString(text,0,font.getSize()); } } class IsingPanel extends Panel { Ising is; IsingCanvas can; GridBagLayout GBLay; GridBagConstraints c; Checkbox check; Double Temp; public TextOutField Blubber; public EnterTextField TempText; boolean dummy; public IsingPanel(Ising is, IsingCanvas can) { this.is=is; this.can=can; } protected void makebutton(String name, GridBagLayout gb, GridBagConstraints gbc) { Button button=new Button(name); gb.setConstraints(button,gbc); add(button); } public void init() { GBLay=new GridBagLayout(); c=new GridBagConstraints(); setLayout(GBLay); c.gridx=0; c.gridy=0; c.gridheight=1; c.fill=GridBagConstraints.BOTH; Blubber=new TextOutField("Temperature", new Font("TimesRoman",Font.PLAIN,14), Color.red); GBLay.setConstraints(Blubber,c); add(Blubber); c.gridy=1; Temp=new Double(is.lattice.Temp); if (Temp.doubleValue() == is.lattice.TempMax) Temp=new Double(Double.POSITIVE_INFINITY); TempText=new EnterTextField(is,Temp.toString(),10); GBLay.setConstraints(TempText,c); add(TempText); c.gridx=1; c.gridy=0; makebutton("Init cold",GBLay,c); c.gridx=2; // makebutton("Init hot",GBLay,c); c.gridx=3; makebutton("Init warm",GBLay,c); c.gridx=4; c.gridheight=2; check=new Checkbox("Grid"); check.setState(can.GridFlag); GBLay.setConstraints(check,c); add(check); c.gridx=1; c.gridy=1; c.gridheight=1; makebutton("Start",GBLay,c); c.gridx=2; makebutton("Stop",GBLay,c); c.gridx=3; makebutton("Step",GBLay,c); } public boolean action(Event ev, Object arg) { if (ev.target instanceof Button) { is.postEvent(ev); return true; } else if (ev.target instanceof Checkbox) { if (can.GridForbidden) check.hide(); else can.setGridFlag(check.getState()); is.postEvent(ev); return true; } else if (ev.id == Event.MOUSE_DRAG || ev.id == Event.MOUSE_DOWN || ev.id == Event.MOUSE_UP) { is.postEvent(ev); return true; } return false; } }