      PROGRAM demon
*     零磁場下の d = 1 イジング・モデルにおけるデーモン・アルゴリズム
      IMPLICIT NONE
      REAL*8 E, Ecum, Ed, Edcum, M, M2cum, Mcum
      INTEGER IR_, N, spin(1000), accept, imcs, mcs
      DATA accept/0/
      CALL GWopen(IR_, 0)
      CALL initial(N,spin,E,Ed,M,mcs,Ecum,Edcum,Mcum,M2cum)
      CALL setupscreen(N,spin)
      DO imcs = 1, mcs
         CALL change(N,spin,E,Ed,M,accept)
         CALL mydata(E,Ed,M,Ecum,Edcum,Mcum,M2cum)
      END DO
      CALL averages(N,Ecum,Edcum,Mcum,M2cum,mcs,accept)
      CALL GWquit(IR_)
      END
C
      SUBROUTINE initial(N,spin,E,Ed,M,mcs,Ecum,Edcum,Mcum,M2cum)
      IMPLICIT NONE
      REAL*8 Etot, E, Ed, M, Ecum, Edcum, Mcum, M2cum
      REAL dmy, rnd
      INTEGER isite, N, spin(1000), mcs
      dmy = rnd(-1)
      WRITE(*,'(A,$)') 'number of spins = '
      READ(*,*) N
*     全エネルギーを 4J の整数倍になるように選ぶ
*     結合定数 J は 1 にとる
      WRITE(*,'(A,$)') 'desired total energy = '
      READ(*,*) Etot
      Etot = 4*int(Etot/4)
      WRITE(*,'(A,$)') 'number of Monte Carlo steps per spin = '
      READ(*,*) mcs
*     最低エネルギー状態でのスピンの初期配置
      DO isite = 1, N
         spin(isite) = 1
      END DO
      M = N                                 ! 正味の磁化
*     系の初期エネルギーの計算
      E = -N                                ! 周期的境界条件
      Ed = (Etot - E)
      WRITE(*,*) 'total energy = ', E + Ed
*     和の変数の初期化
      Ecum = 0
      Edcum = 0
      Mcum = 0
      M2cum = 0
      END
C
      SUBROUTINE setupscreen(N,spin)
      IMPLICIT NONE
      REAL pi, r, xwin, ywin
      PARAMETER(pi = 3.1415926)
      INTEGER IR_, i, N, spin(1000)
      r = N/(2*pi)
      CALL compute_aspect_ratio(r+2,xwin,ywin)
      CALL GWindow(IR_, -xwin, -ywin, xwin, ywin)
      DO i = 1, N
         CALL showspin(N,spin(i),i)
      END DO
      END
C
      SUBROUTINE change(N,spin,E,Ed,M,accept)
      IMPLICIT NONE
      REAL*8 de, left, right, E, Ed, M
      REAL rnd
      INTEGER i, isite, N, spin(1000), accept
      DO i = 1, N
         isite = int(rnd(0)*N + 1)          ! ランダムにスピンを選ぶ
*        隣接するスピンの値を決定する
         IF(isite .EQ. 1) THEN
            left = spin(N)
         ELSE
            left = spin(isite - 1)
         END IF
         IF(isite .EQ. N) THEN
            right = spin(1)
         ELSE
            right = spin(isite + 1)
         END IF
*        試行エネルギー変化
         de =  2*spin(isite)*(left + right)
         IF(de .LE. Ed) THEN
*           スピン反転動力学
            spin(isite) = -spin(isite)
            M = M + 2*spin(isite)
            accept = accept + 1             ! 受け入れられた試行変化の回数
            Ed = Ed - de
            E = E + de
         END IF
         CALL showspin(N,spin(isite),isite)
      END DO
      END
C
      SUBROUTINE mydata(E,Ed,M,Ecum,Edcum,Mcum,M2cum)
*     データを積算する
      IMPLICIT NONE
      REAL*8 E, Ed, M, Ecum, Edcum, Mcum, M2cum
      Ecum = Ecum + E
      Edcum = Edcum + Ed
      Mcum = Mcum + M
      M2cum = M2cum + M*M
      END
C
      SUBROUTINE averages(N,Ecum,Edcum,Mcum,M2cum,mcs,accept)
      IMPLICIT NONE
      REAL*8 Eave, Edave, M2ave, Mave, T, accept_prob, norm, Ecum,
     +       Edcum, Mcum, M2cum
      INTEGER N, mcs, accept
      norm = 1.0D0/mcs                          ! データは各試行の後に集められている
      Edave = Edcum*norm
      WRITE(*,*) 'mean demon energy =', Edave
      T = 4/log(1 + 4/Edave)
      WRITE(*,*) 'T =', T
      Eave = Ecum*norm
      WRITE(*,*) '<E> = ', Eave
      Mave = Mcum*norm
      WRITE(*,*) '<M> =', Mave
      M2ave = M2cum*norm
      WRITE(*,*) '<M*M> =', M2ave
      accept_prob = accept*norm/N
      WRITE(*,*) 'acceptance probability =', accept_prob
      END
C
      SUBROUTINE showspin(N,dir,isite)
      IMPLICIT NONE
      REAL pi, r, theta, x, y
      PARAMETER(pi = 3.141592)
      INTEGER IR_, N, dir, isite
      r = N/(2*pi)
      theta = isite/r
      x = r*cos(theta)
      y = r*sin(theta)
      CALL GWerase(IR_, isite, 0)
      CALL GWsetogn(IR_, 0, isite)
      IF(dir .EQ. 1) THEN
         CALL GWsrect(IR_, x-0.25, y-0.25, x+0.25, y+0.25, 13)
      ELSE
         CALL GWsrect(IR_, x-0.25, y-0.25, x+0.25, y+0.25, 16)
      END IF
      END
