	program ising2
c
c ***********************************************************************
c       Simple Ising model simulation on square lattice.
c ***********************************************************************
c
	parameter (maxn=101,maxt=100001)
	implicit real*8 (a-h,o-z)
	common isp(0:maxn,0:maxn)
	dimension ord(maxt)
	character*12 of1,of2
	real etime,time(2)
10	print *,'Ising model on square lattice: lattice edge length?'
	read(5,*) ne
	if(ne.gt.maxn) go to 10
	print *,'initial spin config (1 up, -1 down), ranf seed ?'
	read(5,*) init,isd
	print *,'start and end temp (J/k), #steps ?'
	read(5,*) t1,t2,nt
	print *,'start and end fields (J/mu), #steps ?'
	read(5,*) h1,h2,nh
	print *,'ms0(init trans), ms(rec int), ns(#rec)?'
	read(5,*) ms0,ms,ns
	if(nt.gt.0.or.nh.gt.0) then
		print *,'reinitialize for each T/H ? [1 yes, 0 no]'
		read(5,*) f2
		print *,'transient per T/H ?'
		read(5,*) ms1
	endif
	if(ms0+(ns-1)*ms+1.gt.maxt.or.ms1+(ns-1)*ms+1.gt.maxt) then
		print *,'maxt is too small!'
		go to 10
	endif
	print *,'periodic (1) or free (2) boundary ?'
	read(5,*) ib
	print *,'output file for thermodynamic functions ?'
	read(5,15) of1
15	format(a12)
	print *,'output file for magnetization time series ?'
	read(5,15) of2
	time0=etime(time)
	if(nt.gt.0) then
		dt=(t2-t1)/nt
	else
		dt=0.d0
	endif
	if(nh.gt.0) then
		dh=(h2-h1)/nh
	else
		dh=0.d0
	endif
	write(6,35)
35	format(/2x,'Temperature',2x,'Magnetic fld',1x,'Magnetization',2x,'Energy',2x,
     c         'Susceptibility',1x,'Heat Capacity'/)
	m1=0
	call init_spin(ne,init,ord,m1,maxt,isd)
	call transient(t1,h1,ne,ms0,ib,ord,m1,maxt,isd)
	if(of1.ne.'') then
		open(1,file=of1)
		rewind(1)
	endif
	do 20 i=1,nt+1
		t=t1+(i-1)*dt
		do 30 j=1,nh+1
		h=h1+(j-1)*dh
		if(i.gt.1.or.j.gt.1) then
			if(f2.eq.1) call init_spin(ne,init,ord,m1,maxt,isd)
			call transient(t,h,ne,ms1,ib,ord,m1,maxt,isd)
		endif
	        call calc(t,h,or,en,chi,ch,ne,m1,ms,ns,ib,ord,maxt,isd)
		if(of1.ne.'') write(1,25) t,h,or,en,chi,ch
		write(6,25) t,h,or,en,chi,ch
25		format(1x,1p,6(e12.5,1x))
30		continue
20	continue
	if(of1.ne.'') close(1)
	if(of2.ne.'') then
		open(2,file=of2)
		rewind(2)
		do 50 m=1,m1
			o1=ord(m)/dfloat(ne)**2
			write(2,55) m,o1
55			format(1x,i6,1x,1p,e12.5)
50		continue
		close(2)
	endif
	time1=etime(time)
	write(6,45) time1-time0
45	format(/1x,'CPU time = ',1p,e12.5,' sec')
	stop
	end
c
c
c
	subroutine init_spin(ne,init,ord,m1,maxt,isd)
	parameter (maxn=101)
	implicit real*8 (a-h,o-z)
	real ranf
	common isp(0:maxn,0:maxn)
	dimension ord(1)
	do 70 j=0,ne+1
	isp(0,j)=0
70	isp(ne+1,j)=0
	do 80 i=1,ne
	isp(i,0)=0
80	isp(i,ne+1)=0
	m1=m1+1
	if(m1.gt.maxt) then
		ord(1)=ord(m1-1)
		m1=2
	endif
	if(init.eq.1.or.init.eq.-1) then
		do 10 i=1,ne
			do 15 j=1,ne
				isp(i,j)=init
15			continue
10		continue
		ord(m1)=dfloat(init*ne**2)
	else
		ord(m1)=0.d0
		do 20 i=1,ne
			do 25 j=1,ne
				if(ranf(isd).le.0.5) then
					isp(i,j)=1
				else
					isp(i,j)=-1
				endif
				ord(m1)=ord(m1)+isp(i,j)
