// 2D Ising with Metropolis algorithm, Evgeny Demidov 23 Oct 2006 // based on Harvey Gould and Jan Tobochnik sources http://sip.clarku.edu import java.awt.*; import java.awt.event.*; public class @file extends java.applet.Applet implements MouseListener, MouseMotionListener, ItemListener, KeyListener, ActionListener, Runnable { Thread thCycle; int L = 50,L1, M, E, d, w, hd, hBut = 30, border = 0, nInit = 0, it, Mi[], Ei[], spin[][]; double T = 2.269, avM, avMM, avE, avEE, wi[]; boolean painted = false, bCycle = false; long generTime; float flM, flE; Image buffImage; Graphics buffGraphics; Choice chL,chBorder,chInit; Label lbL,lbT,lbBorder,lbInit; TextField tfT; Button btRun, btClear, btPrint; public void init(){ w = getSize().width - 200 - 10; spin = new int[w+2][w+2]; Mi = new int[w]; Ei = new int[w]; String s=getParameter("L"); if (s != null) L = Integer.parseInt(s); d = w/L; hd = w-d; L1 = L+1; s=getParameter("T"); if (s != null) T = Double.valueOf(s).doubleValue(); s=getParameter("Init"); if (s != null) nInit = Integer.parseInt(s); wi = new double[5]; wi[0] = 1.; for (int i = 1; i < 5; i++) wi[i] = Math.exp(-2*i/T); setup(); lbT = new Label("T", Label.RIGHT); add(lbT); tfT = new TextField( "" + (float)T, 5); add(tfT); tfT.addKeyListener(this); lbL = new Label("L", Label.RIGHT); add(lbL); chL = new Choice(); if (w == 400){ chL.addItem("20"); for (int i = 0, l = 50; i < 4; i++){ chL.addItem(Integer.toString(l)); l *= 2;}} else for (int i = 0, l = 20; i < 6; i++){ chL.addItem(Integer.toString(l)); l *= 2;}; chL.select(""+L); chL.addItemListener(this); add(chL); lbBorder = new Label("border", Label.RIGHT); add(lbBorder); chBorder = new Choice(); chBorder.addItem("free"); chBorder.addItem(" +1 "); chBorder.select(border); chBorder.addItemListener(this); add(chBorder); lbInit = new Label("init", Label.RIGHT); add(lbInit); chInit = new Choice(); chInit.addItem(" -1 "); chInit.addItem("rand"); chInit.addItem(" +1 "); chInit.select(nInit + 1); chInit.addItemListener(this); add(chInit); btRun = new Button("Run "); btRun.addActionListener(this); add(btRun); btClear = new Button("Clear"); btClear.addActionListener(this); add(btClear); btPrint = new Button("Print"); btPrint.addActionListener(this); add(btPrint); buffImage = createImage(w+210, w); buffGraphics = buffImage.getGraphics(); addMouseListener(this); addMouseMotionListener(this); } public void setup(){ it = 0; for (int i = 0; i < w; i++) Mi[i] = Ei[i] = w; for (int i = 0; i <= L1; i++) spin[0][i] = spin[L1][i] = spin[i][0] = spin[i][L1] = border; M = E = it = 0; for (int i = 1; i < L1; i++) for (int j = 1; j < L1; j++){ int s; if (nInit != 0) s = spin[i][j] = nInit; else if (Math.random() > .5) s = spin[i][j] = 1; else s = spin[i][j] = -1; M += s; E -= s*(spin[i-1][j] + spin[i][j-1]);} for (int i = 1; i < L1; i++){ E -= spin[i][L]*spin[i][L1]; E -= spin[L][i]*spin[L1][i];} M /= 2; E /= 2; } public void destroy(){ removeMouseListener(this); removeMouseMotionListener(this); } public void run() { while(true) { if ( Thread.currentThread() != thCycle ) return; MC(); painted = false; repaint(); try { Thread.sleep( 20 ); } catch (InterruptedException e) {} } } public void stop(){ thCycle = null; } public void actionPerformed(ActionEvent e){ if ( e.getActionCommand().equals("Clear") ){ for (int i = 0; i < w; i++) Mi[i] = Ei[i] = w; it = 0; avM = avMM = avE = avEE = 0.; showStatus( "it="+ it);} else if ( e.getActionCommand().equals("Print") ){ double Mt = avM/it, Et = avE/it, n = L*L; showStatus( "T="+ (float)T +" M="+ (float)Mt + " x="+ (float)(n*(avMM/it - Mt*Mt)/T) +" E="+ (float)Et + " C="+ (float)(n*(avEE/it - Et*Et)/(T*T)) +" it="+ it ); System.out.println( ""+ (float)T +" "+ (float)Mt + " "+ (float)(n*(avMM/it - Mt*Mt)/T) +" "+ (float)Et + " "+ (float)(n*(avEE/it - Et*Et)/(T*T)) );} else{ if (bCycle){ bCycle = false; btRun.setLabel("Run "); thCycle = null;} else { bCycle = true; btRun.setLabel("Stop"); thCycle = new Thread(this); thCycle.start();}} } public void mouseClicked(MouseEvent e){} // event handling public void mousePressed(MouseEvent e) { if( e.getX() < w){ MC(); painted = false; repaint();} e.consume(); } public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseMoved(MouseEvent e) {} public void mouseDragged(MouseEvent e) { if( e.getX() > w){ T = 6. - (e.getY() - 30)*6./w; for (int i = 1; i < 5; i++) wi[i] = Math.exp(-2*i/T); tfT.setText(""+(float)T); painted = false; repaint();} e.consume(); } public void keyTyped(KeyEvent e){} public void keyPressed(KeyEvent e){} public void keyReleased(KeyEvent e){ final int keyEnter = 10; if (e.getKeyCode() == keyEnter){ try{ T = Double.valueOf(tfT.getText()).doubleValue(); }catch(NumberFormatException ne){} for (int i = 1; i < 5; i++) wi[i] = Math.exp(-2*i/T); painted = false; repaint(); } e.consume(); } public void itemStateChanged(ItemEvent e){ Object src = e.getSource(); if (src == chL){ L = Integer.parseInt(chL.getSelectedItem()); d = w/L; hd = w-d; L1 = L+1;} if (src == chBorder) border = chBorder.getSelectedIndex(); if (src == chInit) nInit = chInit.getSelectedIndex() - 1; setup(); painted = false; repaint(); } public void MC(){ generTime = System.currentTimeMillis(); for (int i = 1; i < L1; i++) for (int j = 1; j < L1; j++){ int sum = spin[i][j]* (spin[i][j+1] + spin[i][j-1] + spin[i+1][j] + spin[i-1][j]); if ( (sum <= 0)||(Math.random() < wi[sum]) ){ int s = spin[i][j] = -spin[i][j]; M += s; E += sum;}} flM = 2*(float)M/(L*L); flE = 2*(float)E/(L1*L1); avM += flM; avMM += flM*flM; avE += flE; avEE += flE*flE; Mi[it % w] = w + (int)(100*(flM + 1)); Ei[it % w] = w + (int)(50*(flE + 2)); it++; generTime = System.currentTimeMillis() - generTime; } public void paint(Graphics g){ if ( !painted ){ buffGraphics.setColor(Color.white); buffGraphics.fillRect(0, 0, w+200, w); buffGraphics.setColor(Color.black); for (int i = 0; i < L; i++) for (int j = 0; j < L; j++) if (spin[i+1][j+1] < 0) buffGraphics.fillRect(j*d,hd-i*d, d,d); buffGraphics.setColor(Color.lightGray); for (int i = 0; i < 200; i += 20) buffGraphics.drawLine(w+i, 0, w+i, w); buffGraphics.setColor(Color.gray); buffGraphics.drawLine(w+100, 0, w+100, w); buffGraphics.setColor(Color.red); for (int i = 0; i < w; i++) buffGraphics.drawLine(Mi[i], i, Mi[i], i); buffGraphics.setColor(Color.blue); for (int i = 0; i < w; i++) buffGraphics.drawLine(Ei[i], i, Ei[i], i); int Ti = (int)((1. - T/6.)*w); buffGraphics.setColor(Color.red); buffGraphics.fillRect(w+200, Ti, 10, w-Ti); buffGraphics.setColor(Color.white); buffGraphics.fillRect(w+200, 0, 10, Ti); buffGraphics.setColor(Color.black); buffGraphics.fillRect(w+200, (int)((1. - 2.269/6.)*w)-1, 10, 3); painted = true;} g.drawImage(buffImage, 0, hBut, this); showStatus( "T="+ (float)T +" it="+ it +" M="+ flM + " E="+ flE +" t="+ generTime +"ms "); } public void update(Graphics g){ paint(g); } }