forked from TinkerTools/tinker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmdinit.f
462 lines (462 loc) · 14.3 KB
/
mdinit.f
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
c
c
c ###################################################
c ## COPYRIGHT (C) 1990 by Jay William Ponder ##
c ## All Rights Reserved ##
c ###################################################
c
c ###############################################################
c ## ##
c ## subroutine mdinit -- initialize a dynamics trajectory ##
c ## ##
c ###############################################################
c
c
c "mdinit" initializes the velocities and accelerations
c for a molecular dynamics trajectory, including restarts
c
c
subroutine mdinit (dt)
use atomid
use atoms
use bath
use bound
use couple
use files
use freeze
use group
use inform
use iounit
use keys
use mdstuf
use molcul
use moldyn
use mpole
use output
use potent
use rgddyn
use rigid
use stodyn
use units
use usage
implicit none
integer i,j,istep
integer idyn,lext
integer size,next
integer freeunit
real*8 dt,eps
real*8 e,ekt,qterm
real*8 maxwell,speed
real*8 amass,gmass
real*8 vec(3)
real*8, allocatable :: derivs(:,:)
logical exist
character*7 ext
character*20 keyword
character*240 dynfile
character*240 record
character*240 string
c
c
c set default parameters for the dynamics trajectory
c
integrate = 'BEEMAN'
bmnmix = 8
arespa = 0.00025d0
nfree = 0
irest = 100
velsave = .false.
frcsave = .false.
uindsave = .false.
friction = 91.0d0
use_sdarea = .false.
iprint = 100
c
c set default values for temperature and pressure control
c
thermostat = 'BUSSI'
tautemp = -1.0d0
collide = 0.1d0
do i = 1, maxnose
vnh(i) = 0.0d0
qnh(i) = 0.0d0
gnh(i) = 0.0d0
end do
barostat = 'BERENDSEN'
anisotrop = .false.
taupres = -1.0d0
compress = 0.000046d0
vbar = 0.0d0
qbar = 0.0d0
gbar = 0.0d0
eta = 0.0d0
voltrial = 25
volmove = 100.0d0
volscale = 'MOLECULAR'
c
c check for keywords containing any altered parameters
c
do i = 1, nkey
next = 1
record = keyline(i)
call gettext (record,keyword,next)
call upcase (keyword)
string = record(next:240)
if (keyword(1:11) .eq. 'INTEGRATOR ') then
call getword (record,integrate,next)
call upcase (integrate)
else if (keyword(1:14) .eq. 'BEEMAN-MIXING ') then
read (string,*,err=10,end=10) bmnmix
else if (keyword(1:12) .eq. 'RESPA-INNER ') then
read (string,*,err=10,end=10) arespa
arespa = 0.001d0 * arespa
else if (keyword(1:16) .eq. 'DEGREES-FREEDOM ') then
read (string,*,err=10,end=10) nfree
else if (keyword(1:15) .eq. 'REMOVE-INERTIA ') then
read (string,*,err=10,end=10) irest
else if (keyword(1:14) .eq. 'SAVE-VELOCITY ') then
velsave = .true.
else if (keyword(1:11) .eq. 'SAVE-FORCE ') then
frcsave = .true.
else if (keyword(1:13) .eq. 'SAVE-INDUCED ') then
uindsave = .true.
else if (keyword(1:9) .eq. 'FRICTION ') then
read (string,*,err=10,end=10) friction
else if (keyword(1:17) .eq. 'FRICTION-SCALING ') then
use_sdarea = .true.
else if (keyword(1:11) .eq. 'THERMOSTAT ') then
call getword (record,thermostat,next)
call upcase (thermostat)
else if (keyword(1:16) .eq. 'TAU-TEMPERATURE ') then
read (string,*,err=10,end=10) tautemp
else if (keyword(1:10) .eq. 'COLLISION ') then
read (string,*,err=10,end=10) collide
else if (keyword(1:9) .eq. 'BAROSTAT ') then
call getword (record,barostat,next)
call upcase (barostat)
else if (keyword(1:15) .eq. 'ANISO-PRESSURE ') then
anisotrop = .true.
else if (keyword(1:13) .eq. 'TAU-PRESSURE ') then
read (string,*,err=10,end=10) taupres
else if (keyword(1:9) .eq. 'COMPRESS ') then
read (string,*,err=10,end=10) compress
else if (keyword(1:13) .eq. 'VOLUME-TRIAL ') then
read (string,*,err=10,end=10) voltrial
else if (keyword(1:12) .eq. 'VOLUME-MOVE ') then
read (string,*,err=10,end=10) volmove
else if (keyword(1:13) .eq. 'VOLUME-SCALE ') then
call getword (record,volscale,next)
call upcase (volscale)
else if (keyword(1:9) .eq. 'PRINTOUT ') then
read (string,*,err=10,end=10) iprint
end if
10 continue
end do
c
c check for use of induced dipole prediction methods
c
if (use_polar) call predict
c
c make sure all atoms or groups have a nonzero mass
c
if (integrate .eq. 'RIGIDBODY') then
do i = 1, ngrp
if (grpmass(i) .le. 0.0d0) then
grpmass(i) = 1.0d0
if (igrp(1,i) .le. igrp(2,i)) then
totmass = totmass + 1.0d0
if (verbose) then
write (iout,20) i
20 format (/,' MDINIT -- Warning, Mass of Group',
& i6,' Set to 1.0 for Dynamics')
end if
end if
end if
end do
else
do i = 1, n
if (use(i) .and. mass(i).le.0.0d0) then
mass(i) = 1.0d0
totmass = totmass + 1.0d0
if (verbose) then
write (iout,30) i
30 format (/,' MDINIT -- Warning, Mass of Atom',
& i6,' Set to 1.0 for Dynamics')
end if
end if
end do
end if
c
c enforce use of velocity Verlet with Andersen thermostat
c
if (thermostat .eq. 'ANDERSEN') then
if (integrate .eq. 'BEEMAN') integrate = 'VERLET'
end if
c
c enforce use of Bussi thermostat/barostat with integrator
c
if (integrate .eq. 'BUSSI') then
thermostat = 'BUSSI'
barostat = 'BUSSI'
else if (thermostat.eq.'BUSSI' .and. barostat.eq.'BUSSI') then
integrate = 'BUSSI'
end if
c
c enforce use of Nose-Hoover thermostat/barostat with integrator
c
if (integrate .eq. 'NOSE-HOOVER') then
thermostat = 'NOSE-HOOVER'
barostat = 'NOSE-HOOVER'
else if (thermostat.eq.'NOSE-HOOVER' .and.
& barostat.eq.'NOSE-HOOVER') then
integrate = 'NOSE-HOOVER'
end if
c
c apply default values for thermostat and barostat coupling
c
if (tautemp .lt. 0.0d0) then
tautemp = 0.2d0
if (thermostat .eq. 'NOSE-HOOVER') tautemp = 1.0d0
end if
if (taupres .lt. 0.0d0) then
taupres = 2.0d0
if (barostat .eq. 'NOSE-HOOVER') taupres = 10.0d0
end if
c
c check for use of Monte Carlo barostat with constraints
c
if (barostat.eq.'MONTECARLO' .and. volscale.eq.'ATOMIC') then
if (use_rattle) then
write (iout,40)
40 format (/,' MDINIT -- Atom-based Monte Carlo',
& ' Barostat Incompatible with RATTLE')
call fatal
end if
end if
c
c perform dynamic allocation of some global arrays
c
if (integrate .eq. 'RIGIDBODY') then
if (.not. allocated(xcmo)) allocate (xcmo(n))
if (.not. allocated(ycmo)) allocate (ycmo(n))
if (.not. allocated(zcmo)) allocate (zcmo(n))
if (.not. allocated(vcm)) allocate (vcm(3,ngrp))
if (.not. allocated(wcm)) allocate (wcm(3,ngrp))
if (.not. allocated(lm)) allocate (lm(3,ngrp))
if (.not. allocated(vc)) allocate (vc(3,ngrp))
if (.not. allocated(wc)) allocate (wc(3,ngrp))
if (.not. allocated(linear)) allocate (linear(ngrp))
else
if (.not. allocated(v)) allocate (v(3,n))
if (.not. allocated(a)) allocate (a(3,n))
if (.not. allocated(aalt)) allocate (aalt(3,n))
end if
c
c set the number of degrees of freedom for the system
c
if (nfree .eq. 0) then
if (integrate .eq. 'RIGIDBODY') then
call grpline
nfree = 6 * ngrp
do i = 1, ngrp
size = igrp(2,i) - igrp(1,i) + 1
if (size .eq. 1) nfree = nfree - 3
if (linear(i)) nfree = nfree - 1
end do
else
nfree = 3 * nuse
end if
if (use_rattle) then
nfree = nfree - nrat
do i = 1, nratx
nfree = nfree - kratx(i)
end do
end if
if (isothermal .and. thermostat.ne.'ANDERSEN' .and.
& integrate.ne.'STOCHASTIC' .and. integrate.ne.'BAOAB' .and.
& integrate.ne.'GHMC') then
if (use_bounds) then
nfree = nfree - 3
else
nfree = nfree - 6
end if
end if
if (barostat .eq. 'BUSSI') nfree = nfree + 1
end if
c
c check for a nonzero number of degrees of freedom
c
if (nfree .lt. 0) nfree = 0
if (debug) then
write (iout,50) nfree
50 format (/,' Number of Degrees of Freedom for Dynamics :',i10)
end if
if (nfree .eq. 0) then
write (iout,60)
60 format (/,' MDINIT -- No Degrees of Freedom for Dynamics')
call fatal
end if
c
c set masses for Nose-Hoover thermostat and barostat
c
if (thermostat .eq. 'NOSE-HOOVER') then
ekt = gasconst * kelvin
qterm = ekt * tautemp * tautemp
do j = 1, maxnose
if (qnh(j) .eq. 0.0d0) qnh(j) = qterm
end do
qnh(1) = dble(nfree) * qnh(1)
end if
if (barostat .eq. 'NOSE-HOOVER') then
ekt = gasconst * kelvin
qterm = ekt * taupres * taupres
qbar = dble(nfree+1) * qterm
end if
c
c decide whether to remove center of mass motion
c
dorest = .true.
if (irest .eq. 0) dorest = .false.
if (nuse. ne. n) dorest = .false.
if (integrate .eq. 'STOCHASTIC') dorest = .false.
if (integrate .eq. 'BAOAB') dorest = .false.
if (integrate .eq. 'GHMC') dorest = .false.
if (isothermal .and. thermostat.eq.'ANDERSEN') dorest = .false.
c
c set inner steps per outer step for RESPA integrator
c
eps = 0.00000001d0
nrespa = int(dt/(arespa+eps)) + 1
c
c perform dynamic allocation of some local arrays
c
allocate (derivs(3,n))
c
c try to restart using prior velocities and accelerations
c
dynfile = filename(1:leng)//'.dyn'
call version (dynfile,'old')
inquire (file=dynfile,exist=exist)
if (exist) then
call gradient (e,derivs)
idyn = freeunit ()
open (unit=idyn,file=dynfile,status='old')
rewind (unit=idyn)
call readdyn (idyn)
close (unit=idyn)
c
c set translational velocities for rigid body dynamics
c
else if (integrate .eq. 'RIGIDBODY') then
call gradient (e,derivs)
do i = 1, ngrp
gmass = grpmass(i)
speed = maxwell (gmass,kelvin)
call ranvec (vec)
do j = 1, 3
vcm(j,i) = speed * vec(j)
wcm(j,i) = 0.0d0
lm(j,i) = 0.0d0
end do
end do
if (nuse .eq. n) then
istep = 0
call mdrest (istep)
end if
c
c set velocities and fast/slow accelerations for RESPA method
c
else if (integrate .eq. 'RESPA') then
call gradslow (e,derivs)
do i = 1, n
amass = mass(i)
if (use(i) .and. amass.ne.0.0d0) then
speed = maxwell (amass,kelvin)
call ranvec (vec)
do j = 1, 3
v(j,i) = speed * vec(j)
a(j,i) = -ekcal * derivs(j,i) / mass(i)
end do
else
do j = 1, 3
v(j,i) = 0.0d0
a(j,i) = 0.0d0
end do
end if
end do
call gradfast (e,derivs)
do i = 1, n
amass = mass(i)
if (use(i) .and. amass.ne.0.0d0) then
do j = 1, 3
aalt(j,i) = -ekcal * derivs(j,i) / amass
end do
else
do j = 1, 3
aalt(j,i) = 0.0d0
end do
end if
end do
if (nuse .eq. n) then
istep = 0
call mdrest (istep)
end if
c
c set velocities and accelerations for Cartesian dynamics
c
else
call gradient (e,derivs)
do i = 1, n
amass = mass(i)
if (use(i) .and. amass.ne.0.0d0) then
speed = maxwell (amass,kelvin)
call ranvec (vec)
do j = 1, 3
v(j,i) = speed * vec(j)
a(j,i) = -ekcal * derivs(j,i) / amass
aalt(j,i) = a(j,i)
end do
else
do j = 1, 3
v(j,i) = 0.0d0
a(j,i) = 0.0d0
aalt(j,i) = 0.0d0
end do
end if
end do
if (nuse .eq. n) then
istep = 0
call mdrest (istep)
end if
end if
c
c perform deallocation of some local arrays
c
deallocate (derivs)
c
c check for any prior dynamics coordinate sets
c
i = 0
exist = .true.
do while (exist)
i = i + 1
lext = 3
call numeral (i,ext,lext)
dynfile = filename(1:leng)//'.'//ext(1:lext)
inquire (file=dynfile,exist=exist)
if (.not.exist .and. i.lt.100) then
lext = 2
call numeral (i,ext,lext)
dynfile = filename(1:leng)//'.'//ext(1:lext)
inquire (file=dynfile,exist=exist)
end if
if (.not.exist .and. i.lt.10) then
lext = 1
call numeral (i,ext,lext)
dynfile = filename(1:leng)//'.'//ext(1:lext)
inquire (file=dynfile,exist=exist)
end if
end do
nprior = i - 1
return
end