PROGRAM sandpile * simple one-dimensional sandpile model IMPLICIT NONE INTEGER N(0:51), grain, height(51) INTEGER IC1_, IC2_, IR_, L, move(100), topple, unstable LOGICAL TBkeyinput, Ltmp1_ DATA IC1_/1/ DATA IC2_/2/ CALL GWopen(IR_, 0) CALL initial(height,N,L,IC1_,IC2_) grain = 0 DO WHILE(.NOT.TBkeyinput()) height(1) = height(1) + 1 ! add grain to first site CALL GWselvp(IR_, IC1_) CALL GWsetogn(IR_, 0, L + height(1)) CALL GWsrect(IR_, 1.1, height(1) - 0.4, + 1.9, height(1) + 0.4, 16) topple = 0 ! number of grains that topple grain = grain + 1 ! number of grains added Ltmp1_ = .TRUE. DO WHILE(Ltmp1_) CALL check(height,L,move,unstable) IF(unstable .EQ. 1) THEN CALL slide(height,L,move,IC1_) topple = topple + 1 END IF Ltmp1_ = unstable .NE. 0 END DO N(topple) = N(topple) + 1 CALL show_distribution(N,L,grain,IC2_) END DO CALL GWquit(IR_) END C SUBROUTINE initial(height,N,L,IC1_,IC2_) IMPLICIT NONE CHARACTER*80 Stmp1_ INTEGER height(51), N(0:51) REAL GWaspect INTEGER IR_, i, topple, L, IC1_, IC2_ CALL GWsetogn(IR_, 0, 1) CALL GWvport(IR_, 0.0, 0.0, 0.7*GWaspect(1), 1.0) CALL GWinput(IR_, 'lattice size L = ', Stmp1_) READ(Stmp1_,*) L ! suggest L = 20 DO i = 1, L height(i) = 0 END DO height(L+1) = 0 ! boundary condition CALL GWindow(IR_, -1.0, -2.0, REAL(L+1), 40.0) CALL GWsetpen(IR_, 0, -1, -1, 4) CALL GWline(IR_, 1.0, -0.05, REAL(L+1), -0.05) CALL GWsavevp(IR_, IC1_) * initialize array DO topple = 0, L N(topple) = 0 END DO CALL GWvport(IR_, 0.72*GWaspect(1), 0.4, GWaspect(1), 1.0) CALL GWindow(IR_, -0.1, -0.05, REAL(L+1), 1.01) CALL GWline(IR_, 0.0, -0.01, L+0.2, -0.01) CALL GWline(IR_, -0.05, -0.01, -0.05, 1.0) CALL GWsavevp(IR_, IC2_) CALL GWsetogn(IR_, 1, 0) END C SUBROUTINE check(height,L,move,unstable) IMPLICIT NONE INTEGER height(51) INTEGER i, L, move(100), unstable unstable = 0 DO i = 1, L IF(height(i) - height(i+1) .GT. 1) THEN move(i) = 1 unstable = 1 ELSE move(i) = 0 END IF END DO END C SUBROUTINE slide(height,L,move,IC1_) IMPLICIT NONE INTEGER height(51) INTEGER IR_, i, L, move(100), IC1_ CALL GWselvp(IR_, IC1_) DO i = 1, L IF(move(i) .EQ. 1) THEN CALL GWerase(IR_, i*L+height(i), -1) height(i) = height(i) - 1 ! sand topples IF(i .LT. L) THEN * next site receives grain height(i+1) = height(i+1) + 1 CALL GWsetogn(IR_, 0, (i + 1)*L+height(i + 1)) CALL GWsrect(IR_, i + 0.1, height(i + 1) - 0.4, + i + 0.9, height(i + 1) + 0.4, 16) END IF END IF END DO END C SUBROUTINE show_distribution(N,L,grain,IC2_) IMPLICIT NONE INTEGER N(0:51), grain INTEGER IR_, topple, L, IC2_ * erase previous graph CALL GWselvp(IR_, IC2_) DO topple = 0, L IF(N(topple) .GT. 0) THEN CALL GWerase(IR_, topple+10000, -1) CALL GWsetogn(IR_, 0, topple+10000) CALL GWsrect(IR_, REAL(topple), 0.0, + topple+0.2, REAL(N(topple))/grain, 0) END IF END DO END