ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/nano_mpi/src/dynamics_nose_hoover.F90
Revision: 8
Committed: Wed Jun 19 18:48:10 2002 UTC (22 years ago) by pconfort
File size: 9537 byte(s)
Log Message:
*** empty log message ***

File Contents

# Content
1 ! MTK (Martina Tuckerman and Klein) Nosie' Hoover chains
2 ! See Molecular Physics, 1996, Vol. 87, No. 5, 1117-1157 for details of
3 ! the algorithm.
4 !
5 ! author: Charles F. Vardeman II
6 ! date: 6-12-02
7 !
8 ! Interfaces:
9 ! Called from dynamics module:
10 ! public: nose_hoover_dynamics(): controls nose-hoover chains dynamics
11 ! for the length of the simulation time:
12 ! No Arguments:
13
14 ! private:
15 ! nose_hoovera: updates nose_hoover chains and then advances particle positions and velocities
16 ! by velocity verlet.
17 ! nose_hooverb: updates velocities, second half of velocity verlet. and thermostat velocities and
18 ! positions.
19 ! init_hoover: initalize hoover structures
20 ! apply_NHC_par: performs details of nose-hoover chains.
21
22
23 module dynamics_nose_hoover
24 use definitions, ONLY : DP,NDIM
25 use constants
26 use simulation
27 use parameter
28 use force_module, ONLY : calc_forces
29 use force_utilities, ONLY : check
30 use velocity, ONLY : scale_velocities
31 use dynamics_utilities, ONLY : evolve_time, sim_status, init_dynamics_loop, &
32 DT2,DTSQRT,init_status
33 #ifdef MPI
34 use mpi_module, ONLY : mpi_allreduce,mpi_comm_world,mpi_err,&
35 mpi_double_precision, mpi_sum
36 #endif
37
38 implicit none
39 PRIVATE
40
41
42
43 public :: nose_hoover_dynamics
44
45 type (sim_status) :: nose_status
46
47
48 contains
49
50
51 subroutine nose_hoover_dynamics()
52 use velocity, ONLY : calc_temp
53
54
55
56 logical :: update_nlist
57 logical :: do_pot
58 logical :: not_done
59 logical :: nmflag
60
61 integer :: step, i
62
63 ! initialize status (ke,pe,time, etc.)
64 call init_status(nose_status)
65 call init_dynamics_loop( nose_status )
66
67 ! Start the main simulation loop.
68
69 do_pot = .true.
70 not_done = .true.
71 nmflag = .false.
72 step = 0
73
74 dynamics: do
75 if (.not.not_done) exit dynamics
76
77 step = step + 1
78
79
80 if (checktemp.and.(mod(step,check_temp_steps).eq.0)) then
81 call calc_temp(nose_status%temp)
82 if (dabs(nose_status%temp-target_temp).gt.therm_variance) then
83 call scale_velocities(target_temp)
84 end if
85 end if
86
87 call nose_hoovera()
88
89 call check(update_nlist)
90
91
92 if (do_pot) then
93 call calc_forces(update_nlist,nmflag,pe = nose_status%pot_e)
94 else
95 call calc_forces(update_nlist,nmflag)
96 endif
97
98
99 call nose_hooverb()
100
101 call evolve_time(step,nose_status,do_pot,not_done)
102
103
104 #ifdef MPI
105 call mpi_barrier(mpi_comm_world,mpi_err)
106 #endif
107 end do dynamics
108
109 end subroutine nose_hoover_dynamics
110
111
112 ! nose_hoovera(): advances velocities from T to T + DT/2 and positions from T to T + DT
113 subroutine nose_hoovera()
114 use velocity, ONLY : remove_cm_momentum,remove_angular_momentum
115
116
117
118
119 integer :: i, dim
120 real( kind = DP) :: ke, v2, instatemp, chi
121 real( kind = DP) :: kebar
122
123 real( kind = DP ), dimension(ndim) :: v_dim_i
124
125 real(kind=DP) :: ke_local
126
127 ! units for time are femtosec (10^-15 sec)
128 ! units for distance are angstroms (10^-10 m)
129 ! units for velocity are angstroms femtosec^-1
130 ! units for mass are a.m.u. (1.661 * 10^-27 kg)
131 ! units for force are kcal mol^-1 angstrom^-1
132 !
133 ! converter will put the final terms into angstroms.
134 ! or angstrom/femtosecond.
135
136 ! converter = 1.0d0/2.390664d3
137
138
139 ! call nose_hoover chains
140 call apply_NHC_par()
141
142 ! advance velocities from t to t + dt/2
143 do i = 1, nlocal
144 v(1:ndim,i) = v(1:ndim,i) + &
145 (dt2*f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
146 end do
147
148 ! advance positions from t to t+dt
149 do i = 1, nlocal
150 q(1:ndim,i) = q(1:ndim,i) + dt*v(1:ndim,i)
151 end do
152
153
154 end subroutine nose_hoovera
155
156
157 ! advances velocities another half step from t+dt/2 to t + dt
158 subroutine nose_hooverb( )
159 use velocity, ONLY : remove_cm_momentum,remove_angular_momentum
160 integer i
161
162 ! units for time are femtosec (10^-15 sec)
163 ! units for distance are angstroms (10^-10 m)
164 ! units for velocity are angstroms femtosec^-1
165 ! units for mass are a.m.u. (1.661 * 10^-27 kg)
166 ! units for force are kcal mol^-1 angstrom^-1
167
168 do i = 1, nlocal
169 v(1:ndim,i) = v(1:ndim,i) + &
170 (dt2*f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
171 end do
172
173 ! apply nose-hoover thermostat
174 call apply_NHC_par()
175
176 if (sim_type == "cluster") then
177 call remove_cm_momentum()
178 call remove_angular_momentum()
179 endif
180 end subroutine nose_hooverb
181
182
183 ! does the Nose-Hoover part of the integration from t = 0 to t=DT/2
184 ! borrowed from Chris Fennel's code of thermostating
185 ! by way of Hoover, Phys.Rev.A 1985, Vol.31 (3) 1695-1697
186
187 subroutine apply_NHC_par()
188 use velocity, ONLY : calc_temp
189 real(kind = DP) :: system_ke
190 real(kind = DP) :: system_temp
191 real(kind = DP) :: G_NkT
192 real(kind = DP) :: Q_mass
193 real(kind = DP) :: zeta
194 real(kind = DP) :: zetaScale
195 real(kind = DP),dimension(ndim) :: vi
196
197 integer :: i
198
199 call calc_temp(system_temp,system_ke)
200
201 G_NkT = natoms*ndim*K_BOLTZ*target_temp
202 ! and aren't the system_temp and system_ke similar to chris's kt and ke?
203
204 ! Q_mass is a function of the omega parameter
205 Q_mass = G_NkT / (omega * omega)
206
207 ! advance the zeta term to zeta(t + dt)
208 zeta = zeta + dt*((system_temp*2 - G_NkT)/Q_mass)
209 zetaScale = zeta * dt
210
211 ! perform thermostating on velocities and angular momenta
212 do i = 1, nlocal
213 vi(1:ndim) = v(1:ndim,i)*zetaScale
214 ! similar thing here for our angular momenta
215
216 v(1:ndim,i) = v(1:ndim,i) - vi(1:ndim)
217 ! similar thing here for our angular momenta
218 enddo
219
220 end subroutine apply_NHC_par
221
222
223
224 !!$ ! other code borrowed from Chris Fennell's code of
225 !!$ ! G.J. Martyna et al. Mol. Phys., 1996, Vol. 87, No. 5, 1117-1157
226 !!$
227 !!$ subroutine apply_NHC_par()
228 !!$ use velocity, ONLY : calc_temp
229 !!$ real(kind = DP) :: scale
230 !!$ real(kind = DP) :: system_ke
231 !!$ real(kind = DP) :: system_temp
232 !!$ real(kind = DP) :: G_NkT
233 !!$ real(kind = DP) :: omega2
234 !!$ real(kind = DP) :: value1, value2, value3, value4
235 !!$ real(kind = DP) :: wdti2(n_ysval), wdti4(n_ysval), wdti8(n_ysval)
236 !!$ real(kind = DP) :: G_val(N_nos), vval(N_nos), xival(N_nos)
237 !!$ real(kind = DP) :: Q_mass
238 !!$
239 !!$ integer :: i, j
240 !!$
241 !!$ scale = 1._DP
242 !!$
243 !!$ call calc_temp(system_temp,system_ke)
244 !!$
245 !!$ G_NkT = natoms*ndim*K_BOLTZ*my_temp
246 !!$
247 !!$ ! we need to get the w numbers for these values
248 !!$ ! but i think that chris has calculated the values
249 !!$ ! because they are values of constants
250 !!$ value1 = 0.67560359598d0 * dt
251 !!$ value2 = -0.85120719196d0 * dt
252 !!$ value3 = 0.207245385897d0 * dt
253 !!$ value4 = -0.328981543589d0 * dt
254 !!$ if (n_ysval.eq.3) then
255 !!$ wdti2(1) = value1
256 !!$ wdti2(2) = value2
257 !!$ wdti2(3) = value1
258 !!$ wdti4(1) = 0.5_DP * wdti2(1)
259 !!$ wdti4(2) = 0.5_DP * wdti2(2)
260 !!$ wdti4(3) = wdti4(1)
261 !!$ wdti8(1) = 0.5_DP * wdti4(1)
262 !!$ wdti8(2) = 0.5_DP * wdti4(2)
263 !!$ wdti8(3) = wdti8(1)
264 !!$ else
265 !!$ write(*,*) 'Error: n_syval must be 3'
266 !!$ stop
267 !!$ endif
268 !!$
269 !!$ omega2 = omega * omega
270 !!$
271 !!$ ! set the Q_mass values
272 !!$ Q_mass(1) = G_NkT/omega2
273 !!$ do i = 2, N_nos-1
274 !!$ Q_mass(i) = system_temp/omega2
275 !!$ enddo
276 !!$
277 !!$ qmass(N_nos) = 2 * omega
278 !!$
279 !!$ ! zero the intial xivals and vvals
280 !!$ do i = 1, N_nos
281 !!$ xival(i) = 0._DP
282 !!$ vval(i) = 0._DP
283 !!$ enddo
284 !!$
285 !!$ ! Start the Nose_Hoover chain stepping
286 !!$ ! update the forces
287 !!$ G_val(1) = (system_ke - G_NkT)/Q_mass(1)
288 !!$
289 !!$ ! start the multiple time stepping
290 !!$ do i = 1, n_cval
291 !!$ do j = 1, n_ysval
292 !!$
293 !!$ ! update the thermostat velocities
294 !!$ vval(N_nos) = vval(N_nos) + G_val(N_nos)*wdti4(j)/i
295 !!$ do mcount = 1, N_nos-1
296 !!$ aa = exp((-wdti8(j)/i) * vval((N_nos+1)-mcount))
297 !!$ vval(N_nos-mcount) = vval(N_nos-mcount)*aa*aa &
298 !!$ + wdti4(j)*G_val(N_nos)*wdti4(j)/(i*i)
299 !!$ enddo
300 !!$
301 !!$ ! update particle velocities
302 !!$ aa = exp((-wdti2(j)/i)*vval(1))
303 !!$ scale = scale*aa
304 !!$
305 !!$ ! update the forces
306 !!$ G_val(1) = (scale*scale*ke -G_NkT)/Q_mass(1)
307 !!$
308 !!$ ! update the thermostat positions
309 !!$ do mcount = 1, N_nos-1
310 !!$ xival(mcount) = xival(mcount) + vval(mcount)*(wdti2(j)/i)
311 !!$ enddo
312 !!$
313 !!$ ! update the thermostat velocities
314 !!$ do mcount = 1, N_nos-1
315 !!$ aa = exp((-wdti8(j)/i)*vval(mcount+1))
316 !!$ vval(mcount) = vval(mcount)*aa*aa &
317 !!$ + (wdti4(j)/i)*G_val(mcount)*aa
318 !!$ G_val(mcount+1) = (Q_mass(mcount)*vval(mcount)*vval(mcount) &
319 !!$ - system_temp)/Q_mass(mcount+1)
320 !!$ enddo
321 !!$
322 !!$ vval(N_nos) = vval(N_nos) + G_val(N_nos)*(wdti4(j)/i)
323 !!$ enddo
324 !!$ enddo
325 !!$
326 !!$ ! scale both linear velocities and angular momenta
327 !!$ do i = 1, nlocal
328 !!$ v(1:ndim,i) = v(1:ndim,i)*scale
329 !!$ !something here for what we use for angular momenta
330 !!$ enddo
331 !!$
332 !!$ end subroutine apply_NHC_par
333
334
335
336 end module dynamics_nose_hoover