/* Steven Andrews, 12/02, 1/03 */ /* See documentation called Ising doc */ /* Copyright 2003 by Steven Andrews. Permission is granted for non-commercial use of and modifications to the code. */ #include #include #include #include "Ising.h" #define RGTS(s) (s) #define DWNS(s) (s&~3|s+1&3) #define LFTS(s) (s&~3|s+2&3) #define UPPS(s) (s&~3|s+3&3) #define RGTH(s) (s) #define RDWH(s) (s&~7|((s&7)+1)%6) #define LDWH(s) (s&~7|((s&7)+2)%6) #define LFTH(s) (s&~7|((s&7)+3)%6) #define LUPH(s) (s&~7|((s&7)+4)%6) #define RUPH(s) (s&~7|((s&7)+5)%6) #define RGTT(s) (s) #define LDWT(s) (s&~3|((s&3)+1)%3) #define LUPT(s) (s&~3|((s&3)+2)%3) int clsizeS(int *g,int nx,int ny,int ix,int iy); int clsizeH(int *g,int nx,int ny,int ix,int iy); int clsizeT(int *g,int nx,int ny,int ix,int iy); Lattice SetUpIsing(char shape,int nx,int ny,int spc,int *nunit,int rot) { int i,ix,iy,s,*g,ntot,sm,max; Lattice lt; if(shape!='S'&&shape!='H'&&shape!='T') return NULL; if(nx<1||nx>RAND_MAX+1||ny<1||ny>RAND_MAX+1) return NULL; if(spc<1) return NULL; if(nunit) for(ntot=0,s=0;s1) return NULL; lt=(Lattice)malloc(sizeof(struct LatticeType)); if(!lt) return NULL; lt->g=NULL; lt->shape=shape; lt->nx=nx; lt->ny=ny; lt->spc=spc; lt->rot=rot; lt->g=g=(int*)calloc(nx*ny,sizeof(int)); if(!g) {free(lt);return NULL;} if(!nunit) { for(i=0;imax) { max=nunit[s]; sm=s; } for(i=0;ig) free(lt->g); free(lt); return; } void DisplayIsing(Lattice lt) { int ix,iy,nx,ny,*g,spc,rot; char c,shape; if(!lt||!lt->g) { printf("NULL lattice.\n"); return; } g=lt->g; nx=lt->nx; ny=lt->ny; shape=lt->shape; spc=lt->spc; if(lt->rot) rot=shape=='H'?8:4; else rot=0; if(spc==1) c='x'-1; else c='a'-1; for(ix=0;ix<(rot?3*nx:2*nx);ix++) putchar('-'); putchar('\n'); for(iy=0;iyg; nx=lt->nx; ny=lt->ny; if((nx*ny&-nx*ny)!=nx*ny) return; spc=lt->spc; rot=lt->rot; small=nx*ny<=RAND_MAX+1?nx*ny-1:0; nx--; ny--; for(b=0;nx>>b&1;b+=1); if(rot) { spc=(spc+1)*4; while(itmax--) { if(small) { while(!g[ix=rand()&small]); iy=ix>>b; ix&=nx; } else while(!g[(iy=rand()&ny)<>4&3; de+=eps[RGTS(is2)*spc+LFTS(kir)]; de+=eps[DWNS(is2)*spc+UPPS(kid)]; de+=eps[LFTS(is2)*spc+RGTS(kil)]; de+=eps[UPPS(is2)*spc+DWNS(kiu)]; if(de>0&&rand()>RAND_MAX*exp(-de)) g[iy<>4&3):0; g[jy<>6&3; kir=g[iy<0&&rand()>RAND_MAX*exp(-de)) { g[iy<1) { // S, no rotation spc++; while(itmax--) { if(small) { while(!g[ix=rand()&small]); iy=ix>>b; ix&=nx; } else while(!g[(iy=rand()&ny)<0&&rand()>RAND_MAX*exp(-de)) { g[iy<>b; ix&=nx; } else while(!g[(iy=rand()&ny)<g; nx=lt->nx; ny=lt->ny; if((nx*ny&-nx*ny)!=nx*ny) return; spc=lt->spc; rot=lt->rot; small=nx*ny<=RAND_MAX+1?nx*ny-1:0; nx--; ny--; for(b=0;nx>>b&1;b+=1); if(rot) { spc=(spc+1)*8; while(itmax--) { if(small) { while(!g[ix=rand()&small]); iy=ix>>b; ix&=nx; } else while(!g[(iy=rand()&ny)<>4)%6; de+=eps[RGTH(is2)*spc+LFTH(ki0)]; de+=eps[RDWH(is2)*spc+LUPH(ki1)]; de+=eps[LDWH(is2)*spc+RUPH(ki2)]; de+=eps[LFTH(is2)*spc+RGTH(ki3)]; de+=eps[LUPH(is2)*spc+RDWH(ki4)]; de+=eps[RUPH(is2)*spc+LDWH(ki5)]; if(de>0&&rand()>RAND_MAX*exp(-de)) g[iy<>4)%6:0; g[jy<>6)%6; if(iy&1) { ki0=g[iy<0&&rand()>RAND_MAX*exp(-de)) { g[iy<1) { // H, no rotation spc++; while(itmax--) { if(small) { while(!g[ix=rand()&small]); iy=ix>>b; ix&=nx; } else while(!g[(iy=rand()&ny)<0&&rand()>RAND_MAX*exp(-de)) { g[iy<>b; ix&=nx; } else while(!g[(iy=rand()&ny)<g; nx=lt->nx; ny=lt->ny; if((nx*ny&-nx*ny)!=nx*ny) return; spc=lt->spc; rot=lt->rot; small=nx*ny<=RAND_MAX+1?nx*ny-1:0; nx--; ny--; for(b=0;nx>>b&1;b+=1); if(rot) { spc=(spc+1)*4; while(itmax--) { if(small) { while(!g[ix=rand()&small]); iy=ix>>b; ix&=nx; } else while(!g[(iy=rand()&ny)<>4)%3; if(iy&1) { de+=eps[RGTT(is2)*spc+LUPT(ki0)]; de+=eps[LDWT(is2)*spc+RGTT(ki1)]; de+=eps[LUPT(is2)*spc+LDWT(ki2)]; } else { de+=eps[RGTT(is2)*spc+LDWT(ki0)]; de+=eps[LDWT(is2)*spc+LUPT(ki1)]; de+=eps[LUPT(is2)*spc+RGTT(ki2)]; } if(de>0&&rand()>RAND_MAX*exp(-de)) g[iy<>4)%3:0; g[jy<>6)%3; if((iy&3)==0) { ki0=g[((iy-1)&ny)<0&&rand()>RAND_MAX*exp(-de)) { g[iy<1) { // T, no rotation spc++; while(itmax--) { if(small) { while(!g[ix=rand()&small]); iy=ix>>b; ix&=nx; } else while(!g[(iy=rand()&ny)<0&&rand()>RAND_MAX*exp(-de)) { g[iy<>b; ix&=nx; } else while(!g[(iy=rand()&ny)<shape=='S') MetropolisIsingS(lt,itmax,eps); else if(lt->shape=='H') MetropolisIsingH(lt,itmax,eps); else MetropolisIsingT(lt,itmax,eps); return; } float EnergyAtIsingS(Lattice lt,float *eps,int ix,int iy,int spc1,int rot1) { float e; int nx,ny,bond,is2,spc,rot,*g; int k0,k1,k2,k3; g=lt->g; nx=lt->nx; ny=lt->ny; spc=lt->spc; rot=lt->rot; if(rot) { spc=(spc+1)*4; is2=spc1<<2|rot1; k0=g[iy*nx+(ix+1)%nx]; k1=g[(iy+1)%ny*nx+ix]; k2=g[iy*nx+(ix-1+nx)%nx]; k3=g[(iy-1+ny)%ny*nx+ix]; e=eps[RGTS(is2)*spc+LFTS(k0)]; e+=eps[DWNS(is2)*spc+UPPS(k1)]; e+=eps[LFTS(is2)*spc+RGTS(k2)]; e+=eps[UPPS(is2)*spc+DWNS(k3)]; } else if(spc>1) { spc++; is2=spc1*spc; e=eps[is2+g[iy*nx+(ix+1)%nx]]; e+=eps[is2+g[(iy+1)%ny*nx+ix]]; e+=eps[is2+g[iy*nx+(ix-1+nx)%nx]]; e+=eps[is2+g[(iy-1+ny)%ny*nx+ix]]; } else if(spc1) { bond=g[iy*nx+(ix+1)%nx]; bond+=g[(iy+1)%ny*nx+ix]; bond+=g[iy*nx+(ix-1+nx)%nx]; bond+=g[(iy-1+ny)%ny*nx+ix]; e=*eps*bond; } else e=0; return e; } float EnergyAtIsingH(Lattice lt,float *eps,int ix,int iy,int spc1,int rot1) { float e; int nx,ny,bond,is2,spc,rot,*g; int k0,k1,k2,k3,k4,k5; g=lt->g; nx=lt->nx; ny=lt->ny; spc=lt->spc; rot=lt->rot; if(rot) { spc=(spc+1)*8; is2=spc1<<3|rot1; if(iy&1) { k0=g[iy*nx+(ix+1)%nx]; k1=g[(iy+1)%ny*nx+(ix+1)%nx]; k2=g[(iy+1)%ny*nx+ix]; k3=g[iy*nx+(ix-1+nx)%nx]; k4=g[(iy-1+ny)%ny*nx+ix]; k5=g[(iy-1+ny)%ny*nx+(ix+1)%nx]; } else { k0=g[iy*nx+(ix+1)%nx]; k1=g[(iy+1)%ny*nx+ix]; k2=g[(iy+1)%ny*nx+(ix-1+nx)%nx]; k3=g[iy*nx+(ix-1+nx)%nx]; k4=g[(iy-1+ny)%ny*nx+(ix-1+nx)%nx]; k5=g[(iy-1+ny)%ny*nx+ix]; } e=eps[RGTH(is2)*spc+LFTH(k0)]; e+=eps[RDWH(is2)*spc+LUPH(k1)]; e+=eps[LDWH(is2)*spc+RUPH(k2)]; e+=eps[LFTH(is2)*spc+RGTH(k3)]; e+=eps[LUPH(is2)*spc+RDWH(k4)]; e+=eps[RUPH(is2)*spc+LDWH(k5)]; } else if(spc>1) { spc++; is2=spc1*spc; e=eps[is2+g[iy*nx+(ix+1)%nx]]; e+=eps[is2+g[(iy+1)%ny*nx+ix]]; e+=eps[is2+g[iy*nx+(ix-1+nx)%nx]]; e+=eps[is2+g[(iy-1+ny)%ny*nx+ix]]; e+=eps[is2+g[(iy-1+ny)%ny*nx+(ix+(iy&1?1:-1)+nx)%nx]]; e+=eps[is2+g[(iy+1)%ny*nx+(ix+(iy&1?1:-1)+nx)%nx]]; } else if(spc1) { bond=g[iy*nx+(ix+1)%nx]; bond+=g[(iy+1)%ny*nx+ix]; bond+=g[iy*nx+(ix-1+nx)%nx]; bond+=g[(iy-1+ny)%ny*nx+ix]; bond+=g[(iy-1+ny)%ny*nx+(ix+(iy&1?1:-1)+nx)%nx]; bond+=g[(iy+1)%ny*nx+(ix+(iy&1?1:-1)+nx)%nx]; e=*eps*bond; } else e=0; return e; } float EnergyAtIsingT(Lattice lt,float *eps,int ix,int iy,int spc1,int rot1) { float e; int nx,ny,bond,is2,spc,rot,*g; int k0,k1,k2; g=lt->g; nx=lt->nx; ny=lt->ny; spc=lt->spc; rot=lt->rot; if(rot) { spc=(spc+1)*4; is2=spc1<<2|rot1; if((iy&3)==0) { k0=g[(iy-1+ny)%ny*nx+ix]; k1=g[(iy+1)%ny*nx+ix]; k2=g[(iy-1+ny)%ny*nx+(ix-1+nx)%nx]; } else if((iy&3)==1) { k0=g[(iy+1)%ny*nx+ix]; k1=g[(iy+1)%ny*nx+(ix-1+nx)%nx]; k2=g[(iy-1+ny)%ny*nx+ix]; } else if((iy&3)==2) { k0=g[(iy-1+ny)%ny*nx+(ix+1)%nx]; k1=g[(iy+1)%ny*nx+ix]; k2=g[(iy-1+ny)%ny*nx+ix]; } else { k0=g[(iy+1)%ny*nx+(ix+1)%nx]; k1=g[(iy+1)%ny*nx+ix]; k2=g[(iy-1+ny)%ny*nx+ix]; } if(iy&1) { e=eps[RGTT(is2)*spc+LUPT(k0)]; e+=eps[LDWT(is2)*spc+RGTT(k1)]; e+=eps[LUPT(is2)*spc+LDWT(k2)]; } else { e=eps[RGTT(is2)*spc+LDWT(k0)]; e+=eps[LDWT(is2)*spc+LUPT(k1)]; e+=eps[LUPT(is2)*spc+RGTT(k2)]; }} else if(spc>1) { spc++; is2=spc1*spc; e=eps[is2+g[(iy-1+ny)%ny*nx+ix]]; e+=eps[is2+g[(iy+1)%ny*nx+ix]]; e+=eps[is2+g[(iy+(iy&1?1:-1)+ny)%ny*nx+(ix+(iy&2?1:-1)+nx)%nx]]; } else if(spc1) { bond=g[(iy-1+ny)%ny*nx+ix]; bond+=g[(iy+1)%ny*nx+ix]; bond+=g[(iy+(iy&1?1:-1)+ny)%ny*nx+(ix+(iy&2?1:-1)+nx)%nx]; e=*eps*bond; } else e=0; return e; } float EnergyAtIsing(Lattice lt,float *eps,int ix,int iy,int spc1,int rot1) { if(lt->shape=='S') return EnergyAtIsingS(lt,eps,ix,iy,spc1,rot1); else if(lt->shape=='H') return EnergyAtIsingH(lt,eps,ix,iy,spc1,rot1); else return EnergyAtIsingT(lt,eps,ix,iy,spc1,rot1); } float EnergyIsingS(Lattice lt,float *eps) { float e; int ix,iy,nx,ny,bond,is2,spc,rot,*g; int k0,k1; g=lt->g; nx=lt->nx; ny=lt->ny; spc=lt->spc; rot=lt->rot; if(rot) { spc=(spc+1)*4; e=0; for(iy=0;iy1) { spc++; e=0; for(iy=0;iyg; nx=lt->nx; ny=lt->ny; spc=lt->spc; rot=lt->rot; if(rot) { spc=(spc+1)*8; e=0; for(iy=0;iy1) { spc++; e=0; for(iy=0;iyg; nx=lt->nx; ny=lt->ny; spc=lt->spc; rot=lt->rot; if(rot) { spc=(spc+1)*4; e=0; for(iy=0;iy1) { spc++; e=0; for(iy=0;iyshape=='S') return EnergyIsingS(lt,eps); else if(lt->shape=='H') return EnergyIsingH(lt,eps); else return EnergyIsingT(lt,eps); } int clsizeS(int *g,int nx,int ny,int ix,int iy) { int sum; if(g[iy*nx+ix]<1) return 0; g[iy*nx+ix]*=-1; sum=1; if(rand()&1) { sum+=clsizeS(g,nx,ny,(ix+1)%nx,iy); sum+=clsizeS(g,nx,ny,ix,(iy+1)%ny); sum+=clsizeS(g,nx,ny,(ix-1+nx)%nx,iy); sum+=clsizeS(g,nx,ny,ix,(iy-1+ny)%ny); } else { sum+=clsizeS(g,nx,ny,ix,(iy-1+ny)%ny); sum+=clsizeS(g,nx,ny,(ix-1+nx)%nx,iy); sum+=clsizeS(g,nx,ny,ix,(iy+1)%ny); sum+=clsizeS(g,nx,ny,(ix+1)%nx,iy); } return sum; } int clsizeH(int *g,int nx,int ny,int ix,int iy) { int sum; if(g[iy*nx+ix]<1) return 0; g[iy*nx+ix]*=-1; sum=1; if(rand()&1) { sum+=clsizeH(g,nx,ny,(ix+1)%nx,iy); sum+=clsizeH(g,nx,ny,ix,(iy+1)%ny); sum+=clsizeH(g,nx,ny,(ix-1+nx)%nx,iy); sum+=clsizeH(g,nx,ny,ix,(iy-1+ny)%ny); sum+=clsizeH(g,nx,ny,(ix+(iy&1?1:-1)+nx)%nx,(iy+1)%ny); sum+=clsizeH(g,nx,ny,(ix+(iy&1?1:-1)+nx)%nx,(iy-1+ny)%ny); } else { sum+=clsizeH(g,nx,ny,(ix+(iy&1?1:-1)+nx)%nx,(iy-1+ny)%ny); sum+=clsizeH(g,nx,ny,(ix+(iy&1?1:-1)+nx)%nx,(iy+1)%ny); sum+=clsizeH(g,nx,ny,ix,(iy-1+ny)%ny); sum+=clsizeH(g,nx,ny,(ix-1+nx)%nx,iy); sum+=clsizeH(g,nx,ny,ix,(iy+1)%ny); sum+=clsizeH(g,nx,ny,(ix+1)%nx,iy); } return sum; } int clsizeT(int *g,int nx,int ny,int ix,int iy) { int sum; if(g[iy*nx+ix]<1) return 0; g[iy*nx+ix]*=-1; sum=1; if(rand()&1) { sum+=clsizeT(g,nx,ny,ix,(iy+1)%ny); sum+=clsizeT(g,nx,ny,ix,(iy-1+ny)%ny); sum+=clsizeT(g,nx,ny,(ix+(iy&2?1:-1)+nx)%nx,(iy+(iy&1?1:-1)+ny)%ny); } else { sum+=clsizeT(g,nx,ny,(ix+(iy&2?1:-1)+nx)%nx,(iy+(iy&1?1:-1)+ny)%ny); sum+=clsizeT(g,nx,ny,ix,(iy-1+ny)%ny); sum+=clsizeT(g,nx,ny,ix,(iy+1)%ny); } return sum; } int CtClustersIsing(Lattice lt,int *count,int ncount) { int i,max,ct,nx,ny,*g; char shape; g=lt->g; nx=lt->nx; ny=lt->ny; shape=lt->shape; max=0; for(i=0;i0) { if(shape=='S') ct=clsizeS(g,nx,ny,i%nx,i/nx); else if(shape=='H') ct=clsizeH(g,nx,ny,i%nx,i/nx); else ct=clsizeT(g,nx,ny,i%nx,i/nx); if(ctmax) max=ct; } for(i=0;inx; ny=lt->ny; count=(int*)calloc(nx*ny,sizeof(int)); if(!count) return; max=CtClustersIsing(lt,count,nx*ny); printf("size\tnum\t\tconc.\n"); for(i=1;i<=max;i++) if(count[i]) printf("%i\t\t%i\t\t%f\n",i,count[i],1.0*count[i]/(nx*ny)); free(count); return; } float MinDistIsing(Lattice lt,int ix,int iy,int jx,int jy) { float dist,distx,disty; int nx,ny,dx,dy; nx=lt->nx; ny=lt->ny; dx=jx-ix; dy=jy-iy; if(lt->shape=='S') { if(dx<-nx/2) dx+=nx; else if(dx>nx/2) dx-=nx; if(dy<-ny/2) dy+=ny; else if(dy>ny/2) dy-=ny; dist=sqrt(dx*dx+dy*dy); } else if(lt->shape=='H') { if((iy&1)==(jy&1)) distx=dx; else if(iy&1) distx=dx-0.5; else distx=dx+0.5; if(distx<-nx/2) distx+=nx; else if(distx>nx/2) distx-=nx; if(dy<-ny/2) dy+=ny; else if(dy>ny/2) dy-=ny; dist=sqrt(distx*distx+3.0/4.0*dy*dy); } else { if((iy&2)==(jy&2)) distx=sqrt(3)*dx; else if(iy&2) distx=sqrt(3)*(dx-0.5); else distx=sqrt(3)*(dx+0.5); if((iy&3)==(jy&3)) disty=3.0*dy/4.0; else if((iy&1)==(jy&1)) disty=1.5+3.0*floor(dy/4.0); else if((iy&1)&&(jy&3)==(iy+1&3)) disty=0.5+3.0*floor(dy/4.0); else if(iy&1) disty=2.0+3.0*floor(dy/4.0); else if((jy&3)==(iy+1&3)) disty=1.0+3.0*floor(dy/4.0); else disty=2.5+3.0*floor(dy/4.0); if(distx<-nx*sqrt(3)/2.0) distx+=nx*sqrt(3); else if(distx>nx*sqrt(3)/2.0) distx-=nx*sqrt(3); if(disty<-nx*3.0/8.0) disty+=nx*3.0/4.0; else if(disty>nx*3.0/8.0) disty-=nx*3.0/4.0; dist=sqrt(distx*distx+disty*disty); } return dist; } void RadCorrFnIsing(Lattice lt,int spc1,int spc2,float *bins,int nbins,float binsize) { int i,j,nx,ny,obit,n1,n2; int *g; float d; char shape; nx=lt->nx; ny=lt->ny; g=lt->g; shape=lt->shape; for(i=0;irot) obit=0; else obit=shape=='H'?3:2; for(i=0;i>obit==spc1) for(j=i+1;j>obit==spc2) { d=MinDistIsing(lt,i%nx,i/nx,j%nx,j/nx); if(d/binsize>obit==spc1) n1++; if(g[i]>>obit==spc2) n2++; } if(spc1==spc2) bins[0]+=n1; if(!n1||!n2) return; if(shape=='S') d=nx*ny; else if(shape=='H') d=nx*ny*sqrt(3)/2.0; else d=nx*ny*sqrt(3)*3.0/4.0; for(i=0;ishape; nx=lt->nx; ny=lt->ny; if(shape=='S') {dx=nx;dy=ny;} else if(shape=='H') {dx=nx;dy=sqrt(3)/2.0*ny;} else {dx=sqrt(3)*nx;dy=3.0/4.0*ny;} d=dx #include void DisplayIsingGL(Lattice lt,float *colors) { int ix,iy,ic,nx,ny,spc; float x,y,color[4]; int *g; nx=lt->nx; ny=lt->ny; spc=lt->spc; g=lt->g; if(spc>16) spc=16; if(nx<2||ny<2) return; if(lt->shape=='S'&&!lt->rot) { for(iy=0;iyshape=='S') { for(iy=0;iy>2)*4+ic]; glColor4fv(color); glRectf(ix-0.5,iy-0.5,ix+0.5,iy+0.5); }}}} else if(lt->shape=='H'&&!lt->rot) { for(iy=0;iyshape=='H') { for(iy=0;iy>3)*4+ic]; glColor4fv(color); glBegin(GL_POLYGON); glVertex2f(x,y-1.0/sqrt(3)); glVertex2f(x-0.5,y-0.5/sqrt(3)); glVertex2f(x-0.5,y+0.5/sqrt(3)); glVertex2f(x,y+1.0/sqrt(3)); glVertex2f(x+0.5,y+0.5/sqrt(3)); glVertex2f(x+0.5,y-0.5/sqrt(3)); glEnd(); }}}} return; } //#endif