LCOV - code coverage report
Current view: top level - src/45_geomoptim - m_pimd_langevin.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.6 % 291 287
Test Date: 2026-09-20 18:56:22 Functions: 100.0 % 2 2

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

Generated by: LCOV version 2.3-1