      PROGRAM perc_cluster
*     ハマースリー，リース，アレクサンドロビツらのアルゴリズムによる
*     クラスターの生成
      IMPLICIT NONE
      REAL*8 p
      INTEGER IR_, L, N, xs(10000), ys(10000), status(0:2)
      DATA xs,ys/20000*0/
      CALL GWopen(IR_, 0)
      CALL initial(p,L,status)
      CALL grow(p,L,N,xs,ys,status)
      CALL mass_dist(L,N,xs,ys)
      CALL GWquit(IR_)
      END
C
      SUBROUTINE initial(p,L,status)
      IMPLICIT NONE
      REAL*8 p
      REAL xwin, ywin, sz
      REAL dmy, rnd
      INTEGER IR_, L, x, y, status(0:2)
      dmy = rnd(-1)
      WRITE(*,'(A,$)') 'value of L (odd) = '
      READ(*,*) L
      WRITE(*,'(A,$)') 'site occupation probability = '
      READ(*,*) p
      CALL compute_aspect_ratio(REAL(L),xwin,ywin)
      CALL GWindow(IR_, 0.0, 0.0, xwin, ywin)
      sz = ywin/30
      CALL GWsettxt(IR_, sz, 0.0, 5, -1, -1, '')
      CALL GWsetpen(IR_, 0, -1, -1, -1)
      CALL GWrect(IR_, 0.5, 0.5, L+0.5, L+0.5)
      DO y = 1, L
         DO x = 1, L
            CALL GWsetpxl(IR_, REAL(x), REAL(y), 0)
         END DO
      END DO
      CALL GWsetpen(IR_, 13, -1, -1, 4)
      CALL GWcmbmrk(status(1), 2, 6, 1.0, 13, -1, 4)  ! 占有された格子点
      CALL GWputcmb(IR_, status(1), 0.5+sz/2, L+0.5+sz, sz, sz, 0)
      CALL GWputtxt(IR_, 0.5+sz*1.5, L+0.5+sz, 'occupied site')
      CALL GWsetpen(IR_, 16, -1, -1, 4)
      CALL GWcmbmrk(status(2), 3, 6, 1.0, 16, -1, 4)  ! 周辺の点
      CALL GWputcmb(IR_, status(2), 
     +              L/3.0+0.5+sz/2, L+0.5+sz, sz, sz, 0)
      CALL GWputtxt(IR_, 
     +              L/3.0+0.5+sz*1.5, L+0.5+sz, 'perimeter site')
      CALL GWsetpen(IR_, 0, -1, -1, 4)
      CALL GWcmbmrk(status(0), 4, 6, 1.0, 0, -1, 4)   ! 試されたが占有されなかった格子点
      CALL GWputcmb(IR_, status(0), 
     +              L/3.0*2+0.5+sz/2, L+0.5+sz, sz, sz, 0)
      CALL GWputtxt(IR_, 
     +              L/3.0*2+0.5+sz*1.5, L+0.5+sz, 'tested site')
      END
C
      SUBROUTINE grow(p,L,N,xs,ys,status)
*     1つのパーコレーションクラスターを生成
*     境界の点の設定
      IMPLICIT NONE
      REAL*8 p
      REAL rnd
      INTEGER nx(4), ny(4), site(0:131,0:131), L, xs(10000),
     +       ys(10000), status(0:2)
      INTEGER IR_, i, iper, nn, nper, perx(25000), pery(25000), x,
     +       xnew, xseed, y, ynew, yseed, N
      LOGICAL Ltmp1_
      INTEGER DP_, DATA_(8)
      DATA DP_/1/,DATA_/1,0,-1,0,0,1,0,-1/
      DO i = 1, L
         site(0,i) = -1
         site(L+1,i) = -1
         site(i,L+1) = -1
         site(i,0) = -1
      END DO
