Line data Source code
1 : !!****m* ABINIT/m_pimd
2 : !! NAME
3 : !! m_pimd
4 : !!
5 : !! FUNCTION
6 : !! This module provides several routines and datatypes for the
7 : !! Path-Integral Molecular Dynamics (PIMD) implementation.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2010-2026 ABINIT group (GG,MT)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : MODULE m_pimd
24 :
25 : use defs_basis
26 : use m_abicore
27 : use m_dtset
28 : use m_errors
29 : use m_io_tools
30 : use m_random_zbq
31 :
32 : use m_numeric_tools, only : uniformrandom
33 : use m_matrix, only : matr3inv
34 : use m_geometry, only : mkradim
35 :
36 : implicit none
37 :
38 : private
39 :
40 : !public procedures
41 : public :: pimd_init
42 : public :: pimd_nullify
43 : public :: pimd_destroy
44 : public :: pimd_init_qtb
45 : public :: pimd_skip_qtb
46 : public :: pimd_print
47 : public :: pimd_is_restart
48 : public :: pimd_temperature
49 : public :: pimd_initvel
50 : public :: pimd_initvel_from_scratch
51 : public :: pimd_langevin_random
52 : public :: pimd_langevin_random_qtb
53 : public :: pimd_langevin_random_bar
54 : public :: pimd_langevin_random_init
55 : public :: pimd_energies
56 : public :: pimd_forces
57 : public :: pimd_langevin_forces
58 : public :: pimd_nosehoover_forces
59 : public :: pimd_stresses
60 : public :: pimd_diff_stress
61 : public :: pimd_predict_taylor
62 : public :: pimd_predict_verlet
63 : public :: pimd_predict_vel
64 : public :: pimd_predict_velcell
65 : public :: pimd_nosehoover_propagate
66 : public :: pimd_coord_transform
67 : public :: pimd_force_transform
68 : public :: pimd_apply_constraint
69 : public :: pimd_mass_spring
70 : !!***
71 :
72 : !!****t* m_pimd/pimd_type
73 : !! NAME
74 : !! pimd_type
75 : !!
76 : !! FUNCTION
77 : !! Datatype with the variables required to perform PIMD
78 : !!
79 : !! NOTES
80 : !!
81 : !! SOURCE
82 :
83 : type,public :: pimd_type
84 : ! Scalars
85 : integer :: adpimd
86 : integer :: constraint
87 : integer :: irandom
88 : integer :: nnos
89 : integer :: ntypat
90 : integer :: optcell
91 : integer :: pitransform
92 : integer :: traj_unit
93 : integer :: use_qtb
94 : integer :: qtb_file_unit
95 : real(dp) :: adpimd_gamma
96 : real(dp) :: friction
97 : real(dp) :: bmass
98 : real(dp) :: dtion
99 : real(dp) :: frictionbar
100 : ! Arrays
101 : integer ,pointer :: typat(:) ! This pointer is associated with dtset%typat
102 : real(dp),pointer :: amu(:) ! This pointer is associated with dtset%%amu_orig(:,1)
103 : real(dp),pointer :: mdtemp(:) ! This pointer is associated with dtset%mdtemp
104 : real(dp),pointer :: pimass(:) ! This pointer is associated with dtset%pimass
105 : real(dp),pointer :: qmass(:) ! This pointer is associated with dtset%qmass
106 : real(dp),pointer :: strtarget(:) ! This pointer is associated with dtset%strtarget
107 : real(dp),pointer :: wtatcon(:,:,:) ! This pointer is associated with dtset%wtatcon
108 : real(dp),allocatable :: zeta_prev(:,:,:,:)
109 : real(dp),allocatable :: zeta (:,:,:,:)
110 : real(dp),allocatable :: zeta_next(:,:,:,:)
111 : real(dp),allocatable :: dzeta (:,:,:,:)
112 : end type pimd_type
113 : !!***
114 :
115 : CONTAINS !===========================================================
116 : !!***
117 :
118 : !!****f* m_pimd/pimd_init
119 : !! NAME
120 : !! pimd_init
121 : !!
122 : !! FUNCTION
123 : !! Initialize a datastructure of type pimd_type.
124 : !! Open file(s) related to this datastructure.
125 : !!
126 : !! INPUTS
127 : !! dtset <type(dataset_type)>=all input variables in current dataset
128 : !! is_master= TRUE if I am the master process (proc 0)
129 : !!
130 : !! OUTPUT
131 : !!
132 : !! SIDE EFFECTS
133 : !! pimd_param=datastructure of type pimd_type.
134 : !! several parameters for Path-Integral MD.
135 : !!
136 : !! SOURCE
137 :
138 3985 : subroutine pimd_init(dtset,pimd_param,is_master,force_imgmov)
139 :
140 : !Arguments ------------------------------------
141 : !scalars
142 : logical,intent(in) :: is_master
143 : type(dataset_type),target,intent(in) :: dtset
144 : type(pimd_type),intent(inout) :: pimd_param
145 : integer,optional,intent(in) :: force_imgmov
146 : !Local variables-------------------------------
147 : !scalars
148 : integer :: ierr,imgmov
149 : character(len=200) :: msg
150 :
151 : !************************************************************************
152 3985 : if(present(force_imgmov)) then
153 10 : imgmov=force_imgmov
154 : else
155 3975 : imgmov=dtset%imgmov
156 : end if
157 :
158 3985 : call pimd_nullify(pimd_param)
159 :
160 3985 : if((imgmov==9).or.(imgmov==10).or.(imgmov==13))then
161 17 : pimd_param%adpimd = dtset%adpimd
162 17 : pimd_param%constraint = dtset%pimd_constraint
163 17 : pimd_param%irandom = dtset%irandom
164 17 : pimd_param%nnos = dtset%nnos
165 17 : pimd_param%ntypat = dtset%ntypat
166 17 : pimd_param%optcell = dtset%optcell
167 17 : pimd_param%pitransform = dtset%pitransform
168 17 : pimd_param%adpimd_gamma= dtset%adpimd_gamma
169 17 : pimd_param%friction = dtset%friction
170 17 : pimd_param%bmass = dtset%bmass
171 17 : pimd_param%dtion = dtset%dtion
172 17 : pimd_param%frictionbar = dtset%frictionbar
173 17 : pimd_param%mdtemp =>dtset%mdtemp
174 17 : pimd_param%pimass =>dtset%pimass
175 17 : pimd_param%strtarget =>dtset%strtarget
176 17 : pimd_param%amu =>dtset%amu_orig(:,1)
177 17 : pimd_param%qmass =>dtset%qmass
178 17 : pimd_param%typat =>dtset%typat
179 17 : pimd_param%wtatcon =>dtset%wtatcon
180 17 : if(imgmov==10)then
181 0 : pimd_param%use_qtb=1
182 0 : if(is_master)then
183 0 : call pimd_init_qtb(dtset,pimd_param%qtb_file_unit)
184 : end if
185 : end if
186 17 : if(imgmov==13)then
187 15 : ABI_MALLOC(pimd_param%zeta_prev,(3,dtset%natom,dtset%nimage,dtset%nnos))
188 12 : ABI_MALLOC(pimd_param%zeta ,(3,dtset%natom,dtset%nimage,dtset%nnos))
189 12 : ABI_MALLOC(pimd_param%zeta_next,(3,dtset%natom,dtset%nimage,dtset%nnos))
190 12 : ABI_MALLOC(pimd_param%dzeta ,(3,dtset%natom,dtset%nimage,dtset%nnos))
191 828 : pimd_param%zeta_prev=zero
192 828 : pimd_param%zeta =zero
193 828 : pimd_param%zeta_next=zero
194 828 : pimd_param%dzeta =zero
195 : end if
196 17 : if(dtset%useria==37)then
197 0 : ierr=open_file('pimd_traj.dat',msg,newunit=pimd_param%traj_unit,form='unformatted')
198 0 : if (ierr/=0) then
199 0 : ABI_ERROR(msg)
200 : end if
201 : end if
202 : end if
203 :
204 3985 : end subroutine pimd_init
205 : !!***
206 :
207 : !----------------------------------------------------------------------
208 :
209 : !!****f* m_pimd/pimd_nullify
210 : !! NAME
211 : !! pimd_nullify
212 : !!
213 : !! FUNCTION
214 : !! Nullify the content of a datastructure of type pimd_type.
215 : !!
216 : !! INPUTS
217 : !!
218 : !! OUTPUT
219 : !!
220 : !! SIDE EFFECTS
221 : !! pimd_param=datastructure of type pimd_type.
222 : !! several parameters for Path-Integral MD.
223 : !!
224 : !! SOURCE
225 :
226 7960 : subroutine pimd_nullify(pimd_param)
227 :
228 : !Arguments ------------------------------------
229 : !scalars
230 : type(pimd_type),intent(inout) :: pimd_param
231 :
232 : !************************************************************************
233 :
234 7960 : pimd_param%adpimd = 0
235 7960 : pimd_param%constraint = 0
236 7960 : pimd_param%irandom = -1
237 7960 : pimd_param%nnos = -1
238 7960 : pimd_param%ntypat = -1
239 7960 : pimd_param%optcell = -1
240 7960 : pimd_param%pitransform = -1
241 7960 : pimd_param%qtb_file_unit= -1
242 7960 : pimd_param%traj_unit = -1
243 7960 : pimd_param%use_qtb = 0
244 7960 : pimd_param%adpimd_gamma = one
245 7960 : pimd_param%friction = zero
246 7960 : pimd_param%bmass = zero
247 7960 : pimd_param%dtion = zero
248 7960 : pimd_param%frictionbar = zero
249 7960 : nullify(pimd_param%mdtemp)
250 7960 : nullify(pimd_param%pimass)
251 7960 : nullify(pimd_param%strtarget)
252 7960 : nullify(pimd_param%amu)
253 7960 : nullify(pimd_param%qmass)
254 7960 : nullify(pimd_param%typat)
255 7960 : nullify(pimd_param%wtatcon)
256 :
257 7960 : end subroutine pimd_nullify
258 : !!***
259 :
260 : !----------------------------------------------------------------------
261 :
262 : !!****f* m_pimd/pimd_destroy
263 : !! NAME
264 : !! pimd_destroy
265 : !!
266 : !! FUNCTION
267 : !! Destroy the content of a datastructure of type pimd_type.
268 : !! Close open file(s) related to this datastructure.
269 : !!
270 : !! INPUTS
271 : !!
272 : !! OUTPUT
273 : !!
274 : !! SIDE EFFECTS
275 : !! pimd_param=datastructure of type pimd_type.
276 : !! several parameters for PIMD.
277 : !!
278 : !! SOURCE
279 :
280 3975 : subroutine pimd_destroy(pimd_param)
281 :
282 : !Arguments ------------------------------------
283 : !scalars
284 : type(pimd_type),intent(inout) :: pimd_param
285 : !arrays
286 : !Local variables-------------------------------
287 : !scalars
288 : integer :: ierr
289 : character(len=100) :: msg
290 : !arrays
291 :
292 : !************************************************************************
293 :
294 3975 : ABI_SFREE(pimd_param%zeta_prev)
295 3975 : ABI_SFREE(pimd_param%zeta)
296 3975 : ABI_SFREE(pimd_param%zeta_next)
297 3975 : ABI_SFREE(pimd_param%dzeta)
298 :
299 3975 : if (pimd_param%qtb_file_unit>0) then
300 0 : if (is_open(pimd_param%qtb_file_unit)) then
301 0 : ierr=close_unit(pimd_param%qtb_file_unit,msg)
302 : end if
303 : end if
304 :
305 3975 : if (pimd_param%traj_unit>0) then
306 0 : if (is_open(pimd_param%traj_unit)) then
307 0 : ierr=close_unit(pimd_param%traj_unit,msg)
308 : end if
309 : end if
310 :
311 3975 : call pimd_nullify(pimd_param)
312 :
313 3975 : end subroutine pimd_destroy
314 : !!***
315 :
316 : !----------------------------------------------------------------------
317 :
318 : !!****f* m_pimd/pimd_init_qtb
319 : !! NAME
320 : !! pimd_init_qtb
321 : !!
322 : !! FUNCTION
323 : !! Only relevant for PIMD + Quantum Thermal Bath (QTB);
324 : !! Initialize reading of PIQTB random force file.
325 : !! This routine should be called only by master proc.
326 : !!
327 : !! INPUTS
328 : !! dtset <type(dataset_type)>=all input variables in current dataset
329 : !!
330 : !! OUTPUT
331 : !! qtb_file_unit=if a PIQTB_force file exists, return its file unit.
332 : !!
333 : !! SOURCE
334 :
335 0 : subroutine pimd_init_qtb(dtset,qtb_file_unit)
336 :
337 : !Arguments ------------------------------------
338 : !scalars
339 : integer,intent(out) :: qtb_file_unit
340 : type(dataset_type),target,intent(in) :: dtset
341 : !Local variables-------------------------------
342 : !scalars
343 : integer :: ierr,ndof_qtb,ntimimage_qtb,nimage_qtb
344 : real(dp) :: dtion_qtb,mdtemp_qtb
345 : character(len=200) :: msg
346 :
347 : !************************************************************************
348 :
349 : !Try to open PIQTB random force file
350 : ierr=open_file('piqtb_force',msg,newunit=qtb_file_unit,&
351 0 : & form='unformatted',status='old')
352 :
353 : !Read first line of the file
354 0 : read(qtb_file_unit) dtion_qtb,ntimimage_qtb,mdtemp_qtb,nimage_qtb,ndof_qtb
355 :
356 : !Check consistency of the read parameters with ABINIT input file
357 0 : if (abs(dtion_qtb-dtset%dtion)>tol6) then
358 0 : msg='dtion read from piqtb_force file different from dtion in input file!'
359 0 : ABI_ERROR(msg)
360 : end if
361 0 : if (abs(mdtemp_qtb-dtset%mdtemp(2))>tol6) then
362 0 : msg='mdtemp read from piqtb_force file different from mdtemp(2) in input file!'
363 0 : ABI_ERROR(msg)
364 : end if
365 0 : if (ntimimage_qtb<dtset%ntimimage) then
366 0 : msg='ntimimage read from piqtb_force file smaller than ntimimage in input file!'
367 0 : ABI_ERROR(msg)
368 : end if
369 0 : if (nimage_qtb/=dtset%nimage) then
370 0 : msg='nimage read from piqtb_force file different from nimage in input file!'
371 0 : ABI_ERROR(msg)
372 : end if
373 0 : if (ndof_qtb/=3*dtset%natom*dtset%nimage) then
374 0 : msg='Nb of degrees of freedom read from piqtb_force not consistent with input file!'
375 0 : ABI_ERROR(msg)
376 : end if
377 :
378 0 : end subroutine pimd_init_qtb
379 : !!***
380 :
381 : !----------------------------------------------------------------------
382 :
383 : !!****f* m_pimd/pimd_skip_qtb
384 : !! NAME
385 : !! pimd_skip_qtb
386 : !!
387 : !! FUNCTION
388 : !! Only relevant in case of PI-QTB:
389 : !! Skip a line in a QTB random force file
390 : !!
391 : !! INPUTS
392 : !! pimd_param=datastructure of type pimd_type.
393 : !! several parameters for Path-Integral MD.
394 : !!
395 : !! OUTPUT
396 : !!
397 : !! SOURCE
398 :
399 0 : subroutine pimd_skip_qtb(pimd_param)
400 :
401 : !Arguments ------------------------------------
402 : !scalars
403 : type(pimd_type),intent(in) :: pimd_param
404 : !arrays
405 : !Local variables-------------------------------
406 : !scalars
407 : character(len=500) :: msg
408 : !arrays
409 :
410 : !************************************************************************
411 :
412 0 : if (pimd_param%use_qtb==0) return
413 :
414 0 : if (pimd_param%qtb_file_unit<0) then
415 0 : msg='QTB forces file unit should be positive!'
416 0 : ABI_BUG(msg)
417 : end if
418 :
419 : !Skip one line QTB random forces file
420 0 : read(pimd_param%qtb_file_unit)
421 :
422 : end subroutine pimd_skip_qtb
423 : !!***
424 :
425 : !----------------------------------------------------------------------
426 :
427 : !!****f* m_pimd/pimd_is_restart
428 : !! NAME
429 : !! pimd_is_restart
430 : !!
431 : !! FUNCTION
432 : !! Determine whether this is a PIMD restart or not:
433 : !! test on value of velocities and corresponding temperature
434 : !!
435 : !! INPUTS
436 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
437 : !! vel(3,natom,nimage)=velocities for each image of the cell
438 : !!
439 : !! OUTPUT
440 : !! pimd_is_restart=1 if temperature is not zero
441 : !!
442 : !! SIDE EFFECTS
443 : !!
444 : !! SOURCE
445 :
446 8 : function pimd_is_restart(mass,vel,vel_cell)
447 :
448 : !Arguments ------------------------------------
449 : !scalars
450 : integer :: pimd_is_restart
451 : !arrays
452 : real(dp),intent(in) :: mass(:,:),vel(:,:,:)
453 : real(dp),intent(in),optional :: vel_cell(:,:)
454 : !Local variables-------------------------------
455 : !scalars
456 : real(dp),parameter :: zero_temp=tol7
457 : !arrays
458 :
459 : !************************************************************************
460 :
461 8 : pimd_is_restart=0
462 8 : if (pimd_temperature(mass,vel)>zero_temp) pimd_is_restart=1
463 8 : if (present(vel_cell)) then
464 13 : if (maxval(vel_cell)>zero_temp) pimd_is_restart=pimd_is_restart+10
465 : end if
466 :
467 8 : end function pimd_is_restart
468 : !!***
469 :
470 : !----------------------------------------------------------------------
471 :
472 : !!****f* m_pimd/pimd_temperature
473 : !! NAME
474 : !! pimd_temperature
475 : !!
476 : !! FUNCTION
477 : !! Compute temperature from velocities and masses
478 : !!
479 : !! INPUTS
480 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
481 : !! vel(3,natom,nimage)=velocities for each image of the cell
482 : !!
483 : !! OUTPUT
484 : !! pimd_temperature=temperature (from all images of the cell)
485 : !!
486 : !! SIDE EFFECTS
487 : !!
488 : !! SOURCE
489 :
490 355 : function pimd_temperature(mass,vel)
491 :
492 : !Arguments ------------------------------------
493 : !scalars
494 : real(dp) :: pimd_temperature
495 : !arrays
496 : real(dp),intent(in) :: mass(:,:),vel(:,:,:)
497 : !Local variables-------------------------------
498 : !scalars
499 : integer :: iatom,iimage,imass,natom,natom_mass,ndir,nimage,nmass
500 : real(dp) :: v2
501 : character(len=500) :: msg
502 : !arrays
503 :
504 : !************************************************************************
505 :
506 355 : ndir=size(vel,1);natom=size(vel,2);nimage=size(vel,3)
507 355 : natom_mass=size(mass,1);nmass=size(mass,2)
508 355 : if (ndir/=3.or.natom<=0.or.nimage<=0) then
509 0 : msg='Wrong sizes for vel array !'
510 0 : ABI_BUG(msg)
511 : end if
512 355 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=nimage)) then
513 0 : msg='Wrong dimensions for array mass !'
514 0 : ABI_BUG(msg)
515 : end if
516 :
517 355 : v2=zero
518 2019 : do iimage = 1, nimage
519 1664 : imass = min(nmass, iimage)
520 6315 : do iatom = 1, natom
521 18848 : v2 = v2 + sum(vel(:, iatom, iimage)**2) * mass(iatom, imass)
522 : end do
523 : end do
524 355 : pimd_temperature=v2/(dble(3*natom*nimage)*kb_HaK)
525 :
526 355 : end function pimd_temperature
527 : !!***
528 :
529 : !----------------------------------------------------------------------
530 :
531 : !!****f* m_pimd/pimd_print
532 : !! NAME
533 : !! pimd_print
534 : !!
535 : !! FUNCTION
536 : !! Print out results related to PIMD (for given time step)
537 : !!
538 : !! INPUTS
539 : !! constraint=type of constraint eventually applied (on a reaction coordinate)
540 : !! constraint_output(2)=several (real) data to be output when a constraint has been applied
541 : !! eharm=harmonic energy
542 : !! eharm_virial=harmonic energy from virial
543 : !! epot=potential energy
544 : !! forces(3,natom,trotter)=forces on atoms in each cell
545 : !! inertmass(natom)=inertial masses of atoms
546 : !! irestart=1 if this is a restart
547 : !! itimimage=index of time step
548 : !! kt=Thermal energy K_b.T
549 : !! natom=number of atoms
550 : !! optcell=option for cell evolution
551 : !! prtstress=flag for stress tensor printing
552 : !! prtvolimg=printing volume
553 : !! rprim(3,3)=dimensionless real space primitive translations
554 : !! stress(3,3,3)=stress tensor (first dimension corresponds to 3 different estimators)
555 : !! temperature= temperature at present time step
556 : !! traj_unit=flag activating printing of the trajectory in an external file\
557 : !! if >0, indicates the unit number of the trajectory file
558 : !! trotter=Trotter number
559 : !! vel(3,natom,trotter)=velocities of atoms in in each cell
560 : !! vel_cell(3,3)= velocities of cell parameters (time derivative of rprimd)
561 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in in each cell
562 : !! xred(3,natom,trotter)=reduced coordinates of atoms in in each cell
563 : !! [print_forces]= optional argument; if TRUE print all forces on atoms (default=FALSE)
564 : !!
565 : !! OUTPUT
566 : !! -- only printing --
567 : !!
568 : !! SIDE EFFECTS
569 : !!
570 : !! SOURCE
571 :
572 45 : subroutine pimd_print(constraint,constraint_output,eharm,eharm_virial,epot,&
573 45 : & forces,inertmass,irestart,itimimage,kt,natom,optcell,prtstress,&
574 : & prtvolimg,rprimd,stress,temperature,traj_unit,&
575 45 : & trotter,vel,vel_cell,xcart,xred, &
576 : & print_forces) ! optional argument
577 :
578 : !Arguments ------------------------------------
579 : !scalars
580 : integer,intent(in) :: constraint,irestart,itimimage,natom,optcell
581 : integer,intent(in) :: prtstress,prtvolimg,traj_unit,trotter
582 : logical,optional,intent(in) :: print_forces
583 : real(dp),intent(in) :: eharm,eharm_virial,epot,kt,temperature
584 : !arrays
585 : real(dp),intent(in) :: constraint_output(2)
586 : real(dp),intent(in) :: forces(3,natom,trotter),inertmass(natom)
587 : real(dp),intent(in) :: rprimd(3,3),stress(3,3,3),vel(3,natom,trotter),vel_cell(3,3)
588 : real(dp),intent(in) :: xcart(3,natom,trotter),xred(3,natom,trotter)
589 : !Local variables-------------------------------
590 : !scalars
591 : integer :: iatom,ii,iimage
592 : real(dp) :: mtot
593 : character(len=500) :: msg
594 : !arrays
595 : real(dp) :: acell(3),cdm_cart(3),cdm_red(3),forcetot(3),rprim(3,3)
596 45 : real(dp),allocatable :: centroid(:,:),qudeloc(:)
597 :
598 : !************************************************************************
599 :
600 : !Temperature
601 45 : if(itimimage==1)then
602 8 : msg=ch10
603 8 : if(mod(irestart,10)==0.and.trotter>1) then
604 6 : write(msg,'(2a)') ch10,' This is a PIMD calculation from scratch'
605 2 : else if (mod(irestart,10)==1) then
606 0 : write(msg,'(2a)') ch10,' This is a RESTART calculation'
607 : end if
608 8 : call wrtout(ab_out,msg,'COLL')
609 8 : call wrtout(std_out,msg,'COLL')
610 : ! write(msg,'(a,f12.5,a)') &
611 : !& ' In the initial configuration, the temperature is ',temperature1,' K'
612 : ! call wrtout(ab_out,msg,'COLL')
613 : ! call wrtout(std_out,msg,'COLL')
614 : end if
615 45 : if (trotter>1) then
616 35 : write(msg,'(2a,i5,a,f12.5,a)') ch10,&
617 70 : & ' At PIMD time step ',itimimage,', the temperature is',temperature,' K'
618 : else
619 10 : write(msg,'(2a,i5,a,f12.5,a)') ch10,&
620 20 : & ' At time step ',itimimage,', the temperature is',temperature,' K'
621 : end if
622 45 : call wrtout(ab_out,msg,'COLL')
623 45 : call wrtout(std_out,msg,'COLL')
624 :
625 : !Energies
626 45 : if (trotter>1) then
627 35 : write(msg,'(4a,f18.9,a,a,a,f18.9,a,a)') ch10,&
628 35 : & ' Energy:',ch10, &
629 35 : & ' Internal energy (PRIMITIVE estimator) =',onehalf*dble(natom*trotter)*kt-eharm+epot ,' Ha',ch10, &
630 70 : & ' Internal energy (VIRIAL estimator) =',onehalf*dble(natom)*kt+eharm_virial+epot,' Ha',ch10
631 : else
632 10 : write(msg,'(2a,f18.9,a)') ch10,&
633 20 : & ' Internal energy =',onehalf*dble(natom)*temperature*kb_HaK+epot ,' Ha'
634 : end if
635 45 : call wrtout(ab_out,msg,'COLL')
636 45 : call wrtout(std_out,msg,'COLL')
637 :
638 : !Forces
639 45 : if (present(print_forces)) then
640 0 : if (print_forces) then
641 0 : write(msg,'(2a)') ch10,' Forces on atoms:'
642 0 : call wrtout(std_out,msg,'COLL')
643 0 : call wrtout(ab_out,msg,'COLL')
644 0 : do iimage=1,trotter
645 0 : select case(iimage)
646 : case(1)
647 0 : write(msg,'(a)') ' fcart'
648 : case(2,3,4,5,6,7,8,9)
649 0 : write(msg,'(a,i1,a)') ' fcart_',iimage,'img'
650 : case(10:99)
651 0 : write(msg,'(a,i2,a)') ' fcart_',iimage,'img'
652 : case default
653 0 : write(msg,'(a,i3,a)') ' fcart_',iimage,'img'
654 : end select
655 0 : call wrtout(std_out,msg,'COLL')
656 0 : call wrtout(ab_out,msg,'COLL')
657 0 : do iatom=1,natom
658 0 : write(msg,'(3f18.10)') forces(1:3,iatom,iimage)
659 0 : call wrtout(std_out,msg,'COLL')
660 0 : call wrtout(ab_out,msg,'COLL')
661 : end do
662 : end do
663 : end if
664 : end if
665 :
666 : !Stress tensor and pressure
667 45 : write(msg,'(2a,3(2a,3f18.9))') ch10,&
668 45 : & ' Stress tensor from PRIMITIVE estimator (Ha/Bohr^3):',ch10, &
669 45 : & ' ',stress(1,1,1),stress(1,1,2),stress(1,1,3),ch10, &
670 45 : & ' ',stress(1,2,1),stress(1,2,2),stress(1,2,3),ch10, &
671 90 : & ' ',stress(1,3,1),stress(1,3,2),stress(1,3,3)
672 45 : if (prtstress==1) then
673 40 : call wrtout(ab_out,msg,'COLL')
674 : end if
675 45 : call wrtout(std_out,msg,'COLL')
676 45 : write(msg,'(a,f18.9,a)') ' Pressure (primitive estimator) =', &
677 90 : & -third*(stress(1,1,1)+stress(1,2,2)+stress(1,3,3))*HaBohr3_GPa,' GPa'
678 45 : call wrtout(ab_out,msg,'COLL')
679 45 : call wrtout(std_out,msg,'COLL')
680 :
681 : !Data related to constraint eventually applied
682 45 : if (constraint/=0) then
683 5 : if (constraint==1) write(msg,'(2a)') ch10,' Blue Moon Ensemble method is activated:'
684 5 : call wrtout(ab_out,msg,'COLL')
685 5 : call wrtout(std_out,msg,'COLL')
686 : write(msg,'(a,f18.10,2a,f18.10)') &
687 5 : & ' - Reaction coordinate =',constraint_output(1),ch10,&
688 10 : & ' - Instantaneous force on the reaction coord. =',constraint_output(2)
689 5 : call wrtout(ab_out,msg,'COLL')
690 5 : call wrtout(std_out,msg,'COLL')
691 : end if
692 :
693 : !Total force
694 45 : if (prtvolimg<=1) then
695 40 : forcetot=zero
696 230 : do iimage=1,trotter
697 650 : do iatom=1,natom
698 1870 : do ii=1,3
699 1680 : forcetot(ii)=forcetot(ii)+forces(ii,iatom,iimage)
700 : end do
701 : end do
702 : end do
703 40 : write(msg,'(2a,3f18.10)') ch10,' Total force=',forcetot(1:3)
704 40 : call wrtout(std_out,msg,'COLL')
705 : end if
706 :
707 : !position of mass center
708 45 : if (prtvolimg<=1) then
709 40 : mtot=zero;cdm_cart=zero;cdm_red=zero
710 230 : do iimage=1,trotter
711 650 : do iatom=1,natom
712 1680 : cdm_cart(:)=cdm_cart(:)+inertmass(iatom)*xcart(:,iatom,iimage)
713 1680 : cdm_red (:)=cdm_red (:)+inertmass(iatom)*xred (:,iatom,iimage)
714 610 : mtot=mtot+inertmass(iatom)
715 : end do
716 : end do
717 160 : cdm_cart=cdm_cart/mtot
718 160 : cdm_red =cdm_red /mtot
719 40 : write(msg,'(3a,3x,3f18.10,3a,3x,3f18.10)') ch10,&
720 40 : & ' Center of mass, in cartes. coordinates :',ch10,cdm_cart(:),ch10,&
721 80 : & ' Center of mass, in reduced coordinates :',ch10,cdm_red(:)
722 40 : call wrtout(std_out,msg,'COLL')
723 40 : call wrtout(ab_out,msg,'COLL')
724 : end if
725 :
726 : !Positions
727 45 : write(msg,'(2a)') ch10,' Atomic positions:'
728 45 : call wrtout(std_out,msg,'COLL')
729 45 : call wrtout(ab_out,msg,'COLL')
730 260 : do iimage=1,trotter
731 45 : select case(iimage)
732 : case(1)
733 45 : write(msg,'(a)') ' xred'
734 : case(2,3,4,5,6,7,8,9)
735 170 : write(msg,'(a,i1,a)') ' xred_',iimage,'img'
736 : case(10:99)
737 0 : write(msg,'(a,i2,a)') ' xred_',iimage,'img'
738 : case default
739 215 : write(msg,'(a,i3,a)') ' xred_',iimage,'img'
740 : end select
741 215 : call wrtout(std_out,msg,'COLL')
742 215 : call wrtout(ab_out,msg,'COLL')
743 215 : if (traj_unit>0) then
744 0 : call wrtout(traj_unit,msg,'COLL')
745 : end if
746 830 : do iatom=1,natom
747 570 : write(msg,'(3f18.10)') xred(1:3,iatom,iimage)
748 570 : call wrtout(std_out,msg,'COLL')
749 570 : call wrtout(ab_out,msg,'COLL')
750 785 : if (traj_unit>0) then
751 0 : call wrtout(traj_unit,msg,'COLL')
752 : end if
753 : end do
754 : end do
755 :
756 : !Velocities
757 45 : write(msg,'(2a)') ch10,' Velocities:'
758 45 : call wrtout(std_out,msg,'COLL')
759 45 : call wrtout(ab_out,msg,'COLL')
760 260 : do iimage=1,trotter
761 45 : select case(iimage)
762 : case(1)
763 45 : write(msg,'(a)') ' vel'
764 : case(2,3,4,5,6,7,8,9)
765 170 : write(msg,'(a,i1,a)') ' vel_',iimage,'img'
766 : case(10:99)
767 0 : write(msg,'(a,i2,a)') ' vel_',iimage,'img'
768 : case default
769 215 : write(msg,'(a,i3,a)') ' vel_',iimage,'img'
770 : end select
771 215 : call wrtout(std_out,msg,'COLL')
772 215 : call wrtout(ab_out,msg,'COLL')
773 215 : if (traj_unit>0) then
774 0 : call wrtout(traj_unit,msg,'COLL')
775 : end if
776 830 : do iatom=1,natom
777 570 : write(msg,'(3f18.10)') vel(1:3,iatom,iimage)
778 570 : call wrtout(std_out,msg,'COLL')
779 570 : call wrtout(ab_out,msg,'COLL')
780 785 : if (traj_unit>0) then
781 0 : call wrtout(traj_unit,msg,'COLL')
782 : end if
783 : end do
784 : end do
785 :
786 45 : if (optcell>0) then
787 :
788 5 : call mkradim(acell,rprim,rprimd)
789 :
790 : ! Time derivative of rprimd
791 5 : write(msg,'(2a)') ch10,' Time derivative of rprimd:'
792 5 : call wrtout(std_out,msg,'COLL')
793 5 : call wrtout(ab_out,msg,'COLL')
794 5 : write(msg,'(2a,3(3f18.10))') ' vel_cell',ch10,vel_cell(:,:)
795 5 : call wrtout(std_out,msg,'COLL')
796 5 : call wrtout(ab_out,msg,'COLL')
797 5 : if (traj_unit>0) then
798 0 : call wrtout(traj_unit,msg,'COLL')
799 : end if
800 :
801 : ! rprimd
802 5 : write(msg,'(2a)') ch10,' Cell parameters:'
803 5 : call wrtout(std_out,msg,'COLL')
804 5 : call wrtout(ab_out,msg,'COLL')
805 5 : write(msg,'(2a,3(3f18.10),3a,3f18.10)') ' rprim',ch10,rprim(:,:),ch10,&
806 10 : & ' acell',ch10,acell(:)
807 5 : call wrtout(std_out,msg,'COLL')
808 5 : call wrtout(ab_out,msg,'COLL')
809 5 : if (traj_unit>0) then
810 0 : call wrtout(traj_unit,msg,'COLL')
811 : end if
812 :
813 : end if
814 :
815 : !Centroids and wave-packet spatial spreads
816 135 : ABI_MALLOC(centroid,(3,natom))
817 135 : ABI_MALLOC(qudeloc,(natom))
818 795 : centroid=zero;qudeloc=zero
819 260 : do iimage=1,trotter
820 830 : do iatom=1,natom
821 2495 : do ii=1,3
822 2280 : centroid(ii,iatom)=centroid(ii,iatom)+xcart(ii,iatom,iimage)
823 : end do
824 : end do
825 : end do
826 645 : centroid=centroid/dble(trotter)
827 260 : do iimage=1,trotter
828 830 : do iatom=1,natom
829 2495 : do ii=1,3
830 2280 : qudeloc(iatom)=qudeloc(iatom)+((xcart(ii,iatom,iimage)-centroid(ii,iatom))**2)
831 : end do
832 : end do
833 : end do
834 195 : qudeloc(:)=sqrt(qudeloc(:)/dble(trotter))
835 45 : write(msg,'(4a)') ch10,' Centroids and wave-packet spatial spreads (cart. coord.):',ch10,&
836 90 : & ' iat centroid_x centroid_y centroid_z spatial_spread'
837 45 : call wrtout(std_out,msg,'COLL')
838 195 : do iatom=1,natom
839 150 : write(msg,'(i4,4f18.10)') iatom,centroid(1:3,iatom),qudeloc(iatom)
840 195 : call wrtout(std_out,msg,'COLL')
841 : end do
842 45 : ABI_FREE(centroid)
843 45 : ABI_FREE(qudeloc)
844 :
845 : !Fake statement
846 : return;ii=prtvolimg
847 :
848 : end subroutine pimd_print
849 : !!***
850 :
851 : !----------------------------------------------------------------------
852 :
853 : !!****f* m_pimd/pimd_initvel
854 : !! NAME
855 : !! pimd_initvel
856 : !!
857 : !! FUNCTION
858 : !! Initialize velocities for PIMD with a gaussian distribution
859 : !! fixing the center of mass
860 : !! and eventually applying a constraint on atomic positions
861 : !!
862 : !! INPUTS
863 : !! constraint=type of constraint to be applied
864 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
865 : !! natom=number of atoms
866 : !! temperature=temperature used to define velocities
867 : !! trotter=Trotter number
868 : !! wtatcon(3,natom)=weights for atomic constraints
869 : !!
870 : !! OUTPUT
871 : !! vel(3,natom,trotter)=velocities of atoms in in each cell
872 : !!
873 : !! SIDE EFFECTS
874 : !! iseed=seed for random number generator
875 : !!
876 : !! SOURCE
877 :
878 8 : subroutine pimd_initvel(iseed,mass,natom,temperature,trotter,vel,constraint,wtatcon)
879 :
880 : !Arguments ------------------------------------
881 : !scalars
882 : integer,intent(in) :: constraint,natom,trotter
883 : integer,intent(inout) :: iseed
884 : real(dp),intent(in) :: temperature
885 : !arrays
886 : real(dp),intent(in) :: mass(:,:),wtatcon(3,natom)
887 : real(dp),intent(out) :: vel(3,natom,trotter)
888 : !Local variables-------------------------------
889 : !scalars
890 : integer :: iatom,ii,iimage,imass,natom_mass,nmass
891 : real(dp) :: mtot,rescale_vel
892 : character(len=500) :: msg
893 : !arrays
894 : real(dp) :: mvini(3)
895 :
896 : !************************************************************************
897 :
898 8 : natom_mass=size(mass,1);nmass=size(mass,2)
899 8 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
900 0 : msg='Wrong dimensions for array mass !'
901 0 : ABI_BUG(msg)
902 : end if
903 :
904 : !Compute total mass (of non-constrained atoms)
905 8 : if (constraint==0) then
906 100 : mtot=sum(mass(1:natom,1:nmass))
907 : else
908 : mtot=zero
909 0 : do iatom=1,natom
910 0 : if (all(abs(wtatcon(:,iatom))<tol8)) mtot=mtot+sum(mass(iatom,1:nmass))
911 : end do
912 : end if
913 8 : if (nmass==1) mtot=mtot*dble(trotter)
914 :
915 : !Initialize randomly the velocities
916 46 : do iimage=1,trotter
917 38 : imass=min(nmass,iimage)
918 130 : do iatom=1,natom
919 374 : do ii=1,3
920 252 : vel(ii,iatom,iimage)=sqrt(kb_HaK*temperature/mass(iatom,imass))*cos(two_pi*uniformrandom(iseed))
921 336 : vel(ii,iatom,iimage)=vel(ii,iatom,iimage)*sqrt(-two*log(uniformrandom(iseed)))
922 : end do
923 : end do
924 : end do
925 :
926 : !Cancel velocities of constrained atoms
927 8 : if (constraint/=0) then
928 0 : do iimage=1,trotter
929 0 : do iatom=1,natom
930 0 : if (any(abs(wtatcon(:,iatom))>=tol8)) vel(:,iatom,iimage)=zero
931 : end do
932 : end do
933 : end if
934 :
935 : !Make sure that the (sum of m_i v_i) at step zero is zero
936 8 : mvini=zero
937 46 : do iimage=1,trotter
938 38 : imass=min(nmass,iimage)
939 130 : do iatom=1,natom
940 374 : do ii=1,3
941 336 : mvini(ii)=mvini(ii)+mass(iatom,imass)*vel(ii,iatom,iimage)
942 : end do
943 : end do
944 : end do
945 8 : if (constraint==0) then
946 46 : do iimage=1,trotter
947 130 : do iatom=1,natom
948 374 : do ii=1,3
949 336 : vel(ii,iatom,iimage)=vel(ii,iatom,iimage)-(mvini(ii)/mtot)
950 : end do
951 : end do
952 : end do
953 : else
954 0 : do iimage=1,trotter
955 0 : do iatom=1,natom
956 0 : if (all(abs(wtatcon(:,iatom))<tol8)) vel(:,iatom,iimage)=vel(:,iatom,iimage)-(mvini(:)/mtot)
957 : end do
958 : end do
959 : end if
960 :
961 : !Now rescale the velocities to give the exact temperature
962 8 : rescale_vel=sqrt(temperature/pimd_temperature(mass,vel))
963 382 : vel(:,:,:)=vel(:,:,:)*rescale_vel
964 :
965 8 : end subroutine pimd_initvel
966 : !!***
967 :
968 : !----------------------------------------------------------------------
969 :
970 : !!****f* m_pimd/pimd_initvel_from_scratch
971 : !! NAME
972 : !! pimd_initvel_from_scratch
973 : !!
974 : !! FUNCTION
975 : !! Initialize velocities for PIMD with a gaussian distribution
976 : !! at start of the calculation (with initial temperature)
977 : !!
978 : !! INPUTS
979 : !! pimd_temperature=temperature (from all images of the cell)
980 : !! natom=number of atoms
981 : !! trotter=Trotter number
982 : !! vel_cell(3,3)=cell velocities
983 : !!
984 : !! OUTPUT
985 : !! vel(3,natom,nimage)=velocities for each image of the cell
986 : !!
987 : !! SOURCE
988 :
989 0 : subroutine pimd_initvel_from_scratch(pimd_param,natom,trotter,vel,vel_cell)
990 :
991 : !Arguments ------------------------------------
992 : !scalars
993 : integer,intent(in) :: natom,trotter
994 : real(dp),intent(in) :: vel_cell(3,3)
995 : real(dp),intent(out) :: vel(3,natom,trotter)
996 : type(pimd_type),intent(inout) :: pimd_param
997 : !Local variables-------------------------------
998 : !scalars
999 : integer :: iseed=-5,iimage,irestart,ndof,zeroforce
1000 : real(dp) :: initemp,rescale_temp
1001 : !arrays
1002 0 : real(dp),allocatable :: inertmass(:,:)
1003 :
1004 : !************************************************************************
1005 :
1006 0 : ABI_MALLOC(inertmass,(natom,trotter))
1007 0 : do iimage=1,trotter
1008 0 : inertmass(1:natom,iimage)=pimd_param%pimass(pimd_param%typat(1:natom))*amu_emass
1009 : end do
1010 :
1011 0 : irestart=pimd_is_restart(inertmass,vel,vel_cell)
1012 :
1013 : !Initialize derivatives
1014 0 : if (mod(irestart,10)==0) then
1015 0 : ndof=3*natom*trotter
1016 0 : rescale_temp=one ; if(zeroforce==1) rescale_temp=dble(ndof)/dble(ndof-3)
1017 : zeroforce=1 ; if(pimd_param%pitransform==1.or.pimd_param%pitransform==2) zeroforce=0
1018 0 : if(pimd_param%constraint==1) zeroforce=0
1019 0 : initemp=pimd_param%mdtemp(1)/rescale_temp
1020 0 : call pimd_initvel(iseed,inertmass,natom,initemp,trotter,vel,pimd_param%constraint,pimd_param%wtatcon)
1021 : end if
1022 :
1023 0 : ABI_FREE(inertmass)
1024 :
1025 0 : end subroutine pimd_initvel_from_scratch
1026 : !!***
1027 :
1028 : !----------------------------------------------------------------------
1029 :
1030 : !!****f* m_pimd/pimd_langevin_random
1031 : !! NAME
1032 : !! pimd_langevin_random
1033 : !!
1034 : !! FUNCTION
1035 : !! Generate a set of random numbers to be used for PIMD Langevin algorithm
1036 : !!
1037 : !! INPUTS
1038 : !! irandom=option for random number generator:
1039 : !! 1:uniform random routine provided within Abinit package
1040 : !! 2:Fortran 90 random number generator
1041 : !! 3:ZBQLU01 non deterministic random number generator
1042 : !! langev(natom,mass_dim)=Langevin factors (mass_dim=1 or trotter)
1043 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1044 : !! natom=number of atoms
1045 : !! trotter=Trotter number
1046 : !! zeroforce=flag; if 1 keep sum of forces equal to zero
1047 : !!
1048 : !! OUTPUT
1049 : !! alea(3,natom,trotter)=set of random numbers
1050 : !!
1051 : !! SIDE EFFECTS
1052 : !! iseed=seed for random number generator (used only if irandom=1)
1053 : !!
1054 : !! SOURCE
1055 :
1056 30 : subroutine pimd_langevin_random(alea,irandom,iseed,langev,mass,natom,trotter,zeroforce)
1057 :
1058 : !Arguments ------------------------------------
1059 : !scalars
1060 : integer,intent(in) :: irandom,natom,trotter,zeroforce
1061 : integer,intent(inout) :: iseed
1062 : !arrays
1063 : real(dp),intent(in) :: langev(:,:),mass(:,:)
1064 : real(dp),intent(out) :: alea(3,natom,trotter)
1065 : !Local variables-------------------------------
1066 : !scalars
1067 : integer :: iatom,ii,iimage,imass,nmass,natom_mass
1068 : real(dp) :: mtot,r1,r2
1069 : character(len=500) :: msg
1070 : !arrays
1071 : real(dp) :: total(3)
1072 :
1073 : !************************************************************************
1074 :
1075 30 : natom_mass=size(mass,1);nmass=size(mass,2)
1076 30 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1077 0 : msg='Wrong dimensions for array mass !'
1078 0 : ABI_BUG(msg)
1079 : end if
1080 :
1081 : mtot=sum(mass(1:natom,1:nmass))
1082 30 : if (nmass==1) mtot=mtot*trotter
1083 :
1084 : !Draw random numbers
1085 155 : do iimage=1,trotter
1086 545 : do iatom=1,natom
1087 1685 : do ii=1,3
1088 2340 : select case(irandom)
1089 : case(1)
1090 1170 : r1=uniformrandom(iseed)
1091 1170 : r2=uniformrandom(iseed)
1092 : case(2)
1093 0 : call random_number(r1)
1094 0 : call random_number(r2)
1095 : case(3)
1096 0 : r1=ZBQLU01(zero)
1097 1170 : r2=ZBQLU01(zero)
1098 : end select
1099 1560 : alea(ii,iatom,iimage)= cos(two_pi*r1)*sqrt(-log(r2)*two)
1100 : end do
1101 : end do
1102 : end do
1103 :
1104 : !Make sure that the sum of random forces is zero
1105 30 : if(zeroforce==1)then
1106 15 : total=zero
1107 15 : mtot=zero
1108 55 : do iimage=1,trotter
1109 40 : imass=min(nmass,iimage)
1110 175 : do iatom=1,natom
1111 160 : mtot=mtot+mass(iatom,imass)
1112 : end do
1113 : end do
1114 55 : do iimage=1,trotter
1115 40 : imass=min(nmass,iimage)
1116 175 : do iatom=1,natom
1117 520 : do ii=1,3
1118 480 : total(ii)=total(ii)+langev(iatom,imass)*alea(ii,iatom,iimage)
1119 : end do
1120 : end do
1121 : end do
1122 55 : do iimage=1,trotter
1123 40 : imass=min(nmass,iimage)
1124 175 : do iatom=1,natom
1125 520 : do ii=1,3
1126 : alea(ii,iatom,iimage)= alea(ii,iatom,iimage)- &
1127 480 : & (total(ii)*mass(iatom,imass))/(langev(iatom,imass)*mtot)
1128 : end do
1129 : end do
1130 : end do
1131 : ! now random forces have been rescaled so that their sum is zero
1132 : end if
1133 :
1134 30 : end subroutine pimd_langevin_random
1135 : !!***
1136 :
1137 : !----------------------------------------------------------------------
1138 :
1139 : !!****f* m_pimd/pimd_langevin_random_qtb
1140 : !! NAME
1141 : !! pimd_langevin_random_qtb
1142 : !!
1143 : !! FUNCTION
1144 : !! Read a set of random forces (atm units) to be used for PIMD QTB algorithm
1145 : !!
1146 : !! INPUTS
1147 : !! langev(natom,mass_dim)=Langevin factors (mass_dim=1 or trotter)
1148 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1149 : !! natom=number of atoms
1150 : !! qtb_file_unit= ramdom forces file unit
1151 : !! trotter=Trotter number
1152 : !! zeroforce=flag; if 1 keep sum of forces equal to zero
1153 : !!
1154 : !! OUTPUT
1155 : !! alea(3,natom,trotter)=set of random forces
1156 : !!
1157 : !! SOURCE
1158 :
1159 0 : subroutine pimd_langevin_random_qtb(alea,langev,mass,natom,qtb_file_unit,trotter,zeroforce)
1160 :
1161 : !Arguments ------------------------------------
1162 : !scalars
1163 : integer,intent(in) :: natom,qtb_file_unit,trotter,zeroforce
1164 : !arrays
1165 : real(dp),intent(in) :: langev(:,:),mass(:,:)
1166 : real(dp),intent(out) :: alea(3,natom,trotter)
1167 : !Local variables-------------------------------
1168 : !scalars
1169 : integer :: iatom,ii,iimage,imass,nmass,natom_mass
1170 : real(dp) :: mtot
1171 : character(len=500) :: msg
1172 : !arrays
1173 0 : real(sp) :: alea_sp(3,natom,trotter)
1174 : real(dp) :: total(3)
1175 :
1176 : !************************************************************************
1177 :
1178 0 : if (qtb_file_unit<0) then
1179 0 : msg='QTB forces file unit should be positive!'
1180 0 : ABI_BUG(msg)
1181 : end if
1182 0 : natom_mass=size(mass,1);nmass=size(mass,2)
1183 0 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1184 0 : msg='Wrong dimensions for array mass !'
1185 0 : ABI_BUG(msg)
1186 : end if
1187 :
1188 : !Read QTB random forces
1189 0 : read(qtb_file_unit) alea_sp(1:3,1:natom,1:trotter)
1190 0 : alea(:,:,:)=dble(alea_sp(:,:,:))
1191 :
1192 : !Make sure that the sum of random forces is zero
1193 0 : if(zeroforce==1)then
1194 0 : total=zero
1195 0 : mtot=zero
1196 0 : do iimage=1,trotter
1197 0 : imass=min(nmass,iimage)
1198 0 : do iatom=1,natom
1199 0 : mtot=mtot+mass(iatom,imass)
1200 : end do
1201 : end do
1202 0 : do iimage=1,trotter
1203 0 : imass=min(nmass,iimage)
1204 0 : do iatom=1,natom
1205 0 : do ii=1,3
1206 0 : total(ii)=total(ii)+langev(iatom,imass)*alea(ii,iatom,iimage)
1207 : end do
1208 : end do
1209 : end do
1210 0 : do iimage=1,trotter
1211 0 : imass=min(nmass,iimage)
1212 0 : do iatom=1,natom
1213 0 : do ii=1,3
1214 : alea(ii,iatom,iimage)= alea(ii,iatom,iimage)- &
1215 0 : & (total(ii)*mass(iatom,imass))/(langev(iatom,imass)*mtot)
1216 : end do
1217 : end do
1218 : end do
1219 : ! now random forces have been rescaled so that their sum is zero
1220 : end if
1221 :
1222 0 : end subroutine pimd_langevin_random_qtb
1223 : !!***
1224 :
1225 : !----------------------------------------------------------------------
1226 :
1227 : !!****f* m_pimd/pimd_langevin_random_bar
1228 : !! NAME
1229 : !! pimd_langevin_random_bar
1230 : !!
1231 : !! FUNCTION
1232 : !! Generate a set of random numbers to be used for the barostat of PIMD Langevin algorithm
1233 : !!
1234 : !! INPUTS
1235 : !! irandom=option for random number generator:
1236 : !! 1:uniform random routine provided within Abinit package
1237 : !! 2:Fortran 90 random number generator
1238 : !! 3:ZBQLU01 non deterministic random number generator
1239 : !!
1240 : !! OUTPUT
1241 : !! alea_bar(3,3)=set of random numbers
1242 : !!
1243 : !! SIDE EFFECTS
1244 : !! iseed=seed for random number generator (used only if irandom=1)
1245 : !!
1246 : !! SOURCE
1247 :
1248 5 : subroutine pimd_langevin_random_bar(alea_bar,irandom,iseed)
1249 :
1250 : !Arguments ------------------------------------
1251 : !scalars
1252 : integer,intent(in) :: irandom
1253 : integer,intent(inout) :: iseed
1254 : !arrays
1255 : real(dp),intent(out) :: alea_bar(3,3)
1256 : !Local variables-------------------------------
1257 : !scalars
1258 : integer :: ii,jj
1259 : real(dp) :: r1,r2
1260 : !arrays
1261 :
1262 : !************************************************************************
1263 :
1264 : !Draw random numbers
1265 20 : do ii=1,3
1266 65 : do jj=1,3
1267 90 : select case(irandom)
1268 : case(1)
1269 45 : r1=uniformrandom(iseed)
1270 45 : r2=uniformrandom(iseed)
1271 : case(2)
1272 0 : call random_number(r1)
1273 0 : call random_number(r2)
1274 : case(3)
1275 0 : r1=ZBQLU01(zero)
1276 45 : r2=ZBQLU01(zero)
1277 : end select
1278 60 : alea_bar(ii,jj)= cos(two_pi*r1)*sqrt(-log(r2)*two)
1279 : end do
1280 : end do
1281 :
1282 : !Symmetrize
1283 5 : alea_bar(1,2)=half*(alea_bar(1,2)+alea_bar(2,1))
1284 5 : alea_bar(1,3)=half*(alea_bar(1,3)+alea_bar(3,1))
1285 5 : alea_bar(2,3)=half*(alea_bar(2,3)+alea_bar(3,2))
1286 5 : alea_bar(2,1)=alea_bar(1,2)
1287 5 : alea_bar(3,1)=alea_bar(1,3)
1288 5 : alea_bar(3,2)=alea_bar(2,3)
1289 :
1290 5 : end subroutine pimd_langevin_random_bar
1291 : !!***
1292 :
1293 : !----------------------------------------------------------------------
1294 :
1295 : !!****f* m_pimd/pimd_langevin_random_init
1296 : !! NAME
1297 : !! pimd_langevin_random_init
1298 : !!
1299 : !! FUNCTION
1300 : !! Initialize random number generator to be used for PIMD Langevin algorithm
1301 : !!
1302 : !! INPUTS
1303 : !! irandom=option for random number generator:
1304 : !! 1:uniform random routine provided within Abinit package
1305 : !! 2:Fortran 90 random number generator
1306 : !! 3:ZBQLU01 non deterministic random number generator
1307 : !!
1308 : !! OUTPUT
1309 : !!
1310 : !! SIDE EFFECTS
1311 : !! iseed=seed for random number generator (used only if irandom=1)
1312 : !!
1313 : !! SOURCE
1314 :
1315 5 : subroutine pimd_langevin_random_init(irandom,iseed)
1316 :
1317 : !Arguments ------------------------------------
1318 : !scalars
1319 : integer,intent(in) :: irandom
1320 : integer,intent(inout) :: iseed
1321 :
1322 : !************************************************************************
1323 :
1324 5 : if (irandom==3) then
1325 0 : call ZBQLINI(0)
1326 : end if
1327 :
1328 : !Fake statement
1329 : return;if (.false.) iseed=zero
1330 :
1331 : end subroutine pimd_langevin_random_init
1332 : !!***
1333 :
1334 : !----------------------------------------------------------------------
1335 :
1336 : !!****f* m_pimd/pimd_energies
1337 : !! NAME
1338 : !! pimd_energies
1339 : !!
1340 : !! FUNCTION
1341 : !! In the case od PIMD, compute the several contribution to total energy
1342 : !!
1343 : !! INPUTS
1344 : !! etotal_img(trotter)= energy (from DFT) for each cell
1345 : !! forces(3,natom,trotter)=forces (from DFT) on atoms in each cell
1346 : !! natom=number of atoms
1347 : !! spring(natom)=spring constants in the primitive scheme
1348 : !! trotter=Trotter number
1349 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in each cell at t
1350 : !!
1351 : !! OUTPUT
1352 : !! eharm =harmonic energy
1353 : !! eharm_virial=harmonic energy from virial estimator
1354 : !! epot =potential energy
1355 : !!
1356 : !! SIDE EFFECTS
1357 : !!
1358 : !! SOURCE
1359 :
1360 45 : subroutine pimd_energies(eharm,eharm_virial,epot,etotal_img,forces,natom,spring,trotter,xcart)
1361 :
1362 : !Arguments ------------------------------------
1363 : !scalars
1364 : integer,intent(in) :: natom,trotter
1365 : real(dp),intent(out) :: eharm,eharm_virial,epot
1366 : !arrays
1367 : real(dp),intent(in) :: etotal_img(trotter),forces(3,natom,trotter)
1368 : real(dp),intent(in) :: xcart(3,natom,trotter)
1369 : real(dp),intent(in) :: spring(natom)
1370 : !Local variables-------------------------------
1371 : !scalars
1372 : integer :: iatom,ii,iimage,iimagep
1373 : !arrays
1374 45 : real(dp),allocatable :: centroid(:,:)
1375 :
1376 : !************************************************************************
1377 :
1378 : !Compute the centroid
1379 135 : ABI_MALLOC(centroid,(3,natom))
1380 645 : centroid=zero
1381 260 : do iimage=1,trotter
1382 830 : do iatom=1,natom
1383 2495 : do ii=1,3
1384 2280 : centroid(ii,iatom)=centroid(ii,iatom)+xcart(ii,iatom,iimage)
1385 : end do
1386 : end do
1387 : end do
1388 645 : centroid=centroid/dble(trotter)
1389 :
1390 : !Potential energy
1391 260 : epot=sum(etotal_img(1:trotter))/dble(trotter)
1392 :
1393 : !Harmonic energy
1394 45 : eharm=zero
1395 260 : do iimage=1,trotter
1396 215 : iimagep=iimage+1;if(iimage==trotter)iimagep=1
1397 830 : do iatom=1,natom
1398 2495 : do ii=1,3
1399 2280 : eharm=eharm+half*spring(iatom)*((xcart(ii,iatom,iimagep)-xcart(ii,iatom,iimage))**2)
1400 : end do
1401 : end do
1402 : end do
1403 :
1404 : !Harmonic energy from virial estimator
1405 45 : eharm_virial=zero
1406 260 : do iimage=1,trotter
1407 830 : do iatom=1,natom
1408 2495 : do ii=1,3
1409 : eharm_virial=eharm_virial-(xcart(ii,iatom,iimage)-centroid(ii,iatom)) &
1410 2280 : & *forces(ii,iatom,iimage)
1411 : end do
1412 : end do
1413 : end do
1414 45 : eharm_virial=eharm_virial/dble(two*trotter)
1415 :
1416 45 : ABI_FREE(centroid)
1417 :
1418 45 : end subroutine pimd_energies
1419 : !!***
1420 :
1421 : !----------------------------------------------------------------------
1422 :
1423 : !!****f* m_pimd/pimd_forces
1424 : !! NAME
1425 : !! pimd_forces
1426 : !!
1427 : !! FUNCTION
1428 : !! Modify forces in order to take into account PIMD contribution
1429 : !!
1430 : !! INPUTS
1431 : !! natom=number of atoms
1432 : !! spring(natom,spring_dim)=spring constants (spring_dim=1 or trotter)
1433 : !! transform=coordinate transformation:
1434 : !! 0: no tranformation
1435 : !! 1: normal mode transformation
1436 : !! 2: staging transformation
1437 : !! trotter=Trotter number
1438 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in each cell
1439 : !!
1440 : !! OUTPUT
1441 : !!
1442 : !! SIDE EFFECTS
1443 : !! forces(3,natom,trotter)=
1444 : !! at input: forces from electronic calculation
1445 : !! at output: forces from electronic calculation + quantum spring contribution
1446 : !!
1447 : !! SOURCE
1448 :
1449 45 : subroutine pimd_forces(forces,natom,spring,transform,trotter,xcart)
1450 :
1451 : !Arguments ------------------------------------
1452 : !scalars
1453 : integer,intent(in) :: natom,transform,trotter
1454 : !arrays
1455 : real(dp),intent(in) :: xcart(3,natom,trotter)
1456 : real(dp),intent(in) :: spring(:,:)
1457 : real(dp),intent(inout) :: forces(3,natom,trotter)
1458 : !Local variables-------------------------------
1459 : !scalars
1460 : integer :: iatom,ii,iimage,iimagem,iimagep,ispring,natom_spring,nspring
1461 : character(len=500) :: msg
1462 : !arrays
1463 :
1464 : !************************************************************************
1465 :
1466 45 : natom_spring=size(spring,1);nspring=size(spring,2)
1467 45 : if (natom/=natom_spring.or.(nspring/=1.and.nspring/=trotter)) then
1468 0 : msg='Wrong dimensions for array spring !'
1469 0 : ABI_BUG(msg)
1470 : end if
1471 :
1472 45 : if (transform==0) then
1473 120 : do iimage=1,trotter
1474 95 : ispring=min(nspring,iimage)
1475 95 : iimagep=iimage+1; iimagem=iimage-1
1476 95 : if(iimage==trotter) iimagep=1
1477 95 : if(iimage==1) iimagem=trotter
1478 450 : do iatom=1,natom
1479 1415 : do ii=1,3
1480 : forces(ii,iatom,iimage)= &
1481 : & forces(ii,iatom,iimage)/dble(trotter) &
1482 : & - spring(iatom,ispring)*(two*xcart(ii,iatom,iimage)-xcart(ii,iatom,iimagem) &
1483 1320 : & -xcart(ii,iatom,iimagep))
1484 : end do
1485 : end do
1486 : end do
1487 :
1488 : else
1489 140 : do iimage=1,trotter
1490 120 : ispring=min(nspring,iimage)
1491 380 : do iatom=1,natom
1492 1080 : do ii=1,3
1493 : forces(ii,iatom,iimage)= &
1494 : & forces(ii,iatom,iimage)/dble(trotter) &
1495 960 : & - spring(iatom,ispring)*xcart(ii,iatom,iimage)
1496 : end do
1497 : end do
1498 : end do
1499 :
1500 : end if
1501 :
1502 45 : end subroutine pimd_forces
1503 : !!***
1504 :
1505 : !----------------------------------------------------------------------
1506 :
1507 : !!****f* m_pimd/pimd_langevin_forces
1508 : !! NAME
1509 : !! pimd_langevin_forces
1510 : !!
1511 : !! FUNCTION
1512 : !! Compute Langevin contribution to PIMD forces
1513 : !!
1514 : !! INPUTS
1515 : !! alea(3,natom,trotter)=set of random numbers
1516 : !! forces(3,natom,trotter)=forces without Langevin contribution
1517 : !! friction=friction factor
1518 : !! langev(natom,mass_dim)=Langevin factors (mass_dim=1 or trotter)
1519 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1520 : !! natom=number of atoms
1521 : !! trotter=Trotter number
1522 : !! vel(3,natom,trotter)=velocities of atoms in each cell
1523 : !!
1524 : !! OUTPUT
1525 : !! forces_langevin(3,natom,trotter)=forces including Langevin contribution
1526 : !!
1527 : !! SIDE EFFECTS
1528 : !!
1529 : !! SOURCE
1530 :
1531 408 : subroutine pimd_langevin_forces(alea,forces,forces_langevin,friction,&
1532 136 : & langev,mass,natom,trotter,vel)
1533 :
1534 : !Arguments ------------------------------------
1535 : !scalars
1536 : integer,intent(in) :: natom,trotter
1537 : real(dp),intent(in) :: friction
1538 : !arrays
1539 : real(dp),intent(in) :: alea(3,natom,trotter),forces(3,natom,trotter)
1540 : real(dp),intent(in) :: langev(:,:),mass(:,:),vel(3,natom,trotter)
1541 : real(dp),intent(out) :: forces_langevin(3,natom,trotter)
1542 : !Local variables-------------------------------
1543 : !scalars
1544 : integer :: iatom,ii,iimage,imass,natom_mass,nmass
1545 : character(len=500) :: msg
1546 : !arrays
1547 :
1548 : !************************************************************************
1549 :
1550 136 : natom_mass=size(mass,1);nmass=size(mass,2)
1551 136 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1552 0 : msg='Wrong dimensions for array mass !'
1553 0 : ABI_BUG(msg)
1554 : end if
1555 :
1556 691 : do iimage=1,trotter
1557 555 : imass=min(nmass,iimage)
1558 2509 : do iatom=1,natom
1559 7827 : do ii=1,3
1560 : forces_langevin(ii,iatom,iimage)=forces(ii,iatom,iimage) &
1561 : & + langev(iatom,imass)*alea(ii,iatom,iimage) &
1562 7272 : & - friction*mass(iatom,imass)*vel(ii,iatom,iimage)
1563 : end do
1564 : end do
1565 : end do
1566 :
1567 136 : end subroutine pimd_langevin_forces
1568 : !!***
1569 :
1570 : !----------------------------------------------------------------------
1571 :
1572 : !!****f* m_pimd/pimd_noseehoover_forces
1573 : !! NAME
1574 : !! pimd_nosehoover_forces
1575 : !!
1576 : !! FUNCTION
1577 : !! Compute Nose-Hoover contribution to PIMD forces
1578 : !! by adding friction force of thermostat number one
1579 : !!
1580 : !! INPUTS
1581 : !! dzeta(3,natom,trotter,nnos)=variables of thermostats, in (atomic time unit)^(-1)
1582 : !! used only when a coordinate transformation is applied (transfom/=0)
1583 : !! forces(3,natom,trotter)=forces without Nose-Hoover contribution
1584 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1585 : !! natom=number of atoms
1586 : !! nnos=number of thermostats
1587 : !! trotter=Trotter number
1588 : !! vel(3,natom,trotter)=velocities of atoms in each cell
1589 : !!
1590 : !! OUTPUT
1591 : !! forces_nosehoover(3,natom,trotter)=forces including thermostat contribution
1592 : !!
1593 : !! SIDE EFFECTS
1594 : !!
1595 : !! SOURCE
1596 :
1597 132 : subroutine pimd_nosehoover_forces(dzeta,forces,forces_nosehoover,mass,natom,&
1598 132 : & nnos,trotter,vel)
1599 :
1600 : !Arguments ------------------------------------
1601 : !scalars
1602 : integer,intent(in) :: natom,nnos,trotter
1603 : !arrays
1604 : real(dp),intent(in) :: dzeta(3,natom,trotter,nnos),forces(3,natom,trotter)
1605 : real(dp),intent(in) :: vel(3,natom,trotter)
1606 : real(dp),intent(in) :: mass(:,:)
1607 : real(dp),intent(out) :: forces_nosehoover(3,natom,trotter)
1608 : !Local variables-------------------------------
1609 : !scalars
1610 : integer :: iatom,ii,iimage,imass,natom_mass,nmass
1611 : character(len=500) :: msg
1612 : !arrays
1613 :
1614 : !************************************************************************
1615 :
1616 132 : natom_mass=size(mass,1);nmass=size(mass,2)
1617 132 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1618 0 : msg='Wrong dimensions for array mass !'
1619 0 : ABI_BUG(msg)
1620 : end if
1621 :
1622 924 : do iimage=1,trotter
1623 792 : imass=min(nmass,iimage)
1624 2508 : do iatom=1,natom
1625 7128 : do ii=1,3
1626 : forces_nosehoover(ii,iatom,iimage)=forces(ii,iatom,iimage) &
1627 6336 : & - mass(iatom,imass)*dzeta(ii,iatom,iimage,1)*vel(ii,iatom,iimage)
1628 : end do
1629 : end do
1630 : end do
1631 :
1632 132 : end subroutine pimd_nosehoover_forces
1633 : !!***
1634 :
1635 : !----------------------------------------------------------------------
1636 :
1637 : !!****f* m_pimd/pimd_stresses
1638 : !! NAME
1639 : !! pimd_stresses
1640 : !!
1641 : !! FUNCTION
1642 : !! In the case od PIMD, compute the pressure tensor from virial theorem
1643 : !!
1644 : !! INPUTS
1645 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1646 : !! natom=number of atoms
1647 : !! quantummass(natom)=quantum masses of atoms
1648 : !! stressin(3,3,trotter)=electronic stress tensor for each image
1649 : !! temperature=temperature (could be instantaneous temp. or thermostat temp.)
1650 : !! temperature_therm=thermostat temperature
1651 : !! trotter=Trotter number
1652 : !! vel(3,natom,trotter)=velocities of atoms in each cell
1653 : !! volume=volume of each cell (common to all cells)
1654 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in each cell at t
1655 : !! temperature=thermostat temperature
1656 : !!
1657 : !! OUTPUT
1658 : !! stress_pimd(3,3,3)=stress tensor for PIMD
1659 : !! First dimension (3) corresponds to 3 different pressure estimators
1660 : !!
1661 : !! SIDE EFFECTS
1662 : !!
1663 : !! SOURCE
1664 :
1665 71 : subroutine pimd_stresses(mass,natom,quantummass,stress_pimd,stressin,&
1666 71 : & temperature,temperature_therm,trotter,vel,volume,xcart)
1667 :
1668 : !Arguments ------------------------------------
1669 : !scalars
1670 : integer,intent(in) :: natom,trotter
1671 : real(dp),intent(in) :: temperature,temperature_therm,volume
1672 : !arrays
1673 : real(dp),intent(in) :: vel(3,natom,trotter),xcart(3,natom,trotter)
1674 : real(dp),intent(in) :: mass(:,:),stressin(3,3,trotter),quantummass(natom)
1675 : real(dp),intent(out) :: stress_pimd(3,3,3)
1676 : !Local variables-------------------------------
1677 : !scalars
1678 : integer :: iatom,ii,iimage,imass,jj,natom_mass,nmass,iimagep
1679 : real(dp) :: stress_tmp(3,3,3),omega2,kt,kt_therm
1680 : character(len=500) :: msg
1681 :
1682 : !************************************************************************
1683 :
1684 71 : natom_mass=size(mass,1);nmass=size(mass,2)
1685 71 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1686 0 : msg='Wrong dimensions for array mass !'
1687 0 : ABI_BUG(msg)
1688 : end if
1689 :
1690 71 : kt=temperature*kb_HaK
1691 71 : kt_therm=temperature_therm*kb_HaK
1692 71 : stress_pimd=zero
1693 :
1694 : !I-PRIMITIVE ESTIMATOR
1695 : !1-Kinetic part
1696 284 : do ii=1,3
1697 284 : stress_pimd(1,ii,ii)=dble(natom)*dble(trotter)*kt/volume
1698 : end do
1699 :
1700 : !2-Potential part
1701 312 : do iimage=1,trotter
1702 1035 : do ii=1,3
1703 3133 : do jj=1,3
1704 2892 : stress_pimd(1,ii,jj)=stress_pimd(1,ii,jj)-stressin(ii,jj,iimage)/dble(trotter)
1705 : !minus to convert stress into pressure
1706 : end do
1707 : end do
1708 : end do
1709 :
1710 : !3-Contribution from springs
1711 71 : omega2=dble(trotter)*kt_therm*kt_therm
1712 312 : do iimage=1,trotter
1713 241 : iimagep=iimage+1
1714 241 : if(iimage==trotter) then
1715 71 : iimagep=1
1716 : end if
1717 1038 : do iatom=1,natom
1718 3145 : do ii=1,3
1719 9438 : do jj=1,3
1720 : stress_pimd(1,ii,jj)=stress_pimd(1,ii,jj)-quantummass(iatom)*omega2* &
1721 : & (xcart(ii,iatom,iimagep)-xcart(ii,iatom,iimage))* &
1722 8712 : & (xcart(jj,iatom,iimagep)-xcart(jj,iatom,iimage))/volume
1723 : end do
1724 : end do
1725 : end do
1726 : end do
1727 :
1728 : !II-Average of classical pressures
1729 : !1-Kinetic part
1730 312 : do iimage=1,trotter
1731 241 : imass=min(nmass,iimage)
1732 1038 : do iatom=1,natom
1733 3145 : do ii=1,3
1734 9438 : do jj=1,3
1735 : stress_pimd(2,ii,jj)=stress_pimd(2,ii,jj)+ &
1736 8712 : & mass(iatom,imass)*vel(ii,iatom,iimage)*vel(jj,iatom,iimage)/volume
1737 : end do
1738 : end do
1739 : end do
1740 : end do
1741 :
1742 : !2-Contribution from electronic stress
1743 312 : do iimage=1,trotter
1744 1035 : do ii=1,3
1745 3133 : do jj=1,3
1746 2892 : stress_pimd(2,ii,jj)=stress_pimd(2,ii,jj)-stressin(ii,jj,iimage)
1747 : end do
1748 : end do
1749 : end do
1750 284 : do ii=1,3
1751 923 : do jj=1,3
1752 852 : stress_pimd(2,ii,jj)=stress_pimd(2,ii,jj)/dble(trotter)
1753 : end do
1754 : end do
1755 :
1756 : !III-pressure from VIRIAL estimator: stress_pimd(3,:,:)
1757 : !1-kinetic part
1758 : ! do ii=1,3
1759 : ! stress_pimd(3,ii,ii)=dfloat(natom)*kt/volume
1760 : ! end do
1761 :
1762 : !Symmetrize internal pressure
1763 71 : stress_tmp=stress_pimd
1764 284 : stress_pimd(:,2,1)=half*(stress_tmp(:,1,2)+stress_tmp(:,2,1))
1765 284 : stress_pimd(:,1,2)=half*(stress_tmp(:,1,2)+stress_tmp(:,2,1))
1766 284 : stress_pimd(:,3,1)=half*(stress_tmp(:,1,3)+stress_tmp(:,3,1))
1767 284 : stress_pimd(:,1,3)=half*(stress_tmp(:,1,3)+stress_tmp(:,3,1))
1768 284 : stress_pimd(:,2,3)=half*(stress_tmp(:,3,2)+stress_tmp(:,2,3))
1769 284 : stress_pimd(:,3,2)=half*(stress_tmp(:,3,2)+stress_tmp(:,2,3))
1770 :
1771 71 : end subroutine pimd_stresses
1772 : !!***
1773 :
1774 : !----------------------------------------------------------------------
1775 :
1776 : !!****f* m_pimd/pimd_diff_stress
1777 : !! NAME
1778 : !! pimd_diff_stress
1779 : !!
1780 : !! FUNCTION
1781 : !! Compute the difference between the stress tensor and the stress target
1782 : !!
1783 : !! INPUTS
1784 : !! stress_pimd(3,3,3)=stress tensor for PIMD
1785 : !! Last dimension (3) corresponds to 3 different pressure estimators
1786 : !! stress_target(6)=stress target
1787 : !!
1788 : !! OUTPUT
1789 : !! pimd_diff_stress(3,3,3)=difference between stresses and stress target
1790 : !! First dimension (3) corresponds to 3 different pressure estimators
1791 : !!
1792 : !! SIDE EFFECTS
1793 : !!
1794 : !! SOURCE
1795 :
1796 26 : function pimd_diff_stress(stress_pimd,stress_target)
1797 :
1798 : !Arguments ------------------------------------
1799 : !scalars
1800 : !arrays
1801 : real(dp),intent(in) :: stress_pimd(3,3,3),stress_target(6)
1802 : real(dp) :: pimd_diff_stress(3,3)
1803 : !Local variables-------------------------------
1804 : !scalars
1805 : !arrays
1806 : real(dp) :: stress_pimd2(3,3)
1807 :
1808 : !************************************************************************
1809 :
1810 : !Choice: the primitive estimator for pressure is chosen
1811 338 : stress_pimd2(:,:) = stress_pimd(1, :, :)
1812 :
1813 : !+stress_target instead of - because it is translated from stress to pressure tensor
1814 26 : pimd_diff_stress(1,1)=stress_pimd2(1,1)+stress_target(1)
1815 26 : pimd_diff_stress(2,2)=stress_pimd2(2,2)+stress_target(2)
1816 26 : pimd_diff_stress(3,3)=stress_pimd2(3,3)+stress_target(3)
1817 26 : pimd_diff_stress(2,3)=stress_pimd2(2,3)+stress_target(4)
1818 26 : pimd_diff_stress(3,2)=stress_pimd2(3,2)+stress_target(4)
1819 26 : pimd_diff_stress(1,3)=stress_pimd2(1,3)+stress_target(5)
1820 26 : pimd_diff_stress(3,1)=stress_pimd2(3,1)+stress_target(5)
1821 26 : pimd_diff_stress(1,2)=stress_pimd2(1,2)+stress_target(6)
1822 26 : pimd_diff_stress(2,1)=stress_pimd2(2,1)+stress_target(6)
1823 :
1824 : end function pimd_diff_stress
1825 : !!***
1826 :
1827 : !----------------------------------------------------------------------
1828 :
1829 : !!****f* m_pimd/pimd_predict_taylor
1830 : !! NAME
1831 : !! pimd_predict_taylor
1832 : !!
1833 : !! FUNCTION
1834 : !! Predict new atomic positions using a Taylor algorithm (first time step) - for PIMD
1835 : !!
1836 : !! INPUTS
1837 : !! dtion=time step
1838 : !! forces(3,natom,trotter)=PIMD forces on atoms in each cell
1839 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1840 : !! natom=number of atoms
1841 : !! trotter=Trotter number
1842 : !! vel(3,natom,trotter)=velocities of atoms in each cell
1843 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in each cell at t
1844 : !!
1845 : !! OUTPUT
1846 : !! xcart_next(3,natom,trotter)=cartesian coordinates of atoms in each cell at t+dt
1847 : !!
1848 : !! SIDE EFFECTS
1849 : !!
1850 : !! SOURCE
1851 :
1852 7 : subroutine pimd_predict_taylor(dtion,forces,mass,natom,trotter,vel,xcart,xcart_next)
1853 :
1854 : !Arguments ------------------------------------
1855 : !scalars
1856 : integer,intent(in) :: natom,trotter
1857 : real(dp),intent(in) :: dtion
1858 : !arrays
1859 : real(dp),intent(in) :: forces(3,natom,trotter),vel(3,natom,trotter),xcart(3,natom,trotter)
1860 : real(dp),intent(in) :: mass(:,:)
1861 : real(dp),intent(out) :: xcart_next(3,natom,trotter)
1862 : !Local variables-------------------------------
1863 : !scalars
1864 : integer :: iatom,ii,iimage,imass,natom_mass,nmass
1865 : character(len=500) :: msg
1866 : !arrays
1867 :
1868 : !************************************************************************
1869 :
1870 7 : natom_mass=size(mass,1);nmass=size(mass,2)
1871 7 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1872 0 : msg='Wrong dimensions for array mass !'
1873 0 : ABI_BUG(msg)
1874 : end if
1875 :
1876 44 : do iimage=1,trotter
1877 37 : imass=min(nmass,iimage)
1878 122 : do iatom=1,natom
1879 349 : do ii=1,3
1880 : xcart_next(ii,iatom,iimage)=xcart(ii,iatom,iimage) &
1881 : & + half*dtion*dtion*forces(ii,iatom,iimage)/mass(iatom,imass) &
1882 312 : & + dtion*vel(ii,iatom,iimage)
1883 : end do
1884 : end do
1885 : end do
1886 :
1887 7 : end subroutine pimd_predict_taylor
1888 : !!***
1889 :
1890 : !----------------------------------------------------------------------
1891 :
1892 : !!****f* m_pimd/pimd_predict_verlet
1893 : !! NAME
1894 : !! pimd_predict_verlet
1895 : !!
1896 : !! FUNCTION
1897 : !! Predict new atomic positions using a Verlet algorithm - for PIMD
1898 : !!
1899 : !! INPUTS
1900 : !! dtion=time step
1901 : !! forces(3,natom,trotter)=PIMD forces on atoms in each cell
1902 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
1903 : !! natom=number of atoms
1904 : !! trotter=Trotter number
1905 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in each cell at t
1906 : !! xcart_prev(3,natom,trotter)=cartesian coordinates of atoms in each cell at t-dt
1907 : !!
1908 : !! OUTPUT
1909 : !! xcart_next(3,natom,trotter)=cartesian coordinates of atoms in each cell at t+dt
1910 : !!
1911 : !! SIDE EFFECTS
1912 : !!
1913 : !! SOURCE
1914 :
1915 235 : subroutine pimd_predict_verlet(dtion,forces,mass,natom,trotter,xcart,xcart_next,xcart_prev)
1916 :
1917 : !Arguments ------------------------------------
1918 : !scalars
1919 : integer,intent(in) :: natom,trotter
1920 : real(dp),intent(in) :: dtion
1921 : !arrays
1922 : real(dp),intent(in) :: forces(3,natom,trotter)
1923 : real(dp),intent(in) :: xcart(3,natom,trotter),xcart_prev(3,natom,trotter)
1924 : real(dp),intent(in) :: mass(:,:)
1925 : real(dp),intent(out) :: xcart_next(3,natom,trotter)
1926 : !Local variables-------------------------------
1927 : !scalars
1928 : integer :: iatom,ii,iimage,imass,natom_mass,nmass
1929 : character(len=500) :: msg
1930 : !arrays
1931 :
1932 : !************************************************************************
1933 :
1934 235 : natom_mass=size(mass,1);nmass=size(mass,2)
1935 235 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
1936 0 : msg='Wrong dimensions for array mass !'
1937 0 : ABI_BUG(msg)
1938 : end if
1939 :
1940 1519 : do iimage=1,trotter
1941 1284 : imass=min(nmass,iimage)
1942 4687 : do iatom=1,natom
1943 13956 : do ii=1,3
1944 : xcart_next(ii,iatom,iimage)= &
1945 : & two*xcart(ii,iatom,iimage) &
1946 : & - xcart_prev(ii,iatom,iimage) &
1947 12672 : & + dtion*dtion*forces(ii,iatom,iimage)/mass(iatom,imass)
1948 : end do
1949 : end do
1950 : end do
1951 :
1952 235 : end subroutine pimd_predict_verlet
1953 : !!***
1954 :
1955 : !----------------------------------------------------------------------
1956 :
1957 : !!****f* m_pimd/pimd_predict_vel
1958 : !! NAME
1959 : !! pimd_predict_vel
1960 : !!
1961 : !! FUNCTION
1962 : !! Predict an estimation of the velocities at next time time step
1963 : !! from the positions of 3 consecutive time steps
1964 : !!
1965 : !! INPUTS
1966 : !! dtion=time step
1967 : !! itime=time step index
1968 : !! natom=number of atoms
1969 : !! trotter=Trotter number
1970 : !! pitransform=integer selecting the transformation of coordinates
1971 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms in each cell at t
1972 : !! xcart_next(3,natom,trotter)=cartesian coordinates of atoms in each cell at t+dt
1973 : !! xcart_prev(3,natom,trotter)=cartesian coordinates of atoms in each cell at t-dt
1974 : !!
1975 : !! OUTPUT
1976 : !! vel(3,natom,trotter)=estimation of velocities at t+dt
1977 : !!
1978 : !! SIDE EFFECTS
1979 : !!
1980 : !! SOURCE
1981 :
1982 44 : subroutine pimd_predict_vel(dtion,itime,natom,trotter,pitransform,xcart,xcart_next,xcart_prev,vel)
1983 :
1984 : !Arguments ------------------------------------
1985 : !scalars
1986 : integer,intent(in) :: itime,natom,pitransform,trotter
1987 : real(dp),intent(in) :: dtion
1988 : !arrays
1989 : real(dp),intent(inout) :: xcart(3,natom,trotter),xcart_next(3,natom,trotter),xcart_prev(3,natom,trotter)
1990 : real(dp),intent(out) :: vel(3,natom,trotter)
1991 : !Local variables-------------------------------
1992 : !scalars
1993 : integer :: iatom,ii,iimage
1994 :
1995 : !************************************************************************
1996 :
1997 : !Set the coordinates in the transformed representation
1998 44 : if (pitransform>0) then
1999 10 : call pimd_coord_transform(xcart_next,1,natom,pitransform,trotter)
2000 10 : call pimd_coord_transform(xcart,1,natom,pitransform,trotter)
2001 10 : call pimd_coord_transform(xcart_prev,1,natom,pitransform,trotter)
2002 : end if
2003 :
2004 44 : if (itime>1) then
2005 214 : do iimage=1,trotter
2006 700 : do iatom=1,natom
2007 2121 : do ii=1,3
2008 : vel(ii,iatom,iimage)= &
2009 : & (three*xcart_next(ii,iatom,iimage) &
2010 : & -four*xcart(ii,iatom,iimage) &
2011 : & +xcart_prev(ii,iatom,iimage)) &
2012 1944 : & / (two*dtion)
2013 : end do
2014 : end do
2015 : end do
2016 : else
2017 44 : do iimage=1,trotter
2018 122 : do iatom=1,natom
2019 349 : do ii=1,3
2020 312 : vel(ii,iatom,iimage)=(xcart_next(ii,iatom,iimage)-xcart(ii,iatom,iimage))/dtion
2021 : end do
2022 : end do
2023 : end do
2024 : end if
2025 :
2026 : !Set back the coordinates
2027 44 : if (pitransform>0) then
2028 10 : call pimd_coord_transform(xcart_next,-1,natom,pitransform,trotter)
2029 10 : call pimd_coord_transform(xcart,-1,natom,pitransform,trotter)
2030 10 : call pimd_coord_transform(xcart_prev,-1,natom,pitransform,trotter)
2031 : end if
2032 :
2033 44 : end subroutine pimd_predict_vel
2034 : !!***
2035 :
2036 : !----------------------------------------------------------------------
2037 :
2038 : !!****f* m_pimd/pimd_predict_velcell
2039 : !! NAME
2040 : !! pimd_predict_velcell
2041 : !!
2042 : !! FUNCTION
2043 : !! Predict an estimation of the cell velocities at next time time step
2044 : !! from the cell at 3 consecutive time steps
2045 : !!
2046 : !! INPUTS
2047 : !! dtion=time step
2048 : !! itime=time step index
2049 : !! pitransform=integer selecting the transformation of coordinates
2050 : !! rprimd(3,3)=cell coordinates at t
2051 : !! rprimd_next(3,3)=cell coordinates at t+dt
2052 : !! rprimd_prev(3,3)=cell coordinates at t-dt
2053 : !!
2054 : !! OUTPUT
2055 : !! vel_cell(3,3)=estimation of cell velocities at t+dt
2056 : !!
2057 : !! SIDE EFFECTS
2058 : !!
2059 : !! SOURCE
2060 :
2061 4 : subroutine pimd_predict_velcell(dtion,itime,rprimd,rprimd_next,rprimd_prev,vel_cell)
2062 :
2063 : !Arguments ------------------------------------
2064 : !scalars
2065 : integer,intent(in) :: itime
2066 : real(dp),intent(in) :: dtion
2067 : !arrays
2068 : real(dp),intent(in) :: rprimd(3,3),rprimd_next(3,3),rprimd_prev(3,3)
2069 : real(dp),intent(out) :: vel_cell(3,3)
2070 : !Local variables-------------------------------
2071 : !scalars
2072 : integer :: ii,jj
2073 :
2074 : !************************************************************************
2075 :
2076 4 : if (itime>1) then
2077 16 : do jj=1,3
2078 52 : do ii=1,3
2079 : vel_cell(ii,jj)= &
2080 48 : & (three*rprimd_next(ii,jj)-four*rprimd(ii,jj)+rprimd_prev(ii,jj))/(two*dtion)
2081 : end do
2082 : end do
2083 : else
2084 0 : do jj=1,3
2085 0 : do ii=1,3
2086 0 : vel_cell(ii,jj)=(rprimd_next(ii,jj)-rprimd(ii,jj))/dtion
2087 : end do
2088 : end do
2089 : end if
2090 :
2091 4 : end subroutine pimd_predict_velcell
2092 : !!***
2093 :
2094 : !----------------------------------------------------------------------
2095 :
2096 : !!****f* m_pimd/pimd_nosehoover_propagate
2097 : !! NAME
2098 : !! pimd_nosehoover_propagate
2099 : !!
2100 : !! FUNCTION
2101 : !! Propagate thermostat variables (Nose-Hoover algorithm) - for PIMD
2102 : !!
2103 : !! INPUTS
2104 : !! dtion=time step
2105 : !! dzeta(3,natom,trotter,nnos)=time derivative of zeta at time t
2106 : !! itimimage=index of time step
2107 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
2108 : !! natom=number of atoms
2109 : !! nnos=number of thermostats
2110 : !! qmass(nnos)=masses of thermostats
2111 : !! temperature=temperature
2112 : !! transform=coordinate transformation:
2113 : !! 0: no tranformation
2114 : !! 1: normal mode transformation
2115 : !! 2: staging transformation
2116 : !! trotter=Trotter number
2117 : !! vel(3,natom,trotter)=velocities of atoms in each cell
2118 : !! zeta(3,natom,trotter,nnos)=variables of thermostats, in (atomic time unit)^(-1)
2119 : !! used only when no coordinate transformation is applied (transfom==0)
2120 : !! at time t
2121 : !! zeta_prev(3,natom,trotter,nnos)=previous value of zeta (t-dt)
2122 : !!
2123 : !! OUTPUT
2124 : !! zeta_next(3,natom,trotter,nnos)=next value of zeta (t+dt)
2125 : !!
2126 : !! SIDE EFFECTS
2127 : !!
2128 : !! SOURCE
2129 :
2130 132 : subroutine pimd_nosehoover_propagate(dtion,dzeta,mass,natom,nnos,qmass,temperature,&
2131 132 : & trotter,vel,zeta,zeta_next,zeta_prev,itimimage,transform)
2132 :
2133 : !Arguments ------------------------------------
2134 : !scalars
2135 : integer,intent(in) :: itimimage,natom,nnos,transform,trotter
2136 : real(dp),intent(in) :: dtion,temperature
2137 : !arrays
2138 : real(dp),intent(in) :: qmass(nnos),vel(3,natom,trotter)
2139 : real(dp),intent(in) :: mass(:,:)
2140 : real(dp),intent(in) :: dzeta(3,natom,trotter,nnos),zeta_prev(3,natom,trotter,nnos)
2141 : real(dp),intent(in) :: zeta(3,natom,trotter,nnos)
2142 : real(dp),intent(out) :: zeta_next(3,natom,trotter,nnos)
2143 : !Local variables-------------------------------
2144 : !scalars
2145 : integer :: iatom,ii,iimage,inos,natom_mass,nmass
2146 : real(dp) :: kt
2147 : character(len=500) :: msg
2148 : !arrays
2149 132 : real(dp),allocatable :: thermforces(:,:,:,:)
2150 :
2151 : !************************************************************************
2152 :
2153 132 : natom_mass=size(mass,1);nmass=size(mass,2)
2154 132 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
2155 0 : msg='Wrong dimensions for array mass !'
2156 0 : ABI_BUG(msg)
2157 : end if
2158 132 : if (nnos<3) then
2159 0 : msg='Not available for nnos<3 !'
2160 0 : ABI_BUG(msg)
2161 : end if
2162 :
2163 132 : kt=temperature*kb_HaK
2164 660 : ABI_MALLOC(thermforces,(3,natom,trotter,nnos))
2165 :
2166 : !forces on the thermostats
2167 792 : do inos=1,nnos
2168 792 : if(inos==1)then
2169 924 : do iimage=1,trotter
2170 2508 : do iatom=1,natom
2171 7128 : do ii=1,3
2172 1584 : select case(transform)
2173 : case(0)
2174 1512 : thermforces(ii,iatom,iimage,1)=mass(iatom,1)*(vel(ii,iatom,iimage)**2)-kt
2175 : case(1)
2176 1620 : thermforces(ii,iatom,iimage,1)=mass(iatom,iimage)*(vel(ii,iatom,iimage)**2)-kt
2177 : case(2)
2178 4752 : thermforces(ii,iatom,iimage,1)=mass(iatom,iimage)*(vel(ii,iatom,iimage)**2)-kt
2179 : end select
2180 : end do
2181 : end do
2182 : end do
2183 528 : elseif(inos==(nnos-1))then
2184 924 : do iimage=1,trotter
2185 2508 : do iatom=1,natom
2186 7128 : do ii=1,3
2187 : thermforces(ii,iatom,iimage,inos)=&
2188 : & (qmass(nnos-2)*(dzeta(ii,iatom,iimage,nnos-2)**2)-kt) + &
2189 6336 : & (qmass(nnos )*(dzeta(ii,iatom,iimage,nnos) **2)-kt)
2190 : end do
2191 : end do
2192 : end do
2193 396 : elseif(inos==nnos)then
2194 924 : do iimage=1,trotter
2195 2508 : do iatom=1,natom
2196 7128 : do ii=1,3
2197 : thermforces(ii,iatom,iimage,inos)=&
2198 6336 : & qmass(nnos-1)*(dzeta(ii,iatom,iimage,nnos-1)**2)-kt
2199 : end do
2200 : end do
2201 : end do
2202 : else
2203 1848 : do iimage=1,trotter
2204 5016 : do iatom=1,natom
2205 14256 : do ii=1,3
2206 : thermforces(ii,iatom,iimage,inos)=&
2207 12672 : & qmass(inos-1)*(dzeta(ii,iatom,iimage,inos-1)**2)-kt
2208 : end do
2209 : end do
2210 : end do
2211 : end if
2212 : end do
2213 :
2214 132 : select case(itimimage)
2215 : case(1) !taylor
2216 :
2217 18 : do inos=1,nnos
2218 18 : if(inos==1)then
2219 : zeta_next(:,:,:,1)=zeta(:,:,:,1)+ dzeta(:,:,:,1)*dtion + &
2220 : & (thermforces(:,:,:,1)-qmass(1)*dzeta(:,:,:,1)*dzeta(:,:,:,2))* &
2221 165 : & dtion*dtion/(two*qmass(1))
2222 12 : elseif(inos==(nnos-1))then
2223 : zeta_next(:,:,:,inos)=zeta(:,:,:,inos)+ dzeta(:,:,:,inos)*dtion + &
2224 : & (thermforces(:,:,:,inos)-qmass(inos)*dzeta(:,:,:,inos)*dzeta(:,:,:,nnos))* &
2225 165 : & dtion*dtion/(two*qmass(inos))
2226 9 : elseif(inos==nnos)then
2227 : zeta_next(:,:,:,inos)=zeta(:,:,:,inos)+ dzeta(:,:,:,inos)*dtion + &
2228 : & (thermforces(:,:,:,inos)-qmass(inos)*dzeta(:,:,:,nnos-1)*dzeta(:,:,:,nnos))* &
2229 165 : & dtion*dtion/(two*qmass(inos))
2230 : else
2231 : zeta_next(:,:,:,inos)=zeta(:,:,:,inos)+ dzeta(:,:,:,inos)*dtion + &
2232 : & (thermforces(:,:,:,inos)-qmass(inos)*dzeta(:,:,:,inos)*dzeta(:,:,:,inos+1))* &
2233 330 : & dtion*dtion/(two*qmass(inos))
2234 : end if
2235 : end do
2236 :
2237 : case default !verlet
2238 :
2239 906 : do inos=1,nnos
2240 774 : if(inos==1)then
2241 : zeta_next(:,:,:,1)=two*zeta(:,:,:,1) - zeta_prev(:,:,:,1) + &
2242 : & (thermforces(:,:,:,1)-qmass(1)*dzeta(:,:,:,1)*dzeta(:,:,:,2))* &
2243 7095 : & dtion*dtion/qmass(1)
2244 516 : elseif(inos==(nnos-1))then
2245 : zeta_next(:,:,:,inos)=two*zeta(:,:,:,inos) - zeta_prev(:,:,:,inos) + &
2246 : & (thermforces(:,:,:,inos)-qmass(inos)*dzeta(:,:,:,inos)*dzeta(:,:,:,nnos))* &
2247 7095 : & dtion*dtion/qmass(inos)
2248 387 : elseif(inos==nnos)then
2249 : zeta_next(:,:,:,inos)=two*zeta(:,:,:,inos) - zeta_prev(:,:,:,inos) + &
2250 : & (thermforces(:,:,:,inos)-qmass(inos)*dzeta(:,:,:,nnos-1)*dzeta(:,:,:,nnos))* &
2251 7095 : & dtion*dtion/qmass(inos)
2252 : else
2253 : zeta_next(:,:,:,inos)=two*zeta(:,:,:,inos) - zeta_prev(:,:,:,inos) + &
2254 : & (thermforces(:,:,:,inos)-qmass(inos)*dzeta(:,:,:,inos)*dzeta(:,:,:,inos+1))* &
2255 14190 : & dtion*dtion/qmass(inos)
2256 : end if
2257 : end do
2258 :
2259 : end select
2260 :
2261 132 : ABI_FREE(thermforces)
2262 :
2263 132 : end subroutine pimd_nosehoover_propagate
2264 : !!***
2265 :
2266 : !----------------------------------------------------------------------
2267 :
2268 : !!****f* m_pimd/pimd_coord_transform
2269 : !! NAME
2270 : !! pimd_coord_transform
2271 : !!
2272 : !! FUNCTION
2273 : !! Apply a coordinate transformation on a given vector field
2274 : !! (defined for each atom in in cell) - for PIMD
2275 : !! Possible choices for the transformation:
2276 : !! 0: no transformation
2277 : !! 1: normal mode tranformation
2278 : !! 2: staging transformation
2279 : !!
2280 : !! INPUTS
2281 : !! ioption=option given the direction of the transformation
2282 : !! +1: from primitive coordinates to transformed coordinates
2283 : !! -1: from transformed coordinates to primitive coordinates
2284 : !! natom=number of atoms
2285 : !! transform=coordinate transformation:
2286 : !! 0: no tranformation
2287 : !! 1: normal mode transformation
2288 : !! 2: staging transformation
2289 : !! trotter=Trotter number
2290 : !!
2291 : !! OUTPUT
2292 : !!
2293 : !! SIDE EFFECTS
2294 : !! array(3,natom,trotter)=array to be transformed
2295 : !!
2296 : !! SOURCE
2297 :
2298 253 : subroutine pimd_coord_transform(array,ioption,natom,transform,trotter)
2299 :
2300 : !Arguments ------------------------------------
2301 : !scalars
2302 : integer,intent(in) :: ioption,natom,transform,trotter
2303 : !arrays
2304 : real(dp),intent(inout) :: array(3,natom,trotter)
2305 : !Local variables-------------------------------
2306 : !scalars
2307 : integer :: iatom,ii,iimage,iimagem,iimagep,iimage2,ll
2308 : !arrays
2309 253 : real(dp),allocatable :: array_temp(:,:,:)
2310 253 : real(dp),allocatable :: nrm(:,:)
2311 :
2312 : !************************************************************************
2313 :
2314 : !=== No transformation ===================================================
2315 253 : if (transform==0) then
2316 :
2317 : return
2318 :
2319 : !=== Normal mode transformation ==========================================
2320 156 : else if (transform==1) then
2321 :
2322 : ! ---------------- From primitive to transformed coordinates ------------
2323 24 : if (ioption==+1) then
2324 36 : ABI_MALLOC(array_temp,(3,natom,trotter))
2325 :
2326 81 : array_temp(:,:,1)=zero
2327 63 : do iimage=1,trotter
2328 495 : array_temp(:,:,1)=array_temp(:,:,1)+array(:,:,iimage)
2329 : end do
2330 :
2331 27 : do ll=2,trotter/2
2332 162 : array_temp(:,:,2*ll-2)=zero
2333 162 : array_temp(:,:,2*ll-1)=zero
2334 135 : do iimage=1,trotter
2335 : array_temp(:,:,2*ll-2)=array_temp(:,:,2*ll-2)+array(:,:,iimage)* &
2336 972 : & cos(two_pi*dble((iimage-1)*(ll-1))/dble(trotter))
2337 : array_temp(:,:,2*ll-1)=array_temp(:,:,2*ll-1)-array(:,:,iimage)* &
2338 990 : & sin(two_pi*dble((iimage-1)*(ll-1))/dble(trotter))
2339 : end do
2340 : end do
2341 :
2342 81 : array_temp(:,:,trotter)=zero
2343 63 : do iimage=1,trotter
2344 : array_temp(:,:,trotter)=array_temp(:,:,trotter)+&
2345 495 : & array(:,:,iimage)*dble((-1)**(iimage-1))
2346 : end do
2347 :
2348 495 : array=array_temp/dble(trotter)
2349 :
2350 9 : ABI_FREE(array_temp)
2351 :
2352 : ! ---------------- From transformed to primitive coordinates ------------
2353 15 : else if (ioption==-1) then
2354 :
2355 60 : ABI_MALLOC(array_temp,(3,natom,trotter)) !real part
2356 60 : ABI_MALLOC(nrm,(trotter,trotter)) !real part
2357 :
2358 105 : do iimage=1,trotter
2359 90 : nrm(iimage,1)=one
2360 105 : nrm(iimage,trotter)=dble((-1)**(iimage-1))
2361 : end do
2362 :
2363 45 : do ll=2,trotter/2
2364 225 : do iimage=1,trotter
2365 : nrm(iimage,2*ll-2)= two*cos(two_pi*dble((ll-1)* &
2366 180 : & (iimage-1))/dble(trotter))
2367 : nrm(iimage,2*ll-1)=-two*sin(two_pi*dble((ll-1)* &
2368 210 : & (iimage-1))/dble(trotter))
2369 : end do
2370 : end do
2371 :
2372 105 : do iimage=1,trotter
2373 810 : array_temp(:,:,iimage)=zero
2374 645 : do ll=1,trotter
2375 4950 : array_temp(:,:,iimage)=array_temp(:,:,iimage)+nrm(iimage,ll)*array(:,:,ll)
2376 : end do
2377 : end do
2378 825 : array=array_temp
2379 :
2380 15 : ABI_FREE(array_temp)
2381 15 : ABI_FREE(nrm)
2382 :
2383 : end if ! ioption
2384 :
2385 : !=== Staging transformation ==============================================
2386 132 : else if (transform==2) then
2387 :
2388 : ! ---------------- From primitive to transformed coordinates ------------
2389 132 : if (ioption==+1) then
2390 :
2391 228 : ABI_MALLOC(array_temp,(3,natom,trotter))
2392 3135 : array_temp=zero
2393 399 : do iimage=1,trotter
2394 342 : iimagep=iimage+1;if(iimage==trotter) iimagep=1
2395 342 : iimagem=iimage-1;if(iimage==1) iimagem=trotter
2396 1083 : do iatom=1,natom
2397 3078 : do ii=1,3
2398 2736 : array_temp(ii,iatom,iimage)=(dble(iimagem)*array(ii,iatom,iimagep)+array(ii,iatom,1))/dble(iimage)
2399 : end do
2400 : end do
2401 : end do
2402 57 : if (trotter>1) then
2403 342 : do iimage=2,trotter
2404 912 : do iatom=1,natom
2405 2565 : do ii=1,3
2406 2280 : array(ii,iatom,iimage)=array(ii,iatom,iimage)-array_temp(ii,iatom,iimage)
2407 : end do
2408 : end do
2409 : end do
2410 : end if
2411 57 : ABI_FREE(array_temp)
2412 :
2413 : ! ---------------- From transformed to primitive coordinates ------------
2414 75 : else if (ioption==-1) then
2415 :
2416 300 : ABI_MALLOC(array_temp,(3,natom,trotter))
2417 4125 : array_temp=zero
2418 525 : do iimage=1,trotter
2419 1425 : do iatom=1,natom
2420 4050 : do ii=1,3
2421 3600 : array_temp(ii,iatom,iimage)=array(ii,iatom,1)
2422 : end do
2423 : end do
2424 : end do
2425 75 : if (trotter>1) then
2426 450 : do iimage=2,trotter
2427 1200 : do iatom=1,natom
2428 3375 : do ii=1,3
2429 9750 : do iimage2=iimage,trotter
2430 : array_temp(ii,iatom,iimage)=array_temp(ii,iatom,iimage) &
2431 9000 : & +array(ii,iatom,iimage2)*(dble(iimage-1))/(dble(iimage2-1))
2432 : end do
2433 : end do
2434 : end do
2435 : end do
2436 : end if
2437 4125 : array(:,:,:)=array_temp(:,:,:)
2438 75 : ABI_FREE(array_temp)
2439 :
2440 : end if ! ioption
2441 :
2442 : end if ! transform
2443 :
2444 : end subroutine pimd_coord_transform
2445 : !!***
2446 :
2447 : !----------------------------------------------------------------------
2448 :
2449 : !!****f* m_pimd/pimd_force_transform
2450 : !! NAME
2451 : !! pimd_force_transform
2452 : !!
2453 : !! FUNCTION
2454 : !! Apply a coordinate transformation on forces (defined for each atom in in cell) - for PIMD
2455 : !! Possible choices for the transformation:
2456 : !! 0: no transformation
2457 : !! 1: normal mode tranformation
2458 : !! 2: staging transformation
2459 : !!
2460 : !! INPUTS
2461 : !! ioption=option given the direction of the transformation
2462 : !! +1: from primitive coordinates to transformed coordinates
2463 : !! -1: from transformed coordinates to primitive coordinates
2464 : !! natom=number of atoms
2465 : !! transform=coordinate transformation:
2466 : !! 0: no tranformation
2467 : !! 1: normal mode transformation
2468 : !! 2: staging transformation
2469 : !! trotter=Trotter number
2470 : !!
2471 : !! OUTPUT
2472 : !!
2473 : !! SIDE EFFECTS
2474 : !! forces(3,natom,trotter)=array containing forces
2475 : !!
2476 : !! NOTES
2477 : !! Back transformation (ioption=-1) not implemented !
2478 : !!
2479 : !! SOURCE
2480 :
2481 40 : subroutine pimd_force_transform(forces,ioption,natom,transform,trotter)
2482 :
2483 : !Arguments ------------------------------------
2484 : !scalars
2485 : integer,intent(in) :: ioption,natom,transform,trotter
2486 : !arrays
2487 : real(dp),intent(inout) :: forces(3,natom,trotter)
2488 : !Local variables-------------------------------
2489 : !scalars
2490 : integer :: iatom,ii,iimage,ll
2491 : character(len=500) :: msg
2492 : !arrays
2493 40 : real(dp),allocatable :: forces_temp(:,:,:),nrm(:,:)
2494 :
2495 : !************************************************************************
2496 :
2497 40 : if (ioption==-1) then
2498 0 : msg='Back transformation not implemented !'
2499 0 : ABI_BUG(msg)
2500 : end if
2501 :
2502 : !=== No transformation ===================================================
2503 40 : if (transform==0) then
2504 :
2505 : return
2506 :
2507 : !=== Normal mode transformation ==========================================
2508 20 : else if (transform==1) then
2509 :
2510 : !normal mode forces
2511 20 : ABI_MALLOC(forces_temp,(3,natom,trotter))
2512 20 : ABI_MALLOC(nrm,(trotter,trotter))
2513 :
2514 35 : do iimage=1,trotter
2515 30 : nrm(iimage,1)=one
2516 35 : nrm(iimage,trotter)=dble((-1)**(iimage-1))
2517 : end do
2518 :
2519 15 : do ll=2,trotter/2
2520 75 : do iimage=1,trotter
2521 : nrm(iimage,2*ll-2)= two*cos(two_pi*dble((ll-1)* &
2522 60 : & (iimage-1))/dble(trotter))
2523 : nrm(iimage,2*ll-1)=-two*sin(two_pi*dble((ll-1)* &
2524 70 : & (iimage-1))/dble(trotter))
2525 : end do
2526 : end do
2527 :
2528 35 : do ll=1,trotter
2529 270 : forces_temp(:,:,ll)=zero
2530 215 : do iimage=1,trotter
2531 1650 : forces_temp(:,:,ll)=forces_temp(:,:,ll)+nrm(iimage,ll)*forces(:,:,iimage)
2532 : end do
2533 : end do
2534 :
2535 275 : forces=forces_temp
2536 :
2537 5 : ABI_FREE(forces_temp)
2538 5 : ABI_FREE(nrm)
2539 :
2540 : !=== Staging transformation ==============================================
2541 15 : else if (transform==2) then
2542 :
2543 : !staging forces
2544 60 : ABI_MALLOC(forces_temp,(3,natom,trotter))
2545 825 : forces_temp=zero
2546 105 : do iimage=1,trotter
2547 285 : do iatom=1,natom
2548 810 : do ii=1,3
2549 720 : forces_temp(ii,iatom,1)=forces_temp(ii,iatom,1)+forces(ii,iatom,iimage)
2550 : end do
2551 : end do
2552 : end do
2553 15 : if (trotter>1) then
2554 90 : do iimage=2,trotter
2555 240 : do iatom=1,natom
2556 675 : do ii=1,3
2557 : forces_temp(ii,iatom,iimage)=forces(ii,iatom,iimage) &
2558 600 : & +forces_temp(ii,iatom,iimage-1)*(dble(iimage-2)/dble(iimage-1))
2559 : end do
2560 : end do
2561 : end do
2562 : end if
2563 825 : forces=forces_temp
2564 15 : ABI_FREE(forces_temp)
2565 :
2566 : end if ! transform
2567 :
2568 : end subroutine pimd_force_transform
2569 : !!***
2570 :
2571 : !----------------------------------------------------------------------
2572 :
2573 : !!****f* m_pimd/pimd_apply_constraint
2574 : !! NAME
2575 : !! pimd_apply_constraint
2576 : !!
2577 : !! FUNCTION
2578 : !! Modify forces to take into account an holonomic constraint
2579 : !! according to "pimd_constraint" parameter
2580 : !! Available constraints:
2581 : !! 0: no constraint
2582 : !! 1: linear combination of coordinates
2583 : !!
2584 : !! INPUTS
2585 : !! constraint=type of constraint to be applied
2586 : !! mass(natom)=fictitious masses of atoms
2587 : !! natom=number of atoms
2588 : !! trotter=Trotter number
2589 : !! wtatcon(3,natom)=weights for atomic constraints
2590 : !! xcart(3,natom,trotter)=cartesian coordinates of atoms
2591 : !!
2592 : !! OUTPUT
2593 : !! constraint_output(2)=several (real) data to be output
2594 : !! when a constraint has been applied
2595 : !!
2596 : !! SIDE EFFECTS
2597 : !! forces(3,natom,trotter)=array containing forces
2598 : !!
2599 : !! SOURCE
2600 :
2601 268 : subroutine pimd_apply_constraint(constraint,constraint_output,forces,mass,natom,&
2602 268 : & trotter,wtatcon,xcart)
2603 :
2604 : !Arguments ------------------------------------
2605 : !scalars
2606 : integer,intent(in) :: constraint,natom,trotter
2607 : !arrays
2608 : real(dp),intent(in) :: mass(natom),wtatcon(3,natom),xcart(3,natom,trotter)
2609 : real(dp),intent(out) :: constraint_output(2)
2610 : real(dp),intent(inout) :: forces(3,natom,trotter)
2611 : !Local variables-------------------------------
2612 : !scalars
2613 : integer :: iatom,ii,iimage
2614 : real(dp) :: af,lambda_cst,masstot,one_over_trotter,xcart_centroid,zz
2615 : !character(len=500) :: msg
2616 : !arrays
2617 : real(dp) :: force_centroid(3),lambda_com(3),mat(3,3),matinv(3,3),vec(3),weightsum(3)
2618 :
2619 : !************************************************************************
2620 :
2621 :
2622 510 : select case(constraint)
2623 :
2624 : !=== No constraint =======================================================
2625 : case(0)
2626 :
2627 242 : constraint_output(:)=zero
2628 242 : return
2629 :
2630 : !=== Linear combination of centroid coordinates ==========================
2631 : case(1)
2632 :
2633 : ! Some useful quantities
2634 182 : masstot=sum(mass)*dble(trotter)
2635 572 : weightsum(:)=sum(wtatcon,dim=2)*dble(trotter)
2636 26 : zz=zero;af=zero;force_centroid=zero
2637 156 : do iimage=1,trotter
2638 936 : do iatom=1,natom
2639 3250 : do ii=1,3
2640 2340 : force_centroid(ii)=force_centroid(ii)+forces(ii,iatom,iimage)
2641 2340 : af=af+wtatcon(ii,iatom)*forces(ii,iatom,iimage)/mass(iatom)
2642 3120 : zz=zz+wtatcon(ii,iatom)**2/mass(iatom)
2643 : end do
2644 : end do
2645 : end do
2646 104 : vec(:)=force_centroid(:)-weightsum(:)*af/zz
2647 104 : do ii=1,3
2648 312 : mat(:,ii)=-weightsum(:)*weightsum(ii)/zz
2649 104 : mat(ii,ii)=mat(ii,ii)+masstot
2650 : end do
2651 26 : call matr3inv(mat,matinv)
2652 :
2653 : !Calculation of a Lagrange multipliers:
2654 : ! lambda_cst: to apply the constraint
2655 : ! lambda_com: to maintain the position of the center of mass
2656 338 : lambda_com(:)=matmul(matinv,vec)
2657 104 : lambda_cst=(af-dot_product(weightsum,lambda_com))*dble(trotter)/zz
2658 :
2659 : !Modification of forces
2660 26 : one_over_trotter=one/dble(trotter)
2661 156 : do iimage=1,trotter
2662 936 : do iatom=1,natom
2663 3250 : do ii=1,3
2664 : forces(ii,iatom,iimage)=forces(ii,iatom,iimage) &
2665 : & -lambda_cst*wtatcon(ii,iatom)*one_over_trotter &
2666 3120 : & -lambda_com(ii)*mass(iatom)
2667 : end do
2668 : end do
2669 : end do
2670 :
2671 : !Computation of relevant outputs
2672 26 : constraint_output(:)=zero
2673 : !1-Reaction coordinate
2674 182 : do iatom=1,natom
2675 650 : do ii=1,3
2676 : xcart_centroid=zero
2677 2808 : do iimage=1,trotter
2678 2808 : xcart_centroid=xcart_centroid+xcart(ii,iatom,iimage)
2679 : end do
2680 624 : constraint_output(1)=constraint_output(1)+xcart_centroid*wtatcon(ii,iatom)
2681 : end do
2682 : end do
2683 26 : constraint_output(1)=constraint_output(1)/dble(trotter)
2684 : !2-Force on reaction coordinate
2685 294 : constraint_output(2)=-lambda_cst
2686 :
2687 : end select
2688 :
2689 : end subroutine pimd_apply_constraint
2690 : !!***
2691 :
2692 : !----------------------------------------------------------------------
2693 :
2694 : !!****f* m_pimd/pimd_mass_spring
2695 : !! NAME
2696 : !! pimd_mass_spring
2697 : !!
2698 : !! FUNCTION
2699 : !! Compute masses and spring constants for PIMD. Eventually apply a coordinate transformation.
2700 : !! Possible choices for the transformation:
2701 : !! 0: no transformation
2702 : !! 1: normal mode tranformation
2703 : !! 2: staging transformation
2704 : !!
2705 : !! INPUTS
2706 : !! inertmass(natom)=fictitious masses of atoms
2707 : !! kt=kT constant
2708 : !! natom=number of atoms
2709 : !! quantummass(natom)=true masses of atoms
2710 : !! transform=coordinate transformation:
2711 : !! 0: no tranformation
2712 : !! 1: normal mode transformation
2713 : !! 2: staging transformation
2714 : !! trotter=Trotter number
2715 : !!
2716 : !! OUTPUT
2717 : !!
2718 : !! SIDE EFFECTS
2719 : !! mass(natom,mass_dim)=masses of atoms (mass_dim=1 or trotter)
2720 : !! spring(natom,mass_dim)=spring constants of atoms (mass_dim=1 or trotter)
2721 : !!
2722 : !! NOTES
2723 : !! Back transformation (ioption=-1) not implemented !
2724 : !!
2725 : !! SOURCE
2726 :
2727 45 : subroutine pimd_mass_spring(inertmass,kt,mass,natom,quantummass,spring,transform,trotter)
2728 :
2729 : !Arguments ------------------------------------
2730 : !scalars
2731 : integer,intent(in) :: natom,transform,trotter
2732 : real(dp),intent(in) :: kt
2733 : !arrays
2734 : real(dp),intent(in) :: inertmass(natom),quantummass(natom)
2735 : real(dp),intent(out) :: mass(:,:),spring(:,:)
2736 : !Local variables-------------------------------
2737 : !scalars
2738 : integer :: iimage,kk,natom_mass,natom_spring,nmass,nspring
2739 : real(dp) :: gammasquare
2740 : character(len=500) :: msg
2741 : !arrays
2742 45 : real(dp),allocatable :: mass_temp(:,:),lambda(:)
2743 :
2744 : !************************************************************************
2745 :
2746 45 : natom_mass =size(mass ,1);nmass =size(mass ,2)
2747 45 : natom_spring=size(spring,1);nspring=size(spring,2)
2748 45 : if (natom/=natom_mass.or.(nmass/=1.and.nmass/=trotter)) then
2749 0 : msg='Wrong dimensions for array mass !'
2750 0 : ABI_BUG(msg)
2751 : end if
2752 45 : if (natom/=natom_spring.or.(nspring/=1.and.nspring/=trotter)) then
2753 0 : msg='Wrong dimensions for array spring !'
2754 0 : ABI_BUG(msg)
2755 : end if
2756 :
2757 : !=== No transformation ===================================================
2758 45 : if (transform==0) then
2759 : !2nd dim of mass and spring = 1
2760 135 : mass(1:natom,1)=inertmass(1:natom)
2761 135 : spring(1:natom,1)=quantummass(1:natom)*dble(trotter)*kt*kt
2762 :
2763 : !=== Normal mode transformation ==========================================
2764 20 : else if (transform==1) then
2765 :
2766 15 : ABI_MALLOC(lambda,(trotter))
2767 5 : lambda(1)=zero; lambda(trotter)=four*dble(trotter)
2768 15 : do kk=2,trotter/2
2769 : lambda(2*kk-2)=four*dble(trotter)* &
2770 10 : & (one-cos(two_pi*dble(kk-1)/dble(trotter)))
2771 : lambda(2*kk-1)=four*dble(trotter)* &
2772 15 : & (one-cos(two_pi*dble(kk-1)/dble(trotter)))
2773 : end do
2774 :
2775 : !normal mode masses
2776 35 : do iimage=1,trotter
2777 95 : mass(:,iimage)=quantummass(:)*lambda(iimage)
2778 : end do
2779 :
2780 35 : do iimage=1,trotter
2781 95 : spring(:,iimage)=mass(:,iimage)*dble(trotter)*kt*kt
2782 : end do
2783 :
2784 : !fictitious masses
2785 15 : mass(:,1)=inertmass(:)
2786 :
2787 : !from 2 to P not changed except if adiabatic PIMD
2788 : !see Hone et al, JCP 124, 154103 (2006)
2789 : gammasquare=one !adiabaticity parameter
2790 : do iimage=2,trotter
2791 : mass(:,iimage)=mass(:,iimage)/gammasquare
2792 : end do
2793 :
2794 5 : ABI_FREE(lambda)
2795 :
2796 : !=== Staging transformation ==============================================
2797 15 : else if (transform==2) then
2798 :
2799 : !Fictitious masses
2800 45 : mass(1:natom,1)=inertmass(1:natom)
2801 15 : if (nmass>1) then
2802 90 : do iimage=2,trotter
2803 240 : mass(1:natom,iimage)=inertmass(1:natom)*dble(iimage)/dble(iimage-1)
2804 : end do
2805 : end if
2806 :
2807 : !Staging masses (mass_temp)
2808 60 : ABI_MALLOC(mass_temp,(natom,trotter))
2809 45 : mass_temp(1:natom,1)=zero
2810 15 : if (nmass>1) then
2811 90 : do iimage=2,trotter
2812 240 : mass_temp(1:natom,iimage)=quantummass(1:natom)*dble(iimage)/dble(iimage-1)
2813 : end do
2814 : end if
2815 :
2816 45 : spring(1:natom,1)=mass_temp(1:natom,1)*dble(trotter)*kt*kt
2817 15 : if (nspring>1) then
2818 90 : do iimage=2,trotter
2819 240 : spring(1:natom,iimage)=mass_temp(1:natom,iimage)*dble(trotter)*kt*kt
2820 : end do
2821 : end if
2822 15 : ABI_FREE(mass_temp)
2823 :
2824 : end if
2825 :
2826 45 : end subroutine pimd_mass_spring
2827 : !!***
2828 :
2829 0 : END MODULE m_pimd
2830 : !!***
|