LCOV - code coverage report
Current view: top level - src/45_geomoptim - m_pred_moldyn.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.1 % 130 121
Test Date: 2026-09-21 22:40:37 Functions: 100.0 % 1 1

            Line data    Source code
       1              : !!****m* ABINIT/m_pred_moldyn
       2              : !! NAME
       3              : !!  m_pred_moldyn
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !! COPYRIGHT
       8              : !!  Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, SE)
       9              : !!  This file is distributed under the terms of the
      10              : !!  GNU General Public License, see ~abinit/COPYING
      11              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      12              : !!
      13              : !! SOURCE
      14              : 
      15              : #if defined HAVE_CONFIG_H
      16              : #include "config.h"
      17              : #endif
      18              : 
      19              : #include "abi_common.h"
      20              : 
      21              : module m_pred_moldyn
      22              : 
      23              :  use defs_basis
      24              :  use m_abicore
      25              :  use m_abimover
      26              :  use m_abihist
      27              : 
      28              :  use m_geometry,  only : xcart2xred, xred2xcart
      29              :  use m_predtk,    only : fdtion
      30              : 
      31              :  implicit none
      32              : 
      33              :  private
      34              : !!***
      35              : 
      36              :  public :: pred_moldyn
      37              : !!***
      38              : 
      39              : contains
      40              : !!***
      41              : 
      42              : !!****f* ABINIT/pred_moldyn
      43              : !! NAME
      44              : !! pred_moldyn
      45              : !!
      46              : !! FUNCTION
      47              : !! Ionmov predictor (1) Molecular dynamics
      48              : !!
      49              : !! Molecular dynamics, with or without viscous damping
      50              : !! This function should be called after the call to scfcv
      51              : !! Updates positions, velocities and forces
      52              : !!
      53              : !! INPUTS
      54              : !! ab_mover<type abimover>=Subset of dtset only related with
      55              : !!          |                 movement of ions and acell, contains:
      56              : !!          | dtion:  Time step
      57              : !!          ! natom:  Number of atoms
      58              : !!          | vis:    viscosity
      59              : !!          | iatfix: Index of atoms and directions fixed
      60              : !!          | amass:  Mass of ions
      61              : !! icycle: Index of the internal cycle inside a time step (itime)
      62              : !! itime: Index of time iteration
      63              : !! zDEBUG : if true print some debugging information
      64              : !!
      65              : !! OUTPUT
      66              : !!
      67              : !! SIDE EFFECTS
      68              : !! hist<type abihist>=Historical record of positions, forces,
      69              : !!                               stresses, cell and energies,
      70              : !!
      71              : !! ncycle: Number of cycles of a particular time step
      72              : !!
      73              : !! NOTES
      74              : !! * This routine is a predictor, it only produces new positions
      75              : !!   to be computed in the next iteration, this routine should
      76              : !!   produce not output at all
      77              : !! * ncycle changes from 4 for the first iteration (itime==1) to 1 for (itime>1)
      78              : !! * The arrays vec_tmp1 and vec_tmp2 are triky, they are use with
      79              : !!   different meanings, during the initialization they contains
      80              : !!   working positions and velocities that acumulated produce the
      81              : !!   first positions of itime=1, for itime>1 they will contain
      82              : !!   positions in 2 previous steps, those values are different
      83              : !!   from the values store in the history, thats the reason why
      84              : !!   we cannot simply use hist%xred to obtain those positions.
      85              : !!
      86              : !! SOURCE
      87              : 
      88           73 : subroutine pred_moldyn(ab_mover,hist,icycle,itime,ncycle,ntime,zDEBUG,iexit)
      89              : 
      90              : !Arguments ------------------------------------
      91              : !scalars
      92              : type(abimover),intent(in)       :: ab_mover
      93              : type(abihist),intent(inout),target :: hist
      94              : integer,intent(in)    :: icycle
      95              : integer,intent(inout) :: ncycle
      96              : integer,intent(in)    :: itime
      97              : integer,intent(in)    :: ntime
      98              : integer,intent(in)    :: iexit
      99              : logical,intent(in)    :: zDEBUG
     100              : 
     101              : !Local variables-------------------------------
     102              : !scalars
     103              : integer  :: kk,jj,ihist,ihist_next,ihist_prev,ihist_prev2
     104              : integer  :: ihist_prev4,ihist_prev5
     105              : real(dp) :: aa,alfa,bb,cc,x0,xm,em,vis,dx,dv
     106              : real(dp) :: fcart,fprev,fprev2
     107              : real(dp) :: xc
     108              : real(dp) :: vel,vnow,xnow,vprev
     109              : real(dp),save :: hh,time
     110              : !arrays
     111              : real(dp) :: acell(3),rprimd(3,3)
     112            6 : real(dp) :: xred(3,ab_mover%natom)
     113           73 : real(dp),allocatable :: xcart(:,:),xcart_prev(:,:)
     114              : real(dp),save,allocatable :: vec_tmp1(:,:)
     115              : real(dp),save,allocatable :: vec_tmp2(:,:)
     116           73 : real(dp), ABI_CONTIGUOUS pointer :: vel_cur(:,:),vel_next(:,:)
     117           73 : real(dp),pointer :: fcart_cur(:,:),fcart_prev(:,:),fcart_prev2(:,:)
     118              : 
     119              : !***************************************************************************
     120              : !Beginning of executable session
     121              : !***************************************************************************
     122              : 
     123           73 :  if(iexit/=0)then
     124            6 :    if(allocated(vec_tmp1))  then
     125            6 :      ABI_FREE(vec_tmp1)
     126              :    end if
     127            6 :    if(allocated(vec_tmp2))  then
     128            6 :      ABI_FREE(vec_tmp2)
     129              :    end if
     130              :    return
     131              :  end if
     132              : 
     133           67 :  vis= ab_mover%vis
     134              : !Just to avoid warnings of uninitialized variables
     135              :  fprev=0.0_dp
     136           67 :  fprev=0.0_dp
     137           67 :  fprev2=0.0_dp
     138           67 :  vnow=0.0_dp
     139           67 :  vprev=0.0_dp
     140           67 :  xnow=0.0_dp
     141              : 
     142              : !Those arrays contains intermediary results used with
     143              : !different meanings during the different time steps
     144              : !We need to preserv the allocation status, this is the
     145              : !reason to be 'SAVE'
     146           67 :  if (itime==1.and.icycle==1)then
     147            6 :    if(allocated(vec_tmp1))  then
     148            0 :      ABI_FREE(vec_tmp1)
     149              :    end if
     150            6 :    if(allocated(vec_tmp2))  then
     151            0 :      ABI_FREE(vec_tmp2)
     152              :    end if
     153           18 :    ABI_MALLOC(vec_tmp1,(3,ab_mover%natom))
     154           12 :    ABI_MALLOC(vec_tmp2,(3,ab_mover%natom))
     155              :  end if
     156              : 
     157              : !write(std_out,*) '00'
     158              : !##########################################################
     159              : !### 00. Copy from the history to the variables
     160              : 
     161           67 :  call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
     162              : 
     163          201 :  ABI_MALLOC(xcart,(3,ab_mover%natom))
     164           67 :  call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
     165              : 
     166           67 :  if (itime==1.or.itime==2)then
     167           90 :    ABI_MALLOC(xcart_prev,(3,ab_mover%natom))
     168           30 :    call xred2xcart(ab_mover%natom,rprimd,xcart_prev,hist%xred(:,:,1))
     169              :  end if
     170              : 
     171           67 :  ihist = abihist_findIndex(hist, 0)
     172           67 :  ihist_prev  = abihist_findIndex(hist,-1)
     173           67 :  ihist_prev2 = abihist_findIndex(hist,-2)
     174           67 :  ihist_prev4 = abihist_findIndex(hist,-4)
     175           67 :  ihist_prev5 = abihist_findIndex(hist,-5)
     176           67 :  ihist_next  = abihist_findIndex(hist,+1)
     177              : 
     178           67 :  fcart_cur => hist%fcart(:,:,ihist)
     179           67 :  if (itime==2) fcart_prev  => hist%fcart(:,:,ihist_prev4)
     180           67 :  if (itime==3) fcart_prev2 => hist%fcart(:,:,ihist_prev5)
     181           67 :  if (itime >2.or. icycle>=2)fcart_prev  => hist%fcart(:,:,ihist_prev)
     182           67 :  if (itime >3.or. icycle>=3)fcart_prev2 => hist%fcart(:,:,ihist_prev2)
     183              : 
     184           67 :  vel_cur  => hist%vel(:,:,ihist)
     185           67 :  vel_next => hist%vel(:,:,ihist_next)
     186              : 
     187              : !write(std_out,*) '01'
     188              : !##########################################################
     189              : !### 01. Get or compute the time step dtion
     190              : 
     191           67 :  if (ab_mover%dtion>0)then
     192           67 :    hh = ab_mover%dtion
     193              :  else
     194            0 :    hh=fdtion(ab_mover,itime,xcart,fcart_cur,vel_cur)
     195              :  end if
     196              : 
     197              : !write(std_out,*) '02'
     198              : !##########################################################
     199              : !### 02. For all atoms and directions
     200          366 :  do kk=1,ab_mover%natom
     201          299 :    em=ab_mover%amass(kk)
     202         1263 :    do jj=1,3
     203              : 
     204              : !    write(std_out,*) '03'
     205              : !    ##########################################################
     206              : !    ### 03. Filling other values from history (forces and vel)
     207          897 :      fcart=fcart_cur(jj,kk)
     208          897 :      xc=xcart(jj,kk)
     209          897 :      vel=hist%vel(jj,kk,1)
     210              : 
     211              : !    Previous values only after first iteration
     212          897 :      if (itime>=2.or.icycle>=2) then
     213          813 :        fprev=fcart_prev(jj,kk)
     214          813 :        vprev=hist%vel(jj,kk,hist%ihist)
     215              :      end if
     216          897 :      if (itime>=3.or.icycle>=3) then
     217          645 :        fprev2=fcart_prev2(jj,kk)
     218              :      end if
     219              : 
     220          897 :      if (itime==2)then
     221           84 :        vec_tmp1(jj,kk)=xcart_prev(jj,kk)
     222           84 :        vec_tmp2(jj,kk)=xcart(jj,kk)
     223              :      end if
     224              : 
     225              : !    write(std_out,*) '04'
     226              : !    ##########################################################
     227              : !    ### 04. Take first the atoms that are not allowed to move along
     228              : !    ###     this direction
     229              : !    ###     Warning : implemented in cartesian coordinates
     230          897 :      if (ab_mover%iatfix(jj,kk)==1) then
     231              : !      Their positions will be the same as xcart
     232          445 :        xnow=xcart(jj,kk)
     233              : !      Their velocities are zero
     234          445 :        vnow=0.0_dp
     235              :      else
     236              : 
     237              : !      write(std_out,*) '05'
     238              : !      ##########################################################
     239              : !      ### 05. Initialization (itime==1):
     240              : !      ###     4 calls to obtain the forces are neeeded
     241              : !      ###     The variables vec_tmp2 and vec_tmp1 from previous
     242              : !      ###     calls are used in the following ones.
     243          452 :        if(itime==1)then
     244          152 :          x0=xcart_prev(jj,kk)
     245              : 
     246              : !        Prepare the second cycle
     247          152 :          if(icycle==1)then
     248           38 :            dx=hh*vel
     249           38 :            dv=hh/em*(fcart-vis*vel)
     250           38 :            xnow=x0+.5_dp*dx
     251           38 :            vnow=vel+.5_dp*dv
     252           38 :            vec_tmp2(jj,kk)=xc+sixth*dx
     253           38 :            vec_tmp1(jj,kk)=vel+sixth*dv
     254          114 :          else if(icycle==2)then
     255           38 :            dx=hh*vprev
     256           38 :            dv=hh/em*(fcart-vis*vprev)
     257           38 :            xnow=x0+.5_dp*dx
     258           38 :            vnow=vel+.5_dp*dv
     259           38 :            vec_tmp2(jj,kk)=vec_tmp2(jj,kk)+third*dx
     260           38 :            vec_tmp1(jj,kk)=vec_tmp1(jj,kk)+third*dv
     261           76 :          else if(icycle==3)then
     262           38 :            dx=hh*vprev
     263           38 :            dv=hh/em*(fcart-vis*vprev)
     264           38 :            xnow=x0+dx
     265           38 :            vnow=vel+dv
     266           38 :            vec_tmp2(jj,kk)=vec_tmp2(jj,kk)+third*dx
     267           38 :            vec_tmp1(jj,kk)=vec_tmp1(jj,kk)+third*dv
     268           38 :          else if(icycle==4)then
     269           38 :            dx=hh*vprev
     270           38 :            dv=hh/em*(fcart-vis*vprev)
     271           38 :            xnow=vec_tmp2(jj,kk)+sixth*dx
     272           38 :            vnow=vec_tmp1(jj,kk)+sixth*dv
     273              :          end if
     274              :        else !(itime/=1)
     275              : 
     276              : !        write(std_out,*) '06'
     277              : !        ##########################################################
     278              : !        ### 06. Change positions and velocities
     279              : !        ###     These changes only applies for itime>2
     280          300 :          if (itime>2)then
     281              : !          Uses a corrector to have better value of xnow, and
     282              : !          derive vnow. Only update atoms position and
     283              : !          velocity along its allowed directions
     284          262 :            aa=fprev
     285          262 :            bb=(fcart-fprev2)/(2._dp*hh)
     286          262 :            cc=(fcart+fprev2-2._dp*fprev)/(2._dp*hh*hh)
     287          262 :            x0=vec_tmp2(jj,kk)
     288          262 :            xm=vec_tmp1(jj,kk)
     289          262 :            if(abs(vis)<=1.d-8)then
     290              : !            NON-DAMPED DYNAMICS (Post-Code)
     291              :              xnow=2._dp*x0-xm+hh**2/em/12._dp*&
     292            0 : &             (fprev2+10._dp*fprev+fcart)
     293              :              vnow=(bb*hh**2)/(3._dp*em)&
     294              : &             +1.5_dp*aa*hh/em+&
     295              : &             (5._dp/12._dp)*cc*hh**3/em&
     296            0 : &             +x0/hh-xm/hh
     297              :            else
     298              : !            DAMPED DYNAMICS (Post-Code)
     299          262 :              alfa=exp(-vis*hh/em)
     300              :              xnow=((-aa*hh*vis**2+0.5_dp*bb*hh**2*vis**2&
     301              : &             -third*cc*hh**3*vis**2+em*bb*hh*vis&
     302              : &             -em*cc*hh**2*vis-2._dp*em**2*cc*hh+x0*vis**3-xm*vis**3)*alfa&
     303              : &             +aa*hh*vis**2-em*bb*hh*vis+third*cc*hh**3*vis**2&
     304              : &             +2._dp*em**2*cc*hh+0.5D0*bb*hh**2*vis**2-em*cc*hh**2*vis+x0*vis**3)&
     305          262 : &             /vis**3
     306              :              vnow=(em*aa*vis**2*alfa-em*aa*vis**2+bb*hh*vis**2*em*alfa&
     307              : &             -bb*hh*vis**2*em+cc*hh**2*vis**2*em*alfa-cc*hh**2*vis**2*em&
     308              : &             -em**2*bb*vis*alfa+em**2*bb*vis-2._dp*em**2*cc*hh*vis*alfa+&
     309              : &             2._dp*em**2*cc*hh*vis+2._dp*em**3*cc*alfa-2._dp*em**3*cc+&
     310              : &             vis**3*alfa**2*aa*hh-0.5_dp*vis**3*alfa**2*bb*hh**2+&
     311              : &             third*vis**3*alfa**2*cc*hh**3-vis**2*&
     312              : &             alfa**2*em*bb*hh+vis**2*alfa**2*em*cc*hh**2+&
     313              : &             2._dp*vis*alfa**2*em**2*cc*hh-vis**4*alfa**2*x0+&
     314          262 : &             vis**4*alfa**2*xm)/vis**3/(alfa-1._dp)/em
     315              : 
     316              :            end if !if(abs(vis)<=1.d-8)
     317              : 
     318          262 :            xc=xnow
     319          262 :            vec_tmp1(jj,kk)=vec_tmp2(jj,kk)
     320          262 :            vec_tmp2(jj,kk)=xnow
     321              :          else
     322              :            vnow=vprev
     323              :          end if !if(itime>2)
     324              : 
     325              : !        write(std_out,*) '07'
     326              : !        ##########################################################
     327              : !        ### 07. Correct positions
     328              : !        ###     These changes only applies for itime>1
     329              : 
     330          300 :          if(abs(vis)<=1.d-8)then
     331              : !          NON-DAMPED DYNAMICS (Pre-Code)
     332              : !          If the viscosity is too small, the equations become
     333              : !          ill conditioned due to rounding error so do regular
     334              : !          Verlet predictor Numerov corrector.
     335            0 :            x0=vec_tmp2(jj,kk)
     336            0 :            xm=vec_tmp1(jj,kk)
     337              :            xnow=2._dp*x0-xm&
     338            0 : &           + hh**2/em*fcart
     339              :          else
     340              : !          DAMPED DYNAMICS (Pre-Code)
     341              : !          These equations come from solving
     342              : !          m*d2x/dt2+vis*dx/dt=a+b*t+c*t**2
     343              : !          analytically under the boundary conditions that
     344              : !          x(0)=x0 and x(-h)=xm, and the following is the
     345              : !          expression for x(h). a, b and c are determined
     346              : !          from our knowledge of the driving forces.
     347          300 :            aa=fcart
     348          300 :            bb=(fcart-fprev)/hh
     349          300 :            x0=vec_tmp2(jj,kk)
     350          300 :            xm=vec_tmp1(jj,kk)
     351          300 :            alfa=exp(-vis*hh/em)
     352              :            xnow=( (-aa*hh*vis**2 +0.5_dp*bb*hh**2*vis**2&
     353              : &           +em*bb*hh*vis +x0*vis**3 -xm*vis**3)*alfa&
     354              : &           +aa*hh*vis**2 -em*bb*hh*vis&
     355          300 : &           +0.5_dp*bb*hh**2*vis**2 +x0*vis**3)/vis**3
     356              : !          End of choice between initialisation, damped
     357              : !          dynamics and non-damped dynamics
     358              :          end if
     359              : 
     360              :        end if !if(itime==1)
     361              : 
     362              :      end if !if(ab_mover%iatfix(jj,kk)==1)
     363              : 
     364              : !    write(std_out,*) '08'
     365              : !    ##########################################################
     366              : !    ### 08. Update history
     367              : 
     368          897 :      xcart(jj,kk)=xnow
     369         1196 :      vel_next(jj,kk)=vnow
     370              : 
     371              : !    write(std_out,*) '09'
     372              : !    ##########################################################
     373              : !    ### 09. End loops of atoms and directions
     374              :    end do ! jj=1,3
     375              :  end do ! kk=1,ab_mover%natom
     376              : 
     377              : !write(std_out,*) '10'
     378              : !##########################################################
     379              : !### 10. Filling history with the new values
     380              : 
     381           67 :  hist%ihist = abihist_findIndex(hist,+1)
     382              : 
     383           67 :  call xcart2xred(ab_mover%natom,rprimd,xcart,xred)
     384           67 :  call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
     385              : 
     386              : !Change ncycle for itime>1
     387           67 :  if (icycle==4)  ncycle=1
     388              : 
     389           67 :  if (itime==1)then
     390           24 :    time=0.0_dp
     391           24 :    if (ab_mover%dtion<0)then
     392            0 :      write(std_out,*) 'Time=',time
     393              :    end if
     394              :  end if
     395           67 :  time=time+hh
     396           67 :  hist%time(hist%ihist)=time
     397              : 
     398           67 :  ABI_SFREE(xcart)
     399           67 :  ABI_SFREE(xcart_prev)
     400              : 
     401              :  if (.false.) write(std_out,*) ntime
     402              : 
     403          140 : end subroutine pred_moldyn
     404              : !!***
     405              : 
     406              : end module m_pred_moldyn
     407              : !!***
        

Generated by: LCOV version 2.3-1