LCOV - code coverage report
Current view: top level - src/67_common - m_forces.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.5 % 563 515
Test Date: 2026-09-21 22:40:37 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !!****m* ABINIT/m_forces
       2              : !! NAME
       3              : !!  m_forces
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !!
       8              : !! COPYRIGHT
       9              : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, FJ, MM, MT, SCE)
      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              : ! nvtx related macro definition
      23              : #include "nvtx_macros.h"
      24              : 
      25              : module m_forces
      26              : 
      27              :  use defs_basis
      28              :  use defs_wvltypes
      29              :  use m_abicore
      30              :  use m_efield
      31              :  use m_errors
      32              :  use m_atomdata
      33              :  use m_dtset
      34              : 
      35              :  use defs_datatypes,     only : pseudopotential_type
      36              :  use defs_abitypes,      only : MPI_type
      37              :  use m_time,             only : timab
      38              :  use m_geometry,         only : gred2fcart, metric, xred2xcart
      39              :  use m_fock,             only : fock_type
      40              :  use m_pawrad,           only : pawrad_type
      41              :  use m_pawtab,           only : pawtab_type
      42              :  use m_electronpositron, only : electronpositron_type,electronpositron_calctype
      43              :  use libxc_functionals,  only : libxc_functionals_is_hybrid
      44              :  use m_fft,              only : zerosym, fourdp
      45              :  use m_cgtools,          only : mean_fftr
      46              :  use m_mpinfo,           only : pre_gather, pre_scatter
      47              :  use m_atm2fft,          only : atm2fft
      48              :  use m_mklocl,           only : mklocl
      49              :  use m_predtk,           only : prtxvf
      50              :  use m_xchybrid,         only : xchybrid_ncpp_cc
      51              :  use m_mkcore,           only : mkcore, mkcore_alt
      52              :  use m_mkcore_wvl,       only : mkcore_wvl
      53              : 
      54              : #if defined(HAVE_GPU_MARKERS)
      55              :  use m_nvtx_data
      56              : #endif
      57              : 
      58              :  implicit none
      59              : 
      60              :  private
      61              : !!***
      62              : 
      63              :  public :: forces
      64              :  public :: fresid
      65              : !!***
      66              : 
      67              : contains
      68              : !!***
      69              : 
      70              : !!****f* ABINIT/forces
      71              : !! NAME
      72              : !! forces
      73              : !!
      74              : !! FUNCTION
      75              : !! Assemble gradients of various total energy terms with respect
      76              : !! to reduced coordinates, including possible symmetrization,
      77              : !! in order to produce forces.
      78              : !!
      79              : !!     fcart(i,iat) = d(Etot)/(d(r(i,iat)))
      80              : !!
      81              : !! INPUTS
      82              : !!  atindx1(natom)=index table for atoms, inverse of atindx
      83              : !!  dtefield <type(efield_type)> = variables related to Berry phase
      84              : !!  dtset <type(dataset_type)>=all input variables in this dataset
      85              : !! berryopt    =  4/14: electric field is on -> add the contribution of the
      86              : !!                      -ebar_i p_i - Omega/(8*pi) (g^{-1})_ij ebar_i ebar_j  terms to the total energy
      87              : !!     = 6/16, or 7/17: electric displacement field is on  -> add the contribution of the
      88              : !!                      Omega/(8*pi) (g^{-1})_ij ebar_i ebar_j  terms to the total energy
      89              : !!   | efield = cartesian coordinates of the electric field in atomic units
      90              : !!   | dfield = cartesian coordinates of the electric displacement field in atomic units
      91              : !!   | iatfix(3,natom)=1 for frozen atom along specified direction, 0 for unfrozen
      92              : !!   | ionmov=governs the movement of atoms (see help file)
      93              : !!   | densfor_pred=governs the mixed electronic-atomic part of the preconditioner
      94              : !!   | natom=number of atoms in cell
      95              : !!   | nconeq=number of atomic constraint equations
      96              : !!   | nspden=number of spin-density components
      97              : !!   | nsym=number of symmetries in space group
      98              : !!   | prtvol=integer controlling volume of printed output
      99              : !!   | typat(natom)=type integer for each atom in cell
     100              : !!   | wtatcon(3,natom,nconeq)=weights for atomic constraints
     101              : !!  fock <type(fock_type)>= quantities to calculate Fock exact exchange
     102              : !!  grchempottn(3,natom)=d(E_chemical potential)/d(xred) (hartree)
     103              : !!  grcondft(3,natom)=d(E_constrainedDFT)/d(xred) (hartree)
     104              : !!  grewtn(3,natom)=d(Ewald)/d(xred) (hartree)
     105              : !!  grnl(3*natom)=gradients of Etot due to nonlocal contributions
     106              : !!  grvdw(3,ngrvdw)=gradients of energy due to Van der Waals DFT-D dispersion (hartree)
     107              : !!  gsqcut=cutoff value on G**2 for (large) sphere inside FFT box.
     108              : !!                       gsqcut=(boxcut**2)*ecut/(2._dp*(Pi**2)
     109              : !!  indsym(4,nsym,natom)=indirect indexing array for atom labels
     110              : !!  mgfft=maximum size of 1D FFTs
     111              : !!  mpi_enreg=information about MPI parallelization
     112              : !!  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
     113              : !!  n3xccc=dimension of the xccc3d array (0 or nfft).
     114              : !!  nattyp(ntypat)=number of atoms of each type
     115              : !!  nfft=(effective) number of FFT grid points (for this processor)
     116              : !!  ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     117              : !!  ngrvdw=size of grvdw(:,:); can be 0 or natom according to dtset%vdw_xc
     118              : !!  ntypat=number of types of atoms
     119              : !!  pawrad(ntypat*usepaw) <type(pawrad_type)>=paw radial mesh and related data
     120              : !!  pawtab(ntypat*dtset%usepaw) <type(pawtab_type)>=paw tabulated starting data
     121              : !!  ph1d(2,3*(2*mgfft+1)*natom)=1-dim phase (structure factor) array
     122              : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
     123              : !!  rhog(2,nfft)=Fourier transform of charge density (bohr^-3)
     124              : !!  rhor(nfft,nspden)=array for electron density in electrons/bohr**3
     125              : !!  rprimd(3,3)=dimensional primitive translations in real space (bohr)
     126              : !!  symrec(3,3,nsym)=symmetries in reciprocal space, reduced coordinates
     127              : !!  usefock=1 if fock operator is used; 0 otherwise.
     128              : !!  usevxctau=1 if if XC functional depends on kinetic energy density
     129              : !!  vresid(nfft,nspden)=potential residual (if non-collinear magn., only trace of it)
     130              : !!  vxc(nfft,nspden)=exchange-correlation potential (hartree) in real space
     131              : !!  vxctau(nfft,nspden,4*usevxctau)=(only for meta-GGA): derivative of XC energy density
     132              : !!                                wrt kinetic energy density (depsxcdtau)
     133              : !!  xred(3,natom)=reduced dimensionless atomic coordinates
     134              : !!  xred_old(3,natom)=previous reduced dimensionless atomic coordinates
     135              : !!
     136              : !! OUTPUT
     137              : !!  diffor=maximal absolute value of changes in the components of
     138              : !!         force between the input and the output.
     139              : !!  favg(3)=mean of the forces before correction for translational symmetry
     140              : !!  forold(3,natom)=cartesian forces of previous SCF cycle (hartree/bohr)
     141              : !!  gred(3,natom)=symmetrized grtn = d(etotal)/d(xred)
     142              : !!  gresid(3,natom)=forces due to the residual of the density/potential
     143              : !!  grhf(3,natom)=Hellman-Feynman derivatives of the total energy
     144              : !!  grxc(9+3*natom)=d(Exc)/d(xred) if core charges are used
     145              : !!  maxfor=maximal absolute value of the output array force.
     146              : !!  synlgr(3,natom)=symmetrized d(enl)/d(xred)
     147              : !!
     148              : !! SIDE EFFECTS
     149              : !!  electronpositron <type(electronpositron_type)>=quantities for the electron-positron annihilation (optional argument)
     150              : !!  fcart(3,natom)=forces in cartesian coordinates (Ha/Bohr)
     151              : !!    Note : unlike gred, this array has been corrected by enforcing
     152              : !!    the translational symmetry, namely that the sum of force
     153              : !!    on all atoms is zero.
     154              : !!
     155              : !! NOTES
     156              : !! * Symmetrization of gradients with respect to reduced
     157              : !!   coordinates xred is conducted according to the expression
     158              : !!   [d(e)/d(t(n,a))]_symmetrized = (1/Nsym) Sum(S) symrec(n,m,S)*
     159              : !!                [d(e)/d(t(m,b))]_unsymmetrized
     160              : !!   where t(m,b)= (symrel^-1)(m,n)*(t(n,a)-tnons(n)) and tnons
     161              : !!   is a possible nonsymmorphic translation.  The label "b" here
     162              : !!   refers to the atom which gets rotated into "a" under symmetry "S".
     163              : !!   symrel is the symmetry matrix in real space, which is the inverse
     164              : !!   transpose of symrec.  symrec is the symmetry matrix in reciprocal
     165              : !!   space.  sym_cartesian = R * symrel * R^-1 = G * symrec * G^-1
     166              : !!   where the columns of R and G are the dimensional primitive translations
     167              : !!   in real and reciprocal space respectively.
     168              : !! * Note the use of "symrec" in the symmetrization expression above.
     169              : !!
     170              : !! SOURCE
     171              : 
     172        23761 : subroutine forces(atindx1,diffor,dtefield,dtset,favg,fcart,fock,&
     173        23761 : &                  forold,gred,grchempottn,grcondft,gresid,grewtn,&
     174        23761 : &                  grhf,grnl,grvdw,grxc,gsqcut,indsym,&
     175              : &                  maxfor,mgfft,mpi_enreg,n1xccc,n3xccc,&
     176        23761 : &                  nattyp,nfft,ngfft,ngrvdw,ntypat,&
     177        23761 : &                  pawrad,pawtab,ph1d,psps,rhog,rhor,rprimd,symrec,synlgr,&
     178              : &                  usefock,usevxctau,&
     179        23761 : &                  vresid,vxc,vxctau,wvl,wvl_den,xred,&
     180              : &                  electronpositron) ! optional argument
     181              : 
     182              : !Arguments ------------------------------------
     183              : !scalars
     184              :  integer,intent(in) :: mgfft,n1xccc,n3xccc,nfft,ngrvdw,ntypat,usefock,usevxctau
     185              :  real(dp),intent(in) :: gsqcut
     186              :  real(dp),intent(out) :: diffor,maxfor
     187              :  type(MPI_type),intent(in) :: mpi_enreg
     188              :  type(efield_type),intent(in) :: dtefield
     189              :  type(dataset_type),intent(in) :: dtset
     190              :  type(electronpositron_type),pointer,optional :: electronpositron
     191              :  type(pseudopotential_type),intent(in) :: psps
     192              :  type(wvl_internal_type), intent(in) :: wvl
     193              :  type(wvl_denspot_type), intent(inout) :: wvl_den
     194              :  type(fock_type),pointer, intent(inout) :: fock
     195              : !arrays
     196              :  integer,intent(in) :: atindx1(dtset%natom),indsym(4,dtset%nsym,dtset%natom)
     197              :  integer,intent(in) :: nattyp(ntypat),ngfft(18),symrec(3,3,dtset%nsym)
     198              :  real(dp),intent(in) :: grchempottn(3,dtset%natom),grcondft(3,dtset%natom),grewtn(3,dtset%natom)
     199              :  real(dp),intent(in) :: grvdw(3,ngrvdw),grnl(3*dtset%natom)
     200              :  real(dp),intent(in) :: ph1d(2,3*(2*mgfft+1)*dtset%natom)
     201              :  real(dp),intent(in) :: rhog(2,nfft),rhor(nfft,dtset%nspden)
     202              :  real(dp),intent(in) :: vxc(nfft,dtset%nspden),vxctau(nfft,dtset%nspden,4*usevxctau)
     203              :  real(dp),intent(inout) :: fcart(3,dtset%natom),forold(3,dtset%natom)
     204              :  real(dp),intent(inout) :: vresid(nfft,dtset%nspden),xred(3,dtset%natom)
     205              :  real(dp),intent(out) :: favg(3),gred(3,dtset%natom),gresid(3,dtset%natom)
     206              :  real(dp),intent(out) :: grhf(3,dtset%natom),rprimd(3,3)
     207              :  real(dp),intent(inout) :: grxc(3,dtset%natom)
     208              :  real(dp),intent(out) :: synlgr(3,dtset%natom)
     209              :  type(pawrad_type),intent(in) :: pawrad(ntypat*psps%usepaw)
     210              :  type(pawtab_type),intent(in) :: pawtab(ntypat*psps%usepaw)
     211              : 
     212              : !Local variables-------------------------------
     213              : !scalars
     214              :  integer :: coredens_method,coretau_method,fdir,has_vxctau,iatom,idir,indx,ipositron,itypat,mu
     215              :  integer :: optatm,optdyfr,opteltfr,optgr,option,optn,optn2,optstr,optv,vloc_method
     216              :  real(dp) :: eei_dum1,eei_dum2,ucvol,ucvol_local,vol_element,entropy_dum1
     217              :  logical :: calc_epaw3_forces, efield_flag
     218              :  logical :: is_hybrid_ncpp
     219              : !arrays
     220              :  integer :: qprtrb_dum(3)
     221              :  real(dp) :: dummy6(6),ep3(3),fioncart(3),gmet(3,3),gprimd(3,3)
     222              :  real(dp) :: rmet(3,3),strn_dummy6(6),strv_dummy6(6),tsec(2),vprtrb_dum(2)
     223        23761 :  real(dp),allocatable :: atmrho_dum(:),atmvloc_dum(:),dyfrlo_dum(:,:,:)
     224        23761 :  real(dp),allocatable :: dyfrn_dum(:,:,:),dyfrv_dum(:,:,:)
     225        23761 :  real(dp),allocatable :: dyfrx2_dum(:,:,:),eltfrn_dum(:,:),gauss_dum(:,:)
     226        23761 :  real(dp),allocatable :: epawf3red(:,:),fin(:,:),fionred(:,:),grl(:,:),grl_dum(:,:)
     227        23761 :  real(dp),allocatable :: grnl_tmp(:,:),grtn(:,:),grtn_indx(:,:),grxctau(:,:),v_dum(:),vxctotg(:,:)
     228        23761 :  real(dp),allocatable :: xccc3d_dum(:)
     229              : 
     230              : ! *************************************************************************
     231              : 
     232        23761 :  call timab(69,1,tsec)
     233              :  ABI_NVTX_START_RANGE(NVTX_FORCES)
     234              : 
     235              : !Save input value of forces
     236        71283 :  ABI_MALLOC(fin,(3,dtset%natom))
     237       286261 :  fin(:,:)=fcart(:,:)
     238              : 
     239              : !Compute different geometric tensor, as well as ucvol, from rprimd
     240        23761 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     241              : 
     242              : !Test size of vxctau
     243        95044 :  has_vxctau=size(vxctau)
     244        23761 :  if (has_vxctau/=nfft*dtset%nspden*4.and.has_vxctau/=0) then
     245            0 :    ABI_BUG('Wrong size for vxctau!')
     246              :  else if (has_vxctau/=0) then
     247        23761 :    has_vxctau=1
     248              :  end if
     249              : 
     250              : !Check if we're in hybrid norm conserving pseudopotential
     251              :  is_hybrid_ncpp=(psps%usepaw==0 .and. &
     252        23761 : & (dtset%ixc==41.or.dtset%ixc==42.or.libxc_functionals_is_hybrid()))
     253              : 
     254              : !=======================================================================
     255              : !========= Local pseudopotential and core charge contributions =========
     256              : !=======================================================================
     257              : 
     258        47522 :  ABI_MALLOC(grl,(3,dtset%natom))
     259              : 
     260              : !Determine by which method the local ionic potential and/or the pseudo core
     261              : !  charge density contributions have to be computed
     262              : !Local ionic potential:
     263              : ! Method 1: PAW
     264              : ! Method 2: Norm-conserving PP, icoulomb>0, wavelets
     265        23761 :  vloc_method=1;if (psps%usepaw==0) vloc_method=2
     266        23761 :  if (dtset%icoulomb>0) vloc_method=2
     267        23761 :  if (psps%usewvl==1) vloc_method=2
     268              : !Pseudo core charge density:
     269              : ! Method 1 construct through G space FT: PAW, nc_xccc_gspace==1
     270              : ! Method 2 construct in real space     : Norm-conserving PP default, wavelets
     271              :  coredens_method=1;if (psps%usepaw==0) coredens_method=2
     272        23761 :  if (psps%nc_xccc_gspace==1) coredens_method=1
     273        23761 :  if (psps%nc_xccc_gspace==0) coredens_method=2
     274        23761 :  if (psps%usewvl==1) coredens_method=2
     275              : !Pseudo core charge kinetic energy density: same convention as coredens_method
     276        23761 :  coretau_method=0
     277        23761 :  if (dtset%usekden==1) then
     278           60 :    coretau_method=1;if (psps%nc_xccc_gspace==0) coretau_method=2
     279              :  end if
     280              : 
     281              : !Local ionic potential and/or pseudo core charge by method 1
     282        23761 :  if (vloc_method==1.or.coredens_method==1.or.coretau_method==1) then
     283         6697 :    if (psps%nc_xccc_gspace==1.and.psps%usepaw==0.and.is_hybrid_ncpp) then
     284            0 :      ABI_BUG(' Not yet implemented !')
     285              :    end if
     286         6697 :    call timab(550,1,tsec)
     287              : !  Allocate (unused) dummy variables, otherwise some compilers complain
     288         6697 :    ABI_MALLOC(gauss_dum,(0,0))
     289         6697 :    ABI_MALLOC(atmrho_dum,(0))
     290         6697 :    ABI_MALLOC(atmvloc_dum,(0))
     291         6697 :    ABI_MALLOC(dyfrn_dum,(0,0,0))
     292         6697 :    ABI_MALLOC(dyfrv_dum,(0,0,0))
     293         6697 :    ABI_MALLOC(eltfrn_dum,(0,0))
     294              : !  Compute Vxc in reciprocal space
     295         6697 :    if (coredens_method==1.and.n3xccc>0) then
     296        12549 :      ABI_MALLOC(v_dum,(nfft))
     297        12549 :      ABI_MALLOC(vxctotg,(2,nfft))
     298    157580223 :      v_dum(:)=vxc(:,1);if (dtset%nspden>=2) v_dum(:)=0.5_dp*(v_dum(:)+vxc(:,2))
     299         4183 :      call fourdp(1,vxctotg,v_dum,-1,mpi_enreg,nfft,1,ngfft,0)
     300              :      call zerosym(vxctotg,2,ngfft(1),ngfft(2),ngfft(3),&
     301         4183 : &     comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     302         4183 :      ABI_FREE(v_dum)
     303              :    else
     304         2514 :      ABI_MALLOC(vxctotg,(0,0))
     305              :    end if
     306              : !  Compute contribution to forces from Vloc and/or pseudo core density
     307         6697 :    optv=0;if (vloc_method==1) optv=1
     308         6697 :    optn=0;if (coredens_method==1) optn=n3xccc/nfft
     309         6697 :    optatm=0;optdyfr=0;optgr=1;optstr=0;optn2=1;opteltfr=0
     310         6697 :    if (vloc_method==1.or.coredens_method==1) then
     311              :      call atm2fft(atindx1,atmrho_dum,atmvloc_dum,dyfrn_dum,dyfrv_dum,&
     312              : &     eltfrn_dum,gauss_dum,gmet,gprimd,&
     313              : &     grxc,grl,gsqcut,mgfft,psps%mqgrid_vl,dtset%natom,nattyp,nfft,ngfft,ntypat,&
     314              : &     optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab,ph1d,psps%qgrid_vl,qprtrb_dum,&
     315              : &     dtset%rcut,rhog,rprimd,strn_dummy6,strv_dummy6,ucvol,psps%usepaw,vxctotg,vxctotg,vxctotg,vprtrb_dum,psps%vlspl,&
     316              : &     comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
     317         6697 : &     paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
     318              :    end if
     319        43501 :    if (n3xccc==0.and.coredens_method==1) grxc=zero
     320         6697 :    ABI_FREE(vxctotg)
     321         6697 :    if (dtset%usekden==1.and.usevxctau==1.and.coretau_method==1.and.n3xccc>0) then
     322              : !    Compute contribution to forces from pseudo kinetic energy core density
     323           29 :      optv=0;optn=1;optn2=4
     324           58 :      ABI_MALLOC(grxctau,(3,dtset%natom))
     325           29 :      ABI_MALLOC(grl_dum,(0,0))
     326           87 :      ABI_MALLOC(v_dum,(nfft))
     327           87 :      ABI_MALLOC(vxctotg,(2,nfft))
     328      1353053 :      v_dum(:)=vxctau(:,1,1);if (dtset%nspden>=2) v_dum(:)=0.5_dp*(v_dum(:)+vxctau(:,2,1))
     329           29 :      call fourdp(1,vxctotg,v_dum,-1,mpi_enreg,nfft,1,ngfft,0)
     330              :      call zerosym(vxctotg,2,ngfft(1),ngfft(2),ngfft(3),&
     331           29 : &     comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft)
     332           29 :      ABI_FREE(v_dum)
     333              :      call atm2fft(atindx1,atmrho_dum,atmvloc_dum,dyfrn_dum,dyfrv_dum,&
     334              : &     eltfrn_dum,gauss_dum,gmet,gprimd,&
     335              : &     grxctau,grl_dum,gsqcut,mgfft,psps%mqgrid_vl,dtset%natom,nattyp,nfft,ngfft,ntypat,&
     336              : &     optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab,ph1d,psps%qgrid_vl,qprtrb_dum,&
     337              : &     dtset%rcut,rhog,rprimd,strn_dummy6,strv_dummy6,ucvol,psps%usepaw,vxctotg,vxctotg,vxctotg,vprtrb_dum,psps%vlspl,&
     338              : &     comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
     339           29 : &     paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
     340          261 :      grxc(:,:)=grxc(:,:)+grxctau(:,:)
     341           29 :      ABI_FREE(grl_dum)
     342           29 :      ABI_FREE(grxctau)
     343           29 :      ABI_FREE(vxctotg)
     344              :    end if
     345              : !  Deallocate temporary arrays
     346         6697 :    ABI_FREE(gauss_dum)
     347         6697 :    ABI_FREE(atmrho_dum)
     348         6697 :    ABI_FREE(atmvloc_dum)
     349         6697 :    ABI_FREE(dyfrn_dum)
     350         6697 :    ABI_FREE(dyfrv_dum)
     351         6697 :    ABI_FREE(eltfrn_dum)
     352         6697 :    call timab(550,2,tsec)
     353              :  end if
     354              : 
     355              : !Local ionic potential by method 2
     356        23761 :  if (vloc_method==2) then
     357        17067 :    option=2
     358        51201 :    ABI_MALLOC(dyfrlo_dum,(3,3,dtset%natom))
     359        34134 :    ABI_MALLOC(grtn_indx,(3,dtset%natom))
     360        51201 :    ABI_MALLOC(v_dum,(nfft))
     361              :    call mklocl(dtset,dyfrlo_dum,eei_dum1,gmet,gprimd,grtn_indx,gsqcut,dummy6,mgfft,&
     362              : &   mpi_enreg,dtset%natom,nattyp,nfft,ngfft,dtset%nspden,ntypat,option,pawtab,ph1d,psps,&
     363        17067 : &   qprtrb_dum,rhog,rhor,rprimd,ucvol,vprtrb_dum,v_dum,wvl,wvl_den,xred)
     364        61247 :    do iatom=1,dtset%natom
     365              : !    Has to use the indexing array atindx1
     366       193787 :      grl(1:3,atindx1(iatom))=grtn_indx(1:3,iatom)
     367              :    end do
     368        17067 :    ABI_FREE(dyfrlo_dum)
     369        17067 :    ABI_FREE(grtn_indx)
     370        17067 :    ABI_FREE(v_dum)
     371              : !  If gradients are computed in real space, we need to symmetrize the system before summing.
     372              : !  Rshaltaf: I changed the following line to include surfaces BC
     373        17067 :    if (dtset%icoulomb == 1 .or. dtset%icoulomb == 2) then
     374            0 :      ABI_MALLOC(grnl_tmp,(3,dtset%natom))
     375            0 :      call sygrad(grnl_tmp,dtset%natom,grl,dtset%nsym,symrec,indsym)
     376            0 :      grl(:, :) = grnl_tmp(:, :)
     377            0 :      ABI_FREE(grnl_tmp)
     378              :    end if
     379              :  end if
     380              : 
     381              : !Pseudo core electron density by method 2
     382        23761 :  if (coredens_method==2.or.coretau_method==2) then
     383        17064 :    if (n1xccc/=0) then
     384         4093 :      call timab(53,1,tsec)
     385         4093 :      option=2
     386        12279 :      ABI_MALLOC(dyfrx2_dum,(3,3,dtset%natom))
     387        12279 :      ABI_MALLOC(xccc3d_dum,(n3xccc))
     388         4093 :      if (coredens_method==2) then
     389         4093 :        if (is_hybrid_ncpp) then
     390              :          call xchybrid_ncpp_cc(dtset,eei_dum1,entropy_dum1,mpi_enreg,nfft,ngfft,n3xccc,rhor,rprimd,&
     391          100 : &         dummy6,eei_dum2,xccc3d_dum,grxc=grxc,xcccrc=psps%xcccrc,xccc1d=psps%xccc1d,xred=xred,n1xccc=n1xccc)
     392              :        else
     393         3993 :          if (psps%usewvl==0.and.psps%usepaw==0.and.dtset%icoulomb==0) then
     394              :            call mkcore(dummy6,dyfrx2_dum,grxc,mpi_enreg,dtset%natom,nfft,dtset%nspden,ntypat,&
     395              : &           ngfft(1),n1xccc, ngfft(2),ngfft(3),option,rprimd,dtset%typat,ucvol,vxc,&
     396         3993 : &           psps%xcccrc,psps%xccc1d,xccc3d_dum,xred)
     397            0 :          else if (psps%usewvl==0.and.(psps%usepaw==1.or.dtset%icoulomb==1)) then
     398              :            call mkcore_alt(atindx1,dummy6,dyfrx2_dum,grxc,dtset%icoulomb,mpi_enreg,dtset%natom,nfft,&
     399              : &           dtset%nspden,nattyp,ntypat,ngfft(1),n1xccc,ngfft(2),ngfft(3),option,rprimd,&
     400            0 : &           ucvol,vxc,psps%xcccrc,psps%xccc1d,xccc3d_dum,xred,pawrad,pawtab,psps%usepaw)
     401              :          else if (psps%usewvl==1.and.psps%usepaw==1) then
     402              :            ucvol_local=ucvol
     403              : #if defined HAVE_BIGDFT
     404              : !          ucvol_local=product(wvl_den%denspot%dpbox%hgrids)*real(product(wvl_den%denspot%dpbox%ndims),dp)
     405              : !          call mkcore_wvl_old(atindx1,dummy6,dyfrx2_dum,wvl%atoms%astruct%geocode,grxc,wvl%h,dtset%natom,&
     406              : ! &           nattyp,nfft,wvl_den%denspot%dpbox%nscatterarr(mpi_enreg%me_wvl,:),dtset%nspden,ntypat,&
     407              : ! &           wvl%Glr%d%n1,wvl%Glr%d%n1i,wvl%Glr%d%n2,wvl%Glr%d%n2i,wvl%Glr%d%n3,wvl_den%denspot%dpbox%n3pi,&
     408              : ! &           n3xccc,option,pawrad,pawtab,psps%gth_params%psppar,rprimd,ucvol_local,vxc,xccc3d_dum,xred,&
     409              : ! &           mpi_comm_wvl=mpi_enreg%comm_wvl)
     410              :            call mkcore_wvl(atindx1,dummy6,grxc,dtset%natom,nattyp,nfft,dtset%nspden,ntypat,&
     411              : &           n1xccc,n3xccc,option,pawrad,pawtab,rprimd,vxc,psps%xccc1d,xccc3d_dum,&
     412              : &           psps%xcccrc,xred,wvl_den,wvl,mpi_comm_wvl=mpi_enreg%comm_wvl)
     413              : #endif
     414              :          end if
     415              :        end if
     416              :      end if
     417         4093 :      if (dtset%usekden==1.and.usevxctau==1.and.coretau_method==2) then
     418            6 :        ABI_MALLOC(grxctau,(3,dtset%natom))
     419              :        call mkcore_alt(atindx1,dummy6,dyfrx2_dum,grxctau,dtset%icoulomb,mpi_enreg,dtset%natom,nfft,&
     420              : &       dtset%nspden,nattyp,ntypat,ngfft(1),n1xccc,ngfft(2),ngfft(3),option,rprimd,&
     421              : &       ucvol,vxctau(:,:,1),psps%xcccrc,psps%xccc1d,xccc3d_dum,xred,pawrad,pawtab,psps%usepaw,&
     422            3 : &       usekden=.true.)
     423           23 :        grxc(:,:)=grxc(:,:)+grxctau(:,:)
     424            3 :        ABI_FREE(grxctau)
     425              :      end if
     426         4093 :      ABI_FREE(xccc3d_dum)
     427         4093 :      ABI_FREE(dyfrx2_dum)
     428         4093 :      call timab(53,2,tsec)
     429              :    else
     430       130507 :      grxc(:,:)=zero
     431              :    end if
     432              :  end if
     433              : 
     434              : !=======================================================================
     435              : !===================== Nonlocal contributions ==========================
     436              : !=======================================================================
     437              : 
     438              : !Only has to apply symmetries
     439        47522 :  ABI_MALLOC(grnl_tmp,(3,dtset%natom))
     440        89386 :  do iatom=1,dtset%natom
     441       286261 :    indx=3*(iatom-1);grnl_tmp(1:3,atindx1(iatom))=grnl(indx+1:indx+3)
     442              :  end do
     443        23761 :  if (dtset%usewvl == 0) then
     444        23761 :    call sygrad(synlgr,dtset%natom,grnl_tmp,dtset%nsym,symrec,indsym)
     445              :  else
     446            0 :    synlgr = grnl_tmp
     447              :  end if
     448        23761 :  ABI_FREE(grnl_tmp)
     449              : 
     450              : !=======================================================================
     451              : !============ Density/potential residual contributions =================
     452              : !=======================================================================
     453              : 
     454        23761 :  if (dtset%usewvl==0.and.abs(dtset%densfor_pred)>=1.and.abs(dtset%densfor_pred)<=3) then
     455              :    call fresid(dtset,gresid,mpi_enreg,nfft,ngfft,ntypat,1,&
     456        19370 : &   pawtab,rhor,rprimd,ucvol,vresid,xred,xred,psps%znuclpsp)
     457         4391 :  else if (dtset%usewvl==0.and.(abs(dtset%densfor_pred)==4.or.abs(dtset%densfor_pred)==6)) then
     458              :    call fresidrsp(atindx1,dtset,gmet,gprimd,gresid,gsqcut,mgfft,&
     459              : &   mpi_enreg,psps%mqgrid_vl,nattyp,nfft,ngfft,ntypat,psps,pawtab,ph1d,&
     460         4373 : &   psps%qgrid_vl,rprimd,ucvol,psps%usepaw,vresid,psps%zionpsp,psps%znuclpsp)
     461              :  else
     462          470 :    gresid(:,:)=zero
     463              :  end if
     464              : 
     465              : !=======================================================================
     466              : !======================= Other contributions ===========================
     467              : !=======================================================================
     468              : 
     469              : !Ewald energy contribution to forces as already been computed in "ewald"
     470              : 
     471              : !Potential residual contribution to forces as already been computed (forstr)
     472              : 
     473              : !Add Berry phase contributions (berryopt == 4/6/7/14/16/17)
     474              : !(compute the electric field force on the ion cores)
     475              :  efield_flag = (dtset%berryopt==4 .or. dtset%berryopt==6 .or. dtset%berryopt==7 .or. &
     476        23761 : & dtset%berryopt==14 .or. dtset%berryopt==16 .or. dtset%berryopt==17)
     477           25 :  calc_epaw3_forces = (efield_flag .and. dtset%optforces /= 0 .and. psps%usepaw == 1)
     478              :  if ( efield_flag ) then
     479           50 :    ABI_MALLOC(fionred,(3,dtset%natom))
     480          449 :    fionred(:,:)=zero
     481          131 :    do iatom=1,dtset%natom
     482          106 :      itypat=dtset%typat(iatom)
     483              : ! force on ion due to electric field, cartesian representation
     484          424 :      fioncart(:)=psps%ziontypat(itypat)*dtset%efield(:)
     485              : ! form fionred = rprimd^T * fioncart, note that forces transform
     486              : ! oppositely to coordinates, because they are derivative with respect to
     487              : ! coordinates
     488          131 :      call dgemv('T',3,3,one,rprimd,3,fioncart,1,zero,fionred(1:3,iatom),1)
     489              : !     do mu=1,3
     490              : !       fionred(mu,iatom)=rprimd(1,mu)*fioncart(1) &
     491              : !&       +rprimd(2,mu)*fioncart(2) &
     492              : !&       +rprimd(3,mu)*fioncart(3)
     493              : !     end do
     494              :    end do
     495              :  end if
     496              : 
     497              : !(compute additional F3-type force due to projectors for electric field with PAW)
     498           25 :  if ( efield_flag .and. calc_epaw3_forces ) then
     499           18 :    ABI_MALLOC(epawf3red,(3,dtset%natom))
     500              : ! dtefield%epawf3(iatom,idir,fdir) contains
     501           81 :    epawf3red(:,:)=zero
     502           27 :    do iatom=1,dtset%natom
     503           81 :      do fdir = 1, 3
     504          216 :        do idir = 1, 3
     505              : ! vol_element is volume/pt for integration of epawf3. volume is BZ volume
     506              : ! so 1/ucvol, and number of kpts is nstr(idir)*nkstr(idir)
     507          162 :          vol_element=one/(ucvol*dtefield%nstr(idir)*dtefield%nkstr(idir))
     508          216 :          ep3(idir) = vol_element*dtefield%epawf3(iatom,idir,fdir)
     509              :        end do
     510          234 :        epawf3red(fdir,iatom) = -ucvol*dot_product(dtset%red_efieldbar(1:3),ep3(1:3))
     511              :      end do
     512              :    end do ! end loop over iatom
     513              :  end if
     514              : 
     515              : !This was incorrect coding. Bug found by Jiawang Hong
     516              : !if (dtset%berryopt==4) then
     517              : !allocate(fionred(3,dtset%natom));fionred(:,:)=zero
     518              : !iatom = 0
     519              : !do itypat=1,ntypat
     520              : !do iattyp=1,nattyp(itypat)
     521              : !iatom=iatom+1
     522              : !fioncart(:)=psps%ziontypat(itypat)*dtset%efield(:)
     523              : !do mu=1,3
     524              : !fionred(mu,iatom)=rprimd(1,mu)*fioncart(1) &
     525              : !&         +rprimd(2,mu)*fioncart(2) &
     526              : !&         +rprimd(3,mu)*fioncart(3)
     527              : !end do
     528              : !end do
     529              : !end do
     530              : !end if
     531              : 
     532              : !=======================================================================
     533              : !======= Assemble the various contributions to the forces ==============
     534              : !=======================================================================
     535              : 
     536              : !Collect grads of etot wrt reduced coordinates
     537              : !This gives non-symmetrized Hellman-Feynman reduced gradients
     538        47522 :  ABI_MALLOC(grtn,(3,dtset%natom))
     539       286261 :  grtn(:,:)=grl(:,:)+grchempottn(:,:)+grcondft(:,:)+grewtn(:,:)+synlgr(:,:)+grxc(:,:)
     540              : 
     541        23761 :  if (usefock==1 .and. associated(fock)) then
     542          320 :    if (fock%fock_common%optfor) then
     543         2070 :      grtn(:,:)=grtn(:,:)+fock%fock_common%forces(:,:)
     544              :    end if
     545              :  end if
     546              : 
     547        23833 :  if (ngrvdw==dtset%natom) grtn(:,:)=grtn(:,:)+grvdw(:,:)
     548              : ! note that fionred is subtracted, because it really is a force and we need to
     549              : ! turn it back into a gradient. The gred2fcart routine below includes the minus
     550              : ! sign to convert gradients back to forces
     551        24185 :  if ( efield_flag ) grtn(:,:)=grtn(:,:)-fionred(:,:)
     552              : ! epawf3red is added, because it actually is a gradient, not a force
     553           97 :  if ( efield_flag .and. calc_epaw3_forces ) grtn(:,:) = grtn(:,:) + epawf3red(:,:)
     554              : 
     555              : !Symmetrize explicitly for given space group and store in grhf :
     556        23761 :  call sygrad(grhf,dtset%natom,grtn,dtset%nsym,symrec,indsym)
     557              : 
     558              : !If residual forces are too large, there must be a problem: cancel them !
     559        23761 :  if (dtset%usewvl==0.and.abs(dtset%densfor_pred)>0.and.abs(dtset%densfor_pred)/=5) then
     560        89255 :    do iatom=1,dtset%natom
     561       285791 :      do mu=1,3
     562       262048 :        if (abs(gresid(mu,iatom))>10000._dp*abs(grtn(mu,iatom))) gresid(mu,iatom)=zero
     563              :      end do
     564              :    end do
     565              :  end if
     566              : 
     567              : !Add residual potential correction
     568       286261 :  grtn(:,:)=grtn(:,:)+gresid(:,:)
     569              : 
     570              : !Additional stuff for electron-positron
     571        23761 :  ipositron=0
     572        23761 :  if (present(electronpositron)) then
     573        23761 :    if (associated(electronpositron)) then
     574          289 :      if (allocated(electronpositron%gred_ep)) ipositron=electronpositron_calctype(electronpositron)
     575              :    end if
     576              :  end if
     577          289 :  if (abs(ipositron)==1) then
     578         5440 :    grtn(:,:)=grtn(:,:)-grxc(:,:)-grchempottn(:,:)-grcondft(:,:)-grewtn(:,:)-gresid(:,:)-two*grl(:,:)
     579              : !  grtn(:,:)=grtn(:,:)-grxc(:,:)-grewtn(:,:)-gresid(:,:)-two*grl(:,:)
     580        16120 :    grl(:,:)=-grl(:,:);grxc(:,:)=zero;gresid(:,:)=zero
     581          100 :    if (ngrvdw==dtset%natom) grtn(:,:)=grtn(:,:)-grvdw(:,:)
     582              :    if ( dtset%berryopt== 4 .or. dtset%berryopt== 6 .or. dtset%berryopt== 7 .or. &
     583              : &   dtset%berryopt==14 .or. dtset%berryopt==16 .or. dtset%berryopt==17)  then
     584            0 :      grtn(:,:)=grtn(:,:)+fionred(:,:)
     585            0 :      fionred(:,:)=zero
     586              :    end if
     587              :  end if
     588        39009 :  if (ipositron>0) grtn(:,:)=grtn(:,:)+electronpositron%gred_ep(:,:)
     589              : 
     590              : !Symmetrize all grads explicitly for given space group:
     591        23761 :  if (dtset%usewvl == 0) then
     592        23761 :    call sygrad(gred,dtset%natom,grtn,dtset%nsym,symrec,indsym)
     593              :  else
     594            0 :    gred = grtn
     595              :  end if
     596              : 
     597              : !Conversion to cartesian coordinates (bohr) AND
     598              : !Subtract off average force from each force component
     599              : !to avoid spurious drifting of atoms across cell.
     600              : ! notice that gred2fcart multiplies gred by -1 to convert it
     601              : ! from a gradient (input) to a force (output)
     602              : 
     603        23953 :  call gred2fcart(favg,(dtset%jellslab==0 .and. dtset%nzchempot==0),fcart,gred,gprimd,dtset%natom)
     604              : 
     605              : !Compute maximal force and maximal difference
     606        23761 :  maxfor=zero;diffor=zero
     607        89386 :  do iatom=1,dtset%natom
     608       286261 :    do mu=1,3
     609       262500 :      if (dtset%iatfix(mu,iatom) /= 1) then
     610       165847 :        maxfor=max(maxfor,abs(fcart(mu,iatom)))
     611       165847 :        diffor=max(diffor,abs(fcart(mu,iatom)-fin(mu,iatom)))
     612        31028 :      else if (dtset%ionmov==4 .or. dtset%ionmov==5) then
     613              : !      Make the force vanish on fixed atoms when ionmov=4 or 5
     614              : !      This is because fixing of atom cannot be imposed at the
     615              : !      level of a routine similar to brdmin or moldyn for these options.
     616          672 :        fcart(mu,iatom)=zero
     617              :      end if
     618              :    end do
     619              :  end do
     620              : 
     621              : !Apply any generalized constraints to the forces
     622        23761 :  if (dtset%nconeq>0) call constrf(diffor,fcart,forold,gred,dtset%iatfix,dtset%ionmov,maxfor,&
     623          740 : & dtset%natom,dtset%nconeq,dtset%prtvol,rprimd,dtset%wtatcon,xred)
     624              : 
     625              : !=======================================================================
     626              : !Memory deallocations
     627        23761 :  ABI_FREE(grl)
     628        23761 :  ABI_FREE(grtn)
     629        23761 :  ABI_FREE(fin)
     630        23761 :  if ( efield_flag )  then
     631           25 :    ABI_FREE(fionred)
     632           25 :    if ( calc_epaw3_forces ) then
     633            9 :      ABI_FREE(epawf3red)
     634              :    end if
     635              :  end if
     636              : 
     637              :  ABI_NVTX_END_RANGE()
     638        23761 :  call timab(69,2,tsec)
     639              : 
     640        23761 : end subroutine forces
     641              : !!***
     642              : 
     643              : !!****f* ABINIT/sygrad
     644              : !!
     645              : !! NAME
     646              : !! sygrad
     647              : !!
     648              : !! FUNCTION
     649              : !! Symmetrize derivatives of energy with respect to coordinates.
     650              : !! Unsymmetrized gradients are input as dedt; symmetrized grads are then placed in gred.
     651              : !! If nsym=1 simply copy dedt into gred (only symmetry is identity).
     652              : !!
     653              : !! INPUTS
     654              : !!  natom=number of atoms in cell
     655              : !!  dedt(3,natom)=unsymmetrized gradients wrt dimensionless tn (hartree)
     656              : !!  nsym=number of symmetry operators in group
     657              : !!  symrec(3,3,nsym)=symmetries of group in terms of operations on
     658              : !!    reciprocal space primitive translations--see comments below
     659              : !!  indsym(4,nsym,natom)=label given by subroutine symatm, indicating atom
     660              : !!   label which gets rotated into given atom by given symmetry
     661              : !!   (first three elements are related primitive translation--
     662              : !!   see symatm where this is computed)
     663              : !!
     664              : !! OUTPUT
     665              : !! gred(3,3,natom)=symmetrized gradients wrt reduced coordinates (hartree)
     666              : !!
     667              : !! NOTES
     668              : !! symmetrization of gradients with respect to reduced
     669              : !! coordinates tn is conducted according to the expression
     670              : !! $[d(e)/d(t(n,a))]_{symmetrized} = (1/Nsym)*Sum(S)*symrec(n,m,S)*
     671              : !!              [d(e)/d(t(m,b))]_{unsymmetrized}$
     672              : !! where $t(m,b)= (symrel^{-1})(m,n)*(t(n,a)-tnons(n))$ and tnons
     673              : !! is a possible nonsymmorphic translation.  The label "b" here
     674              : !! refers to the atom which gets rotated into "a" under symmetry "S".
     675              : !! symrel is the symmetry matrix in real space, which is the inverse
     676              : !! transpose of symrec.  symrec is the symmetry matrix in reciprocal
     677              : !! space.  $sym_{cartesian} = R * symrel * R^{-1} = G * symrec * G^{-1}$
     678              : !! where the columns of R and G are the dimensional primitive translations
     679              : !! in real and reciprocal space respectively.
     680              : !! Note the use of "symrec" in the symmetrization expression above.
     681              : !!
     682              : !! SOURCE
     683              : 
     684        71283 : subroutine sygrad(gred,natom,dedt,nsym,symrec,indsym)
     685              : 
     686              : !Arguments ------------------------------------
     687              : !scalars
     688              :  integer,intent(in) :: natom,nsym
     689              : !arrays
     690              :  integer,intent(in) :: indsym(4,nsym,natom),symrec(3,3,nsym)
     691              :  real(dp),intent(in) :: dedt(3,natom)
     692              :  real(dp),intent(out) :: gred(3,natom)
     693              : 
     694              : !Local variables-------------------------------
     695              : !scalars
     696              :  integer :: ia,ind,isym,mu
     697              :  real(dp),parameter :: tol=1.0d-30
     698              :  real(dp) :: summ
     699              : 
     700              : ! *************************************************************************
     701              : !
     702        71283 :  if (nsym==1) then
     703              : !  only symmetry is identity so simply copy
     704       332601 :    gred(:,:)=dedt(:,:)
     705              :  else
     706              : !  actually conduct symmetrization
     707       168972 :    do ia=1,natom
     708       526182 :      do mu=1,3
     709              :        summ=0._dp
     710      4325130 :        do isym=1,nsym
     711      3967920 :          ind=indsym(4,isym,ia)
     712              :          summ=summ+dble(symrec(mu,1,isym))*dedt(1,ind)+&
     713              : &         dble(symrec(mu,2,isym))*dedt(2,ind)+&
     714      4325130 : &         dble(symrec(mu,3,isym))*dedt(3,ind)
     715              :        end do
     716       357210 :        gred(mu,ia)=summ/dble(nsym)
     717       476280 :        if(abs(gred(mu,ia))<tol)gred(mu,ia)=0.0_dp
     718              :      end do
     719              :    end do
     720              :  end if
     721              : 
     722        71283 : end subroutine sygrad
     723              : !!***
     724              : 
     725              : !!****f* ABINIT/fresidrsp
     726              : !!
     727              : !! NAME
     728              : !! fresidrsp
     729              : !!
     730              : !! FUNCTION
     731              : !! Compute the forces due to the residual of the potential (or density)
     732              : !! in RECIPROCAL SPACE, using
     733              : !!  - the atomic density read in psp file (PAW or NC with nctval_spl e.g. psp8 format)
     734              : !!  - a gaussian atomic density (norm-conserving psps if nctval_spl is not available)
     735              : !!
     736              : !! INPUTS
     737              : !! atindx1(natom)=index table for atoms, inverse of atindx
     738              : !! dtset <type(dataset_type)>=all input variables in this dataset
     739              : !!  | densty(ntypat,4)=parameters for initialisation of the density of each atom type
     740              : !!  | icoulomb=0 periodic treatment of Hartree potential, 1 use of Poisson solver
     741              : !!  | ixc= choice of exchange-correlation scheme
     742              : !!  | natom=number of atoms in cell.
     743              : !!  | nspden=number of spin-density components
     744              : !!  | typat(natom)=integer type for each atom in cell
     745              : !! gmet(3,3)=reciprocal space metric
     746              : !! gprimd(3,3)=reciprocal space dimensional primitive translations
     747              : !! gsqcut=cutoff value on G**2 for sphere inside fft box
     748              : !! mgfft=maximum size of 1D FFTs
     749              : !! mpi_enreg=information about MPI parallelization
     750              : !! mqgrid=number of grid pts in q array for atomic density spline n^AT(q)
     751              : !! nattyp(ntypat)=number of atoms of each type in cell
     752              : !! nfft=(effective) number of FFT grid points (for this processor)
     753              : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     754              : !! ntypat=number of types of atoms in cell.
     755              : !! psps <type(pseudopotential_type)>=variables related to pseudopotentials
     756              : !! pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
     757              : !! ph1d(2,3*(2*mgfft+1)*natom)=1-dim phase information for given atom coordinates.
     758              : !! qgrid(mqgrid)=q grid for spline atomic valence density n^AT(q) from 0 to qmax
     759              : !! ucvol=unit cell volume (bohr**3).
     760              : !! usepaw= 0 for non paw calculation; =1 for paw calculation
     761              : !! vresid(nfft,nspden)=potential residual - (non-collinear magn. : only V11 and V22 are used)
     762              : !! zion(ntypat)=charge on each type of atom (real number)
     763              : !! znucl(ntypat)=atomic number, for each type of atom
     764              : !!
     765              : !! OUTPUT
     766              : !! gresid(3,natom)=forces due to the residual of the potential
     767              : !!
     768              : !! SOURCE
     769              : 
     770         4373 : subroutine fresidrsp(atindx1,dtset,gmet,gprimd,gresid,gsqcut,mgfft,mpi_enreg,mqgrid,nattyp,nfft,&
     771         4373 : &          ngfft,ntypat,psps,pawtab,ph1d,qgrid,rprimd,ucvol,usepaw,vresid,zion,znucl)
     772              : 
     773              : !Arguments ------------------------------------
     774              : !scalars
     775              :  integer,intent(in) :: mgfft,mqgrid,nfft,ntypat,usepaw
     776              :  real(dp),intent(in) :: gsqcut,ucvol
     777              :  type(pseudopotential_type),intent(in) :: psps
     778              :  type(MPI_type),intent(in) :: mpi_enreg
     779              :  type(dataset_type),intent(in) :: dtset
     780              : !arrays
     781              :  integer,intent(in) :: atindx1(dtset%natom),nattyp(ntypat),ngfft(18)
     782              :  real(dp),intent(in) :: gmet(3,3),gprimd(3,3),ph1d(2,3*(2*mgfft+1)*dtset%natom)
     783              :  real(dp),intent(in) :: qgrid(mqgrid),vresid(nfft,dtset%nspden),zion(ntypat)
     784              :  real(dp),intent(inout) :: rprimd(3,3)
     785              :  real(dp),intent(in) :: znucl(ntypat)
     786              :  real(dp),intent(out) :: gresid(3,dtset%natom)
     787              :  type(pawtab_type),intent(in) :: pawtab(ntypat*usepaw)
     788              : 
     789              : !Local variables-------------------------------
     790              : !scalars
     791              :  integer :: itypat,optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv
     792              :  logical :: usegauss
     793              : !arrays
     794              :  integer :: dummy3(3)
     795              :  real(dp) :: dummy2(2)
     796              :  real(dp) :: dummy_in1(0),dummy_in2(0)
     797              :  real(dp) :: dummy_out1(0),dummy_out2(0),dummy_out3(0),dummy_out4(0),dummy_out5(0),dummy_out6(0)
     798              :  real(dp) :: strn_dummy6(6),strv_dummy6(6)
     799         4373 :  real(dp),allocatable :: gauss(:,:),vresg(:,:),work(:)
     800              : 
     801              : ! *************************************************************************
     802              : 
     803              : !Inits
     804         4373 :  optatm=0;optdyfr=0;opteltfr=0;optgr=1;optstr=0;optv=0;optn=1
     805        13119 :  ABI_MALLOC(vresg,(2,nfft))
     806              : 
     807              : !Transfer potential residual to reciprocal space
     808              : !Use only Vres=Vres11+Vres22=Vres_up+Vres_dn
     809        13119 :  ABI_MALLOC(work,(nfft))
     810    231692637 :  work(:)=vresid(:,1)
     811      1192481 :  if (dtset%nspden>=2) work(:)=work(:)+vresid(:,2)
     812         4373 :  call fourdp(1,vresg,work,-1,mpi_enreg,nfft,1,ngfft,0)
     813         4373 :  ABI_FREE(work)
     814              : 
     815              : !Determine whether a gaussan atomic density has to be used or not
     816         4373 :  usegauss=.true.
     817         5071 :  if (usepaw==0) usegauss = any(.not.psps%nctab(1:ntypat)%has_tvale)
     818         9988 :  if (usepaw==1) usegauss=(minval(pawtab(1:ntypat)%has_tvale)==0)
     819         4373 :  if (usegauss) then
     820         1837 :    optn2=3
     821         5511 :    ABI_MALLOC(gauss,(2,ntypat))
     822         3686 :    do itypat=1,ntypat
     823         1849 :      gauss(1,itypat)=zion(itypat)
     824         3686 :      gauss(2,itypat) = atom_length(dtset%densty(itypat,1),zion(itypat),znucl(itypat))
     825              :    end do
     826         1837 :    call wrtout(std_out," Computing residual forces using gaussian functions as atomic densities", "COLL")
     827              :  else
     828         2536 :    optn2=2
     829         2536 :    ABI_MALLOC(gauss,(2,0))
     830         2536 :    call wrtout(std_out," Computing residual forces using atomic densities taken from pseudos", "COLL")
     831              :  end if
     832              : 
     833              : !Compute forces due to residual
     834              :  call atm2fft(atindx1,dummy_out1,dummy_out2,dummy_out3,dummy_out4,&
     835              : & dummy_out5,gauss,gmet,gprimd,gresid,dummy_out6,gsqcut,mgfft,&
     836              : & mqgrid,dtset%natom,nattyp,nfft,ngfft,ntypat,optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,&
     837              : & psps,pawtab,ph1d,qgrid,dummy3,dtset%rcut,dummy_in1,rprimd,strn_dummy6,strv_dummy6,ucvol,usepaw,&
     838              : & vresg,vresg,vresg,dummy2,dummy_in2,comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
     839         4373 : & paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
     840              : 
     841              : !In case of nspden>=2, has to apply 1/2 factor
     842         4701 :  if (dtset%nspden>=2) gresid=gresid*half
     843              : 
     844         4373 :  ABI_FREE(gauss)
     845         4373 :  ABI_FREE(vresg)
     846              : 
     847         4373 : end subroutine fresidrsp
     848              : !!***
     849              : 
     850              : !!****f* ABINIT/fresid
     851              : !! NAME
     852              : !! fresid
     853              : !!
     854              : !! FUNCTION
     855              : !! If option=1, compute the forces due to the residual of the potential
     856              : !! If option=2, generate approximate new density from old one,
     857              : !!              old atomic positions, and new atomic positions
     858              : !!
     859              : !! INPUTS
     860              : !! dtset <type(dataset_type)>=all input variables in this dataset
     861              : !!  | icoulomb=0 periodic treatment of Hartree potential, 1 use of Poisson solver
     862              : !!  | natom=number of atoms in cell.
     863              : !!  | nspden=number of spin-density components
     864              : !!  | typat(natom)=integer type for each atom in cell
     865              : !!  | usepaw= 0 for non paw calculation; =1 for paw calculation
     866              : !!  | xclevel= level of the XC functional
     867              : !! mpi_enreg=information about MPI parallelization
     868              : !! nfft=(effective) number of FFT grid points (for this processor)
     869              : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
     870              : !! ntypat=number of types of atoms in cell.
     871              : !! option=see below
     872              : !! pawtab(ntypat*dtset%usepaw) <type(pawtab_type)>=paw tabulated starting data
     873              : !! rhor(nfft,nspden)=electron density in electrons/bohr**3 (slices of it if FTT parallelism).
     874              : !! rprimd(3,3)=dimensional primitive translation vectors (bohr)
     875              : !! ucvol=unit cell volume (bohr**3).
     876              : !! xred_new(3,natom)=new reduced coordinates for atoms in unit cell
     877              : !! xred_old(3,natom)=old reduced coordinates for atoms in unit cell
     878              : !! znucl(ntypat)=real(dp), atomic number of atom type
     879              : !!
     880              : !! OUTPUT
     881              : !! gresid(3,natom)=forces due to the residual of the potential
     882              : !!
     883              : !! SIDE EFFECTS
     884              : !! work(nfft,nspden)=functions on the fft grid (slices of it if FTT parallelism):
     885              : !!  if option==1, the POTENTIAL residual is input
     886              : !!  if option==2, the interpolated density is output
     887              : !!
     888              : !! NOTES
     889              : !! FFT parallelism:
     890              : !! At the beginning of this routine, the plane-waves are ditributed over all the processors.
     891              : !! In the main part, all the processors perform the same calculations over the whole FFT grid.
     892              : !! At the end, each processor gets its part of the whole FFT grid.
     893              : !! These modifications are not efficient when large FFT grids are used.
     894              : !! So they have to be considered as a first step before a comprehensive parallelization of this routine.
     895              : !!
     896              : !! SOURCE
     897              : 
     898        21387 : subroutine fresid(dtset,gresid,mpi_enreg,nfft,ngfft,ntypat,option,&
     899        21387 : &                 pawtab,rhor,rprimd,ucvol,work,xred_new,xred_old,znucl)
     900              : 
     901              : !Arguments ------------------------------------
     902              : !scalars
     903              :  integer,intent(in) :: nfft,ntypat,option
     904              :  real(dp),intent(in) :: ucvol
     905              :  type(MPI_type),intent(in) :: mpi_enreg
     906              :  type(dataset_type),intent(in) :: dtset
     907              : !arrays
     908              :  integer,intent(in) :: ngfft(18)
     909              :  real(dp),intent(in) :: rhor(nfft,dtset%nspden),rprimd(3,3)
     910              :  real(dp),intent(in) :: xred_new(3,dtset%natom),xred_old(3,dtset%natom)
     911              :  real(dp),intent(in) :: znucl(ntypat)
     912              :  real(dp),intent(inout) :: work(nfft,dtset%nspden)
     913              :  real(dp),intent(out) :: gresid(3,dtset%natom)
     914              :  type(pawtab_type),intent(in) :: pawtab(ntypat*dtset%usepaw)
     915              : 
     916              : !Local variables-------------------------------
     917              : !real(dp), parameter :: app_remain=0.001_dp
     918              : !scalars
     919              :  integer,parameter :: natnum=110
     920              :  integer :: atmove,i1,i1_new,i1m,i1p,i2,i2_new,i2m,i2p,i3,i3_new,i3m,i3p
     921              :  integer :: iatom,ifft,ifft_new,iloop,ind2m,ind2m3m,ind2p,ind2p3p,ind3m,ind3p
     922              :  integer :: index,index_new,ishift,ishift1,ishift2,ishift3,ispden,ixp,mshift,mu
     923              :  integer :: n1,n2,n3,n4,nfft_tmp,nfftot,nu,quit
     924              :  real(dp),parameter :: app_remain=0.01_dp
     925              :  real(dp) :: diff_rem1,diff_rem2,diff_rem3,difmag,difmag2
     926              :  real(dp) :: difmag2_fact,difmag2_part,drho1,drho11,drho12,drho13,drho14
     927              :  real(dp) :: drho1dn,drho1mx,drho1my,drho1mz,drho1tot,drho1up,drho2,drho21
     928              :  real(dp) :: drho22,drho23,drho24,drho2dn,drho2mx,drho2my,drho2mz,drho2tot
     929              :  real(dp) :: drho2up,drho3,drho31,drho32,drho33,drho34,drho3dn,drho3mx,drho3my
     930              :  real(dp) :: drho3mz,drho3tot,drho3up,drhox00,drhox01,drhox10,drhox11,drhoxy0
     931              :  real(dp) :: drhoxy1,drhoxyz,fact,range,range2,rcov,rcov2,rcovm1,rdiff1
     932              :  real(dp) :: rdiff2,rdiff3,vresid1,vresid2,vresid3,vresid4,xx
     933              :  type(atomdata_t) :: atom
     934              : !arrays
     935              :  integer :: diff_igrid(3),igrid(3),irange(3)
     936        21387 :  integer,allocatable :: ii(:,:)
     937              :  real(dp) :: diff_grid(3),diff_rem(3),diff_tau(3),diff_xred(3),lencp(3)
     938              :  real(dp) :: rho_tot(4),rhosum(4),rmet(3,3),scale(3),tau(3)
     939        21387 :  real(dp),allocatable :: approp(:),atmrho(:,:),rhor_tot(:,:),rrdiff(:,:)
     940        21387 :  real(dp),allocatable :: work_tot(:,:)
     941        21387 :  logical,allocatable :: my_sphere(:)
     942              : 
     943              : ! *************************************************************************
     944              : 
     945              : !Compute lengths of cross products for pairs of primitive
     946              : !translation vectors (used in setting index search range below)
     947              :  lencp(1)=cross_fr(rprimd(1,2),rprimd(2,2),rprimd(3,2),&
     948        21387 : & rprimd(1,3),rprimd(2,3),rprimd(3,3))
     949              :  lencp(2)=cross_fr(rprimd(1,3),rprimd(2,3),rprimd(3,3),&
     950        21387 : & rprimd(1,1),rprimd(2,1),rprimd(3,1))
     951              :  lencp(3)=cross_fr(rprimd(1,1),rprimd(2,1),rprimd(3,1),&
     952        21387 : & rprimd(1,2),rprimd(2,2),rprimd(3,2))
     953              : 
     954              : !Compute factor R1.(R2xR3)/|R2xR3| etc for 1, 2, 3
     955              : !(recall ucvol=R1.(R2xR3))
     956        85548 :  scale(:)=ucvol/lencp(:)
     957              : 
     958              : !initialize diff_igrid, otherwise valgrind complains
     959        21387 :  diff_igrid=0
     960              : 
     961              : !Compute metric tensor in real space rmet
     962        85548 :  do nu=1,3
     963       278031 :    rmet(:,nu)=rprimd(1,:)*rprimd(1,nu)+rprimd(2,:)*rprimd(2,nu)+rprimd(3,:)*rprimd(3,nu)
     964              :  end do
     965              : 
     966              : !FFT parallelization: Starting from now, calculations are performed on the whole FFT grid
     967              : !and no more on slices. The nfft variable becomes nfft_tmp until the end
     968        21387 :  n1=ngfft(1);n2=ngfft(2);n3=ngfft(3)
     969        21387 :  n4=n3/mpi_enreg%nproc_fft
     970        85548 :  nfftot=PRODUCT(ngfft(1:3));nfft_tmp=nfftot
     971        21387 :  if(mpi_enreg%paral_kgb==1) then
     972            0 :    ABI_MALLOC(rhor_tot,(nfftot,dtset%nspden))
     973            0 :    ABI_MALLOC(work_tot,(nfftot,dtset%nspden))
     974            0 :    do ispden=1,dtset%nspden
     975            0 :      call pre_gather(rhor(:,ispden),rhor_tot(:,ispden),n1,n2,n3,n4,mpi_enreg)
     976            0 :      call pre_gather(work(:,ispden),work_tot(:,ispden),n1,n2,n3,n4,mpi_enreg)
     977              :    end do
     978              :  end if
     979              : 
     980       246991 :  gresid(1:3,1:dtset%natom)=0.0_dp
     981        21387 :  quit=0
     982              : 
     983              : !Initialize appropriation function
     984        64161 :  ABI_MALLOC(approp,(nfft_tmp))
     985        85548 :  ABI_MALLOC(atmrho,(nfft_tmp,dtset%nspden))
     986        64161 :  ABI_MALLOC(my_sphere,(nfft_tmp))
     987              : 
     988    382952698 :  approp(:)=app_remain
     989              : !First loop over atoms in unit cell : build appropriation function
     990              : !Second loop : compute forces
     991        64161 :  do iloop=1,2
     992              : 
     993              : !  Take into account the remaining density
     994        42774 :    if(option==2 .and. iloop==2)then
     995         2017 :      if(mpi_enreg%paral_kgb==1) then
     996              : !      FFT parallelization: All the processors perform the same calculation.
     997              : !      We divided by nproc_fft in order to "remove" the xmpi_sum made in mean_fftr
     998            0 :        do ispden=1,dtset%nspden
     999            0 :          do ifft=1,nfft_tmp
    1000            0 :            work_tot(ifft,ispden)=rhor_tot(ifft,ispden)*approp(ifft)*app_remain
    1001              :          end do
    1002              :        end do
    1003            0 :        call mean_fftr(work_tot,rhosum,nfft_tmp,nfftot,dtset%nspden,mpi_comm_sphgrid=mpi_enreg%comm_fft)
    1004            0 :        rhosum(1:dtset%nspden)=rhosum(1:dtset%nspden)/mpi_enreg%nproc_fft
    1005              :      else
    1006         4209 :        do ispden=1,dtset%nspden
    1007     38938549 :          do ifft=1,nfft_tmp
    1008     38936532 :            work(ifft,ispden)=rhor(ifft,ispden)*approp(ifft)*app_remain
    1009              :          end do
    1010              :        end do
    1011         2017 :        call mean_fftr(work,rhosum,nfft_tmp,nfftot,dtset%nspden,mpi_comm_sphgrid=mpi_enreg%comm_fft)
    1012              :      end if
    1013              : 
    1014              : !    This will be used to restore proper normalization of density
    1015         4209 :      rho_tot(1:dtset%nspden)=rhosum(1:dtset%nspden)*nfftot
    1016              :    end if
    1017              : 
    1018       155576 :    do iatom=1,dtset%natom
    1019              : 
    1020              : !    Get the covalent radius
    1021       112802 :      call atomdata_from_znucl(atom,znucl(dtset%typat(iatom)))
    1022       112802 :      rcov = atom%rcov
    1023              : !    PAW choose PAW radius instead...
    1024       112802 :      if (dtset%usepaw==1) rcov=max(rcov,pawtab(dtset%typat(iatom))%rpaw)
    1025              : 
    1026              : !    Set search range
    1027       112802 :      rcov2=rcov**2
    1028       112802 :      range=2._dp*rcov
    1029       112802 :      range2=range**2
    1030       112802 :      rcovm1=1.0_dp/rcov
    1031              : 
    1032              : !    Use range to compute an index range along R(1:3)
    1033              : !    (add 1 to make sure it covers full range)
    1034       112802 :      irange(1)=1+nint((range/scale(1))*dble(n1))
    1035       112802 :      irange(2)=1+nint((range/scale(2))*dble(n2))
    1036       112802 :      irange(3)=1+nint((range/scale(3))*dble(n3))
    1037              : 
    1038              : !    Allocate ii and rrdiff
    1039       451208 :      mshift=2*maxval(irange(1:3))+1
    1040       338406 :      ABI_MALLOC(ii,(mshift,3))
    1041       338406 :      ABI_MALLOC(rrdiff,(mshift,3))
    1042              : 
    1043              : !    Consider each component in turn
    1044       451208 :      do mu=1,3
    1045              : 
    1046              : !      Convert reduced coord of given atom to [0,1)
    1047       338406 :        tau(mu)=mod(xred_old(mu,iatom)+1._dp-aint(xred_old(mu,iatom)),1._dp)
    1048              : 
    1049              : !      Use tau to find nearest grid point along R(mu)
    1050              : !      (igrid=0 is the origin; shift by 1 to agree with usual index)
    1051       338406 :        igrid(mu)=nint(tau(mu)*dble(ngfft(mu)))
    1052              : 
    1053              : !      Set up a counter that explore the relevant range
    1054              : !      of points around the atom
    1055       338406 :        ishift=0
    1056      7114704 :        do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
    1057      6776298 :          ishift=ishift+1
    1058      6776298 :          ii(ishift,mu)=1+mod(ngfft(mu)+mod(ixp,ngfft(mu)),ngfft(mu))
    1059      7114704 :          rrdiff(ishift,mu)=dble(ixp)/dble(ngfft(mu))-tau(mu)
    1060              :        end do
    1061              : 
    1062              : !      If option 2, set up quantities related with the change of atomic coordinates
    1063       451208 :        if(option==2 .and. iloop==2)then
    1064        17055 :          diff_xred(mu)=xred_new(mu,iatom)-xred_old(mu,iatom)
    1065              : !        Convert to [0,1)
    1066        17055 :          diff_tau(mu)=mod(diff_xred(mu)+1._dp-aint(diff_xred(mu)),1._dp)
    1067              : !        Convert to [0,ngfft)
    1068        17055 :          diff_grid(mu)=diff_tau(mu)*dble(ngfft(mu))
    1069              : !        Integer part
    1070        17055 :          diff_igrid(mu)=int(diff_grid(mu))
    1071              : !        Compute remainder
    1072        17055 :          diff_rem(mu)=diff_grid(mu)-diff_igrid(mu)
    1073              : 
    1074              : !        DEBUG
    1075              : !        write(std_out,*)' mu,diff',mu,diff_igrid(mu),diff_rem(mu)
    1076              : !        ENDDEBUG
    1077              : 
    1078              :        end if
    1079              : 
    1080              : !      End loop on mu
    1081              :      end do
    1082              : 
    1083              : !    May be the atom is fixed
    1084       112802 :      atmove=1
    1085       112802 :      if(option==2 .and. iloop==2)then
    1086         5685 :        if(diff_xred(1)**2+diff_xred(2)**2+diff_xred(3)**2 < 1.0d-24)then
    1087              :          atmove=0
    1088              :        else
    1089         4233 :          diff_rem1=diff_rem(1)
    1090         4233 :          diff_rem2=diff_rem(2)
    1091         4233 :          diff_rem3=diff_rem(3)
    1092              :        end if
    1093              :      end if
    1094              : 
    1095              : !    If second loop, initialize atomic density, and the variable
    1096              : !    that says whether a fft point belongs to the sphere of the atom
    1097       107117 :      if(iloop==2) then
    1098   1708975250 :        atmrho(:,:)=0.0_dp
    1099   1596391643 :        my_sphere(:)=.false.
    1100              :      end if
    1101              : 
    1102              : !    Conduct triple loop over restricted range of grid points for iatom
    1103              : 
    1104      2356636 :      do ishift3=1,1+2*irange(3)
    1105              : !      map back to [1,ngfft(3)] for usual fortran index in unit cell
    1106      2243834 :        i3=ii(ishift3,3)
    1107      2243834 :        i3m=i3-1 ; if(i3==1)i3m=n3
    1108      2243834 :        i3p=i3+1 ; if(i3==n3)i3p=1
    1109              : 
    1110              : !      find vector from atom location to grid point (reduced)
    1111      2243834 :        rdiff3=rrdiff(ishift3,3)
    1112              : 
    1113     61458442 :        do ishift2=1,1+2*irange(2)
    1114     59101806 :          i2=ii(ishift2,2)
    1115     59101806 :          i2m=i2-1 ; if(i2==1)i2m=n2
    1116     59101806 :          i2p=i2+1 ; if(i2==n2)i2p=1
    1117     59101806 :          index=n1*(i2-1+n2*(i3-1))
    1118     59101806 :          ind3m=n1*(i2-1+n2*(i3m-1))
    1119     59101806 :          ind3p=n1*(i2-1+n2*(i3p-1))
    1120     59101806 :          ind2m=n1*(i2m-1+n2*(i3-1))
    1121     59101806 :          ind2p=n1*(i2p-1+n2*(i3-1))
    1122     59101806 :          ind2p3p=n1*(i2p-1+n2*(i3p-1))
    1123              : 
    1124     59101806 :          rdiff2=rrdiff(ishift2,2)
    1125              : !        Prepare the computation of difmag2
    1126              :          difmag2_part=rmet(3,3)*rdiff3**2+rmet(2,2)*rdiff2**2&
    1127     59101806 : &         +2.0_dp*rmet(3,2)*rdiff3*rdiff2
    1128     59101806 :          difmag2_fact=2.0_dp*(rmet(3,1)*rdiff3+rmet(2,1)*rdiff2)
    1129              : 
    1130   2069358086 :          do ishift1=1,1+2*irange(1)
    1131   2008012446 :            rdiff1=rrdiff(ishift1,1)
    1132              : 
    1133              : !          Compute (rgrid-tau-Rprim)**2
    1134   2008012446 :            difmag2= difmag2_part+rdiff1*(difmag2_fact+rmet(1,1)*rdiff1)
    1135              : 
    1136              : !          Only accept contribution inside defined range
    1137              : !          This condition means that x, calculated below, cannot exceed 2.0_dp
    1138   2067114252 :            if (difmag2<range2) then
    1139              : 
    1140              : !            Will compute contribution to appropriation function based on
    1141              : !            rcov2, range2 and difmag2
    1142    677755748 :              i1=ii(ishift1,1)
    1143    677755748 :              ifft=i1+index
    1144              : 
    1145    677755748 :              if(iloop==1)then
    1146              : 
    1147              : !              Build appropriation function
    1148    338877874 :                if (difmag2<rcov2)then
    1149     42373024 :                  approp(ifft)=approp(ifft)+1.0_dp
    1150              :                else
    1151    296504850 :                  difmag=sqrt(difmag2)
    1152    296504850 :                  xx=difmag*rcovm1
    1153              : !                The following function is 1. at xx=1, 0. at xx=2, with vanishing
    1154              : !                derivatives at these points.
    1155    296504850 :                  approp(ifft)=approp(ifft)+((2.0_dp*xx-9.0_dp)*xx+12.0_dp)*xx-4.0_dp
    1156              :                end if
    1157              : 
    1158              :              else
    1159              : 
    1160    338877874 :                if (difmag2<rcov2) then
    1161              :                  fact=one
    1162              :                else
    1163    296504850 :                  difmag=sqrt(difmag2)
    1164    296504850 :                  xx=difmag*rcovm1
    1165    296504850 :                  fact=((2.0_dp*xx-9.0_dp)*xx+12.0_dp)*xx-4.0_dp
    1166              :                end if
    1167              : 
    1168              : !              Build atomic density
    1169    338877874 :                if(mpi_enreg%paral_kgb==1) then
    1170              :                  atmrho(ifft,1:dtset%nspden)=atmrho(ifft,1:dtset%nspden) &
    1171            0 : &                 +rhor_tot(ifft,1:dtset%nspden)*fact*approp(ifft)
    1172              :                else
    1173              :                  atmrho(ifft,1:dtset%nspden)=atmrho(ifft,1:dtset%nspden) &
    1174    731581060 : &                 +rhor(ifft,1:dtset%nspden)*fact*approp(ifft)
    1175              :                end if
    1176              : 
    1177              : !              Compute the sphere of the atom : it is different for
    1178              : !              option 1 and for option 2
    1179    338877874 :                i1p=i1+1 ; if(i1==n1)i1p=1
    1180    338877874 :                if(option==1)then
    1181    307499042 :                  i1m=i1-1 ; if(i1==1)i1m=n1
    1182    307499042 :                  my_sphere(ifft)=.true.
    1183    307499042 :                  my_sphere(i1p+index)=.true. ; my_sphere(i1m+index)=.true.
    1184    307499042 :                  my_sphere(i1+ind2p)=.true. ; my_sphere(i1+ind2m)=.true.
    1185    307499042 :                  my_sphere(i1+ind3p)=.true. ; my_sphere(i1+ind3m)=.true.
    1186              :                else
    1187     31378832 :                  my_sphere(ifft)=.true. ; my_sphere(i1p+index)=.true.
    1188     31378832 :                  my_sphere(i1+ind2p)=.true. ; my_sphere(i1p+ind2p)=.true.
    1189     31378832 :                  my_sphere(i1+ind3p)=.true. ; my_sphere(i1p+ind3p)=.true.
    1190     31378832 :                  my_sphere(i1+ind2p3p)=.true. ; my_sphere(i1p+ind2p3p)=.true.
    1191              :                end if
    1192              : 
    1193              :              end if
    1194              : 
    1195              : !            End of condition on the range
    1196              :            end if
    1197              : 
    1198              : !          End loop on ishift1
    1199              :          end do
    1200              : 
    1201              : !        End loop on ishift2
    1202              :        end do
    1203              : 
    1204              : !      End loop on ishift3
    1205              :      end do
    1206              : !    At the end of the second loop for each atom, compute the force
    1207              : !    from the atomic densities, or translate density.
    1208              : !    In the first case, use a two-point finite-difference approximation,
    1209              : !    since this calculation serves only to decrease the error,
    1210              : !    and should not be very accurate, but fast.
    1211              : !    In the second case, using a crude trilinear interpolation scheme
    1212              : !    for the same reason.
    1213              : !
    1214              : !    The section is skipped if option==2 and the atom is fixed
    1215       112802 :      if(iloop==2 .and. (option==1 .or. atmove==1) )then
    1216              : 
    1217      1371341 :        do i3=1,n3
    1218      1316392 :          i3m=i3-1 ; if(i3==1)i3m=n3
    1219      1316392 :          i3p=i3+1 ; if(i3==n3)i3p=1
    1220              : !        note: diff_igrid is only set  if(option==2 .and. iloop==2)
    1221      1316392 :          i3_new=i3+diff_igrid(3) ; if(i3_new > n3)i3_new=i3_new-n3
    1222     41297387 :          do i2=1,n2
    1223     39926046 :            i2m=i2-1 ; if(i2==1)i2m=n2
    1224     39926046 :            i2p=i2+1 ; if(i2==n2)i2p=1
    1225     39926046 :            i2_new=i2+diff_igrid(2) ; if(i2_new > n2)i2_new=i2_new-n2
    1226     39926046 :            index=n1*(i2-1+n2*(i3-1))
    1227     39926046 :            index_new=n1*(i2_new-1+n2*(i3_new-1))
    1228     39926046 :            ind3m=n1*(i2-1+n2*(i3m-1))
    1229     39926046 :            ind3p=n1*(i2-1+n2*(i3p-1))
    1230     39926046 :            ind2m=n1*(i2m-1+n2*(i3-1))
    1231     39926046 :            ind2p=n1*(i2p-1+n2*(i3-1))
    1232     39926046 :            ind2m3m=n1*(i2m-1+n2*(i3m-1))
    1233   1627916196 :            do i1=1,n1
    1234   1586673758 :              ifft=i1+index
    1235   1626599804 :              if(my_sphere(ifft))then
    1236              : 
    1237    309607368 :                i1m=i1-1 ; if(i1==1)i1m=n1
    1238              : 
    1239    309607368 :                if(option==1)then
    1240              : !                Treat option 1 : computation of residual forces
    1241    287723562 :                  i1p=i1+1 ; if(i1==n1)i1p=1
    1242              : !                Distinguish spin-unpolarized and spin-polarized
    1243    287723562 :                  if(dtset%nspden==1)then ! Non magnetic
    1244              : !                  Note that the factor needed to obtain a true finite difference
    1245              : !                  estimation of the derivative will be applied afterwards, for speed
    1246    255981919 :                    drho1=atmrho(i1p+index,1)-atmrho(i1m+index,1)
    1247    255981919 :                    drho2=atmrho(i1+ind2p,1) -atmrho(i1+ind2m,1)
    1248    255981919 :                    drho3=atmrho(i1+ind3p,1) -atmrho(i1+ind3m,1)
    1249    255981919 :                    if(mpi_enreg%paral_kgb==1) then
    1250            0 :                      vresid1=work_tot(ifft,1)
    1251              :                    else
    1252    255981919 :                      vresid1=work(ifft,1)
    1253              :                    end if
    1254    255981919 :                    gresid(1,iatom)=gresid(1,iatom)+drho1*vresid1
    1255    255981919 :                    gresid(2,iatom)=gresid(2,iatom)+drho2*vresid1
    1256    255981919 :                    gresid(3,iatom)=gresid(3,iatom)+drho3*vresid1
    1257     31741643 :                  else if(dtset%nspden==2) then ! Collinear magnetism
    1258     28783850 :                    drho1tot=atmrho(i1p+index,1)-atmrho(i1m+index,1)
    1259     28783850 :                    drho2tot=atmrho(i1+ind2p,1) -atmrho(i1+ind2m,1)
    1260     28783850 :                    drho3tot=atmrho(i1+ind3p,1) -atmrho(i1+ind3m,1)
    1261     28783850 :                    drho1up=atmrho(i1p+index,2)-atmrho(i1m+index,2)
    1262     28783850 :                    drho2up=atmrho(i1+ind2p,2) -atmrho(i1+ind2m,2)
    1263     28783850 :                    drho3up=atmrho(i1+ind3p,2) -atmrho(i1+ind3m,2)
    1264     28783850 :                    drho1dn=drho1tot-drho1up
    1265     28783850 :                    drho2dn=drho2tot-drho2up
    1266     28783850 :                    drho3dn=drho3tot-drho3up
    1267     28783850 :                    if(mpi_enreg%paral_kgb==1) then
    1268            0 :                      vresid1=work_tot(ifft,1)
    1269            0 :                      vresid2=work_tot(ifft,2)
    1270              :                    else
    1271     28783850 :                      vresid1=work(ifft,1)
    1272     28783850 :                      vresid2=work(ifft,2)
    1273              :                    end if
    1274     28783850 :                    gresid(1,iatom)=gresid(1,iatom)+drho1up*vresid1+drho1dn*vresid2
    1275     28783850 :                    gresid(2,iatom)=gresid(2,iatom)+drho2up*vresid1+drho2dn*vresid2
    1276     28783850 :                    gresid(3,iatom)=gresid(3,iatom)+drho3up*vresid1+drho3dn*vresid2
    1277              :                  else ! Non-collinear magnetism
    1278      2957793 :                    drho1tot=atmrho(i1p+index,1)-atmrho(i1m+index,1)
    1279      2957793 :                    drho1mx =atmrho(i1p+index,2)-atmrho(i1m+index,2)
    1280      2957793 :                    drho1my =atmrho(i1p+index,3)-atmrho(i1m+index,3)
    1281      2957793 :                    drho1mz =atmrho(i1p+index,4)-atmrho(i1m+index,4)
    1282      2957793 :                    drho2tot=atmrho(i1+ind2p,1) -atmrho(i1+ind2m,1)
    1283      2957793 :                    drho2mx =atmrho(i1+ind2p,2) -atmrho(i1+ind2m,2)
    1284      2957793 :                    drho2my =atmrho(i1+ind2p,3) -atmrho(i1+ind2m,3)
    1285      2957793 :                    drho2mz =atmrho(i1+ind2p,4) -atmrho(i1+ind2m,4)
    1286      2957793 :                    drho3tot=atmrho(i1+ind3p,1) -atmrho(i1+ind3m,1)
    1287      2957793 :                    drho3mx =atmrho(i1+ind3p,2) -atmrho(i1+ind3m,2)
    1288      2957793 :                    drho3my =atmrho(i1+ind3p,3) -atmrho(i1+ind3m,3)
    1289      2957793 :                    drho3mz =atmrho(i1+ind3p,4) -atmrho(i1+ind3m,4)
    1290      2957793 :                    drho11=half*(drho1tot+drho1mz)
    1291      2957793 :                    drho12=half*(drho1tot-drho1mz)
    1292      2957793 :                    drho13= half*drho1mx
    1293      2957793 :                    drho14=-half*drho1my
    1294      2957793 :                    drho21=half*(drho2tot+drho2mz)
    1295      2957793 :                    drho22=half*(drho2tot-drho2mz)
    1296      2957793 :                    drho23= half*drho2mx
    1297      2957793 :                    drho24=-half*drho2my
    1298      2957793 :                    drho31=half*(drho3tot+drho3mz)
    1299      2957793 :                    drho32=half*(drho3tot-drho3mz)
    1300      2957793 :                    drho33= half*drho3mx
    1301      2957793 :                    drho34=-half*drho3my
    1302      2957793 :                    if(mpi_enreg%paral_kgb==1) then
    1303            0 :                      vresid1=work_tot(ifft,1)
    1304            0 :                      vresid2=work_tot(ifft,2)
    1305            0 :                      vresid3=work_tot(ifft,3)
    1306            0 :                      vresid4=work_tot(ifft,4)
    1307              :                    else
    1308      2957793 :                      vresid1=work(ifft,1)
    1309      2957793 :                      vresid2=work(ifft,2)
    1310      2957793 :                      vresid3=work(ifft,3)
    1311      2957793 :                      vresid4=work(ifft,4)
    1312              :                    end if
    1313      2957793 :                    gresid(1,iatom)=gresid(1,iatom)+drho11*vresid1+drho12*vresid2+two*(drho13*vresid3+drho14*vresid4)
    1314      2957793 :                    gresid(2,iatom)=gresid(2,iatom)+drho21*vresid1+drho22*vresid2+two*(drho23*vresid3+drho24*vresid4)
    1315      2957793 :                    gresid(3,iatom)=gresid(3,iatom)+drho31*vresid1+drho32*vresid2+two*(drho33*vresid3+drho34*vresid4)
    1316              :                  end if
    1317              : !                Treat the case option==2 now : trilinear interpolation of the density
    1318              :                else
    1319     21883806 :                  i1_new=i1+diff_igrid(1) ; if(i1_new > n1)i1_new=i1_new-n1
    1320     21883806 :                  ifft_new=i1_new+index_new
    1321     46555152 :                  do ispden=1,dtset%nspden
    1322              :                    drhox00=(atmrho(i1m+index,ispden)-atmrho(i1+index,ispden))*diff_rem1 &
    1323     24671346 : &                   +atmrho(i1+index,ispden)
    1324              :                    drhox10=(atmrho(i1m+ind2m,ispden)-atmrho(i1+ind2m,ispden))*diff_rem1 &
    1325     24671346 : &                   +atmrho(i1+ind2m,ispden)
    1326              :                    drhox01=(atmrho(i1m+ind3m,ispden)-atmrho(i1+ind3m,ispden))*diff_rem1 &
    1327     24671346 : &                   +atmrho(i1+ind3m,ispden)
    1328              :                    drhox11=(atmrho(i1m+ind2m3m,ispden)-atmrho(i1+ind2m3m,ispden))*diff_rem1 &
    1329     24671346 : &                   +atmrho(i1+ind2m3m,ispden)
    1330     24671346 :                    drhoxy0=(drhox10-drhox00)*diff_rem2+drhox00
    1331     24671346 :                    drhoxy1=(drhox11-drhox01)*diff_rem2+drhox01
    1332     24671346 :                    drhoxyz=(drhoxy1-drhoxy0)*diff_rem3+drhoxy0
    1333     24671346 :                    if(mpi_enreg%paral_kgb==1) then
    1334            0 :                      work_tot(ifft_new,ispden)=work_tot(ifft_new,ispden)+drhoxyz
    1335              :                    else
    1336     24671346 :                      work(ifft_new,ispden)=work(ifft_new,ispden)+drhoxyz
    1337              :                    end if
    1338     46555152 :                    rho_tot(ispden)=rho_tot(ispden)+drhoxyz
    1339              :                  end do
    1340              :                end if
    1341              : 
    1342              : !              End condition of belonging to the sphere of influence of the atom
    1343              :              end if
    1344              :            end do
    1345              :          end do
    1346              :        end do
    1347              : !      The finite-difference factor applied here also take
    1348              : !      into account diverse factors
    1349        54949 :        fact=-ucvol/dble(nfftot)
    1350        54949 :        gresid(1,iatom)=gresid(1,iatom)*dble(n1)*.5_dp*fact
    1351        54949 :        gresid(2,iatom)=gresid(2,iatom)*dble(n2)*.5_dp*fact
    1352        54949 :        gresid(3,iatom)=gresid(3,iatom)*dble(n3)*.5_dp*fact
    1353              :      end if
    1354              : 
    1355              : !    Update work if the atom is fixed.
    1356        56401 :      if(iloop==2 .and. option==2 .and. atmove==0)then
    1357         1452 :        if(mpi_enreg%paral_kgb==1) then
    1358              : !        FFT parallelization: All the processors perform the same calculation.
    1359              : !        We divided by nproc_fft in order to "remove" the xmpi_sum made in mean_fftr
    1360            0 :          do ispden=1,dtset%nspden
    1361            0 :            do ifft=1,nfft_tmp
    1362            0 :              work_tot(ifft,ispden)=work_tot(ifft,ispden)+atmrho(ifft,ispden)
    1363              :            end do
    1364              :          end do
    1365            0 :          call mean_fftr(atmrho,rhosum,nfft_tmp,nfftot,dtset%nspden,mpi_comm_sphgrid=mpi_enreg%comm_fft)
    1366            0 :          rhosum(1:dtset%nspden)=rhosum(1:dtset%nspden)/mpi_enreg%nproc_fft
    1367              :        else
    1368         2940 :          do ispden=1,dtset%nspden
    1369     10819304 :            do ifft=1,nfft_tmp
    1370     10817852 :              work(ifft,ispden)=work(ifft,ispden)+atmrho(ifft,ispden)
    1371              :            end do
    1372              :          end do
    1373         1452 :          call mean_fftr(atmrho,rhosum,nfft_tmp,nfftot,dtset%nspden,mpi_comm_sphgrid=mpi_enreg%comm_fft)
    1374              :        end if
    1375              : 
    1376         2940 :        rho_tot(1:dtset%nspden)=rho_tot(1:dtset%nspden)+rhosum(1:dtset%nspden)*nfftot
    1377              :      end if
    1378              : 
    1379       112802 :      ABI_FREE(ii)
    1380       268378 :      ABI_FREE(rrdiff)
    1381              : 
    1382              : !    End loop on atoms
    1383              :    end do
    1384              : 
    1385              : !  DEBUG
    1386              : !  if(option==2)then
    1387              : !  if(iloop==1)then
    1388              : !  write(std_out,*)' fresid : rhor, approp'
    1389              : !  do ifft=1,n1
    1390              : !  write(std_out,*)ifft,rhor(ifft,1),approp(ifft)
    1391              : !  end do
    1392              : !  end if
    1393              : !  if(iloop==2)then
    1394              : !  write(std_out,*)' fresid : rhor, approp, work(:,:)'
    1395              : !  do ifft=1,n1
    1396              : !  write(std_out,'(i4,3es18.8)' )ifft,rhor(ifft,1),approp(ifft),work(ifft,1)
    1397              : !  end do
    1398              : !  do ifft=1,nfft_tmp
    1399              : !  if(work(ifft,1)<0.0_dp)then
    1400              : !  write(std_out,*)' f_fft negative value',work(ifft,1),' for ifft=',ifft
    1401              : !  end if
    1402              : !  if(rhor(ifft,1)<0.0_dp)then
    1403              : !  write(std_out,*)' rhor  negative value',rhor(ifft,1),' for ifft=',ifft
    1404              : !  end if
    1405              : !  end do
    1406              : !  end if
    1407              : !  end if
    1408              : !  ENDDEBUG
    1409              : 
    1410              :    if(quit==1)exit
    1411              : 
    1412              : !  At the end of the first loop, where the appropriation function is generated,
    1413              : !  invert it, to save cpu time later.
    1414    382995472 :    if(iloop==1)approp(:)=1.0_dp/approp(:)
    1415              : 
    1416              : !  End first or second pass through atoms
    1417              :  end do
    1418              : 
    1419              : !Restore proper normalisation of density
    1420              : !(Non-collinear magnetism: n, mx,my,mz integral conservation)
    1421        21387 :  if(option==2)then
    1422         2017 :    if(mpi_enreg%paral_kgb==1) then
    1423              : !    FFT parallelization: All the processors perform the same calculation.
    1424              : !    We divided by nproc_fft in order to "remove" the xmpi_sum made in mean_fftr
    1425              : !    Trangel: mpicomm now is optional in mean_fftr, no need to divide over nproc_fft
    1426            0 :      call mean_fftr(rhor_tot,rhosum,nfft_tmp,nfftot,dtset%nspden)
    1427              : !    rhosum(1:dtset%nspden)=rhosum(1:dtset%nspden)/mpi_enreg%nproc_fft
    1428              :    else
    1429         2017 :      call mean_fftr(rhor,rhosum,nfft_tmp,nfftot,dtset%nspden,mpi_comm_sphgrid=mpi_enreg%comm_fft)
    1430              :    end if
    1431              : !  "!OCL NOPREEX" to avoid zero division after optimization (-Of) by MM
    1432              : !  (Even if nspden=1, "1.0/rho_tot" will appear on vpp fujitsu
    1433              : !  OCL NOPREEX
    1434         2017 :    if(mpi_enreg%paral_kgb==1) then
    1435            0 :      do ispden=1,dtset%nspden
    1436            0 :        fact=rhosum(ispden)*dble(nfftot)/rho_tot(ispden)
    1437            0 :        work_tot(:,ispden)=fact*work_tot(:,ispden)
    1438            0 :        call pre_scatter(work(:,ispden),work_tot(:,ispden),n1,n2,n3,n4,mpi_enreg)
    1439              :      end do
    1440              :    else
    1441         4209 :      do ispden=1,dtset%nspden
    1442         2192 :        fact=rhosum(ispden)*dble(nfftot)/rho_tot(ispden)
    1443     38938549 :        work(:,ispden)=fact*work(:,ispden)
    1444              :      end do
    1445              :    end if
    1446              : !  DEBUG
    1447              : !  Here, zero all the hard work, for checking purposes !
    1448              : !  work(:,:)=rhor(:,:)
    1449              : !  ENDDEBUG
    1450              :  end if
    1451              : 
    1452        21387 :  ABI_FREE(approp)
    1453        21387 :  ABI_FREE(atmrho)
    1454        21387 :  ABI_FREE(my_sphere)
    1455        21387 :  if(mpi_enreg%paral_kgb==1) then
    1456            0 :    ABI_FREE(rhor_tot)
    1457            0 :    ABI_FREE(work_tot)
    1458              :  end if
    1459              : 
    1460              : !DEBUG
    1461              : !write(std_out,*)' fresid : exit '
    1462              : !do iatom=1,dtset%natom
    1463              : !write(std_out,*)iatom,gresid(1:3,iatom)
    1464              : !enddo
    1465              : !ENDDEBUG
    1466              : 
    1467              :  contains
    1468              : 
    1469        64161 :    function cross_fr(xx,yy,zz,aa,bb,cc)
    1470              : !Define magnitude of cross product of two vectors
    1471              :    real(dp) :: cross_fr
    1472              :    real(dp),intent(in) :: xx,yy,zz,aa,bb,cc
    1473        64161 :    cross_fr=sqrt((yy*cc-zz*bb)**2+(zz*aa-xx*cc)**2+(xx*bb-yy*aa)**2)
    1474        64161 :  end function cross_fr
    1475              : 
    1476              : end subroutine fresid
    1477              : !!***
    1478              : 
    1479              : !!****f* ABINIT/constrf
    1480              : !! NAME
    1481              : !! constrf
    1482              : !!
    1483              : !! FUNCTION
    1484              : !! Computes projected forces, fpcart, which satisfy a set of
    1485              : !! constraint equations of the form
    1486              : !!  Sum[mu,iatom]: wtatcon(mu,iatom,iconeq)*fpcart(mu,iatom) = 0 (iconeq=1,nconeq).
    1487              : !! These projected forces are returned in fcart and thus replace
    1488              : !! the original forces.
    1489              : !!
    1490              : !! INPUTS
    1491              : !!  iatfix(3,natom)=1 for frozen atom along each direction, 0 for unfrozen
    1492              : !!  natom=number of atoms in cell
    1493              : !!  nconeq=number of atomic constraint equations
    1494              : !!  prtvol=control print volume and debugging
    1495              : !!  rprimd(3,3)=dimensional primitive translations in real space (bohr)
    1496              : !!  wtatcon(3,natom,nconeq)=weights for atomic constraints
    1497              : !!  xred(3,natom)=reduced dimensionless atomic coordinates
    1498              : !!
    1499              : !! OUTPUT
    1500              : !!  diffor=maximum absolute change in component of projected fcart between present
    1501              : !!          and previous SCF cycle
    1502              : !!  gred(3,natom)=grads of Etot wrt reduced coordinates (hartree)
    1503              : !!  maxfor=maximum absolute value of fcart
    1504              : !!
    1505              : !! SIDE EFFECTS
    1506              : !!  fcart(3,natom)=cartesian forces (hartree/bohr) on input, projected forces on output
    1507              : !!  forold(3,natom)=cartesian forces of previous SCF cycle (hartree/bohr)
    1508              : !!
    1509              : !! TODO
    1510              : !!
    1511              : !! SOURCE
    1512              : 
    1513          740 : subroutine constrf(diffor,fcart,forold,gred,iatfix,ionmov,maxfor,natom,&
    1514          740 : & nconeq,prtvol,rprimd,wtatcon,xred)
    1515              : 
    1516              :  use m_linalg_interfaces
    1517              : 
    1518              : !Arguments ------------------------------------
    1519              : !scalars
    1520              :  integer,intent(in) :: ionmov,natom,nconeq,prtvol
    1521              :  real(dp),intent(out) :: diffor,maxfor
    1522              : !arrays
    1523              :  integer,intent(in) :: iatfix(3,natom)
    1524              :  real(dp),intent(in) :: rprimd(3,3),wtatcon(3,natom,nconeq)
    1525              :  real(dp),intent(inout) :: fcart(3,natom),forold(3,natom),xred(3,natom)
    1526              :  real(dp),intent(inout) :: gred(3,natom) !vz_i
    1527              : 
    1528              : !Local variables -------------------------
    1529              : !scalars
    1530              :  integer :: iatom,iconeq,iconeq1,iconeq2,index,info,mu,prtvel
    1531              :  character(len=500) :: message
    1532              : !arrays
    1533          740 :  real(dp),allocatable :: fcartvec(:),fpcart(:,:),fvector(:),vel_dummy(:,:)
    1534          740 :  real(dp),allocatable :: wmatrix(:,:),wtatconvec(:,:),wtcoeffs(:),xcart(:,:)
    1535              : 
    1536              : !************************************************************************
    1537              : 
    1538              : !Allocate temporary variables
    1539         2220 :  ABI_MALLOC(fpcart,(3,natom))
    1540         2960 :  ABI_MALLOC(fcartvec,(3*natom))
    1541         2220 :  ABI_MALLOC(fvector,(nconeq))
    1542         1480 :  ABI_MALLOC(vel_dummy,(3,natom))
    1543         2960 :  ABI_MALLOC(wmatrix,(nconeq,nconeq))
    1544         2960 :  ABI_MALLOC(wtatconvec,(3*natom,nconeq))
    1545         1480 :  ABI_MALLOC(wtcoeffs,(nconeq))
    1546         1480 :  ABI_MALLOC(xcart,(3,natom))
    1547              : 
    1548              : !If prtvol>10, output coordinates and forces prior to projecting
    1549          740 :  if(prtvol>=10)then
    1550          132 :    write(message,'(a)')' constrf - coordinates and forces prior to constraint projections:'
    1551          132 :    call wrtout(std_out,message,'COLL')
    1552          132 :    call xred2xcart(natom,rprimd,xcart,xred)
    1553          132 :    prtvel=0
    1554          132 :    call prtxvf(fcart,gred,iatfix,06,natom,prtvel,vel_dummy,xcart,xred)
    1555              :  end if
    1556              : 
    1557              : !Transfer fcart and wtatcon to flat vectors
    1558              :  index=0
    1559         4040 :  do iatom=1,natom
    1560        13940 :    do mu=1,3
    1561         9900 :      index=index+1
    1562         9900 :      fcartvec(index)=fcart(mu,iatom)
    1563        23100 :      wtatconvec(index,:)=wtatcon(mu,iatom,:)
    1564              :    end do
    1565              :  end do
    1566              : 
    1567              : !Compute a matrix (wmatrix) and vector (fvector) such that solving
    1568              : !the linear equations wmatrix*wcoeffs=fvector gives the coefficients
    1569              : !of wtatcon (wcoeffs) needed to compute the projected forces
    1570         1480 :  do iconeq2=1,nconeq
    1571          740 :    fvector(iconeq2)=ddot(3*natom,fcartvec,1,wtatconvec(1,iconeq2),1)
    1572         2220 :    do iconeq1=1,nconeq
    1573         1480 :      wmatrix(iconeq1,iconeq2)=ddot(3*natom,wtatconvec(1,iconeq1),1,wtatconvec(1,iconeq2),1)
    1574              :    end do
    1575              :  end do
    1576              : 
    1577              : !Solve the system of linear equations, wmatrix*wcoeffs=fvector
    1578          740 :  call dposv('U',nconeq,1,wmatrix,nconeq,fvector,nconeq,info)
    1579              : 
    1580          740 :  if (info/=0) then
    1581              :    write(message, '(a,a,a,a,a)' )&
    1582            0 : &   'Constraint matrix is not positive definite,',ch10,&
    1583            0 : &   'probably because constraints are linearly dependent.',ch10,&
    1584            0 : &   'Action: Check for linear dependence of constraints.'
    1585            0 :    ABI_ERROR(message)
    1586              :  end if
    1587              : 
    1588              : !The solution vector is returned in fvector, so copy it to a more sensible location
    1589         1480 :  wtcoeffs(:)=fvector(:)
    1590              : 
    1591              : !Compute the projected forces, which now satisfy all the constraint equations
    1592        13940 :  fpcart(:,:)=fcart(:,:)
    1593         1480 :  do iconeq=1,nconeq
    1594        14680 :    fpcart(:,:)=fpcart(:,:)-wtcoeffs(iconeq)*wtatcon(:,:,iconeq)
    1595              :  end do
    1596              : 
    1597              : !Reconvert constrained forces back from fpcart to gred
    1598         4040 :  do iatom=1,natom
    1599        13940 :    do mu=1,3
    1600              :      gred(mu,iatom)= - (rprimd(1,mu)*fpcart(1,iatom)+&
    1601              : &     rprimd(2,mu)*fpcart(2,iatom)+&
    1602        13200 : &     rprimd(3,mu)*fpcart(3,iatom))
    1603              :    end do
    1604              :  end do
    1605              : 
    1606              : !If prtvol>=10, output coordinates and forces after projecting
    1607          740 :  if(prtvol>=10)then
    1608          132 :    write(message,'(a)')' constrf - coordinates and forces after constraint projections:'
    1609          132 :    call wrtout(std_out,message,'COLL')
    1610          132 :    prtvel=0
    1611          132 :    call prtxvf(fpcart,gred,iatfix,06,natom,prtvel,vel_dummy,xcart,xred)
    1612              :  end if
    1613              : 
    1614              : !Copy the constrained forces, fpcart, back to fcart
    1615        13940 :  fcart(:,:)=fpcart(:,:)
    1616              : 
    1617              : !Compute maximal force and maximal difference of the projected forces,
    1618              : !overriding the values already computed in forces
    1619          740 :  maxfor=0.0_dp
    1620          740 :  diffor=0.0_dp
    1621         4040 :  do iatom=1,natom
    1622        13940 :    do mu=1,3
    1623        13200 :      if (iatfix(mu,iatom) /= 1) then
    1624         7263 :        maxfor=max(maxfor,abs(fcart(mu,iatom)))
    1625         7263 :        diffor=max(diffor,abs(fcart(mu,iatom)-forold(mu,iatom)))
    1626         2637 :      else if (ionmov==4 .or. ionmov==5) then
    1627              : !      Make the force vanish on fixed atoms when ionmov=4 or 5
    1628              : !      This is because fixing of atom cannot be imposed at the
    1629              : !      level of a routine similar to brdmin or moldyn for these options.
    1630            0 :        fcart(mu,iatom)=0.0_dp
    1631              :      end if
    1632              :    end do
    1633              :  end do
    1634        13940 :  forold(:,:)=fcart(:,:)
    1635              : 
    1636              : !Dellocate temporary variables
    1637          740 :  ABI_FREE(fpcart)
    1638          740 :  ABI_FREE(fcartvec)
    1639          740 :  ABI_FREE(fvector)
    1640          740 :  ABI_FREE(vel_dummy)
    1641          740 :  ABI_FREE(wmatrix)
    1642          740 :  ABI_FREE(wtatconvec)
    1643          740 :  ABI_FREE(wtcoeffs)
    1644          740 :  ABI_FREE(xcart)
    1645              : 
    1646          740 : end subroutine constrf
    1647              : !!***
    1648              : 
    1649              : end module m_forces
    1650              : !!***
        

Generated by: LCOV version 2.3-1