Branch data Line data Source code
1 : : !!****m* ABINIT/m_pimd_langevin
2 : : !! NAME
3 : : !! m_pimd_langevin
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 2011-2026 ABINIT group (GG,MT)
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_pimd_langevin
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_errors
27 : : use m_pimd
28 : : use m_random_zbq
29 : :
30 : : use m_matrix, only : matr3inv
31 : : use m_geometry, only : xcart2xred, xred2xcart
32 : :
33 : :
34 : : implicit none
35 : :
36 : : private
37 : : !!***
38 : :
39 : : public :: pimd_langevin_npt
40 : : public :: pimd_langevin_nvt
41 : : !!***
42 : :
43 : : contains
44 : : !!***
45 : :
46 : : !!****f* ABINIT/pimd_langevin_npt
47 : : !! NAME
48 : : !! pimd_langevin_npt
49 : : !!
50 : : !! FUNCTION
51 : : !! Predicts new positions in Path Integral Molecular Dynamics using Langevin thermostat in the NPT ensemble.
52 : : !! Given the positions at time t and t-dtion, an estimation of the velocities at time t,
53 : : !! the forces and an estimation of the stress at time t, and an estimation of the cell at time t,
54 : : !! computes in the Path Integral Molecular Dynamics framework the new positions at time t+dtion,
55 : : !! computes self-consistently the velocities, the stress and the cell at time t and produces
56 : : !! an estimation of the velocities, stress and new cell at time t+dtion
57 : : !!
58 : : !! INPUTS
59 : : !! etotal(trotter)=electronic total energy for all images
60 : : !! itimimage=number of the current time for image propagation (itimimage+1 is to be predicted here)
61 : : !! natom=dimension of vel_timimage and xred_timimage
62 : : !! pimd_param=datastructure that contains all the parameters necessary to Path-Integral MD
63 : : !! prtvolimg=printing volume
64 : : !! rprimd(3,3)=dimensionless unit cell vectors (common to all images) at time t (present time step)
65 : : !! rprimd_prev(3,3)=dimensionless unit cell vectors (common to all images) at time t-dt (previous time step)
66 : : !! stressin(3,3,trotter)=electronic stress tensor for each image
67 : : !! trotter=Trotter number (total number of images)
68 : : !! volume=volume of unit cell (common to all images)
69 : : !! xred(3,natom,trotter)=reduced coordinates of atoms for all images at time t (present time step)
70 : : !! xred_prev(3,natom,trotter)=reduced coordinates of atoms for all images at time t-dt (previous time step)
71 : : !!
72 : : !! OUTPUT
73 : : !! rprimd_next(3,3)=dimensionless unit cell vectors (common to all images) at time t+dt (next time step)
74 : : !! xred_next(3,natom,trotter)=reduced coordinates of atoms for all images at time t+dt (next time step)
75 : : !!
76 : : !! SIDE EFFECTS
77 : : !! forces(3,natom,trotter)=forces over atoms for all images
78 : : !! at input, electronic forces
79 : : !! at output, electronic forces + quantum spring contribution
80 : : !! vel(3,natom,trotter)/vel_next(3,natom,trotter)/=velocies of atoms for all images
81 : : !! at input, vel(itimimage) = values of the estimated vel at t
82 : : !! at output, vel(itimimage) = values of the exact vel at t
83 : : !! vel_next(itimimage) = values of the estimated vel at t+dt
84 : : !! vel_cell(3,3)/vel_cell_next(3,3)=time derivative of cell parameters
85 : : !! at input, vel_cell(itimimage) = values of the estimated cell vel at t
86 : : !! at output, vel_cell(itimimage) = values of the exact cell vel at t
87 : : !! vel_cell_next(itimimage) = values of the estimated cell vel at t+dt
88 : : !!
89 : : !! NOTES
90 : : !! Here follows PIMD in the NPT ensemble within the Langevin barostat algorithm
91 : : !! of Quigley and Probert: J. Chem. Phys. 120, 11432 (2004) [[cite:Quigley2004]]
92 : : !! and Comput. Phys. Comm. 169, 322 (2005) [[cite:Quigley2005]]
93 : : !!
94 : : !! SOURCE
95 : :
96 : 5 : subroutine pimd_langevin_npt(etotal,forces,itimimage,natom,pimd_param,prtvolimg,&
97 : 5 : & rprimd,rprimd_next,rprimd_prev,stressin,trotter,vel,vel_next,vel_cell,&
98 : 5 : & vel_cell_next,volume,xred,xred_next,xred_prev)
99 : :
100 : : !Arguments ------------------------------------
101 : : !scalars
102 : : integer,intent(in) :: itimimage,natom,prtvolimg,trotter
103 : : real(dp),intent(in) :: volume
104 : : type(pimd_type),intent(in) :: pimd_param
105 : : !arrays
106 : : real(dp),intent(in) :: etotal(trotter),rprimd(3,3),rprimd_prev(3,3),stressin(3,3,trotter)
107 : : real(dp),intent(in),target :: xred(3,natom,trotter),xred_prev(3,natom,trotter)
108 : : real(dp),intent(out) :: rprimd_next(3,3),xred_next(3,natom,trotter)
109 : : real(dp),intent(out) :: vel_next(3,natom,trotter),vel_cell_next(3,3)
110 : : real(dp),intent(inout) :: forces(3,natom,trotter),vel(3,natom,trotter),vel_cell(3,3)
111 : :
112 : : !Local variables-------------------------------
113 : : !Options
114 : : ! Option for the Langevin algorithm correction
115 : : integer,parameter :: ilangevin=0
116 : : ! The following option forces the total of forces to be zero
117 : : ! It prevents the translation of the center of mass
118 : : ! If it is zero, no constraint on mass center is applied
119 : : integer,parameter :: zeroforce=1
120 : : ! Tolerance for the SC cycle
121 : : real(dp),parameter :: tolerance=tol9
122 : :
123 : : !scalars
124 : : integer :: idum=-5
125 : : integer :: constraint,iatom,ii,iimage,irestart,jj,ndof,prtstress
126 : : real(dp) :: dtion,eharm,eharm2,epot,friction,frictionbar,initemp,kt,rescale_temp,scalebar
127 : : real(dp) :: temperature1,temperature2,temp2_prev,thermtemp,tol,tracepg,wg
128 : : !arrays
129 : : real, parameter :: identity(3,3)=reshape((/(one,(zero,ii=1,3),jj=1,2),one/),(/3,3/))
130 : : real(dp) :: aleabar(3,3),constraint_output(2),ddh(3,3),diffstress(3,3)
131 : : real(dp) :: dstrhh(3,3),fg(3,3),invrprimd(3,3)
132 : : real(dp) :: langev_bar(3,3),pg(3,3),pgdh(3,3),stress_pimd(3,3,3),strtarget(6),tmp(3,3)
133 : 5 : real(dp),allocatable :: alea(:,:,:),forces_orig(:,:,:),forces_pimd(:,:,:),forces_pimd_red(:,:)
134 : 5 : real(dp),allocatable :: fsup(:,:),hxredpoint(:,:,:),inertmass(:),langev(:,:)
135 : 5 : real(dp),allocatable :: mass(:,:),quantummass(:),spring(:,:)
136 : 5 : real(dp),allocatable :: xcart(:,:,:),xcart_next(:,:,:),xcart_prev(:,:,:)
137 : 5 : real(dp),allocatable :: xredpoint(:,:,:)
138 : :
139 : : ! *************************************************************************
140 : :
141 : : !############# Initializations ###########################
142 : :
143 : : !Allocation of local arrays
144 [ - + + - : 20 : ABI_MALLOC(xcart,(3,natom,trotter))
- + + - +
- + - - +
- + ]
145 [ - + + - : 15 : ABI_MALLOC(xcart_prev,(3,natom,trotter))
- + + - -
+ - + ]
146 [ - + + - : 15 : ABI_MALLOC(xcart_next,(3,natom,trotter))
- + + - -
+ - + ]
147 [ - + + - : 15 : ABI_MALLOC(forces_orig,(3,natom,trotter))
- + + - -
+ - + ]
148 [ - + + - : 15 : ABI_MALLOC(forces_pimd,(3,natom,trotter))
- + + - -
+ - + ]
149 [ - + + - : 15 : ABI_MALLOC(inertmass,(natom))
+ - + - -
+ - + ]
150 [ - + + - : 10 : ABI_MALLOC(quantummass,(natom))
- + - + ]
151 : :
152 : : !Fill in the local variables
153 : 5 : ndof=3*natom*trotter
154 : 5 : rescale_temp=one;if(zeroforce==1)rescale_temp=dble(ndof)/dble(ndof-3)
155 [ + - + + : 65 : quantummass(1:natom)=pimd_param%amu (pimd_param%typat(1:natom))*amu_emass
+ + ]
156 [ + + + + ]: 65 : inertmass (1:natom)=pimd_param%pimass(pimd_param%typat(1:natom))*amu_emass
157 : 5 : initemp=pimd_param%mdtemp(1)/rescale_temp
158 : 5 : thermtemp=pimd_param%mdtemp(2)
159 : 5 : dtion=pimd_param%dtion
160 : 5 : kt=thermtemp*kb_HaK
161 : 5 : friction=pimd_param%friction
162 : 5 : wg=pimd_param%bmass
163 [ + + ]: 35 : strtarget(:)=pimd_param%strtarget(:) ! imposed stress tensor
164 : 5 : frictionbar=pimd_param%frictionbar ! friction coeff of barostat
165 : 5 : scalebar=sqrt(two*frictionbar*wg*kt/dtion)
166 [ - + + + : 135 : forces_orig=forces
+ + + + ]
167 : 5 : constraint=0
168 : :
169 : : !Masses and spring constants
170 [ - + + - : 10 : ABI_MALLOC(mass,(natom,1))
- + - + ]
171 [ - + + - : 10 : ABI_MALLOC(spring,(natom,1))
- + - + ]
172 : 5 : call pimd_mass_spring(inertmass,kt,mass,natom,quantummass,spring,0,trotter)
173 : :
174 : : !Initialize random forces
175 [ - + + - : 15 : ABI_MALLOC(alea,(3,natom,trotter))
- + + - -
+ - + ]
176 [ - + + - : 20 : ABI_MALLOC(langev,(natom,trotter))
- + + - +
- + - - +
- + ]
177 [ + + ]: 35 : langev(:,1)=sqrt(two*friction*inertmass(:)*kt/dtion)
178 : : if(ilangevin==1)then
179 : : langev(:,1)=langev(:,1)*sqrt(one-(friction*dtion/(two*inertmass(:))))
180 : : end if
181 : :
182 : : !Random number generator initialization
183 [ + + ]: 5 : if(itimimage<=1) then
184 : 1 : call pimd_langevin_random_init(pimd_param%irandom,idum)
185 : : end if
186 : :
187 : : !Compute cartesian coordinates
188 [ + + ]: 10 : do iimage=1,trotter
189 : 5 : call xred2xcart(natom,rprimd,xcart (:,:,iimage),xred(:,:,iimage))
190 : 10 : call xred2xcart(natom,rprimd,xcart_prev(:,:,iimage),xred_prev(:,:,iimage))
191 : : end do
192 : :
193 : : !Determine if it is a restart or not
194 : : !If this is a calculation from scratch,generate random distribution of velocities
195 [ + + ]: 5 : irestart=1;if (itimimage==1) irestart=pimd_is_restart(mass,vel,vel_cell)
196 : :
197 : : !Initialize derivatives
198 [ + + ]: 5 : if (mod(irestart,10)==0) then
199 [ + - - - : 1 : call pimd_initvel(idum,mass,natom,initemp,trotter,vel,pimd_param%constraint,pimd_param%wtatcon)
- - - - -
- - + ]
200 : : end if
201 : : !vel_cell does not depend on Trotter...
202 [ + - ]: 5 : ddh(:,:)=vel_cell(:,:);if (irestart<10) ddh=zero
203 : :
204 [ + + ]: 5 : if (itimimage<=1) then
205 : :
206 : : ! ========================= FIRST TIME STEP =======================================
207 : :
208 [ - + + - : 3 : ABI_MALLOC(hxredpoint,(3,natom,trotter))
- + + - -
+ - + -
+ ]
209 [ - + + - : 3 : ABI_MALLOC(xredpoint,(3,natom,trotter))
- + + - -
+ - + -
+ ]
210 [ - + + - : 3 : ABI_MALLOC(forces_pimd_red,(3,natom))
+ - + - -
+ - + ]
211 [ - + + - : 2 : ABI_MALLOC(fsup,(3,natom))
- + - + ]
212 : :
213 [ + + ]: 2 : do iimage=1,trotter
214 [ + - + + : 182 : hxredpoint(:,:,iimage)=vel(:,:,iimage) - matmul(ddh(:,:),xred(:,:,iimage))
+ + + + +
+ + + + -
+ - + + +
+ ]
215 : : end do
216 : 1 : call matr3inv(rprimd,invrprimd)
217 [ + + ]: 2 : do iimage=1,trotter
218 [ + - + + : 266 : xredpoint(:,:,iimage)=matmul(invrprimd(:,:),hxredpoint(:,:,iimage))
+ + + + +
+ + + + -
+ - + - +
- ]
219 : : end do
220 : :
221 : : ! Generate random numbers
222 : 1 : call pimd_langevin_random(alea,pimd_param%irandom,idum,langev,mass,natom,trotter,zeroforce)
223 : :
224 : : ! Compute PIMD and Langevin contributions to forces
225 : 1 : call pimd_forces(forces,natom,spring,0,trotter,xcart)
226 : 1 : call pimd_langevin_forces(alea,forces,forces_pimd,friction,langev,mass,natom,trotter,hxredpoint)
227 : : call pimd_apply_constraint(pimd_param%constraint,constraint_output,forces_pimd,&
228 [ + - - - : 1 : & mass,natom,trotter,pimd_param%wtatcon,xcart)
- - - - -
- - + ]
229 [ + + + + : 40 : tmp=matmul(invrprimd,ddh)
+ + ]
230 [ + + + + : 52 : pg=wg*matmul(ddh,invrprimd)
+ + + + +
+ ]
231 : 1 : tracepg=pg(1,1)+pg(2,2)+pg(3,3)
232 : :
233 : : ! Taylor algorithm
234 [ + + ]: 2 : do iimage=1,trotter
235 : 1 : call xcart2xred(natom,rprimd,forces_pimd(:,:,iimage),forces_pimd_red)
236 [ + - + + : 157 : fsup(:,:)=matmul(tmp,xredpoint(:,:,iimage))
+ + + + +
+ + + + -
+ - ]
237 [ + + ]: 8 : do iatom=1,natom
238 : : xred_next(:,iatom,iimage)=xred(:,iatom,iimage)+dtion*xredpoint(:,iatom,iimage) + &
239 : : & half*( &
240 : : & forces_pimd_red(:,iatom)-two*inertmass(iatom)*fsup(:,iatom)- &
241 : : & (tracepg*inertmass(iatom)*xredpoint(:,iatom,iimage)/(wg*dble(ndof))) &
242 [ + + ]: 25 : & )*dtion*dtion/inertmass(iatom)
243 : : end do
244 : : end do
245 : :
246 : : ! predict rprimd at time t+dt from taylor algorithm
247 : 1 : call pimd_langevin_random_bar(aleabar,pimd_param%irandom,idum)
248 [ + + + + : 52 : langev_bar=matmul(aleabar,rprimd)*scalebar
+ + + + +
+ ]
249 : 1 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,thermtemp,thermtemp,trotter,hxredpoint,volume,xcart)
250 : 1 : diffstress=pimd_diff_stress(stress_pimd,strtarget)
251 [ + + + + : 40 : dstrhh=matmul(diffstress,rprimd)
+ + ]
252 [ + + + + : 40 : pgdh=matmul(pg,ddh)
+ + ]
253 : 1 : temperature1=pimd_temperature(mass,hxredpoint)*rescale_temp
254 [ + + + + ]: 13 : fg(:,:)=volume*dstrhh(:,:)+pgdh(:,:)+temperature1*kb_HaK*rprimd(:,:)
255 : :
256 : : rprimd_next(:,:)=rprimd(:,:) + dtion*ddh(:,:) + half*( &
257 : : & fg(:,:)-wg*frictionbar*ddh(:,:)+langev_bar &
258 [ + + + + ]: 13 : & )*dtion*dtion/wg
259 : :
260 : : ! Recompute xcart_next
261 [ + + ]: 2 : do iimage=1,trotter
262 : 2 : call xred2xcart(natom,rprimd_next,xcart_next(:,:,iimage),xred_next(:,:,iimage))
263 : : end do
264 : :
265 : : ! Compute stress tensor at t from virial theorem
266 : 1 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,thermtemp,thermtemp,trotter,vel,volume,xcart)
267 : :
268 : : ! Translate from pressure to stress for print
269 [ + + + + : 40 : stress_pimd=-stress_pimd
+ + ]
270 : :
271 : : ! Compute temperature at current step
272 : 1 : temperature1=pimd_temperature(mass,vel)*rescale_temp
273 : :
274 : : ! Estimate the velocities at t+dt
275 [ + + ]: 2 : do iimage=1,trotter
276 [ + + ]: 8 : do iatom=1,natom
277 : : xredpoint(:,iatom,iimage)=xredpoint(:,iatom,iimage)+(forces_pimd_red(:,iatom)-two*inertmass(iatom)*fsup(:,iatom)- &
278 [ + + ]: 25 : (tracepg*inertmass(iatom)*xredpoint(:,iatom,iimage)/(wg*dble(ndof))))*dtion/inertmass(iatom)
279 : : end do
280 : : end do
281 [ + + + + ]: 13 : ddh(:,:)=ddh(:,:)+( fg(:,:)-wg*frictionbar*ddh(:,:)+langev_bar(:,:) )*dtion/wg
282 [ + + ]: 2 : do iimage=1,trotter
283 : 2 : call xred2xcart(natom,rprimd_next,hxredpoint(:,:,iimage),xredpoint(:,:,iimage))
284 : : end do
285 [ + + ]: 2 : do iimage=1,trotter
286 [ + + ]: 8 : do iatom=1,natom
287 [ + + + + : 115 : vel_next(:,iatom,iimage)=hxredpoint(:,iatom,iimage)+matmul(ddh(:,:),xred(:,iatom,iimage))
+ + + + ]
288 : : end do
289 : : end do
290 : :
291 : : ! Compute new temperature
292 : 1 : temperature2=pimd_temperature(mass,vel)*rescale_temp
293 : :
294 [ + + + + : 26 : vel=xredpoint !scaled velocities transmitted to step 2
+ + ]
295 : :
296 [ - + ]: 1 : ABI_FREE(hxredpoint)
297 [ - + ]: 1 : ABI_FREE(xredpoint)
298 [ - + ]: 1 : ABI_FREE(forces_pimd_red)
299 [ - + ]: 1 : ABI_FREE(fsup)
300 : :
301 : : else
302 : :
303 : : ! ========================= OTHER TIME STEPS ======================================
304 : :
305 : : ! Additional allocations
306 [ - + + - : 12 : ABI_MALLOC(hxredpoint,(3,natom,trotter))
- + + - -
+ - + -
+ ]
307 [ - + + - : 12 : ABI_MALLOC(xredpoint,(3,natom,trotter))
- + + - -
+ - + -
+ ]
308 [ - + + - : 12 : ABI_MALLOC(forces_pimd_red,(3,natom))
+ - + - -
+ - + ]
309 [ - + + - : 8 : ABI_MALLOC(fsup,(3,natom))
- + - + ]
310 : :
311 : 4 : ddh=vel_cell(:,:)
312 : :
313 [ + + ]: 8 : do iimage=1,trotter
314 [ + - + + : 728 : hxredpoint(:,:,iimage)=vel(:,:,iimage) - matmul(ddh(:,:),xred(:,:,iimage))
+ + + + +
+ + + + -
+ - + + +
+ ]
315 : : end do
316 : :
317 : : ! first estimation of ddh, pg and its trace:
318 : 4 : call matr3inv(rprimd,invrprimd)
319 [ + + + + : 208 : pg=wg*matmul(ddh,invrprimd)
+ + + + +
+ ]
320 : 4 : tracepg=pg(1,1)+pg(2,2)+pg(3,3)
321 : :
322 : : ! Momenta hxredpoint = H ds/dt: estimation
323 [ + + ]: 8 : do iimage=1,trotter
324 [ + - + + : 632 : hxredpoint(:,:,iimage)=matmul(rprimd,vel(:,:,iimage))
+ + + + +
+ + + + -
+ - ]
325 : : end do
326 : :
327 : : ! Compute temperature at t
328 : 4 : temperature1=pimd_temperature(mass,hxredpoint)*rescale_temp
329 : :
330 : : ! Generate random numbers
331 : 4 : call pimd_langevin_random(alea,pimd_param%irandom,idum,langev,mass,natom,trotter,zeroforce)
332 : :
333 : : ! Generate random numbers for the barostat
334 : 4 : call pimd_langevin_random_bar(aleabar,pimd_param%irandom,idum)
335 [ + + + + : 208 : langev_bar=matmul(aleabar,rprimd)*scalebar
+ + + + +
+ ]
336 : :
337 : : ! Compute PIMD and Langevin contributions to forces
338 : 4 : call pimd_forces(forces,natom,spring,0,trotter,xcart)
339 : 4 : call pimd_langevin_forces(alea,forces,forces_pimd,friction,langev,mass,natom,trotter,hxredpoint)
340 : : call pimd_apply_constraint(pimd_param%constraint,constraint_output,forces_pimd,&
341 [ + - - - : 4 : & mass,natom,trotter,pimd_param%wtatcon,xcart)
- - - - -
- - + ]
342 : :
343 : : ! Compute difference between instantaneous stress and imposed stress (barostat)
344 : 4 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,thermtemp,thermtemp,trotter,hxredpoint,volume,xcart)
345 : :
346 : 4 : diffstress=pimd_diff_stress(stress_pimd,strtarget)
347 : :
348 : : ! Compute "force" on supercell vectors
349 [ + + + + : 160 : dstrhh=matmul(diffstress,rprimd)
+ + ]
350 [ + + + + : 160 : pgdh=matmul(pg,ddh)
+ + ]
351 [ + + + + ]: 52 : fg(:,:)=volume*dstrhh(:,:)+pgdh(:,:)+temperature1*kb_HaK*rprimd(:,:)
352 : :
353 : : ! Evolve the supercell (fist estimation)
354 [ + + + + ]: 52 : rprimd_next=two*rprimd-rprimd_prev+(fg-wg*frictionbar*ddh+langev_bar)*dtion*dtion/wg
355 : :
356 : : ! Evolve atomic positions (first estimation)
357 [ + + + + : 160 : tmp=matmul(invrprimd,ddh)
+ + ]
358 [ + + ]: 8 : do iimage=1,trotter
359 : 4 : call xcart2xred(natom,rprimd,hxredpoint(:,:,iimage),xredpoint(:,:,iimage))
360 [ + - + + : 628 : fsup(:,:)=matmul(tmp,xredpoint(:,:,iimage))
+ + + + +
+ + + + -
+ - ]
361 : 4 : call xcart2xred(natom,rprimd,forces_pimd(:,:,iimage),forces_pimd_red)
362 : :
363 [ + + ]: 32 : do iatom=1,natom
364 : : xred_next(:,iatom,iimage)= &
365 : : & two*xred(:,iatom,iimage) - xred_prev(:,iatom,iimage) &
366 : : & +(forces_pimd_red(:,iatom)-two*inertmass(iatom)*fsup(:,iatom) &
367 : : & -tracepg*inertmass(iatom)*xredpoint(:,iatom,iimage)/(wg*dble(ndof))) &
368 [ + + ]: 100 : & *dtion*dtion/inertmass(iatom)
369 : : end do
370 : : end do
371 : :
372 : : ! Self-consistent loop
373 : 4 : temperature2=pimd_temperature(mass,xredpoint)*rescale_temp
374 : 4 : temp2_prev=temperature2; tol=one
375 : :
376 [ + + ]: 25 : do while (tol>tolerance)
377 : : ! Reestimate dH/dt at t
378 [ + + + + ]: 273 : ddh(:,:)=(rprimd_next(:,:)-rprimd_prev(:,:))/(two*dtion)
379 : :
380 : : ! Reestimate the scaled velocities at t
381 [ + + ]: 42 : do iimage=1,trotter
382 [ + + + + ]: 525 : xredpoint(:,:,iimage)=(xred_next(:,:,iimage)-xred_prev(:,:,iimage))/(two*dtion)
383 : 42 : call xred2xcart(natom,rprimd,hxredpoint(:,:,iimage),xredpoint(:,:,iimage))
384 : : end do
385 : : ! Reestimate the forces
386 : 21 : call pimd_langevin_forces(alea,forces,forces_pimd,friction,langev,mass,natom,trotter,hxredpoint)
387 : : call pimd_apply_constraint(pimd_param%constraint,constraint_output,forces_pimd,&
388 [ + - - - : 21 : & mass,natom,trotter,pimd_param%wtatcon,xcart)
- - - - -
- - + ]
389 : : ! Compute variation of temperature (to check convergence of SC loop)
390 : 21 : temperature2=pimd_temperature(mass,xredpoint)*rescale_temp
391 : 21 : tol=dabs(temperature2-temp2_prev)/dabs(temp2_prev)
392 : 21 : temp2_prev=temperature2
393 : : ! Recompute the temperature
394 : 21 : temperature2=pimd_temperature(mass,hxredpoint)*rescale_temp
395 : : ! Recompute pg
396 [ + + + + : 1092 : pg=wg*matmul(ddh,invrprimd)
+ + + + +
+ ]
397 : 21 : tracepg=pg(1,1)+pg(2,2)+pg(3,3)
398 : : ! Recompute difference between instantaneous stress and imposed stress (barostat)
399 : 21 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,thermtemp,thermtemp,trotter,hxredpoint,volume,xcart)
400 : :
401 : 21 : diffstress=pimd_diff_stress(stress_pimd,strtarget)
402 : :
403 : : ! Recompute "force" on supercell vectors
404 [ + + + + : 840 : dstrhh=matmul(diffstress,rprimd)
+ + ]
405 [ + + + + : 840 : pgdh=matmul(pg,ddh)
+ + ]
406 [ + + + + ]: 273 : fg(:,:)=volume*dstrhh(:,:)+pgdh(:,:)+temperature2*kb_HaK*rprimd(:,:)
407 : : ! Evolve the supercell (better estimation)
408 [ + + + + ]: 273 : rprimd_next=two*rprimd-rprimd_prev+(fg-wg*frictionbar*ddh+langev_bar)*dtion*dtion/wg
409 : :
410 : : ! Evolve atomic positions (better estimation):
411 [ + + + + : 840 : tmp=matmul(invrprimd,ddh)
+ + ]
412 [ + + ]: 46 : do iimage=1,trotter
413 : 21 : call xcart2xred(natom,rprimd,hxredpoint(:,:,iimage),xredpoint(:,:,iimage))
414 [ + - + + : 3297 : fsup(:,:)=matmul(tmp,xredpoint(:,:,iimage))
+ + + + +
+ + + + -
+ - ]
415 : 21 : call xcart2xred(natom,rprimd,forces_pimd(:,:,iimage),forces_pimd_red)
416 [ + + ]: 168 : do iatom=1,natom
417 : : xred_next(:,iatom,iimage)= &
418 : : & two*xred(:,iatom,iimage) - xred_prev(:,iatom,iimage) &
419 : : & +(forces_pimd_red(:,iatom)-two*inertmass(iatom)*fsup(:,iatom) &
420 : : & -(tracepg*inertmass(iatom)*xredpoint(:,iatom,iimage)/(wg*dble(ndof)))) &
421 [ + + ]: 525 : & *dtion*dtion/inertmass(iatom)
422 : : end do
423 : : end do
424 : : end do ! End self-consistent loop
425 : :
426 : : ! Computation of true temperature from true velocities at t
427 [ + + ]: 8 : do iimage=1,trotter
428 [ + - + + : 512 : vel(:,:,iimage)=hxredpoint(:,:,iimage)+matmul(ddh,xred(:,:,iimage))
+ + + + +
+ + + + +
+ + ]
429 : : end do
430 : 4 : temperature2=pimd_temperature(mass,vel)*rescale_temp
431 : :
432 : : ! Computation of the real stress tensor at t
433 : 4 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,thermtemp,thermtemp,trotter,vel,volume,xcart)
434 : :
435 : : ! translate from pressure to stress
436 [ + + + + : 160 : stress_pimd=-stress_pimd
+ + ]
437 : :
438 : : ! Deallocations (Verlet algo)
439 [ - + ]: 4 : ABI_FREE(xredpoint)
440 [ - + ]: 4 : ABI_FREE(hxredpoint)
441 [ - + ]: 4 : ABI_FREE(forces_pimd_red)
442 [ - + ]: 4 : ABI_FREE(fsup)
443 : :
444 : : end if ! itimimage==1
445 : :
446 : : !############# Final operations ############################
447 : :
448 : : !Compute contributions to energy
449 : 5 : call pimd_energies(eharm,eharm2,epot,etotal,forces_orig,natom,spring,trotter,xcart)
450 : :
451 : : !Print messages
452 : 5 : prtstress=1
453 : : call pimd_print(constraint,constraint_output,&
454 : : & eharm,eharm2,epot,forces_pimd,inertmass,irestart,&
455 : : & itimimage,kt,natom,pimd_param%optcell,prtstress,prtvolimg,rprimd,&
456 : : & stress_pimd,temperature2,&
457 : 5 : & pimd_param%traj_unit,trotter,vel,ddh,xcart,xred)
458 : :
459 : : !Compute cartesian coordinates
460 [ + + ]: 10 : do iimage=1,trotter
461 : 10 : call xred2xcart(natom,rprimd_next,xcart_next(:,:,iimage),xred_next(:,:,iimage))
462 : : end do
463 : :
464 : : !If possible, estimate the velocities at t+dt
465 [ + + ]: 5 : if (itimimage>1) then
466 : 4 : call pimd_predict_vel(dtion,itimimage,natom,trotter,0,xcart,xcart_next,xcart_prev,vel_next)
467 : 4 : call pimd_predict_velcell(dtion,itimimage,rprimd,rprimd_next,rprimd_prev,ddh)
468 : : end if
469 : :
470 : : !Return cell velocities (does not depend on Trotter)
471 : 5 : vel_cell_next(:,:)=ddh(:,:)
472 : :
473 : : !Free memory
474 [ - + ]: 5 : ABI_FREE(xcart)
475 [ - + ]: 5 : ABI_FREE(xcart_prev)
476 [ - + ]: 5 : ABI_FREE(xcart_next)
477 [ - + ]: 5 : ABI_FREE(forces_orig)
478 [ - + ]: 5 : ABI_FREE(forces_pimd)
479 [ - + ]: 5 : ABI_FREE(inertmass)
480 [ - + ]: 5 : ABI_FREE(quantummass)
481 [ - + ]: 5 : ABI_FREE(mass)
482 [ - + ]: 5 : ABI_FREE(spring)
483 [ - + ]: 5 : ABI_FREE(alea)
484 [ - + ]: 5 : ABI_FREE(langev)
485 : :
486 [ - + - + : 10 : end subroutine pimd_langevin_npt
- + ]
487 : : !!***
488 : :
489 : : !!****f* ABINIT/pimd_langevin_nvt
490 : : !! NAME
491 : : !! pimd_langevin_nvt
492 : : !!
493 : : !! FUNCTION
494 : : !! Predicts new positions in Path Integral Molecular Dynamics using Langevin thermostat in the NVT ensemble.
495 : : !! Given the positions at time t and t-dtion, an estimation of the velocities at time t,
496 : : !! the forces and an estimation of the stress at time t, and an estimation of the cell at time t,
497 : : !! computes in the Path Integral Molecular Dynamics framework the new positions at time t+dtion,
498 : : !! computes self-consistently the velocities, the stress and the cell at time t and produces
499 : : !! an estimation of the velocities, stress and new cell at time t+dtion
500 : : !!
501 : : !! INPUTS
502 : : !! etotal(trotter)=electronic total energy for all images
503 : : !! itimimage=number of the current time for image propagation (itimimage+1 is to be predicted here)
504 : : !! natom=dimension of vel_timimage and xred_timimage
505 : : !! pimd_param=datastructure that contains all the parameters necessary to Path-Integral MD
506 : : !! prtvolimg=printing volume
507 : : !! rprimd(3,3)=dimensionless unit cell vectors (common to all images)
508 : : !! stressin(3,3,trotter)=electronic stress tensor for each image
509 : : !! trotter=Trotter number (total number of images)
510 : : !! volume=volume of unit cell (common to all images)
511 : : !! xred(3,natom,trotter)=reduced coordinates of atoms for all images at time t (present time step)
512 : : !! xred_prev(3,natom,trotter)=reduced coordinates of atoms for all images at time t-dt (previous time step)
513 : : !!
514 : : !! OUTPUT
515 : : !! xred_next(3,natom,trotter)=reduced coordinates of atoms for all images at time t+dt (next time step)
516 : : !!
517 : : !! SIDE EFFECTS
518 : : !! forces(3,natom,trotter)=forces over atoms for all images
519 : : !! at input, electronic forces
520 : : !! at output, electronic forces + quantum spring contribution
521 : : !! vel(3,natom,trotter)/vel_next(3,natom,trotter)/=velocies of atoms for all images
522 : : !! at input, vel(itimimage) = values of the estimated vel at t
523 : : !! at output, vel(itimimage) = values of the exact vel at t
524 : : !! vel_next(itimimage) = values of the estimated vel at t+dt
525 : : !!
526 : : !! NOTES
527 : : !! See Quigley,Probert, JCP 120, 11432 (2004) [[cite:Quigley2004]], part III
528 : : !!
529 : : !! SOURCE
530 : :
531 : 25 : subroutine pimd_langevin_nvt(etotal,forces,itimimage,natom,pimd_param,prtvolimg,&
532 : 25 : & rprimd,stressin,trotter,vel,vel_next,volume,xred,xred_next,xred_prev)
533 : :
534 : : !Arguments ------------------------------------
535 : : !scalars
536 : : integer,intent(in) :: itimimage,natom,prtvolimg,trotter
537 : : real(dp),intent(in) :: volume
538 : : type(pimd_type),intent(in) :: pimd_param
539 : : !arrays
540 : : real(dp),intent(in) :: etotal(trotter),rprimd(3,3),stressin(3,3,trotter)
541 : : real(dp),intent(in),target :: xred(3,natom,trotter),xred_prev(3,natom,trotter)
542 : : real(dp),intent(out) :: xred_next(3,natom,trotter),vel_next(3,natom,trotter)
543 : : real(dp),intent(inout) :: forces(3,natom,trotter),vel(3,natom,trotter)
544 : :
545 : : !Local variables-------------------------------
546 : : !Options
547 : : ! Option for the Langevin algorithm correction
548 : : integer,parameter :: ilangevin=0
549 : : ! Tolerance for the SC cycle
550 : : real(dp),parameter :: tolerance=tol9
551 : :
552 : : !scalars
553 : : integer :: idum=-5
554 : : integer :: iimage,irestart,ndof,pitransform,prtstress,use_qtb,zeroforce
555 : : real(dp) :: dtion,eharm,eharm2,epot,friction,initemp,kt,kt_,rescale_temp
556 : : real(dp) :: temperature1,temperature2,temp2_prev,thermtemp,tol
557 : : !arrays
558 : 50 : real(dp) :: constraint_output(2),spring_prim(natom),stress_pimd(3,3,3),vel_cell(3,3)
559 : 25 : real(dp),allocatable :: alea(:,:,:),forces_orig(:,:,:),forces_pimd(:,:,:)
560 : 25 : real(dp),allocatable :: inertmass(:),langev(:,:),mass(:,:),quantummass(:),spring(:,:)
561 : 25 : real(dp),allocatable :: xcart(:,:,:),xcart_next(:,:,:),xcart_prev(:,:,:)
562 : :
563 : : ! *************************************************************************
564 : :
565 [ - + - - ]: 25 : if (pimd_param%use_qtb==1.and.pimd_param%qtb_file_unit<=0) then
566 : 0 : ABI_BUG('piqtb_force not open!')
567 : : end if
568 : :
569 : : !############# Initializations ###########################
570 : :
571 : 25 : pitransform=pimd_param%pitransform
572 : :
573 : : !The following option forces the total of forces to be zero
574 : : !It prevents the translation of the center of mass
575 : : !If it is zero, no constraint on mass center is applied
576 : 25 : zeroforce=1
577 [ - + ]: 25 : if(pitransform==1) zeroforce=0
578 [ + + ]: 25 : if(pitransform==2) zeroforce=0
579 [ + + ]: 25 : if(pimd_param%constraint==1) zeroforce=0
580 : :
581 : : !Allocation of local arrays
582 [ - + + - : 100 : ABI_MALLOC(xcart,(3,natom,trotter))
- + + - +
- + - - +
- + ]
583 [ - + + - : 75 : ABI_MALLOC(xcart_prev,(3,natom,trotter))
- + + - -
+ - + ]
584 [ - + + - : 75 : ABI_MALLOC(xcart_next,(3,natom,trotter))
- + + - -
+ - + ]
585 [ - + + - : 75 : ABI_MALLOC(forces_orig,(3,natom,trotter))
- + + - -
+ - + ]
586 [ - + + - : 75 : ABI_MALLOC(forces_pimd,(3,natom,trotter))
- + + - -
+ - + ]
587 [ - + + - : 75 : ABI_MALLOC(inertmass,(natom))
+ - + - -
+ - + ]
588 [ - + + - : 50 : ABI_MALLOC(quantummass,(natom))
- + - + ]
589 : :
590 : : !Fill in the local variables
591 : 25 : use_qtb=pimd_param%use_qtb
592 : 25 : ndof=3*natom*trotter
593 : 25 : rescale_temp=one
594 [ + + ]: 25 : if(zeroforce==1) rescale_temp=dble(ndof)/dble(ndof-3)
595 [ + - + + : 205 : quantummass(1:natom)=pimd_param%amu (pimd_param%typat(1:natom))*amu_emass
+ + ]
596 [ + + + + ]: 205 : inertmass (1:natom)=pimd_param%pimass(pimd_param%typat(1:natom))*amu_emass
597 [ - + - - : 25 : if(pitransform==1) inertmass=quantummass !compulsory for good definition of normal mode masses
- - ]
598 [ + + - + : 55 : if(pitransform==2) inertmass=quantummass !compulsory for good definition of staging masses
+ + ]
599 : 25 : initemp=pimd_param%mdtemp(1)/rescale_temp
600 : 25 : thermtemp=pimd_param%mdtemp(2)
601 : 25 : friction=pimd_param%friction
602 : 25 : dtion=pimd_param%dtion
603 : 25 : kt=thermtemp*kb_HaK
604 [ - + + + : 1610 : forces_orig=forces
+ + + + ]
605 : :
606 : : !Masses and spring constants
607 : 15 : select case(pitransform)
608 : : case(0)
609 [ - + + - : 30 : ABI_MALLOC(mass,(natom,1)) ! This second dimension is needed
- + - + ]
610 [ - + + - : 30 : ABI_MALLOC(spring,(natom,1))
- + - + ]
611 [ - + + - : 30 : ABI_MALLOC(langev,(natom,1))
- + - + ]
612 : : case(1,2)
613 [ - + + - : 40 : ABI_MALLOC(mass,(natom,trotter))
- + + - +
- + - - +
- + ]
614 [ - + + - : 30 : ABI_MALLOC(spring,(natom,trotter))
- + + - -
+ - + ]
615 [ + + - - : 55 : ABI_MALLOC(langev,(natom,trotter))
+ + - - +
+ - - + -
+ ]
616 : : end select
617 [ + + ]: 115 : spring_prim(:)=quantummass(:)*dble(trotter)*kt*kt
618 : 25 : call pimd_mass_spring(inertmass,kt,mass,natom,quantummass,spring,pitransform,trotter)
619 : :
620 : : !Initialize random forces
621 [ - + + - : 75 : ABI_MALLOC(alea,(3,natom,trotter))
- + + - -
+ - + ]
622 [ + - ]: 25 : if (use_qtb==0) then
623 [ + + + + ]: 290 : langev(:,:)=sqrt(two*friction*mass(:,:)*kt/dtion)
624 : : else
625 [ # # # # ]: 0 : langev(:,:)=sqrt(two*friction*mass(:,:))
626 : : end if
627 : :
628 : : !Random number generator initialization
629 [ + + ]: 25 : if(itimimage<=1) then
630 : 4 : call pimd_langevin_random_init(pimd_param%irandom,idum)
631 : : end if
632 : :
633 : : !Compute cartesian coordinates
634 [ + + ]: 145 : do iimage=1,trotter
635 : 120 : call xred2xcart(natom,rprimd,xcart (:,:,iimage),xred(:,:,iimage))
636 : 145 : call xred2xcart(natom,rprimd,xcart_prev(:,:,iimage),xred_prev(:,:,iimage))
637 : : end do
638 : :
639 : : !Determine if it is a restart or not
640 : : !If this is a calculation from scratch,generate random distribution of velocities
641 [ + + ]: 25 : irestart=1;if (itimimage==1) irestart=pimd_is_restart(mass,vel)
642 [ + + ]: 25 : if (irestart==0) then
643 [ + - - - : 4 : call pimd_initvel(idum,mass,natom,initemp,trotter,vel,pimd_param%constraint,pimd_param%wtatcon)
- - - - -
- - + ]
644 : : end if
645 : :
646 : : !Compute temperature at t
647 : 25 : temperature1=pimd_temperature(mass,vel)*rescale_temp
648 : :
649 : : !################## Images evolution #####################
650 : :
651 : : !Generate random numbers
652 [ + - ]: 25 : if (use_qtb==0) then
653 : 25 : call pimd_langevin_random(alea,pimd_param%irandom,idum,langev,mass,natom,trotter,zeroforce)
654 : : else
655 : 0 : call pimd_langevin_random_qtb(alea,langev,mass,natom,pimd_param%qtb_file_unit,trotter,zeroforce)
656 : : end if
657 : :
658 : : !Compute PIMD and Langevin contributions to forces
659 : 25 : call pimd_coord_transform(xcart,1,natom,pitransform,trotter)
660 : 25 : call pimd_force_transform(forces,1,natom,pitransform,trotter) !compute staging forces
661 : 25 : call pimd_forces(forces,natom,spring,pitransform,trotter,xcart)
662 : 25 : call pimd_langevin_forces(alea,forces,forces_pimd,friction,langev,mass,natom,trotter,vel)
663 : : call pimd_apply_constraint(pimd_param%constraint,constraint_output,forces_pimd,&
664 [ + - - - : 25 : & mass,natom,trotter,pimd_param%wtatcon,xcart)
- - - - -
- - + ]
665 : :
666 : : !Compute atomic positions at t+dt
667 [ + + ]: 25 : if (itimimage<=1) then
668 : :
669 : : ! === 1st time step: single Taylor algorithm
670 : : ! Predict positions
671 : : call pimd_predict_taylor(dtion,forces_pimd,mass,natom,trotter,&
672 : 4 : & vel,xcart,xcart_next)
673 : :
674 : : ! Compute new temperature
675 : 4 : temperature2=pimd_temperature(mass,vel)*rescale_temp
676 : :
677 : : else
678 : :
679 : : ! === Other time steps: Verlet algorithm + SC cycle
680 : : ! Predict positions
681 : 21 : call pimd_coord_transform(xcart_prev,1,natom,pitransform,trotter)
682 : : call pimd_predict_verlet(dtion,forces_pimd,mass,natom,trotter,&
683 : 21 : & xcart,xcart_next,xcart_prev)
684 : : ! Self-consistent loop
685 : 21 : temperature2=pimd_temperature(mass,vel)*rescale_temp
686 : 21 : temp2_prev=temperature2; tol=one
687 [ + + ]: 106 : do while (tol>tolerance)
688 : : ! Recompute a (better) estimation of the velocity at time step t
689 [ + + + + : 5702 : vel = (xcart_next - xcart_prev) / (two*dtion)
+ + ]
690 : 85 : temperature2=pimd_temperature(mass,vel)*rescale_temp
691 : : ! Reestimate the force
692 : : call pimd_langevin_forces(alea,forces,forces_pimd,friction,&
693 : 85 : & langev,mass,natom,trotter,vel)
694 : : call pimd_apply_constraint(pimd_param%constraint,constraint_output,forces_pimd,&
695 [ + - - - : 85 : & mass,natom,trotter,pimd_param%wtatcon,xcart)
- - - - -
- - + ]
696 : : ! Compute new positions
697 : : call pimd_predict_verlet(dtion,forces_pimd,mass,natom,trotter,&
698 : 85 : & xcart,xcart_next,xcart_prev)
699 : :
700 : : ! Compute variation of temperature (to check convergence of SC loop)
701 : 85 : tol=dabs(temperature2-temp2_prev)/dabs(temp2_prev)
702 : 85 : temp2_prev=temperature2
703 : :
704 : : end do ! End self-consistent loop
705 : :
706 : : end if ! itimimage==1
707 : :
708 : 25 : call pimd_coord_transform(xcart_next,-1,natom,pitransform,trotter)
709 : 25 : call pimd_coord_transform(xcart,-1,natom,pitransform,trotter)
710 : 25 : call pimd_coord_transform(xcart_prev,-1,natom,pitransform,trotter)
711 : :
712 : : !Compute contributions to energy
713 : 25 : call pimd_energies(eharm,eharm2,epot,etotal,forces_orig,natom,spring_prim,trotter,xcart)
714 : :
715 : : !Compute stress tensor at t
716 [ + - ]: 25 : if (use_qtb==0) then
717 : 25 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,thermtemp,thermtemp,trotter,vel,volume,xcart)
718 : : else
719 : 0 : call pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,temperature2,thermtemp,trotter,vel,volume,xcart)
720 : : end if
721 [ + + + + : 1000 : stress_pimd=-stress_pimd ! Translate pressure to stress
+ + ]
722 : :
723 : : !############# Final operations ############################
724 : :
725 : : !Print messages
726 [ + + ]: 25 : vel_cell=zero;prtstress=1;if (prtvolimg>=2) prtstress=0
727 [ - + ]: 25 : kt_=kt;if (use_qtb==1) kt_=temperature2*kb_HaK
728 : : call pimd_print(pimd_param%constraint,constraint_output,&
729 : : & eharm,eharm2,epot,forces_pimd,inertmass,irestart,&
730 : : & itimimage,kt_,natom,pimd_param%optcell,prtstress,prtvolimg,rprimd,&
731 : : & stress_pimd,temperature2,&
732 : 25 : & pimd_param%traj_unit,trotter,vel,vel_cell,xcart,xred)
733 : :
734 : : !If possible, estimate the (transformed) velocities at t+dt
735 : 25 : call pimd_predict_vel(dtion,itimimage,natom,trotter,pitransform,xcart,xcart_next,xcart_prev,vel_next)
736 : :
737 : : !Come back to reduced coordinates
738 [ + + ]: 145 : do iimage=1,trotter
739 : 145 : call xcart2xred(natom,rprimd,xcart_next(:,:,iimage),xred_next(:,:,iimage))
740 : : end do
741 : :
742 : : !Free memory
743 [ - + ]: 25 : ABI_FREE(xcart)
744 [ - + ]: 25 : ABI_FREE(xcart_prev)
745 [ - + ]: 25 : ABI_FREE(xcart_next)
746 [ - + ]: 25 : ABI_FREE(forces_orig)
747 [ - + ]: 25 : ABI_FREE(forces_pimd)
748 [ - + ]: 25 : ABI_FREE(inertmass)
749 [ - + ]: 25 : ABI_FREE(quantummass)
750 [ - + ]: 25 : ABI_FREE(mass)
751 [ - + ]: 25 : ABI_FREE(spring)
752 [ - + ]: 25 : ABI_FREE(alea)
753 [ - + ]: 25 : ABI_FREE(langev)
754 : :
755 : 25 : end subroutine pimd_langevin_nvt
756 : : !!***
757 : :
758 : : end module m_pimd_langevin
759 : : !!***
|