#define PROGNAME "mc_Ising_2D"
#define VERSION "0.2a"
#define DATE "14.05.2007"
#define AUTHOR "Nils Bluemer"
/* Metropolis Monte Carlo for 2D-Ising Model with pbc */
/* Code adapted from http://gold.cchem.berkeley.edu/~acpan/220A/2DIsing.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*************************
* Constant Declarations *
************************/
#define NMAX 20 /* Lattice size (i.e. NMAX x NMAX) */
#define J -1.0 /* Ising lattice coupling constant
J < 0: Ferromagnetic
J > 0: Antiferromagnetic */
#define H 0.0 /* Ising lattice field strength */
void error(char error_text[])
/* standard error handler */
{
fprintf(stderr,"\n%s run-time error\n",PROGNAME);
fprintf(stderr,"--%s--\n",error_text);
fprintf(stderr,"for general help use option -h\n");
fprintf(stderr,"...now exiting to system...\n");
exit(1);
}
void random_init(int mag[NMAX][NMAX], int L)
{
int i,j;
for(i = 0; i < L; i++)
for(j = 0; j < L; j++)
{
if(drand48() > 0.5)
mag[i][j] = 1;
else
mag[i][j] = -1;
}
}
void outputmag(int mag[NMAX][NMAX], int L)
{
int i,j;
printf("\n");
for(i = 0; i < L; i++)
{
for(j = 0; j < L; j++)
{
if(mag[i][j] == -1)
printf("* ");
else
printf(" ");
}
printf("\n");
}
}
double mag_av(int mag[NMAX][NMAX], int L)
/* computes average magnetization */
{
int i,j;
double x;
x=0.0;
for(i = 0; i < L; i++)
for(j = 0; j < L; j++)
x+=1.0*mag[i][j];
x=x/(L*L);
return(x);
}
void printhelp ()
{
printf("**********************************************************\n");
printf("%s: Metropolis Monte Carlo for 2D Ising model\n",PROGNAME);
printf("Version: %s, %s by %s\n",VERSION,DATE,AUTHOR);
printf("based on http://gold.cchem.berkeley.edu/~acpan/220A/2DIsing.c\n");
printf("options: -T temperature (really: k_B T/|J|)\n");
printf(" -L linear dimension of lattice (L<=%d)\n",NMAX);
printf(" -w# number of initialization sweeps\n");
printf(" -n# number of measurement sweeps\n");
printf(" -c print configurations\n");
printf(" -h this help\n");
}
/***********************************************************/
int main(int argc, char *argv[])
{
/*************************
* Variable Declarations *
************************/
int mag[NMAX][NMAX]; /* 2D Ising Lattice */
int i, j, k; /* Loop counters */
int s,d; /* Lattice spin variables */
double Energy; /* Total lattice energy */
int Inn[4] = {1,-1,0,0}; /* Nearest neighbor array I */
int Jnn[4] = {0,0,1,-1}; /* Nearest neighbor array J */
int Inew, Jnew; /* Nearest neighbot indices */
double Etemp, deltaE; /* Temp energy variables for MC moves */
int accept = 0; /* Number of accepted moves */
int move = 0; /* Number of moves total */
char c;
double T; /* temperature (in units of J/k_B) */
double beta;
int sweeps; /* number of measurement sweeps */
int warm; /* number of warm-up sweeps */
int print_conf; /* flag for printing configurations */
int L; /* lattice dimension */
/***************************
* Initialization *
***************************/
T=1.5;
sweeps=100;
print_conf=0;
L=NMAX;
while (--argc > 0 && (*++argv)[0] == '-')
while (c= *++argv[0])
switch (c) {
case 'n':
sscanf(++argv[0],"%d\n",&sweeps);
break;
case 'w':
sscanf(++argv[0],"%d\n",&warm);
break;
case 'L':
sscanf(++argv[0],"%d\n",&L);
if (L>NMAX) error ("L too large");
break;
case 'T':
sscanf(++argv[0],"%lf\n",&T);
break;
case 'c':
print_conf=1;
break;
case 'h':
printhelp();
exit(0);
break;
/* default: */
/* error("No valid choice"); */
}
beta=1.0/T;
printf("# L=%d, T=%f, n=%d, print_conf=%d\n", L, T, sweeps, print_conf);
printf("# magnetization/site, energy/site\n");
/* Seed the random number generator */
srand48((unsigned int) time(NULL) - (time(NULL)/100000)*100000);
/* Generate random initial configuration */
random_init(mag, L);
/* Determine the energy initially */
Energy = 0.0;
for(i=0;i<L;i++)
for(j=0;j<L;j++)
{
/* Loop over nearest neighbors */
for(k=0;k<4;k++)
{
Inew = i + Inn[k];
Jnew = j + Jnn[k];
/* Check periodic boundary conditions */
if(Inew < 0)
Inew = L-1;
else if(Inew >= L)
Inew = 0;
if(Jnew < 0)
Jnew = L-1;
else if(Jnew >= L)
Jnew = 0;
/* Update the energy */
Energy += J * mag[i][j] * mag[Inew][Jnew];
}
/*Calculate the contribution from the field H */
Energy += 2*H*mag[i][j];
}
/* Account for double counting */
Energy /= 2.0;
/* Monte Carlo Initialization */
for(i=0;i<warm;i++)
{
for(j=0;j<L*L;j++)
{
/* NB: put Metropolis update etc here !!!!!!!!!!!!!!!!!!! */
}
}
/***************************
* The Run *
***************************/
for(i=0;i<sweeps;i++){
/* NB: put Metropolis update etc here !!!!!!!!!!!!!!!!!!! */
/* COLLECT DATA HERE */
printf ("%9.6lf %9.6lf\n", mag_av(mag,L), Energy/(L*L));
}
/*****************************
* Output data and shut down *
****************************/
/* OUTPUT DATA HERE */
if (print_conf>0)
outputmag(mag, L);
/*Ratio of accepted spin flips compared to total attempted flips*/
printf("# Acceptance rate: %2.1f %%\n", 100.0*accept/move);
}
syntax highlighted by Code2HTML, v. 0.9.1