//setDefaultLookAndFeelDecorated (true); // doens't work properly
/*
Potts model with disorder
Definitions of the model, Hamiltonian, parameters, etc.
This applet simulates a disordered Potts model.
It generates samples from the distribution Prob[s] ~ exp (-Ham/T) where
Ham[s] = -sum_{} K_{ij} 2 delta_{s_i s_j} - sum_i (H + H_i) 2 delta_{s_i 0},
and:
- The spins, s_i, are integer variables taking values 0,...,smax-1. For Ising models, set smax=2.
- The factors of 2 are inserted to maintain consistency with Ising models, since EWC and YLL are primarily interested in random-field Ising models.
- K_{ij} are random bond strengths and H_i are random fields, picked from double-Gaussian probability distributions,
P(Kij) = (1-pK)*Gaussian(Kij-K0,R_K) + pK*Gaussian(Kij+K0,R_K) ,
P(Hi) = (1-pH)*Gaussian(Hi -H0,R_H) + pH*Gaussian(Hi +H0,R_H) .
In particular, R_H, or just R, is the same R as in Karin Dahmen's papers -- the width of the Gaussian distribution of the random fields. At the moment the applet is locked in RFIM mode, such that Kij=K=1 (identical bond strengths) and R is the only controllable disorder parameter.
- H is the external field and T is temperature.
To do: Make LAYERED Ising model where Kx and Kz can be different.
Suggestions for use
You can try the following:
- Measuring hysteresis curves, m(H), for various R. First, set T=0.000001 and make sure you sweep very slowly. This gives a well-defined limiting case. Then you can try studying the effect of finite T and finite sweep rates. Observe the avalanches and popping/crackling/snapping noise.
- Measuring spontaneous magnetization, m(T), for various R. This includes the zero-field-cooling experiment.
Comments (on programming issues)
- The "refresh interval" is not a number in seconds; rather, it controls the number of spin flips to perform between display refreshes.
- The Metropolis algorithm is not ergodic at J/T=0; Glauber is. The current Glauber algorithm hasn't been optimized for smax=2 (Ising) models.
- The Wolff algorithm assumes that H=0. (It does not check.)
- There are three types of parameters. Setup parameters (smax, xmax, ymax, lattice) trigger a complete restart if changed. Disorder parameters (R, etc.) only cause the disorder to be generated again. Runtime parameters (T, H, etc.) can be changed on the fly.
- Note that H (External field) and H0 (mag of rand field) are different things.
Credits and references
(...)
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*; // for changelistener
import javax.swing.JSpinner.NumberEditor;
import java.text.DecimalFormat;
import java.util.Random;
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Frame class with image that updates automatically
// "Picture Displayer"
// This simple functionality requires hierarchy of 5 objects!
// This is the only reason why I am making this a separate class.
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class MyFrame extends JFrame {
Container pane;
JLabel label;
ImageIcon icon;
Image image;
//===========================================================================
// Constructor
public MyFrame () { //Component listener) {
super(); // call JFrame constructor
pane = this.getContentPane();
icon = new ImageIcon();
label = new JLabel(icon);
label.setDoubleBuffered(true); //This helps to eliminate flicker
label.setOpaque(true); //No need for JFrameInFrame to redraw itself
pane.add(label);
//this.setIgnoreRepaint(false);//Controls need to draw themselves. Actually this statement doesn't seem to be necessary.
}
//===========================================================================
// Make sure that "image" is valid
void woohoo () {
int widthLabel,heightLabel,widthImage,heightImage;
widthLabel = label.getSize().width;
heightLabel = label.getSize().height;
if (image==null) {
image = createImage(widthLabel, heightLabel);
icon.setImage(image);
}
else {
widthImage = image.getWidth(null);
heightImage = image.getHeight(null);
if (widthImage != widthLabel || heightImage != heightLabel) {
image = createImage(widthLabel, heightLabel); // memleak?
icon.setImage(image);
}
}
}
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// JApplet class
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
public class dirtypotts extends JApplet
implements Runnable,ComponentListener,ChangeListener,ActionListener {
final String namesOfLattices[] = {"Cubic"};
final String namesOfAlgorithms[] = {"Metropolis", "Glauber", "Wolff"};
final String namesOfVisualizations[] = {"Colored cells", "Cells w/borders", "Stripes"};
//---------- Eyecandy stuff
// Usage of the following flags is not well thought-out
boolean makeLattice,makeDirt,drawLattice,drawDirt,getRuntime,drawSpins;
// These are WIDTH AND HEIGHT OF THE OFFSCREEN IMAGE THAT IS CURRENTLY BEING WORKED ON
int width,height;
Container appletPane;
JFrame frCtrls;
MyFrame mfSpinConfig,mfDirtConfig,mfNoise,mfHysteresis,mfMvsT;
JSpinner
spnrsmax,spnrxmax,spnrymax,spnrzmax,
spnrK0,spnrPK,spnrSK,spnrH0,spnrPH,spnrSH,spnrseed,
spnrH,spnrT,
spnrdelay,spnrrefresh,
spnrz;
JButton buttonPolarize,buttonRandomize;
JComboBox comboAlgorithm,comboLattice,comboVisual;
JCheckBox chkboxRunning;
Color colorTable[];
Thread thread1;
int zslice;
int delay,refresh;
double mctime; // This is a joke. Don't take it seriously.
//---------- Core stuff
int smax,xmax,ymax,zmax,imax,bmax;
double kk[][]; // Random bonds
double hh[]; // Random fields
byte ss[]; // Potts spins
int cc[]; // Cluster flags for Wolff
int nn[][] ; // Neighbour list
double zz[]; // Probability list for Glauber
int iqueue[]; // Queue for Wolff
int counter=1; // Counter for Wolff
int seed;
boolean haveNumber=false; // For drand_gauss
double boxMullerNumber=1e100; // For drand_gauss
double
disorderK0,disorderH0,disorderPK,disorderSK,disorderPH,disorderSH,
tempT,beta,pstop,fieldH;
int ncluster;
Random rng;
int nsub[]; // total "0-particles" on each sublattice
int ntot;
double mag; // magnetization
//====================================================================
// Set up Potts model
//====================================================================
public int IXYZ (int x, int y, int z) {return x+xmax*(y+ymax*z);}
int irand (int i) {
//return (int)(Math.random()*i);
return rng.nextInt(i);
}
double drand_gauss () {
/* double x,y,u,t,xx;
if (haveNumber) {haveNumber=false; return boxMullerNumber;}
haveNumber=true;
do {x=rng.nextDouble()*2-1; y=rng.nextDouble()*2-1; u=x*x + y*y;} while (u>1);
t = Math.sqrt(-2*Math.log(u)/u); xx=t*x; boxMullerNumber=t*y;
return xx;
*/
return rng.nextGaussian();
}
public void initPotts() {
int x,y,z,i;
getSetupPars();
rng = new Random();
//---------- Set up the neighborlist
switch (comboLattice.getSelectedIndex()) {
case 0: // LATTICE_CUBIC:
bmax = 6;
imax = xmax*ymax*zmax;
nn = new int[imax][bmax];
for (z=0; z pstop) {
ss[j] = sprimej; // Flip j
cc[j] = counter; // Mark j as part of cluster
iqueue[++ltail] = j;// Push j on queue
}
}
}
}
ncluster = lhead+1; // Return the cluster size!
mctime += ncluster/(double)imax; // Time not well-defined for Wolff...
}
//&&&&&&&&&&&& Get parameterse from spinners
public void getSetupPars() { // Essential parameters such as system size
// get lattice type ... but no need really
smax = Integer.parseInt(spnrsmax.getValue().toString());
xmax = Integer.parseInt(spnrxmax.getValue().toString());
ymax = Integer.parseInt(spnrymax.getValue().toString());
zmax = Integer.parseInt(spnrzmax.getValue().toString());
}
public void getDisorderPars() {
disorderK0 = Double.parseDouble(spnrK0.getValue().toString());
disorderPK = Double.parseDouble(spnrPK.getValue().toString());
disorderSK = Double.parseDouble(spnrSK.getValue().toString());
disorderH0 = Double.parseDouble(spnrH0.getValue().toString());
disorderPH = Double.parseDouble(spnrPH.getValue().toString());
disorderSH = Double.parseDouble(spnrSH.getValue().toString());
seed = Integer.parseInt(spnrseed.getValue().toString());
}
public void getRuntimePars() {
tempT = Double.parseDouble(spnrT.getValue().toString());
fieldH = Double.parseDouble(spnrH.getValue().toString());
refresh = Integer.parseInt(spnrrefresh.getValue().toString());
//delay = Integer.parseInt(spnrdelay.getValue().toString());
beta = 1d/tempT;
zslice = Integer.parseInt(spnrz.getValue().toString());
if (zslice >= zmax || zslice < 0) {
zslice = (zslice+zmax*10) % zmax;
spnrz.setValue(new Integer(zslice));
}
}
//&&&&&&&&&&&&&&&& Override JApplet.init() etc
//public void stop() {frame1.dispose();} // I think I gotit right
//public void destroy() {frame1.dispose();}
//========== Make a spinner and add it to frCtrls
public JSpinner addSpnr (String labeltext, char mnemonic, int initval, int minval, int maxval, int step) {
GridBagConstraints gbc = new GridBagConstraints();
JLabel lbl = new JLabel(labeltext);
JSpinner spnr = new JSpinner(new SpinnerNumberModel(initval, minval, maxval, step));
if (mnemonic != ' ') lbl.setDisplayedMnemonic(mnemonic);
lbl.setLabelFor(spnr);
spnr.setEditor(new NumberEditor(spnr, "###0")); //No commas!
gbc.anchor = GridBagConstraints.EAST;
gbc.gridwidth = GridBagConstraints.RELATIVE;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
frCtrls.add(lbl, gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
frCtrls.add(spnr, gbc);
spnr.addChangeListener(this);
return spnr;
}
public JSpinner addSpnr (String labeltext, char mnemonic, double initval, double minval, double maxval, double step) {
GridBagConstraints gbc = new GridBagConstraints();
JLabel lbl = new JLabel(labeltext);
JSpinner spnr = new JSpinner(new SpinnerNumberModel(initval, minval, maxval, step));
if (mnemonic != ' ') lbl.setDisplayedMnemonic(mnemonic);
lbl.setLabelFor(spnr);
spnr.setEditor(new NumberEditor(spnr, "###0.#####")); //Float
gbc.anchor = GridBagConstraints.EAST;
gbc.gridwidth = GridBagConstraints.RELATIVE;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
frCtrls.add(lbl, gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
frCtrls.add(spnr, gbc);
spnr.addChangeListener(this);
return spnr;
}
public void init() {
makeLattice=drawLattice=makeDirt=drawDirt=getRuntime=drawSpins=true;
smax=2; xmax=ymax=32; zmax=32;
disorderK0=1d; disorderPK=0d; disorderSK=0d;
disorderH0=0d; disorderPH=0d; disorderSH=2.0d;
seed = 123456789;
tempT=1d; fieldH=0.0d;
zslice=0;
refresh=500;
//---------- Set up applet, frame, and panels
appletPane = getContentPane();
setSize(256,32); appletPane.add(new JLabel("See popup window"));
//=============================================================
// Set up frCtrls (CONTROL PANEL)
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.CENTER;
gbc.weightx = 0.0;
GridBagConstraints gbcL = new GridBagConstraints();
gbcL.anchor = GridBagConstraints.EAST;
gbcL.gridwidth = GridBagConstraints.RELATIVE;
gbcL.fill = GridBagConstraints.NONE;
gbcL.weightx = 0.0;
GridBagConstraints gbcR = new GridBagConstraints();
gbcR.gridwidth = GridBagConstraints.REMAINDER;
gbcR.fill = GridBagConstraints.HORIZONTAL;
gbcR.weightx = 1.0;
frCtrls = new JFrame("Controls");
//frCtrls.setFont (new Font("TimesRoman", Font.PLAIN, 12));
frCtrls.setSize(256, 768);
frCtrls.setLayout(new GridBagLayout());
//---------- Add lattice combo box
JLabel lbl;
comboLattice = new JComboBox(namesOfLattices);
lbl = new JLabel (" Lattice ");
lbl.setDisplayedMnemonic('L');
lbl.setLabelFor(comboLattice);
frCtrls.add(lbl, gbcL);
frCtrls.add(comboLattice, gbcR);
// comboLattice.addActionListener(this);// nonneed?
//---------- Add spinners
spnrsmax = addSpnr(" Spin-type smax " ,'s', smax, 1, 10, 1);
spnrxmax = addSpnr(" Size xmax " ,'x', xmax, 1, 8192, 1);
spnrymax = addSpnr(" Size ymax " ,'y', ymax, 1, 8192, 1);
spnrzmax = addSpnr(" Size zmax " ,'z', zmax, 1, 8192, 1);
frCtrls.add(new JLabel(" "), gbc); // spacer
//frCtrls.add(new JLabel(" RBIM parameters ", SwingConstants.CENTER), gbc);
spnrK0 = addSpnr(" Ising coupling K0 " ,' ', disorderK0, -1000d, 1000d, 0.01d);
spnrPK = addSpnr(" RBIM p " ,' ', disorderPK, 0d, 1d, 0.01d);
spnrSK = addSpnr(" RBIM R " ,' ', disorderSK, 0d, 1000d, 0.01d);
frCtrls.add(new JLabel(" "), gbc); // spacer
spnrH0 = addSpnr(" RFIM H0 " ,' ', disorderH0, -1000d, 1000d, 0.01d);
spnrPH = addSpnr(" RFIM p " ,' ', disorderPH, 0d, 1d, 0.01d);
spnrSH = addSpnr(" RFIM R " ,' ', disorderSH, 0d, 1000d, 0.01d);
spnrseed = addSpnr(" Disorder seed " ,' ', seed,-0x7fffffff,0x7fffffff,1);
frCtrls.add(new JLabel(" "), gbc); // spacer
spnrH = addSpnr(" Field H " ,'H', fieldH, -1000d, 1000d, 0.01d);
spnrT = addSpnr(" Temperature T " ,'T', tempT, 0.000001d, 1000d, 0.01d);
spnrrefresh = addSpnr(" Refresh intvl ",' ', refresh, 1, 5000, 1);
comboLattice.setEnabled(false);
spnrPK.setEnabled(false);
spnrSK.setEnabled(false);
spnrH0.setEnabled(false);
spnrPH.setEnabled(false);
//---------- Add algorithm combo box
comboAlgorithm = new JComboBox(namesOfAlgorithms);
lbl = new JLabel (" Algorithm ");
lbl.setDisplayedMnemonic('A');
lbl.setLabelFor(comboAlgorithm);
frCtrls.add(lbl, gbcL);
frCtrls.add(comboAlgorithm, gbcR);
frCtrls.add(new JLabel(" "), gbc); // spacer
//---------- Add visualization-mode combo box
comboVisual = new JComboBox(namesOfVisualizations);
lbl = new JLabel (" Visualization ");
lbl.setDisplayedMnemonic('V');
lbl.setLabelFor(comboVisual);
frCtrls.add(lbl, gbcL);
frCtrls.add(comboVisual, gbcR);
comboVisual.addActionListener(this); // balhblah
spnrz = addSpnr(" zslice " ,'z', zslice, -8192, 8192, 1);
//---------- Add checkboxes
chkboxRunning = new JCheckBox ("Running", true);
frCtrls.add(chkboxRunning, gbc);
frCtrls.setVisible(true);
//=============================================================
// Set up other display frames
mfSpinConfig = new MyFrame(); //this);
mfSpinConfig.setTitle("Spin Configuration");
mfSpinConfig.setLocation(256, 0);
mfSpinConfig.setSize(512, 512);
mfSpinConfig.setVisible(true);
mfDirtConfig = new MyFrame();
mfDirtConfig.setTitle("Dirt Configuration");
mfDirtConfig.setLocation(768, 0);
mfDirtConfig.setSize(512, 512);
mfDirtConfig.setVisible(true);
mfNoise = new MyFrame(); //this);
mfNoise.setTitle("Noise m(t)");
mfNoise.setLocation(256, 512+28);
mfNoise.setSize(256,256);
mfNoise.setVisible(true);
mfHysteresis = new MyFrame(); //this);
mfHysteresis.setTitle("Hysteresis m(h)");
mfHysteresis.setLocation(512, 512+28);
mfHysteresis.setSize(256,256);
mfHysteresis.setVisible(true);
mfMvsT = new MyFrame(); //this);
mfMvsT.setTitle("m(T)");
mfMvsT.setLocation(768, 512+28);
mfMvsT.setSize(256,256);
mfMvsT.setVisible(true);
mfSpinConfig.addComponentListener(this); // maybe not necessary
mfDirtConfig.addComponentListener(this); // this is necessary
mfNoise.addComponentListener(this); // this is necessary
mfHysteresis.addComponentListener(this); // this is necessary
mfMvsT.addComponentListener(this); // this is necessary
//---------- Init system and start simulation
thread1=new Thread(this);
thread1.start();
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// Implement Runnable.
// This method runs in the thread that calls glauber() and also
// renderSpinConfig(), etc.
public void run() {
try {
while (true) {
if (makeLattice) {
initPotts();
makeLattice=false; drawLattice=true; makeDirt=true;
}
if (makeDirt) {
makeDirt();
makeDirt=false; drawDirt=true;
}
if (drawDirt) {
renderDirtConfig(); mfDirtConfig.label.repaint();
drawDirt = false;
}
if (getRuntime) {
getRuntimePars();
getRuntime=false; drawSpins=true;
}
if (drawSpins) {
renderSpinConfig();
mfSpinConfig.label.repaint();
computeMag(); // Important!
renderNoise(); // Every time we draw ss[i], draw m(t) too
mfNoise.label.repaint();
renderHysteresis(); // Every time we draw ss[i], draw m(t) too
mfHysteresis.label.repaint();
renderMvsT(); // Every time we draw ss[i], draw m(t) too
mfMvsT.label.repaint();
drawSpins=false;
}
drawLattice=false; // don't know what im doing
if (chkboxRunning.isSelected()) {
//----- Metropolis or Wolff ----
switch (comboAlgorithm.getSelectedIndex()) {
case 0: // Metropolis: n=number of iterations
for (int n=1+(int)((500d*refresh)/imax); n>0; n--) metropolis();
break;
case 1: // Glauber
for (int n=1+(int)((500d*refresh)/imax); n>0; n--) glauber();
break;
case 2: // Wolff
// Assume that flipping 1 spin takes 1 unit of time.
// In order for the Wolff simulation to have a steady refresh rate
// regardless of temperature, we need to aim for roughly the same number
// of spin flips between refreshes, n.
for (int n=1000*refresh; n>0; n-=ncluster) wolff();
break;
}
drawSpins=true;
}
else {
Thread.sleep (250);
}
}
} catch (Exception e) {
System.out.println("run() exception, exiting");
}
}
//&&&&&&&&&&&&&&&& Implement ChangeListener
public void stateChanged(ChangeEvent e) {
Object esrc = e.getSource();
if (esrc==spnrsmax || esrc==spnrxmax || esrc==spnrymax || esrc==spnrsmax)
makeLattice=true; // demand full restart
else if (esrc==spnrK0 || esrc==spnrPK || esrc==spnrSK ||
esrc==spnrH0 || esrc==spnrPH || esrc==spnrSH ||
esrc==spnrseed)
makeDirt=true;
else {
getRuntime=true; // if tempT is changed, must read new tempT
drawSpins=true; // if zslice is changed then we need to redraw
}
}
//&&&&&&&&&&&&&&&& Implement ActionListener
public void actionPerformed(ActionEvent e) {
Object esrc = e.getSource();
if (esrc==comboLattice || esrc==comboVisual) {
drawLattice=true;
}
}
//&&&&&&&&&&&&&&&& Implement ComponentListener
// These events are only triggered by MyFrame objects! ...?
public void componentHidden(ComponentEvent e){}
public void componentMoved(ComponentEvent e){}
public void componentShown(ComponentEvent e) {}
public void componentResized(ComponentEvent e) {
Object esrc = e.getSource();
if (esrc==mfDirtConfig.pane)
drawDirt=true; // leave it to run() to do the drawing
else
drawLattice=true; //??????
}
//&&&&&&&&&&&&&&&& Implement MouseListener (NOT!)
public void mouseEntered (MouseEvent e) {}
public void mouseExited (MouseEvent e) {}
public void mousePressed (MouseEvent e) {}
public void mouseReleased (MouseEvent e) {}
public void mouseClicked (MouseEvent e) {}
//&&&&&&&&&&&&&&&& This code is the RENDERING CODE!
// It prepares the offscreen images.....
//===========================================================================
// Render the current spin configuration, ss[i]
//===========================================================================
void renderSpinConfig() {
int X,Y,x,y;
Graphics g;
if (!mfSpinConfig.isShowing()) return;
mfSpinConfig.woohoo();
g = mfSpinConfig.image.getGraphics();
width = mfSpinConfig.image.getWidth(null);
height = mfSpinConfig.image.getHeight(null);
if (drawLattice) {
g.setColor(Color.white); g.fillRect(0,0,width,height);
//drawLattice = false; humph
}
int xscal=width/xmax;
int yscal=height/ymax;
xscal = yscal = Math.max(1, Math.min(xscal,yscal));
int Yorg = height - yscal;
if (comboVisual.getSelectedIndex()==0) {
for (y=0; y= 0) {
ih = (int)(h*255);
if (ih > 255) ih = 255;
g.setColor(new Color( (ih << 16) ));
}
else {
ih = (int)(-h*255);
if (ih > 255) ih = 255;
g.setColor(new Color( (ih<<8) | (ih) ));
}
g.fillRect (X, Y, xscal-cellborder, yscal-cellborder);
}
}
}
//===========================================================================
// Add points to the "noise" plot
//===========================================================================
void computeMag() {
int sublatt,x,y,z;
ntot=0;
for (sublatt=0; sublatt<2; sublatt++) {
nsub[sublatt] = 0;
for (z=0; z