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 : !!***
|