Line data Source code
1 : !!****m* ABINIT/m_pred_isothermal
2 : !! NAME
3 : !! m_pred_isothermal
4 : !!
5 : !! FUNCTION
6 : !! Ionmov predictors (13) Isothermal integrator
7 : !! This program is decribed in the following paper
8 : !! Explicit integrators for extended systems dynamics
9 : !! Glenn J Martyna et al.
10 : !! Mol. Phys., 1996, Vol. 87, pp. 1117-1157 [[cite:Martyna1996]]
11 : !!
12 : !! COPYRIGHT
13 : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, JCC, JYR, SE)
14 : !! This file is distributed under the terms of the
15 : !! GNU General Public License, see ~abinit/COPYING
16 : !! or http://www.gnu.org/copyleft/gpl.txt .
17 : !!
18 : !! SOURCE
19 :
20 : #if defined HAVE_CONFIG_H
21 : #include "config.h"
22 : #endif
23 :
24 : #include "abi_common.h"
25 :
26 : module m_pred_isothermal
27 :
28 : use defs_basis
29 : use m_errors
30 : use m_abicore
31 : use m_abimover
32 : use m_abihist
33 : use m_linalg_interfaces
34 :
35 : use m_numeric_tools, only : uniformrandom
36 : use m_geometry, only : mkrdim, xcart2xred, xred2xcart, metric
37 :
38 : implicit none
39 :
40 : private
41 : !!***
42 :
43 : public :: pred_isothermal
44 : !!***
45 :
46 : contains
47 : !!***
48 :
49 : !!****f* ABINIT/pred_isothermal
50 : !! NAME
51 : !! pred_isothermal
52 : !!
53 : !! FUNCTION
54 : !! Ionmov predictors (13) Isothermal integrator
55 : !!
56 : !! IONMOV 13:
57 : !! Reversible integrator of Martyna at al.
58 : !! The equation of motion of the ions in contact with a thermostat
59 : !! and a barostat are solved with the algorithm proposed by Martyna,
60 : !! Tuckermann Tobias and Klein, Mol. Phys., 1996, p. 1117. [[cite:Martyna1996]]
61 : !! Related parameters : the time step (dtion),
62 : !! the initial temperature mdtemp(1), the final temperature mdtemp(2),
63 : !! the number of thermostats (nnos), and the masses of thermostats (qmass).
64 : !! If optcell=1 or 2, the mass of the barostat (bmass) must be given in addition.
65 : !!
66 : !! There are three sub cases according to the value of optcell
67 : !! optcell=0: isothermal
68 : !! optcell=1: homogeneous cell fluctuations
69 : !! optcell=2: full cell fluctuation in addition to temperature control.
70 : !!
71 : !! INPUTS
72 : !! ab_mover <type(abimover)> : Datatype with all the information
73 : !! needed by the preditor
74 : !! itime : Index of the present iteration
75 : !! ntime : Maximal number of iterations
76 : !! zDEBUG : if true print some debugging information
77 : !!
78 : !! SIDE EFFECTS
79 : !! hist <type(abihist)> : History of positions,forces
80 : !! acell, rprimd, stresses
81 : !!
82 : !! SOURCE
83 :
84 9093 : subroutine pred_isothermal(ab_mover,hist,itime,mttk_vars,ntime,zDEBUG,iexit)
85 :
86 : !Arguments ------------------------------------
87 : !scalars
88 : type(abimover),intent(in) :: ab_mover
89 : type(abihist),intent(inout) :: hist
90 : type(mttk_type),intent(inout) :: mttk_vars
91 : integer,intent(in) :: itime
92 : integer,intent(in) :: ntime
93 : integer,intent(in) :: iexit
94 : logical,intent(in) :: zDEBUG
95 :
96 : !Local variables-------------------------------
97 : !scalars
98 : integer :: ii,kk,iatom,idim,idum=5,ierr
99 : integer,parameter :: lwork=8
100 : real(dp) :: ucvol,ucvol0,ucvol_next,mttk_aloc,mttk_aloc2,mttk_bloc,ekin
101 : real(dp) :: massvol=0
102 : real(dp),parameter :: esh2=one/six,esh4=esh2/20._dp,esh6=esh4/42._dp
103 : real(dp),parameter :: esh8=esh6/72._dp,nosetol=tol10,v2tol=tol8
104 : real(dp) :: etotal,rescale_vel,polysh,s1,s2,sigma2,v2gauss,vtest
105 : real(dp),save :: ktemp,vlogv
106 : character(len=5000) :: message
107 : !arrays
108 : real(dp),allocatable,save :: fcart_m(:,:),vel_nexthalf(:,:)
109 :
110 : real(dp) :: mttk_alc(3),mttk_alc2(3),mttk_blc(3),mttk_psh(3)
111 : real(dp) :: mttk_tv(3,3),mttk_vt(3,3),mttk_ubox(3,3)
112 : real(dp) :: mttk_uu(3),mttk_uv(3),mttk_veig(3)
113 : real(dp) :: acell(3),acell0(3),acell_next(3)
114 : real(dp) :: rprimd(3,3),rprimd0(3,3),rprim(3,3),rprimd_next(3,3),rprim_next(3,3)
115 : real(dp) :: gprimd(3,3)
116 : real(dp) :: gmet(3,3)
117 : real(dp) :: rmet(3,3)
118 18186 : real(dp) :: fcart(3,ab_mover%natom)
119 18186 : real(dp) :: xcart(3,ab_mover%natom),xcart_next(3,ab_mover%natom)
120 18186 : real(dp) :: xred(3,ab_mover%natom),xred_next(3,ab_mover%natom)
121 9093 : real(dp) :: vel(3,ab_mover%natom)
122 : real(dp) :: strten(6),work(lwork)
123 :
124 : !***************************************************************************
125 : !Beginning of executable session
126 : !***************************************************************************
127 :
128 9093 : if(iexit/=0)then
129 31 : ABI_SFREE(fcart_m)
130 31 : ABI_SFREE(vel_nexthalf)
131 : return
132 : end if
133 :
134 : !write(std_out,*) 'isothermal 01'
135 : !##########################################################
136 : !### 01. Debugging and Verbose
137 :
138 9062 : if(zDEBUG)then
139 0 : write(std_out,'(a,3a,41a,36a)') ch10,('-',kk=1,3),&
140 0 : & 'Debugging and Verbose for pred_isothermal',('-',kk=1,36)
141 0 : write(std_out,*) 'ionmov: ',13
142 0 : write(std_out,*) 'itime: ',itime
143 : end if
144 :
145 : !write(std_out,*) 'isothermal 01'
146 : !##########################################################
147 : !### 01. Allocate the vectors vin, vout and hessian matrix
148 : !### These arrays could be allocated from a previus
149 : !### dataset that exit before itime==ntime
150 :
151 9062 : if(itime==1)then
152 233 : ABI_SFREE(fcart_m)
153 233 : ABI_SFREE(vel_nexthalf)
154 : end if
155 :
156 9062 : if (.not.allocated(fcart_m)) then
157 699 : ABI_MALLOC(fcart_m,(3,ab_mover%natom))
158 : end if
159 9062 : if (.not.allocated(vel_nexthalf)) then
160 699 : ABI_MALLOC(vel_nexthalf,(3,ab_mover%natom))
161 : end if
162 :
163 : !write(std_out,*) 'isothermal 02'
164 : !##########################################################
165 : !### 02. Obtain the present values from the history
166 :
167 9062 : call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
168 :
169 35378022 : fcart(:,:)=hist%fcart(:,:,hist%ihist)
170 63434 : strten(:) =hist%strten(:,hist%ihist)
171 35378022 : vel(:,:) =hist%vel(:,:,hist%ihist)
172 9062 : etotal =hist%etot(hist%ihist)
173 :
174 36248 : do ii=1,3
175 117806 : rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
176 : end do
177 9062 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
178 :
179 9062 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
180 :
181 9062 : if(zDEBUG)then
182 0 : write (std_out,*) 'fcart:'
183 0 : do kk=1,ab_mover%natom
184 0 : write (std_out,*) fcart(:,kk)
185 : end do
186 0 : write (std_out,*) 'vel:'
187 0 : do kk=1,ab_mover%natom
188 0 : write (std_out,*) vel(:,kk)
189 : end do
190 0 : write (std_out,*) 'strten:'
191 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
192 0 : write (std_out,*) 'etotal:'
193 0 : write (std_out,*) etotal
194 : end if
195 :
196 : !Save initial values
197 9062 : acell0(:)=acell(:)
198 9062 : rprimd0(:,:)=rprimd(:,:)
199 9062 : ucvol0=ucvol
200 :
201 : !write(std_out,*) 'isothermal 03'
202 : !##########################################################
203 : !### 05. Seconde half velocity step
204 :
205 9062 : if (itime>1) then
206 :
207 : ! Next Half velocity step
208 35316 : do idim=1,3
209 25904088 : fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
210 : end do
211 34500525 : vel(:,:)=vel_nexthalf(:,:)+ab_mover%dtion/two*fcart_m(:,:)
212 :
213 8829 : if (ab_mover%optcell==0) then
214 : ! Update Thermostat variables and velocity
215 : call isotemp(ab_mover%amass,ab_mover%dtion,ekin,ab_mover%iatfix,&
216 7861 : & ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,vel)
217 968 : else if (ab_mover%optcell==1) then
218 : ! Update Thermostat variables and velocity
219 : call isopress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
220 : & ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,&
221 14 : & strten,ab_mover%strtarget,ucvol,vel,vlogv)
222 954 : else if (ab_mover%optcell==2) then
223 : ! Next half step for extended variables
224 : call isostress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
225 : & ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,&
226 954 : & ab_mover%qmass,strten,ab_mover%strtarget,ucvol,vel)
227 : end if
228 :
229 8829 : if(itime==2) massvol=ekin+etotal
230 :
231 8829 : if (ab_mover%optcell==2) then
232 : ! Evolution of cell and volume
233 954 : acell_next(:)=acell(:)
234 954 : ucvol_next=ucvol
235 : end if
236 :
237 8829 : call mkrdim(acell,rprim,rprimd)
238 8829 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
239 :
240 8829 : if(zDEBUG)then
241 0 : write(std_out,*) 'Second half velocity step'
242 0 : write(std_out,*) 'Cell parameters:'
243 0 : write(std_out,*) 'rprimd:'
244 0 : do kk=1,3
245 0 : write(std_out,*) rprimd(:,kk)
246 : end do
247 0 : write(std_out,*) 'rprim:'
248 0 : do kk=1,3
249 0 : write(std_out,*) rprim(:,kk)
250 : end do
251 0 : write(std_out,*) 'acell:'
252 0 : write(std_out,*) acell(:)
253 0 : write(std_out,*) 'Conserved energy:',(ekin+etotal)-massvol,ekin,etotal
254 0 : write(std_out,*) 'Volume of unitqry cell (ucvol):',ucvol
255 : end if
256 :
257 : end if ! if (itime>1)
258 :
259 : !write(std_out,*) 'isothermal 04'
260 : !##########################################################
261 : !### 03. Compute the next values
262 :
263 : !The temperature is linear between initial and final values
264 : !It is here converted from Kelvin to Hartree (kb_HaK)
265 9062 : ktemp=(ab_mover%mdtemp(1)+((ab_mover%mdtemp(2)-ab_mover%mdtemp(1))/dble(ntime-1))*(itime-1))*kb_HaK
266 :
267 9062 : if(zDEBUG)then
268 0 : write(std_out,*) 'Temperature in Kelvin (ktemp):',ktemp
269 0 : write(std_out,*) 'Initial temp (mdtemp(1)):',ab_mover%mdtemp(1)
270 0 : write(std_out,*) 'Final temp (mdtemp(2)):',ab_mover%mdtemp(2)
271 0 : write(std_out,*) 'Delay for atom permutation (delayperm)',ab_mover%delayperm
272 0 : write(std_out,*) 'dtion',ab_mover%dtion
273 0 : write(std_out,*) 'nnos:', ab_mover%nnos
274 0 : write(std_out,*) 'qmass', ab_mover%qmass(:)
275 0 : write(std_out,*) 'bmass',ab_mover%bmass
276 : end if
277 :
278 9062 : if(itime==1) then
279 962 : mttk_vars%glogs(:)=zero; mttk_vars%vlogs(:)=zero; mttk_vars%xlogs(:)=zero
280 3029 : mttk_vars%vboxg(:,:)=zero
281 233 : vlogv=zero
282 : ! v2gauss is twice the kinetic energy
283 233 : v2gauss=0.0_dp
284 219549 : do iatom=1,ab_mover%natom
285 877497 : do idim=1,3
286 877264 : v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
287 : end do
288 : end do
289 :
290 : ! If there is no kinetic energy
291 233 : if (v2gauss<=v2tol.and.itime==1) then
292 : ! Maxwell-Boltzman distribution
293 219549 : v2gauss=zero
294 219549 : vtest=zero
295 219549 : do iatom=1,ab_mover%natom
296 877497 : do idim=1,3
297 657948 : vel(idim,iatom)=sqrt(kb_HaK*ab_mover%mdtemp(1)/ab_mover%amass(iatom))*cos(two_pi*uniformrandom(idum))
298 877264 : vel(idim,iatom)=vel(idim,iatom)*sqrt(-2._dp*log(uniformrandom(idum)))
299 : end do
300 : end do
301 :
302 : ! Get rid of center-of-mass velocity
303 219549 : s1=sum(ab_mover%amass(:))
304 932 : do idim=1,3
305 658647 : s2=sum(ab_mover%amass(:)*vel(idim,:))
306 658880 : vel(idim,:)=vel(idim,:)-s2/s1
307 : end do
308 :
309 : ! Recompute v2gauss
310 219549 : do iatom=1,ab_mover%natom
311 877497 : do idim=1,3
312 657948 : v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
313 877264 : vtest=vtest+vel(idim,iatom)/(3._dp*ab_mover%natom)
314 : end do
315 : end do
316 :
317 : ! Now rescale the velocities to give the exact temperature
318 233 : rescale_vel=sqrt(3._dp*ab_mover%natom*kb_HaK*ab_mover%mdtemp(1)/v2gauss)
319 877497 : vel(:,:)=vel(:,:)*rescale_vel
320 :
321 : ! Recompute v2gauss with the rescaled velocities
322 : v2gauss=zero
323 219549 : do iatom=1,ab_mover%natom
324 877497 : do idim=1,3
325 877264 : v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
326 : end do
327 : end do
328 :
329 : ! Compute the variance and print
330 233 : sigma2=(v2gauss/(3._dp*ab_mover%natom)-ab_mover%amass(1)*vtest**2)/kb_HaK
331 :
332 233 : if (zDEBUG)then
333 : write(message, '(a)' )&
334 0 : & ' Rescaling or initializing velocities to initial temperature'
335 0 : call wrtout(std_out,message,'COLL')
336 : write(message, '(a,d12.5,a,D12.5)' )&
337 0 : & ' --- Scaling factor :',rescale_vel,' Asked T (K) ',ab_mover%mdtemp(1)
338 0 : call wrtout(std_out,message,'COLL')
339 : write(message, '(a,d12.5,a,D12.5)' )&
340 0 : & ' --- Effective temperature',v2gauss/(3*ab_mover%natom*kb_HaK),' From variance', sigma2
341 0 : call wrtout(std_out,message,'COLL')
342 : end if
343 :
344 : end if !(v2gauss<=v2tol.and.itime==1)
345 : end if !(itime==1)
346 :
347 : !XG070613 : Do not take away the following line , seems needed for the pathscale compiler
348 :
349 9062 : if (zDEBUG) write(std_out,*) 'vboxg',mttk_vars%vboxg(:,:)
350 :
351 :
352 : !write(std_out,*) 'isothermal 05'
353 : !##########################################################
354 : !### 03. First half velocity step
355 :
356 : !write(std_out,*) 'FIRST HALF VELOCITY STEP',ucvol
357 : !write(std_out,*) 'OPTCELL option selected:',ab_mover%optcell
358 : !write(std_out,*) 'RPRIMD'
359 : !do kk=1,3
360 : !write(std_out,*) rprimd(:,kk)
361 : !end do
362 : !write(std_out,*) 'RPRIM'
363 : !do kk=1,3
364 : !write(std_out,*) rprim(:,kk)
365 : !end do
366 : !write(std_out,*) 'ACELL'
367 : !write(std_out,*) acell(:)
368 :
369 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 : !%%% BEGIN sub case optcell=0 Isothermal Ensemble
371 : !%%%
372 9062 : if(ab_mover%optcell==0) then
373 : ! There is no evolution of cell
374 8068 : acell_next(:)=acell(:)
375 8068 : ucvol_next=ucvol
376 8068 : rprim_next(:,:)=rprim(:,:)
377 8068 : rprimd_next(:,:)=rprimd(:,:)
378 : ! Update Thermostat variables and scale velocitie
379 : call isotemp(ab_mover%amass,ab_mover%dtion,ekin,ab_mover%iatfix,&
380 8068 : & ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,vel)
381 :
382 : ! Half velocity step
383 32272 : do idim=1,3
384 25966768 : fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
385 : end do
386 34587396 : vel_nexthalf(:,:)=vel(:,:)+ab_mover%dtion/two*fcart_m(:,:)
387 : ! New positions
388 : ! Convert input xred (reduced coordinates) to xcart (cartesian)
389 8068 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
390 34587396 : xcart_next(:,:)=xcart(:,:)+vel_nexthalf(:,:)*ab_mover%dtion
391 : ! Convert back to xred (reduced coordinates)
392 8068 : call xcart2xred(ab_mover%natom,rprimd,xcart_next,xred_next)
393 : ! %%%
394 : ! %%% END sub case optcell=0 Isothermal Ensemble
395 : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396 :
397 : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 : ! %%% BEGIN sub case optcell=1 Isothermal-Isenthalpic
399 : ! %%% Ensemble (homogeneous cell deformation)
400 : ! %%%
401 994 : else if (ab_mover%optcell==1) then
402 : ! Only homogeneous evolution of cell
403 : ! Evolution of cell we keep rprim constant
404 16 : rprim_next(:,:)=rprim(:,:)
405 : ! Update Thermostat variables and velocity
406 : call isopress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
407 : & ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,&
408 16 : & strten,ab_mover%strtarget,ucvol,vel,vlogv)
409 :
410 : ! Half velocity step
411 64 : do idim=1,3
412 256 : fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
413 : end do
414 272 : vel_nexthalf(:,:)=vel(:,:)+ab_mover%dtion/two*fcart_m(:,:)
415 : ! New positions
416 16 : mttk_aloc=exp(ab_mover%dtion/two*vlogv)
417 16 : mttk_aloc2=(vlogv*ab_mover%dtion/two)**2
418 16 : polysh=(((esh8*mttk_aloc2+esh6)*mttk_aloc2+esh4)*mttk_aloc2+esh2)*mttk_aloc2+one
419 16 : mttk_bloc=mttk_aloc*polysh*ab_mover%dtion
420 : ! Convert input xred (reduced coordinates) to xcart (cartesian)
421 16 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
422 272 : xcart_next(:,:)=xcart(:,:)*mttk_aloc**2+vel_nexthalf(:,:)*mttk_bloc
423 : ! Update the volume and related quantities
424 64 : acell_next(:)=acell(:)*exp(ab_mover%dtion*vlogv)
425 : ! ucvol=ucvol*exp(ab_mover%dtion*vlogv)
426 16 : call mkrdim(acell_next,rprim,rprimd_next)
427 16 : call metric(gmet,gprimd,-1,rmet,rprimd_next,ucvol_next)
428 : ! Convert back to xred (reduced coordinates)
429 16 : call xcart2xred(ab_mover%natom,rprimd_next,xcart_next,xred_next)
430 : ! Computation of the forces for the new positions
431 : ! Compute DFT forces (big loop)
432 :
433 : ! COMMENTED
434 : ! This should be in mover.F90
435 :
436 : ! ! If metric has changed since the initialization, update the Ylm's
437 : ! if (ab_mover%optcell/=0.and.psps%useylm==1.and.itime>1)then
438 : ! option=0;if (ab_mover%iscf>0) option=1
439 : ! call initylmg(gprimd,kg,ab_mover%kptns,ab_mover%mkmem,mpi_enreg,psps%mpsang,ab_mover%mpw,ab_mover%nband,ab_mover%nkpt,&
440 : ! & npwarr,ab_mover%nsppol,option,rprimd_next,ylm,ylmgr)
441 : ! end if
442 :
443 :
444 : ! %%%
445 : ! %%% END sub case optcell=1 Isothermal-Isenthalpic
446 : ! %%% Ensemble (homogeneous cell deformation)
447 : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 :
449 : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
450 : ! %%% BEGIN sub case optcell=2 Isothermal-Isenthalpic
451 : ! %%% Ensemble (full cell deformation)
452 : ! %%%
453 978 : else if (ab_mover%optcell==2) then
454 978 : acell_next=acell
455 : ! Fisrt half step for extended variables
456 : call isostress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
457 : & ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,&
458 978 : & ab_mover%qmass,strten,ab_mover%strtarget,ucvol,vel)
459 : ! Half velocity step
460 3912 : do idim=1,3
461 595944 : fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
462 : end do
463 790354 : vel_nexthalf(:,:)=vel(:,:)+ab_mover%dtion/two*fcart_m(:,:)
464 : ! Convert input xred (reduced coordinates) to xcart (cartesian)
465 978 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
466 : ! New positions
467 12714 : mttk_vt(:,:)=mttk_vars%vboxg(:,:)
468 978 : call dsyev('V','U',3,mttk_vt,3,mttk_veig,work,lwork,ierr)
469 12714 : mttk_tv(:,:)=transpose(mttk_vt)
470 3912 : mttk_alc(:)=exp(ab_mover%dtion/two*mttk_veig(:))
471 3912 : mttk_alc2(:)=(mttk_veig(:)*ab_mover%dtion/two)**2
472 3912 : mttk_psh(:)=(((esh8*mttk_alc2(:)+esh6)*mttk_alc2(:)+esh4)*mttk_alc2(:)+esh2)*mttk_alc2(:)+one
473 3912 : mttk_blc(:)=mttk_alc(:)*mttk_psh(:)*ab_mover%dtion
474 : ! Update the positions
475 198322 : do iatom=1,ab_mover%natom
476 2565472 : mttk_uu(:)=matmul(mttk_tv,xcart(:,iatom))
477 2565472 : mttk_uv(:)=matmul(mttk_tv,vel_nexthalf(:,iatom))
478 789376 : mttk_uu(:)=mttk_uu(:)*mttk_alc(:)**2+mttk_uv(:)*mttk_blc(:)
479 3158482 : xcart_next(:,iatom)=matmul(mttk_vt,mttk_uu)
480 : end do
481 : ! Update the box (rprimd and rprim)
482 39120 : mttk_ubox(:,:)=matmul(mttk_tv,rprimd)
483 3912 : do idim=1,3
484 12714 : mttk_ubox(:,idim)=mttk_ubox(:,idim)*mttk_alc(:)**2
485 : end do
486 39120 : rprimd_next(:,:)=matmul(mttk_vt,mttk_ubox)
487 3912 : do idim=1,3
488 12714 : rprim_next(idim,:)=rprimd_next(idim,:)/acell(:)
489 : end do
490 : ! Update the volume
491 978 : call metric(gmet,gprimd,-1,rmet,rprimd_next,ucvol)
492 : ! Convert back to xred (reduced coordinates)
493 978 : call xcart2xred(ab_mover%natom,rprimd_next,xcart_next,xred_next)
494 : ! Computation of the forces for the new positions
495 :
496 : ! COMMENTED
497 : ! This should be in mover.F90
498 :
499 : ! ! If metric has changed since the initialization, update the Ylm's
500 : ! if (ab_mover%optcell/=0.and.psps%useylm==1.and.itime>1)then
501 : ! option=0;if (ab_mover%iscf>0) option=1
502 : ! call initylmg(gprimd,kg,ab_mover%kptns,ab_mover%mkmem,mpi_enreg,psps%mpsang,ab_mover%mpw,ab_mover%nband,ab_mover%nkpt,&
503 : ! & npwarr,ab_mover%nsppol,option,rprimd_next,ylm,ylmgr)
504 : ! end if
505 :
506 : ! %%%
507 : ! %%% END sub case optcell=2 Isothermal-Isenthalpic
508 : ! %%% Ensemble (full cell deformation)
509 : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 : else
511 : write(message, '(a,i12,a,a)' )&
512 0 : & ' Disallowed value for optcell=',ab_mover%optcell,ch10,&
513 0 : & ' Allowed values with ionmov==13 : 0 to 2.'
514 0 : ABI_BUG(message)
515 : end if
516 :
517 : !write(std_out,*) 'OLD PARAMETERS'
518 : !write(std_out,*) 'RPRIMD'
519 : !do kk=1,3
520 : !write(std_out,*) rprimd(:,kk)
521 : !end do
522 : !write(std_out,*) 'RPRIM'
523 : !do kk=1,3
524 : !write(std_out,*) rprim(:,kk)
525 : !end do
526 : !write(std_out,*) 'ACELL'
527 : !write(std_out,*) acell(:)
528 :
529 : !write(std_out,*) 'NEXT PARAMETERS'
530 : !write(std_out,*) 'RPRIMD'
531 : !do kk=1,3
532 : !write(std_out,*) rprimd_next(:,kk)
533 : !end do
534 : !write(std_out,*) 'RPRIM'
535 : !do kk=1,3
536 : !write(std_out,*) rprim_next(:,kk)
537 : !end do
538 : !write(std_out,*) 'ACELL'
539 : !write(std_out,*) acell_next(:)
540 :
541 :
542 : !Those are the values store into the history
543 9062 : rprim=rprim_next
544 9062 : rprimd=rprimd_next
545 35378022 : xred=xred_next
546 35378022 : xcart=xcart_next
547 9062 : acell=acell_next
548 :
549 : !write(std_out,*) 'isothermal 06'
550 : !##########################################################
551 : !### 06. Update the history with the prediction
552 :
553 : !Increase indexes
554 9062 : hist%ihist = abihist_findIndex(hist,+1)
555 :
556 : !Fill the history with the variables
557 : !xred, acell, rprimd, vel
558 9062 : call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
559 35378022 : hist%vel(:,:,hist%ihist)=vel(:,:)
560 9062 : hist%time(hist%ihist)=real(itime,kind=dp)*ab_mover%dtion
561 :
562 9062 : if(zDEBUG)then
563 0 : write (std_out,*) 'fcart:'
564 0 : do kk=1,ab_mover%natom
565 0 : write (std_out,*) fcart(:,kk)
566 : end do
567 0 : write (std_out,*) 'vel:'
568 0 : do kk=1,ab_mover%natom
569 0 : write (std_out,*) vel(:,kk)
570 : end do
571 0 : write (std_out,*) 'strten:'
572 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
573 0 : write (std_out,*) 'etotal:'
574 0 : write (std_out,*) etotal
575 : end if
576 :
577 : end subroutine pred_isothermal
578 : !!***
579 :
580 : !!****f* ABINIT/isotemp
581 : !! NAME
582 : !! isotemp
583 : !!
584 : !! FUNCTION
585 : !! performs one half step on isotemp parameters according to Martyna et al.
586 : !!
587 : !! INPUTS
588 : !! amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
589 : !! dtion=
590 : !! isotemp_data
591 : !! ktemp
592 : !! vel
593 : !!
594 : !! OUTPUT
595 : !! Only updates variables
596 : !!
597 : !! SIDE EFFECTS
598 : !! isotemp_data: updates the thermostat parameters
599 : !! vel=update the velocities
600 : !!
601 : !! SOURCE
602 :
603 15929 : subroutine isotemp(amass,dtion,ekin,iatfix,ktemp,mttk_vars,natom,nnos,qmass,vel)
604 :
605 : !Arguments ------------------------------------
606 : !scalars
607 : integer,intent(in) :: natom
608 : integer,intent(in) :: nnos
609 : real(dp),intent(in) :: dtion,ktemp
610 : real(dp),intent(out) :: ekin
611 : type(mttk_type) :: mttk_vars
612 : !arrays
613 : real(dp),intent(in) :: amass(natom)
614 : real(dp),intent(inout) :: vel(3,natom)
615 : real(dp),intent(in) :: qmass(:)
616 : integer,intent(in) :: iatfix(:,:)
617 :
618 : !Local variables ------------------------------
619 : !scalars
620 : integer :: iatom,idir,inos
621 : real(dp) :: alocal,gnkt,nfree,scale
622 : !character(len=500) :: message
623 : !arrays
624 15929 : real(dp),allocatable :: glogs(:),vlogs(:),xlogs(:)
625 :
626 : !***************************************************************************
627 : !Beginning of executable session
628 : !***************************************************************************
629 :
630 47787 : ABI_MALLOC(glogs,(nnos))
631 31858 : ABI_MALLOC(vlogs,(nnos))
632 31858 : ABI_MALLOC(xlogs,(nnos))
633 31888 : glogs(:)=mttk_vars%glogs(:)
634 31888 : vlogs(:)=mttk_vars%vlogs(:)
635 31888 : xlogs(:)=mttk_vars%xlogs(:)
636 15929 : scale=one
637 : !Compute the ionic kinetic energy
638 15929 : nfree=zero
639 15929 : ekin=zero
640 17089109 : do iatom=1,natom
641 68308649 : do idir=1,3
642 : ! Warning : the fixing of atomis is implemented in reduced
643 : ! coordinates, so that this expression is wrong
644 68292720 : if (iatfix(idir,iatom) == 0) then
645 51219540 : ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
646 : ! Counts the degrees of freedom
647 51219540 : nfree=nfree+one
648 : end if
649 : end do
650 : end do
651 15929 : gnkt=nfree*ktemp
652 : !Update the forces
653 15929 : glogs(1)=(two*ekin-gnkt)/qmass(1)
654 15929 : vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
655 15959 : do inos=1,nnos-1
656 30 : alocal=exp(-dtion/eight*vlogs(nnos+1-inos))
657 : vlogs(nnos-inos)=vlogs(nnos-inos)*alocal*alocal+&
658 15959 : & dtion/four*glogs(nnos-inos)*alocal
659 : end do
660 : !Update the particle velocities
661 15929 : alocal=exp(-dtion/two*vlogs(1))
662 15929 : scale=scale*alocal
663 : !Update the forces
664 15929 : glogs(1)=(scale*scale*two*ekin-gnkt)/qmass(1)
665 : !Update the thermostat positions
666 31888 : do inos=1,nnos
667 31888 : xlogs(inos)=xlogs(inos)+vlogs(inos)*dtion/two
668 : end do
669 : !Update the thermostat velocities
670 15959 : do inos=1,nnos-1
671 30 : alocal=exp(-dtion/eight*vlogs(inos+1))
672 30 : vlogs(inos)=vlogs(inos)*alocal*alocal+dtion/four*glogs(inos)*alocal
673 15959 : glogs(inos+1)=(qmass(inos)*vlogs(inos)*vlogs(inos)-ktemp)/qmass(inos+1)
674 : end do
675 15929 : vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
676 68308649 : vel(:,:)=vel(:,:)*scale
677 : !Compute the ionic kinetic energy
678 15929 : ekin=zero
679 17089109 : do iatom=1,natom
680 68308649 : do idir=1,3
681 : ! Warning : the fixing of atomis is implemented in reduced
682 : ! coordinates, so that this expression is wrong
683 68292720 : if (iatfix(idir,iatom) == 0) then
684 51219540 : ekin=ekin+half*amass(iatom)*vel(idir,iatom)**2
685 : end if
686 : end do
687 : end do
688 : !Compute the thermostat kinetic energy and add it to the ionic one
689 15929 : ekin=ekin+half*qmass(1)*vlogs(1)**2+xlogs(1)*nfree*ktemp
690 15959 : do inos=2,nnos
691 15959 : ekin=ekin+half*qmass(inos)*vlogs(inos)**2+xlogs(inos)*ktemp
692 : end do
693 31888 : mttk_vars%glogs(:)=glogs(:)
694 31888 : mttk_vars%vlogs(:)=vlogs(:)
695 31888 : mttk_vars%xlogs(:)=xlogs(:)
696 15929 : ABI_FREE(glogs)
697 15929 : ABI_FREE(vlogs)
698 15929 : ABI_FREE(xlogs)
699 : !DEBUG
700 : !write(std_out,*)'ekin added',half*qmass(1)*vlogs(1)**2,xlogs(1)*(nfree)*ktemp
701 : !ENDEBUG
702 :
703 15929 : end subroutine isotemp
704 : !!***
705 :
706 : !----------------------------------------------------------------------
707 :
708 : !!****f* ABINIT/isopress
709 : !! NAME
710 : !! isopress
711 : !!
712 : !! FUNCTION
713 : !! performs one half step on isopress parameters according to Martyna et al.
714 : !!
715 : !! INPUTS
716 : !! amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
717 : !! dtion= ionic time step
718 : !! isotemp_data
719 : !! ktemp
720 : !! press= current pressure of the system
721 : !! prtarget= target pressure
722 : !! ucvol= unit cell volume
723 : !! vel= current velocity
724 : !!
725 : !! OUTPUT
726 : !! Only updates variables
727 : !!
728 : !! SIDE EFFECTS
729 : !! isotemp_data: updates the thermostat parameters (saved variables: bouh !)
730 : !! vel=update the velocities
731 : !!
732 : !! SOURCE
733 :
734 30 : subroutine isopress(amass,bmass,dtion,ekin,iatfix,ktemp,mttk_vars,natom,nnos,qmass,&
735 30 : & strten,strtarget,ucvol,vel,vlogv)
736 :
737 : !Arguments ------------------------------------
738 : !scalars
739 : integer,intent(in) :: nnos,natom
740 : real(dp),intent(in) :: dtion,ktemp,ucvol,bmass
741 : real(dp),intent(inout) :: vlogv
742 : real(dp),intent(out) :: ekin
743 : type(mttk_type) :: mttk_vars
744 : !arrays
745 : real(dp),intent(in) :: amass(natom),strtarget(6),strten(6)
746 : real(dp),intent(inout) :: vel(3,natom)
747 : real(dp),intent(in) :: qmass(:)
748 : integer,intent(in) :: iatfix(:,:)
749 :
750 : !Local variables ------------------------------
751 : !scalars
752 : integer :: iatom,idir,inos
753 : real(dp) :: alocal,glogv,gn1kt,gnkt,nfree,odnf,press,prtarget,scale
754 : logical :: DEBUG=.FALSE.
755 : !character(len=500) :: message
756 : !arrays
757 30 : real(dp),allocatable :: glogs(:),vlogs(:),xlogs(:)
758 :
759 : !***************************************************************************
760 : !Beginning of executable session
761 : !***************************************************************************
762 :
763 30 : if(DEBUG) then
764 0 : write(std_out,*) ch10,'***',ch10
765 0 : write(std_out,*)' isopress : enter '
766 0 : write(std_out,*)' strtarget=',strtarget
767 0 : write(std_out,*)' bmass=',bmass
768 0 : write(std_out,*)' dtion=',dtion
769 0 : write(std_out,*)' ktemp=',ktemp
770 0 : write(std_out,*)' natom=',natom
771 0 : write(std_out,*)' nnos=',nnos
772 0 : write(std_out,*)' strten=',strten
773 0 : write(std_out,*)' ucvol=',ucvol
774 : end if
775 :
776 90 : ABI_MALLOC(glogs,(nnos))
777 60 : ABI_MALLOC(vlogs,(nnos))
778 60 : ABI_MALLOC(xlogs,(nnos))
779 120 : glogs(:)=mttk_vars%glogs(:)
780 120 : vlogs(:)=mttk_vars%vlogs(:)
781 120 : xlogs(:)=mttk_vars%xlogs(:)
782 30 : glogv =mttk_vars%glogv
783 30 : scale=one
784 : !Compute the ionic kinetic energy
785 30 : nfree=zero
786 30 : ekin=zero
787 150 : do iatom=1,natom
788 510 : do idir=1,3
789 : ! Warning : the fixing of atomis is implemented in reduced
790 : ! coordinates, so that this expression is wrong
791 480 : if (iatfix(idir,iatom) == 0) then
792 360 : ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
793 : ! Counts the degrees of freedom
794 360 : nfree=nfree+one
795 : end if
796 : end do
797 : end do
798 30 : prtarget=-(strtarget(1)+strtarget(2)+strtarget(3))/three
799 30 : press=-(strten(1)+strten(2)+strten(3))/three
800 30 : gnkt=nfree*ktemp
801 30 : gn1kt=(nfree+one)*ktemp
802 30 : odnf=one+three/nfree
803 : !Update the forces
804 30 : glogs(1)=(two*ekin+bmass*vlogv*vlogv-gn1kt)/qmass(1)
805 30 : glogv=(odnf*two*ekin+three*(press-prtarget)*ucvol)/bmass
806 : !Update thermostat velocity
807 30 : vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
808 90 : do inos=1,nnos-1
809 60 : alocal=exp(-dtion/eight*vlogs(nnos+1-inos))
810 : vlogs(nnos-inos)=vlogs(nnos-inos)*alocal*alocal+&
811 90 : & dtion/four*glogs(nnos-inos)*alocal
812 : end do
813 : !Update dLog(V)/dt
814 30 : alocal=exp(-dtion/eight*vlogs(1))
815 30 : vlogv=vlogv*alocal**2+dtion/four*glogv*alocal
816 : !Update the particle velocities
817 30 : alocal=exp(-dtion/two*(vlogs(1)+odnf*vlogv))
818 30 : scale=scale*alocal
819 30 : ekin=ekin*alocal**2
820 30 : glogv=(odnf*two*ekin+three*(press-prtarget)*ucvol)/bmass
821 : !Update the thermostat positions
822 120 : do inos=1,nnos
823 120 : xlogs(inos)=xlogs(inos)+vlogs(inos)*dtion/two
824 : end do
825 : !Update dLog(V)/dt
826 30 : alocal=exp(-dtion/eight*vlogs(1))
827 30 : vlogv=vlogv*alocal**2+dtion/four*glogv*alocal
828 : !Update the forces
829 30 : glogs(1)=(two*ekin+bmass*vlogv*vlogv-gn1kt)/qmass(1)
830 : !Update the thermostat velocities
831 90 : do inos=1,nnos-1
832 60 : alocal=exp(-dtion/eight*vlogs(inos+1))
833 60 : vlogs(inos)=vlogs(inos)*alocal*alocal+dtion/four*glogs(inos)*alocal
834 90 : glogs(inos+1)=(qmass(inos)*vlogs(inos)*vlogs(inos)-ktemp)/qmass(inos+1)
835 : end do
836 30 : vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
837 510 : vel(:,:)=vel(:,:)*scale
838 : !Compute the ionic kinetic energy
839 30 : ekin=zero
840 150 : do iatom=1,natom
841 510 : do idir=1,3
842 : ! Warning : the fixing of atomis is implemented in reduced
843 : ! coordinates, so that this expression is wrong
844 480 : if (iatfix(idir,iatom) == 0) then
845 360 : ekin=ekin+half*amass(iatom)*vel(idir,iatom)**2
846 : end if
847 : end do
848 : end do
849 : !Compute the thermostat kinetic energy and add it to the ionic one
850 : !First thermostat
851 30 : ekin=ekin+half*qmass(1)*vlogs(1)**2+xlogs(1)*(nfree+one)*ktemp
852 : !Other thermostats
853 90 : do inos=2,nnos
854 90 : ekin=ekin+half*qmass(inos)*vlogs(inos)**2+xlogs(inos)*ktemp
855 : end do
856 : !Barostat
857 30 : ekin=ekin+half*bmass*vlogv**2+prtarget*ucvol
858 30 : ABI_FREE(glogs)
859 30 : ABI_FREE(vlogs)
860 30 : ABI_FREE(xlogs)
861 :
862 : !DEBUG
863 : !write(std_out,*) 'EKIN',ekin
864 : !write(std_out,*) 'VLOGV',vlogv
865 : !write(std_out,*)'ekin added T',half*qmass(:)*vlogs(:)**2,xlogs(:)*(nfree)*ktemp
866 : !write(std_out,*)'ekin added P',half*bmass*vlogv**2,prtarget*ucvol
867 : !write(std_out,*)'ekin last',ekin
868 : !ENDDEBUG
869 30 : end subroutine isopress
870 : !!***
871 :
872 : !----------------------------------------------------------------------
873 :
874 : !!****f* ABINIT/isostress
875 : !! NAME
876 : !! isostress
877 : !!
878 : !! FUNCTION
879 : !! performs one half step on isostress parameters according to Martyna et al.
880 : !!
881 : !! INPUTS
882 : !! amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
883 : !! dtion= ionic time step
884 : !! isotemp_data
885 : !! ktemp
886 : !! press= current pressure of the system
887 : !! prtarget= target pressure
888 : !! ucvol= unit cell volume
889 : !! vel= current velocity
890 : !!
891 : !! OUTPUT
892 : !! Only updates variables
893 : !!
894 : !! SIDE EFFECTS
895 : !! isotemp_data: updates the thermostat parameters (saved variables: bouh !)
896 : !! vel=update the velocities
897 : !!
898 : !! SOURCE
899 :
900 1932 : subroutine isostress(amass,bmass,dtion,ekin,iatfix,ktemp,mttk_vars,natom,nnos,&
901 1932 : & qmass,strten,strtarget,ucvol,vel)
902 :
903 : use m_linalg_interfaces
904 :
905 : !Arguments ------------------------------------
906 : !scalars
907 : integer,intent(in) :: natom,nnos
908 : real(dp),intent(in) :: dtion,ktemp,ucvol,bmass
909 : real(dp),intent(out) :: ekin
910 : type(mttk_type) :: mttk_vars
911 : !arrays
912 : real(dp),intent(in) :: amass(natom),strtarget(6),strten(6),qmass(:)
913 : real(dp),intent(inout) :: vel(3,natom)
914 : integer, intent(in) :: iatfix(:,:)
915 :
916 : !Local variables ------------------------------
917 : !scalars
918 : integer,parameter :: lwork=8
919 : integer :: iatom,idir,info,inos,jdir
920 : real(dp) :: akinb,alocal,gn1kt,gnd2kt,nfree,odnf,trvg !,gnkt,scale
921 : logical :: DEBUG=.FALSE.
922 : !character(len=500) :: message
923 : !arrays
924 : real(dp) :: akin(3,3),expdiag(3),gboxg(3,3),identity(3,3),press(3,3)
925 : real(dp) :: prtarget(3,3),tvtemp(3,3),uv(3),vboxg(3,3),veig(3),vtemp(3,3)
926 : real(dp) :: work(lwork)
927 1932 : real(dp),allocatable :: glogs(:),vlogs(:),xlogs(:)
928 :
929 : !***************************************************************************
930 : !Beginning of executable session
931 : !***************************************************************************
932 :
933 1932 : if(DEBUG) then
934 0 : write(std_out,*) ch10,'***',ch10
935 0 : write(std_out,*)' isostress : enter '
936 0 : write(std_out,*)' strtarget=',strtarget
937 0 : write(std_out,*)' bmass=',bmass
938 0 : write(std_out,*)' dtion=',dtion
939 0 : write(std_out,*)' ktemp=',ktemp
940 0 : write(std_out,*)' natom=',natom
941 0 : write(std_out,*)' nnos=',nnos
942 0 : write(std_out,*)' strten=',strten
943 0 : write(std_out,*)' ucvol=',ucvol
944 : end if
945 :
946 5796 : ABI_MALLOC(glogs,(nnos))
947 3864 : ABI_MALLOC(vlogs,(nnos))
948 3864 : ABI_MALLOC(xlogs,(nnos))
949 3924 : glogs(:)=mttk_vars%glogs(:)
950 3924 : vlogs(:)=mttk_vars%vlogs(:)
951 3924 : xlogs(:)=mttk_vars%xlogs(:)
952 25116 : vboxg(:,:)=mttk_vars%vboxg(:,:)
953 1932 : identity(:,:)=zero
954 7728 : do idir=1,3
955 7728 : identity(idir,idir)=one
956 : end do
957 :
958 : !write(std_out,*) 'isostress 02'
959 : !##########################################################
960 : !### 03. Compute the ionic kinetic energy
961 :
962 1932 : nfree=zero
963 1932 : ekin=zero
964 393796 : do iatom=1,natom
965 1569388 : do idir=1,3
966 : ! Warning : the fixing of atomis is implemented in reduced
967 : ! coordinates, so that this exprtargetion is wrong
968 1567456 : if (iatfix(idir,iatom) == 0) then
969 1175592 : ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
970 : ! Counts the degrees of freedom
971 1175592 : nfree=nfree+one
972 : end if
973 : end do
974 : end do
975 :
976 1932 : gn1kt=(nfree+one)*ktemp
977 1932 : gnd2kt=(nfree+9)*ktemp
978 1932 : odnf=one+three/nfree
979 1932 : akin(:,:)=zero
980 393796 : do iatom=1,natom
981 1569388 : do idir=1,3
982 5094232 : do jdir=1,3
983 : ! Warning : the fixing of atomis is implemented in reduced
984 : ! coordinates, so that this expression is wrong
985 4702368 : akin(idir,jdir)=akin(idir,jdir)+0.5d0*amass(iatom)*vel(idir,iatom)*vel(jdir,iatom)
986 : end do
987 : end do
988 : end do
989 : akinb=zero
990 7728 : do idir=1,3
991 25116 : do jdir=1,3
992 23184 : akinb=akinb+0.5d0*bmass*vboxg(idir,jdir)**2
993 : end do
994 : end do
995 : !Compute the pressure: from Voigt to tensor notation+kinetic energy
996 7728 : do idir=1,3
997 5796 : press(idir,idir)=-strten(idir)
998 7728 : prtarget(idir,idir)=-strtarget(idir)
999 : end do
1000 1932 : press(3,2)=-strten(4); press(1,3)=-strten(5); press(2,1)=-strten(6)
1001 1932 : prtarget(3,2)=-strtarget(4); prtarget(1,3)=-strtarget(5); prtarget(2,1)=-strtarget(6)
1002 1932 : press(2,3)=press(3,2); press(3,1)=press(1,3); press(1,2)=press(2,1)
1003 1932 : prtarget(2,3)=prtarget(3,2); prtarget(3,1)=prtarget(1,3); prtarget(1,2)=prtarget(2,1)
1004 : !Update the forces
1005 1932 : glogs(1)=(two*ekin+two*akinb-gnd2kt)/qmass(1)
1006 25116 : gboxg(:,:)=(two*ekin/nfree*identity(:,:)+two*akin(:,:)+(press(:,:)-prtarget(:,:))*ucvol)/bmass
1007 : !Update thermostat velocity
1008 1932 : if (nnos > 0) vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
1009 1992 : do inos=1,nnos-1
1010 60 : alocal=exp(-dtion/eight*vlogs(nnos+1-inos))
1011 : vlogs(nnos-inos)=vlogs(nnos-inos)*alocal*alocal+&
1012 1992 : & dtion/four*glogs(nnos-inos)*alocal
1013 : end do
1014 : !Update box velocity
1015 1932 : alocal=exp(-dtion/eight*vlogs(1))
1016 :
1017 1932 : if(DEBUG) then
1018 0 : write(std_out,*)' gboxg(:,:)=',gboxg(:,:)
1019 0 : write(std_out,*)' vboxg(:,:)=',vboxg(:,:)
1020 0 : write(std_out,*)' alocal=',alocal
1021 : end if
1022 :
1023 25116 : vboxg(:,:)=vboxg(:,:)*alocal**2+dtion/four*gboxg(:,:)*alocal
1024 : !Update the thermostat positions
1025 3924 : do inos=1,nnos
1026 3924 : xlogs(inos)=xlogs(inos)+vlogs(inos)*dtion/two
1027 : end do
1028 : !Update the particle velocities
1029 1932 : trvg=(vboxg(1,1)+vboxg(2,2)+vboxg(3,3))/nfree
1030 25116 : vtemp(:,:)=vboxg(:,:)+(trvg+vlogs(1))*identity(:,:)
1031 1932 : call dsyev('V','U',3,vtemp,3,veig,work,lwork,info)
1032 : !On exit, we have vtemp=U such that tU vtemp U = veig
1033 25116 : tvtemp(:,:)=transpose(vtemp)
1034 :
1035 1932 : if(DEBUG) then
1036 0 : write(std_out,*)' vboxg(:,:)=',vboxg(:,:)
1037 0 : write(std_out,*)' vtemp(:,:)=',vtemp(:,:)
1038 0 : write(std_out,*)' veig(:)=',veig(:)
1039 : end if
1040 :
1041 1932 : expdiag(1)=exp(-veig(1)*dtion/two)
1042 1932 : expdiag(2)=exp(-veig(2)*dtion/two)
1043 1932 : expdiag(3)=exp(-veig(3)*dtion/two)
1044 : !if(DEBUG) then
1045 : ! write(std_out,*)' isostress : expdiag(:)=',expdiag(:) ! Do not remove this line : seems to be needed for g95 compilo
1046 : !end if
1047 393796 : do iatom=1,natom
1048 5094232 : uv(:)=matmul(tvtemp,vel(:,iatom))
1049 1567456 : uv(:)=uv(:)*expdiag(:)
1050 6271756 : vel(:,iatom)=matmul(vtemp,uv)
1051 : end do
1052 : !Compute the ionic kinetic energy
1053 1932 : nfree=zero
1054 1932 : ekin=zero
1055 393796 : do iatom=1,natom
1056 1569388 : do idir=1,3
1057 : ! Warning : the fixing of atomis is implemented in reduced
1058 : ! coordinates, so that this expression is wrong
1059 1567456 : if (iatfix(idir,iatom) == 0) then
1060 1175592 : ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
1061 1175592 : if(DEBUG) then
1062 0 : write(std_out,*)'kin',iatom,ekin,vel(idir,iatom)
1063 : end if
1064 : ! Counts the degrees of freedom
1065 1175592 : nfree=nfree+one
1066 : end if
1067 : end do
1068 : end do
1069 1932 : gn1kt=(nfree+one)*ktemp
1070 1932 : gnd2kt=(nfree+9)*ktemp
1071 1932 : odnf=one+three/nfree
1072 1932 : akin(:,:)=zero
1073 393796 : do iatom=1,natom
1074 1569388 : do idir=1,3
1075 5094232 : do jdir=1,3
1076 : ! Warning : the fixing of atomis is implemented in reduced
1077 : ! coordinates, so that this expression is wrong
1078 4702368 : akin(idir,jdir)=akin(idir,jdir)+0.5d0*amass(iatom)*vel(idir,iatom)*vel(jdir,iatom)
1079 : end do
1080 : end do
1081 : end do
1082 25116 : gboxg(:,:)=(two*ekin/nfree*identity(:,:)+two*akin(:,:)+(press(:,:)-prtarget(:,:))*ucvol)/bmass
1083 : !Update box velocity
1084 : alocal=exp(-dtion/eight*vlogs(1))
1085 25116 : vboxg(:,:)=vboxg(:,:)*alocal**2+dtion/four*gboxg(:,:)*alocal
1086 : !Compute the box kinetic energy
1087 : akinb=zero
1088 7728 : do idir=1,3
1089 25116 : do jdir=1,3
1090 23184 : akinb=akinb+0.5d0*bmass*vboxg(idir,jdir)**2
1091 : end do
1092 : end do
1093 1932 : glogs(1)=(two*ekin+two*akinb-gnd2kt)/qmass(1)
1094 : !Update the thermostat velocities
1095 1992 : do inos=1,nnos-1
1096 60 : alocal=exp(-dtion/eight*vlogs(inos+1))
1097 60 : vlogs(inos)=vlogs(inos)*alocal*alocal+dtion/four*glogs(inos)*alocal
1098 1992 : glogs(inos+1)=(qmass(inos)*vlogs(inos)*vlogs(inos)-ktemp)/qmass(inos+1)
1099 : end do
1100 1932 : if (nnos > 0) vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
1101 : !Compute the ionic kinetic energy
1102 1932 : ekin=zero
1103 393796 : do iatom=1,natom
1104 1569388 : do idir=1,3
1105 : ! Warning : the fixing of atomis is implemented in reduced
1106 : ! coordinates, so that this expression is wrong
1107 1567456 : if (iatfix(idir,iatom) == 0) then
1108 1175592 : ekin=ekin+half*amass(iatom)*vel(idir,iatom)**2
1109 : end if
1110 : end do
1111 : end do
1112 : !Compute the thermostat kinetic energy and add it to the ionic one
1113 : !First thermostat
1114 1932 : ekin=ekin+half*qmass(1)*vlogs(1)**2+xlogs(1)*(nfree+nine)*ktemp
1115 : !Other thermostats
1116 1992 : do inos=2,nnos
1117 1992 : ekin=ekin+half*qmass(inos)*vlogs(inos)**2+xlogs(inos)*ktemp
1118 : end do
1119 : !Barostat kinetic energy
1120 : akinb=zero
1121 7728 : do idir=1,3
1122 25116 : do jdir=1,3
1123 23184 : akinb=akinb+0.5d0*bmass*vboxg(idir,jdir)**2
1124 : end do
1125 : end do
1126 : !ekin is the invariant minus the potential energy
1127 1932 : ekin=ekin+akinb+prtarget(1,1)*ucvol
1128 :
1129 25116 : mttk_vars%vboxg(:,:)=vboxg(:,:)
1130 3924 : mttk_vars%glogs(:)=glogs(:)
1131 3924 : mttk_vars%vlogs(:)=vlogs(:)
1132 3924 : mttk_vars%xlogs(:)=xlogs(:)
1133 1932 : ABI_FREE(glogs)
1134 1932 : ABI_FREE(vlogs)
1135 1932 : ABI_FREE(xlogs)
1136 :
1137 1932 : if(DEBUG) then
1138 : ! write(std_out,*)'ekin added T',half*qmass(:)*vlogs(:)**2,xlogs(:)*(nfree)*ktemp
1139 : ! write(std_out,*)'ekin added P',akinb,prtarget*ucvol
1140 : ! write(std_out,*)'ekin last',ekin
1141 0 : write(std_out,*) ch10,' exiting from isostress',ch10
1142 : end if
1143 :
1144 1932 : end subroutine isostress
1145 : !!***
1146 :
1147 : !----------------------------------------------------------------------
1148 :
1149 : end module m_pred_isothermal
1150 : !!***
|