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

            Line data    Source code
       1              : !!****m* ABINIT/m_pred_fire
       2              : !! NAME
       3              : !!  m_pred_fire
       4              : !!
       5              : !! FUNCTION
       6              : !! Ionmov predictors (15) FIRE algorithm
       7              : !! The fast inertial relaxation engine (FIRE) method for relaxation.
       8              : !! The method is described in  Erik Bitzek, Pekka Koskinen, Franz G"ahler,
       9              : !! Michael Moseler, and Peter Gumbsch, Phys. Rev. Lett. 97, 170201 [[cite:Bitzek2006]]
      10              : !!
      11              : !! COPYRIGHT
      12              : !!  Copyright (C) 1998-2026 ABINIT group (hexu)
      13              : !!  This file is distributed under the terms of the
      14              : !!  GNU General Public License, see ~abinit/COPYING
      15              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      16              : !!
      17              : !! SOURCE
      18              : 
      19              : #if defined HAVE_CONFIG_H
      20              : #include "config.h"
      21              : #endif
      22              : 
      23              : #include "abi_common.h"
      24              : 
      25              : module m_pred_fire
      26              :  use defs_basis
      27              :  use m_abicore
      28              :  use m_abimover
      29              :  use m_abihist
      30              :  use m_xfpack
      31              :  use m_geometry,    only : mkrdim, fcart2gred, metric, xred2xcart
      32              :  use m_errors, only: unused_var
      33              : 
      34              :  implicit none
      35              : 
      36              :  private
      37              : 
      38              :  public :: pred_fire
      39              : 
      40              : contains
      41              : 
      42              : !!***
      43              : 
      44              : !!****f* m_pred_fire/pred_fire
      45              : !! NAME
      46              : !! pred_fire
      47              : !!
      48              : !! FUNCTION
      49              : !!
      50              : !! IONMOV 15:
      51              : !! Given a starting point xred that is a vector of length 3*natom
      52              : !! (reduced nuclei coordinates), a velocity vector (in cartesian
      53              : !! coordinates), and unit cell parameters (acell and rprimd -
      54              : !! without velocities in the present implementation), the Verlet
      55              : !! dynamics is performed, using the gradient of the energy
      56              : !! (atomic forces and stresses) as calculated by the routine scfcv.
      57              : !!
      58              : !! At each step, the dot product of velocity and force is calculated.
      59              : !! If the v.dot.f is positive for min_downhill consecutive steps, the
      60              : !! time step dtion is increased by dtinc until it reaches dtmax. If
      61              : !! v.dot.f is negative, dtion is mulitiplied by dtdec.
      62              : !!
      63              : !! Some atoms can be kept fixed, while the propagation of unit cell
      64              : !! parameters is only performed if optcell/=0.
      65              : !! No more than ab_mover%ntime steps are performed.
      66              : !! The time step is governed by dtion, contained in ab_mover
      67              : !! (coming from dtset).
      68              : !! Returned quantities are xred, and eventually acell and rprimd
      69              : !! (new ones!).
      70              : !!
      71              : 
      72              : !! INPUTS
      73              : !! ab_mover <type(abimover)> : Datatype with all the information
      74              : !!                                needed by the preditor
      75              : !! itime  : Index of the present iteration
      76              : !! ntime  : Maximal number of iterations
      77              : !! ionmov : (15) FIRE. Not used in function. just to keep the same format as bfgs.
      78              : !! zDEBUG : if true print some debugging information
      79              : !!
      80              : !! OUTPUT
      81              : !!
      82              : !! SIDE EFFECTS
      83              : !! hist <type(abihist)> : History of positions,forces
      84              : !!                               acell, rprimd, stresses
      85              : !!
      86              : !! SOURCE
      87           12 : subroutine pred_fire(ab_mover, ab_xfh,forstr,hist,ionmov,itime,zDEBUG,iexit)
      88              : 
      89              : !Arguments ------------------------------------
      90              : !scalars
      91              :  type(abimover),intent(in) :: ab_mover
      92              :  type(ab_xfh_type),intent(inout) :: ab_xfh
      93              :  type(abiforstr),intent(in) :: forstr
      94              :  type(abihist),intent(inout) :: hist
      95              :  integer, intent(in) :: ionmov
      96              :  integer,intent(in) :: itime
      97              :  integer,intent(in) :: iexit
      98              :  logical,intent(in) :: zDEBUG
      99              : 
     100              : 
     101              : !Local variables-------------------------------
     102              : !scalars
     103              : integer  :: ihist,ihist_prev,ndim
     104              : integer, parameter :: min_downhill=4
     105              : integer  :: ii,jj,kk
     106              : real(dp),save :: ucvol0
     107              : real(dp) :: ucvol
     108              : real(dp) :: etotal,etotal_prev
     109              : real(dp) :: favg
     110              : ! time step, damping factor initially dtion
     111              : real(dp),save :: dtratio, alpha
     112              : ! dtinc: increment of dtratio
     113              : ! dtdec: decrement of dtratio
     114              : ! dtmax: maximum allowd value of dtratio
     115              : ! alphadec: decrement of alpha
     116              : ! alpha0: initial value of alpha
     117              : ! mixold: if energy goes up, linear mix old and new coordinates. mixold
     118              : real(dp), parameter :: dtinc=1.1, dtdec=0.5, dtmax=10.0
     119              : real(dp), parameter :: alphadec=0.99, alpha0=0.2, mixold=0.3
     120              : ! v.dot.f
     121              : real(dp) :: vf
     122              : ! number of v.dot.f >0
     123              : integer, save :: ndownhill
     124              : ! reset_lattice: whether to reset lattice if energy goes up.
     125              : logical, parameter :: reset_lattice = .true.
     126              : 
     127              : !arrays
     128              : real(dp) :: gprimd(3,3)
     129              : real(dp) :: gmet(3,3)
     130              : real(dp) :: rmet(3,3)
     131           24 : real(dp) :: fcart(3, ab_mover%natom)
     132              : real(dp) :: acell(3),strten(6), acell0(3)
     133              : real(dp) :: rprim(3,3),rprimd(3,3), rprimd0(3,3)
     134           24 : real(dp) :: xred(3,ab_mover%natom),xcart(3,ab_mover%natom)
     135              : ! velocity are saved
     136           24 : real(dp) :: vel(3,ab_mover%natom)
     137           12 : real(dp) :: residual(3,ab_mover%natom),residual_corrected(3,ab_mover%natom)
     138              : real(dp),allocatable, save :: vin(:), vout(:)
     139              : real(dp), allocatable, save:: vin_prev(:)
     140              : ! velocity but correspoing to vin&vout, for ion&cell relaxation
     141              : real(dp),allocatable,save :: vel_ioncell(:)
     142              : 
     143              :  ABI_UNUSED((/ionmov, ab_xfh%mxfh/))
     144              : 
     145              : !***************************************************************************
     146              : !Beginning of executable session
     147              : !***************************************************************************
     148              : 
     149           12 :  if(iexit/=0)then
     150            1 :    ABI_SFREE(vin)
     151            1 :    ABI_SFREE(vout)
     152            1 :    ABI_SFREE(vin_prev)
     153            1 :    ABI_SFREE(vel_ioncell)
     154              :    return
     155              :  end if
     156              : 
     157           11 : write(std_out,*) 'FIRE 01'
     158              : !##########################################################
     159              : !### 01. Compute the dimension of vectors (ndim)
     160              : 
     161           11 :  ndim=3*ab_mover%natom
     162           11 :  if(ab_mover%optcell==1) ndim=ndim+1
     163           11 :  if(ab_mover%optcell==2 .or.&
     164            0 : & ab_mover%optcell==3) ndim=ndim+6
     165           11 :  if(ab_mover%optcell>=4) ndim=ndim+3
     166              : 
     167           11 : write(std_out,*) 'FIRE: ndim=', ndim
     168           11 : write(std_out,*) 'FIRE 02'
     169              : !##########################################################
     170              : !### 02. Allocate the vectors vin
     171              : 
     172              : !Notice that vin, vout, etc could be allocated
     173              : !From a previous dataset with a different ndim
     174           11 :  if(itime==1)then
     175            1 :    ABI_SFREE(vin)
     176            1 :    ABI_SFREE(vout)
     177            1 :    ABI_SFREE(vin_prev)
     178            1 :    ABI_SFREE(vel_ioncell)
     179              : 
     180            3 :    ABI_MALLOC(vin,(ndim))
     181            2 :    ABI_MALLOC(vout,(ndim))
     182            2 :    ABI_MALLOC(vin_prev,(ndim))
     183            2 :    ABI_MALLOC(vel_ioncell,(ndim))
     184           28 :    vel_ioncell(:)=0.0
     185              :  end if
     186              : 
     187           11 :  write(std_out,*) 'FIRE 03'
     188              : !##########################################################
     189              : !### 03. Obtain the present values from the history
     190              : 
     191           11 :  call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
     192              : 
     193           11 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     194              : 
     195           44 :  do ii=1,3
     196          143 :    rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
     197              :  end do
     198              : 
     199           11 :  ihist = abihist_findIndex(hist, 0)
     200           11 :  ihist_prev  = abihist_findIndex(hist,-1)
     201              : 
     202           11 :  call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
     203          407 :  fcart(:,:)  =hist%fcart(:,:,hist%ihist)
     204           77 :  strten(:)  =hist%strten(:,hist%ihist)
     205           11 :  etotal=hist%etot(hist%ihist)
     206              : 
     207           11 :  if(itime==1) then
     208              :      etotal_prev=0.0
     209              :  else
     210           10 :      etotal_prev=hist%etot(ihist_prev)
     211              :  endif
     212              : 
     213              : !Fill the residual with forces (No preconditioning)
     214              : !Or the preconditioned forces
     215           11 :  if (ab_mover%goprecon==0)then
     216           11 :    call fcart2gred(hist%fcart(:,:,hist%ihist),residual,rprimd,ab_mover%natom)
     217              :  else
     218            0 :    residual(:,:)=forstr%gred(:,:)
     219              :  end if
     220              : 
     221              : !Save initial values
     222           11 :  if (itime==1)then
     223            1 :    acell0(:)=acell(:)
     224            1 :    rprimd0(:,:)=rprimd(:,:)
     225            1 :    ucvol0=ucvol
     226              :  end if
     227              : 
     228              : 
     229           11 :  if(zDEBUG)then
     230            0 :    write (std_out,*) 'fcart:'
     231            0 :    do kk=1,ab_mover%natom
     232            0 :      write (std_out,*) fcart(:,kk)
     233              :    end do
     234            0 :    write (std_out,*) 'vel:'
     235            0 :    do kk=1,ab_mover%natom
     236            0 :      write (std_out,*) vel(:,kk)
     237              :    end do
     238            0 :    write (std_out,*) 'strten:'
     239            0 :    write (std_out,*) strten(1:3),ch10,strten(4:6)
     240            0 :    write (std_out,*) 'etotal:'
     241            0 :    write (std_out,*) etotal
     242              :  end if
     243              : 
     244              : !Get rid of mean force on whole unit cell, but only if no
     245              : !generalized constraints are in effect
     246              : 
     247          407 :  residual_corrected(:,:)=residual(:,:)
     248           11 :  if(ab_mover%nconeq==0)then
     249           44 :    do kk=1,3
     250           44 :      if (kk/=3.or.ab_mover%jellslab==0) then
     251          330 :        favg=sum(residual_corrected(kk,:))/dble(ab_mover%natom)
     252          330 :        residual_corrected(kk,:)=residual_corrected(kk,:)-favg
     253              :      end if
     254              :    end do
     255              :  end if
     256              : 
     257           11 :  write(std_out,*) 'FIRE 04'
     258              : !##########################################################
     259              : !### 04. Fill the vectors vin and vout
     260              : 
     261              : !Initialize input vectors : first vin, then vout
     262              : ! transfer xred, acell, and rprim to vin
     263              : call xfpack_x2vin(acell, ab_mover%natom, ndim,&
     264              : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
     265           11 : & ab_mover%symrel, ucvol, ucvol0, vin, xred)
     266              : !end if
     267              : 
     268              : !transfer gred and strten to vout.
     269              : !Note: gred is not f in reduced co.
     270              : !but dE/dx
     271              : 
     272              :  call xfpack_f2vout(residual_corrected, ab_mover%natom, ndim,&
     273              : & ab_mover%optcell, ab_mover%strtarget, strten, ucvol,&
     274           11 : & vout)
     275              : ! Now vout -> -dE/dx
     276          308 : vout(:) = -1.0*vout(:)
     277              : 
     278           11 :  write(std_out,*) 'FIRE 05'
     279              : !##########################################################
     280              : !### 05. iniialize FIRE
     281           11 : if ( itime==1 ) then
     282            1 :    ndownhill=0
     283            1 :    alpha=alpha0
     284            1 :    if (ab_mover%dtion>0)then
     285            1 :      dtratio = 1.0
     286              :    end if
     287              : end if
     288              : 
     289           11 :  write(std_out,*) 'FIRE 06'
     290              : !##########################################################
     291              : !### 06. update timestep
     292              : ! Note that vin & vout are in reduced coordinates.
     293          308 : vf=sum(vel_ioncell*vout)
     294           11 : if ( vf >= 0.0_dp .and. (etotal- etotal_prev <0.0_dp) ) then
     295              : !if ( vf >= 0.0_dp ) then
     296           10 :     ndownhill=ndownhill+1
     297              :     ! mix v with the v projected on force vector.
     298              :     vel_ioncell(:)=(1.0-alpha)*vel_ioncell(:) + alpha* vout *  &
     299          820 : &               sqrt(sum(vel_ioncell*vel_ioncell)/sum(vout*vout))
     300           10 :     if ( ndownhill>min_downhill ) then
     301            2 :         dtratio = min(dtratio * dtinc, dtmax)
     302            2 :         alpha = alpha * alphadec
     303              :     end if
     304              : else
     305              :     ! reset downhill counter, velocity, alpha. decrease dtratio.
     306            1 :     ndownhill=0
     307           28 :     vel_ioncell(:)=0.0
     308            1 :     alpha=alpha0
     309            1 :     dtratio = dtratio*dtdec
     310              : endif
     311              : 
     312           11 :  write(std_out,*) 'FIRE 07'
     313              : !##########################################################
     314              : !### 07. MD step. update vel_ioncell
     315              : 
     316              : ! Here mass is not used: all masses=1
     317              : !write(std_out,*) 'FIRE vin: ', vin
     318              : ! update v
     319          319 : vel_ioncell = vel_ioncell + dtratio*ab_mover%dtion* vout
     320              : !write(std_out,*) 'FIRE vel: ', vel_ioncell
     321              : !write(std_out,*) 'FIRE delta x',dtratio*ab_mover%dtion* vel_ioncell
     322              : ! update x
     323          319 : vin = vin + dtratio*ab_mover%dtion* vel_ioncell
     324              : !write(std_out,*) 'FIRE vin: ', vin
     325              : 
     326              : !   write(std_out,*) 'FIRE vout: ', vout
     327              : !   write(std_out,*) 'FIRE vf: ', vf
     328              : !   write(std_out,*) 'FIRE etotal: ', etotal
     329              : !   write(std_out,*) 'FIRE etotal_prev: ', etotal_prev
     330              : !   write(std_out,*) 'FIRE deltaE: ',etotal-etotal_prev
     331           11 :    write(std_out,*) 'FIRE ndownhill: ', ndownhill
     332              : !   write(std_out,*) 'FIRE dtratio: ', dtratio
     333              : !   write(std_out,*) 'FIRE dtion: ', ab_mover%dtion
     334              : 
     335              : 
     336              : !Implement fixing of atoms : put back old values for fixed
     337              : !components
     338          110 :  do kk=1,ab_mover%natom
     339          407 :    do jj=1,3
     340              : !    Warning : implemented in reduced coordinates
     341          396 :      if ( ab_mover%iatfix(jj,kk)==1) then
     342            0 :        vin(jj+(kk-1)*3)=vin_prev(jj+(kk-1)*3)
     343              :      end if
     344              :    end do
     345              :  end do
     346              : 
     347              : ! reset_lattice to last step by a ratio if energy is increased.
     348              : ! disabled for debugging
     349           11 : if ( etotal - etotal_prev >0.0 ) then
     350            0 :     vin= vin*(1-mixold)+vin_prev*mixold
     351              : end if
     352              : 
     353              : ! only set vin to vin_prev when energy decreased, so it's
     354              : ! possible to go back.
     355              : ! if (etotal - etotal_prev <0.0 ) then
     356          308 :  vin_prev(:)=vin(:)
     357              : ! endif
     358              : 
     359              : 
     360              : 
     361              : !##########################################################
     362              : !### 08. update hist.
     363              : 
     364              : !Increase indexes
     365           11 :  hist%ihist = abihist_findIndex(hist,+1)
     366              : !Transfer vin  to xred, acell and rprim
     367              :  call xfpack_vin2x(acell, acell0, ab_mover%natom, ndim,&
     368              : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
     369              : & ab_mover%symrel, ucvol, ucvol0,&
     370           11 : & vin, xred)
     371              : 
     372           11 :  if(ab_mover%optcell/=0)then
     373            0 :    call mkrdim(acell,rprim,rprimd)
     374            0 :    call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     375              :  end if
     376              : 
     377              : !Fill the history with the variables
     378              : !xcart, xred, acell, rprimd
     379           11 :  call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
     380           11 :  ihist_prev = abihist_findIndex(hist,-1)
     381          407 :  hist%vel(:,:,hist%ihist)=hist%vel(:,:,ihist_prev)
     382              : 
     383           11 :  if(zDEBUG)then
     384            0 :    write (std_out,*) 'residual:'
     385            0 :    do kk=1,ab_mover%natom
     386            0 :      write (std_out,*) residual(:,kk)
     387              :    end do
     388            0 :    write (std_out,*) 'strten:'
     389            0 :    write (std_out,*) strten(1:3),ch10,strten(4:6)
     390            0 :    write (std_out,*) 'etotal:'
     391            0 :    write (std_out,*) etotal
     392              :  end if
     393              : 
     394              : 
     395              : end subroutine pred_fire
     396              : !!***
     397              : 
     398              : end module m_pred_fire
     399              : 
        

Generated by: LCOV version 2.3-1