File: mc.f

package info (click to toggle)
ga 5.9.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 18,472 kB
  • sloc: ansic: 192,963; fortran: 53,761; f90: 11,218; cpp: 5,784; makefile: 2,248; sh: 1,945; python: 1,734; perl: 534; csh: 134; asm: 106
file content (190 lines) | stat: -rw-r--r-- 5,387 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
      program he
C$Id: mc.f,v 1.2 1995-02-02 23:24:16 d3g681 Exp $
      implicit double precision (a-h, o-z)
      include 'msgtypesf.h'
      parameter (maxpt=512)
      dimension x(6,maxpt), psix(maxpt), ex(maxpt)
      data esq/0.0d0/
c
c     Monte Carlo Test Program ... evaluates the expectation 
c     value of the energy for a simple wavefunction for helium.
c
c     Initalize the message passing environment
c
      call pbeginf
      call evon
c
c     process zero reads in input and then broadcasts to others
c
      if (nodeid().eq.0) then
        write(6,1)
1       format(' He atom variational monte carlo '//
     &         ' Input neq and nstep '$)
c       call flush(6)
        read(5,*) neq, nstep
        nstep = ( (nstep+99)/100 ) * 100
        neq = ( (neq+99)/100 ) * 100
      endif
      call brdcst(1+MSGINT, neq, mitob(1), 0)
      call brdcst(1+MSGINT, nstep, mitob(1), 0)
c
c     Divide up the work ... each process does a subset of the points
c     or configurations ... make sure that total is indeed maxpt
c
      nproc = nnodes()
      npoint = maxpt / nproc
      nremain = maxpt - npoint*nproc
      if (nodeid().lt.nremain) npoint = npoint + 1
c
c     Actually do the work. Routine init generates the intial points
c     in a 2x2x2 cube. Equilibriate for neq moves then compute averages
c     for nstep moves.
c
      rjunk = timer()
      call init(npoint, x, psix)
      call mover(x, psix, ex, e, esq, npoint, neq)
      call mover(x, psix, ex, e, esq, npoint, nstep)
c
c     Sum the results from all the processors
c
      call dgop(2+MSGDBL, e, 1, '+')
      call dgop(3+MSGDBL, esq, 1, '+')
c
c     Write out the results before terminating
c
      if (nodeid().eq.0) then
         e = e / dble(nproc)
         esq = esq / dble(nproc)
         err = sqrt((esq-e*e) / dble(nproc*nstep/100))
         used = timer()
         write(6,2) e, err, used, nproc
 2       format(' energy =',f10.6,' +/-',f9.6,': used =',f7.2,' secs',
     $        ': nproc =',i3)
      endif
c
      call pend
      call fexit
c
      end
      subroutine mover(x, psix, ex, e, esq, npoint, nstep)
      implicit double precision (a-h, o-z)
      dimension x(6,npoint), psix(npoint), ex(npoint)
c
c     move the set of points nstep times accumulating averages
c     for the energy and square of the energy
c     
      e = 0.0d0
      esq = 0.0d0
      eb = 0.0d0
      do 10 istep = 1, nstep
c
c     sample a new set of points
c
         do 20 ipoint = 1, npoint
            call sample(x(1, ipoint), psix(ipoint), ex(ipoint))
 20      continue
c
c     accumulate average(s)
c
         do 30 ipoint = 1, npoint
            eb = eb + ex(ipoint)
 30      continue
c
c     block averages every 100 moves to reduce statistical correlation
c
         if (mod(istep,100).eq.0) then
            eb = eb / dble(npoint*100)
            e = e + eb
            esq = esq + eb*eb
            eb = 0.0d0
         endif
 10   continue
c
c     compute final averages
c
      e = e / dble(nstep/100)
      esq = esq / dble(nstep/100)
c
      end
      subroutine sample(x, psix, ex)
      implicit double precision (a-h, o-z)
      dimension x(6), xnew(6)
c
c     sample a new point ... i.e. move current point by a
c     random amount and accept the move according to the
c     ratio of the square of the wavefunction at the new
c     point and the old point.
c
c     generate trial point and info at the new point
c
      do 10 i = 1,6
         xnew(i) = x(i) + (drand48(0)-0.5d0)*0.3d0
 10   continue
      call rvals(xnew, r1, r2, r12, r1dr2)
      psinew = psi(r1, r2, r12)
c
c     accept or reject the move
c
      prob = min((psinew / psix)**2, 1.0d0)
      if (prob .gt. drand48(0)) then
         do 20 i = 1,6
            x(i) = xnew(i)
 20      continue
         psix = psinew
      else
         call rvals(x, r1, r2, r12, r1dr2)
      endif
      ex = elocal(r1, r2, r12, r1dr2)
c     
      end
      subroutine rvals(x, r1, r2, r12, r1dr2)
      implicit double precision (a-h, o-z)
      dimension x(6)
c
c     compute required distances etc.
c
      r1 = dsqrt(x(1)**2 + x(2)**2 + x(3)**2)
      r2 = dsqrt(x(4)**2 + x(5)**2 + x(6)**2)
      r12 = dsqrt((x(1)-x(4))**2 + (x(2)-x(5))**2 + (x(3)-x(6))**2)
      r1dr2 = x(1)*x(4) + x(2)*x(5) + x(3)*x(6)
c
      end
      double precision function psi(r1, r2, r12)
      implicit double precision (a-h, o-z)
c
c     compute value of the trial wavefunction
c
      psi = dexp(-2.0d0*(r1+r2)) * (1.0d0 + 0.5d0*r12)
c
      end
      double precision function elocal(r1, r2, r12, r1dr2)
      implicit double precision (a-h, o-z)
c
c     compute local energy = (H psi) / psi 
c
      f = r12*(1.0d0 + 0.5d0*r12)
      g = 0.5d0*r12 + r1 +r2 - r1dr2*(1.0d0/r1 + 1.0d0/r2)
      elocal = -4.0d0 + g / f
c
      end
      subroutine init(npoint, x, psix)
      implicit double precision (a-h, o-z)
      dimension x(6,npoint), psix(npoint)
c
c     distribute points in a 2x2x2 cube.
c
c     in parallel version make random no. seed depend on the
c     process number ... for a production code should be more
c     sophisticated than this.
c
      call srand48(2*nodeid()+1)
c      
      do 10 ipoint = 1,npoint
         do 20 i = 1,6
            x(i,ipoint) = (drand48(0) - 0.5d0) * 2.0d0
 20      continue
         call rvals(x(1,ipoint), r1, r2, r12, r1dr2)
         psix(ipoint) = psi(r1, r2, r12)
 10   continue
c
      end