For use with An Introduction to Thermal Physics by Daniel V. Schroeder.
This code is written in Java (version 1.0). You can copy the code below and paste it into a file (call the file "Ising.java"), or click here to download a ready-to-compile copy in a separate file.
If you don't like Java, here are versions of this program written in Mathematica and True Basic. There's also a much more elaborate version written in REALbasic, which you can download (as source code or a compiled application) from here.
To compile and run this program, you must have the Java compiler and runtime environment installed on your computer. These are preinstalled on every Macintosh with OSX; just launch the Terminal application and cd to the directory containing Ising.java. To download Java for Windows, click here and follow the instructions (you want the "standard edition SDK"), including the part about updating the PATH variable, then open a DOS or Command Prompt window and cd to the directory containing Ising.java. You can also get Java for other operating systems, but I don't know how to install it. If you have a Macintosh and happen to have a Java virtual machine that runs under the Classic environment, you'll get better graphics performance than under OSX.
Once you have Java installed, and you have a command-line prompt with Ising.java in the current directory, just type "javac Ising.java" to compile, then "java Ising" to run the program. To stop the program, try command-Q or control-C or something like that.
Note that this program does not make particularly efficient use of Java's random number generator, since each call to Math.random actually makes two calls to the underlying generator, to obtain double precision. You can speed up the code with a judicious use of the java.util.Random methods.
import java.awt.*; // uses the abstract windowing toolkit
public class Ising {
// change the following globals to suit your fancy:
static int maxSize = 400; // width of window in pixels
static int size = 100; // lattice size; can be any divisor of maxSize
static double T = 2.27; // temperature in units of epsilon/k
static Color upColor = new Color(00,160,60);
static Color downColor = new Color(255,245,220);
// other globals:
static int squareWidth = maxSize / size;
static Graphics g; // the frame's graphics object, for drawing into
static int frameTop, frameLeft; // platform-dependent width of frame's top and left edges
static int[][] s; // the array of spins
public static void main(String[] args) {
int i, j; // indices into array of spins
double Ediff; // energy change upon flipping
// initialize window and graphics:
Frame gWin = new Frame("Ising Model");
gWin.setLocation(50,50); // screen coordinates of top left corner
gWin.setResizable(false);
gWin.setVisible(true); // show it!
Insets theInsets = gWin.getInsets();
gWin.setSize(maxSize+theInsets.left+theInsets.right,maxSize+theInsets.top+theInsets.bottom);
frameTop = theInsets.top;
frameLeft = theInsets.left;
long resumeTime = System.currentTimeMillis() + 1000;
do {} while (System.currentTimeMillis() < resumeTime); // wait for frame to get initialized
g = gWin.getGraphics(); // stick graphics object into a global so we can draw from anywhere!
// initialize array of spins:
s = new int[size][size];
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
if (Math.random() < 0.5) s[i][j] = 1; else s[i][j] = -1;
colorSquare(i,j);
}
}
// main loop:
while (true) {
i = (int) (Math.random() * size); // choose a random lattice site
j = (int) (Math.random() * size);
Ediff = deltaU(i,j); // compute hypothetical energy change upon flipping
if (Ediff <= 0.0) { // if energy would decrease...
s[i][j] = -s[i][j]; // flip it!
colorSquare(i,j);
}
else { // otherwise...
if (Math.random() < Math.exp(-Ediff/T)) { // Boltzmann factor gives flipping probability
s[i][j] = -s[i][j];
colorSquare(i,j);
}
}
}
}
// given a lattice site, compute energy change from hypothetical flip; note pbc:
private static double deltaU(int i, int j) {
int leftS, rightS, topS, bottomS; // values of neighboring spins
if (i == 0) leftS = s[size-1][j]; else leftS = s[i-1][j];
if (i == size-1) rightS = s[0][j]; else rightS = s[i+1][j];
if (j == 0) topS = s[i][size-1]; else topS = s[i][j-1];
if (j == size-1) bottomS = s[i][0]; else bottomS = s[i][j+1];
return 2.0 * s[i][j] * (leftS + rightS + topS + bottomS);
}
// given a lattice site, color that square according to the current s value:
private static void colorSquare(int i, int j) {
if (s[i][j] == 1) g.setColor(upColor); else g.setColor(downColor);
g.fillRect(squareWidth*i + frameLeft, squareWidth*j + frameTop, squareWidth, squareWidth);
}
}
Last modified on January 22, 2003.