Home
|
Course Outline
|
Lectures
|
Homework
|
Files
Here is the code which generates this applet:
// Macrostates.java
import comphys.graphics.*;
import comphys.Easy;
import java.awt.event.*;
public class Macrostates extends Animation {
// Count microstates in each macrostate
// specified by sum(s_i) and sum(s_i * s_j)
int Lx = 4; // lattice extent in x direction
int Ly = 4; // lattice extent in y direction
int N = Lx * Ly; // number of spins
int[][] spin; // 2-d array of spin variables
boolean hotStart; // initial random spins
int M; // total magnetic moment (spin sum)
int SS; // sum s_i * s_j (bond sum)
int microState; // microstate number
int[][] macroState; // to count micros in each macro
int maxMacro; // max number of micros is any macro
int Nmax = 30; // max N for exact evaluation
boolean exact; // do exact evaluation if N <= Nmax
int exactMicroStates; // exact number of microstates
double T = 2; // absolute temperature kT
double[] F, E, TS; // free energy, energy, entropy
double FESmin, FESmax; // for plotting
int spinSum () {
int sum = 0;
for (int x = 0; x < Lx; x++)
for (int y = 0; y < Ly; y++)
sum += spin[x][y];
return sum;
}
int bondSum () {
int sum = 0;
for (int x = 0; x < Lx; x++) {
int right = x + 1;
if (right == Lx)
right = 0;
for (int y = 0; y < Ly; y++) {
int up = y + 1;
if (up == Ly)
up = 0;
int neighbors = spin[x][up] + spin[right][y];
sum += spin[x][y] * neighbors;
}
}
return sum;
}
void initial () {
N = Lx * Ly;
if (N > Nmax)
exact = false;
if (N <= Nmax) {
exactMicroStates = 1;
for (int i = 0; i < N; i++)
exactMicroStates *= 2;
}
// allocate spin and macrostate arrays if necessary
if (spin == null || spin.length < Lx || spin[0].length < Ly) {
spin = new int[Lx][Ly];
macroState = new int[N + 1][N + 1];
}
// initialize spins
for (int x = 0; x < Lx; x++)
for (int y = 0; y < Ly; y++) {
spin[x][y] = +1;
if (hotStart && Math.random() < 0.5)
spin[x][y] = -1;
}
M = spinSum();
SS = bondSum();
microState = maxMacro = 0;
for (int i = 0; i < N + 1; i++)
for (int j = 0; j < N + 1; j++)
macroState[i][j] = 0;
// allocate F, E, S arrays if necessary
if (F == null || F.length < N + 1) {
F = new double[N + 1];
E = new double[N + 1];
TS = new double[N + 1];
}
for (int i = 0; i < N + 1; i++)
F[i] = E[i] = TS[i] = 0;
}
void updateMacroState () {
++microState;
int l = ++macroState[(N - M) / 2][(2 * N - SS) / 4];
if (l > maxMacro)
maxMacro = l;
}
void nextExact () {
int n = microState;
for (int bit = 0; bit < N; bit++) {
int s = n % 2;
int x = bit % Lx;
int y = (bit - x) / Lx;
if (s == 0)
spin[x][y] = 1;
else
spin[x][y] = -1;
n -= s;
n >>= 1;
}
M = spinSum();
SS = bondSum();
updateMacroState();
}
int sumOfNeighbors (int x, int y) {
// periodic boundary conditions
int left = 0;
if (x == 0)
left = spin[Lx - 1][y];
else left = spin[x - 1][y];
int right = 0;
if (x == Lx - 1)
right = spin[0][y];
else right = spin[x + 1][y];
int down = 0;
if (y == 0)
down = spin[x][Ly - 1];
else down = spin[x][y - 1];
int up = 0;
if (y == Ly - 1)
up = spin[x][0];
else up = spin[x][y + 1];
return left + right + up + down;
}
void nextRandom () {
// flip random spin for next microstate
int x = (int) (Lx * Math.random());
int y = (int) (Ly * Math.random());
spin[x][y] = -spin[x][y];
M += 2 * spin[x][y];
SS += 2 * spin[x][y] * sumOfNeighbors(x, y);
updateMacroState();
}
void computeFES () {
FESmin = FESmax = 0;
for (int n = 0; n < N + 1; n++) {
E[n] = 4 * n - 2 * N;
int states = 0;
for (int i = 0; i < N + 1; i++)
states += macroState[i][n];
if (states > 0) {
TS[n] = T * Math.log(states);
F[n] = E[n] - TS[n];
if (FESmin > E[n]) FESmin = E[n];
if (FESmin > TS[n]) FESmin = TS[n];
if (FESmin > F[n]) FESmin = F[n];
if (FESmax < E[n]) FESmax = E[n];
if (FESmax < TS[n]) FESmax = TS[n];
if (FESmax < F[n]) FESmax = F[n];
} else {
TS[n] = -1; // minus infinity
}
}
}
String[] color = {"lightGray", "pink", "orange", "yellow",
"green", "cyan", "blue", "magenta", "red"};
boolean mouseInPlot;
int xMouse;
int yMouse;
class Macro extends Plot implements MouseListener, MouseMotionListener {
Macro () {
setSize(300, 300);
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint () {
clear();
setWindow(0, N + 1, 0, N + 1);
for (int m = 0; m < N + 1; m++) {
for (int ss = 0; ss < N + 1; ss++) {
int n = macroState[N - m][ss];
if (macroState[m][ss] > 0) {
int i = (int) (n / (double) maxMacro * 8.99999);
setColor(color[i]);
} else
setColor("white");
boxArea(ss, ss + 1.1, m, m + 1.1);
}
}
setColor("blue");
double d = 0.05 * (N + 1);
plotStringLeft("x-axis: bond sum = 2N...-2N", N + 1 - d, d);
plotStringLeft("y-axis: spin sum = -N...N", N + 1 - d, N + 1 - d);
}
public void mouseClicked (MouseEvent me) { }
public void mouseEntered (MouseEvent me) {
mouseInPlot = true;
}
public void mouseExited (MouseEvent me) {
mouseInPlot = false;
}
public void mousePressed (MouseEvent me) { }
public void mouseReleased (MouseEvent me) { }
public void mouseDragged (MouseEvent me) { }
public void mouseMoved (MouseEvent me) {
xMouse = (int) xWorld(me.getX());
yMouse = (int) yWorld(me.getY());
if (xMouse >= 0 && xMouse <= N && yMouse >= 0 && yMouse <= N) {
mouseInPlot = true;
output.repaint();
} else {
mouseInPlot = false;
}
}
}
class FreeEnergy extends Plot {
FreeEnergy () {
setSize(300, 300);
}
public void paint () {
clear();
setColor("black");
if (FESmin == FESmax)
return;
drawAxes(0, N + 1, FESmin, FESmax);
double v = FESmax;
plotStringCenter("Energy versus Entropy", N / 2, v);
for (int n = 0; n < N + 1; n++) {
if (TS[n] < 0)
continue;
setColor("red");
v = E[n];
plotLine(n, v, n + 1, v);
setColor("green");
v = TS[n];
plotLine(n, v, n + 1, v);
setColor("blue");
v = F[n];
plotLine(n, v, n + 1, v);
}
v = FESmin - 0.07 * (FESmax - FESmin);
setColor("red");
plotString("energy E", 0, v);
setColor("green");
plotStringLeft("T log n(E)", N, v);
setColor("blue");
plotStringCenter("F = E-TS", N / 2, v);
}
}
class Output extends Plot {
Output () {
setSize(600, 30);
}
public void paint () {
setWindow(0, 100, 0, 3);
clear();
setColor("blue");
boxArea(0, 100, 0, 3);
setColor("white");
plotString("N = " + N + " n = " + (int) microState, 5, 1);
if (mouseInPlot) {
int n = macroState[yMouse][xMouse];
plotStringCenter("n(E, M) = " + n, 50, 1);
int SS = 2 * N - 4 * xMouse;
int M = 2 * yMouse - N;
plotStringLeft("E = -(" + SS + ") J - (" + M + ") H", 95, 1);
} else {
plotString("Move mouse into left plot to view n(E, M)", 30, 1);
}
}
}
Macro macro;
FreeEnergy freeEnergy;
Output output;
Reader LxReader, LyReader, skipReader, exactReader,
TReader, hotStartReader;
int skip = 100;
public void init () {
initial();
add(macro = new Macro());
add(freeEnergy = new FreeEnergy());
add(output = new Output());
add(LxReader = new Reader("L_x = ", Lx));
add(LyReader = new Reader("L_y = ", Ly));
add(skipReader = new Reader("skip states = ", skip));
add(exactReader = new Reader("Exact (N < 31)", exact));
add(TReader = new Reader("T = ", T, 4));
add(hotStartReader = new Reader("Random Initial", hotStart));
addControlPanel();
}
public void step () {
for (int step = 0; step < skip; step++) {
if (exact) {
nextExact();
if (microState >= exactMicroStates)
break;
} else {
nextRandom();
}
}
computeFES();
macro.repaint();
freeEnergy.repaint();
output.repaint();
if (exact && microState >= exactMicroStates)
stopAnimation();
}
public void reset () {
Lx = LxReader.readInt();
Ly = LyReader.readInt();
skip = skipReader.readInt();
exact = exactReader.readBoolean();
T = TReader.readDouble();
hotStart = hotStartReader.readBoolean();
initial();
computeFES();
macro.repaint();
freeEnergy.repaint();
output.repaint();
}
public static void main (String[] args) {
Macrostates macrostates = new Macrostates();
macrostates.frame("Macrostates of 2-d Ising Model", 630, 500);
}
}