Home
|
Course Outline
|
Lectures
|
Homework
|
Files
The following applet, which is generated by the program FiniteSizeScaling.java, generates data for the susceptibility that is similar to the heat capacity data given in Figure 17.2 on page 587 in the textbook.
Here is the code which generates this applet:
// FiniteSizeScaling.java
import comphys.graphics.*;
import comphys.Easy;
public class FiniteSizeScaling extends Animation {
// 2-D Ising Model simulation using the Metropolis algorithm
// finite size scaling data for the isothermal susceptibility
int L; // linear size of lattice
int N; // number of spins
int[][] spin; // spin values
double T; // absolute temperature
double H; // magnetic field
double[][] w; // Boltzmann factors
int mcs; // Monte Carlo step number
int nequil = 1000; // thermalization steps
int ndata = 2000; // number of data steps
int M; // magnetization
int SS; // sum s_i s_j
double mcum; // accumulate magnetization per spin
double m2cum; // square of magnetization per spin
int Lmin = 4; // minimum lattice dimension
int Lsteps = 3; // number of L doublings
double Tmin = 1.5; // minimum temperature
double Tmax = 3.5; // maximum temperature
int Tsteps = 10; // number of temperature steps
double[][] chi; // isothermal susceptibility data
double chiMax = 0.1; // for plotting
int Lindex; // index of current L value
int Tindex; // index of current T value
double TcExact = 2 / Math.log(1 + Math.sqrt(2));
void initial () {
N = L * L;
if (spin == null || spin.length < L)
spin = new int[L][L];
if (T == Tmin) {
// initialize all spins up
for (int x = 0; x < L; x++)
for (int y = 0; y < L; y++)
spin[x][y] = +1;
M = N;
SS = 2 * N;
}
// Boltzmann factors
if (w == null)
w = new double[17][3];
for (int i = -8; i <= 8; i += 4) {
w[i + 8][0] = Math.exp( - (i + 2 * H) / T);
w[i + 8][2] = Math.exp( - (i - 2 * H) / T);
}
mcs = 0;
mcum = m2cum = 0;
}
void data () {
if (mcs == nequil + 1)
mcum = m2cum = 0;
double m = M;
m /= N;
if (m < 0)
m = -m;
mcum += m;
m2cum += m * m;
int n = mcs; // number of data points so far
if (mcs > nequil)
n -= nequil;
double mAv = mcum / n;
double m2Av = m2cum / n;
double chiValue = N / T * (m2Av - mAv * mAv);
chi[Lindex][Tindex] = chiValue;
if (mcs == nequil + ndata && chiValue > chiMax)
chiMax = chiValue;
}
int sumOfNeighbors (int x, int y) {
// periodic boundary conditions
int left = 0;
if (x == 0)
left = spin[L - 1][y];
else left = spin[x - 1][y];
int right = 0;
if (x == L - 1)
right = spin[0][y];
else right = spin[x + 1][y];
int down = 0;
if (y == 0)
down = spin[x][L - 1];
else down = spin[x][y - 1];
int up = 0;
if (y == L - 1)
up = spin[x][0];
else up = spin[x][y + 1];
return left + right + up + down;
}
void Metropolis () {
// one Monte Carlo step per spin
for (int ispin = 0; ispin < N; ispin++) {
int x = (int) (L * Math.random());
if (x == L)
--x;
int y = (int) (L * Math.random());
if (y == L)
--y;
int dSS = 2 * spin[x][y] * sumOfNeighbors(x, y);
if (Math.random() < w[dSS + 8][spin[x][y] + 1]) {
spin[x][y] = -spin[x][y]; // flip spin
M += 2 * spin[x][y];
SS -= dSS;
}
}
++mcs;
data();
}
void initializeSimulation () {
if (chi == null ||
chi.length < Lsteps + 1 ||
chi[0].length < Tsteps + 1) {
chi = new double[Lsteps + 1][Tsteps + 1];
}
for (int i = 0; i <= Lsteps; i++)
for (int j = 0; j <= Tsteps; j++)
chi[i][j] = 0;
L = Lmin;
Lindex = 0;
T = Tmin;
Tindex = 0;
initial();
}
class Lattice extends Plot {
Lattice () {
setSize(300, 300);
}
public void paint () {
clear();
setWindow(0, L, 0, L);
for (int x = 0; x < L; x++) {
for (int y = 0; y < L; y++) {
if (spin[x][y] == 1)
setColor("red");
else
setColor("green");
boxArea(x, x + 1.1, y, y + 1.1);
}
}
}
}
class Graph extends Plot {
Graph () {
setSize(300, 300);
}
public void paint () {
clear();
setColor("black");
drawAxes(Tmin - TcExact, Tmax - TcExact, 0, chiMax);
setColor("blue");
plotStringCenter("T = T_c", 0, -0.07 * chiMax);
plotStringLeft("chi = " + Easy.format(chiMax, 3),
0, 1.02 * chiMax);
double dT = (Tmax - Tmin) / Tsteps;
double rx = 0.01 * (Tmax - Tmin);
double ry = 0.01 * chiMax;
double T0 = Tmin - TcExact;
for (int l = 0; l <= Lindex; l++) {
int tmax = Tsteps;
if (l == Lindex)
tmax = Tindex;
if (l == Lindex && mcs < nequil + ndata)
setColor("green");
else
setColor("magenta");
for (int t = 0; t < tmax; t++)
plotLine(T0 + t * dT, chi[l][t],
T0 + t * dT + dT, chi[l][t + 1]);
if (l == Lindex && mcs < nequil + ndata)
setColor("red");
else
setColor("blue");
for (int t = 0; t <= Tsteps; t++)
floodCircle(T0 + t * dT - rx, T0 + t * dT + rx,
chi[l][t] - ry, chi[l][t] + ry);
}
}
}
class Output extends Plot {
Output () {
setSize(600, 30);
}
public void paint () {
clear();
setWindow(0, 100, 0, 3);
setColor("blue");
boxArea(0, 100, 0, 3);
setColor("white");
plotString("L = " + L, 5, 1);
plotString("T = " + Easy.format(T, 4), 20, 1);
plotString("MC step = " + mcs, 35, 1);
if (mcs > nequil)
plotString("Data step = " + (mcs - nequil), 55, 1);
else
plotString("Therm step = " + mcs, 55, 1);
plotString("chi = " + Easy.format(chi[Lindex][Tindex], 4), 80, 1);
}
}
Lattice lattice;
Graph graph;
Output output;
Reader LminReader, LstepsReader, TminReader, TmaxReader, TstepsReader;
Reader nequilReader, ndataReader, skipReader;
int skip = 20;
public void init () {
initializeSimulation();
add(lattice = new Lattice());
add(graph = new Graph());
add(output = new Output());
add(LminReader = new Reader("L_min = ", Lmin));
add(LstepsReader = new Reader("L steps = ", Lsteps));
add(TminReader = new Reader("T_min = ", Tmin, 4));
add(TmaxReader = new Reader("T_max = ", Tmax, 4));
add(TstepsReader = new Reader("T steps = ", Tsteps));
add(nequilReader = new Reader("Therm steps", nequil));
add(ndataReader = new Reader("Data steps", ndata));
add(skipReader = new Reader("Skip steps", skip));
addControlPanel();
}
void check () {
if (mcs > nequil + ndata) { // current T data done
if (Tindex == Tsteps) { // current L data done
if (Lindex == Lsteps) { // simulation done
stopAnimation();
return;
} else { // proceed to next L value
L *= 2;
++Lindex;
T = Tmin;
Tindex = 0;
}
} else { // proceed to next T value
T += (Tmax - Tmin) / Tsteps;
++Tindex;
}
initial(); // initialize lattice
}
}
public void step () {
for (int step = 0; step < skip; step++) {
Metropolis();
check();
}
Metropolis();
check();
lattice.repaint();
graph.repaint();
output.repaint();
}
public void reset () {
Lmin = LminReader.readInt();
Lsteps = LstepsReader.readInt();
Tmin = TminReader.readDouble();
Tmax = TmaxReader.readDouble();
Tsteps = TstepsReader.readInt();
nequil = nequilReader.readInt();
ndata = ndataReader.readInt();
skip = skipReader.readInt();
initializeSimulation();
lattice.repaint();
graph.repaint();
output.repaint();
}
public static void main (String[] args) {
FiniteSizeScaling fss = new FiniteSizeScaling();
fss.frame("Finite Size Scaling in the 2-D Ising model", 630, 550);
}
}