Branch data Line data Source code
1 : : !!****m* ABINIT/m_dfpt_elt
2 : : !! NAME
3 : : !! m_dfpt_elt
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 1998-2026 ABINIT group (DRH, DCA, XG, GM, AR, MB)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! SOURCE
15 : :
16 : : #if defined HAVE_CONFIG_H
17 : : #include "config.h"
18 : : #endif
19 : :
20 : : #include "abi_common.h"
21 : :
22 : : module m_dfpt_elt
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_errors
27 : : use m_xmpi
28 : : use m_dtset
29 : :
30 : : use defs_datatypes, only : pseudopotential_type
31 : : use defs_abitypes, only : MPI_type
32 : : use m_time, only : timab
33 : : use m_special_funcs, only : abi_derfc
34 : : use m_geometry, only : metric
35 : : use m_cgtools, only : dotprod_vn
36 : : use m_pawtab, only : pawtab_type,pawtab_free,pawtab_nullify
37 : : use m_pawrad, only : pawrad_type,pawrad_init,pawrad_free
38 : : use m_pawpsp, only : pawpsp_cg
39 : : use m_paw_numeric, only : paw_spline
40 : : use m_spacepar, only : redgr
41 : : use m_atm2fft, only : atm2fft, dfpt_atm2fft
42 : : use m_mkcore, only : dfpt_mkcore
43 : : use m_dfpt_mkvxcstr, only : dfpt_mkvxcstr
44 : : use m_paral_atom, only : get_my_atmtab, free_my_atmtab
45 : : use m_mpinfo, only : ptabs_fourdp, proc_distrb_cycle, proc_distrb_nband
46 : : use m_fftcore, only : sphereboundary
47 : : use m_fft, only : fourdp
48 : : use m_gtermcutoff, only : termcutoff
49 : :
50 : : implicit none
51 : :
52 : : private
53 : : !!***
54 : :
55 : : public :: dfpt_eltfrxc
56 : : public :: dfpt_eltfrloc
57 : : public :: dfpt_eltfrkin
58 : : public :: dfpt_eltfrhar
59 : : public :: elt_ewald
60 : : public :: dfpt_ewald
61 : : public :: dfpt_ewalddq
62 : : public :: dfpt_ewalddqdq
63 : : !!***
64 : :
65 : : contains
66 : : !!***
67 : :
68 : : !!****f* ABINIT/dfpt_eltfrxc
69 : : !! NAME
70 : : !! dfpt_eltfrxc
71 : : !!
72 : : !! FUNCTION
73 : : !! Compute the 2nd derivatives of exchange-correlation energy
74 : : !! with respect to all pairs of strain and strain-atomic displacement
75 : : !! for the frozen wavefunction contribution to the elastic
76 : : !! and internal strain tensors
77 : : !!
78 : : !! INPUTS
79 : : !! atindx(natom)=index table for atoms ordered by type
80 : : !! dtset <type(dataset_type)>=all input variables for this dataset
81 : : !! | natom=number of atoms in unit cell
82 : : !! | nfft=(effective) number of FFT grid points (for this processor)
83 : : !! | nspden=number of spin-density components
84 : : !! | ntypat=number of types of atoms in cell.
85 : : !! | typat(natom)=integer type for each atom in cell
86 : : !! enxc=exchange and correlation energy (hartree)
87 : : !! gsqcut=Fourier cutoff on G^2 for "large sphere" of radius double that of the basis sphere
88 : : !! kxc(nfft,nkxc)=exchange and correlation kernel
89 : : !! mgfft=maximum size of 1D FFTs
90 : : !! mpi_enreg=information about MPI parallelization
91 : : !! ngfft(18)=contain all needed information about 3D FFT,
92 : : !! see ~abinit/doc/variables/vargs.htm#ngfft
93 : : !! ngfftf(18)= -PAW ONLY- contain all needed information about 3D FFT for the fine grid
94 : : !! (ngfftf=ngfft for norm-conserving potential runs)
95 : : !! nkxc=2nd dimension of kxc
96 : : !! n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
97 : : !! n3xccc=dimension of xccc3d (0 if no core charge, nfft otherwise)
98 : : !! nhat(nfft,nspden*nhatdim)= -PAW only- compensation density
99 : : !! pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
100 : : !! ph1d(2,3*(2*mgfft+1)*natom)=1-dim phase (structure factor) information
101 : : !! psps <type(pseudopotential_type)>=variables related to pseudopotentials
102 : : !! rhor(nfft,nspden)=electron density in r space
103 : : !! (if spin polarized, array contains total density in first half and
104 : : !! spin-up density in second half)
105 : : !! (for non-collinear magnetism, first element: total density,
106 : : !! 3 next ones: mx,my,mz)
107 : : !! rprimd(3,3)=dimensional primitive translation vectors (bohr)
108 : : !! usexcnhat= -PAW only- 1 if nhat density has to be taken into account in Vxc
109 : : !! vxc(nfft,nspden)=xc potential (spin up in first half and spin down in
110 : : !! second half if nspden=2)
111 : : !! xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
112 : : !! xccc1d(n1xccc,6,ntypat)=1D core charge function and five derivatives,
113 : : !! for each type of atom, from psp
114 : : !! xccc3d(n3xccc)=3D core electron density for XC core correction, bohr^-3
115 : : !! xred(3,natom)=reduced coordinates for atoms in unit cell
116 : : !!
117 : : !! OUTPUT
118 : : !! eltfrxc(6+3*natom,6) = xc frozen wavefunction contribution to the
119 : : !! elastic tensor
120 : : !!
121 : : !! SIDE EFFECTS
122 : : !!
123 : : !! NOTES
124 : : !! Much of the code in versions of this routine prior to 4.4.5
125 : : !! has been transfered to its child eltxccore.
126 : : !!
127 : : !! SOURCE
128 : :
129 : 37 : subroutine dfpt_eltfrxc(atindx,dtset,eltfrxc,enxc,gsqcut,kxc,mpi_enreg,mgfft,&
130 : 37 : & nattyp,nfft,ngfft,ngfftf,nhat,nkxc,n3xccc,pawtab,ph1d,psps,rhor,rprimd,&
131 : 37 : & usexcnhat,vxc,xccc3d,xred)
132 : :
133 : : !Arguments ------------------------------------
134 : : !type
135 : : !scalars
136 : : integer,intent(in) :: mgfft,n3xccc,nfft,nkxc,usexcnhat
137 : : real(dp),intent(in) :: enxc,gsqcut
138 : : type(MPI_type),intent(in) :: mpi_enreg
139 : : type(dataset_type),intent(in) :: dtset
140 : : type(pseudopotential_type),intent(inout) :: psps
141 : : !arrays
142 : : integer,intent(in) :: atindx(dtset%natom),nattyp(dtset%ntypat),ngfft(18)
143 : : integer,intent(in) :: ngfftf(18)
144 : : real(dp),intent(in) :: nhat(nfft,dtset%nspden*psps%usepaw)
145 : : real(dp),intent(in) :: ph1d(2,3*(2*mgfft+1)*dtset%natom)
146 : : real(dp),intent(in) :: vxc(nfft,dtset%nspden),xccc3d(n3xccc)
147 : : real(dp),intent(in) :: xred(3,dtset%natom)
148 : : real(dp),intent(in),target :: rhor(nfft,dtset%nspden)
149 : : real(dp),intent(inout) :: kxc(nfft,nkxc)
150 : : real(dp),intent(out) :: eltfrxc(6+3*dtset%natom,6),rprimd(3,3)
151 : : type(pawtab_type),intent(in) :: pawtab(dtset%ntypat*dtset%usepaw)
152 : :
153 : : !Local variables-------------------------------
154 : : !scalars
155 : : integer,parameter :: mshift=401
156 : : integer :: cplex,fgga,ia,idir,ielt,ieltx,ierr,ifft,ii,ipert,is1,is2,ispden,ispden_c,jj,ka,kb
157 : : integer :: kd,kg,n1,n1xccc,n2,n3,n3xccc_loc,optatm,optdyfr,opteltfr,optgr
158 : : integer :: option,optn,optn2,optstr,optv
159 : : logical :: nmxc
160 : : real(dp) :: d2eacc,d2ecdgs2,d2exdgs2,d2gsds1ds2,d2gstds1ds2,decdgs,dexdgs
161 : : real(dp) :: dgsds10,dgsds20,dgstds10,dgstds20,rstep,spnorm,tmp0,tmp0t
162 : : real(dp) :: ucvol,valuei,yp1,ypn
163 : 37 : type(pawrad_type) :: core_mesh
164 : : !arrays
165 : : integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
166 : : real(dp) :: corstr(6),dummy6(0),dummy_in(0,0)
167 : : real(dp) :: dummy_out1(0),dummy_out2(0),dummy_out3(0),dummy_out4(0),dummy_out5(0),dummy_out6(0)
168 : 74 : real(dp) :: eltfrxc_test1(6+3*dtset%natom,6),eltfrxc_test2(6+3*dtset%natom,6)
169 : : real(dp) :: gmet(3,3),gprimd(3,3),qphon(3),rmet(3,3),tsec(2)
170 : : real(dp) :: strn_dummy6(0), strv_dummy6(0)
171 : 37 : real(dp),allocatable :: d2gm(:,:,:,:),dgm(:,:,:),eltfrxc_tmp(:,:)
172 : 37 : real(dp),allocatable :: eltfrxc_tmp2(:,:),elt_work(:,:),rho0_redgr(:,:,:)
173 : 37 : real(dp),allocatable :: vxc10(:,:),vxc10_core(:),vxc10_coreg(:,:)
174 : 37 : real(dp),allocatable :: vxc1is_core(:),vxc1is_coreg(:,:),vxc_core(:)
175 : 37 : real(dp),allocatable :: vxc_coreg(:,:),work(:),workgr(:,:),xccc1d(:,:,:)
176 : 37 : real(dp),allocatable :: xccc3d1(:),xccc3d1_temp(:,:),xcccrc(:)
177 : 37 : real(dp),pointer :: rhor_(:,:)
178 : 37 : type(pawtab_type),allocatable :: pawtab_test(:)
179 : :
180 : : ! *************************************************************************
181 : :
182 : : !Initialize variables
183 : 37 : cplex=1
184 : 37 : qphon(:)=zero
185 : 37 : n1=ngfft(1)
186 : 37 : n2=ngfft(2)
187 : 37 : n3=ngfft(3)
188 : :
189 : 37 : n1xccc = psps%n1xccc
190 : 37 : if(psps%usepaw==0)then
191 [ - + + - : 75 : ABI_MALLOC(xcccrc,(dtset%ntypat))
+ - + - -
+ - + ]
192 [ + + + - : 100 : ABI_MALLOC(xccc1d,(n1xccc,6,dtset%ntypat))
- + + - +
- + + - +
- + ]
193 [ + - - + : 89 : xcccrc = psps%xcccrc
- - - - +
+ ]
194 [ + - + - : 375473 : xccc1d = psps%xccc1d
+ - - + -
- - - - -
- - + + +
+ + + ]
195 : : end if
196 : :
197 [ + + + + ]: 37 : if (usexcnhat==0.and.dtset%usepaw==1) then
198 [ - + + - : 8 : ABI_MALLOC(rhor_,(nfft,dtset%nspden))
- + + - +
- + - - +
- + ]
199 [ + - + + : 31112 : rhor_(:,:) = rhor(:,:)-nhat(:,:)
+ + + + +
+ ]
200 : : else
201 : 35 : rhor_ => rhor
202 : : end if
203 : :
204 : : !HACK - should be fixed globally
205 [ + + ]: 37 : if(n1xccc==0) then
206 : 9 : n3xccc_loc=0
207 : : else
208 : 28 : n3xccc_loc=n3xccc
209 : : end if
210 : :
211 [ + + ]: 37 : fgga=0 ; if(nkxc==7.or.nkxc==19) fgga=1
212 [ + + + - ]: 37 : nmxc=(dtset%usepaw==1.and.mod(abs(dtset%usepawu),10)==4)
213 : :
214 [ + - - + : 185 : ABI_MALLOC(eltfrxc_tmp,(6+3*dtset%natom,6))
+ - + - +
- + - - +
- + ]
215 [ - + + - : 74 : ABI_MALLOC(eltfrxc_tmp2,(6+3*dtset%natom,6))
- + - + ]
216 [ - + + - : 148 : ABI_MALLOC(vxc10,(nfft,dtset%nspden))
- + + - +
- + - - +
- + ]
217 [ - + + - : 111 : ABI_MALLOC(xccc3d1,(cplex*nfft))
+ - + - -
+ - + ]
218 : :
219 [ + + ]: 37 : if(n1xccc/=0) then
220 [ - + + - : 56 : ABI_MALLOC(vxc_core,(nfft))
- + - + ]
221 [ - + + - : 56 : ABI_MALLOC(vxc10_core,(nfft))
- + - + ]
222 [ - + + - : 56 : ABI_MALLOC(vxc1is_core,(nfft))
- + - + ]
223 : :
224 [ + + ]: 28 : if(dtset%nspden==1) then
225 [ + + ]: 175399 : vxc_core(:)=vxc(:,1)
226 : : else
227 [ + + ]: 11666 : vxc_core(:)=0.5_dp*(vxc(:,1)+vxc(:,2))
228 : : end if
229 : : end if
230 : :
231 : : !Compute gmet, gprimd and ucvol from rprimd
232 : 37 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
233 : :
234 : : !For GGA case, prepare quantities needed to evaluate contributions
235 : : !arising from the strain dependence of the gradient operator itself
236 : :
237 [ + + ]: 37 : if(fgga==1) then
238 [ - + + - : 16 : ABI_MALLOC(rho0_redgr,(3,nfft,dtset%nspden))
- + + - +
- + - - +
- + ]
239 [ - + + - : 8 : ABI_MALLOC(work,(nfft))
- + - + ]
240 [ - + + - : 12 : ABI_MALLOC(workgr,(nfft,3))
+ - + - -
+ - + ]
241 : :
242 : : ! Set up metric tensor derivatives
243 [ - + ]: 4 : ABI_MALLOC(dgm,(3,3,6))
244 [ - + ]: 4 : ABI_MALLOC(d2gm,(3,3,6,6))
245 : : ! Loop over 2nd strain index
246 [ + + ]: 28 : do is2=1,6
247 : 24 : kg=idx(2*is2-1);kd=idx(2*is2)
248 [ + + ]: 96 : do jj = 1,3
249 [ + + ]: 312 : dgm(:,jj,is2)=-(gprimd(kg,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kg,jj))
250 : : end do
251 : :
252 : : ! Loop over 1st strain index
253 [ + + ]: 172 : do is1=1,6
254 : 144 : ka=idx(2*is1-1);kb=idx(2*is1)
255 [ + + + + ]: 1872 : d2gm(:,:,is1,is2)=0._dp
256 [ + + ]: 576 : do jj = 1,3
257 [ + + ]: 432 : if(ka==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
258 [ + + ]: 672 : & +gprimd(kb,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kb,jj)
259 [ + + ]: 432 : if(ka==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
260 [ + + ]: 480 : & +gprimd(kb,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(kb,jj)
261 [ + + ]: 432 : if(kb==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
262 [ + + ]: 480 : & +gprimd(ka,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(ka,jj)
263 [ + + ]: 432 : if(kb==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
264 [ + + ]: 816 : & +gprimd(ka,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(ka,jj)
265 : : end do
266 [ + + + + ]: 1896 : d2gm(:,:,is1,is2)=0.5_dp*d2gm(:,:,is1,is2)
267 : : end do
268 : : end do
269 : :
270 : : ! Compute the reduced gradients of the zero-order charge density.
271 : : ! Note that in the spin-polarized case, we are computing the reduced
272 : : ! gradients of 2 X the spin-up or spin-down charge. This simplifies
273 : : ! subsequent code for the non-spin-polarized case.
274 [ + + ]: 4 : if(dtset%nspden==1) then
275 [ + + ]: 12878 : work(:)=rhor_(:,1)
276 : : else
277 [ + + ]: 5833 : work(:)=2.0_dp*rhor_(:,2)
278 : : end if
279 [ + + ]: 4 : if(n1xccc/=0) then
280 [ + + ]: 13834 : work(:)=work(:)+xccc3d(:)
281 : : end if
282 : 4 : call redgr (work,workgr,mpi_enreg,nfft,ngfft)
283 [ + + ]: 18711 : do ifft=1,nfft
284 [ + + ]: 74832 : rho0_redgr(:,ifft,1)=workgr(ifft,:)
285 : : end do
286 [ + + ]: 4 : if(dtset%nspden==2) then
287 [ + + ]: 5833 : work(:)=2.0_dp*(rhor_(:,1)-rhor_(:,2))
288 [ + - ]: 1 : if(n1xccc/=0) then
289 [ + + ]: 5833 : work(:)=work(:)+xccc3d(:)
290 : : end if
291 : 1 : call redgr(work,workgr,mpi_enreg,nfft,ngfft)
292 [ + + ]: 5833 : do ifft=1,nfft
293 [ + + ]: 23329 : rho0_redgr(:,ifft,2)=workgr(ifft,:)
294 : : end do
295 : : end if
296 [ - + ]: 4 : ABI_FREE(work)
297 [ - + ]: 4 : ABI_FREE(workgr)
298 : : end if !GGA
299 : :
300 : : !Null the elastic tensor accumulator
301 [ + + + + : 9849 : eltfrxc(:,:)=zero;eltfrxc_tmp(:,:)=zero;eltfrxc_tmp2(:,:) = zero
+ + + + +
+ + + ]
302 : :
303 : : !Normalization factor
304 [ + + ]: 37 : if(dtset%nspden==1) then
305 : : spnorm=one
306 : : else
307 : 2 : spnorm=half
308 : : end if
309 : :
310 : : !Big loop over 2nd strain index
311 [ + + ]: 259 : do is2=1,6
312 : :
313 : : ! Translate strain index as needed by dfpt_mkcore below.
314 [ + + ]: 222 : if(is2<=3) then
315 : 111 : ipert=dtset%natom+3
316 : 111 : idir=is2
317 : : else
318 : 111 : ipert=dtset%natom+4
319 : 111 : idir=is2-3
320 : : end if
321 : :
322 : : ! Generate first-order core charge for is2 strain if core charges are present.
323 [ + + ]: 222 : if(n1xccc/=0)then
324 : :
325 [ + + - + ]: 168 : if (psps%usepaw==1 .or. psps%nc_xccc_gspace==1) then
326 : : ! Calculation in Reciprocal space for paw or NC with nc_xccc_gspace
327 [ - + + - : 144 : ABI_MALLOC(xccc3d1_temp,(cplex*nfft,1))
- + - + ]
328 [ + + + + ]: 653328 : xccc3d1_temp = zero
329 : :
330 : : call dfpt_atm2fft(atindx,cplex,gmet,gprimd,gsqcut,is2,ipert,&
331 : : & mgfft,psps%mqgrid_vl,dtset%natom,1,nfft,ngfftf,dtset%ntypat,&
332 : : & ph1d,psps%qgrid_vl,qphon,dtset%typat,ucvol,psps%usepaw,xred,psps,pawtab,&
333 : : & atmrhor1=xccc3d1_temp,optn2_in=1,&
334 : : & comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
335 : 72 : & paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
336 [ + + ]: 653256 : xccc3d1(:) = xccc3d1_temp(:,1)
337 [ - + ]: 72 : ABI_FREE(xccc3d1_temp)
338 : :
339 : : else
340 : : ! Calculation in direct space for norm conserving:
341 : : call dfpt_mkcore(cplex,idir,ipert,dtset%natom,dtset%ntypat,n1,n1xccc,&
342 : : & n2,n3,qphon,rprimd,dtset%typat,ucvol,&
343 : 96 : & xcccrc,xccc1d,xccc3d1,xred)
344 : : end if
345 : : else
346 [ + + ]: 229116 : xccc3d1(:)=zero
347 : : end if
348 : :
349 : : ! Compute the first-order potentials.
350 : : ! Standard first-order potential for LDA and GGA with core charge
351 [ + + + + ]: 222 : if(fgga==0 .or. (fgga==1 .and. n1xccc/=0)) then
352 : 210 : option=0
353 : : call dfpt_mkvxcstr(cplex,idir,ipert,kxc,mpi_enreg,dtset%natom,nfft,ngfft,nhat,&
354 : : & dummy_in,nkxc,nmxc,dtset%nspden,n3xccc_loc,option,qphon,rhor,rhor,&
355 : 210 : & rprimd,dtset%usepaw,usexcnhat,vxc10,xccc3d1)
356 [ + + ]: 210 : if(n1xccc/=0)then
357 [ + + ]: 168 : if(dtset%nspden==1) then
358 [ + + ]: 1052394 : vxc10_core(:)=vxc10(:,1)
359 [ + + ]: 1052394 : vxc1is_core(:)=vxc10(:,1)
360 : : else
361 [ + + ]: 69996 : vxc10_core(:)=0.5_dp*(vxc10(:,1)+vxc10(:,2))
362 [ + + ]: 69996 : vxc1is_core(:)=0.5_dp*(vxc10(:,1)+vxc10(:,2))
363 : : end if
364 : : end if
365 : : end if
366 : :
367 : : ! For GGA, first-order potential with doubled gradient operator strain
368 : : ! derivative terms needed for elastic tensor but not internal strain.
369 [ + + ]: 222 : if(fgga==1) then
370 : 24 : option=2
371 : : call dfpt_mkvxcstr(cplex,idir,ipert,kxc,mpi_enreg,dtset%natom,nfft,ngfft,nhat,&
372 : : & dummy_in,nkxc,nmxc,dtset%nspden,n3xccc_loc,option,qphon,rhor,rhor,&
373 : 24 : & rprimd,dtset%usepaw,usexcnhat,vxc10,xccc3d1)
374 [ + + ]: 24 : if(n1xccc/=0)then
375 [ + + ]: 12 : if(dtset%nspden==1) then
376 [ + + ]: 48006 : vxc10_core(:)=vxc10(:,1)
377 : : else
378 [ + + ]: 34998 : vxc10_core(:)=0.5_dp*(vxc10(:,1)+vxc10(:,2))
379 : : end if
380 : : end if
381 : : end if
382 : :
383 : :
384 : : ! Additional term for diagonal strains.
385 [ + + ]: 222 : if(is2<=3) then
386 [ + + + + ]: 710862 : vxc10(:,:)=vxc10(:,:)+vxc(:,:)
387 [ + + ]: 111 : if(n1xccc/=0) then
388 [ + + ]: 561195 : vxc10_core(:)=vxc10_core(:)+2.0_dp*vxc_core(:)
389 [ + + ]: 561195 : vxc1is_core(:)=vxc1is_core(:)+vxc_core(:)
390 : : end if
391 : : end if
392 : :
393 : : ! For GGA, compute the contributions from the strain derivatives acting
394 : : ! on the gradient operators.
395 [ + + ]: 222 : if(fgga==1) then
396 : :
397 [ + + ]: 24 : if (dtset%nspden==1) then
398 [ + + ]: 77268 : do ifft=1,nfft
399 : : ! Collect the needed derivatives of Exc. The factors introduced
400 : : ! deal with the difference between density as used here and
401 : : ! spin density as used with these kxc terms in other contexts.
402 : 77250 : dexdgs =half *kxc(ifft,2)
403 : 77250 : d2exdgs2=quarter*kxc(ifft,4)
404 : : ! Loop over 1st strain index
405 [ + + ]: 540768 : do is1=1,6
406 : : ! The notation here is .gs... for the derivatives of the squared-
407 : : ! gradient of (2X) each spin density, and .gst... for the total density.
408 : : dgsds10=zero;dgsds20=zero;d2gsds1ds2=zero
409 [ + + ]: 1854000 : do jj=1,3
410 [ + + ]: 6025500 : do ii=1,3
411 : 4171500 : tmp0=rho0_redgr(ii,ifft,1)*rho0_redgr(jj,ifft,1)
412 : 4171500 : dgsds10=dgsds10+dgm(ii,jj,is1)*tmp0
413 : 4171500 : dgsds20=dgsds20+dgm(ii,jj,is2)*tmp0
414 : 5562000 : d2gsds1ds2=d2gsds1ds2+d2gm(ii,jj,is1,is2)*tmp0
415 : : end do
416 : : end do
417 : : ! Volume derivative terms added
418 [ + + ]: 463500 : if(is1<=3) d2gsds1ds2=d2gsds1ds2+dgsds20
419 [ + + ]: 463500 : if(is2<=3) d2gsds1ds2=d2gsds1ds2+dgsds10
420 : : ! Add the gradient derivative terms to eltfrxc.
421 : 540750 : eltfrxc(is1,is2)=eltfrxc(is1,is2)+d2exdgs2*dgsds10*dgsds20+dexdgs*d2gsds1ds2
422 : : end do !is1
423 : : end do !ifft
424 : :
425 : : else ! nspden==2
426 : :
427 [ + + ]: 18 : do ispden=1,dtset%nspden
428 : 12 : ispden_c=dtset%nspden-ispden+1
429 : :
430 [ + + ]: 70002 : do ifft=1,nfft
431 : :
432 : : ! Collect the needed derivatives of Exc. The factors introduced
433 : : ! deal with the difference between density as used here and
434 : : ! spin density as used with these kxc terms in other contexts.
435 : 69984 : dexdgs =quarter *kxc(ifft,3+ispden)
436 : 69984 : d2exdgs2=quarter*eighth*kxc(ifft,7+ispden)
437 : 69984 : decdgs =eighth *kxc(ifft,10)
438 : 69984 : d2ecdgs2=eighth*eighth *kxc(ifft,13)
439 : :
440 : : ! Loop over 1st strain index
441 [ + + ]: 489900 : do is1=1,6
442 : :
443 : : ! The notation here is .gs... for the derivatives of the squared-
444 : : ! gradient of (2X) each spin density, and .gst... for the total
445 : : ! density. Note the hack that the the total density is given
446 : : ! by the same expression for either the non-polarized or spin-
447 : : ! polarized case, implemented with the "complementary" index ispden_c
448 : : ! in the expression for tmp0t below.
449 : : dgsds10=zero;dgsds20=zero;d2gsds1ds2=zero
450 : : dgstds10=zero;dgstds20=zero;d2gstds1ds2=zero
451 [ + + ]: 1679616 : do jj=1,3
452 [ + + ]: 5458752 : do ii=1,3
453 : 3779136 : tmp0=rho0_redgr(ii,ifft,ispden)*rho0_redgr(jj,ifft,ispden)
454 : : tmp0t=(rho0_redgr(ii,ifft,ispden)+rho0_redgr(ii,ifft,ispden_c))&
455 : 3779136 : & *(rho0_redgr(jj,ifft,ispden)+rho0_redgr(jj,ifft,ispden_c))
456 : 3779136 : dgsds10=dgsds10+dgm(ii,jj,is1)*tmp0
457 : 3779136 : dgsds20=dgsds20+dgm(ii,jj,is2)*tmp0
458 : 3779136 : dgstds10=dgstds10+dgm(ii,jj,is1)*tmp0t
459 : 3779136 : dgstds20=dgstds20+dgm(ii,jj,is2)*tmp0t
460 : 3779136 : d2gsds1ds2=d2gsds1ds2+d2gm(ii,jj,is1,is2)*tmp0
461 : 5038848 : d2gstds1ds2=d2gstds1ds2+d2gm(ii,jj,is1,is2)*tmp0t
462 : : end do
463 : : end do
464 : : ! Volume derivative terms added
465 [ + + ]: 419904 : if(is1<=3) then
466 : 209952 : d2gsds1ds2=d2gsds1ds2+dgsds20
467 : 209952 : d2gstds1ds2=d2gstds1ds2+dgstds20
468 : : end if
469 [ + + ]: 419904 : if(is2<=3) then
470 : 209952 : d2gsds1ds2=d2gsds1ds2+dgsds10
471 : 209952 : d2gstds1ds2=d2gstds1ds2+dgstds10
472 : : end if
473 : :
474 : : ! Add the gradient derivative terms to eltfrxc.
475 : : eltfrxc(is1,is2)=eltfrxc(is1,is2)+spnorm*&
476 : : & (d2exdgs2*(dgsds10 *dgsds20) + dexdgs*d2gsds1ds2&
477 : 489888 : & +d2ecdgs2*(dgstds10*dgstds20)+ decdgs*d2gstds1ds2)
478 : :
479 : : end do !is1
480 : : end do !ifft
481 : : end do !ispden
482 : :
483 : : end if ! nspden
484 : :
485 : : end if !GGA
486 : :
487 : : ! Compute valence electron 1st-order charge contributions. Recall that
488 : : ! the diagonal strain derivatives of the valence charge are minus the
489 : : ! zero-order density. The explicit symmetrization avoids the need
490 : : ! to store vxc10 for strain indices other than is2.
491 : :
492 : : call dotprod_vn(1,rhor_,d2eacc,valuei,nfft,nfft,dtset%nspden,1,&
493 [ - + ]: 222 : & vxc10,ucvol)
494 [ + + ]: 888 : do is1=1,3
495 : 666 : eltfrxc_tmp(is1,is2)=eltfrxc_tmp(is1,is2)-0.5_dp*d2eacc
496 : 888 : eltfrxc_tmp(is2,is1)=eltfrxc_tmp(is2,is1)-0.5_dp*d2eacc
497 : : end do
498 : :
499 : : ! Compute additional core contributions from is1 perturbation
500 : : ! Internal strain terms calculated here.
501 [ + + ]: 222 : if(n1xccc/=0) then
502 : :
503 [ + + - + ]: 168 : if (psps%usepaw==1 .or. psps%nc_xccc_gspace==1) then
504 : : ! Calculation in Reciprocal space for paw or NC with nc_xccc_gspace
505 : 72 : optatm=0;optdyfr=0;optgr=0;optstr=0;optv=0;optn=n3xccc/nfft;optn2=1;opteltfr=1
506 [ - + + - : 216 : ABI_MALLOC(vxc10_coreg,(2,nfft))
+ - + - -
+ - + ]
507 [ - + + - : 144 : ABI_MALLOC(vxc_coreg,(2,nfft))
- + - + ]
508 [ - + + - : 216 : ABI_MALLOC(vxc1is_coreg,(2,nfft))
+ - + - -
+ - + ]
509 : :
510 [ + + + + : 5878872 : vxc10_coreg(:,:)=zero;vxc10_coreg(:,:)=zero;vxc1is_coreg(:,:)=zero;
+ + + + +
+ + + ]
511 : :
512 : : ! Fourier transform of Vxc_core/vxc10_core to use in atm2fft (reciprocal space calculation)
513 : 72 : call fourdp(1,vxc10_coreg,vxc10_core,-1,mpi_enreg,nfft,1, ngfft,0)
514 : 72 : call fourdp(1,vxc_coreg,vxc_core,-1,mpi_enreg,nfft,1, ngfft, 0)
515 : 72 : call fourdp(1,vxc1is_coreg,vxc1is_core,-1,mpi_enreg,nfft,1, ngfft, 0)
516 : :
517 : : call atm2fft(atindx,dummy_out1,dummy_out2,dummy_out3,dummy_out4,eltfrxc_tmp2,dummy_in,gmet,gprimd,&
518 : : & dummy_out5,dummy_out6,gsqcut,mgfft,psps%mqgrid_vl,dtset%natom,nattyp,nfft,ngfft,dtset%ntypat,&
519 : : & optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab,ph1d,psps%qgrid_vl,dtset%qprtrb,&
520 : : & dtset%rcut,dummy_in,rprimd,strn_dummy6,strv_dummy6,ucvol,psps%usepaw,&
521 : : & vxc_coreg,vxc10_coreg,vxc1is_coreg,dtset%vprtrb,psps%vlspl,is2_in=is2,&
522 : : & comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
523 : 72 : & paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
524 : :
525 : : ! The indexing array atindx is used to reestablish the correct order of atoms
526 [ + - - + : 288 : ABI_MALLOC(elt_work,(6+3*dtset%natom,6))
+ - + - +
- + - - +
- + ]
527 [ + + + + ]: 3096 : elt_work(1:6,1:6)=eltfrxc_tmp2(1:6,1:6)
528 [ + + ]: 324 : do ia=1,dtset%natom
529 : 252 : ielt=7+3*(ia-1)
530 : 252 : ieltx=7+3*(atindx(ia)-1)
531 [ + + + + ]: 6372 : elt_work(ielt:ielt+2,1:6)=eltfrxc_tmp2(ieltx:ieltx+2,1:6)
532 : : end do
533 [ + + + + ]: 7632 : eltfrxc_tmp2(:,:)=elt_work(:,:)
534 [ - + ]: 72 : ABI_FREE(elt_work)
535 : :
536 : :
537 [ - + ]: 72 : ABI_FREE(vxc10_coreg)
538 [ - + ]: 72 : ABI_FREE(vxc_coreg)
539 [ - + ]: 72 : ABI_FREE(vxc1is_coreg)
540 [ + + + + ]: 7632 : eltfrxc(:,:)= eltfrxc(:,:) + eltfrxc_tmp2(:,:)
541 : :
542 : : else
543 : :
544 : : call eltxccore(eltfrxc,is2,mpi_enreg%my_natom,dtset%natom,nfft,dtset%ntypat,&
545 : : & n1,n1xccc,n2,n3,rprimd,dtset%typat,ucvol,vxc_core,vxc10_core,vxc1is_core,&
546 : 96 : & xcccrc,xccc1d,xred,mpi_atmtab=mpi_enreg%my_atmtab,comm_atom=mpi_enreg%comm_atom)
547 : :
548 : : !DEBUG
549 : : ! TEST ZONE (DO NOT REMOVE) USE TO RECIPROCAL SPACE IN NC CASE
550 [ - + ]: 96 : if (dtset%userid==567) then
551 [ # # # # ]: 0 : eltfrxc_test1(:,is2)=zero;eltfrxc_test2(:,is2)=zero
552 : : call eltxccore(eltfrxc_test1,is2,mpi_enreg%my_natom,dtset%natom,nfft,dtset%ntypat,&
553 : : & n1,n1xccc,n2,n3,rprimd,dtset%typat,ucvol,vxc_core,vxc10_core,vxc1is_core,&
554 : 0 : & xcccrc,xccc1d,xred,mpi_atmtab=mpi_enreg%my_atmtab,comm_atom=mpi_enreg%comm_atom)
555 : : ! if (is2==1) print*,"elt-frxc from eltxccore",is2,eltfrxc_test1(1,1)*ucvol/dble(nfft)
556 [ # # # # : 0 : ABI_MALLOC(pawtab_test,(dtset%ntypat))
# # # # #
# # # # #
# # ]
557 : 0 : call pawtab_nullify(pawtab_test)
558 [ # # ]: 0 : do jj=1,dtset%ntypat
559 : 0 : pawtab_test(jj)%mqgrid=psps%mqgrid_vl
560 [ # # # # : 0 : ABI_MALLOC(pawtab_test(jj)%tcorespl,(pawtab_test(jj)%mqgrid,2))
# # # # #
# # # #
# ]
561 : 0 : rstep=xcccrc(jj)/dble(n1xccc-1)
562 : 0 : call pawrad_init(mesh=core_mesh,mesh_size=n1xccc,mesh_type=1,rstep=rstep)
563 : : call pawpsp_cg(pawtab_test(jj)%dncdq0,pawtab_test(jj)%d2ncdq0,psps%mqgrid_vl,psps%qgrid_vl,&
564 : 0 : & pawtab_test(jj)%tcorespl(:,1),core_mesh,xccc1d(:,1,jj),yp1,ypn)
565 : 0 : call paw_spline(psps%qgrid_vl,pawtab_test(jj)%tcorespl(:,1),psps%mqgrid_vl,yp1,ypn,pawtab_test(jj)%tcorespl(:,2))
566 : : ! if (is2==1) then
567 : : ! do ii=1,n1xccc;write(100+jj,*) (ii-1)*rstep,xccc1d(ii,1,jj);enddo
568 : : ! do ii=1,psps%mqgrid_vl;write(200+jj,*) psps%qgrid_vl(ii),pawtab_test(jj)%tcorespl(ii,1);enddo
569 : : ! end if
570 : : end do
571 [ # # # # : 0 : ABI_MALLOC(vxc10_coreg,(2,nfft))
# # # # #
# # # ]
572 [ # # # # : 0 : ABI_MALLOC(vxc_coreg,(2,nfft))
# # # # ]
573 [ # # # # : 0 : ABI_MALLOC(vxc1is_coreg,(2,nfft))
# # # # ]
574 [ # # # # : 0 : vxc10_coreg(:,:)=zero;vxc10_coreg(:,:)=zero;vxc1is_coreg(:,:)=zero;
# # # # #
# # # ]
575 : 0 : call fourdp(1,vxc10_coreg,vxc10_core,-1,mpi_enreg,nfft,1, ngfft, 0)
576 : 0 : call fourdp(1,vxc_coreg,vxc_core,-1,mpi_enreg,nfft,1, ngfft,0)
577 : 0 : call fourdp(1,vxc1is_coreg,vxc1is_core,-1,mpi_enreg,nfft,1, ngfft, 0)
578 : 0 : optatm=0;optdyfr=0;optgr=0;optstr=0;optv=0;optn=1;optn2=1;opteltfr=1;corstr=zero
579 : : call atm2fft(atindx,dummy_out1,dummy_out2,dummy_out3,dummy_out4,eltfrxc_test2,dummy_in,gmet,gprimd,&
580 : : & dummy_out5,dummy_out6,gsqcut,mgfft,psps%mqgrid_vl,dtset%natom,nattyp,nfft,ngfft,dtset%ntypat,&
581 : : & optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab_test,ph1d,psps%qgrid_vl,dtset%qprtrb,&
582 : : & dtset%rcut,dummy_in,rprimd,corstr,dummy6,ucvol,psps%usepaw,&
583 : 0 : & vxc_coreg,vxc10_coreg,vxc1is_coreg,dtset%vprtrb,psps%vlspl,is2_in=is2)
584 [ # # ]: 0 : ABI_FREE(vxc10_coreg)
585 [ # # ]: 0 : ABI_FREE(vxc_coreg)
586 [ # # ]: 0 : ABI_FREE(vxc1is_coreg)
587 : 0 : call pawrad_free(core_mesh)
588 : 0 : call pawtab_free(pawtab_test)
589 [ # # # # : 0 : ABI_FREE(pawtab_test)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
590 [ # # # # ]: 0 : eltfrxc(:,:)= eltfrxc(:,:)+eltfrxc_test2(:,:)
591 : : ! if (is2==1) print*,"cor-str from atm2fft",is2,corstr*ucvol
592 : : ! if (is2==1) print*,"elt-frxc from atm2fft ",is2,eltfrxc_test2(1,1)
593 : : end if
594 : : !DEBUG
595 : :
596 : : end if
597 : : end if
598 : :
599 : : ! Additional term for diagonal strains
600 [ + + ]: 259 : if(is2<=3) then
601 [ + + ]: 444 : do is1=1,3
602 : 444 : eltfrxc_tmp(is1,is2)=eltfrxc_tmp(is1,is2)+enxc
603 : : end do
604 : : end if
605 : : end do !is2 outermost strain loop
606 : :
607 : : !Accumulate eltfrxc accross processors
608 : 37 : call timab(48,1,tsec)
609 : 37 : call xmpi_sum(eltfrxc,mpi_enreg%comm_fft,ierr)
610 : 37 : call timab(48,2,tsec)
611 : :
612 : : !Normalize accumulated 2nd derivatives in NC case
613 [ + + ]: 37 : if(psps%usepaw==1)then
614 [ + + + + ]: 1272 : eltfrxc(:,:)=eltfrxc_tmp(:,:)+eltfrxc
615 : : else
616 [ + + + + ]: 2011 : eltfrxc(:,:)=eltfrxc_tmp(:,:)+eltfrxc*ucvol/dble(nfft)
617 : : end if
618 : :
619 [ - + ]: 37 : ABI_FREE(eltfrxc_tmp)
620 [ - + ]: 37 : ABI_FREE(eltfrxc_tmp2)
621 [ - + ]: 37 : ABI_FREE(vxc10)
622 [ - + ]: 37 : ABI_FREE(xccc3d1)
623 [ + + ]: 37 : if(psps%usepaw==0)then
624 [ - + ]: 25 : ABI_FREE(xccc1d)
625 [ - + ]: 25 : ABI_FREE(xcccrc)
626 : : end if
627 [ + + + + ]: 37 : if (usexcnhat==0.and.dtset%usepaw==1) then
628 [ - + ]: 2 : ABI_FREE(rhor_)
629 : : end if
630 : :
631 [ + + ]: 37 : if(n1xccc/=0) then
632 [ - + ]: 28 : ABI_FREE(vxc_core)
633 [ - + ]: 28 : ABI_FREE(vxc10_core)
634 [ - + ]: 28 : ABI_FREE(vxc1is_core)
635 : : end if
636 : :
637 [ + + ]: 37 : if(fgga==1) then
638 [ - + ]: 4 : ABI_FREE(rho0_redgr)
639 [ - + ]: 4 : ABI_FREE(dgm)
640 [ - + ]: 4 : ABI_FREE(d2gm)
641 : : end if
642 : :
643 [ + + - + : 74 : end subroutine dfpt_eltfrxc
- + - + -
+ - + - +
- + - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- + - + -
+ - + -
+ ]
644 : : !!***
645 : :
646 : : !!****f* ABINIT/eltxccore
647 : : !! NAME
648 : : !! eltxccore
649 : : !!
650 : : !! FUNCTION
651 : : !! Compute the core charge contributions to the 2nd derivatives
652 : : !! of the exchange-correlation energy with respect to all pairs of
653 : : !! strain or strain and atomic displacement for the frozen wavefunction
654 : : !! contribution to the elastic tensor. 1st-order potentials representing
655 : : !! the perturbation by one strain are supplied, and the routine loops
656 : : !! over the second strain and over all atomic displacements.
657 : : !!
658 : : !! COPYRIGHT
659 : : !! Copyright (C) 1998-2026 ABINIT group (DRH, DCA, XG, GMR)
660 : : !! This file is distributed under the terms of the
661 : : !! GNU General Public License, see ~abinit/COPYING
662 : : !! or http://www.gnu.org/copyleft/gpl.txt .
663 : : !!
664 : : !! INPUTS
665 : : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
666 : : !! comm_atom=--optional-- MPI communicator over atoms
667 : : !! my_natom=number of atoms treated by current processor
668 : : !! natom=number of atoms in cell.
669 : : !! nfft=number of fft grid points
670 : : !! ntypat=number of types of atoms in cell.
671 : : !! n1,n2,n3=fft grid dimensions.
672 : : !! n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
673 : : !! rprimd(3,3)=dimensional primitive translation vectors (bohr)
674 : : !! typat(natom)=integer type for each atom in cell
675 : : !! ucvol=unit cell volume (bohr**3).
676 : : !! vxc_core(nfft)=spin-averaged xc potential
677 : : !! vxc10_core(nfft)=spin-averaged 1st-order xc potential for elastic tensor
678 : : !! vxc1is_core(nfft)=spin-averaged 1st-order xc potential for internal strain
679 : : !! xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
680 : : !! xccc1d(n1xccc,6,ntypat)=1D core charge function and five derivatives,
681 : : !! for each type of atom, from psp
682 : : !! xred(3,natom)=reduced coordinates for atoms in unit cell
683 : : !!
684 : : !! OUTPUT
685 : : !! eltfrxc(6+3*natom,6) = xc frozen wavefunction contribution to the
686 : : !! elastic tensor
687 : : !!
688 : : !! SIDE EFFECTS
689 : : !! eltfrxc(6+3*natom,6) = xc frozen wavefunction contribution to the
690 : : !! elastic and internal-strain tensor. One column is incremented
691 : : !! by the core contribution.
692 : : !!
693 : : !! NOTES
694 : : !! Note that this routine is related to the mkcore.f routine
695 : : !!
696 : : !! SOURCE
697 : :
698 : 192 : subroutine eltxccore(eltfrxc,is2_in,my_natom,natom,nfft,ntypat,&
699 : 96 : & n1,n1xccc,n2,n3,rprimd,typat,ucvol,vxc_core,vxc10_core,vxc1is_core,&
700 : 96 : & xcccrc,xccc1d,xred, &
701 [ + - - + : 96 : & mpi_atmtab,comm_atom) ! optional arguments (parallelism)
- - ]
702 : :
703 : : !Arguments ------------------------------------
704 : : !scalars
705 : : integer,intent(in) :: is2_in,n1,n1xccc,n2,n3,my_natom,natom,nfft,ntypat
706 : : integer,optional,intent(in) :: comm_atom
707 : : real(dp),intent(in) :: ucvol
708 : : !arrays
709 : : integer,intent(in) :: typat(natom)
710 : : integer,optional,target,intent(in) :: mpi_atmtab(:)
711 : : real(dp),intent(in) :: vxc10_core(nfft),vxc1is_core(nfft)
712 : : real(dp),intent(in) :: vxc_core(nfft),xccc1d(n1xccc,6,ntypat)
713 : : real(dp),intent(in) :: xcccrc(ntypat),xred(3,natom)
714 : : real(dp),intent(inout) :: eltfrxc(6+3*natom,6),rprimd(3,3)
715 : :
716 : : !Local variables-------------------------------
717 : : !scalars
718 : : integer,parameter :: mshift=401
719 : : integer :: i1,i2,i3,iat,iatom,ierr,ifft,is1,is2,ishift,ishift1,ishift2
720 : : integer :: ishift3,ixp,jj,js,ka,kb,kd,kg,mu,my_comm_atom,nu
721 : : logical :: my_atmtab_allocated,paral_atom
722 : : real(dp) :: aa,bb,cc,d2rss,dd,delta,delta2div6,deltam1,diff
723 : : real(dp) :: difmag,difmag2,difmag2_fact,difmag2_part,drss1,drss2,func1
724 : : real(dp) :: func2,range,range2,rangem1,rdiff1,rdiff2,rdiff3
725 : : real(dp) :: term1,term2,yy
726 : : character(len=500) :: message
727 : : !arrays
728 : : integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
729 : : integer :: igrid(3),ii(mshift,3),irange(3),ngfft(3)
730 : 96 : integer,pointer :: my_atmtab(:)
731 : 192 : real(dp) :: drm(3,3,6),eltfrxc_core(6+3*natom,6),lencp(3),rmet(3,3),rrdiff(mshift,3)
732 : : real(dp) :: scale(3),tau(3),ts2(3),tsec(2),tt(3)
733 : 96 : real(dp),allocatable :: d2rm(:,:,:,:)
734 : :
735 : : ! *************************************************************************
736 : :
737 : : !Compute lengths of cross products for pairs of primitive
738 : : !translation vectors (used in setting index search range below)
739 : : lencp(1)=cross_elt(rprimd(1,2),rprimd(2,2),rprimd(3,2),&
740 : 96 : & rprimd(1,3),rprimd(2,3),rprimd(3,3))
741 : : lencp(2)=cross_elt(rprimd(1,3),rprimd(2,3),rprimd(3,3),&
742 : 96 : & rprimd(1,1),rprimd(2,1),rprimd(3,1))
743 : : lencp(3)=cross_elt(rprimd(1,1),rprimd(2,1),rprimd(3,1),&
744 : 96 : & rprimd(1,2),rprimd(2,2),rprimd(3,2))
745 : :
746 : : !Set up parallelism over atoms
747 [ + - ]: 96 : paral_atom=(present(comm_atom).and.(my_natom/=natom))
748 [ - + ]: 96 : nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
749 [ + - ]: 96 : my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
750 : 96 : call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
751 : :
752 : : !Compute factor R1.(R2xR3)/|R2xR3| etc for 1, 2, 3
753 : : !(recall ucvol=R1.(R2xR3))
754 [ + + ]: 384 : scale(:)=ucvol/lencp(:)
755 : :
756 : : !Compute metric tensor in real space rmet
757 [ + + ]: 384 : do nu=1,3
758 : : rmet(:,nu)=rprimd(1,:)*rprimd(1,nu)+rprimd(2,:)*rprimd(2,nu)+&
759 [ + + ]: 1248 : & rprimd(3,:)*rprimd(3,nu)
760 : : end do
761 : :
762 : : !Compute 1st and 2nd derivatives of metric tensor wrt all strain components
763 : : !and store for use in inner loop below.
764 : :
765 [ - + ]: 96 : ABI_MALLOC(d2rm,(3,3,6,6))
766 : :
767 : : !Loop over 2nd strain index
768 [ + + ]: 672 : do is2=1,6
769 : 576 : kg=idx(2*is2-1);kd=idx(2*is2)
770 [ + + ]: 2304 : do jj = 1,3
771 [ + + ]: 7488 : drm(:,jj,is2)=rprimd(kg,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kg,jj)
772 : : end do
773 : :
774 : : ! Loop over 1st strain index
775 [ + + ]: 4128 : do is1=1,6
776 : :
777 : 3456 : ka=idx(2*is1-1);kb=idx(2*is1)
778 [ + + + + ]: 44928 : d2rm(:,:,is1,is2)=0._dp
779 [ + + ]: 14400 : do jj = 1,3
780 [ + + ]: 10368 : if(ka==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
781 [ + + ]: 16128 : & +rprimd(kb,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kb,jj)
782 [ + + ]: 10368 : if(ka==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
783 [ + + ]: 11520 : & +rprimd(kb,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(kb,jj)
784 [ + + ]: 10368 : if(kb==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
785 [ + + ]: 11520 : & +rprimd(ka,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(ka,jj)
786 [ + + ]: 10368 : if(kb==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
787 [ + + ]: 19584 : & +rprimd(ka,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(ka,jj)
788 : : end do
789 : : end do !is1
790 : : end do !is2
791 : :
792 : 96 : ngfft(1)=n1
793 : 96 : ngfft(2)=n2
794 : 96 : ngfft(3)=n3
795 : 96 : delta=1.0_dp/(n1xccc-1)
796 : 96 : deltam1=n1xccc-1
797 : 96 : delta2div6=delta**2/6.0_dp
798 : :
799 : : !Loop over atoms in unit cell
800 [ + + + + ]: 7476 : eltfrxc_core(:,:)=zero
801 : :
802 [ + + ]: 282 : do iat=1,my_natom
803 [ - + ]: 186 : iatom=iat;if (paral_atom) iatom=my_atmtab(iat)
804 : 186 : js=7+3*(iatom-1)
805 : : ! Set search range (density cuts off perfectly beyond range)
806 : : ! Cycle if no range.
807 : 186 : range=0.0_dp
808 : 186 : range=xcccrc(typat(iatom))
809 [ + + ]: 186 : if(range<1.d-16) cycle
810 : :
811 : 180 : range2=range**2
812 : 180 : rangem1=1.0_dp/range
813 : :
814 : : ! Consider each component in turn
815 [ + + ]: 720 : do mu=1,3
816 : 540 : tau(mu)=mod(xred(mu,iatom)+1._dp-aint(xred(mu,iatom)),1._dp)
817 : :
818 : : ! Use tau to find nearest grid point along R(mu)
819 : : ! (igrid=0 is the origin; shift by 1 to agree with usual index)
820 : 540 : igrid(mu)=nint(tau(mu)*dble(ngfft(mu)))
821 : :
822 : : ! Use range to compute an index range along R(mu)
823 : : ! (add 1 to make sure it covers full range)
824 : 540 : irange(mu)=1+nint((range/scale(mu))*dble(ngfft(mu)))
825 : :
826 : : ! Check that the largest range is smallest than the maximum
827 : : ! allowed one
828 [ - + ]: 540 : if(2*irange(mu)+1 > mshift)then
829 : 0 : write(message, '(a,i0,a)' )' The range around atom',iatom,' is too large.'
830 : 0 : ABI_BUG(message)
831 : : end if
832 : :
833 : : ! Set up a counter that explore the relevant range
834 : : ! of points around the atom
835 : 540 : ishift=0
836 [ + + ]: 19320 : do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
837 : 18600 : ishift=ishift+1
838 : 18600 : ii(ishift,mu)=1+mod(ngfft(mu)+mod(ixp,ngfft(mu)),ngfft(mu))
839 : 19140 : rrdiff(ishift,mu)=dble(ixp)/dble(ngfft(mu))-tau(mu)
840 : : end do
841 : :
842 : : ! End loop on mu
843 : : end do
844 : :
845 : : ! Conduct triple loop over restricted range of grid points for iatom
846 : :
847 [ + + ]: 6468 : do ishift3=1,1+2*irange(3)
848 : : ! map back to [1,ngfft(3)] for usual fortran index in unit cell
849 : 6192 : i3=ii(ishift3,3)
850 : : ! find vector from atom location to grid point (reduced)
851 : 6192 : rdiff3=rrdiff(ishift3,3)
852 : :
853 [ + + ]: 226506 : do ishift2=1,1+2*irange(2)
854 : 220128 : i2=ii(ishift2,2)
855 : 220128 : rdiff2=rrdiff(ishift2,2)
856 : : ! Prepare the computation of difmag2
857 : : difmag2_part=rmet(3,3)*rdiff3**2+rmet(2,2)*rdiff2**2&
858 : 220128 : & +2.0_dp*rmet(3,2)*rdiff3*rdiff2
859 : 220128 : difmag2_fact=2.0_dp*(rmet(3,1)*rdiff3+rmet(2,1)*rdiff2)
860 : :
861 [ + + ]: 8302464 : do ishift1=1,1+2*irange(1)
862 : 8076144 : rdiff1=rrdiff(ishift1,1)
863 : :
864 : : ! Compute (rgrid-tau-Rprim)**2
865 : 8076144 : difmag2= difmag2_part+rdiff1*(difmag2_fact+rmet(1,1)*rdiff1)
866 : :
867 : : ! Only accept contribution inside defined range
868 [ + + ]: 8296272 : if (difmag2<range2) then
869 : :
870 : : ! Prepare computation of core charge function and derivatives,
871 : : ! using splines
872 : 2641878 : difmag=sqrt(difmag2)
873 [ + + ]: 2641878 : if (difmag>=1.0d-10) then
874 : 2641764 : i1=ii(ishift1,1)
875 : 2641764 : yy=difmag*rangem1
876 : :
877 : : ! Compute index of yy over 1 to n1xccc scale
878 : 2641764 : jj=1+int(yy*(n1xccc-1))
879 : 2641764 : diff=yy-(jj-1)*delta
880 : :
881 : : ! Will evaluate spline fit (p. 86 Numerical Recipes, Press et al;
882 : : ! NOTE error in book for sign of "aa" term in derivative;
883 : : ! also see splfit routine).
884 : 2641764 : bb = diff*deltam1
885 : 2641764 : aa = 1.0_dp-bb
886 : 2641764 : cc = aa*(aa**2-1.0_dp)*delta2div6
887 : 2641764 : dd = bb*(bb**2-1.0_dp)*delta2div6
888 : :
889 : : ! Evaluate spline fit of 1st der of core charge density
890 : : ! from xccc1d(:,2,:) and (:,4,:)
891 : : func1=aa*xccc1d(jj,2,typat(iatom))+bb*xccc1d(jj+1,2,typat(iatom)) +&
892 : 2641764 : & cc*xccc1d(jj,4,typat(iatom))+dd*xccc1d(jj+1,4,typat(iatom))
893 : 2641764 : term1=func1*rangem1
894 : : ! Evaluate spline fit of 2nd der of core charge density
895 : : ! from xccc1d(:,3,:) and (:,5,:)
896 : : func2=aa*xccc1d(jj,3,typat(iatom))+bb*xccc1d(jj+1,3,typat(iatom)) +&
897 : 2641764 : & cc*xccc1d(jj,5,typat(iatom))+dd*xccc1d(jj+1,5,typat(iatom))
898 : 2641764 : term2=func2*rangem1**2
899 : :
900 : 2641764 : ifft=i1+n1*(i2-1+n2*(i3-1))
901 [ + + ]: 10567056 : tt(:)=rmet(:,1)*rdiff1+rmet(:,2)*rdiff2+rmet(:,3)*rdiff3
902 : :
903 : : ! Add contributions to 2nd derivative tensor
904 : : drss2=&
905 : : & (rdiff1*(drm(1,1,is2_in)*rdiff1+drm(1,2,is2_in)*rdiff2&
906 : : & +drm(1,3,is2_in)*rdiff3)&
907 : : & +rdiff2*(drm(2,1,is2_in)*rdiff1+drm(2,2,is2_in)*rdiff2&
908 : : & +drm(2,3,is2_in)*rdiff3)&
909 : : & +rdiff3*(drm(3,1,is2_in)*rdiff1+drm(3,2,is2_in)*rdiff2&
910 : 2641764 : & +drm(3,3,is2_in)*rdiff3))
911 : :
912 : : ! Loop over 1st strain index
913 [ + + ]: 18492348 : do is1=1,6
914 : :
915 : : drss1=&
916 : : & (rdiff1*(drm(1,1,is1)*rdiff1+drm(1,2,is1)*rdiff2&
917 : : & +drm(1,3,is1)*rdiff3)&
918 : : & +rdiff2*(drm(2,1,is1)*rdiff1+drm(2,2,is1)*rdiff2&
919 : : & +drm(2,3,is1)*rdiff3)&
920 : : & +rdiff3*(drm(3,1,is1)*rdiff1+drm(3,2,is1)*rdiff2&
921 : 15850584 : & +drm(3,3,is1)*rdiff3))
922 : :
923 : : d2rss=&
924 : : & (rdiff1*(d2rm(1,1,is1,is2_in)*rdiff1+d2rm(1,2,is1,is2_in)*rdiff2&
925 : : & +d2rm(1,3,is1,is2_in)*rdiff3)&
926 : : & +rdiff2*(d2rm(2,1,is1,is2_in)*rdiff1+d2rm(2,2,is1,is2_in)*rdiff2&
927 : : & +d2rm(2,3,is1,is2_in)*rdiff3)&
928 : : & +rdiff3*(d2rm(3,1,is1,is2_in)*rdiff1+d2rm(3,2,is1,is2_in)*rdiff2&
929 : 15850584 : & +d2rm(3,3,is1,is2_in)*rdiff3))
930 : :
931 : : ! Vall(0) X Rhocore(2) term
932 : : eltfrxc_core(is1,is2_in)=eltfrxc_core(is1,is2_in)+0.25_dp*&
933 : : & (vxc_core(ifft)*(term1*(d2rss/difmag&
934 : : & -drss1*drss2/difmag**3)&
935 : 15850584 : & +term2*drss1*drss2/difmag**2))
936 : :
937 : : ! Vall(1) X Rhocore(1) term
938 : : eltfrxc_core(is1,is2_in)=eltfrxc_core(is1,is2_in)+0.25_dp*&
939 : 15850584 : & vxc10_core(ifft)*drss1*term1/difmag
940 : : eltfrxc_core(is2_in,is1)=eltfrxc_core(is2_in,is1)+0.25_dp*&
941 : 18492348 : & vxc10_core(ifft)*drss1*term1/difmag
942 : :
943 : : ! End loop in is1
944 : : end do
945 : : ! Internal strain contributions
946 : : ts2(:)=drm(:,1,is2_in)*rdiff1+drm(:,2,is2_in)*rdiff2&
947 [ + + ]: 10567056 : & +drm(:,3,is2_in)*rdiff3
948 : :
949 : : eltfrxc_core(js:js+2,is2_in)=eltfrxc_core(js:js+2,is2_in)&
950 : : & -(vxc1is_core(ifft)*term1/difmag&
951 : : & +0.5_dp*vxc_core(ifft)*(term2-term1/difmag)*drss2/difmag**2)*tt(:)&
952 [ + + ]: 10567056 : & -(vxc_core(ifft)*term1/difmag)*ts2(:)
953 : :
954 : : ! End of the condition for the distance not to vanish
955 : : end if
956 : :
957 : : ! End of condition to be inside the range
958 : : end if
959 : :
960 : : ! End loop on ishift1
961 : : end do
962 : :
963 : : ! End loop on ishift2
964 : : end do
965 : :
966 : : ! End loop on ishift3
967 : : end do
968 : :
969 : : ! End loop on atoms
970 : : end do
971 : :
972 : : !In case of parallelism over atoms: communicate
973 [ - + ]: 96 : if (paral_atom) then
974 : 0 : call timab(48,1,tsec)
975 : 0 : call xmpi_sum(eltfrxc_core,my_comm_atom,ierr)
976 : 0 : call timab(48,2,tsec)
977 : : end if
978 : :
979 : : !Add core contribution to XC elastic tensor
980 [ + + + + ]: 7476 : eltfrxc(:,:)=eltfrxc(:,:)+eltfrxc_core(:,:)
981 : :
982 : : !Destroy atom table used for parallelism
983 : 96 : call free_my_atmtab(my_atmtab,my_atmtab_allocated)
984 : :
985 [ + - - + ]: 192 : ABI_FREE(d2rm)
986 : :
987 : : contains
988 : :
989 : 288 : function cross_elt(xx,yy,zz,aa,bb,cc)
990 : : !Define magnitude of cross product of two vectors
991 : : real(dp) :: cross_elt
992 : : real(dp),intent(in) :: xx,yy,zz,aa,bb,cc
993 : 288 : cross_elt=sqrt((yy*cc-zz*bb)**2+(zz*aa-xx*cc)**2+(xx*bb-yy*aa)**2)
994 : 288 : end function cross_elt
995 : :
996 : : end subroutine eltxccore
997 : : !!***
998 : :
999 : : !!****f* ABINIT/dfpt_eltfrloc
1000 : : !! NAME
1001 : : !! dfpt_eltfrloc
1002 : : !!
1003 : : !! FUNCTION
1004 : : !! Compute the frozen-wavefunction local pseudopotential contribution
1005 : : !! to the elastic tensor and the internal strain (derivative wrt one
1006 : : !! cartesian strain component and one reduced-coordinate atomic displacement).
1007 : : !!
1008 : : !! INPUTS
1009 : : !! atindx(natom)=index table for atoms (see gstate.f)
1010 : : !! gmet(3,3)=reciprocal space metric (bohr^-2)
1011 : : !! gprimd(3,3)=dimensional primitive translations for reciprocal space (bohr**-1)
1012 : : !! gsqcut=cutoff on G^2 based on ecut
1013 : : !! mgfft=maximum size of 1D FFTs
1014 : : !! mpi_enreg=information about MPI parallelization
1015 : : !! mqgrid=dimensioned number of q grid points for local psp spline
1016 : : !! natom=number of atoms in unit cell
1017 : : !! nattyp(ntypat)=number of atoms of each type
1018 : : !! nfft=(effective) number of FFT grid points (for this processor)
1019 : : !! ngfft(18)=contain all needed information about 3D FFT,
1020 : : !! see ~abinit/doc/variables/vargs.htm#ngfft
1021 : : !! ntypat=number of types of atoms
1022 : : !! ph1d(2,3*(2*mgfft+1)*natom)=one-dimensional structure factor information
1023 : : !! qgrid(mqgrid)=q point array for local psp spline fits
1024 : : !! rhog(2,nfft)=electron density in G space
1025 : : !! vlspl(mqgrid,2,ntypat)=q^2 v(q) spline for each type of atom.
1026 : : !!
1027 : : !! OUTPUT
1028 : : !! eltfrloc(6+3*natom,6)=non-symmetrized local pseudopotenial contribution
1029 : : !! to the elastic tensor and internal strain.
1030 : : !!
1031 : : !! SOURCE
1032 : :
1033 : 37 : subroutine dfpt_eltfrloc(atindx,eltfrloc,gmet,gprimd,gsqcut,mgfft,&
1034 : 37 : & mpi_enreg,mqgrid,natom,nattyp,nfft,ngfft,ntypat,ph1d,qgrid,rhog,vlspl)
1035 : :
1036 : : !Arguments ------------------------------------
1037 : : !scalars
1038 : : integer,intent(in) :: mgfft,mqgrid,natom,nfft,ntypat
1039 : : real(dp),intent(in) :: gsqcut
1040 : : type(MPI_type),intent(in) :: mpi_enreg
1041 : : !arrays
1042 : : integer,intent(in) :: atindx(natom),nattyp(ntypat),ngfft(18)
1043 : : real(dp),intent(in) :: gmet(3,3),gprimd(3,3),ph1d(2,3*(2*mgfft+1)*natom)
1044 : : real(dp),intent(in) :: qgrid(mqgrid),rhog(2,nfft),vlspl(mqgrid,2,ntypat)
1045 : : real(dp),intent(out) :: eltfrloc(6+3*natom,6)
1046 : :
1047 : : !Local variables-------------------------------
1048 : : !scalars
1049 : : integer,parameter :: im=2,re=1
1050 : : integer :: i1,i2,i3,ia,ia1,ia2,id1,id2,id3,ielt,ieltx,ierr,ig1,ig2,ig3,ii
1051 : : integer :: is1,is2,itypat,jj,ka,kb,kd,kg,me_fft,n1,n2,n3,nproc_fft
1052 : : real(dp),parameter :: tolfix=1.0000001_dp
1053 : : real(dp) :: aa,bb,cc,cutoff,d2g
1054 : : real(dp) :: dd,dg1,dg2,diff,dq
1055 : : real(dp) :: dq2div6,dqdiv6,dqm1,ee,ff,gmag,gsquar
1056 : : real(dp) :: sfi,sfr,term,term1
1057 : : !real(dp) :: ph1_elt,ph2_elt,ph3_elt,phi_elt,phr_elt
1058 : : real(dp) :: term2,term3,term4,term5,vion1,vion2,vion3
1059 : : !arrays
1060 : : integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
1061 : 37 : integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:)
1062 : 37 : integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:)
1063 : : real(dp) :: dgm(3,3,6),tsec(2)
1064 : 37 : real(dp),allocatable :: d2gm(:,:,:,:),elt_work(:,:)
1065 : :
1066 : : ! *************************************************************************
1067 : :
1068 : 37 : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
1069 : 37 : me_fft=ngfft(11) ; nproc_fft=ngfft(10)
1070 : :
1071 : : !Get the distrib associated with this fft_grid
1072 : 37 : call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
1073 : :
1074 : : !-----
1075 : : !Compute 1st and 2nd derivatives of metric tensor wrt all strain components
1076 : : !and store for use in inner loop below.
1077 [ - + ]: 37 : ABI_MALLOC(d2gm,(3,3,6,6))
1078 : :
1079 : : !Loop over 2nd strain index
1080 [ + + ]: 259 : do is2=1,6
1081 : 222 : kg=idx(2*is2-1);kd=idx(2*is2)
1082 [ + + ]: 888 : do jj = 1,3
1083 [ + + ]: 2886 : dgm(:,jj,is2)=-(gprimd(kg,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kg,jj))
1084 : : end do
1085 : : ! Loop over 1st strain index, upper triangle only
1086 [ + + ]: 1036 : do is1=1,is2
1087 : 777 : ka=idx(2*is1-1);kb=idx(2*is1)
1088 [ + + + + ]: 10101 : d2gm(:,:,is1,is2)=0._dp
1089 [ + + ]: 3330 : do jj = 1,3
1090 [ + + ]: 2331 : if(ka==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
1091 [ + + ]: 4440 : & +gprimd(kb,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kb,jj)
1092 [ + + ]: 2331 : if(ka==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
1093 [ + + ]: 2664 : & +gprimd(kb,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(kb,jj)
1094 [ + + ]: 2331 : if(kb==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
1095 [ + + ]: 3108 : & +gprimd(ka,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(ka,jj)
1096 [ + + ]: 2331 : if(kb==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
1097 [ + + ]: 5217 : & +gprimd(ka,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(ka,jj)
1098 : : end do
1099 : : end do !is1
1100 : : end do !is2
1101 : :
1102 : : !Zero out array to permit accumulation over atom types below:
1103 [ + + + + ]: 3283 : eltfrloc(:,:)=0.0_dp
1104 : :
1105 : 37 : dq=(qgrid(mqgrid)-qgrid(1))/dble(mqgrid-1)
1106 : 37 : dqm1=1.0_dp/dq
1107 : 37 : dqdiv6=dq/6.0_dp
1108 : 37 : dq2div6=dq**2/6.0_dp
1109 : 37 : cutoff=gsqcut*tolfix
1110 : 37 : id1=n1/2+2
1111 : 37 : id2=n2/2+2
1112 : 37 : id3=n3/2+2
1113 : :
1114 : 37 : ia1=1
1115 [ + + ]: 98 : do itypat=1,ntypat
1116 : : ! ia1,ia2 sets range of loop over atoms:
1117 : 61 : ia2=ia1+nattyp(itypat)-1
1118 : 61 : ii=0
1119 [ + + ]: 1411 : do i3=1,n3
1120 : 1350 : ig3=i3-(i3/id3)*n3-1
1121 [ + + ]: 24317 : do i2=1,n2
1122 [ + - ]: 24256 : if (fftn2_distrib(i2)==me_fft) then
1123 : 22906 : ig2=i2-(i2/id2)*n2-1
1124 [ + + ]: 419836 : do i1=1,n1
1125 : 396930 : ig1=i1-(i1/id1)*n1-1
1126 : :
1127 : 396930 : ii=ii+1
1128 : : ! Skip G=0:
1129 [ + + ]: 396930 : if (ig1==0 .and. ig2==0 .and. ig3==0) cycle
1130 : :
1131 : : ! Skip G**2 outside cutoff:
1132 : 396869 : gsquar=gsq_elt(ig1,ig2,ig3)
1133 [ + + ]: 419775 : if (gsquar<=cutoff) then
1134 : 132058 : gmag=sqrt(gsquar)
1135 : :
1136 : : ! Compute vion(G) for given type of atom
1137 : 132058 : jj=1+int(gmag*dqm1)
1138 : 132058 : diff=gmag-qgrid(jj)
1139 : :
1140 : : ! Evaluate spline fit from q^2 V(q) to get V(q):
1141 : : ! (p. 86 Numerical Recipes, Press et al; NOTE error in book for sign
1142 : : ! of "aa" term in derivative; also see splfit routine).
1143 : 132058 : bb = diff*dqm1
1144 : 132058 : aa = 1.0_dp-bb
1145 : 132058 : cc = aa*(aa**2-1.0_dp)*dq2div6
1146 : 132058 : dd = bb*(bb**2-1.0_dp)*dq2div6
1147 : : term1 = (aa*vlspl(jj,1,itypat)+bb*vlspl(jj+1,1,itypat) +&
1148 : 132058 : & cc*vlspl(jj,2,itypat)+dd*vlspl(jj+1,2,itypat))
1149 : 132058 : vion1=term1 / gsquar
1150 : :
1151 : : ! Also get dV(q)/dq:
1152 : : ! (note correction of Numerical Recipes sign error
1153 : : ! before (3._dp*aa**2-1._dp)
1154 : 132058 : ee= vlspl(jj+1,1,itypat)-vlspl(jj,1,itypat)
1155 : : ff= (3._dp*bb**2-1._dp)*vlspl(jj+1,2,itypat) &
1156 : 132058 : & - (3._dp*aa**2-1._dp)*vlspl(jj,2,itypat)
1157 : 132058 : term2 = ee*dqm1 + ff*dqdiv6
1158 : 132058 : vion2 = term2/gsquar - 2._dp*term1/(gsquar*gmag)
1159 : :
1160 : : ! Also get V''(q)
1161 : 132058 : term3=aa*vlspl(jj,2,itypat)+bb*vlspl(jj+1,2,itypat)
1162 : 132058 : vion3 = (term3 - 4.0_dp*term2/gmag + 6._dp*term1/gsquar)/gsquar
1163 : :
1164 : : ! Assemble structure factor over all atoms of given type:
1165 : 132058 : sfr=zero;sfi=zero
1166 [ + + ]: 361046 : do ia=ia1,ia2
1167 : 228988 : sfr=sfr+phre_elt(ig1,ig2,ig3,ia)
1168 : 361046 : sfi=sfi-phimag_elt(ig1,ig2,ig3,ia)
1169 : : end do
1170 : 132058 : term=(rhog(re,ii)*sfr+rhog(im,ii)*sfi)
1171 : :
1172 : : ! Loop over 2nd strain index
1173 [ + + ]: 924406 : do is2=1,6
1174 : 792348 : dg2=0.5_dp*dgsqds_elt(ig1,ig2,ig3,is2)/gmag
1175 : : ! Loop over 1st strain index, upper triangle only
1176 [ + + ]: 3565566 : do is1=1,is2
1177 : 2773218 : dg1=0.5_dp*dgsqds_elt(ig1,ig2,ig3,is1)/gmag
1178 : 2773218 : d2g=(0.25_dp*d2gsqds_elt(ig1,ig2,ig3,is1,is2)-dg1*dg2)/gmag
1179 : : eltfrloc(is1,is2)=eltfrloc(is1,is2)+&
1180 : 2773218 : & term*(vion3*dg1*dg2+vion2*d2g)
1181 [ + + ]: 2773218 : if(is2<=3)&
1182 : 792348 : & eltfrloc(is1,is2)=eltfrloc(is1,is2)-term*vion2*dg1
1183 [ + + ]: 2773218 : if(is1<=3)&
1184 : 1980870 : & eltfrloc(is1,is2)=eltfrloc(is1,is2)-term*vion2*dg2
1185 [ + + + + ]: 2773218 : if(is1<=3 .and. is2<=3)&
1186 : 1584696 : & eltfrloc(is1,is2)=eltfrloc(is1,is2)+term*vion1
1187 : : end do !is1
1188 : :
1189 : : ! Internal strain section - loop over current atoms
1190 [ + + ]: 2298334 : do ia=ia1,ia2
1191 [ + + ]: 1373928 : if(is2 <=3) then
1192 : 686964 : term4=vion2*dg2-vion1
1193 : : else
1194 : 686964 : term4=vion2*dg2
1195 : : end if
1196 : : term5=-two_pi*(rhog(re,ii)*phimag_elt(ig1,ig2,ig3,ia)&
1197 : 1373928 : & +rhog(im,ii)*phre_elt(ig1,ig2,ig3,ia))*term4
1198 : 1373928 : eltfrloc(7+3*(ia-1),is2)=eltfrloc(7+3*(ia-1),is2)+term5*dble(ig1)
1199 : 1373928 : eltfrloc(8+3*(ia-1),is2)=eltfrloc(8+3*(ia-1),is2)+term5*dble(ig2)
1200 : 2166276 : eltfrloc(9+3*(ia-1),is2)=eltfrloc(9+3*(ia-1),is2)+term5*dble(ig3)
1201 : : end do
1202 : :
1203 : : end do !is2
1204 : :
1205 : : ! End skip G**2 outside cutoff:
1206 : : end if
1207 : :
1208 : : ! End loop on n1, n2, n3. There is a "cycle" inside the loop
1209 : : end do
1210 : : end if
1211 : : end do
1212 : : end do
1213 : :
1214 : : ! End loop on type of atoms
1215 : 98 : ia1=ia2+1
1216 : : end do
1217 : : !Init mpi_comm
1218 : 37 : call timab(48,1,tsec)
1219 : 37 : call xmpi_sum(eltfrloc,mpi_enreg%comm_fft,ierr)
1220 : 37 : call timab(48,2,tsec)
1221 : :
1222 : : !Fill in lower triangle
1223 [ + + ]: 222 : do is2=2,6
1224 [ + + ]: 777 : do is1=1,is2-1
1225 : 740 : eltfrloc(is2,is1)=eltfrloc(is1,is2)
1226 : : end do
1227 : : end do
1228 : :
1229 : : !The indexing array atindx is used to reestablish the correct
1230 : : !order of atoms
1231 [ + - - + : 185 : ABI_MALLOC(elt_work,(6+3*natom,6))
+ - + - +
- + - - +
- + ]
1232 [ + + + + ]: 1591 : elt_work(1:6,1:6)=eltfrloc(1:6,1:6)
1233 [ + + ]: 131 : do ia=1,natom
1234 : 94 : ielt=7+3*(ia-1)
1235 : 94 : ieltx=7+3*(atindx(ia)-1)
1236 [ + + + + ]: 2387 : elt_work(ielt:ielt+2,1:6)=eltfrloc(ieltx:ieltx+2,1:6)
1237 : : end do
1238 [ + + + + ]: 3283 : eltfrloc(:,:)=elt_work(:,:)
1239 : :
1240 [ - + ]: 37 : ABI_FREE(d2gm)
1241 [ - + ]: 74 : ABI_FREE(elt_work)
1242 : :
1243 : : contains
1244 : :
1245 : : !Real and imaginary parts of phase.
1246 : 1602916 : function phr_elt(x1,y1,x2,y2,x3,y3)
1247 : :
1248 : : real(dp) :: phr_elt,x1,x2,x3,y1,y2,y3
1249 : 1602916 : phr_elt=(x1*x2-y1*y2)*x3-(y1*x2+x1*y2)*y3
1250 : : end function phr_elt
1251 : :
1252 : 1602916 : function phi_elt(x1,y1,x2,y2,x3,y3)
1253 : :
1254 : : real(dp):: phi_elt,x1,x2,x3,y1,y2,y3
1255 : 1602916 : phi_elt=(x1*x2-y1*y2)*y3+(y1*x2+x1*y2)*x3
1256 : : end function phi_elt
1257 : :
1258 : 6411664 : function ph1_elt(nri,ig1,ia)
1259 : :
1260 : : real(dp):: ph1_elt
1261 : : integer :: nri,ig1,ia
1262 : 6411664 : ph1_elt=ph1d(nri,ig1+1+n1+(ia-1)*(2*n1+1))
1263 : 6411664 : end function ph1_elt
1264 : :
1265 : 6411664 : function ph2_elt(nri,ig2,ia)
1266 : :
1267 : : real(dp):: ph2_elt
1268 : : integer :: nri,ig2,ia
1269 : 6411664 : ph2_elt=ph1d(nri,ig2+1+n2+(ia-1)*(2*n2+1)+natom*(2*n1+1))
1270 : 6411664 : end function ph2_elt
1271 : :
1272 : 6411664 : function ph3_elt(nri,ig3,ia)
1273 : :
1274 : : real(dp):: ph3_elt
1275 : : integer :: nri,ig3,ia
1276 : 6411664 : ph3_elt=ph1d(nri,ig3+1+n3+(ia-1)*(2*n3+1)+natom*(2*n1+1+2*n2+1))
1277 : 6411664 : end function ph3_elt
1278 : :
1279 : 1602916 : function phre_elt(ig1,ig2,ig3,ia)
1280 : :
1281 : : real(dp):: phre_elt
1282 : : integer :: ig1,ig2,ig3,ia
1283 : : phre_elt=phr_elt(ph1_elt(re,ig1,ia),ph1_elt(im,ig1,ia),&
1284 : 1602916 : & ph2_elt(re,ig2,ia),ph2_elt(im,ig2,ia),ph3_elt(re,ig3,ia),ph3_elt(im,ig3,ia))
1285 : 1602916 : end function phre_elt
1286 : :
1287 : 1602916 : function phimag_elt(ig1,ig2,ig3,ia)
1288 : :
1289 : : real(dp) :: phimag_elt
1290 : : integer :: ig1,ig2,ig3,ia
1291 : : phimag_elt=phi_elt(ph1_elt(re,ig1,ia),ph1_elt(im,ig1,ia),&
1292 : 1602916 : & ph2_elt(re,ig2,ia),ph2_elt(im,ig2,ia),ph3_elt(re,ig3,ia),ph3_elt(im,ig3,ia))
1293 : 1602916 : end function phimag_elt
1294 : :
1295 : 396869 : function gsq_elt(i1,i2,i3)
1296 : :
1297 : : real(dp) :: gsq_elt
1298 : : integer :: i1,i2,i3
1299 : : !Define G^2 based on G space metric gmet.
1300 : : gsq_elt=dble(i1*i1)*gmet(1,1)+dble(i2*i2)*gmet(2,2)+&
1301 : : & dble(i3*i3)*gmet(3,3)+dble(2*i1*i2)*gmet(1,2)+&
1302 : 396869 : & dble(2*i2*i3)*gmet(2,3)+dble(2*i3*i1)*gmet(3,1)
1303 : 396869 : end function gsq_elt
1304 : :
1305 : 3565566 : function dgsqds_elt(i1,i2,i3,is)
1306 : :
1307 : : real(dp) :: dgsqds_elt
1308 : : integer :: i1,i2,i3,is
1309 : : !Define dG^2/ds based on G space metric derivative
1310 : : dgsqds_elt=dble(i1*i1)*dgm(1,1,is)+dble(i2*i2)*dgm(2,2,is)+&
1311 : : & dble(i3*i3)*dgm(3,3,is)+&
1312 : : & dble(i1*i2)*(dgm(1,2,is)+dgm(2,1,is))+&
1313 : : & dble(i1*i3)*(dgm(1,3,is)+dgm(3,1,is))+&
1314 : 3565566 : & dble(i2*i3)*(dgm(2,3,is)+dgm(3,2,is))
1315 : 3565566 : end function dgsqds_elt
1316 : :
1317 : 2773218 : function d2gsqds_elt(i1,i2,i3,is1,is2)
1318 : :
1319 : : real(dp) :: d2gsqds_elt
1320 : : integer :: i1,i2,i3,is1,is2
1321 : : !Define 2dG^2/ds1ds2 based on G space metric derivative
1322 : : d2gsqds_elt=dble(i1*i1)*d2gm(1,1,is1,is2)+&
1323 : : & dble(i2*i2)*d2gm(2,2,is1,is2)+dble(i3*i3)*d2gm(3,3,is1,is2)+&
1324 : : & dble(i1*i2)*(d2gm(1,2,is1,is2)+d2gm(2,1,is1,is2))+&
1325 : : & dble(i1*i3)*(d2gm(1,3,is1,is2)+d2gm(3,1,is1,is2))+&
1326 : 2773218 : & dble(i2*i3)*(d2gm(2,3,is1,is2)+d2gm(3,2,is1,is2))
1327 : 2773218 : end function d2gsqds_elt
1328 : :
1329 : : end subroutine dfpt_eltfrloc
1330 : : !!***
1331 : :
1332 : : !!****f* ABINIT/dfpt_eltfrkin
1333 : : !! NAME
1334 : : !! dfpt_eltfrkin
1335 : : !!
1336 : : !! FUNCTION
1337 : : !! Compute the frozen-wavefunction kinetic enegy contribution to the
1338 : : !! elastic tensor
1339 : : !!
1340 : : !! INPUTS
1341 : : !! cg(2,mpw*nspinor*mband_mem*mkmem*nsppol)=<G|Cnk>=Fourier coefficients of wavefunction
1342 : : !! ecut=cut-off energy for plane wave basis sphere (Ha)
1343 : : !! ecutsm=smearing energy for plane wave kinetic energy (Ha) (NOT NEEDED !)
1344 : : !! effmass_free=effective mass for electrons (1. in common case)
1345 : : !! istwfk(nkpt)=input option parameter that describes the storage of wfs
1346 : : !! kg(3,mpw*mkmem)=work array for coordinates of G vectors in basis
1347 : : !! kptns(3,nkpt)=coordinates of k points in terms of reciprocal space
1348 : : !! primitive translations
1349 : : !! mband=maximum number of bands
1350 : : !! mband_mem=maximum number of bands in memory
1351 : : !! mgfft=maximum size of 1D FFTs
1352 : : !! mkmem=number of k points treated by this node.
1353 : : !! mpi_enreg=information about MPI parallelization
1354 : : !! mpw=maximum dimension for number of planewaves
1355 : : !! nband(nkpt*nsppol)=number of bands being considered per k point
1356 : : !! nkpt=number of k points
1357 : : !! ngfft(18)=contain all needed information about 3D FFT, i
1358 : : !! see ~abinit/doc/variables/vargs.htm#ngfft
1359 : : !! npwarr(nkpt)=number of planewaves at each k point, and boundary
1360 : : !! nspinor=number of spinorial components of the wavefunctions
1361 : : !! nsppol=1 for unpolarized, 2 for polarized
1362 : : !! occ(mband*nkpt*nsppol)=occupation numbers of bands (usually 2)
1363 : : !! at each k point
1364 : : !! rprimd(3,3)=dimensional real space primitive translations (bohr)
1365 : : !! wtk(nkpt)=k point weights
1366 : : !!
1367 : : !! OUTPUT
1368 : : !! eltfrkin(6,6)=non-symmetrized kinetic energy contribution to the
1369 : : !! elastic tensor
1370 : : !!
1371 : : !! SOURCE
1372 : :
1373 : 37 : subroutine dfpt_eltfrkin(cg,eltfrkin,ecut,ecutsm,effmass_free,&
1374 : 37 : & istwfk,kg,kptns,mband,mband_mem,mgfft,mkmem,mpi_enreg,&
1375 : 37 : & mpw,nband,nkpt,ngfft,npwarr,nspinor,nsppol,occ,rprimd,wtk)
1376 : :
1377 : : !Arguments ------------------------------------
1378 : : !scalars
1379 : : integer,intent(in) :: mband,mband_mem,mgfft,mkmem,mpw,nkpt,nspinor,nsppol
1380 : : real(dp),intent(in) :: ecut,ecutsm,effmass_free
1381 : : type(MPI_type),intent(in) :: mpi_enreg
1382 : : !arrays
1383 : : integer,intent(in) :: istwfk(nkpt),kg(3,mpw*mkmem),nband(nkpt*nsppol)
1384 : : integer,intent(in) :: ngfft(18),npwarr(nkpt)
1385 : : real(dp),intent(in) :: cg(2,mpw*nspinor*mband_mem*mkmem*nsppol),kptns(3,nkpt)
1386 : : real(dp),intent(in) :: occ(mband*nkpt*nsppol),rprimd(3,3),wtk(nkpt)
1387 : : real(dp),intent(out) :: eltfrkin(6,6)
1388 : :
1389 : : !Local variables-------------------------------
1390 : : !scalars
1391 : : integer :: bdtot_index,iband,icg,ierr,ii,ikg
1392 : : integer :: ikpt,index,ipw,isppol,istwf_k,jj,master,me,n1,n2
1393 : : integer :: n3,nband_k,nkinout,npw_k,spaceComm
1394 : : integer :: nband_me, iband_me
1395 : : real(dp) :: ucvol
1396 : : !arrays
1397 : 37 : integer,allocatable :: gbound(:,:),kg_k(:,:)
1398 : : real(dp) :: gmet(3,3),gprimd(3,3),kpoint(3),rmet(3,3),tsec(2)
1399 : 37 : real(dp),allocatable :: cwavef(:,:),ekinout(:)
1400 : 37 : real(dp),allocatable :: eltfrkink(:,:)
1401 : :
1402 : : ! *************************************************************************
1403 : :
1404 : : DBG_ENTER("COLL")
1405 : :
1406 : : !Default for sequential use
1407 : 37 : master=0
1408 : : !Init mpi_comm
1409 : 37 : spaceComm=mpi_enreg%comm_cell
1410 : 37 : me=mpi_enreg%me_kpt
1411 : :
1412 : : !Compute gmet, gprimd and ucvol from rprimd
1413 : 37 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
1414 : :
1415 : 37 : eltfrkin(:,:)=0.0_dp
1416 : 37 : bdtot_index=0
1417 : 37 : icg=0
1418 : :
1419 : 37 : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
1420 [ - + + - : 111 : ABI_MALLOC(kg_k,(3,mpw))
+ - + - -
+ - + ]
1421 [ - + + - : 111 : ABI_MALLOC(cwavef,(2,mpw*nspinor))
+ - + - -
+ - + ]
1422 [ - + ]: 37 : ABI_MALLOC(eltfrkink,(6,6))
1423 : :
1424 : : !Define k-points distribution
1425 : :
1426 : : !LOOP OVER SPINS
1427 [ + + ]: 76 : do isppol=1,nsppol
1428 : 39 : ikg=0
1429 : :
1430 : : ! Loop over k points
1431 [ + + ]: 5756 : do ikpt=1,nkpt
1432 : :
1433 : 5680 : nband_k=nband(ikpt+(isppol-1)*nkpt)
1434 : 5680 : istwf_k=istwfk(ikpt)
1435 : 5680 : npw_k=npwarr(ikpt)
1436 : :
1437 : : ! Skip this k-point if not the proper processor
1438 [ + + ]: 5680 : if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me)) then
1439 : 32 : bdtot_index=bdtot_index+nband_k
1440 : 32 : cycle
1441 : : end if
1442 : :
1443 : : ! find number of bands I will actually treat
1444 : 5648 : nband_me = proc_distrb_nband(mpi_enreg%proc_distrb,ikpt,nband_k,isppol,me)
1445 : :
1446 [ + - - + : 22592 : ABI_MALLOC(gbound,(2*mgfft+8,2))
+ - + - +
- + - - +
- + ]
1447 [ + + ]: 22592 : kpoint(:)=kptns(:,ikpt)
1448 : :
1449 [ + + + + ]: 2776608 : kg_k(:,:) = 0
1450 : :
1451 : :
1452 : : !$OMP PARALLEL DO PRIVATE(ipw) SHARED(ikg,kg,kg_k,npw_k)
1453 [ + + ]: 662007 : do ipw=1,npw_k
1454 : 656359 : kg_k(1,ipw)=kg(1,ipw+ikg)
1455 : 656359 : kg_k(2,ipw)=kg(2,ipw+ikg)
1456 : 662007 : kg_k(3,ipw)=kg(3,ipw+ikg)
1457 : : end do
1458 : :
1459 : 5648 : call sphereboundary(gbound,istwf_k,kg_k,mgfft,npw_k)
1460 : :
1461 : 5648 : index=1+icg
1462 : :
1463 [ + + + + ]: 242864 : eltfrkink(:,:)=0.0_dp
1464 : :
1465 : 5648 : nkinout=6*6
1466 [ - + ]: 5648 : ABI_MALLOC(ekinout,(nkinout))
1467 [ + + ]: 208976 : ekinout(:)=zero
1468 : :
1469 : : iband_me = 0
1470 [ + + ]: 29080 : do iband=1,nband_k
1471 : :
1472 [ - + ]: 23432 : if(mpi_enreg%proc_distrb(ikpt,iband,isppol) /= me) cycle
1473 : 23432 : iband_me = iband_me + 1
1474 : :
1475 [ + + + + ]: 8715776 : cwavef(:,1:npw_k*nspinor)=cg(:,1+(iband_me-1)*npw_k*nspinor+icg:iband_me*npw_k*nspinor+icg)
1476 : :
1477 : : call d2kindstr2(cwavef,ecut,ecutsm,effmass_free,ekinout,gmet,gprimd,&
1478 : 23432 : & istwf_k,kg_k,kpoint,npw_k,nspinor)
1479 : :
1480 [ + + + + ]: 1013224 : eltfrkink(:,:)=eltfrkink(:,:)+ occ(iband+bdtot_index)* reshape(ekinout(:), (/6,6/) )
1481 : :
1482 : : end do !iband
1483 : :
1484 [ - + ]: 5648 : ABI_FREE(ekinout)
1485 : :
1486 [ + + + + ]: 242864 : eltfrkin(:,:)=eltfrkin(:,:)+wtk(ikpt)*eltfrkink(:,:)
1487 : :
1488 [ - + ]: 5648 : ABI_FREE(gbound)
1489 : :
1490 : 5648 : bdtot_index=bdtot_index+nband_k
1491 : :
1492 [ + - ]: 5687 : if (mkmem/=0) then
1493 : : ! Handle case in which kg, cg, are kept in core
1494 : 5648 : icg=icg+npw_k*nspinor*nband_me
1495 : 5648 : ikg=ikg+npw_k
1496 : : end if
1497 : :
1498 : : end do
1499 : : end do ! End loops on isppol and ikpt
1500 : :
1501 : : !Fill in lower triangle
1502 [ + + ]: 222 : do jj=2,6
1503 [ + + ]: 777 : do ii=1,jj-1
1504 : 740 : eltfrkin(jj,ii)=eltfrkin(ii,jj)
1505 : : end do
1506 : : end do
1507 : :
1508 : : !Accumulate eltfrkin on all proc.
1509 : 37 : call timab(48,1,tsec)
1510 : 37 : call xmpi_sum(eltfrkin,spaceComm,ierr)
1511 : 37 : call timab(48,2,tsec)
1512 : :
1513 [ - + ]: 37 : ABI_FREE(cwavef)
1514 [ - + ]: 37 : ABI_FREE(eltfrkink)
1515 [ - + ]: 37 : ABI_FREE(kg_k)
1516 : :
1517 : : DBG_EXIT("COLL")
1518 : :
1519 : : contains
1520 : : !!***
1521 : :
1522 : : !!****f* ABINIT/d2kindstr2
1523 : : !! NAME
1524 : : !! d2kindstr2
1525 : : !!
1526 : : !! FUNCTION
1527 : : !! compute expectation value of the second derivatives of the kinetic energy
1528 : : !! wrt strain for one band and kpoint
1529 : : !!
1530 : : !! INPUTS
1531 : : !! cwavef(2,npw*nspinor)=wavefunction for current band
1532 : : !! ecut=cut-off energy for plane wave basis sphere (Ha)
1533 : : !! ecutsm=smearing energy for plane wave kinetic energy (Ha)
1534 : : !! effmass_free=effective mass for electrons (1. in common case)
1535 : : !! gmet(3,3)=reciprocal lattice metric tensor ($\textrm{Bohr}^{-2}$)
1536 : : !! gprimd(3,3)=primitive vectors in reciprocal space
1537 : : !! istwfk=information about wavefunction storage
1538 : : !! kg_k(3,npw)=integer coordinates of planewaves in basis sphere.
1539 : : !! kpt(3)=reduced coordinates of k point
1540 : : !! npw=number of plane waves at kpt.
1541 : : !! nspinor=number of spinorial components of the wavefunction
1542 : : !!
1543 : : !! OUTPUT
1544 : : !! ekinout(36)=expectation values of the second strain derivatives
1545 : : !! of the (modified) kinetic energy
1546 : : !!
1547 : : !! NOTES
1548 : : !! Usually, the kinetic energy expression is $(1/2) (2 \pi)^2 (k+G)^2 $
1549 : : !! However, the present implementation allows for a modification
1550 : : !! of this kinetic energy, in order to obtain smooth total energy
1551 : : !! curves with respect to the cut-off energy or the cell size and shape.
1552 : : !! Thus the usual expression is kept if it is lower then ecut-ecutsm,
1553 : : !! zero is returned beyond ecut, and in between, the kinetic
1554 : : !! energy is DIVIDED by a smearing factor (to make it infinite at the
1555 : : !! cut-off energy). The smearing factor is $x^2 (3-2x)$, where
1556 : : !! x = (ecut- unmodified energy)/ecutsm.
1557 : : !!
1558 : : !! SOURCE
1559 : :
1560 : 23432 : subroutine d2kindstr2(cwavef,ecut,ecutsm,effmass_free,ekinout,gmet,gprimd,&
1561 : 23432 : & istwfk,kg_k,kpt,npw,nspinor)
1562 : :
1563 : : !Arguments ------------------------------------
1564 : : !scalars
1565 : : integer,intent(in) :: istwfk,npw,nspinor
1566 : : real(dp),intent(in) :: ecut,ecutsm,effmass_free
1567 : : !arrays
1568 : : integer,intent(in) :: kg_k(3,npw)
1569 : : real(dp),intent(in) :: cwavef(2,npw*nspinor),gmet(3,3),gprimd(3,3),kpt(3)
1570 : : real(dp),intent(inout) :: ekinout(36) !vz_i
1571 : :
1572 : : !Local variables-------------------------------
1573 : : !scalars
1574 : : integer,parameter :: im=2,re=1
1575 : : integer :: ig,igs,ii,ispinor,istr1,istr2,ka,kb,kd,kg
1576 : : real(dp) :: d2fkin,d2fsm,d2kinacc,d2kpg2,dfkin,dfsm,dkpg21,dkpg22,ecutsm_inv
1577 : : real(dp) :: fsm,gpk1,gpk2,gpk3,htpisq,kpg2,term,xx
1578 : : !arrays
1579 : : integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
1580 : : real(dp) :: d2gm(3,3),dgm01(3,3),dgm10(3,3)
1581 : :
1582 : : ! *************************************************************************
1583 : : !
1584 : : !htpisq is (1/2) (2 Pi) **2:
1585 : 23432 : htpisq=0.5_dp*(two_pi)**2
1586 : :
1587 : 23432 : ecutsm_inv=0.0_dp
1588 [ + + ]: 23432 : if(ecutsm>1.0d-20)ecutsm_inv=1/ecutsm
1589 : :
1590 : : !Loop over 2nd strain index
1591 [ + + ]: 164024 : do istr2=1,6
1592 : : ! Loop over 1st strain index, upper triangle only
1593 [ + + ]: 656096 : do istr1=1,istr2
1594 : :
1595 : 492072 : ka=idx(2*istr1-1);kb=idx(2*istr1);kg=idx(2*istr2-1);kd=idx(2*istr2)
1596 : :
1597 [ + + ]: 1968288 : do ii = 1,3
1598 [ + + ]: 5904864 : dgm01(:,ii)=-(gprimd(ka,:)*gprimd(kb,ii)+gprimd(kb,:)*gprimd(ka,ii))
1599 [ + + ]: 6396936 : dgm10(:,ii)=-(gprimd(kg,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kg,ii))
1600 : : end do
1601 : :
1602 : 492072 : d2gm(:,:)=0._dp
1603 [ + + ]: 1968288 : do ii = 1,3
1604 [ + + ]: 1476216 : if(ka==kg) d2gm(:,ii)=d2gm(:,ii)&
1605 [ + + ]: 2811840 : & +gprimd(kb,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kb,ii)
1606 [ + + ]: 1476216 : if(ka==kd) d2gm(:,ii)=d2gm(:,ii)&
1607 [ + + ]: 1687104 : & +gprimd(kb,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(kb,ii)
1608 [ + + ]: 1476216 : if(kb==kg) d2gm(:,ii)=d2gm(:,ii)&
1609 [ + + ]: 1968288 : & +gprimd(ka,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(ka,ii)
1610 [ + + ]: 1476216 : if(kb==kd) d2gm(:,ii)=d2gm(:,ii)&
1611 [ + + ]: 3303912 : & +gprimd(ka,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(ka,ii)
1612 : : end do
1613 [ + + + + ]: 6396936 : d2gm(:,:)=0.5_dp*d2gm(:,:)
1614 : :
1615 : : d2kinacc=0._dp
1616 : :
1617 : : ! loop on spinor index
1618 [ + + ]: 984144 : do ispinor=1,nspinor
1619 : 492072 : igs=(ispinor-1)*npw
1620 : : ! loop on plane waves
1621 [ + + ]: 61830552 : do ig=1,npw
1622 : 60846408 : gpk1=dble(kg_k(1,ig))+kpt(1)
1623 : 60846408 : gpk2=dble(kg_k(2,ig))+kpt(2)
1624 : 60846408 : gpk3=dble(kg_k(3,ig))+kpt(3)
1625 : : kpg2=htpisq*&
1626 : : & ( gmet(1,1)*gpk1**2+ &
1627 : : & gmet(2,2)*gpk2**2+ &
1628 : : & gmet(3,3)*gpk3**2 &
1629 : : & +2.0_dp*(gpk1*gmet(1,2)*gpk2+ &
1630 : : & gpk1*gmet(1,3)*gpk3+ &
1631 : 60846408 : & gpk2*gmet(2,3)*gpk3 ) )
1632 : : dkpg21=htpisq*&
1633 : : & ( dgm01(1,1)*gpk1**2+ &
1634 : : & dgm01(2,2)*gpk2**2+ &
1635 : : & dgm01(3,3)*gpk3**2 &
1636 : : & +2.0_dp*(gpk1*dgm01(1,2)*gpk2+ &
1637 : : & gpk1*dgm01(1,3)*gpk3+ &
1638 : 60846408 : & gpk2*dgm01(2,3)*gpk3 ) )
1639 : : dkpg22=htpisq*&
1640 : : & ( dgm10(1,1)*gpk1**2+ &
1641 : : & dgm10(2,2)*gpk2**2+ &
1642 : : & dgm10(3,3)*gpk3**2 &
1643 : : & +2.0_dp*(gpk1*dgm10(1,2)*gpk2+ &
1644 : : & gpk1*dgm10(1,3)*gpk3+ &
1645 : 60846408 : & gpk2*dgm10(2,3)*gpk3 ) )
1646 : : d2kpg2=htpisq*&
1647 : : & ( d2gm(1,1)*gpk1**2+ &
1648 : : & d2gm(2,2)*gpk2**2+ &
1649 : : & d2gm(3,3)*gpk3**2 &
1650 : : & +2.0_dp*(gpk1*d2gm(1,2)*gpk2+ &
1651 : : & gpk1*d2gm(1,3)*gpk3+ &
1652 : 60846408 : & gpk2*d2gm(2,3)*gpk3 ) )
1653 : :
1654 [ + - ]: 60846408 : if(kpg2>ecut-tol12)then
1655 : : dfkin=0._dp
1656 : : d2fkin=0._dp
1657 [ + + ]: 60846408 : elseif(kpg2>ecut-ecutsm)then
1658 : : ! This kinetic cutoff smoothing function and its xx derivatives
1659 : : ! were produced with Mathematica and the fortran code has been
1660 : : ! numerically checked against Mathematica.
1661 : 6141576 : xx=(ecut-kpg2)*ecutsm_inv
1662 : 6141576 : fsm=1.0_dp/(xx**2*(3+xx*(1+xx*(-6+3*xx))))
1663 : 6141576 : dfsm=-3.0_dp*(-1+xx)**2*xx*(2+5*xx)*fsm**2
1664 : : d2fsm=6.0_dp*xx**2*(9+xx*(8+xx*(-52+xx*(-3+xx*(137+xx*&
1665 : 6141576 : & (-144+45*xx))))))*fsm**3
1666 : 6141576 : dfkin=fsm-ecutsm_inv*kpg2*dfsm
1667 : 6141576 : d2fkin=ecutsm_inv*(-2.0_dp*dfsm+ecutsm_inv*kpg2*d2fsm)
1668 : : else
1669 : : dfkin=1._dp
1670 : : d2fkin=0._dp
1671 : : end if
1672 : :
1673 : : ! accumulate kinetic energy 2nd derivative with wavefunction components
1674 : 60846408 : term=d2fkin*dkpg21*dkpg22 + dfkin*d2kpg2
1675 [ - + - - ]: 60846408 : if(istwfk==2 .and. ig/=1)term=2.0_dp*term
1676 [ - + ]: 60846408 : if(istwfk>2)term=2.0_dp*term
1677 : 61338480 : d2kinacc=d2kinacc + term*(cwavef(re,ig+igs)**2 + cwavef(im,ig+igs)**2)
1678 : :
1679 : : end do !ig
1680 : : end do !ispinor
1681 : :
1682 : 632664 : ekinout(istr1+6*(istr2-1))=d2kinacc/effmass_free
1683 : :
1684 : : end do !istr1
1685 : : end do !istr2
1686 : :
1687 : 23432 : end subroutine d2kindstr2
1688 : : !!***
1689 : :
1690 : : end subroutine dfpt_eltfrkin
1691 : : !!***
1692 : :
1693 : : !!****f* ABINIT/dfpt_eltfrhar
1694 : : !! NAME
1695 : : !! dfpt_eltfrhar
1696 : : !!
1697 : : !! FUNCTION
1698 : : !! Compute the frozen-wavefunction hartree enegy contribution to the elastic tensor
1699 : : !!
1700 : : !! INPUTS
1701 : : !! rprimd(3,3)=dimensional primitive translation vectors (bohr)
1702 : : !! gsqcut =Fourier cutoff on G^2 for "large sphere" of radius double
1703 : : !! that of the basis sphere--appropriate for charge density rho(G),
1704 : : !! Hartree potential, and pseudopotentials
1705 : : !! mpi_enreg=information about MPI parallelization
1706 : : !! nfft =(effective) number of FFT grid points (for this processor)
1707 : : !! ngfft(18)=contain all needed information about 3D FFT,
1708 : : !! see ~abinit/doc/variables/vargs.htm#ngfft
1709 : : !! rhog(2,nfft)=total electron density in G space
1710 : : !!
1711 : : !! OUTPUT
1712 : : !! eltfrhar(6,6)=non-symmetrized kinetic energy contribution to the
1713 : : !! elastic tensor
1714 : : !! NOTES
1715 : : !! *based largely on hartre.f
1716 : : !!
1717 : : !! SOURCE
1718 : :
1719 : 37 : subroutine dfpt_eltfrhar(eltfrhar,rprimd,gsqcut,mpi_enreg,nfft,ngfft,rhog)
1720 : :
1721 : : !Arguments ------------------------------------
1722 : : !scalars
1723 : : integer,intent(in) :: nfft
1724 : : real(dp),intent(in) :: gsqcut
1725 : : type(MPI_type),intent(in) :: mpi_enreg
1726 : : !arrays
1727 : : integer,intent(in) :: ngfft(18)
1728 : : real(dp),intent(in) :: rhog(2,nfft),rprimd(3,3)
1729 : : real(dp),intent(out) :: eltfrhar(6,6)
1730 : :
1731 : : !Local variables-------------------------------
1732 : : !scalars
1733 : : integer,parameter :: im=2,re=1
1734 : : integer :: i1,i2,i23,i3,id2,id3,ierr,ig,ig2,ig3,ii,ii1,ing,istr1,istr2,jj
1735 : : integer :: ka,kb,kd,kg,me_fft,n1,n2,n3,nproc_fft
1736 : : real(dp),parameter :: tolfix=1.000000001_dp
1737 : : real(dp) :: cutoff,d2eacc,d2etot,d2gs,deacc01,deacc10,dgs01,dgs10,eacc,fact,gs
1738 : : real(dp) :: term,ucvol
1739 : : !arrays
1740 : : integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
1741 : : integer :: id(3)
1742 : 37 : integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:)
1743 : 37 : integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:)
1744 : : real(dp) :: d2gm(3,3),dgm01(3,3),dgm10(3,3),gmet(3,3),gprimd(3,3),gqr(3)
1745 : : real(dp) :: rmet(3,3),tsec(2)
1746 : 37 : real(dp),allocatable :: gq(:,:)
1747 : :
1748 : : ! *************************************************************************
1749 : :
1750 : : !Compute gmet, gprimd and ucvol from rprimd
1751 : 37 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
1752 : :
1753 : 37 : eltfrhar(:,:)=0.0_dp
1754 : :
1755 : 37 : n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
1756 : 37 : me_fft=ngfft(11)
1757 : 37 : nproc_fft=ngfft(10)
1758 : :
1759 : : !Get the distrib associated with this fft_grid
1760 : 37 : call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
1761 : :
1762 : : !Initialize a few quantities
1763 : 37 : fact=0.5_dp*ucvol/pi
1764 : 37 : cutoff=gsqcut*tolfix
1765 : :
1766 : : !In order to speed the routine, precompute the components of g+q
1767 : : !Also check if the booked space was large enough...
1768 [ - + + - : 111 : ABI_MALLOC(gq,(3,max(n1,n2,n3)))
+ - + - -
+ + - ]
1769 [ + + ]: 148 : do ii=1,3
1770 : 111 : id(ii)=ngfft(ii)/2+2
1771 [ + + ]: 2130 : do ing=1,ngfft(ii)
1772 : 1982 : ig=ing-(ing/id(ii))*ngfft(ii)-1
1773 : 2093 : gq(ii,ing)=ig
1774 : : end do
1775 : : end do
1776 : :
1777 : : !Loop over 2nd strain index
1778 [ + + ]: 259 : do istr2=1,6
1779 : : ! Loop over 1st strain index, upper triangle only
1780 [ + + ]: 1036 : do istr1=1,istr2
1781 : :
1782 : 777 : ka=idx(2*istr1-1);kb=idx(2*istr1);kg=idx(2*istr2-1);kd=idx(2*istr2)
1783 : :
1784 [ + + ]: 3108 : do ii = 1,3
1785 [ + + ]: 9324 : dgm01(:,ii)=-(gprimd(ka,:)*gprimd(kb,ii)+gprimd(kb,:)*gprimd(ka,ii))
1786 [ + + ]: 10101 : dgm10(:,ii)=-(gprimd(kg,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kg,ii))
1787 : : end do
1788 : :
1789 : 777 : d2gm(:,:)=0._dp
1790 [ + + ]: 3108 : do ii = 1,3
1791 [ + + ]: 2331 : if(ka==kg) d2gm(:,ii)=d2gm(:,ii)&
1792 [ + + ]: 4440 : & +gprimd(kb,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kb,ii)
1793 [ + + ]: 2331 : if(ka==kd) d2gm(:,ii)=d2gm(:,ii)&
1794 [ + + ]: 2664 : & +gprimd(kb,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(kb,ii)
1795 [ + + ]: 2331 : if(kb==kg) d2gm(:,ii)=d2gm(:,ii)&
1796 [ + + ]: 3108 : & +gprimd(ka,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(ka,ii)
1797 [ + + ]: 2331 : if(kb==kd) d2gm(:,ii)=d2gm(:,ii)&
1798 [ + + ]: 5217 : & +gprimd(ka,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(ka,ii)
1799 : : end do
1800 [ + + + + ]: 10101 : d2gm(:,:)=0.5_dp*d2gm(:,:)
1801 : :
1802 : : ! initialize energy accumulator
1803 : 777 : eacc=0._dp
1804 : 777 : deacc01=0._dp
1805 : 777 : deacc10=0._dp
1806 : 777 : d2eacc=0._dp
1807 : :
1808 : 777 : id2=n2/2+2
1809 : 777 : id3=n3/2+2
1810 : : ! Triple loop on each dimension
1811 [ + + ]: 17115 : do i3=1,n3
1812 : 16338 : ig3=i3-(i3/id3)*n3-1
1813 : 16338 : gqr(3)=gq(3,i3)
1814 [ + + ]: 292299 : do i2=1,n2
1815 [ + - ]: 291522 : if (fftn2_distrib(i2)==me_fft) then
1816 : 275184 : gqr(2)=gq(2,i2)
1817 : 275184 : ig2=i2-(i2/id2)*n2-1
1818 : 275184 : i23=n1*(ffti2_local(i2)-1 +(n2/nproc_fft)*(i3-1))
1819 : : ! Do the test that eliminates the Gamma point outside
1820 : : ! of the inner loop
1821 : 275184 : ii1=1
1822 [ + + ]: 275184 : if(i23==0 .and. ig2==0 .and. ig3==0)then
1823 : 777 : ii1=2
1824 : : end if
1825 : :
1826 : : ! Final inner loop on the first dimension
1827 : : ! (note the lower limit)
1828 [ + + ]: 5003901 : do i1=ii1,n1
1829 : 4728717 : gqr(1)=gq(1,i1)
1830 : : gs=(gmet(1,1)*gqr(1)*gqr(1)+gmet(2,2)*gqr(2)*gqr(2)+&
1831 : : & gmet(3,3)*gqr(3)*gqr(3)+2._dp*&
1832 : : & (gmet(1,2)*gqr(1)*gqr(2) + gmet(1,3)*gqr(1)*gqr(3)+&
1833 : 4728717 : & gmet(2,3)*gqr(2)*gqr(3)) )
1834 : 4728717 : ii=i1+i23
1835 [ + + ]: 5003901 : if(gs<=cutoff)then
1836 : : dgs01=(dgm01(1,1)*gqr(1)*gqr(1)+dgm01(2,2)*gqr(2)*gqr(2)+&
1837 : : & dgm01(3,3)*gqr(3)*gqr(3)+2._dp*&
1838 : : & (dgm01(1,2)*gqr(1)*gqr(2) + dgm01(1,3)*gqr(1)*gqr(3)+&
1839 : 1552110 : & dgm01(2,3)*gqr(2)*gqr(3)) )
1840 : : dgs10=(dgm10(1,1)*gqr(1)*gqr(1)+dgm10(2,2)*gqr(2)*gqr(2)+&
1841 : : & dgm10(3,3)*gqr(3)*gqr(3)+2._dp*&
1842 : : & (dgm10(1,2)*gqr(1)*gqr(2) + dgm10(1,3)*gqr(1)*gqr(3)+&
1843 : 1552110 : & dgm10(2,3)*gqr(2)*gqr(3)) )
1844 : : d2gs =(d2gm(1,1)*gqr(1)*gqr(1)+d2gm(2,2)*gqr(2)*gqr(2)+&
1845 : : & d2gm(3,3)*gqr(3)*gqr(3)+2._dp*&
1846 : : & (d2gm(1,2)*gqr(1)*gqr(2) + d2gm(1,3)*gqr(1)*gqr(3)+&
1847 : 1552110 : & d2gm(2,3)*gqr(2)*gqr(3)) )
1848 : :
1849 : 1552110 : term=(rhog(re,ii)**2+rhog(im,ii)**2)/gs
1850 : 1552110 : eacc=eacc+term
1851 : 1552110 : deacc01=deacc01+dgs01*term/gs
1852 : 1552110 : deacc10=deacc10+dgs10*term/gs
1853 : 1552110 : d2eacc=d2eacc+(-d2gs+2._dp*dgs01*dgs10/gs)*term/gs
1854 : : end if
1855 : :
1856 : : ! End loop on i1
1857 : : end do
1858 : : end if
1859 : : ! End loop on i2
1860 : : end do
1861 : : ! End loop on i3
1862 : : end do
1863 : :
1864 : : ! Add contributions taking account diagonal strain terms (from ucvol
1865 : : ! derivatives)
1866 : 777 : d2etot=d2eacc
1867 [ + + ]: 777 : if(istr1<=3) d2etot=d2etot+deacc10
1868 [ + + ]: 777 : if(istr2<=3) d2etot=d2etot+deacc01
1869 [ + + ]: 777 : if(istr1<=3 .and. istr2<=3) d2etot=d2etot+eacc
1870 : :
1871 : 999 : eltfrhar(istr1,istr2)=fact*d2etot
1872 : :
1873 : : ! End loop on istr1
1874 : : end do
1875 : : ! End loop in istr2
1876 : : end do
1877 : :
1878 [ - + ]: 37 : ABI_FREE(gq)
1879 : :
1880 : : !Init mpi_comm
1881 : 37 : call timab(48,1,tsec)
1882 : 37 : call xmpi_sum(eltfrhar,mpi_enreg%comm_fft,ierr)
1883 : 37 : call timab(48,2,tsec)
1884 : :
1885 : : !Fill in lower triangle
1886 [ + + ]: 222 : do jj=2,6
1887 [ + + ]: 777 : do ii=1,jj-1
1888 : 740 : eltfrhar(jj,ii)=eltfrhar(ii,jj)
1889 : : end do
1890 : : end do
1891 : 37 : end subroutine dfpt_eltfrhar
1892 : : !!***
1893 : :
1894 : : !!****f* ABINIT/elt_ewald
1895 : : !!
1896 : : !! NAME
1897 : : !! elt_ewald
1898 : : !!
1899 : : !! FUNCTION
1900 : : !! Compute 2nd derivatives of Ewald energy wrt strain for frozen wavefunction
1901 : : !! contributions to elastic tensor
1902 : : !!
1903 : : !! INPUTS
1904 : : !! gmet(3,3)=metric tensor in reciprocal space (bohr^-2)
1905 : : !! gprimd(3,3)=dimensional primitive translations for reciprocal space (bohr^-1)
1906 : : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
1907 : : !! comm_atom=--optional-- MPI communicator over atoms
1908 : : !! my_natom=number of atoms treated by current processor
1909 : : !! natom=number of atoms in unit cell
1910 : : !! ntypat=numbe of type of atoms
1911 : : !! rmet(3,3)=metric tensor in real space (bohr^2)
1912 : : !! rprimd(3,3)=dimensional primitive translation vectors (bohr)
1913 : : !! typat(natom)=integer label of each type of atom (1,2,...)
1914 : : !! ucvol=unit cell volume (bohr^3)
1915 : : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
1916 : : !! zion(ntypat)=charge on each type of atom (real number)
1917 : : !!
1918 : : !! OUTPUT
1919 : : !! elteew(6+3*natom,6)=2nd derivatives of Ewald energy wrt strain
1920 : : !!
1921 : : !! SOURCE
1922 : :
1923 : 74 : subroutine elt_ewald(elteew,gmet,gprimd,my_natom,natom,ntypat,rmet,rprimd,&
1924 : 37 : & typat,ucvol,xred,zion, &
1925 [ + - + + : 37 : & mpi_atmtab,comm_atom) ! optional arguments (parallelism)
- + ]
1926 : :
1927 : : !Arguments ------------------------------------
1928 : : !scalars
1929 : : integer,intent(in) :: my_natom,natom,ntypat
1930 : : real(dp),intent(in) :: ucvol
1931 : : !arrays
1932 : : integer,intent(in) :: typat(natom)
1933 : : integer,optional,intent(in) :: comm_atom
1934 : : integer,optional,target,intent(in) :: mpi_atmtab(:)
1935 : : real(dp),intent(in) :: gmet(3,3),gprimd(3,3),rmet(3,3),rprimd(3,3)
1936 : : real(dp),intent(in) :: xred(3,natom),zion(ntypat)
1937 : : real(dp),intent(out) :: elteew(6+3*natom,6)
1938 : :
1939 : : !Local variables-------------------------------
1940 : : !scalars
1941 : : integer :: ia,ia0,ib,ierr,ig1,ig2,ig3,ir1,ir2,ir3,is1,is2,jj,js,ka,kb,kd,kg,my_comm_atom,newg,newr,ng,nr
1942 : : logical :: my_atmtab_allocated,paral_atom
1943 : : real(dp) :: arg,ch,chsq,cos_term,d2derfc,d2gss,d2r,d2rs,dderfc,derfc_arg
1944 : : real(dp) :: dgss1,dgss2,direct,dr1,dr2,drs1,drs2,eew,eta,fac,fraca1,fraca2
1945 : : real(dp) :: fraca3,fracb1,fracb2,fracb3,gsq,gsum,r1,r2,r3,recip,reta
1946 : : real(dp) :: rmagn,rsq,sin_term,sumg,summi,summr,sumr,t1,term
1947 : : character(len=500) :: message
1948 : : !arrays
1949 : : integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
1950 : 37 : integer,pointer :: my_atmtab(:)
1951 : : real(dp) :: d2gm(3,3,6,6),d2ris(3),d2rm(3,3,6,6),dgm(3,3,6),dris(3),drm(3,3,6)
1952 : : real(dp) :: t2(3),ts2(3),tsec(2),tt(3)
1953 : 37 : real(dp),allocatable :: d2sumg(:,:),d2sumr(:,:),drhoisi(:,:),drhoisr(:,:)
1954 : 37 : real(dp),allocatable :: mpibuf(:)
1955 : :
1956 : : ! *************************************************************************
1957 : :
1958 : : !DEBUG
1959 : : !write(std_out,*)' elt_ewald : enter '
1960 : : !stop
1961 : : !ENDDEBUG
1962 : :
1963 : : !Compute 1st and 2nd derivatives of metric tensor wrt all strain components
1964 : : !and store for use in inner loop below.
1965 : :
1966 : : !Set up parallelism over atoms
1967 [ + + ]: 37 : paral_atom=(present(comm_atom).and.(my_natom/=natom))
1968 [ + + ]: 37 : nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
1969 [ + - ]: 37 : my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
1970 : 37 : call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
1971 : :
1972 : : !Loop over 2nd strain index
1973 [ + + ]: 259 : do is2=1,6
1974 : 222 : kg=idx(2*is2-1);kd=idx(2*is2)
1975 [ + + ]: 888 : do jj = 1,3
1976 [ + + ]: 2664 : drm(:,jj,is2)=rprimd(kg,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kg,jj)
1977 [ + + ]: 2886 : dgm(:,jj,is2)=-(gprimd(kg,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kg,jj))
1978 : : end do
1979 : :
1980 : : ! Loop over 1st strain index, upper triangle only
1981 [ + + ]: 1036 : do is1=1,is2
1982 : :
1983 : 777 : ka=idx(2*is1-1);kb=idx(2*is1)
1984 [ + + + + ]: 10101 : d2rm(:,:,is1,is2)=zero
1985 [ + + + + ]: 10101 : d2gm(:,:,is1,is2)=zero
1986 [ + + ]: 3330 : do jj = 1,3
1987 [ + + ]: 2331 : if(ka==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
1988 [ + + ]: 4440 : & +rprimd(kb,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kb,jj)
1989 [ + + ]: 2331 : if(ka==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
1990 [ + + ]: 2664 : & +rprimd(kb,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(kb,jj)
1991 [ + + ]: 2331 : if(kb==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
1992 [ + + ]: 3108 : & +rprimd(ka,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(ka,jj)
1993 [ + + ]: 2331 : if(kb==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
1994 [ + + ]: 4440 : & +rprimd(ka,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(ka,jj)
1995 : :
1996 [ + + ]: 2331 : if(ka==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
1997 [ + + ]: 4440 : & +gprimd(kb,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kb,jj)
1998 [ + + ]: 2331 : if(ka==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
1999 [ + + ]: 2664 : & +gprimd(kb,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(kb,jj)
2000 [ + + ]: 2331 : if(kb==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
2001 [ + + ]: 3108 : & +gprimd(ka,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(ka,jj)
2002 [ + + ]: 2331 : if(kb==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
2003 [ + + ]: 5217 : & +gprimd(ka,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(ka,jj)
2004 : : end do
2005 : : end do !is1
2006 : : end do !is2
2007 : :
2008 : : !Add up total charge and sum of $charge^2$ in cell
2009 : : chsq=zero
2010 : : ch=zero
2011 [ + + ]: 131 : do ia=1,natom
2012 : 94 : ch=ch+zion(typat(ia))
2013 : 131 : chsq=chsq+zion(typat(ia))**2
2014 : : end do
2015 : :
2016 : : !Compute eta, the Ewald summation convergence parameter,
2017 : : !for approximately optimized summations:
2018 : : direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
2019 : 37 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
2020 : : recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
2021 : 37 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
2022 : : !Here, a bias is introduced, because G-space summation scales
2023 : : !better than r space summation ! Note : debugging is the most
2024 : : !easier at fixed eta.
2025 : : ! eta=pi*200._dp/33.0_dp*sqrt(1.69_dp*recip/direct)
2026 : 37 : eta=1.0_dp
2027 : :
2028 : : !Conduct reciprocal space summations
2029 : 37 : fac=pi**2/eta ; gsum=zero
2030 [ + - - + : 185 : ABI_MALLOC(d2sumg,(6+3*natom,6))
+ - + - +
- + - - +
- + ]
2031 [ - + + - : 111 : ABI_MALLOC(drhoisr,(3,natom))
+ - + - -
+ - + ]
2032 [ - + + - : 74 : ABI_MALLOC(drhoisi,(3,natom))
- + - + ]
2033 [ + + + + ]: 3283 : d2sumg(:,:)=zero
2034 : :
2035 : : !Sum over G space, done shell after shell until all
2036 : : !contributions are too small.
2037 : 37 : ng=0
2038 : : do
2039 : 930 : ng=ng+1
2040 : 930 : newg=0
2041 : :
2042 [ + + ]: 28672 : do ig3=-ng,ng
2043 [ + + ]: 1174074 : do ig2=-ng,ng
2044 [ + + ]: 57209902 : do ig1=-ng,ng
2045 : :
2046 : : ! Exclude shells previously summed over
2047 : : if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng&
2048 [ + + + + : 57182160 : & .or. ng==1 ) then
+ + + + ]
2049 : :
2050 : : ! gsq is G dot G = |G|^2
2051 : : gsq=gmet(1,1)*dble(ig1*ig1)+gmet(2,2)*dble(ig2*ig2)+&
2052 : : & gmet(3,3)*dble(ig3*ig3)+2._dp*(gmet(2,1)*dble(ig1*ig2)+&
2053 : 6546985 : & gmet(3,1)*dble(ig1*ig3)+gmet(3,2)*dble(ig3*ig2))
2054 : :
2055 : : ! Skip g=0:
2056 [ + + ]: 6546985 : if (gsq>1.0d-20) then
2057 : 6546948 : arg=fac*gsq
2058 : :
2059 : : ! Larger arg gives 0 contribution because of exp(-arg)
2060 [ + + ]: 6546948 : if (arg <= 80._dp) then
2061 : : ! When any term contributes then include next shell
2062 : 1275492 : newg=1
2063 : 1275492 : term=exp(-arg)/gsq
2064 : 1275492 : summr = zero
2065 : 1275492 : summi = zero
2066 : : ! Note that if reduced atomic coordinates xred drift outside
2067 : : ! of unit cell (outside [0,1)) it is irrelevant in the following
2068 : : ! term, which only computes a phase.
2069 [ + + ]: 5371384 : do ia=1,natom
2070 : 4095892 : arg=two_pi*(ig1*xred(1,ia)+ig2*xred(2,ia)+ig3*xred(3,ia))
2071 : : ! Sum real and imaginary parts (avoid complex variables)
2072 : 4095892 : cos_term=cos(arg)
2073 : 4095892 : sin_term=sin(arg)
2074 : 4095892 : summr=summr+zion(typat(ia))*cos_term
2075 : 4095892 : summi=summi+zion(typat(ia))*sin_term
2076 : 4095892 : drhoisr(1,ia)=-two_pi*zion(typat(ia))*sin_term*dble(ig1)
2077 : 4095892 : drhoisi(1,ia)= two_pi*zion(typat(ia))*cos_term*dble(ig1)
2078 : 4095892 : drhoisr(2,ia)=-two_pi*zion(typat(ia))*sin_term*dble(ig2)
2079 : 4095892 : drhoisi(2,ia)= two_pi*zion(typat(ia))*cos_term*dble(ig2)
2080 : 4095892 : drhoisr(3,ia)=-two_pi*zion(typat(ia))*sin_term*dble(ig3)
2081 : 5371384 : drhoisi(3,ia)= two_pi*zion(typat(ia))*cos_term*dble(ig3)
2082 : : end do
2083 : :
2084 : : ! The following two checks avoid an annoying
2085 : : ! underflow error message
2086 [ + + ]: 1275492 : if (abs(summr)<1.d-16) summr=zero
2087 [ + + ]: 1275492 : if (abs(summi)<1.d-16) summi=zero
2088 : :
2089 : : ! The product of term and summr**2 or summi**2 below
2090 : : ! can underflow if not for checks above
2091 : 1275492 : t1=term*(summr*summr+summi*summi)
2092 : 1275492 : gsum=gsum+t1
2093 : : ! Loop over 2nd strain index
2094 [ + + ]: 8928444 : do is2=1,6
2095 : : dgss2=dgm(1,1,is2)*dble(ig1*ig1)+dgm(2,2,is2)*dble(ig2*ig2)+&
2096 : : & dgm(3,3,is2)*dble(ig3*ig3)+2._dp*(dgm(2,1,is2)*dble(ig1*ig2)+&
2097 : 7652952 : & dgm(3,1,is2)*dble(ig1*ig3)+dgm(3,2,is2)*dble(ig3*ig2))
2098 : : ! Loop over 1st strain index, upper triangle only
2099 [ + + ]: 34438284 : do is1=1,is2
2100 : : dgss1=dgm(1,1,is1)*dble(ig1*ig1)+dgm(2,2,is1)*dble(ig2*ig2)+&
2101 : : & dgm(3,3,is1)*dble(ig3*ig3)+2._dp*(dgm(2,1,is1)*dble(ig1*ig2)+&
2102 : 26785332 : & dgm(3,1,is1)*dble(ig1*ig3)+dgm(3,2,is1)*dble(ig3*ig2))
2103 : :
2104 : : d2gss=d2gm(1,1,is1,is2)*dble(ig1*ig1)+&
2105 : : & d2gm(2,2,is1,is2)*dble(ig2*ig2)+&
2106 : : & d2gm(3,3,is1,is2)*dble(ig3*ig3)+2._dp*&
2107 : : & (d2gm(2,1,is1,is2)*dble(ig1*ig2)+&
2108 : : & d2gm(3,1,is1,is2)*dble(ig1*ig3)+&
2109 : 26785332 : & d2gm(3,2,is1,is2)*dble(ig3*ig2))
2110 : :
2111 : : d2sumg(is1,is2)=d2sumg(is1,is2)+&
2112 : : & t1*((fac**2 + 2.0_dp*fac/gsq + 2.0_dp/(gsq**2))*dgss1*dgss2 -&
2113 : 26785332 : & 0.5_dp*(fac + 1.0_dp/gsq)*d2gss)
2114 [ + + ]: 26785332 : if(is1<=3) d2sumg(is1,is2)=d2sumg(is1,is2)+&
2115 : 19132380 : & t1*(fac + 1.0_dp/gsq)*dgss2
2116 [ + + ]: 26785332 : if(is2<=3) d2sumg(is1,is2)=d2sumg(is1,is2)+&
2117 : 7652952 : & t1*(fac + 1.0_dp/gsq)*dgss1
2118 [ + + ]: 34438284 : if(is1<=3 .and. is2<=3) d2sumg(is1,is2)=d2sumg(is1,is2)+t1
2119 : :
2120 : : end do !is1
2121 : :
2122 : : ! Internal strain contributions
2123 [ + + ]: 33503796 : do ia=1,natom
2124 : 24575352 : js=7+3*(ia-1)
2125 [ + + ]: 98301408 : t2(:)=2.0_dp*term*(summr*drhoisr(:,ia)+summi*drhoisi(:,ia))
2126 : : d2sumg(js:js+2,is2)=d2sumg(js:js+2,is2)-&
2127 [ + + ]: 98301408 : & (fac + 1.0_dp/gsq)*dgss2*t2(:)
2128 [ + + + + ]: 69091332 : if(is2<=3) d2sumg(js:js+2,is2)=d2sumg(js:js+2,is2)-t2(:)
2129 : : end do
2130 : : end do !is2
2131 : :
2132 : : end if ! End condition of not larger than 80.0
2133 : : end if ! End skip g=0
2134 : : end if ! End triple loop over G s and associated new shell condition
2135 : : end do
2136 : : end do
2137 : : end do
2138 : :
2139 : : ! Check if new shell must be calculated
2140 [ + + ]: 930 : if (newg==0) exit
2141 : : end do ! End the loop on ng (new shells). Note that there is one exit from this loop.
2142 : :
2143 : 37 : sumg=gsum/(two_pi*ucvol)
2144 [ + + + + ]: 3283 : d2sumg(:,:)=d2sumg(:,:)/(two_pi*ucvol)
2145 : :
2146 [ - + ]: 37 : ABI_FREE(drhoisr)
2147 [ - + ]: 37 : ABI_FREE(drhoisi)
2148 : : !Stress tensor is now computed elsewhere (ewald2) hence do not need
2149 : : !length scale gradients (used to compute them here).
2150 : :
2151 : : !Conduct real space summations
2152 : 37 : reta=sqrt(eta)
2153 : 37 : fac=2._dp*sqrt(eta/pi)
2154 [ - + + - : 74 : ABI_MALLOC(d2sumr,(6+3*natom,6))
- + - + ]
2155 [ + + + + ]: 3283 : sumr=zero;d2sumr(:,:)=zero
2156 : :
2157 : : !In the following a summation is being conducted over all
2158 : : !unit cells (ir1, ir2, ir3) so it is appropriate to map all
2159 : : !reduced coordinates xred back into [0,1).
2160 : : !
2161 : : !Loop on shells in r-space as was done in g-space
2162 : 37 : nr=0
2163 : : do
2164 : 79 : nr=nr+1
2165 : 79 : newr=0
2166 : : !
2167 [ + + ]: 410 : do ir3=-nr,nr
2168 [ + + ]: 1913 : do ir2=-nr,nr
2169 [ + + ]: 9173 : do ir1=-nr,nr
2170 [ + + + + : 8842 : if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
+ + + + ]
2171 : :
2172 [ + + ]: 16773 : do ia0=1,my_natom
2173 [ + + ]: 11058 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2174 : 11058 : js=7+3*(ia-1)
2175 : : ! Map reduced coordinate xred(mu,ia) into [0,1)
2176 : 11058 : fraca1=xred(1,ia)-aint(xred(1,ia))+0.5_dp-sign(0.5_dp,xred(1,ia))
2177 : 11058 : fraca2=xred(2,ia)-aint(xred(2,ia))+0.5_dp-sign(0.5_dp,xred(2,ia))
2178 : 11058 : fraca3=xred(3,ia)-aint(xred(3,ia))+0.5_dp-sign(0.5_dp,xred(3,ia))
2179 [ + + ]: 48641 : do ib=1,natom
2180 : 30244 : fracb1=xred(1,ib)-aint(xred(1,ib))+0.5_dp-sign(0.5_dp,xred(1,ib))
2181 : 30244 : fracb2=xred(2,ib)-aint(xred(2,ib))+0.5_dp-sign(0.5_dp,xred(2,ib))
2182 : 30244 : fracb3=xred(3,ib)-aint(xred(3,ib))+0.5_dp-sign(0.5_dp,xred(3,ib))
2183 : 30244 : r1=dble(ir1)+fracb1-fraca1
2184 : 30244 : r2=dble(ir2)+fracb2-fraca2
2185 : 30244 : r3=dble(ir3)+fracb3-fraca3
2186 : : rsq=rmet(1,1)*r1*r1+rmet(2,2)*r2*r2+rmet(3,3)*r3*r3+&
2187 : 30244 : & 2.0_dp*(rmet(2,1)*r2*r1+rmet(3,2)*r3*r2+rmet(3,1)*r1*r3)
2188 : :
2189 : : ! Avoid zero denominators in 'term':
2190 [ + + ]: 41302 : if (rsq>=1.0d-24) then
2191 : :
2192 : : ! Note: erfc(8) is about 1.1e-29,
2193 : : ! so do not bother with larger arg.
2194 : : ! Also: exp(-64) is about 1.6e-28,
2195 : : ! so do not bother with larger arg**2 in exp.
2196 : 30166 : term=zero
2197 [ + + ]: 30166 : if (eta*rsq<64.0_dp) then
2198 : 1380 : newr=1
2199 : 1380 : rmagn=sqrt(rsq)
2200 : 1380 : arg=reta*rmagn
2201 : : ! derfc computes the complementary error function
2202 : : ! dderfc is the derivative of the complementary error function
2203 : : ! d2derfc is the 2nd derivative of the complementary error function
2204 : 1380 : dderfc=-fac*exp(-eta*rsq)
2205 : 1380 : d2derfc=-2._dp*eta*rmagn*dderfc
2206 : 1380 : derfc_arg = abi_derfc(arg)
2207 : 1380 : term=derfc_arg/rmagn
2208 : 1380 : sumr=sumr+zion(typat(ia))*zion(typat(ib))*term
2209 [ + + ]: 5520 : tt(:)=rmet(:,1)*r1+rmet(:,2)*r2+rmet(:,3)*r3
2210 [ + + ]: 5520 : dris(:)=tt(:)/rmagn
2211 : : ! Loop over 2nd strain index
2212 [ + + ]: 9660 : do is2=1,6
2213 : : drs2=drm(1,1,is2)*r1*r1+drm(2,2,is2)*r2*r2+&
2214 : : & drm(3,3,is2)*r3*r3+&
2215 : : & 2.0_dp*(drm(2,1,is2)*r2*r1+drm(3,2,is2)*r3*r2+&
2216 : 8280 : & drm(3,1,is2)*r1*r3)
2217 : 8280 : dr2=0.5_dp*drs2/rmagn
2218 : : ! Loop over 1st strain index, upper triangle only
2219 [ + + ]: 37260 : do is1=1,is2
2220 : : drs1=drm(1,1,is1)*r1*r1+drm(2,2,is1)*r2*r2+&
2221 : : & drm(3,3,is1)*r3*r3+&
2222 : : & 2.0_dp*(drm(2,1,is1)*r2*r1+drm(3,2,is1)*r3*r2+&
2223 : 28980 : & drm(3,1,is1)*r1*r3)
2224 : 28980 : dr1=0.5_dp*drs1/rmagn
2225 : : d2rs=d2rm(1,1,is1,is2)*r1*r1+d2rm(2,2,is1,is2)*r2*r2+&
2226 : : & d2rm(3,3,is1,is2)*r3*r3+&
2227 : : & 2.0_dp*(d2rm(2,1,is1,is2)*r2*r1+d2rm(3,2,is1,is2)*r3*r2+&
2228 : 28980 : & d2rm(3,1,is1,is2)*r1*r3)
2229 : 28980 : d2r=(0.25_dp*d2rs-dr1*dr2)/rmagn
2230 : : d2sumr(is1,is2)=d2sumr(is1,is2)+&
2231 : : & zion(typat(ia))*zion(typat(ib))*&
2232 : : & ((d2derfc-2.0_dp*dderfc/rmagn+2.0_dp*derfc_arg/rsq)*dr1*dr2+&
2233 : 37260 : & (dderfc-derfc_arg/rmagn)*d2r)/rmagn
2234 : : end do !is1
2235 : : ! Internal strain contribution
2236 [ + + ]: 33120 : ts2(:)=drm(:,1,is2)*r1+drm(:,2,is2)*r2+drm(:,3,is2)*r3
2237 [ + + ]: 33120 : d2ris(:)=ts2(:)/rmagn-0.5_dp*drs2*tt(:)/(rsq*rmagn)
2238 : :
2239 : : d2sumr(js:js+2,is2)=d2sumr(js:js+2,is2)-&
2240 : : & 2.0_dp*zion(typat(ia))*zion(typat(ib))*&
2241 : : & ((d2derfc-2.0_dp*dderfc/rmagn+2.0_dp*derfc_arg/rsq)*dr2*dris(:)+&
2242 [ + + ]: 34500 : & (dderfc-derfc_arg/rmagn)*d2ris(:))/rmagn
2243 : : end do !is2
2244 : : end if
2245 : : end if ! End avoid zero denominators in'term'
2246 : :
2247 : : end do ! end loop over ib:
2248 : : end do ! end loop over ia:
2249 : : end if ! end triple loop over real space points and associated condition of new shell
2250 : : end do
2251 : : end do
2252 : : end do
2253 : :
2254 : : ! Check if new shell must be calculated
2255 [ + + ]: 79 : if(newr==0) exit
2256 : : end do ! End loop on nr (new shells). Note that there is an exit within the loop
2257 : :
2258 : : !In case of parallelism over atoms: communicate
2259 [ + + ]: 37 : if (paral_atom) then
2260 : 6 : call timab(48,1,tsec)
2261 [ + - - + : 18 : ABI_MALLOC(mpibuf,((6+3*natom)*6+1))
+ - + - +
- - + -
+ ]
2262 [ + + ]: 12 : mpibuf(1:(6+3*natom)*6)=reshape(d2sumr(:,:),shape=(/((6+3*natom)*6)/))
2263 : 6 : mpibuf((6+3*natom)*6+1)=sumr
2264 : 6 : call xmpi_sum(mpibuf,my_comm_atom,ierr)
2265 : 6 : sumr=mpibuf((6+3*natom)*6+1)
2266 [ + + ]: 18 : d2sumr(:,:)=reshape(mpibuf(1:(6+3*natom)*6),shape=(/(6+3*natom),6/))
2267 : 6 : ABI_FREE(mpibuf)
2268 : 12 : call timab(48,2,tsec)
2269 : : end if
2270 : :
2271 : 37 : sumr=0.5_dp*sumr
2272 [ + + + + ]: 3283 : d2sumr(:,:)=0.5_dp*d2sumr(:,:)
2273 : 37 : fac=pi*ch**2/(2.0_dp*eta*ucvol)
2274 : :
2275 : : !Finally assemble Ewald energy, eew
2276 : 37 : eew=sumg+sumr-chsq*reta/sqrt(pi)-fac
2277 : :
2278 [ + + + + ]: 3283 : elteew(:,:)=d2sumg(:,:)+d2sumr(:,:)
2279 : :
2280 : : !Additional term for all strains diagonal (from "fac" term in eew)
2281 [ + + + + ]: 481 : elteew(1:3,1:3)=elteew(1:3,1:3)-fac
2282 : :
2283 : : !Fill in lower triangle
2284 [ + + ]: 222 : do is2=2,6
2285 [ + + ]: 777 : do is1=1,is2-1
2286 : 740 : elteew(is2,is1)=elteew(is1,is2)
2287 : : end do
2288 : : end do
2289 : :
2290 [ - + ]: 37 : ABI_FREE(d2sumg)
2291 [ - + ]: 37 : ABI_FREE(d2sumr)
2292 : :
2293 : : !Output the final values of ng and nr
2294 : 37 : write(message, '(a,i4,a,i4)' )' elt_ewald : nr and ng are ',nr,' and ',ng
2295 : 37 : call wrtout(std_out,message,'COLL')
2296 : :
2297 : : !Destroy atom table used for parallelism
2298 : 37 : call free_my_atmtab(my_atmtab,my_atmtab_allocated)
2299 : :
2300 [ + - - + ]: 74 : end subroutine elt_ewald
2301 : : !!***
2302 : :
2303 : : !!****f* ABINIT/dfpt_ewald
2304 : : !!
2305 : : !! NAME
2306 : : !! dfpt_ewald
2307 : : !!
2308 : : !! FUNCTION
2309 : : !! Compute ewald contribution to the dynamical matrix, at a given q wavevector.
2310 : : !! Note: the q=0 part should be subtracted, by another call to
2311 : : !! the present routine, with q=0. The present routine correspond
2312 : : !! to the quantity C_bar defined in Eq.(24) or (27) in Phys. Rev. B 55, 10355 (1997) [[cite:Gonze1997a]].
2313 : : !! The two calls correspond to Eq.(23) of the same paper.
2314 : : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
2315 : : !!
2316 : : !! INPUTS
2317 : : !! gmet(3,3)=metric tensor in reciprocal space (length units **-2)
2318 : : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
2319 : : !! comm_atom=--optional-- MPI communicator over atoms
2320 : : !! icutcoul= type of Coulomb cutoff to apply
2321 : : !! my_natom=number of atoms treated by current processor
2322 : : !! natom=number of atoms in unit cell
2323 : : !! qphon(3)=phonon wavevector (same system of coordinates as the
2324 : : !! reciprocal lattice vectors)
2325 : : !! rmet(3,3)=metric tensor in real space (length units squared)
2326 : : !! sumg0: if=1, the sum in reciprocal space must include g=0,
2327 : : !! if=0, this contribution must be skipped (q=0 singularity)
2328 : : !! typat(natom)=integer label of each type of atom (1,2,...)
2329 : : !! ucvol=unit cell volume in (whatever length scale units)**3
2330 : : !! vcutgeo(3)= array to describe the geometry of the Coulomb cutoff
2331 : : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
2332 : : !! zion(ntypat)=charge on each type of atom (real number)
2333 : : !!
2334 : : !! OUTPUT
2335 : : !! dyew(2,3,natom,3,natom)= Ewald part of the dynamical matrix,
2336 : : !! second energy derivative wrt xred(3,natom), Hartrees.
2337 : : !!
2338 : : !! SOURCE
2339 : :
2340 : 1800 : subroutine dfpt_ewald(dyew,gmet,gsqcut,icutcoul,my_natom,natom,ngfft,nkpt,qphon,rcut, &
2341 : 900 : & rmet,rprimd,sumg0,typat,ucvol,vcutgeo,xred,zion, &
2342 [ + - + + : 900 : & mpi_atmtab,comm_atom ) ! optional arguments (parallelism))
- + ]
2343 : :
2344 : : !Arguments -------------------------------
2345 : : !scalars
2346 : : integer,intent(in) :: icutcoul,my_natom,natom,nkpt,sumg0
2347 : : real(dp),intent(in) :: gsqcut,rcut,ucvol
2348 : : !arrays
2349 : : integer,intent(in) :: ngfft(18),typat(natom)
2350 : : integer,optional,intent(in) :: comm_atom
2351 : : integer,optional,target,intent(in) :: mpi_atmtab(:)
2352 : : real(dp),intent(in) :: gmet(3,3),qphon(3),rmet(3,3),rprimd(3,3),vcutgeo(3),xred(3,natom),zion(*)
2353 : : real(dp),intent(out) :: dyew(2,3,natom,3,natom)
2354 : :
2355 : : !Local variables -------------------------
2356 : : !nr, ng affect convergence of sums (nr=3,ng=5 is not good enough):
2357 : : !scalars
2358 : : integer,parameter :: im=2,ng=10,nr=6,re=1
2359 : : integer :: ia,ia0,ib,ierr,ig,ig1,ig2,ig23,ig3,ii,ing
2360 : : integer :: ir1,ir2,ir3,mu,my_comm_atom,nh,nu
2361 : : logical :: my_atmtab_allocated,paral_atom,computeit
2362 : : real(dp) :: arg,arga,argb,c1i,c1r,da1,da2,da3,derfc_arg
2363 : : real(dp) :: direct,dot1,dot2,dot3,dotr1,dotr2,dotr3
2364 : : real(dp) :: eta,fac,gdot12,gdot13,gdot23,gsq,gsum,norm1
2365 : : real(dp) :: r1,r2,r3,rdot12,rdot13,rdot23,recip,reta
2366 : : real(dp) :: reta3m,rmagn,rsq,term,term1,term2
2367 : : real(dp) :: term3,facg0
2368 : : character(len=500) :: message
2369 : : !arrays
2370 : : integer :: id(3)
2371 : 900 : integer, allocatable :: inv_ig(:,:)
2372 : : real(dp) :: tsec(2)
2373 : 900 : integer,pointer :: my_atmtab(:)
2374 : : real(dp) :: gpq(3),rq(3)
2375 : 900 : real(dp),allocatable :: gcutoff(:)
2376 : :
2377 : : ! *************************************************************************
2378 : :
2379 : : !Set up parallelism over atoms
2380 [ + + ]: 900 : paral_atom=(present(comm_atom).and.(my_natom/=natom))
2381 [ + + ]: 900 : nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
2382 [ + - ]: 900 : my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
2383 : 900 : call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
2384 : :
2385 : : !Compute eta for approximately optimized summations:
2386 : : direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
2387 : 900 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
2388 : : recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
2389 : 900 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
2390 : 900 : eta=pi*(dble(ng)/dble(nr))*sqrt(1.69_dp*recip/direct)
2391 : :
2392 : : !Test Ewald s summation
2393 : : !eta=1.2_dp*eta
2394 : :
2395 : : !Initialize Gcut-off array from m_gtermcutoff
2396 : : call termcutoff(gcutoff,gsqcut,icutcoul,ngfft,nkpt,rcut,rprimd,vcutgeo,&
2397 : 900 : & qpt=qphon)
2398 : :
2399 : : !Need a way to reverse mapping the indexes inside termcutoff and Ewald rotines
2400 : 900 : nh=MAX(ngfft(1),ngfft(2),ngfft(3))/2
2401 [ - + + - : 2700 : ABI_MALLOC(inv_ig,(3,-nh:nh))
+ - + - -
+ - + ]
2402 [ + + ]: 3600 : do ii=1,3
2403 : 2700 : id(ii)=ngfft(ii)/2+2
2404 [ + + ]: 50628 : do ing=1,ngfft(ii)
2405 : 47028 : ig=ing-(ing/id(ii))*ngfft(ii)-1
2406 : : ! Create reverse mapping
2407 : 49728 : inv_ig(ii, ig) = ing
2408 : : end do
2409 : : end do
2410 : :
2411 : : !Sum terms over g space:
2412 : 900 : fac=pi**2/eta
2413 : 900 : gsum=zero
2414 : 900 : da1=zero
2415 : 900 : da2=zero
2416 : 900 : da3=zero
2417 [ + + + + : 180724 : dyew(:,:,:,:,:)=zero
+ + + + +
+ ]
2418 : : ii=0
2419 [ + + ]: 19800 : do ig3=-ng,ng
2420 [ + + ]: 416700 : do ig2=-ng,ng
2421 [ + + ]: 8750700 : do ig1=-ng,ng
2422 : 8334900 : ii=ii+1
2423 : 8334900 : gpq(1)=dble(ig1)+qphon(1)
2424 : 8334900 : gpq(2)=dble(ig2)+qphon(2)
2425 : 8334900 : gpq(3)=dble(ig3)+qphon(3)
2426 : 8334900 : gdot12=gmet(2,1)*gpq(1)*gpq(2)
2427 : 8334900 : gdot13=gmet(3,1)*gpq(1)*gpq(3)
2428 : 8334900 : gdot23=gmet(3,2)*gpq(2)*gpq(3)
2429 : 8334900 : dot1=gmet(1,1)*gpq(1)**2+gdot12+gdot13
2430 : 8334900 : dot2=gmet(2,2)*gpq(2)**2+gdot12+gdot23
2431 : 8334900 : dot3=gmet(3,3)*gpq(3)**2+gdot13+gdot23
2432 : 8334900 : gsq=dot1+dot2+dot3
2433 : 8334900 : facg0= zero
2434 : 8334900 : computeit= .true.
2435 : : ! Skip q=0:
2436 [ + + ]: 8334900 : if (gsq<1.0d-20) then
2437 : 690 : computeit= .false.
2438 [ - + ]: 690 : if (sumg0==1) then
2439 : : write(message,'(5a)')&
2440 : 0 : & 'The phonon wavelength should not be zero : ',ch10,&
2441 : 0 : & 'there are non-analytical terms that the code cannot handle.',ch10,&
2442 : 0 : & 'Action : subtract this wavelength from the input.'
2443 : 0 : ABI_ERROR(message)
2444 : : end if
2445 : : else
2446 [ + - - - : 8334210 : if (icutcoul==55.and.(ig1==0 .and. ig2==0 .and. ig3==0).and. sumg0==0) then
- - ]
2447 : : facg0= one
2448 : : end if
2449 : : ! Endif g/=0 :
2450 : : end if
2451 : :
2452 : 396900 : if (computeit) then
2453 : 8334210 : arg=fac*gsq
2454 : : ! Larger arg gives 0 contribution:
2455 [ + + ]: 8334210 : if (arg <= 80._dp) then
2456 : :
2457 : : ! Apply cutoff
2458 : : if ((abs(ig1).lt.ngfft(1)/2).and.&
2459 [ + + + + : 962086 : & (abs(ig2).lt.ngfft(2)/2).and.&
+ + ]
2460 : : & (abs(ig3).lt.ngfft(3)/2)) then
2461 : : ! Use inv_ig to map back to ing indices
2462 : 702357 : ig23=ngfft(1)*(inv_ig(2,ig2)-1 + ngfft(2)*(inv_ig(3,ig3)-1))
2463 : 702357 : ii=inv_ig(1,ig1)+ig23
2464 : 702357 : term=exp(-arg-facg0)/gsq * gcutoff(ii)
2465 [ + - ]: 259729 : else if (icutcoul.ne.3) then
2466 : : term=zero
2467 : : else
2468 : 259729 : term=exp(-arg)/gsq
2469 : : end if
2470 : :
2471 [ + + ]: 3179405 : do ia0=1,my_natom
2472 [ + + ]: 2217319 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2473 : 2217319 : arga=two_pi*(gpq(1)*xred(1,ia)+gpq(2)*xred(2,ia)+gpq(3)*xred(3,ia))
2474 [ + + ]: 9399142 : do ib=1,ia
2475 : 6219737 : argb=two_pi*(gpq(1)*xred(1,ib)+gpq(2)*xred(2,ib)+gpq(3)*xred(3,ib))
2476 : 6219737 : arg=arga-argb
2477 : 6219737 : c1r=cos(arg)*term
2478 : 6219737 : c1i=sin(arg)*term
2479 : :
2480 [ + + ]: 27096267 : do mu=1,3
2481 [ + + ]: 62197370 : do nu=1,mu
2482 : 37318422 : dyew(re,mu,ia,nu,ib)=dyew(re,mu,ia,nu,ib)+gpq(mu)*gpq(nu)*c1r
2483 : 55977633 : dyew(im,mu,ia,nu,ib)=dyew(im,mu,ia,nu,ib)+gpq(mu)*gpq(nu)*c1i
2484 : : end do
2485 : : end do
2486 : :
2487 : : end do
2488 : : end do
2489 : : end if
2490 : : ! Endif computeit:
2491 : : end if
2492 : : ! End triple loop over G s:
2493 : : end do
2494 : : end do
2495 : : end do
2496 : :
2497 [ - + ]: 900 : ABI_FREE(gcutoff)
2498 [ - + ]: 900 : ABI_FREE(inv_ig)
2499 : :
2500 : : !End G summation by accounting for some common factors.
2501 : : !(for the charges:see end of routine)
2502 : 900 : norm1=4.0_dp*pi/ucvol
2503 [ + + ]: 2654 : do ia0=1,my_natom
2504 [ + + ]: 1754 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2505 [ + + ]: 6060 : do ib=1,ia
2506 [ + + ]: 15378 : do mu=1,3
2507 [ + + ]: 34060 : do nu=1,mu
2508 [ + + ]: 71526 : dyew(:,mu,ia,nu,ib)=dyew(:,mu,ia,nu,ib)*norm1
2509 : : end do
2510 : : end do
2511 : : end do
2512 : : end do
2513 : :
2514 : : !Do sums over real space:
2515 : 900 : reta=sqrt(eta)
2516 : 900 : reta3m=-eta*reta
2517 : 900 : fac=4._dp/3.0_dp/sqrt(pi)
2518 [ + + ]: 12600 : do ir3=-nr,nr
2519 [ + + ]: 164700 : do ir2=-nr,nr
2520 [ + + ]: 2141100 : do ir1=-nr,nr
2521 : 1977300 : arg=-two_pi*(qphon(1)*ir1+qphon(2)*ir2+qphon(3)*ir3)
2522 : 1977300 : c1r=cos(arg)*reta3m
2523 : 1977300 : c1i=sin(arg)*reta3m
2524 [ + + ]: 5982938 : do ia0=1,my_natom
2525 [ + + ]: 3853538 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2526 [ + + ]: 13313820 : do ib=1,ia
2527 : 7482982 : r1=dble(ir1)+xred(1,ia)-xred(1,ib)
2528 : 7482982 : r2=dble(ir2)+xred(2,ia)-xred(2,ib)
2529 : 7482982 : r3=dble(ir3)+xred(3,ia)-xred(3,ib)
2530 : 7482982 : rdot12=rmet(2,1)*r1*r2
2531 : 7482982 : rdot13=rmet(3,1)*r1*r3
2532 : 7482982 : rdot23=rmet(3,2)*r2*r3
2533 : 7482982 : dotr1=rmet(1,1)*r1**2+rdot12+rdot13
2534 : 7482982 : dotr2=rmet(2,2)*r2**2+rdot12+rdot23
2535 : 7482982 : dotr3=rmet(3,3)*r3**2+rdot13+rdot23
2536 : 7482982 : rsq=dotr1+dotr2+dotr3
2537 : 7482982 : rmagn=sqrt(rsq)
2538 : : ! Avoid zero denominators in term :
2539 [ + + ]: 11336520 : if (rmagn>=1.0d-12) then
2540 : 7481228 : arg=reta*rmagn
2541 : 7481228 : term=zero
2542 [ + + ]: 7481228 : if (arg<8.0_dp) then
2543 : : ! Note: erfc(8) is about 1.1e-29,
2544 : : ! so don t bother with larger arg.
2545 : : ! Also: exp(-64) is about 1.6e-28,
2546 : : ! so don t bother with larger arg**2 in exp.
2547 : 883974 : derfc_arg = abi_derfc(arg)
2548 : 883974 : term=derfc_arg/arg**3
2549 : 883974 : term1=2.0_dp/sqrt(pi)*exp(-arg**2)/arg**2
2550 : 883974 : term2=-(term+term1)
2551 : 883974 : term3=(3*term+term1*(3.0_dp+2.0_dp*arg**2))/rsq
2552 : 883974 : rq(1)=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
2553 : 883974 : rq(2)=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
2554 : 883974 : rq(3)=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
2555 [ + + ]: 3535896 : do mu=1,3
2556 [ + + ]: 8839740 : do nu=1,mu
2557 : : dyew(re,mu,ia,nu,ib)=dyew(re,mu,ia,nu,ib)+&
2558 : 5303844 : & c1r*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
2559 : : dyew(im,mu,ia,nu,ib)=dyew(im,mu,ia,nu,ib)+&
2560 : 7955766 : & c1i*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
2561 : : end do
2562 : : end do
2563 : : end if
2564 : : else
2565 [ - + ]: 1754 : if (ia/=ib)then
2566 : : write(message,'(a,a,a,a,a,i5,a,i5,a)')&
2567 : 0 : & 'The distance between two atoms vanishes.',ch10,&
2568 : 0 : & 'This is not allowed.',ch10,&
2569 : 0 : & 'Action: check the input for the atoms number',ia,' and',ib,'.'
2570 : 0 : ABI_ERROR(message)
2571 : : else
2572 [ + + ]: 7016 : do mu=1,3
2573 [ + + ]: 17540 : do nu=1,mu
2574 : : dyew(re,mu,ia,nu,ib)=dyew(re,mu,ia,nu,ib)+&
2575 : 15786 : & fac*reta3m*rmet(mu,nu)
2576 : : end do
2577 : : end do
2578 : : end if
2579 : : end if
2580 : :
2581 : : end do ! End loop over ib:
2582 : : end do ! End loop over ia:
2583 : : end do ! End triple loop over real space points:
2584 : : end do
2585 : : end do
2586 : :
2587 : : !Take account of the charges
2588 : : !write(std_out,*)' '
2589 [ + + ]: 2654 : do ia0=1,my_natom
2590 [ + + ]: 1754 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2591 [ + + ]: 6060 : do ib=1,ia
2592 [ + + ]: 15378 : do mu=1,3
2593 [ + + ]: 34060 : do nu=1,mu
2594 [ + + ]: 71526 : do ii=1,2
2595 : : ! write(std_out,*)dyew(ii,mu,ia,nu,ib)
2596 : : dyew(ii,mu,ia,nu,ib)=dyew(ii,mu,ia,nu,ib)*&
2597 : 61308 : & zion(typat(ia))*zion(typat(ib))
2598 : : end do
2599 : : end do
2600 : : end do
2601 : : end do
2602 : : end do
2603 : :
2604 : : !Symmetrize with respect to the directions
2605 [ + + ]: 2654 : do ia0=1,my_natom
2606 [ + + ]: 1754 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2607 [ + + ]: 6060 : do ib=1,ia
2608 [ + + ]: 15378 : do mu=1,3
2609 [ + + ]: 34060 : do nu=1,mu
2610 : 20436 : dyew(re,nu,ia,mu,ib)=dyew(re,mu,ia,nu,ib)
2611 : 30654 : dyew(im,nu,ia,mu,ib)=dyew(im,mu,ia,nu,ib)
2612 : : end do
2613 : : end do
2614 : : end do
2615 : : end do
2616 : :
2617 : : !In case of parallelism over atoms: communicate
2618 [ + + ]: 900 : if (paral_atom) then
2619 : 44 : call timab(48,1,tsec)
2620 : 44 : call xmpi_sum(dyew,my_comm_atom,ierr)
2621 : 44 : call timab(48,2,tsec)
2622 : : end if
2623 : :
2624 : : !Fill the upper part of the matrix, with the hermitian conjugate
2625 [ + + ]: 2776 : do ia=1,natom
2626 [ + + ]: 6586 : do ib=1,ia
2627 [ + + ]: 17116 : do nu=1,3
2628 [ + + ]: 49530 : do mu=1,3
2629 : 34290 : dyew(re,mu,ib,nu,ia)=dyew(re,mu,ia,nu,ib)
2630 : 45720 : dyew(im,mu,ib,nu,ia)=-dyew(im,mu,ia,nu,ib)
2631 : : end do
2632 : : end do
2633 : : end do
2634 : : end do
2635 : :
2636 : : !Destroy atom table used for parallelism
2637 : 900 : call free_my_atmtab(my_atmtab,my_atmtab_allocated)
2638 : :
2639 [ + - ]: 900 : end subroutine dfpt_ewald
2640 : : !!***
2641 : :
2642 : : !!****f* ABINIT/dfpt_ewalddq
2643 : : !!
2644 : : !! NAME
2645 : : !! dfpt_ewalddq
2646 : : !!
2647 : : !! FUNCTION
2648 : : !! Compute the first q-gradient of Ewald contribution to the dynamical matrix, at a given q wavevector.
2649 : : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
2650 : : !!
2651 : : !! COPYRIGHT
2652 : : !! Copyright (C) 1998-2026 ABINIT group (MR, MS)
2653 : : !! This file is distributed under the terms of the
2654 : : !! GNU General Public License, see ~abinit/COPYING
2655 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2656 : : !!
2657 : : !! INPUTS
2658 : : !! gmet(3,3)=metric tensor in reciprocal space (length units **-2)
2659 : : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
2660 : : !! comm_atom=--optional-- MPI communicator over atoms
2661 : : !! my_natom=number of atoms treated by current processor
2662 : : !! natom=number of atoms in unit cell
2663 : : !! qphon(3)=phonon wavevector (same system of coordinates as the
2664 : : !! reciprocal lattice vectors)
2665 : : !! rmet(3,3)=metric tensor in real space (length units squared)
2666 : : !! sumg0: if=1, the sum in reciprocal space must include g=0,
2667 : : !! if=0, this contribution must be skipped (q=0 singularity)
2668 : : !! typat(natom)=integer label of each type of atom (1,2,...)
2669 : : !! ucvol=unit cell volume in (whatever length scale units)**3
2670 : : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
2671 : : !! zion(ntypat)=charge on each type of atom (real number)
2672 : : !!
2673 : : !! OUTPUT
2674 : : !! dyewdq(2,3,natom,3,natom,3)= First q-gradient of Ewald part of the dynamical matrix,
2675 : : !! second energy derivative wrt xred(3,natom), Hartrees.
2676 : : !!
2677 : : !! SOURCE
2678 : :
2679 : 6 : subroutine dfpt_ewalddq(dyewdq,gmet,my_natom,natom,qphon,rmet,sumg0,typat,ucvol,xred,zion, &
2680 [ - + - - : 3 : & mpi_atmtab,comm_atom ) ! optional arguments (parallelism))
- - ]
2681 : :
2682 : : !Arguments -------------------------------
2683 : : !scalars
2684 : : integer,intent(in) :: my_natom,natom,sumg0
2685 : : real(dp),intent(in) :: ucvol
2686 : : !arrays
2687 : : integer,intent(in) :: typat(natom)
2688 : : integer,optional,intent(in) :: comm_atom
2689 : : integer,optional,target,intent(in) :: mpi_atmtab(:)
2690 : : real(dp),intent(in) :: gmet(3,3),qphon(3),rmet(3,3),xred(3,natom),zion(*)
2691 : : real(dp),intent(out) :: dyewdq(2,3,natom,3,natom,3)
2692 : :
2693 : : !Local variables -------------------------
2694 : : !nr, ng affect convergence of sums (nr=3,ng=5 is not good enough):
2695 : : !scalars
2696 : : integer,parameter :: im=2,nng=10,nnr=6,re=1
2697 : : integer ::ia,ia0,ib,ierr,ig1,ig2,ig3,ii,iq,ir1,ir2,ir3,mu,my_comm_atom,newg,newr,ng,nr,nu
2698 : : logical :: my_atmtab_allocated,paral_atom
2699 : : real(dp) :: arg,arga,argb,c1i,c1r,delag,delbg,derfc_arg
2700 : : real(dp) :: direct,dot1,dot2,dot3,dotr1,dotr2,dotr3
2701 : : real(dp) :: eta,fac,fac2,gdot12,gdot13,gdot23,gsq,gpqdq,gterms,norm1
2702 : : real(dp) :: r1,r2,r3,rdot12,rdot13,rdot23,recip,reta
2703 : : real(dp) :: reta3m,rmagn,rsq,term,term1,term2,term3
2704 : : character(len=500) :: message
2705 : : !arrays
2706 : : real(dp) :: tsec(2)
2707 : 3 : integer,pointer :: my_atmtab(:)
2708 : : real(dp) :: dakk(3),gpq(3),rq(3)
2709 : :
2710 : : ! *************************************************************************
2711 : :
2712 : : !Set up parallelism over atoms
2713 [ + - ]: 3 : paral_atom=(present(comm_atom).and.(my_natom/=natom))
2714 [ - + ]: 3 : nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
2715 [ + - ]: 3 : my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
2716 : 3 : call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
2717 : :
2718 : : !Compute eta for approximately optimized summations:
2719 : : direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
2720 : 3 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
2721 : : recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
2722 : 3 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
2723 : 3 : eta=pi*(dble(nng)/dble(nnr))*sqrt(1.69_dp*recip/direct)
2724 : :
2725 : : !Test Ewald s summation
2726 : : !eta=1.2_dp*eta
2727 : :
2728 : : !Sum over G space, done shell after shell until all
2729 : : !contributions are too small.
2730 : 3 : fac=pi**2.d0/eta
2731 : 3 : fac2=2.d0*fac
2732 [ + + + + : 1164 : dyewdq(:,:,:,:,:,:)=zero
+ + + + +
+ + + ]
2733 : : ng=0
2734 : : do
2735 : 18 : ng=ng+1
2736 : 18 : newg=0
2737 : :
2738 [ + + ]: 162 : do ig3=-ng,ng
2739 [ + + ]: 1524 : do ig2=-ng,ng
2740 [ + + ]: 15762 : do ig1=-ng,ng
2741 : :
2742 : : ! Exclude shells previously summed over
2743 : : if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng&
2744 [ + + + + : 15618 : & .or. ng==1 ) then
+ + + + ]
2745 : :
2746 : 6591 : gpq(1)=dble(ig1)+qphon(1)
2747 : 6591 : gpq(2)=dble(ig2)+qphon(2)
2748 : 6591 : gpq(3)=dble(ig3)+qphon(3)
2749 : 6591 : gdot12=gmet(2,1)*gpq(1)*gpq(2)
2750 : 6591 : gdot13=gmet(3,1)*gpq(1)*gpq(3)
2751 : 6591 : gdot23=gmet(3,2)*gpq(2)*gpq(3)
2752 : 6591 : dot1=gmet(1,1)*gpq(1)**2+gdot12+gdot13
2753 : 6591 : dot2=gmet(2,2)*gpq(2)**2+gdot12+gdot23
2754 : 6591 : dot3=gmet(3,3)*gpq(3)**2+gdot13+gdot23
2755 : 6591 : gsq=dot1+dot2+dot3
2756 : : ! Skip q=0:
2757 [ + + ]: 6591 : if (gsq<1.0d-20) then
2758 [ - + ]: 3 : if (sumg0==1) then
2759 : : write(message,'(3a)')&
2760 : 0 : & 'The G=0 term has no contributions at first order in q: ',ch10,&
2761 : 0 : & 'Action : sumg0=0 '
2762 : 0 : ABI_ERROR(message)
2763 : : end if
2764 : : else
2765 : 6588 : arg=fac*gsq
2766 : : ! Larger arg gives 0 contribution:
2767 [ + + ]: 6588 : if (arg <= 80._dp) then
2768 : : ! When any term contributes then include next shell
2769 : 1230 : newg=1
2770 : 1230 : term=exp(-arg)/gsq
2771 [ + + ]: 3690 : do ia0=1,my_natom
2772 [ - + ]: 2460 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2773 : 2460 : arga=two_pi*(gpq(1)*xred(1,ia)+gpq(2)*xred(2,ia)+gpq(3)*xred(3,ia))
2774 [ + + ]: 7380 : do ib=1,ia
2775 : 3690 : argb=two_pi*(gpq(1)*xred(1,ib)+gpq(2)*xred(2,ib)+gpq(3)*xred(3,ib))
2776 : 3690 : arg=arga-argb
2777 : 3690 : c1r=cos(arg)*term
2778 : 3690 : c1i=sin(arg)*term
2779 : :
2780 [ + + ]: 17220 : do iq=1,3
2781 : 11070 : gpqdq=gmet(iq,1)*gpq(1)+gmet(iq,2)*gpq(2)+gmet(iq,3)*gpq(3)
2782 [ + + ]: 47970 : do mu=1,3
2783 [ + + ]: 33210 : delag=zero; if(iq==mu) delag=one
2784 [ + + ]: 110700 : do nu=1,mu
2785 [ + + ]: 66420 : delbg=zero; if(iq==nu) delbg=one
2786 : 66420 : term1=delag*gpq(nu)+delbg*gpq(mu)
2787 : 66420 : term2=gpq(mu)*gpq(nu)*gpqdq
2788 : 66420 : term3=fac2*term2
2789 : 66420 : term2=two*term2/gsq
2790 : 66420 : gterms=term1-term2-term3
2791 : 66420 : dyewdq(re,mu,ia,nu,ib,iq)=dyewdq(re,mu,ia,nu,ib,iq)+gterms*c1r
2792 : 99630 : dyewdq(im,mu,ia,nu,ib,iq)=dyewdq(im,mu,ia,nu,ib,iq)+gterms*c1i
2793 : : end do
2794 : : end do
2795 : : end do
2796 : :
2797 : : end do
2798 : : end do
2799 : : end if
2800 : : ! Endif g/=0 :
2801 : : end if
2802 : : end if
2803 : : ! End triple loop over G s:
2804 : : end do
2805 : : end do
2806 : : end do
2807 : :
2808 : : ! Check if new shell must be calculated
2809 [ + + ]: 18 : if (newg==0) exit
2810 : : end do ! End the loop on ng (new shells). Note that there is one exit from this loop.
2811 : :
2812 : : !End G summation by accounting for some common factors.
2813 : : !(for the charges:see end of routine)
2814 : 3 : norm1=4.0_dp*pi/ucvol
2815 [ + + ]: 9 : do ia0=1,my_natom
2816 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2817 [ + + ]: 18 : do ib=1,ia
2818 [ + + ]: 42 : do iq=1,3
2819 [ + + ]: 117 : do mu=1,3
2820 [ + + ]: 270 : do nu=1,mu
2821 [ + + ]: 567 : dyewdq(:,mu,ia,nu,ib,iq)=dyewdq(:,mu,ia,nu,ib,iq)*norm1
2822 : : end do
2823 : : end do
2824 : : end do
2825 : : end do
2826 : : end do
2827 : :
2828 : : !Do sums over real space:
2829 : 3 : reta=sqrt(eta)
2830 : 3 : reta3m=-eta*reta
2831 : 3 : fac=4._dp/3.0_dp/sqrt(pi)
2832 : 3 : nr=0
2833 : : do
2834 : 18 : nr=nr+1
2835 : 18 : newr=0
2836 : :
2837 [ + + ]: 162 : do ir3=-nr,nr
2838 [ + + ]: 1524 : do ir2=-nr,nr
2839 [ + + ]: 15762 : do ir1=-nr,nr
2840 [ + + + + : 15618 : if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
+ + + + ]
2841 : :
2842 : 6591 : arg=two_pi*(qphon(1)*ir1+qphon(2)*ir2+qphon(3)*ir3)
2843 : 6591 : c1r=cos(arg)*reta3m
2844 : 6591 : c1i=sin(arg)*reta3m
2845 [ + + ]: 19773 : do ia0=1,my_natom
2846 [ - + ]: 13182 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2847 [ + + ]: 47211 : do ib=1,ia
2848 : 19773 : r1=dble(ir1)+xred(1,ib)-xred(1,ia)
2849 : 19773 : r2=dble(ir2)+xred(2,ib)-xred(2,ia)
2850 : 19773 : r3=dble(ir3)+xred(3,ib)-xred(3,ia)
2851 [ + + ]: 79092 : dakk(:)=two_pi*(/r1,r2,r3/)
2852 : 19773 : rdot12=rmet(2,1)*r1*r2
2853 : 19773 : rdot13=rmet(3,1)*r1*r3
2854 : 19773 : rdot23=rmet(3,2)*r2*r3
2855 : 19773 : dotr1=rmet(1,1)*r1**2+rdot12+rdot13
2856 : 19773 : dotr2=rmet(2,2)*r2**2+rdot12+rdot23
2857 : 19773 : dotr3=rmet(3,3)*r3**2+rdot13+rdot23
2858 : 19773 : rsq=dotr1+dotr2+dotr3
2859 : 19773 : rmagn=sqrt(rsq)
2860 : : ! Avoid zero denominators in term :
2861 [ + + ]: 32955 : if (rmagn>=1.0d-12) then
2862 : 19767 : arg=reta*rmagn
2863 : 19767 : term=zero
2864 [ + + ]: 19767 : if (arg<8.0_dp) then
2865 : : ! Note: erfc(8) is about 1.1e-29,
2866 : : ! so don t bother with larger arg.
2867 : : ! Also: exp(-64) is about 1.6e-28,
2868 : : ! so don t bother with larger arg**2 in exp.
2869 : 4200 : newr=1
2870 : 4200 : derfc_arg = abi_derfc(arg)
2871 : 4200 : term=derfc_arg/arg**3
2872 : 4200 : term1=2.0_dp/sqrt(pi)*exp(-arg**2)/arg**2
2873 : 4200 : term2=-(term+term1)
2874 : 4200 : term3=(3*term+term1*(3.0_dp+2.0_dp*arg**2))/rsq
2875 : 4200 : rq(1)=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
2876 : 4200 : rq(2)=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
2877 : 4200 : rq(3)=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
2878 [ + + ]: 16800 : do iq=1,3
2879 [ + + ]: 54600 : do mu=1,3
2880 : : ! do nu=1,3
2881 [ + + ]: 126000 : do nu=1,mu
2882 : : dyewdq(re,mu,ia,nu,ib,iq)=dyewdq(re,mu,ia,nu,ib,iq)-&
2883 : 75600 : & c1i*dakk(iq)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
2884 : : dyewdq(im,mu,ia,nu,ib,iq)=dyewdq(im,mu,ia,nu,ib,iq)+&
2885 : 113400 : & c1r*dakk(iq)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
2886 : : end do
2887 : : end do
2888 : : end do
2889 : : end if
2890 : : else
2891 [ + - ]: 6 : if (ia/=ib)then
2892 : : write(message,'(a,a,a,a,a,i5,a,i5,a)')&
2893 : 0 : & 'The distance between two atoms vanishes.',ch10,&
2894 : 0 : & 'This is not allowed.',ch10,&
2895 : 0 : & 'Action: check the input for the atoms number',ia,' and',ib,'.'
2896 : 0 : ABI_ERROR(message)
2897 : : end if
2898 : : end if
2899 : :
2900 : : end do ! End loop over ib:
2901 : : end do ! End loop over ia:
2902 : : end if
2903 : : end do ! End triple loop over real space points:
2904 : : end do
2905 : : end do
2906 : :
2907 : : ! Check if new shell must be calculated
2908 [ + + ]: 18 : if(newr==0) exit
2909 : : end do ! End loop on nr (new shells). Note that there is an exit within the loop
2910 : :
2911 : : !Take account of the charges
2912 : : !write(std_out,*)' '
2913 [ + + ]: 9 : do ia0=1,my_natom
2914 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2915 [ + + ]: 18 : do ib=1,ia
2916 [ + + ]: 42 : do iq=1,3
2917 [ + + ]: 117 : do mu=1,3
2918 [ + + ]: 270 : do nu=1,mu
2919 [ + + ]: 567 : do ii=1,2
2920 : : dyewdq(ii,mu,ia,nu,ib,iq)=dyewdq(ii,mu,ia,nu,ib,iq)*&
2921 : 486 : & zion(typat(ia))*zion(typat(ib))
2922 : : end do
2923 : : end do
2924 : : end do
2925 : : end do
2926 : : end do
2927 : : end do
2928 : :
2929 : : !Symmetrize with respect to the directions
2930 [ + + ]: 9 : do ia0=1,my_natom
2931 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
2932 [ + + ]: 18 : do ib=1,ia
2933 [ + + ]: 42 : do iq=1,3
2934 [ + + ]: 117 : do mu=1,3
2935 [ + + ]: 270 : do nu=1,mu
2936 : 162 : dyewdq(re,nu,ia,mu,ib,iq)=dyewdq(re,mu,ia,nu,ib,iq)
2937 : 243 : dyewdq(im,nu,ia,mu,ib,iq)=dyewdq(im,mu,ia,nu,ib,iq)
2938 : : end do
2939 : : end do
2940 : : end do
2941 : : end do
2942 : : end do
2943 : :
2944 : : !In case of parallelism over atoms: communicate
2945 [ - + ]: 3 : if (paral_atom) then
2946 : 0 : call timab(48,1,tsec)
2947 : 0 : call xmpi_sum(dyewdq,my_comm_atom,ierr)
2948 : 0 : call timab(48,2,tsec)
2949 : : end if
2950 : :
2951 : : !Fill the upper part of the matrix, with the hermitian conjugate
2952 [ + + ]: 9 : do ia=1,natom
2953 [ + + ]: 18 : do ib=1,ia
2954 [ + + ]: 42 : do iq=1,3
2955 [ + + ]: 117 : do nu=1,3
2956 [ + + ]: 351 : do mu=1,3
2957 : 243 : dyewdq(re,mu,ib,nu,ia,iq)=dyewdq(re,mu,ia,nu,ib,iq)
2958 : 324 : dyewdq(im,mu,ib,nu,ia,iq)=-dyewdq(im,mu,ia,nu,ib,iq)
2959 : : end do
2960 : : end do
2961 : : end do
2962 : : end do
2963 : : end do
2964 : :
2965 : : !Destroy atom table used for parallelism
2966 : 3 : call free_my_atmtab(my_atmtab,my_atmtab_allocated)
2967 : :
2968 [ + - ]: 3 : end subroutine dfpt_ewalddq
2969 : : !!***
2970 : :
2971 : : !!****f* ABINIT/dfpt_ewalddqdq
2972 : : !!
2973 : : !! NAME
2974 : : !! dfpt_ewalddqdq
2975 : : !!
2976 : : !! FUNCTION
2977 : : !! Compute the second q-gradient of Ewald contribution to the dynamical matrix, at a given q wavevector,
2978 : : !! sumed over the second atomic sublattice.
2979 : : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
2980 : : !!
2981 : : !! COPYRIGHT
2982 : : !! Copyright (C) 1998-2026 ABINIT group (MR, MS)
2983 : : !! This file is distributed under the terms of the
2984 : : !! GNU General Public License, see ~abinit/COPYING
2985 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2986 : : !!
2987 : : !! INPUTS
2988 : : !! gmet(3,3)=metric tensor in reciprocal space (length units **-2)
2989 : : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
2990 : : !! comm_atom=--optional-- MPI communicator over atoms
2991 : : !! my_natom=number of atoms treated by current processor
2992 : : !! natom=number of atoms in unit cell
2993 : : !! qphon(3)=phonon wavevector (same system of coordinates as the
2994 : : !! reciprocal lattice vectors)
2995 : : !! rmet(3,3)=metric tensor in real space (length units squared)
2996 : : !! sumg0: if=1, the sum in reciprocal space must include g=0,
2997 : : !! if=0, this contribution must be skipped (q=0 singularity)
2998 : : !! typat(natom)=integer label of each type of atom (1,2,...)
2999 : : !! ucvol=unit cell volume in (whatever length scale units)**3
3000 : : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
3001 : : !! zion(ntypat)=charge on each type of atom (real number)
3002 : : !!
3003 : : !! OUTPUT
3004 : : !! dyewdqdq(2,3,natom,3,3,3)= First q-gradient of Ewald part of the dynamical matrix,
3005 : : !! sumed over second atomic sublattice.
3006 : : !!
3007 : : !! SOURCE
3008 : :
3009 : 6 : subroutine dfpt_ewalddqdq(dyewdqdq,gmet,my_natom,natom,qphon,rmet,sumg0,typat,ucvol,xred,zion, &
3010 [ - + - - : 3 : & mpi_atmtab,comm_atom ) ! optional arguments (parallelism))
- - ]
3011 : :
3012 : : !Arguments -------------------------------
3013 : : !scalars
3014 : : integer,intent(in) :: my_natom,natom,sumg0
3015 : : real(dp),intent(in) :: ucvol
3016 : : !arrays
3017 : : integer,intent(in) :: typat(natom)
3018 : : integer,optional,intent(in) :: comm_atom
3019 : : integer,optional,target,intent(in) :: mpi_atmtab(:)
3020 : : real(dp),intent(in) :: gmet(3,3),qphon(3),rmet(3,3),xred(3,natom),zion(*)
3021 : : real(dp),intent(out) :: dyewdqdq(2,3,natom,3,3,3)
3022 : :
3023 : : !Local variables -------------------------
3024 : : !nr, ng affect convergence of sums (nr=3,ng=5 is not good enough):
3025 : : !scalars
3026 : : integer,parameter :: im=2,nng=10,nnr=6,re=1
3027 : : integer :: ia,ia0,ib,ierr,ig1,ig2,ig3,ii,iq1,iq2,ir1,ir2,ir3,mu,my_comm_atom,newg,newr,ng,nr,nu
3028 : : logical :: my_atmtab_allocated,paral_atom
3029 : : real(dp) :: arg,arga,argb,c1i,c1r,delad,delag,delbd,delbg,derfc_arg
3030 : : real(dp) :: direct,dot1,dot2,dot3,dotr1,dotr2,dotr3
3031 : : real(dp) :: eta,fac,fac2,fac8,fac2sqr,gdot12,gdot13,gdot23,gsq,gsqsq,gpqdq1,gpqdq2,gterms,g0term,norm1
3032 : : real(dp) :: r1,r2,r3,rdot12,rdot13,rdot23,recip,reta
3033 : : real(dp) :: reta3m,rmagn,rsq,term,term1,term2,term3
3034 : : character(len=500) :: message
3035 : : !arrays
3036 : 3 : integer,pointer :: my_atmtab(:)
3037 : : real(dp) :: dakk(3),gpq(3),rq(3)
3038 : : real(dp) :: tsec(2)
3039 : 3 : real(dp),allocatable :: work(:,:,:,:,:,:,:)
3040 : :
3041 : : ! *************************************************************************
3042 : :
3043 : : !Set up parallelism over atoms
3044 [ + - ]: 3 : paral_atom=(present(comm_atom).and.(my_natom/=natom))
3045 [ - + ]: 3 : nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
3046 [ + - ]: 3 : my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
3047 : 3 : call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
3048 : :
3049 : : !Compute eta for approximately optimized summations:
3050 : : direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
3051 : 3 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
3052 : : recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
3053 : 3 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
3054 : 3 : eta=pi*(dble(nng)/dble(nnr))*sqrt(1.69_dp*recip/direct)
3055 : : ! eta=1.0_dp
3056 : :
3057 : : !Test Ewald s summation
3058 : : !eta=1.2_dp*eta
3059 : :
3060 : : !Sum terms over g space:
3061 : 3 : fac=pi**2.0_dp/eta
3062 : 3 : fac2=2.0_dp*fac
3063 : 3 : fac8=4.0_dp*fac2
3064 : 3 : fac2sqr=fac2*fac2
3065 [ - + + - : 21 : ABI_MALLOC(work,(2,3,natom,3,natom,3,3))
+ - - + +
- + - + -
+ - + - -
+ - + ]
3066 [ + + + + : 3495 : work(:,:,:,:,:,:,:)=zero
+ + + + +
+ + + +
+ ]
3067 : : ng=0
3068 : : do
3069 : 18 : ng=ng+1
3070 : 18 : newg=0
3071 : :
3072 [ + + ]: 162 : do ig3=-ng,ng
3073 [ + + ]: 1524 : do ig2=-ng,ng
3074 [ + + ]: 15762 : do ig1=-ng,ng
3075 : :
3076 : : ! Exclude shells previously summed over
3077 : : if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng&
3078 [ + + + + : 15618 : & .or. ng==1 ) then
+ + + + ]
3079 : :
3080 : 6591 : gpq(1)=dble(ig1)+qphon(1)
3081 : 6591 : gpq(2)=dble(ig2)+qphon(2)
3082 : 6591 : gpq(3)=dble(ig3)+qphon(3)
3083 : 6591 : gdot12=gmet(2,1)*gpq(1)*gpq(2)
3084 : 6591 : gdot13=gmet(3,1)*gpq(1)*gpq(3)
3085 : 6591 : gdot23=gmet(3,2)*gpq(2)*gpq(3)
3086 : 6591 : dot1=gmet(1,1)*gpq(1)**2+gdot12+gdot13
3087 : 6591 : dot2=gmet(2,2)*gpq(2)**2+gdot12+gdot23
3088 : 6591 : dot3=gmet(3,3)*gpq(3)**2+gdot13+gdot23
3089 : 6591 : gsq=dot1+dot2+dot3
3090 : 6591 : gsqsq=gsq*gsq
3091 : : ! Skip q=0:
3092 [ + + ]: 6591 : if (gsq<1.0d-20) then
3093 : :
3094 : : ! At second order in q there is a nonvanishing G=0 contribution in the longwave limit
3095 [ + - ]: 3 : if (sumg0==1) then
3096 [ + + ]: 9 : do ia0=1,my_natom
3097 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
3098 [ + + ]: 18 : do ib=1,ia
3099 [ + + ]: 42 : do iq2=1,3
3100 [ + + ]: 117 : do iq1=1,3
3101 [ + + ]: 351 : do mu=1,3
3102 [ + + ]: 243 : delag=zero; if(iq1==mu) delag=one
3103 [ + + ]: 243 : delad=zero; if(iq2==mu) delad=one
3104 [ + + ]: 810 : do nu=1,mu
3105 [ + + ]: 486 : delbg=zero; if(iq1==nu) delbg=one
3106 [ + + ]: 486 : delbd=zero; if(iq2==nu) delbd=one
3107 : 486 : g0term=-fac*(delad*delbg+delbd*delag)
3108 : 729 : work(re,mu,ia,nu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)+g0term
3109 : : end do
3110 : : end do
3111 : : end do
3112 : : end do
3113 : : end do
3114 : : end do
3115 : : end if
3116 : :
3117 : : else
3118 : 6588 : arg=fac*gsq
3119 : : ! Larger arg gives 0 contribution:
3120 [ + + ]: 6588 : if (arg <= 80._dp) then
3121 : 1230 : newg=1
3122 : 1230 : term=exp(-arg)/gsq
3123 [ + + ]: 3690 : do ia0=1,my_natom
3124 [ - + ]: 2460 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
3125 : 2460 : arga=two_pi*(gpq(1)*xred(1,ia)+gpq(2)*xred(2,ia)+gpq(3)*xred(3,ia))
3126 [ + + ]: 7380 : do ib=1,ia
3127 : 3690 : argb=two_pi*(gpq(1)*xred(1,ib)+gpq(2)*xred(2,ib)+gpq(3)*xred(3,ib))
3128 : 3690 : arg=arga-argb
3129 : 3690 : c1r=cos(arg)*term
3130 : 3690 : c1i=sin(arg)*term
3131 : :
3132 [ + + ]: 17220 : do iq2=1,3
3133 : 11070 : gpqdq2=gmet(iq2,1)*gpq(1)+gmet(iq2,2)*gpq(2)+gmet(iq2,3)*gpq(3)
3134 [ + + ]: 47970 : do iq1=1,3
3135 : 33210 : gpqdq1=gmet(iq1,1)*gpq(1)+gmet(iq1,2)*gpq(2)+gmet(iq1,3)*gpq(3)
3136 [ + + ]: 143910 : do mu=1,3
3137 [ + + ]: 99630 : delag=zero; if(iq1==mu) delag=one
3138 [ + + ]: 99630 : delad=zero; if(iq2==mu) delad=one
3139 [ + + ]: 332100 : do nu=1,mu
3140 [ + + ]: 199260 : delbg=zero; if(iq1==nu) delbg=one
3141 [ + + ]: 199260 : delbd=zero; if(iq2==nu) delbd=one
3142 : :
3143 : 199260 : term1=gpqdq2*(delag*gpq(nu)+delbg*gpq(mu))
3144 : 199260 : term1=term1+gpqdq1*(delad*gpq(nu)+delbd*gpq(mu))
3145 : 199260 : term1=term1+gpq(mu)*gpq(nu)*gmet(iq1,iq2)
3146 : 199260 : term1=-term1*(fac2+2.0_dp/gsq)
3147 : :
3148 : 199260 : term2=delag*delbd + delbg*delad
3149 : :
3150 : 199260 : term3=gpqdq1*gpqdq2*gpq(mu)*gpq(nu)
3151 : 199260 : term3=term3*(fac8/gsq + fac2sqr + 8.0_dp/gsqsq)
3152 : :
3153 : 199260 : gterms=term1+term2+term3
3154 : 199260 : work(re,mu,ia,nu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)+gterms*c1r
3155 : 298890 : work(im,mu,ia,nu,ib,iq1,iq2)=work(im,mu,ia,nu,ib,iq1,iq2)+gterms*c1i
3156 : : end do
3157 : : end do
3158 : : end do
3159 : : end do
3160 : : end do
3161 : : end do
3162 : : end if
3163 : : ! Endif g/=0 :
3164 : : end if
3165 : : end if
3166 : : ! End triple loop over G s:
3167 : : end do
3168 : : end do
3169 : : end do
3170 : :
3171 : : ! Check if new shell must be calculated
3172 [ + + ]: 18 : if (newg==0) exit
3173 : : end do ! End the loop on ng (new shells). Note that there is one exit from this loop.
3174 : :
3175 : : !End G summation by accounting for some common factors.
3176 : : !(for the charges:see end of routine)
3177 : 3 : norm1=4.0_dp*pi/ucvol
3178 [ + + ]: 9 : do ia0=1,my_natom
3179 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
3180 [ + + ]: 18 : do ib=1,ia
3181 [ + + ]: 42 : do iq2=1,3
3182 [ + + ]: 117 : do iq1=1,3
3183 [ + + ]: 351 : do mu=1,3
3184 [ + + ]: 810 : do nu=1,mu
3185 [ + + ]: 1701 : work(:,mu,ia,nu,ib,iq1,iq2)=work(:,mu,ia,nu,ib,iq1,iq2)*norm1
3186 : : end do
3187 : : end do
3188 : : end do
3189 : : end do
3190 : : end do
3191 : : end do
3192 : :
3193 : : !Do sums over real space:
3194 : 3 : reta=sqrt(eta)
3195 : 3 : reta3m=eta*reta
3196 : 3 : fac=4._dp/3.0_dp/sqrt(pi)
3197 : 3 : nr=0
3198 : : do
3199 : 18 : nr=nr+1
3200 : 18 : newr=0
3201 : :
3202 [ + + ]: 162 : do ir3=-nr,nr
3203 [ + + ]: 1524 : do ir2=-nr,nr
3204 [ + + ]: 15762 : do ir1=-nr,nr
3205 [ + + + + : 15618 : if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
+ + + + ]
3206 : :
3207 : 6591 : arg=two_pi*(qphon(1)*ir1+qphon(2)*ir2+qphon(3)*ir3)
3208 : 6591 : c1r=cos(arg)*reta3m
3209 : 6591 : c1i=sin(arg)*reta3m
3210 [ + + ]: 19773 : do ia0=1,my_natom
3211 [ - + ]: 13182 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
3212 [ + + ]: 47211 : do ib=1,ia
3213 : 19773 : r1=dble(ir1)+xred(1,ib)-xred(1,ia)
3214 : 19773 : r2=dble(ir2)+xred(2,ib)-xred(2,ia)
3215 : 19773 : r3=dble(ir3)+xred(3,ib)-xred(3,ia)
3216 [ + + ]: 79092 : dakk(:)=two_pi*(/r1,r2,r3/)
3217 : 19773 : rdot12=rmet(2,1)*r1*r2
3218 : 19773 : rdot13=rmet(3,1)*r1*r3
3219 : 19773 : rdot23=rmet(3,2)*r2*r3
3220 : 19773 : dotr1=rmet(1,1)*r1**2+rdot12+rdot13
3221 : 19773 : dotr2=rmet(2,2)*r2**2+rdot12+rdot23
3222 : 19773 : dotr3=rmet(3,3)*r3**2+rdot13+rdot23
3223 : 19773 : rsq=dotr1+dotr2+dotr3
3224 : 19773 : rmagn=sqrt(rsq)
3225 : : ! Avoid zero denominators in term :
3226 [ + + ]: 32955 : if (rmagn>=1.0d-12) then
3227 : 19767 : arg=reta*rmagn
3228 : 19767 : term=zero
3229 [ + + ]: 19767 : if (arg<8.0_dp) then
3230 : : ! Note: erfc(8) is about 1.1e-29,
3231 : : ! so don t bother with larger arg.
3232 : : ! Also: exp(-64) is about 1.6e-28,
3233 : : ! so don t bother with larger arg**2 in exp.
3234 : 4200 : newr=1
3235 : 4200 : derfc_arg = abi_derfc(arg)
3236 : 4200 : term=derfc_arg/arg**3
3237 : 4200 : term1=2.0_dp/sqrt(pi)*exp(-arg**2)/arg**2
3238 : 4200 : term2=-(term+term1)
3239 : 4200 : term3=(3*term+term1*(3.0_dp+2.0_dp*arg**2))/rsq
3240 : 4200 : rq(1)=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
3241 : 4200 : rq(2)=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
3242 : 4200 : rq(3)=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
3243 [ + + ]: 16800 : do iq2=1,3
3244 [ + + ]: 54600 : do iq1=1,3
3245 [ + + ]: 163800 : do mu=1,3
3246 : : ! do nu=1,3
3247 [ + + ]: 378000 : do nu=1,mu
3248 : : work(re,mu,ia,nu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)+&
3249 : 226800 : & c1r*dakk(iq1)*dakk(iq2)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
3250 : : work(im,mu,ia,nu,ib,iq1,iq2)=work(im,mu,ia,nu,ib,iq1,iq2)+&
3251 : 340200 : & c1i*dakk(iq1)*dakk(iq2)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
3252 : : end do
3253 : : end do
3254 : : end do
3255 : : end do
3256 : : end if
3257 : : else
3258 [ + - ]: 6 : if (ia/=ib)then
3259 : : write(message,'(a,a,a,a,a,i5,a,i5,a)')&
3260 : 0 : & 'The distance between two atoms vanishes.',ch10,&
3261 : 0 : & 'This is not allowed.',ch10,&
3262 : 0 : & 'Action: check the input for the atoms number',ia,' and',ib,'.'
3263 : 0 : ABI_ERROR(message)
3264 : : end if
3265 : : end if
3266 : :
3267 : : end do ! End loop over ib:
3268 : : end do ! End loop over ia:
3269 : : end if
3270 : : end do ! End triple loop over real space points:
3271 : : end do
3272 : : end do
3273 : :
3274 : : ! Check if new shell must be calculated
3275 [ + + ]: 18 : if(newr==0) exit
3276 : : end do ! End loop on nr (new shells). Note that there is an exit within the loop
3277 : :
3278 : : !Take account of the charges
3279 : : !write(std_out,*)' '
3280 [ + + ]: 9 : do ia0=1,my_natom
3281 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
3282 [ + + ]: 18 : do ib=1,ia
3283 [ + + ]: 42 : do iq2=1,3
3284 [ + + ]: 117 : do iq1=1,3
3285 [ + + ]: 351 : do mu=1,3
3286 [ + + ]: 810 : do nu=1,mu
3287 [ + + ]: 1701 : do ii=1,2
3288 : : work(ii,mu,ia,nu,ib,iq1,iq2)=work(ii,mu,ia,nu,ib,iq1,iq2)*&
3289 : 1458 : & zion(typat(ia))*zion(typat(ib))
3290 : : end do
3291 : : end do
3292 : : end do
3293 : : end do
3294 : : end do
3295 : : end do
3296 : : end do
3297 : :
3298 : : !Symmetrize with respect to the directions
3299 [ + + ]: 9 : do ia0=1,my_natom
3300 [ - + ]: 6 : ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
3301 [ + + ]: 18 : do ib=1,ia
3302 [ + + ]: 42 : do iq2=1,3
3303 [ + + ]: 117 : do iq1=1,3
3304 [ + + ]: 351 : do mu=1,3
3305 [ + + ]: 810 : do nu=1,mu
3306 : 486 : work(re,nu,ia,mu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)
3307 : 729 : work(im,nu,ia,mu,ib,iq1,iq2)=work(im,mu,ia,nu,ib,iq1,iq2)
3308 : : end do
3309 : : end do
3310 : : end do
3311 : : end do
3312 : : end do
3313 : : end do
3314 : :
3315 : : !In case of parallelism over atoms: communicate
3316 [ - + ]: 3 : if (paral_atom) then
3317 : 0 : call timab(48,1,tsec)
3318 : 0 : call xmpi_sum(work,my_comm_atom,ierr)
3319 : 0 : call timab(48,2,tsec)
3320 : : end if
3321 : :
3322 : : !Fill the upper part of the matrix, with the hermitian conjugate
3323 [ + + ]: 9 : do ia=1,natom
3324 [ + + ]: 18 : do ib=1,ia
3325 [ + + ]: 42 : do iq2=1,3
3326 [ + + ]: 117 : do iq1=1,3
3327 [ + + ]: 351 : do nu=1,3
3328 [ + + ]: 1053 : do mu=1,3
3329 : 729 : work(re,mu,ib,nu,ia,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)
3330 : 972 : work(im,mu,ib,nu,ia,iq1,iq2)=-work(im,mu,ia,nu,ib,iq1,iq2)
3331 : : end do
3332 : : end do
3333 : : end do
3334 : : end do
3335 : : end do
3336 : : end do
3337 : :
3338 : : !Perform the summation over the second atomic sublattice
3339 [ + + + + : 1740 : dyewdqdq(:,:,:,:,:,:)=zero
+ + + + +
+ + + ]
3340 [ + + ]: 9 : do ia=1,natom
3341 [ + + ]: 27 : do iq2=1,3
3342 [ + + ]: 78 : do iq1=1,3
3343 [ + + ]: 234 : do nu=1,3
3344 [ + + ]: 702 : do mu=1,3
3345 [ + + ]: 1620 : do ib=1,natom
3346 : : dyewdqdq(re,mu,ia,nu,iq1,iq2)=dyewdqdq(re,mu,ia,nu,iq1,iq2) + &
3347 : 972 : & work(re,mu,ia,nu,ib,iq1,iq2)
3348 : : dyewdqdq(im,mu,ia,nu,iq1,iq2)=dyewdqdq(im,mu,ia,nu,iq1,iq2) + &
3349 : 1458 : & work(im,mu,ia,nu,ib,iq1,iq2)
3350 : : end do
3351 : : end do
3352 : : end do
3353 : : end do
3354 : : end do
3355 : : end do
3356 [ - + ]: 3 : ABI_FREE(work)
3357 : :
3358 : : !Destroy atom table used for parallelism
3359 : 3 : call free_my_atmtab(my_atmtab,my_atmtab_allocated)
3360 : :
3361 [ + - ]: 3 : end subroutine dfpt_ewalddqdq
3362 : : !!***
3363 : :
3364 : : end module m_dfpt_elt
3365 : : !!***
|