Line data Source code
1 : !!****m* ABINIT/m_pred_isokinetic
2 : !! NAME
3 : !! m_pred_isokinetic
4 : !!
5 : !! FUNCTION
6 : !!
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, JCC, SE)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !!
14 : !! SOURCE
15 :
16 : #if defined HAVE_CONFIG_H
17 : #include "config.h"
18 : #endif
19 :
20 : #include "abi_common.h"
21 :
22 : module m_pred_isokinetic
23 :
24 : use m_abicore
25 : use defs_basis
26 : use m_abimover
27 : use m_abihist
28 :
29 : use m_numeric_tools, only : uniformrandom
30 : use m_geometry, only : xcart2xred, xred2xcart
31 :
32 :
33 : implicit none
34 :
35 : private
36 : !!***
37 :
38 : public :: pred_isokinetic
39 : !!***
40 :
41 : contains
42 : !!***
43 :
44 :
45 : !!****f* ABINIT/pred_isokinetic
46 : !! NAME
47 : !! pred_isokinetic
48 : !!
49 : !! FUNCTION
50 : !! Ionmov predictors (12) Isokinetic ensemble molecular dynamics
51 : !!
52 : !! IONMOV 12:
53 : !! Isokinetic ensemble molecular dynamics.
54 : !! The equation of motion of the ions in contact with a thermostat
55 : !! are solved with the algorithm proposed by Zhang [J. Chem. Phys. 106, 6102 (1997)] [[cite:Zhang1997]],
56 : !! as worked out by Minary et al, J. Chem. Phys. 188, 2510 (2003) [[cite:Minary2003]].
57 : !! The conservation of the kinetic energy is obtained within machine precision, at each step.
58 : !! Related parameters: the time step (dtion), the initial temperature (mdtemp(1)) if the velocities are not defined to start with.
59 : !!
60 : !! INPUTS
61 : !! ab_mover <type(abimover)> : Datatype with all the information needed by the preditor
62 : !! itime : Index of the present iteration
63 : !! ntime : Maximal number of iterations
64 : !! zDEBUG : if true print some debugging information
65 : !!
66 : !! OUTPUT
67 : !!
68 : !! SIDE EFFECTS
69 : !! hist <type(abihist)> : History of positions,forces acell, rprimd, stresses
70 : !! SOURCE
71 :
72 978 : subroutine pred_isokinetic(ab_mover,hist,itime,ntime,zDEBUG,iexit)
73 :
74 : !Arguments ------------------------------------
75 : !scalars
76 : integer,intent(in) :: itime
77 : integer,intent(in) :: ntime
78 : integer,intent(in) :: iexit
79 : logical,intent(in) :: zDEBUG
80 : type(abimover),intent(in) :: ab_mover
81 : type(abihist),intent(inout) :: hist
82 :
83 : !Local variables-------------------------------
84 : !scalars
85 : integer :: kk,iatom,idim,idum=5,nxyzatfree,ndegfreedom,nfirst,ifirst
86 : real(dp) :: a,as,b,sqb,s,s1,s2,scdot,sigma2,vtest,v2gauss
87 : real(dp),parameter :: v2tol=tol8
88 : real(dp) :: etotal,rescale_vel
89 : character(len=5000) :: message
90 : !arrays
91 : real(dp),allocatable,save :: fcart_m(:,:),vel_nexthalf(:,:)
92 :
93 : real(dp) :: acell(3),rprimd(3,3)
94 1956 : real(dp) :: fcart(3,ab_mover%natom)
95 1956 : real(dp) :: xcart(3,ab_mover%natom),xcart_next(3,ab_mover%natom)
96 1956 : real(dp) :: xred(3,ab_mover%natom),xred_next(3,ab_mover%natom)
97 978 : real(dp) :: vel(3,ab_mover%natom)
98 : real(dp) :: strten(6)
99 :
100 : !***************************************************************************
101 : !Beginning of executable session
102 : !***************************************************************************
103 :
104 : !DEBUG
105 : !write(std_out,*)' pred_isokinetic : enter '
106 : !stop
107 : !ENDDEBUG
108 :
109 978 : if(iexit/=0)then
110 33 : ABI_SFREE(fcart_m)
111 33 : ABI_SFREE(vel_nexthalf)
112 : return
113 : end if
114 :
115 : !write(std_out,*) 'isokinetic 01'
116 : !##########################################################
117 : !### 01. Debugging and Verbose
118 :
119 945 : if(zDEBUG)then
120 0 : write(std_out,'(a,3a,40a,37a)') ch10,('-',kk=1,3),&
121 0 : & 'Debugging and Verbose for pred_isokinetic',('-',kk=1,37)
122 0 : write(std_out,*) 'ionmov: ',12
123 0 : write(std_out,*) 'itime: ',itime
124 : end if
125 :
126 : !write(std_out,*) 'isokinetic 02'
127 : !##########################################################
128 : !### 02. Allocate the vectors vin, vout and hessian matrix
129 : !### These arrays could be allocated from a previous
130 : !### dataset that exit before itime==ntime
131 :
132 945 : if(itime==1)then
133 33 : ABI_SFREE(fcart_m)
134 33 : ABI_SFREE(vel_nexthalf)
135 : end if
136 :
137 945 : if (.not.allocated(fcart_m)) then
138 99 : ABI_MALLOC(fcart_m,(3,ab_mover%natom))
139 : end if
140 945 : if (.not.allocated(vel_nexthalf)) then
141 99 : ABI_MALLOC(vel_nexthalf,(3,ab_mover%natom))
142 : end if
143 :
144 : !write(std_out,*) 'isokinetic 03'
145 : !##########################################################
146 : !### 03. Obtain the present values from the history
147 :
148 945 : call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
149 :
150 119905 : fcart(:,:)=hist%fcart(:,:,hist%ihist)
151 6615 : strten(:) =hist%strten(:,hist%ihist)
152 119905 : vel(:,:) =hist%vel(:,:,hist%ihist)
153 945 : etotal =hist%etot(hist%ihist)
154 :
155 945 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
156 :
157 945 : if(zDEBUG)then
158 0 : write (std_out,*) 'fcart:'
159 0 : do kk=1,ab_mover%natom
160 0 : write (std_out,*) fcart(:,kk)
161 : end do
162 0 : write (std_out,*) 'vel:'
163 0 : do kk=1,ab_mover%natom
164 0 : write (std_out,*) vel(:,kk)
165 : end do
166 0 : write (std_out,*) 'strten:'
167 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
168 0 : write (std_out,*) 'etotal:'
169 0 : write (std_out,*) etotal
170 : end if
171 :
172 : !Count the number of degrees of freedom, taking into account iatfix.
173 : !Also fix the velocity to zero for the fixed atoms
174 945 : nxyzatfree=0
175 30685 : do iatom=1,ab_mover%natom
176 119905 : do idim=1,3
177 118960 : if(ab_mover%iatfix(idim,iatom)==0)then
178 89184 : nxyzatfree=nxyzatfree+1
179 : else
180 36 : vel(idim,iatom)=zero
181 : endif
182 : enddo
183 : enddo
184 :
185 : !Now, the number of degrees of freedom is reduced by four because of the kinetic energy conservation
186 : !and because of the conservation of the total momentum for each dimension, in case no atom position is fixed for that dimension
187 : !(in the latter case, one degree of freedom has already been taken away)
188 : !This was not done until v8.9 of ABINIT ...
189 945 : ndegfreedom=nxyzatfree
190 945 : ndegfreedom=nxyzatfree-1 ! Kinetic energy conservation
191 3780 : do idim=1,3
192 93000 : if(sum(ab_mover%iatfix(idim,:))==0)then
193 2799 : ndegfreedom=ndegfreedom-1 ! Macroscopic momentum
194 : endif
195 : enddo
196 :
197 : !write(std_out,*) 'isokinetic 04'
198 : !##########################################################
199 : !### 04. Second half-velocity (Only after the first itime)
200 :
201 945 : if(itime>1) then
202 :
203 29888 : do iatom=1,ab_mover%natom
204 116816 : do idim=1,3
205 115904 : if(ab_mover%iatfix(idim,iatom)==0)then
206 86896 : fcart_m(idim,iatom)=fcart(idim,iatom)/ab_mover%amass(iatom)
207 : else
208 32 : fcart_m(idim,iatom)=zero
209 : endif
210 : end do
211 : end do
212 :
213 : ! Computation of vel(:,:) at the next positions
214 : ! Computation of v2gauss, actually twice the kinetic energy.
215 : ! Called 2K, cf Eq. (A13) of [[cite:Minary2003]].
216 912 : v2gauss=0.0_dp
217 29888 : do iatom=1,ab_mover%natom
218 116816 : do idim=1,3
219 : v2gauss=v2gauss+&
220 : & vel_nexthalf(idim,iatom)*vel_nexthalf(idim,iatom)*&
221 115904 : & ab_mover%amass(iatom)
222 : end do
223 : end do
224 :
225 : ! Computation of a and b (4.13 of [[cite:Minary2003]])
226 912 : a=0.0_dp
227 912 : b=0.0_dp
228 29888 : do iatom=1,ab_mover%natom
229 116816 : do idim=1,3
230 86928 : a=a+fcart_m(idim,iatom)*vel_nexthalf(idim,iatom)*ab_mover%amass(iatom)
231 115904 : b=b+fcart_m(idim,iatom)*fcart_m(idim,iatom)*ab_mover%amass(iatom)
232 : end do
233 : end do
234 912 : a=a/v2gauss
235 912 : b=b/v2gauss
236 :
237 :
238 : ! Computation of s and scdot
239 912 : sqb=sqrt(b)
240 912 : as=sqb*ab_mover%dtion/2.
241 : ! jmb
242 : if ( as > 300.0 ) as=300.0
243 912 : s1=cosh(as)
244 912 : s2=sinh(as)
245 912 : s=a*(s1-1.)/b+s2/sqb
246 912 : scdot=a*s2/sqb+s1
247 :
248 29888 : do iatom=1,ab_mover%natom
249 116816 : do idim=1,3
250 115904 : if(ab_mover%iatfix(idim,iatom)==0)then
251 86896 : vel(idim,iatom)=(vel_nexthalf(idim,iatom)+fcart_m(idim,iatom)*s)/scdot
252 : else
253 32 : vel(idim,iatom)=zero
254 : endif
255 : enddo
256 : enddo
257 :
258 912 : if (zDEBUG)then
259 0 : write(std_out,*) 'Computation of the second half-velocity'
260 0 : write(std_out,*) 'Cartesian forces per atomic mass (fcart_m):'
261 0 : do kk=1,ab_mover%natom
262 0 : write (std_out,*) fcart_m(:,kk)
263 : end do
264 0 : write(std_out,*) 'vel:'
265 0 : do kk=1,ab_mover%natom
266 0 : write (std_out,*) vel(:,kk)
267 : end do
268 0 : write(std_out,*) 'v2gauss:',v2gauss
269 0 : write(std_out,*) 'a:',a
270 0 : write(std_out,*) 'b:',b
271 0 : write(std_out,*) 's:',s
272 0 : write(std_out,*) 'scdot:',scdot
273 : end if
274 :
275 : end if ! (if itime>1)
276 :
277 : !write(std_out,*) 'isokinetic 05'
278 : !##########################################################
279 : !### 05. First half-time (First cycle the loop is double)
280 :
281 945 : if (itime==1) then
282 : nfirst=2
283 : else
284 912 : nfirst=1
285 : end if
286 :
287 1923 : do ifirst=1,nfirst
288 :
289 : ! Application of Gauss' principle of least constraint according to Fei Zhang's algorithm (J. Chem. Phys. 106, 1997, [[cite:Zhang1997]] p.6102)
290 :
291 : ! v2gauss is twice the kinetic energy
292 978 : v2gauss=0.0_dp
293 31482 : do iatom=1,ab_mover%natom
294 122994 : do idim=1,3
295 122016 : v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
296 : end do
297 : end do
298 :
299 : ! If there is no kinetic energy to start with ...
300 978 : if (v2gauss<=v2tol.and.itime==1) then
301 : ! Maxwell-Boltzman distribution
302 31 : v2gauss=zero
303 31 : vtest=zero
304 731 : do iatom=1,ab_mover%natom
305 2831 : do idim=1,3
306 2800 : if(ab_mover%iatfix(idim,iatom)==0)then
307 2097 : vel(idim,iatom)=sqrt(kb_HaK*ab_mover%mdtemp(1)/ab_mover%amass(iatom))*cos(two_pi*uniformrandom(idum))
308 2097 : vel(idim,iatom)=vel(idim,iatom)*sqrt(-2._dp*log(uniformrandom(idum)))
309 : else
310 3 : vel(idim,iatom)=zero
311 : endif
312 : end do
313 : end do
314 :
315 : ! Get rid of center-of-mass velocity
316 731 : s1=sum(ab_mover%amass(:))
317 124 : do idim=1,3
318 2224 : if(sum(ab_mover%iatfix(idim,:))==0)then
319 2094 : s2=sum(ab_mover%amass(:)*vel(idim,:))
320 2094 : vel(idim,:)=vel(idim,:)-s2/s1
321 : endif
322 : end do
323 :
324 : ! Recompute v2gauss
325 731 : do iatom=1,ab_mover%natom
326 2831 : do idim=1,3
327 2100 : v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
328 2800 : vtest=vtest+vel(idim,iatom)/ndegfreedom
329 : end do
330 : end do
331 :
332 : ! Now rescale the velocities to give the exact temperature
333 31 : rescale_vel=sqrt(ndegfreedom*kb_HaK*ab_mover%mdtemp(1)/v2gauss)
334 2831 : vel(:,:)=vel(:,:)*rescale_vel
335 :
336 : ! Recompute v2gauss with the rescaled velocities
337 31 : v2gauss=zero
338 731 : do iatom=1,ab_mover%natom
339 2831 : do idim=1,3
340 2800 : v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
341 : end do
342 : end do
343 :
344 : ! Compute the variance and print
345 31 : sigma2=(v2gauss/ndegfreedom-ab_mover%amass(1)*vtest**2)/kb_HaK
346 :
347 : end if
348 :
349 31482 : do iatom=1,ab_mover%natom
350 122994 : do idim=1,3
351 122016 : if(ab_mover%iatfix(idim,iatom)==0)then
352 91472 : fcart_m(idim,iatom)=fcart(idim,iatom)/ab_mover%amass(iatom)
353 : else
354 40 : fcart_m(idim,iatom)=zero
355 : endif
356 : end do
357 : end do
358 :
359 978 : if (zDEBUG)then
360 0 : write(std_out,*) 'Calculation first half-velocity '
361 0 : write (std_out,*) 'vel:'
362 0 : do kk=1,ab_mover%natom
363 0 : write (std_out,*) vel(:,kk)
364 : end do
365 0 : write (std_out,*) 'xcart:'
366 0 : do kk=1,ab_mover%natom
367 0 : write (std_out,*) xcart(:,kk)
368 : end do
369 0 : write (std_out,*) 'xred:'
370 0 : do kk=1,ab_mover%natom
371 0 : write (std_out,*) xred(:,kk)
372 : end do
373 0 : write (std_out,*) 'fcart_m'
374 0 : do kk=1,ab_mover%natom
375 0 : write (std_out,*) fcart_m(:,kk)
376 : end do
377 0 : write(std_out,*) 's2',s2
378 0 : write(std_out,*) 'v2gauss',v2gauss
379 0 : write(std_out,*) 'sigma2',sigma2
380 :
381 : write(message, '(a)' )&
382 0 : & ' --- Rescaling or initializing velocities to initial temperature'
383 0 : call wrtout(std_out,message,'COLL')
384 : write(message, '(a,d12.5,a,D12.5)' )&
385 0 : & ' --- Scaling factor :',rescale_vel,' Asked T (K) ',ab_mover%mdtemp(1)
386 0 : call wrtout(std_out,message,'COLL')
387 : write(message, '(a,d12.5,a,D12.5)' )&
388 0 : & ' --- Effective temperature',v2gauss/(ndegfreedom*kb_HaK),' From variance', sigma2
389 0 : call wrtout(std_out,message,'COLL')
390 : end if
391 :
392 : ! Convert input xred (reduced coordinates) to xcart (cartesian)
393 978 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
394 :
395 1923 : if(itime==1.and.ifirst==1) then
396 33 : call wrtout(std_out,'if itime==1','COLL')
397 3089 : vel_nexthalf(:,:)=vel(:,:)
398 3089 : xcart_next(:,:)=xcart(:,:)
399 33 : call xcart2xred(ab_mover%natom,rprimd,xcart_next,xred_next)
400 3089 : xred=xred_next
401 33 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
402 : end if
403 :
404 : end do
405 :
406 : !Computation of vel_nexthalf (4.16 of [[cite:Minary2003]])
407 : !Computation of a and b (4.13 of [[cite:Minary2003]])
408 945 : a=0.0_dp
409 945 : b=0.0_dp
410 30685 : do iatom=1,ab_mover%natom
411 119905 : do idim=1,3
412 89220 : a=a+fcart_m(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
413 118960 : b=b+fcart_m(idim,iatom)*fcart_m(idim,iatom)*ab_mover%amass(iatom)
414 : end do
415 : end do
416 945 : a=a/v2gauss+tol20
417 945 : b=b/v2gauss+tol20
418 : !Computation of s and scdot
419 945 : sqb=sqrt(b)+tol20
420 945 : as=sqb*ab_mover%dtion/2.
421 : ! jmb
422 : if ( as > 300.0 ) as=300.0
423 945 : s1=cosh(as)
424 945 : s2=sinh(as)
425 945 : s=a*(s1-1.)/b+s2/sqb
426 945 : scdot=a*s2/sqb+s1
427 30685 : do iatom=1,ab_mover%natom
428 119905 : do idim=1,3
429 118960 : if(ab_mover%iatfix(idim,iatom)==0)then
430 89184 : vel_nexthalf(idim,iatom)=(vel(idim,iatom)+fcart_m(idim,iatom)*s)/scdot
431 : else
432 36 : vel_nexthalf(idim,iatom)=zero
433 : endif
434 : enddo
435 : enddo
436 :
437 : !Computation of the next positions
438 119905 : xcart_next(:,:)=xcart(:,:)+vel_nexthalf(:,:)*ab_mover%dtion
439 :
440 945 : if (zDEBUG)then
441 0 : write(std_out,*) 'a:',a
442 0 : write(std_out,*) 'b:',b
443 0 : write(std_out,*) 's:',s
444 0 : write(std_out,*) 'scdot:',scdot
445 : end if
446 :
447 : !Convert back to xred (reduced coordinates)
448 :
449 945 : call xcart2xred(ab_mover%natom,rprimd,xcart_next,xred_next)
450 :
451 : !write(std_out,*) 'isokinetic 06'
452 : !##########################################################
453 : !### 06. Update the history with the prediction
454 :
455 119905 : xcart=xcart_next
456 119905 : xred=xred_next
457 :
458 : !increment the ihist
459 945 : hist%ihist = abihist_findIndex(hist,+1)
460 :
461 : !Fill the history with the variables
462 : !xred, acell, rprimd, vel
463 945 : call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
464 119905 : hist%vel(:,:,hist%ihist)=vel(:,:)
465 945 : hist%time(hist%ihist)=real(itime,kind=dp)*ab_mover%dtion
466 :
467 945 : if(zDEBUG)then
468 0 : write (std_out,*) 'fcart:'
469 0 : do kk=1,ab_mover%natom
470 0 : write (std_out,*) fcart(:,kk)
471 : end do
472 0 : write (std_out,*) 'vel:'
473 0 : do kk=1,ab_mover%natom
474 0 : write (std_out,*) vel(:,kk)
475 : end do
476 0 : write (std_out,*) 'strten:'
477 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
478 0 : write (std_out,*) 'etotal:'
479 0 : write (std_out,*) etotal
480 : end if
481 :
482 : if (.false.) write(std_out,*) ntime
483 :
484 : end subroutine pred_isokinetic
485 : !!***
486 :
487 : end module m_pred_isokinetic
488 : !!***
|