LCOV - code coverage report
Current view: top level - src/45_geomoptim - m_pred_isokinetic.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.2 % 201 139
Test Date: 2026-09-21 13:49:52 Functions: 100.0 % 1 1

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

Generated by: LCOV version 2.3-1