*     格子の中央に種を置く
      xseed = L/2 + 1
      yseed = xseed
      site(xseed,yseed) = 1                 ! 種の格子点
      xs(1) = xseed
      ys(1) = yseed
      N = 1                                 ! クラスター内の格子点数
      CALL GWputcmb(IR_, status(1), REAL(xseed), REAL(yseed), 
     +              1.0, 1.0, 0)
      DO i = 1, 4
*        nx,ny: 新しい周辺の点に対する方向ベクトル
         nx(i) = DATA_(DP_)
         ny(i) = DATA_(DP_ + 1)
         DP_ = DP_ + 2
*        perx,pery: 種の周辺の点の位置
         perx(i) = xseed + nx(i)
         pery(i) = yseed + ny(i)
*        周辺の点には2を割り当てる
         site(perx(i),pery(i)) = 2          ! 周辺の点の表に入れられた格子点
         CALL GWputcmb(IR_, status(2), REAL(perx(i)), REAL(pery(i)), 
     +                 1.0, 1.0, 0)
      END DO
      nper = 4                              ! 周辺の点の数の初期値
      Ltmp1_ = .TRUE.
      DO WHILE(Ltmp1_)
*        ランダムに周辺の点を選ぶ
         iper = int(rnd(0)*nper) + 1
         x = perx(iper)                     ! 周辺の点の座標
         y = pery(iper)
*        配列中の最後の周辺の点で新しく選ばれた格子点を置き換える
*       
         perx(iper) = perx(nper)
         pery(iper) = pery(nper)
         nper = nper - 1
         IF(rnd(0) .LT. p) THEN
            site(x,y) = 1
            N = N + 1
            xs(N) = x                       ! 占有された格子点を保存
            ys(N) = y
            CALL GWputcmb(IR_, status(1), REAL(x), REAL(y), 
     +                    1.0, 1.0, 0)
            DO nn = 1, 4
               xnew = x + nx(nn)
               ynew = y + ny(nn)
               IF(site(xnew,ynew) .EQ. 0) THEN
                  nper = nper + 1
                  perx(nper) = xnew
                  pery(nper) = ynew
*                 周辺の点に加える
                  site(xnew,ynew) = 2
                  CALL GWputcmb(IR_, status(2), REAL(xnew), REAL(ynew), 
     +                          1.0, 1.0, 0)
               END IF
            END DO
         ELSE
            site(x,y) = -1
            CALL GWputcmb(IR_, status(0), REAL(x), REAL(y), 
     +                    1.0, 1.0, 0)
         END IF
         Ltmp1_ = .NOT.(nper .LT. 1)
      END DO
      CALL GWsetbrs(IR_, 0, 0, -1)
      CALL GWrect(IR_, 0.5, 0.5, L+0.5, L+0.5)  ! 四角形の再描画を行う
      END
C
      SUBROUTINE mass_dist(L,N,xs,ys)
      IMPLICIT NONE
      REAL*8 dx, dy, xcm, ycm
      INTEGER i, r, rprint, N, L, 
     +        masstotal, mass(10000), xs(10000), ys(10000)
      DATA xcm, ycm/2*0.0D0/
      DATA masstotal, mass/10001*0/
      DO i = 1, N
         xcm = xcm + xs(i)                  ! 重心を計算
         ycm = ycm + ys(i)
      END DO
      xcm = xcm/N
      ycm = ycm/N
      DO i = 1, N
         dx = xs(i) - xcm
         dy = ys(i) - ycm
         r = int(sqrt(dx*dx + dy*dy))
*        重心からの距離
*        mass(r) = 重心からの距離 r の格子点数
         IF(r .GT. 1) mass(r) = mass(r) + 1
      END DO
      rprint = 2
      WRITE(*,'(2A9,2A13)') 'r', 'm', 'ln(r)', 'ln(m)'
      DO r = 2, L/2
         masstotal = masstotal + mass(r)
         IF(r .EQ. rprint) THEN
            WRITE(*,'(2I9,2F13.6)') 
     +         r, masstotal, log(REAL(r)), log(REAL(masstotal))
            rprint = 2*rprint               ! r については対数目盛を使う
         END IF
      END DO
      END