25			continue
20		continue
	endif
	return
	end
c
c
c
	subroutine transient(t,h,ne,ms0,ib,ord,m1,maxt,isd)
	parameter (maxn=101)
	implicit real*8 (a-h,o-z)
	real ranf
	common isp(0:maxn,0:maxn)
	dimension ord(1)
	do 30 m=1,ms0
		m1=m1+1
		if(m1.gt.maxt) then
			ord(1)=ord(m1-1)
			m1=2
		endif
		ord(m1)=ord(m1-1)
		do 40 i=1,ne
			i1=i-1
			if(ib.eq.1.and.i.eq.1) i1=ne
			i2=i+1
			if(ib.eq.1.and.i.eq.ne) i2=1
			do 50 j=1,ne
				j1=j-1
				if(ib.eq.1.and.j.eq.1) j1=ne
				j2=j+1
				if(ib.eq.1.and.j.eq.ne) j2=1
				isum=isp(i1,j)+isp(i2,j)
     c					+isp(i,j1)+isp(i,j2)
				de=2*isp(i,j)*(isum+h)
				if(de.lt.0) then
					isp(i,j)=-isp(i,j)
                                        ord(m1)=ord(m1)+2*isp(i,j)
				elseif(ranf(isd).le.dexp(-de/t)) then
					isp(i,j)=-isp(i,j)
                                        ord(m1)=ord(m1)+2*isp(i,j)
				endif
50			continue
40		continue
30	continue
	return
	end
c
c
c
	subroutine calc(t,h,or,en,chi,ch,ne,m1,ms,ns,ib,ord,maxt,isd)
	parameter (maxn=101)
	implicit real*8 (a-h,o-z)
	real ranf
	common isp(0:maxn,0:maxn)
	dimension ord(1)
c
c initialize sum,sum2,sume,sume2 for the quantities to compute
c
	sum=0.d0
	sum2=0.d0
	sume=0.d0
	sume2=0.d0
	do 10 k=1,ns
	xmag=0.d0
	xe=0.d0
	if(k.eq.1) then
		m2=1
	else
		m2=ms+1
	endif
	do 30 m=1,m2
		if(m.lt.m2) then
			m1=m1+1
			if(m1.gt.maxt) then
				ord(1)=ord(m1-1)
				m1=2
			endif
			ord(m1)=ord(m1-1)
		endif
		do 40 i=1,ne
			i1=i-1
			if(ib.eq.1.and.i.eq.1) i1=ne
			i2=i+1
			if(ib.eq.1.and.i.eq.ne) i2=1
			do 50 j=1,ne
				j1=j-1
				if(ib.eq.1.and.j.eq.1) j1=ne
				j2=j+1
				if(ib.eq.1.and.j.eq.ne) j2=1
				isum=isp(i1,j)+isp(i2,j)
     c					+isp(i,j1)+isp(i,j2)			
				if(m.lt.m2) then
				   de=2*isp(i,j)*(isum+h)
				   if(de.lt.0) then
					isp(i,j)=-isp(i,j)
					ord(m1)=ord(m1)+2.d0*isp(i,j)
				   elseif(ranf(isd).le.dexp(-de/t)) then
					isp(i,j)=-isp(i,j)
					ord(m1)=ord(m1)+2.d0*isp(i,j)
				   endif
				else
				   xmag=xmag+isp(i,j)
				   xe=xe-0.5d0*isp(i,j)*isum-h*isp(i,j)
				endif
50			continue
40		continue
30	continue
c
c compute mag,energy add these to the sum,sum2
c
	sum=sum+xmag
	sum2=sum2+xmag**2
	sume=sume+xe
	sume2=sume2+xe**2
10	continue
c
c average and compute mag,energy,chi,ch and put them in the common
c
	or=sum/dfloat(ns)
	chi=(sum2/dfloat(ns)-or**2)/(t*dfloat(ne**2))
	or=or/dfloat(ne**2)
	en=sume/dfloat(ns)
	ch=(sume2/dfloat(ns)-en**2)/(t*ne)**2
	en=en/dfloat(ne**2)
	return
	end
c
c ***********************************************************************
c       Random number generator
c ***********************************************************************
c
      real function ranf(iseed)
      iseed=iseed*1566083941+1
      ranf=float(iseed)*2.328306e-10+0.5
      return
      end
