PROGRAM lattice_gas * simulation of particle diffusion in a lattice gas IMPLICIT NONE REAL*8 L_2, site(40,40), t, tmax, x0(1200), y0(1200) INTEGER L, N, im1, IC1_, im2, IC2_, IR_, x(1200), y(1200) DATA IC1_/1/ DATA IC2_/2/ CALL GWopen(IR_, 0) CALL initial(L,L_2,N,tmax,im2,IC2_) CALL lattice(site,x,y,x0,y0,L,N,im1,IC1_) DO t = 1, tmax CALL move(site,x,y,x0,y0,L,N,im1,IC1_) CALL mydata(x,y,x0,y0,L,L_2,N,t,im2,IC2_) END DO CALL GWquit(IR_) END C SUBROUTINE initial(L,L_2,N,tmax,im2,IC2_) IMPLICIT NONE CHARACTER*80 Stmp1_ REAL*8 L_2, tmax REAL GWaspect REAL dmy, rnd INTEGER IR_, L, N, im2, IC2_ dmy = rnd(-1) L = 40 ! linear dimension of lattice L_2 = 0.5D0*L N = 500 ! number of particles tmax = 50 ! # Monte Carlo steps per particle CALL GWcolor(IR_, 0, 2) CALL GWvport(IR_, 0.52*GWaspect(1), 0.0, GWaspect(1), 1.0) CALL GWindow(IR_, -1.0, -1.0, REAL(tmax + 1), REAL(L_2 + 1)) CALL GWsavevp(IR_, IC2_) CALL GWsetogn(IR_, 0, N + 1) CALL GWcolor(IR_, 19, 7) CALL GWsetpen(IR_, 19, -1, -1, 4) WRITE(Stmp1_,*) 'Plot of versus t' CALL GWputtxt(IR_, 1.0, REAL(L_2), Stmp1_) CALL GWrect(IR_, 0.0, 0.0, REAL(tmax), REAL(L_2)) CALL GWcmbmrk(im2, 0, 1, REAL(L_2/tmax/4), 19, -1, 4) END C SUBROUTINE lattice(site,x,y,x0,y0,L,N,im1,IC1_) IMPLICIT NONE CHARACTER*80 Stmp1_ REAL*8 site(40,40), x0(1200), y0(1200) REAL r, xwin, ywin, GWaspect, rnd INTEGER IR_, L, N, i, ix, iy, xadd, yadd, x(1200), y(1200), + im1, IC1_ LOGICAL Ltmp1_ CALL GWvport(IR_, 0.0, 0.2, 0.5*GWaspect(1), 1.0) r = 0.5 ! size of box CALL compute_aspect_ratio(REAL(L+r),xwin,ywin) CALL GWindow(IR_, -0.1*xwin, -0.1*ywin, xwin, ywin) CALL GWsavevp(IR_, IC1_) CALL GWsetogn(IR_, 0, N + 1) CALL GWcolor(IR_, 19, 7) WRITE(Stmp1_,*) 'density = ', DBLE(N)/L/L CALL GWputtxt(IR_, 0.0, ywin*0.93, Stmp1_) CALL GWsetpen(IR_, 13, -1, -1, 4) CALL GWrect(IR_, 1-r, 1-r, L+r, L+r) DO iy = 1, L ! draw lattice sites DO ix = 1, L site(ix,iy) = 0 CALL GWsetpxl(IR_, REAL(ix), REAL(iy), 13) END DO END DO i = 0 CALL GWanchor(IR_, 1) CALL GWsetpen(IR_, 16, -1, -1, 4) CALL GWcmbmrk(im1, 0, 6, 1.0, 16, -1, 4) Ltmp1_ = .TRUE. DO WHILE(Ltmp1_) xadd = int(L*rnd(0)) + 1 yadd = int(L*rnd(0)) + 1 IF(site(xadd,yadd) .EQ. 0) THEN i = i + 1 ! number of particles added site(xadd,yadd) = -1 ! site occupied CALL GWsetogn(IR_, 0, i) CALL GWputcmb(IR_, im1, REAL(xadd), REAL(yadd), 0.0, 0.0, 0) x(i) = xadd y(i) = yadd x0(i) = x(i) ! x-coordinate at t = 0 y0(i) = y(i) END IF Ltmp1_ = i .NE. N END DO END C SUBROUTINE move(site,x,y,x0,y0,L,N,im1,IC1_) IMPLICIT NONE REAL*8 site(40,40), x0(1200), y0(1200) REAL rnd INTEGER IR_, particle, i, xtrial, ytrial, x(1200), y(1200), L, N, + im1, IC1_ CALL GWselvp(IR_, IC1_) CALL GWsetogn(IR_, 0, N + 1) DO particle = 1, N i = int(N*rnd(0)) + 1 xtrial = x(i) ytrial = y(i) CALL direction(xtrial,ytrial,L) IF(site(xtrial,ytrial) .GE. 0) THEN ! unoccupied site site(x(i),y(i)) = 0 CALL GWsrect(IR_, x(i)-0.5,y(i)-0.5, x(i)+0.5,y(i)+0.5, -1) CALL GWerase(IR_, i, 0) CALL GWsetogn(IR_, 0, i) x(i) = xtrial y(i) = ytrial site(x(i),y(i)) = -1 ! new site occupied CALL GWputcmb(IR_, im1, REAL(x(i)), REAL(y(i)), 0.0, 0.0, 0) END IF END DO END C SUBROUTINE direction(xtemp,ytemp,L) * choose random direction and use periodic boundary conditions IMPLICIT NONE REAL rnd INTEGER L, dir, xtemp, ytemp dir = int(4*rnd(0)) + 1 IF(dir .EQ. 1) THEN xtemp = xtemp + 1 IF(xtemp .GT. L) xtemp = 1 ELSE IF(dir .EQ. 2) THEN xtemp = xtemp - 1 IF(xtemp .LT. 1) xtemp = L ELSE IF(dir .EQ. 3) THEN ytemp = ytemp + 1 IF(ytemp .GT. L) ytemp = 1 ELSE IF(dir .EQ. 4) THEN ytemp = ytemp - 1 IF(ytemp .LT. 1) ytemp = L ENDIF END C SUBROUTINE mydata(x,y,x0,y0,L,L_2,N,t,im2,IC2_) IMPLICIT NONE REAL*8 L_2, R2, R2bar, dx, dy, x0(1200), y0(1200), t INTEGER IR_, i, x(1200), y(1200), L, N, im2, IC2_ R2 = 0 DO i = 1, N dx = x(i) - x0(i) dy = y(i) - y0(i) CALL separation(dx,dy,L,L_2) R2 = R2 + dx*dx + dy*dy END DO R2bar = R2/N CALL GWselvp(IR_, IC2_) CALL GWsetogn(IR_, 0, N + 1) CALL GWputcmb(IR_, im2, REAL(t), REAL(R2bar), 0.0, 0.0, 0) END C SUBROUTINE separation(dx,dy,L,L_2) * use periodic boundary conditions to determine separation IMPLICIT NONE REAL*8 L_2, dx, dy INTEGER L IF(abs(dx) .GT. L_2) dx = dx - sign(1.0D0,dx)*L IF(abs(dy) .GT. L_2) dy = dy - sign(1.0D0,dy)*L END