Line data Source code
1 : !!****m* ABINIT/m_mklocl_realspace
2 : !! NAME
3 : !! m_mklocl_realspace
4 : !!
5 : !! FUNCTION
6 : !! Routines related to the local part of the pseudopotentials.
7 : !! Computation is done in real space (useful for isolated systems).
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2013-2026 ABINIT group (TRangel, MT, DC)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! TODO
16 : !! This module could be merged with m_mklocl
17 : !!
18 : !! SOURCE
19 :
20 : #if defined HAVE_CONFIG_H
21 : #include "config.h"
22 : #endif
23 :
24 : #include "abi_common.h"
25 :
26 : module m_mklocl_realspace
27 :
28 : use defs_basis
29 : use defs_wvltypes
30 : use m_xmpi
31 : use m_abicore
32 : use m_errors
33 :
34 : use defs_datatypes, only : pseudopotential_type
35 : use defs_abitypes, only : MPI_type
36 : use m_time, only : timab
37 : use m_geometry, only : xred2xcart
38 : use m_fft_mesh, only : mkgrid_fft
39 : use m_mpinfo, only : ptabs_fourdp
40 : use m_pawtab, only : pawtab_type
41 : use m_paw_numeric, only : paw_splint, paw_splint_der
42 : use m_psolver, only : psolver_hartree, psolver_kernel
43 : use m_abi2big, only : wvl_rhov_abi2big
44 : use m_wvl_wfs, only : derf_ab
45 : use m_fft, only : fourdp
46 :
47 : implicit none
48 :
49 : private
50 : !!***
51 :
52 : public :: mklocl_realspace
53 : public :: mklocl_wavelets
54 : !!***
55 :
56 : contains
57 : !!***
58 :
59 : !!****f* ABINIT/mklocl_realspace
60 : !! NAME
61 : !! mklocl_realspace
62 : !!
63 : !! FUNCTION
64 : !! This method is equivalent to mklocl_recipspace except that
65 : !! it uses real space pseudo-potentials. It is useful for isolated
66 : !! systems. Then the option 3 and 4 are not available for this implementation.
67 : !!
68 : !! Optionally compute:
69 : !! option=1 : local ionic potential throughout unit cell
70 : !! option=2 : contribution of local ionic potential to E gradient wrt xred
71 : !!
72 : !! INPUTS
73 : !! dtset <type(dataset_type)>=all input variables in this dataset
74 : !! mpi_enreg=information about MPI parallelization
75 : !! natom=number of atoms in unit cell.
76 : !! nattyp(ntypat)=number of atoms of each type in cell.
77 : !! nfft=(effective) number of FFT grid points (for this processor)
78 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
79 : !! nspden=number of spin-density components
80 : !! ntypat=number of types of atoms.
81 : !! option= (see above)
82 : !! pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
83 : !! psps <type(pseudopotential_type)>=variables related to pseudopotentials
84 : !! rhog(2,nfft)=electron density rho(G) (electrons/$\textrm{Bohr}^3$)
85 : !! rhor(nfft,nspden)=electron density in electrons/bohr**3.
86 : !! (needed if option==2 or if option==4)
87 : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
88 : !! ucvol=unit cell volume ($\textrm{Bohr}^3$).
89 : !! xred(3,natom)=reduced dimensionless atomic coordinates
90 : !!
91 : !! OUTPUT
92 : !! (if option==1) vpsp(nfft)=local crystal pseudopotential in real space.
93 : !! (if option==2) grtn(3,natom)=grads of Etot wrt tn. These gradients are in
94 : !! reduced coordinates. Multiply them by rprimd to get
95 : !! gradients in cartesian coordinates.
96 : !!
97 : !! SOURCE
98 :
99 0 : subroutine mklocl_realspace(grtn,icoulomb,mpi_enreg,natom,nattyp,nfft,ngfft,nscforder, &
100 0 : & nspden,ntypat,option,pawtab,psps,rhog,rhor,rprimd,typat,&
101 0 : & ucvol,usewvl,vpsp,xred)
102 :
103 : #if defined HAVE_BIGDFT
104 : use BigDFT_API, only : coulomb_operator,deallocate_coulomb_operator
105 : use defs_PSolver
106 : #else
107 : use defs_wvltypes, only : coulomb_operator
108 : #endif
109 :
110 : !Arguments ------------------------------------
111 : !scalars
112 : integer,intent(in) :: natom,nfft,nspden,ntypat,option
113 : real(dp),intent(in) :: ucvol
114 : type(MPI_type),intent(in) :: mpi_enreg
115 : type(pseudopotential_type),intent(in) :: psps
116 : type(pawtab_type),intent(in) :: pawtab(ntypat*psps%usepaw)
117 : !arrays
118 : integer,intent(in) :: icoulomb,nscforder,usewvl
119 : integer,intent(in) :: nattyp(ntypat),ngfft(18),typat(natom)
120 : real(dp),intent(in) :: rhog(2,nfft)
121 : real(dp),intent(in) :: rhor(nfft,nspden),rprimd(3,3)
122 : real(dp),intent(in) :: xred(3,natom)
123 : real(dp),intent(out) :: grtn(3,natom),vpsp(nfft)
124 :
125 : !Local variables-------------------------------
126 : character(len=1) :: geocode
127 : !testing variables
128 : !scalars
129 : integer,parameter :: nStep=2
130 : integer :: comm_fft,countParSeconde,i1,i2,i3
131 : integer :: ia,ia1,ia2,igeo,ii,ind,itypat,ix,iy,iz,jj
132 : integer :: kk,me_fft,n1,n2,n3,n3d,n_interpol
133 : integer :: nproc_fft,tpsStart,tpsStop
134 : real(dp),parameter :: min_rho_value=1.0d-12
135 : real(dp) :: aa,bb,cc,dd,delta,deltaV,dr,dr2div6,invdr,r,vol_interpol,x,y,z,hgx,hgy,hgz,entmp
136 : logical,parameter :: customRho=.false.,finiteDiff=.false.,testing=.false.
137 : logical :: doIt
138 : character(len=500) :: message
139 : !arrays
140 : integer :: ngfft_interpol(18)
141 0 : integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:)
142 0 : integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:)
143 : real(dp) :: coord(3),coordXYZ(3),refValue(3),tsec(2)
144 0 : real(dp),allocatable :: coordCart_interpol(:,:),coordRed_interpol(:,:)
145 0 : real(dp),allocatable :: gridcart(:,:)
146 0 : real(dp),allocatable :: grtn_cart_interpol(:,:),grtn_diff(:,:)
147 0 : real(dp),allocatable :: rhog_interpol(:,:),rhog_testing(:,:),rhor_interpol(:)
148 0 : real(dp),allocatable :: rhor_testing(:),rhor_work(:),xcart(:,:),vhartr(:),gxyz(:,:)
149 : type(coulomb_operator):: kernel
150 :
151 : ! *************************************************************************
152 :
153 : !Keep track of total time spent here
154 0 : if (option==2) then
155 0 : call timab(72,1,tsec)
156 : end if
157 :
158 : !Several constants (FFT sizes and parallelism)
159 0 : n1 = ngfft(1) ; n2 = ngfft(2) ; n3 = ngfft(3)
160 0 : nproc_fft = ngfft(10) ; me_fft = ngfft(11)
161 0 : n3d = ngfft(13) !for parallel runs
162 0 : if (nproc_fft==1) n3d=n3 !for serial runs
163 0 : comm_fft=mpi_enreg%comm_fft
164 0 : if(me_fft /= mpi_enreg%me_fft .or. nproc_fft /= mpi_enreg%nproc_fft) then
165 0 : ABI_BUG("mpi_enreg%x_fft not equal to the corresponding values in ngfft")
166 : end if
167 :
168 : !Conditions for periodicity in the three directions
169 0 : geocode='P'
170 0 : if (icoulomb==1) geocode='F'
171 0 : if (icoulomb==2) geocode='S'
172 :
173 : !Get the distrib associated with this fft_grid
174 0 : call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
175 :
176 : !Store xcart for each atom
177 0 : ABI_MALLOC(xcart,(3, natom))
178 0 : call xred2xcart(natom, rprimd, xcart, xred)
179 : !Store cartesian coordinates for each grid points
180 0 : ABI_MALLOC(gridcart,(3, nfft))
181 0 : call mkgrid_fft(ffti3_local,fftn3_distrib,gridcart,nfft,ngfft,rprimd)
182 :
183 : !Check whether all the PSP considered are of type GTH-HGH or PAW
184 0 : doIt=.true.
185 0 : do ii=1,psps%npsp
186 : doIt=doIt .and.&
187 0 : (psps%pspcod(ii)==2.or.psps%pspcod(ii)==3.or.psps%pspcod(ii)==10.or.psps%pspcod(ii)==7)
188 : end do
189 :
190 : !HGH-GTH/PAW treatment presumably starts here
191 0 : if (doIt) then
192 :
193 : ! Definition of the grid spacings as in the kernel routine
194 0 : hgx = rprimd(1,1)/(n1)
195 0 : hgy = rprimd(2,2)/(n2)
196 0 : hgz = rprimd(3,3)/(n3)
197 :
198 :
199 : !----------------------------------------------------------------------
200 : ! ----- Option 1: compute local ionic potential -----
201 : !----------------------------------------------------------------------
202 0 : if (option==1) then
203 :
204 : call psolver_kernel( (/ hgx, hgy, hgz /), 2, icoulomb, me_fft, kernel, comm_fft, &
205 0 : & (/n1,n2,n3/), nproc_fft, nscforder)
206 :
207 : call createIonicPotential_new(fftn3_distrib,ffti3_local,&
208 : & geocode,me_fft, nproc_fft, natom, &
209 : & ntypat, typat, psps%gth_params%psppar, &
210 : & int(psps%ziontypat), xcart,gridcart, hgx,hgy,hgz, &
211 0 : & n1,n2,n3d,n3, kernel, vpsp, comm_fft,pawtab,psps%usepaw)
212 :
213 : !----------------------------------------------------------------------
214 : ! ----- Option 2: compute forces induced by local ionic potential -----
215 : !----------------------------------------------------------------------
216 0 : else if (option == 2) then
217 :
218 : ! Compute Hartree potential from rhor
219 0 : ABI_MALLOC(vhartr,(nfft))
220 : call psolver_hartree(entmp, (/ hgx, hgy, hgz /), icoulomb, me_fft, comm_fft, nfft, &
221 0 : & (/n1,n2,n3/), nproc_fft, nscforder, nspden, rhor, vhartr, usewvl)
222 :
223 : ! Allocate temporary array for forces
224 0 : ABI_MALLOC(gxyz,(3, natom))
225 :
226 : ! Calculate local part of the forces grtn (inspired from BigDFT routine)
227 : call local_forces_new(fftn3_distrib,ffti3_local,geocode,me_fft, ntypat, natom, &
228 : & typat, xcart, gridcart, psps%gth_params%psppar, int(psps%ziontypat), &
229 0 : & hgx,hgy,hgz, n1,n2,n3,n3d, rhor,vhartr, gxyz, pawtab,psps%usepaw)
230 :
231 : ! Forces should be in reduced coordinates.
232 0 : do ia = 1, natom, 1
233 0 : do igeo = 1, 3, 1
234 : grtn(igeo, ia) = - rprimd(1, igeo) * gxyz(1, ia) &
235 : & - rprimd(2, igeo) * gxyz(2, ia) &
236 0 : & - rprimd(3, igeo) * gxyz(3, ia)
237 : end do
238 : end do
239 :
240 : ! Deallocate local variables
241 0 : ABI_FREE(vhartr)
242 0 : ABI_FREE(gxyz)
243 : end if
244 :
245 : !----------------------------------------------------------------------
246 : ! ----- Section for the non-HGH/GTH/PAW pseudopotentials (testing) ----
247 : !----------------------------------------------------------------------
248 : else
249 :
250 : if (testing) then
251 : call system_clock(count_rate = countParSeconde)
252 : call system_clock(tpsStart, count_rate = countParSeconde)
253 : end if
254 :
255 : ! dr is the r step in the sampling psps%vlspl
256 0 : dr = psps%qgrid_vl(2)
257 0 : invdr = 1._dp / dr
258 0 : dr2div6 = dr * dr / 6._dp
259 :
260 0 : if (option == 1) then
261 : ! Set 0 in vpsp before summing
262 0 : vpsp(:) = 0._dp
263 0 : else if (option == 2) then
264 : ! Allocate array to store cartesian gradient computed with
265 : ! an interpolation of rhor
266 0 : ABI_MALLOC(grtn_cart_interpol,(3, natom))
267 0 : grtn_cart_interpol(:, :) = 0._dp
268 :
269 0 : n_interpol = nStep ** 3
270 0 : ABI_MALLOC(coordRed_interpol,(3, nStep ** 3))
271 0 : ABI_MALLOC(coordCart_interpol,(3, nStep ** 3))
272 :
273 : if (testing .and. customRho) then
274 : ! Use a custom rho instead of the self-consistent one.
275 : ABI_MALLOC(rhor_testing,(nfft))
276 : ABI_MALLOC(rhog_testing,(2, nfft))
277 : end if
278 :
279 0 : ABI_MALLOC(rhor_interpol,(nfft * n_interpol))
280 0 : ABI_MALLOC(rhor_work,(nfft * n_interpol))
281 0 : ABI_MALLOC(rhog_interpol,(2, nfft * n_interpol))
282 :
283 : if (testing .and. customRho) then
284 : ! Testing only, changing rho with a centered gaussian
285 : do ii = 1, nfft, 1
286 : ! using the position of the first atom as center.
287 : r = (gridcart(1, ii) - xcart(1, 1)) ** 2 + &
288 : & (gridcart(2, ii) - xcart(2, 1)) ** 2 + &
289 : & (gridcart(3, ii) - xcart(3, 1)) ** 2
290 : rhor_testing(ii) = exp(-r/4._dp)
291 : end do
292 : ! Testing only, compute rhog_testing from rhor_testing
293 : call fourdp(1,rhog_testing,rhor_testing,-1,mpi_enreg,nfft,1,ngfft,0)
294 : end if
295 :
296 : ! Compute the interpolation of rho, using a fourier transform
297 0 : rhog_interpol(:, :) = 0._dp
298 : ii = 0
299 0 : do i3 = 1, n3, 1
300 0 : if (i3 <= n3 / 2) then
301 : iz = i3
302 : else
303 0 : iz = n3 * nStep - n3 + i3
304 : end if
305 0 : do i2 = 1, n2, 1
306 0 : if (i2 <= n2 / 2) then
307 : iy = i2
308 : else
309 0 : iy = n2 * nStep - n2 + i2
310 : end if
311 0 : do i1 = 1, n1, 1
312 0 : ii = ii + 1
313 0 : if (i1 <= n1 / 2) then
314 : ix = i1
315 : else
316 0 : ix = n1 * nStep - n1 + i1
317 : end if
318 0 : jj = (iz - 1) * n2 * n1 * nStep ** 2 + (iy - 1) * n3 * nStep + ix
319 0 : if (testing .and. customRho) then
320 : rhog_interpol(:, jj) = rhog_testing(:, ii)
321 : else
322 0 : rhog_interpol(:, jj) = rhog(:, ii)
323 : end if
324 : end do
325 : end do
326 : end do
327 :
328 : ! Compute the interpolation of rho from the Fourier transformation
329 0 : ngfft_interpol(:) = ngfft(:)
330 0 : ngfft_interpol(1:3) = (/ n1 * nStep, n2 * nStep, n3 * nStep /)
331 0 : ngfft_interpol(4:6) = (/ n1 * nStep + 1, n2 * nStep + 1, n3 * nStep /)
332 0 : call fourdp(1,rhog_interpol,rhor_work,1,mpi_enreg,nfft*n_interpol,1,ngfft_interpol,0)
333 :
334 : ! Reorder rhor_interpol to be able to read it linearly
335 0 : jj = 0
336 0 : do i3 = 1, n3, 1
337 0 : do i2 = 1, n2, 1
338 0 : do i1 = 1, n1, 1
339 0 : do iz = 1, nStep, 1
340 0 : do iy = 1, nStep, 1
341 0 : do ix = 1, nStep, 1
342 0 : jj = jj + 1
343 0 : kk = ((i3 - 1) * nStep + iz - 1) ! z coordinate in the interpolated grid
344 0 : kk = kk * n1 * n2 * nStep ** 2
345 0 : kk = kk + ((i2 - 1) * nStep + iy - 1) * n1 * nStep ! adding y coordinate
346 0 : kk = kk + (i1 - 1) * nStep + ix ! adding x coordinate
347 0 : rhor_interpol(jj) = rhor_work(kk)
348 : end do
349 : end do
350 : end do
351 : end do
352 : end do
353 : end do
354 0 : ABI_FREE(rhor_work)
355 :
356 : ! Compute grid access in the interpolated volume
357 0 : ii = 0
358 0 : do iz = 1, nStep, 1
359 0 : z = real(iz - 1, dp) / real(nStep, dp)
360 0 : do iy = 1, nStep, 1
361 0 : y = real(iy - 1, dp) / real(nStep, dp)
362 0 : do ix = 1, nStep, 1
363 0 : x = real(ix - 1, dp) / real(nStep, dp)
364 0 : ii = ii + 1
365 0 : coordRed_interpol(:, ii) = (/ x, y, z /)
366 : ! Assuming orthogonal box (should be change later)
367 : coordCart_interpol(:, ii) = (/ x * rprimd(1, 1) / real(n1, dp), &
368 : & y * rprimd(2, 2) / real(n2, dp), &
369 0 : & z * rprimd(3, 3) / real(n3, dp) /)
370 : end do
371 : end do
372 : end do
373 :
374 : vol_interpol = 1._dp / real(nStep, dp) ** 3
375 : ! Compute the coordinates (integer) of each atom and deduce
376 : ! the max extens of the integral summation.
377 : ! !! do ia = 1, natom, 1
378 : ! !! coordAtom(1, ia) = int(xred(1, ia) * n1) + 1
379 : ! !! coordAtom(2, ia) = int(xred(2, ia) * n2) + 1
380 : ! !! coordAtom(3, ia) = int(xred(3, ia) * n3) + 1
381 : ! !! end do
382 : end if
383 :
384 : if (testing .and. option == 2) then
385 : call system_clock(tpsStop, count_rate = countParSeconde)
386 : write(std_out,*) "Tps : ", real(tpsStop - tpsStart) / real(countParSeconde)
387 : end if
388 :
389 0 : ia1=1
390 0 : do itypat = 1, ntypat, 1
391 : ! ia1,ia2 sets range of loop over atoms:
392 0 : ia2 = ia1 + nattyp(itypat) - 1
393 :
394 0 : do ii = 1, nfft, 1
395 0 : do ia = ia1, ia2, 1
396 0 : if (option == 1) then
397 : ! Compute the potential
398 : ! r is the distance between grid point and atom
399 : r = sqrt((gridcart(1, ii) - xcart(1, ia)) ** 2 + &
400 : & (gridcart(2, ii) - xcart(2, ia)) ** 2 + &
401 0 : & (gridcart(3, ii) - xcart(3, ia)) ** 2)
402 :
403 : ! Coefficients needed to compute the spline.
404 0 : jj = int(r * invdr) + 1
405 0 : if (jj > psps%mqgrid_vl - 2) then
406 : write(message, '(3a,i0,a,i0,a,a)' )&
407 0 : & ' pseudo-potential local part sampling is not wide enough', ch10, &
408 0 : & ' want to access position ', jj, ' whereas mqgrid_vl = ', psps%mqgrid_vl, ch10, &
409 0 : & ' Action : no idea, contact developpers...'
410 0 : ABI_ERROR(message)
411 : end if
412 0 : delta = r - psps%qgrid_vl(jj)
413 0 : bb = delta * invdr
414 0 : aa = 1._dp - bb
415 0 : cc = aa * (aa ** 2 - 1._dp) * dr2div6
416 0 : dd = bb * (bb ** 2 - 1._dp) * dr2div6
417 :
418 : ! compute V(r) from the spline, jj and jj + 1 is braketting r in
419 : ! the sampling
420 : deltaV = aa * psps%vlspl(jj, 1, itypat) + bb * psps%vlspl(jj + 1, 1, itypat) + &
421 0 : & cc * psps%vlspl(jj, 2, itypat) + dd * psps%vlspl(jj + 1, 2, itypat)
422 : ! Add on grid point ii the contribution of atom ia
423 0 : vpsp(ii) = vpsp(ii) + deltaV
424 0 : else if (option == 2) then
425 : ! Compute the forces, as gradient of energy (V(r).rho(r))
426 :
427 : ! Testing only - reference points
428 : if (.false.) then
429 : ! r is the distance between grid point and atom
430 : r = sqrt((gridcart(1, ii) - xcart(1, ia)) ** 2 + &
431 : & (gridcart(2, ii) - xcart(2, ia)) ** 2 + &
432 : & (gridcart(3, ii) - xcart(3, ia)) ** 2)
433 :
434 : ! Coefficients needed to compute the spline.
435 : jj = int(r * invdr) + 1
436 : delta = r - psps%qgrid_vl(jj)
437 : bb = delta * invdr
438 : aa = 1._dp - bb
439 : cc = aa * (aa ** 2 - 1._dp) * dr2div6
440 : dd = bb * (bb ** 2 - 1._dp) * dr2div6
441 :
442 : ! When mesh position is on a node, forces are null.
443 : if (r /= 0._dp) then
444 : ! This value deltaV is the first derivative of V(r) taken at r.
445 : deltaV = aa * psps%dvlspl(jj, 1, itypat) + bb * psps%dvlspl(jj + 1, 1, itypat) + &
446 : & cc * psps%dvlspl(jj, 2, itypat) + dd * psps%dvlspl(jj + 1, 2, itypat)
447 : ! We multiply by rho(r) to have an energy.
448 : deltaV = deltaV * rhor(ii, 1) / r
449 : refValue(:) = - deltaV * (gridcart(:, ii) - xcart(:, ia))
450 : grtn_cart_interpol(:, ia) = grtn_cart_interpol(:, ia) + refValue(:)
451 : end if
452 : end if
453 :
454 : ! Compute the interpolation for the point ii
455 0 : ind = (ii - 1) * n_interpol
456 0 : do kk = 1, n_interpol, 1
457 0 : ind = ind + 1
458 :
459 0 : if (rhor_interpol(ind) > min_rho_value) then
460 : ! Assume orthogonal box...
461 0 : coordXYZ(1) = gridcart(1, ii) - xcart(1, ia) + coordCart_interpol(1, kk)
462 0 : coordXYZ(2) = gridcart(2, ii) - xcart(2, ia) + coordCart_interpol(2, kk)
463 0 : coordXYZ(3) = gridcart(3, ii) - xcart(3, ia) + coordCart_interpol(3, kk)
464 0 : r = coordXYZ(1) ** 2 + coordXYZ(2) ** 2 + coordXYZ(3) ** 2
465 :
466 0 : if (r /= 0._dp) then
467 0 : r = sqrt(r)
468 : ! Coefficients needed to compute the spline.
469 0 : jj = int(r * invdr) + 1
470 0 : delta = r - psps%qgrid_vl(jj)
471 0 : bb = delta * invdr
472 0 : aa = 1._dp - bb
473 0 : cc = aa * (aa ** 2 - 1._dp) * dr2div6
474 0 : dd = bb * (bb ** 2 - 1._dp) * dr2div6
475 : deltaV = aa * psps%dvlspl(jj, 1, itypat) + &
476 : & bb * psps%dvlspl(jj + 1, 1, itypat) + &
477 : & cc * psps%dvlspl(jj, 2, itypat) + &
478 0 : & dd * psps%dvlspl(jj + 1, 2, itypat)
479 0 : deltaV = deltaV * rhor_interpol(ind) / r
480 0 : grtn_cart_interpol(1, ia) = grtn_cart_interpol(1, ia) - deltaV * coordXYZ(1)
481 0 : grtn_cart_interpol(2, ia) = grtn_cart_interpol(2, ia) - deltaV * coordXYZ(2)
482 0 : grtn_cart_interpol(3, ia) = grtn_cart_interpol(3, ia) - deltaV * coordXYZ(3)
483 : ! do igeo = 1, 3, 1
484 : ! grtn_cart_interpol(igeo, ia) = grtn_cart_interpol(igeo, ia) - deltaV * coordXYZ(igeo)
485 : ! end do
486 : end if
487 : end if
488 : end do
489 :
490 : ! =============
491 : ! Testing only
492 : ! =============
493 : ! use of finite differences
494 : if (finiteDiff) then
495 : do igeo = 1, 3, 1
496 : coord(:) = 0._dp
497 : coord(igeo) = dr / 2.0_dp
498 : r = sqrt((gridcart(1, ii) - xcart(1, ia) + coord(1)) ** 2 + &
499 : & (gridcart(2, ii) - xcart(2, ia) + coord(2)) ** 2 + &
500 : & (gridcart(3, ii) - xcart(3, ia) + coord(3)) ** 2)
501 :
502 : ! Coefficients needed to compute the spline.
503 : jj = int(r * invdr) + 1
504 : delta = r - psps%qgrid_vl(jj)
505 : bb = delta * invdr
506 : aa = 1._dp - bb
507 : cc = aa * (aa ** 2 - 1._dp) * dr2div6
508 : dd = bb * (bb ** 2 - 1._dp) * dr2div6
509 :
510 : deltaV = aa * psps%vlspl(jj, 1, itypat) + bb * psps%vlspl(jj + 1, 1, itypat) + &
511 : & cc * psps%vlspl(jj, 2, itypat) + dd * psps%vlspl(jj + 1, 2, itypat)
512 :
513 :
514 : coord(:) = 0._dp
515 : coord(igeo) = -dr / 2.0_dp
516 : r = sqrt((gridcart(1, ii) - xcart(1, ia) + coord(1)) ** 2 + &
517 : & (gridcart(2, ii) - xcart(2, ia) + coord(2)) ** 2 + &
518 : & (gridcart(3, ii) - xcart(3, ia) + coord(3)) ** 2)
519 :
520 : ! Coefficients needed to compute the spline.
521 : jj = int(r * invdr) + 1
522 : delta = r - psps%qgrid_vl(jj)
523 : bb = delta * invdr
524 : aa = 1._dp - bb
525 : cc = aa * (aa ** 2 - 1._dp) * dr2div6
526 : dd = bb * (bb ** 2 - 1._dp) * dr2div6
527 :
528 : deltaV = deltaV - (aa * psps%vlspl(jj, 1, itypat) + &
529 : & bb * psps%vlspl(jj + 1, 1, itypat) + &
530 : & cc * psps%vlspl(jj, 2, itypat) + &
531 : & dd * psps%vlspl(jj + 1, 2, itypat))
532 : grtn_diff(igeo, ia) = grtn_diff(igeo, ia) - deltaV * rhor(ii, 1) / dr
533 : end do
534 : end if
535 : ! =============
536 : ! Testing only
537 : ! =============
538 :
539 : end if
540 : end do
541 : ! End loop over atoms of type itypat
542 : end do
543 : ! End loop over real space grid points
544 :
545 0 : ia1 = ia2 + 1
546 : end do
547 : ! End loop over type of atoms
548 :
549 0 : if(option==2)then
550 : ! multiply the forces by the volume of a single box mesh.
551 : grtn_cart_interpol(:, :) = grtn_cart_interpol(:, :) * &
552 0 : & ucvol / real(n1 * n2 * n3, dp) * vol_interpol
553 : ! Transform cartesian forces to reduce coordinates
554 0 : do ia = 1, natom, 1
555 0 : do igeo = 1, 3, 1
556 : grtn(igeo, ia) = rprimd(1, igeo) * grtn_cart_interpol(1, ia) + &
557 : & rprimd(2, igeo) * grtn_cart_interpol(2, ia) + &
558 0 : & rprimd(3, igeo) * grtn_cart_interpol(3, ia)
559 : end do
560 : end do
561 0 : ABI_FREE(rhor_interpol)
562 0 : ABI_FREE(rhog_interpol)
563 0 : ABI_FREE(coordRed_interpol)
564 0 : ABI_FREE(coordCart_interpol)
565 : if (testing .and. customRho) then
566 : ABI_FREE(rhor_testing)
567 : ABI_FREE(rhog_testing)
568 : end if
569 :
570 : if (testing) then
571 : call system_clock(tpsStop, count_rate = countParSeconde)
572 : write(std_out,*) "Tps : ", real(tpsStop - tpsStart) / real(countParSeconde)
573 : write(std_out,*) grtn_cart_interpol
574 : ABI_ERROR("Testing section!")
575 : end if
576 :
577 : end if
578 :
579 : !-------------------------
580 : end if ! GTH/HGH/PAW psps
581 :
582 : !Release temporary memory
583 0 : ABI_FREE(xcart)
584 0 : ABI_FREE(gridcart)
585 :
586 : !Close timing counters
587 0 : if (option==2)then
588 0 : call timab(72,2,tsec)
589 : end if
590 :
591 0 : end subroutine mklocl_realspace
592 : !!***
593 :
594 : !----------------------------------------------------------------------
595 :
596 : !!****f* mklocl_realspace/createIonicPotential_new
597 : !! NAME
598 : !! createIonicPotential_new
599 : !!
600 : !! FUNCTION
601 : !!
602 : !! INPUTS
603 : !!
604 : !! OUTPUT
605 : !!
606 : !! SOURCE
607 :
608 0 : subroutine createIonicPotential_new(fftn3_distrib,ffti3_local,geocode,iproc,&
609 0 : & nproc,nat,ntypes,iatype,psppar,nelpsp,rxyz,gridcart,&
610 0 : & hxh,hyh,hzh,n1i,n2i,n3d,n3i,kernel,pot_ion,spaceworld,pawtab,usepaw)
611 :
612 : use defs_wvltypes, only : coulomb_operator
613 :
614 : !Arguments -------------------------------
615 : !scalars
616 : integer, intent(in) :: iproc,nproc,ntypes,nat,n1i,n2i,n3i,n3d,spaceworld,usepaw
617 : real(dp), intent(in) :: hxh,hyh,hzh
618 : character(len=1), intent(in) :: geocode
619 : type(coulomb_operator), intent(in) :: kernel
620 : !arrays
621 : integer, dimension(nat), intent(in) :: iatype
622 : integer, dimension(ntypes), intent(in) :: nelpsp
623 : integer, dimension(*), intent(in) ::fftn3_distrib,ffti3_local
624 : real(dp), dimension(3,n1i*n2i*n3d), intent(in) :: gridcart
625 : real(dp), dimension(0:4,0:6,ntypes), intent(in) :: psppar
626 : real(dp), dimension(3,nat), intent(in) :: rxyz
627 : real(dp), dimension(*), intent(inout) :: pot_ion
628 : type(pawtab_type),intent(in) :: pawtab(ntypes*usepaw)
629 :
630 : !Local variables -------------------------
631 : #if defined HAVE_BIGDFT
632 : !scalars
633 : integer :: iat,i1,i2,i3,j1,j2,j3,isx,isy,isz,iex,iey,iez,ierr,ityp
634 : integer :: ind,nloc,iloc,i3loc,msz
635 : logical :: gox,goy,goz,perx,pery,perz
636 : real(dp) :: arg,charge,cutoff,ehart,eexcu,rholeaked,rholeaked_tot,rloc
637 : real(dp) :: rx,ry,rz,rzero,r2,tt,tt_tot,vexcu,vhgh,x,xp,y,z
638 : !arrays
639 : real(dp) :: rr(1),vpaw(1)
640 : real(dp),pointer :: rad(:),vloc(:),d2vloc(:)
641 : #endif
642 :
643 : ! *********************************************************************
644 :
645 : #if defined HAVE_BIGDFT
646 :
647 : if(nproc<0)then
648 : ABI_ERROR('nproc should not be negative')
649 : end if
650 :
651 : !Ionic charge (must be calculated for the PS active processes)
652 : rholeaked=0._dp
653 : !Ionic energy (can be calculated for all the processors)
654 :
655 : !here we should insert the calculation of the ewald energy for the periodic BC case
656 : !!! eion=0._dp
657 : !!! do iat=1,nat
658 : !!! ityp=iatype(iat)
659 : !!! rx=rxyz(1,iat)
660 : !!! ry=rxyz(2,iat)
661 : !!! rz=rxyz(3,iat)
662 : !!! ! ion-ion interaction
663 : !!! do jat=1,iat-1
664 : !!! dist=sqrt( (rx-rxyz(1,jat))**2+(ry-rxyz(2,jat))**2+(rz-rxyz(3,jat))**2 )
665 : !!! jtyp=iatype(jat)
666 : !!! eion=eion+real(nelpsp(jtyp)*nelpsp(ityp),kind=dp)/dist
667 : !!! enddo
668 : !!! end do
669 : !!! if (iproc.eq.0) write(std_out,'(1x,a,1pe22.14)') 'ion-ion interaction energy',eion
670 :
671 : !Creates charge density arising from the ionic PSP cores
672 : !the n3pi dimension indicates the number of planes trated by each processor in the FFT parallelisation
673 : !for a plane wave treatment this value depends on whether the direct space is divided in planes or not
674 : !I don't know this variable, which in the future must be inserted at the place of n3pi (LG)
675 : !if n3pi=0 this means that the processors doesn't calculate anything
676 : !if (n3pi >0 ) then
677 :
678 : !conditions for periodicity in the three directions
679 : perx=(geocode /= 'F')
680 : pery=(geocode == 'P')
681 : perz=(geocode /= 'F')
682 :
683 : !this initialise the array to zero, it will work only if bigdft library is enabled
684 : pot_ion(1:n1i*n2i*n3d)=zero
685 :
686 : do iat=1,nat
687 : ityp=iatype(iat)
688 : rx=rxyz(1,iat)
689 : ry=rxyz(2,iat)
690 : rz=rxyz(3,iat)
691 :
692 : rloc=psppar(0,0,ityp)
693 : charge=real(nelpsp(ityp),kind=dp)/(2._dp*pi*sqrt(2._dp*pi)*rloc**3)
694 : cutoff=10._dp*rloc
695 :
696 : isx=floor((rx-cutoff)/hxh)
697 : isy=floor((ry-cutoff)/hyh)
698 : isz=floor((rz-cutoff)/hzh)
699 :
700 : iex=ceiling((rx+cutoff)/hxh)
701 : iey=ceiling((ry+cutoff)/hyh)
702 : iez=ceiling((rz+cutoff)/hzh)
703 :
704 : ! Calculate Ionic Density
705 : ! using HGH parameters.
706 : ! Eq. 1.104, T. Deutsch and L. Genovese, JDN. 12, 2011
707 : do i3=isz,iez
708 : z=real(i3,kind=dp)*hzh-rz
709 : call ind_positions_mklocl(perz,i3,n3i,j3,goz)
710 : if(fftn3_distrib(j3)==iproc) then
711 : i3loc=ffti3_local(j3)
712 : do i2=isy,iey
713 : y=real(i2,kind=dp)*hyh-ry
714 : call ind_positions_mklocl(pery,i2,n2i,j2,goy)
715 : do i1=isx,iex
716 : x=real(i1,kind=dp)*hxh-rx
717 : call ind_positions_mklocl(perx,i1,n1i,j1,gox)
718 : r2=x**2+y**2+z**2
719 : if (goz .and. goy .and. gox ) then
720 : ind=j1+(j2-1)*n1i+(i3loc-1)*n1i*n2i
721 : r2=(gridcart(1,ind)-rx)**2+(gridcart(2,ind)-ry)**2+(gridcart(3,ind)-rz)**2
722 : end if
723 : arg=r2/rloc**2
724 : xp=exp(-.5d0*arg)
725 : if (goz .and. goy .and. gox ) then
726 : pot_ion(ind)=pot_ion(ind)-xp*charge
727 : else
728 : rholeaked=rholeaked+xp*charge
729 : end if
730 : end do
731 : end do
732 : end if
733 : end do
734 :
735 : end do
736 :
737 : !Check
738 : tt=0._dp
739 : do j3= 1,n3d
740 : do i2= 1,n2i
741 : do i1= 1,n1i
742 : ind=i1+(i2-1)*n1i+(j3-1)*n1i*n2i
743 : tt=tt+pot_ion(ind)
744 : end do
745 : end do
746 : end do
747 :
748 : tt=tt*hxh*hyh*hzh
749 : rholeaked=rholeaked*hxh*hyh*hzh
750 :
751 : call xmpi_sum(tt,tt_tot,spaceworld,ierr)
752 : call xmpi_sum(rholeaked,rholeaked_tot,spaceworld,ierr)
753 :
754 : if (iproc.eq.0) then
755 : write(std_out,'(1x,a,f26.12,2x,1pe10.3)') &
756 : & 'total ionic charge, leaked charge ',tt_tot,rholeaked_tot
757 : end if
758 :
759 : !Here the value of the datacode must be kept fixed
760 : !there can be some problems when running this stuff in parallel,
761 : ! if the ionic potential distribution does not agree with the
762 : ! plane distribution which is supposed to hold for the Poisson Solver
763 : call psolver(geocode,'D',iproc,nproc,n1i,n2i,n3i,0,hxh,hyh,hzh,&
764 : & pot_ion,kernel%kernel,pot_ion,ehart,eexcu,vexcu,0._dp,.false.,1)
765 :
766 : !Add the remaining short-range local terms
767 : do iat=1,nat
768 : ityp=iatype(iat)
769 :
770 : rx=rxyz(1,iat)
771 : ry=rxyz(2,iat)
772 : rz=rxyz(3,iat)
773 :
774 : ! determine number of local terms
775 : rloc=psppar(0,0,ityp)
776 : cutoff=10._dp*rloc
777 : charge=real(nelpsp(ityp),kind=dp)
778 :
779 : ! determine number of local terms (HGH pot)
780 : nloc=0
781 : do iloc=1,4
782 : if (psppar(0,iloc,ityp).ne.0._dp) nloc=iloc
783 : end do
784 :
785 : ! PAW specifics
786 : if (usepaw==1) then
787 : msz=pawtab(ityp)%wvl%rholoc%msz
788 : rad => pawtab(ityp)%wvl%rholoc%rad(1:msz)
789 : vloc => pawtab(ityp)%wvl%rholoc%d(1:msz,3)
790 : d2vloc => pawtab(ityp)%wvl%rholoc%d(1:msz,4)
791 : rzero=rad(1);if (rzero<=1.d-10) rzero=rad(2)
792 : end if
793 :
794 : isx=floor((rx-cutoff)/hxh)
795 : isy=floor((ry-cutoff)/hyh)
796 : isz=floor((rz-cutoff)/hzh)
797 :
798 : iex=ceiling((rx+cutoff)/hxh)
799 : iey=ceiling((ry+cutoff)/hyh)
800 : iez=ceiling((rz+cutoff)/hzh)
801 :
802 : do i3=isz,iez
803 : z=real(i3,kind=dp)*hzh-rz
804 : call ind_positions_mklocl(perz,i3,n3i,j3,goz)
805 : if(fftn3_distrib(j3) == iproc .and. goz) then !MPI
806 : i3loc=ffti3_local(j3)
807 : if (goz) then
808 : do i2=isy,iey
809 : y=real(i2,kind=dp)*hyh-ry
810 : call ind_positions_mklocl(pery,i2,n2i,j2,goy)
811 : if (goy) then
812 : do i1=isx,iex
813 : x=real(i1,kind=dp)*hxh-rx
814 : call ind_positions_mklocl(perx,i1,n1i,j1,gox)
815 : if (gox) then
816 : ind=j1+(j2-1)*n1i+(i3loc-1)*n1i*n2i
817 : r2=(gridcart(1,ind)-rx)**2+(gridcart(2,ind)-ry)**2+(gridcart(3,ind)-rz)**2
818 : ! r2=x**2+y**2+z**2
819 :
820 : ! HGH: V_S=gaussian potential of Eq. (9) in JCP 129, 014109(2008)
821 : if (usepaw==0) then
822 : if (nloc /= 0) then
823 : arg=r2/rloc**2
824 : xp=exp(-.5d0*arg)
825 : tt=psppar(0,nloc,ityp)
826 : do iloc=nloc-1,1,-1
827 : tt=arg*tt+psppar(0,iloc,ityp)
828 : end do
829 : pot_ion(ind)=pot_ion(ind)+xp*tt
830 : end if
831 :
832 : ! PAW: V_PAW-V_L^HGH
833 : else
834 : rr(1)=sqrt(r2)
835 : if (rr(1)>=rzero) then
836 : call paw_splint(msz,rad,vloc,d2vloc,1,rr,vpaw)
837 : call calcVloc_mklocl(vhgh,rr(1),rloc,charge)
838 : pot_ion(ind)=pot_ion(ind)+vpaw(1)-vhgh
839 : else
840 : pot_ion(ind)=pot_ion(ind)+vloc_zero_mklocl(charge,rloc,msz,rad,vloc,d2vloc)
841 : end if
842 : end if
843 :
844 : end if
845 : end do
846 : end if
847 : end do
848 : end if
849 : end if
850 : end do
851 :
852 : end do !iat
853 : #else
854 0 : BIGDFT_NOTENABLED_ERROR()
855 : if (.false.) write(std_out,*) geocode,iproc,nproc,ntypes,nat,n1i,n2i,n3i,n3d,spaceworld,usepaw,&
856 : & hxh,hyh,hzh,iatype(1),nelpsp(1),fftn3_distrib(1),ffti3_local(1),gridcart(1,1),psppar(1,1,1),&
857 : & rxyz(1,1),pot_ion(1),pawtab(1)%mesh_size,kernel%co
858 : #endif
859 :
860 : CONTAINS
861 : !!***
862 :
863 : !----------------------------------------------------------------------
864 :
865 : !!****f* mklocl_realspace/calcVloc_mklocl
866 : !! NAME
867 : !! calcVloc_mklocl
868 : !!
869 : !! FUNCTION
870 : !!
871 : !! INPUTS
872 : !!
873 : !! OUTPUT
874 : !!
875 : !! SOURCE
876 :
877 : subroutine calcVloc_mklocl(yy,xx,rloc,Z)
878 :
879 : !Arguments ------------------------------------
880 : !scalars
881 : real(dp),intent(in) :: xx,rloc,Z
882 : real(dp),intent(out) :: yy
883 :
884 : !Local variables-------------------------------
885 : !scalars
886 : real(dp):: arg,tt
887 :
888 : ! *************************************************************************
889 :
890 : arg=xx/(sqrt(2.0)*rloc)
891 : call derf_ab(tt,arg)
892 : yy=-Z/xx*tt
893 :
894 : end subroutine calcVloc_mklocl
895 : !!***
896 :
897 : !----------------------------------------------------------------------
898 :
899 : !!****f* mklocl_realspace/vloc_zero_mklocl
900 : !! NAME
901 : !! vloc_zero_mklocl
902 : !!
903 : !! FUNCTION
904 : !! Use a quadratic interpolation to get limit of Vloc(x) at x->0
905 : !!
906 : !! INPUTS
907 : !!
908 : !! OUTPUT
909 : !!
910 : !! SOURCE
911 :
912 : function vloc_zero_mklocl(charge,rloc,msz,rad,vloc,d2vloc)
913 :
914 :
915 : !Arguments ------------------------------------
916 : !scalars
917 : integer,intent(in) :: msz
918 : real(dp) :: vloc_zero_mklocl
919 : real(dp),intent(in) :: charge,rloc
920 : !arrays
921 : real(dp) :: rad(msz),vloc(msz),d2vloc(msz)
922 :
923 : !Local variables-------------------------------
924 : !scalars
925 : real(dp) :: y1,y2,y3,zz=0._dp
926 : !arrays
927 : real(dp) :: ll(3),xx(3),yy(3)
928 :
929 : ! *************************************************************************
930 :
931 : !Select 3 points x1,x2,x3 near 0
932 : if (rad(1)>1.d-10) then
933 : xx(1:3)=rad(1:3)
934 : else
935 : xx(1:3)=rad(2:4)
936 : end if
937 :
938 : !Find the corresponding values of y=(V^PAW(x)-V^HGH(x))/x
939 : call paw_splint(msz,rad,vloc,d2vloc,3,xx,yy)
940 : call calcVloc_mklocl(y1,xx(1),rloc,charge)
941 : call calcVloc_mklocl(y2,xx(2),rloc,charge)
942 : call calcVloc_mklocl(y3,xx(3),rloc,charge)
943 : yy(1)= yy(1)-y1
944 : yy(2)= yy(2)-y2
945 : yy(3)= yy(3)-y3
946 :
947 : !Find a polynomial of the form (z=0):
948 : !P(z) = y1.L1(z) + y2.L2(z) + y3.L3(z)
949 :
950 : !L1(z) = (z-x2)(z-x3)/((x1-x2)(x1-x3))
951 : ll(1)=(zz-xx(2))*(zz-xx(3))/((xx(1)-xx(2))*(xx(1)-xx(3)))
952 : !L2(z) = (z-x1)(z-x3)/((x2-x1)(x2-x3))
953 : ll(2)=(zz-xx(1))*(zz-xx(3))/((xx(2)-xx(1))*(xx(2)-xx(3)))
954 : !L3(z) = (z-x1)(z-x2)/((x3-x1)(x3-x2))
955 : ll(3)=(zz-xx(1))*(zz-xx(2))/((xx(3)-xx(1))*(xx(3)-xx(2)))
956 :
957 : vloc_zero_mklocl=yy(1)*ll(1)+yy(2)*ll(2)+yy(3)*ll(3)
958 :
959 : end function vloc_zero_mklocl
960 : !!***
961 :
962 : end subroutine createIonicPotential_new
963 : !!***
964 :
965 : !----------------------------------------------------------------------
966 :
967 : !!****f* mklocl_realspace/local_forces_new
968 : !! NAME
969 : !! local_forces_new
970 : !!
971 : !! FUNCTION
972 : !!
973 : !! INPUTS
974 : !!
975 : !! OUTPUT
976 : !!
977 : !! SOURCE
978 :
979 0 : subroutine local_forces_new(fftn3_distrib,ffti3_local,&
980 0 : geocode,iproc,ntypes,nat,iatype,rxyz,gridcart,psppar,nelpsp,hxh,hyh,hzh,&
981 0 : n1,n2,n3,n3d,rho,pot,floc,pawtab,usepaw)
982 :
983 :
984 : !Arguments -------------------------------
985 : !scalars
986 : integer, intent(in) :: iproc,ntypes,nat,n1,n2,n3,n3d,usepaw
987 : character(len=1), intent(in) :: geocode
988 : real(dp), intent(in) :: hxh,hyh,hzh
989 : !arrays
990 : integer, dimension(*), intent(in) ::fftn3_distrib,ffti3_local
991 : integer, dimension(nat), intent(in) :: iatype
992 : integer, dimension(ntypes), intent(in) :: nelpsp
993 : real(dp), dimension(3,n1*n2*n3d), intent(in) :: gridcart
994 : real(dp), dimension(0:4,0:6,ntypes), intent(in) :: psppar
995 : real(dp), dimension(3,nat), intent(in) :: rxyz
996 : real(dp), dimension(*), intent(in) :: rho,pot
997 : real(dp), dimension(3,nat), intent(out) :: floc
998 : type(pawtab_type),intent(in) :: pawtab(ntypes*usepaw)
999 :
1000 : !Local variables -------------------------
1001 : !scalars
1002 : integer :: isx,isy,isz,iex,iey,iez,i1,i2,i3,j1,j2,j3,ind,iat,ityp,iloc,i3loc,msz,nloc
1003 : logical :: perx,pery,perz,gox,goy,goz
1004 : real(dp) :: arg,charge,cutoff,dvhgh,fxerf,fyerf,fzerf,fxgau,fygau,fzgau,forceleaked
1005 : real(dp) :: forceloc,prefactor,rloc,rloc2,rhoel,rx,ry,rz,rzero,r2,tt,x,xp,y,z,Vel
1006 : real(dp), dimension(4) :: cprime
1007 : !arrays
1008 : real(dp) :: dvpawdr(1),rr(1)
1009 0 : real(dp),pointer :: rad(:),vloc(:),d2vloc(:)
1010 :
1011 : ! *********************************************************************
1012 :
1013 0 : if (iproc == 0) write(std_out,'(1x,a)',advance='no')'Calculate local forces...'
1014 :
1015 : !Conditions for periodicity in the three directions
1016 0 : perx=(geocode /= 'F')
1017 0 : pery=(geocode == 'P')
1018 0 : perz=(geocode /= 'F')
1019 :
1020 0 : forceleaked=zero
1021 :
1022 0 : do iat=1,nat
1023 0 : ityp=iatype(iat)
1024 : ! Coordinates of the center
1025 0 : rx=rxyz(1,iat)
1026 0 : ry=rxyz(2,iat)
1027 0 : rz=rxyz(3,iat)
1028 :
1029 : ! Initialization of the forces
1030 : ! ion-electron term, error function part
1031 0 : fxerf=zero
1032 0 : fyerf=zero
1033 0 : fzerf=zero
1034 : ! ion-electron term, gaussian part
1035 0 : fxgau=zero
1036 0 : fygau=zero
1037 0 : fzgau=zero
1038 :
1039 : ! Building array of coefficients of the derivative of the gaussian part
1040 0 : cprime(1)=2._dp*psppar(0,2,ityp)-psppar(0,1,ityp)
1041 0 : cprime(2)=4._dp*psppar(0,3,ityp)-psppar(0,2,ityp)
1042 0 : cprime(3)=6._dp*psppar(0,4,ityp)-psppar(0,3,ityp)
1043 0 : cprime(4)=-psppar(0,4,ityp)
1044 :
1045 : ! Determine number of local terms (HGH pot)
1046 0 : nloc=0
1047 0 : do iloc=1,4
1048 0 : if (psppar(0,iloc,ityp).ne.zero) nloc=iloc
1049 : end do
1050 :
1051 : ! Some constants depending on the atom type
1052 0 : rloc=psppar(0,0,ityp) ; rloc2=rloc**2
1053 0 : charge=real(nelpsp(ityp),kind=dp)
1054 0 : prefactor=charge/(2._dp*pi*sqrt(2._dp*pi)*rloc**5)
1055 :
1056 : ! PAW specifics
1057 0 : if (usepaw==1) then
1058 0 : msz=pawtab(ityp)%wvl%rholoc%msz
1059 0 : rad => pawtab(ityp)%wvl%rholoc%rad(1:msz)
1060 0 : vloc => pawtab(ityp)%wvl%rholoc%d(1:msz,3)
1061 0 : d2vloc => pawtab(ityp)%wvl%rholoc%d(1:msz,4)
1062 0 : rzero=rad(1);if (rad(1)<=1.d-10) rzero=rad(2)
1063 : end if
1064 :
1065 : ! Maximum extension of the gaussian
1066 0 : cutoff=10._dp*rloc
1067 0 : isx=floor((rx-cutoff)/hxh)
1068 0 : isy=floor((ry-cutoff)/hyh)
1069 0 : isz=floor((rz-cutoff)/hzh)
1070 0 : iex=ceiling((rx+cutoff)/hxh)
1071 0 : iey=ceiling((ry+cutoff)/hyh)
1072 0 : iez=ceiling((rz+cutoff)/hzh)
1073 :
1074 : ! Calculate the forces near the atom due to the gaussian
1075 : ! and error function parts of the potential
1076 0 : do i3=isz,iez
1077 0 : z=real(i3,kind=dp)*hzh-rz
1078 0 : call ind_positions_mklocl(perz,i3,n3,j3,goz)
1079 0 : if(fftn3_distrib(j3)==iproc) then
1080 0 : i3loc=ffti3_local(j3)
1081 0 : do i2=isy,iey
1082 0 : y=real(i2,kind=dp)*hyh-ry
1083 0 : call ind_positions_mklocl(pery,i2,n2,j2,goy)
1084 0 : do i1=isx,iex
1085 0 : x=real(i1,kind=dp)*hxh-rx
1086 0 : call ind_positions_mklocl(perx,i1,n1,j1,gox)
1087 :
1088 0 : if (goz.and.goy.and.gox) then
1089 0 : ind=j1+(j2-1)*n1+(i3loc-1)*n1*n2
1090 0 : x=(gridcart(1,ind)-rx)
1091 0 : y=(gridcart(2,ind)-ry)
1092 0 : z=(gridcart(3,ind)-rz)
1093 0 : r2=x**2+y**2+z**2
1094 0 : xp=exp(-0.5_dp*r2/rloc**2)
1095 :
1096 : ! Short range part
1097 0 : rhoel=rho(ind)
1098 : ! HGH: V_S^prime=gaussian
1099 0 : if (usepaw==0) then
1100 0 : if (nloc/=0) then
1101 0 : arg=r2/rloc**2
1102 0 : tt=cprime(nloc)
1103 0 : do iloc=nloc-1,1,-1
1104 0 : tt=arg*tt+cprime(iloc)
1105 : end do
1106 0 : forceloc=xp*tt*rhoel
1107 : else
1108 : forceloc=zero
1109 : end if
1110 : ! PAW: V_PAW^prime-V_L^prime
1111 : else
1112 0 : rr(1)=sqrt(r2)
1113 0 : if (rr(1)>=rzero) then
1114 0 : call paw_splint_der(msz,rad,vloc,d2vloc,1,rr,dvpawdr)
1115 0 : call calcdVloc_mklocl(dvhgh,rr(1),rloc,charge)
1116 0 : forceloc=rhoel*rloc2*(dvpawdr(1)-dvhgh)/rr(1)
1117 : else
1118 0 : forceloc=rhoel*rloc2*dvloc_zero_mklocl(charge,rloc,msz,rad,vloc,d2vloc)
1119 : end if
1120 : end if
1121 :
1122 0 : fxgau=fxgau+forceloc*x
1123 0 : fygau=fygau+forceloc*y
1124 0 : fzgau=fzgau+forceloc*z
1125 :
1126 : ! Long range part: error function
1127 0 : Vel=pot(ind)
1128 0 : fxerf=fxerf+xp*Vel*x
1129 0 : fyerf=fyerf+xp*Vel*y
1130 0 : fzerf=fzerf+xp*Vel*z
1131 :
1132 0 : else if (nloc>0) then
1133 0 : r2=x**2+y**2+z**2
1134 0 : arg=r2/rloc**2
1135 0 : xp=exp(-0.5_dp*arg)
1136 0 : tt=cprime(nloc)
1137 0 : do iloc=nloc-1,1,-1
1138 0 : tt=arg*tt+cprime(iloc)
1139 : end do
1140 0 : forceleaked=forceleaked+xp*(1._dp+tt)
1141 : end if
1142 : end do
1143 : end do
1144 : end if
1145 : end do
1146 :
1147 : ! Final result of the forces
1148 0 : floc(1,iat)=(hxh*hyh*hzh*prefactor)*fxerf+(hxh*hyh*hzh/rloc**2)*fxgau
1149 0 : floc(2,iat)=(hxh*hyh*hzh*prefactor)*fyerf+(hxh*hyh*hzh/rloc**2)*fygau
1150 0 : floc(3,iat)=(hxh*hyh*hzh*prefactor)*fzerf+(hxh*hyh*hzh/rloc**2)*fzgau
1151 :
1152 : end do
1153 :
1154 0 : forceleaked=forceleaked*prefactor*hxh*hyh*hzh
1155 0 : if (iproc.eq.0) write(std_out,'(a,1pe12.5)') 'done. Leaked force: ',forceleaked
1156 :
1157 : CONTAINS
1158 : !!***
1159 :
1160 : !----------------------------------------------------------------------
1161 :
1162 : !!****f* mklocl_realspace/calcdVloc_mklocl
1163 : !! NAME
1164 : !! calcdVloc_mklocl
1165 : !!
1166 : !! FUNCTION
1167 : !! Compute 1st-derivative of long-range HGH local ionic potential (derf)
1168 : !!
1169 : !! INPUTS
1170 : !!
1171 : !! OUTPUT
1172 : !!
1173 : !! SOURCE
1174 :
1175 0 : subroutine calcdVloc_mklocl(yy,xx,rloc,Z)
1176 :
1177 : !Arguments ------------------------------------
1178 : !scalars
1179 : real(dp),intent(in) :: xx,rloc,Z
1180 : real(dp),intent(out) :: yy
1181 :
1182 : !Local variables-------------------------------
1183 : !scalars
1184 : real(dp):: arg,tt
1185 :
1186 : ! *************************************************************************
1187 :
1188 0 : arg=xx/(sqrt(2._dp)*rloc)
1189 0 : call derf_ab(tt,arg)
1190 0 : yy=(Z/(xx**2))* ( tt - 2._dp/sqrt(pi)*arg*exp(-arg**2) )
1191 :
1192 0 : end subroutine calcdVloc_mklocl
1193 : !!***
1194 :
1195 : !----------------------------------------------------------------------
1196 :
1197 : !!****f* mklocl_wavelets/dvloc_zero_mklocl
1198 : !! NAME
1199 : !! dvloc_zero_mklocl
1200 : !!
1201 : !! FUNCTION
1202 : !! Use a quadratic interpolation to get limit of (1/x).dVloc(x)/dx at x->0
1203 : !!
1204 : !! INPUTS
1205 : !!
1206 : !! OUTPUT
1207 : !!
1208 : !! SOURCE
1209 :
1210 0 : function dvloc_zero_mklocl(charge,rloc,msz,rad,vloc,d2vloc)
1211 :
1212 :
1213 : !Arguments ------------------------------------
1214 : !scalars
1215 : integer,intent(in) :: msz
1216 : real(dp) :: dvloc_zero_mklocl
1217 : real(dp),intent(in) :: charge,rloc
1218 : !arrays
1219 : real(dp) :: rad(msz),vloc(msz),d2vloc(msz)
1220 :
1221 : !Local variables-------------------------------
1222 : !scalars
1223 : real(dp) :: y1,y2,y3,zz=0._dp
1224 : !arrays
1225 : real(dp) :: ll(3),xx(3),yy(3)
1226 :
1227 : ! *************************************************************************
1228 :
1229 : !Select 3 points x1,x2,x3 near 0
1230 0 : if (rad(1)>1.d-10) then
1231 0 : xx(1:3)=rad(1:3)
1232 : else
1233 0 : xx(1:3)=rad(2:4)
1234 : end if
1235 :
1236 : !Find the corresponding values of y=(V^PAW(x)-V^HGH(x))/x
1237 0 : call paw_splint_der(msz,rad,vloc,d2vloc,3,xx,yy)
1238 0 : call calcdVloc_mklocl(y1,xx(1),rloc,charge)
1239 0 : call calcdVloc_mklocl(y2,xx(2),rloc,charge)
1240 0 : call calcdVloc_mklocl(y3,xx(3),rloc,charge)
1241 0 : yy(1)=(yy(1)-y1)/xx(1)
1242 0 : yy(2)=(yy(2)-y2)/xx(2)
1243 0 : yy(3)=(yy(3)-y3)/xx(3)
1244 :
1245 : !Find a polynomial of the form (z=0):
1246 : !P(z) = y1.L1(z) + y2.L2(z) + y3.L3(z)
1247 :
1248 : !L1(z) = (z-x2)(z-x3)/((x1-x2)(x1-x3))
1249 0 : ll(1)=(zz-xx(2))*(zz-xx(3))/((xx(1)-xx(2))*(xx(1)-xx(3)))
1250 : !L2(z) = (z-x1)(z-x3)/((x2-x1)(x2-x3))
1251 0 : ll(2)=(zz-xx(1))*(zz-xx(3))/((xx(2)-xx(1))*(xx(2)-xx(3)))
1252 : !L3(z) = (z-x1)(z-x2)/((x3-x1)(x3-x2))
1253 0 : ll(3)=(zz-xx(1))*(zz-xx(2))/((xx(3)-xx(1))*(xx(3)-xx(2)))
1254 :
1255 0 : dvloc_zero_mklocl=yy(1)*ll(1)+yy(2)*ll(2)+yy(3)*ll(3)
1256 :
1257 0 : end function dvloc_zero_mklocl
1258 : !!***
1259 :
1260 : end subroutine local_forces_new
1261 : !!***
1262 :
1263 : !----------------------------------------------------------------------
1264 :
1265 : !!****f* mklocl_realspace/ind_positions_mklocl
1266 : !! NAME
1267 : !! ind_positions_mklocl
1268 : !!
1269 : !! FUNCTION
1270 : !! determine the index in which the potential must be inserted, following the BC
1271 : !! determine also whether the index is inside or outside the box for free BC
1272 : !!
1273 : !! INPUTS
1274 : !!
1275 : !! OUTPUT
1276 : !!
1277 : !! SOURCE
1278 :
1279 0 : subroutine ind_positions_mklocl(periodic,i,n,j,go)
1280 :
1281 :
1282 : !Arguments -------------------------------
1283 : logical, intent(in) :: periodic
1284 : integer, intent(in) :: i,n
1285 : logical, intent(out) :: go
1286 : integer, intent(out) :: j
1287 :
1288 : ! *********************************************************************
1289 :
1290 0 : if (periodic) then
1291 0 : go=.true.
1292 0 : j=modulo(i-1,n)+1
1293 : else
1294 0 : j=i
1295 0 : go=(i >= 1 .and. i <= n)
1296 : end if
1297 :
1298 0 : end subroutine ind_positions_mklocl
1299 : !!***
1300 :
1301 : !!****f* ABINIT/mklocl_wavelets
1302 : !!
1303 : !! NAME
1304 : !! mklocl_wavelets
1305 : !!
1306 : !! FUNCTION
1307 : !! Compute the ionic local potential when the pseudo-potentials are GTH, using
1308 : !! the special decomposition of these pseudo. The resulting potential is computed with
1309 : !! free boundary conditions. It gives the same result than mklocl_realspace for the
1310 : !! GTH pseudo only with a different way to compute the potential.
1311 : !!
1312 : !! Optionally compute :
1313 : !! option=1 : local ionic potential throughout unit cell
1314 : !! option=2 : contribution of local ionic potential to E gradient wrt xred
1315 : !!
1316 : !! INPUTS
1317 : !! efield (3)=external electric field
1318 : !! mpi_enreg=information about MPI parallelization
1319 : !! natom=number of atoms
1320 : !! nfft=size of vpsp (local potential)
1321 : !! nspden=number of spin-density components
1322 : !! option=type of calculation (potential, forces, ...)
1323 : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
1324 : !! xcart(3,natom)=cartesian atomic coordinates.
1325 : !! wvl_den=density-potential BigDFT object
1326 : !! wvl_descr=wavelet BigDFT object
1327 : !!
1328 : !! OUTPUT
1329 : !! (if option==1) vpsp(nfft)=the potential resulting from the ionic
1330 : !! density of charge.
1331 : !! (if option==2) grtn(3,natom)=grads of Etot wrt tn. These gradients are in
1332 : !! reduced coordinates. Multiply them by rprimd to get
1333 : !! gradients in cartesian coordinates.
1334 : !!
1335 : !! SOURCE
1336 :
1337 0 : subroutine mklocl_wavelets(efield, grtn, mpi_enreg, natom, nfft, &
1338 0 : & nspden, option, rprimd, vpsp, wvl_den, wvl_descr, xcart)
1339 :
1340 : use defs_wvltypes
1341 : #if defined HAVE_BIGDFT
1342 : use BigDFT_API, only : ELECTRONIC_DENSITY,createIonicPotential,local_forces
1343 : use poisson_solver, only : H_potential
1344 : #endif
1345 :
1346 : !Arguments ------------------------------------
1347 : !scalars
1348 : integer,intent(in) :: option, natom, nfft, nspden
1349 : type(MPI_type),intent(in) :: mpi_enreg
1350 : type(wvl_denspot_type), intent(inout) :: wvl_den
1351 : type(wvl_internal_type), intent(in) :: wvl_descr
1352 : !arrays
1353 : real(dp),intent(in) :: rprimd(3,3),efield(3)
1354 : real(dp),intent(inout) :: grtn(3,natom)
1355 : real(dp), intent(inout) :: vpsp(nfft)
1356 : real(dp),intent(inout) :: xcart(3,natom)
1357 :
1358 : !Local variables-------------------------------
1359 : #if defined HAVE_BIGDFT
1360 : !scalars
1361 : integer :: i,i1,i2,i3,ia,ierr,igeo,me,nproc,shift,comm
1362 : real(dp) :: energ
1363 : character(len=500) :: message
1364 : !arrays
1365 : real(dp) :: epot(3)
1366 : real(dp) :: elecfield(3)=(/zero,zero,zero/) ! Not used here
1367 : real(dp),allocatable :: gxyz(:,:),vhartr(:),rhov(:,:)
1368 : #endif
1369 :
1370 : ! *********************************************************************
1371 :
1372 : #if defined HAVE_BIGDFT
1373 :
1374 : elecfield=zero !not used here
1375 :
1376 : !Manage parallelism
1377 : comm=mpi_enreg%comm_wvl
1378 : nproc=xmpi_comm_size(comm)
1379 : me=xmpi_comm_rank(comm)
1380 :
1381 : !----------------------------------------------------------------------
1382 : ! ----- Option 1: compute local ionic potential -----
1383 : !----------------------------------------------------------------------
1384 : if (option == 1) then
1385 :
1386 : ! We get the kernel for the Poisson solver (used to go from the ionic
1387 : ! charge to the potential).If the kernel is uncomputed, it does it now.
1388 : ! call psolver_kernel(wvl_den%denspot%dpbox%hgrids, 2, icoulomb, me, kernel, &
1389 : !& comm, wvl_den%denspot%dpbox%ndims, nproc, nscforder)
1390 : ! if (.not.associated(kernel%co%kernel)) then
1391 : ! call psolver_kernel(wvl_den%denspot%dpbox%hgrids, 1, icoulomb, me, kernel, &
1392 : !& comm, wvl_den%denspot%dpbox%ndims, nproc, nscforder)
1393 : ! end if
1394 :
1395 : message=ch10//' mklocl_wavelets: Create local potential from ions.'
1396 : call wrtout(std_out,message,'COLL')
1397 :
1398 : shift = 1 + wvl_den%denspot%dpbox%ndims(1) * wvl_den%denspot%dpbox%ndims(2) &
1399 : & * wvl_den%denspot%dpbox%i3xcsh
1400 :
1401 : ! Call the BigDFT routine
1402 : call createIonicPotential(wvl_descr%atoms%astruct%geocode, me, nproc, (me == 0), wvl_descr%atoms, &
1403 : & xcart, wvl_den%denspot%dpbox%hgrids(1), wvl_den%denspot%dpbox%hgrids(2), &
1404 : & wvl_den%denspot%dpbox%hgrids(3), &
1405 : & elecfield, wvl_descr%Glr%d%n1, wvl_descr%Glr%d%n2, wvl_descr%Glr%d%n3, &
1406 : & wvl_den%denspot%dpbox%n3pi, wvl_den%denspot%dpbox%i3s + wvl_den%denspot%dpbox%i3xcsh, &
1407 : & wvl_den%denspot%dpbox%ndims(1), wvl_den%denspot%dpbox%ndims(2), &
1408 : & wvl_den%denspot%dpbox%ndims(3), wvl_den%denspot%pkernel, vpsp(shift), 0.d0,wvl_descr%rholoc)
1409 :
1410 : ! Copy vpsp into bigdft object:
1411 : call wvl_rhov_abi2big(1,vpsp,wvl_den%denspot%v_ext,shift=(shift-1))
1412 :
1413 : ! Eventually add the electric field
1414 : if (maxval(efield) > tol12) then
1415 : message=ch10//'mklocl_wavelets: Add the electric field.'
1416 : call wrtout(std_out,message,'COLL')
1417 : ! We add here the electric field since in BigDFT, the field must be on x...
1418 : epot(:) = real(0.5, dp) * efield(:) * wvl_den%denspot%dpbox%hgrids(:)
1419 : do i3 = 1, wvl_den%denspot%dpbox%n3pi, 1
1420 : ia = (i3 - 1) * wvl_den%denspot%dpbox%ndims(1) * wvl_den%denspot%dpbox%ndims(2)
1421 : do i2 = -14, 2 * wvl_descr%Glr%d%n2 + 16, 1
1422 : i = ia + (i2 + 14) * wvl_den%denspot%dpbox%ndims(1)
1423 : do i1 = -14, 2 * wvl_descr%Glr%d%n1 + 16, 1
1424 : i = i + 1
1425 : vpsp(shift + i) = vpsp(shift + i) + &
1426 : & epot(1) * real(i1 - wvl_descr%Glr%d%n1, dp) + &
1427 : & epot(2) * real(i2 - wvl_descr%Glr%d%n2, dp) + &
1428 : & epot(3) * real(i3 - wvl_descr%Glr%d%n3, dp)
1429 : end do
1430 : end do
1431 : end do
1432 : end if
1433 :
1434 : !----------------------------------------------------------------------
1435 : ! ----- Option 2: compute forces induced by local ionic potential -----
1436 : !----------------------------------------------------------------------
1437 : else if (option == 2) then
1438 :
1439 : message=ch10//' mklocl_wavelets: compute local forces.'
1440 : call wrtout(std_out,message,'COLL')
1441 :
1442 : if (wvl_den%denspot%rhov_is/=ELECTRONIC_DENSITY) then
1443 : message='denspot bigdft datstructure should contain rhor!'
1444 : ABI_BUG(message)
1445 : end if
1446 :
1447 : ! Extract density rhor from bigDFT datastructure
1448 : ABI_MALLOC(rhov,(nfft, nspden))
1449 : ABI_MALLOC(vhartr,(nfft))
1450 : rhov=zero ; vhartr=zero
1451 : shift = wvl_den%denspot%dpbox%ndims(1) * wvl_den%denspot%dpbox%ndims(2) &
1452 : & * wvl_den%denspot%dpbox%i3xcsh
1453 : do i = 1, min(nfft,size(wvl_den%denspot%rhov)-shift)
1454 : rhov(i, 1) = wvl_den%denspot%rhov(i + shift)
1455 : vhartr(i) = wvl_den%denspot%rhov(i + shift)
1456 : end do
1457 : if (nspden == 2) then
1458 : shift = shift + wvl_den%denspot%dpbox%ndims(1) * wvl_den%denspot%dpbox%ndims(2) &
1459 : & * wvl_den%denspot%dpbox%n3d
1460 : do i = 1, min(nfft,size(wvl_den%denspot%rhov)-shift)
1461 : rhov(i, 2) = wvl_den%denspot%rhov(i + shift)
1462 : vhartr(i) = vhartr(i) + wvl_den%denspot%rhov(i + shift)
1463 : end do
1464 : end if
1465 :
1466 : ! Compute Hartree potential from rhor
1467 : call H_potential('D',wvl_den%denspot%pkernel,vhartr,vhartr,energ,zero,.false.)
1468 :
1469 : ! Allocate temporary array for forces
1470 : ABI_MALLOC(gxyz,(3, natom))
1471 :
1472 : ! Calculate local part of the forces grtn (modified BigDFT routine)
1473 : call local_forces_wvl(me,natom,xcart,&
1474 : & wvl_den%denspot%dpbox%hgrids(1),&
1475 : & wvl_den%denspot%dpbox%hgrids(2),&
1476 : & wvl_den%denspot%dpbox%hgrids(3),&
1477 : & wvl_descr%Glr%d%n1,wvl_descr%Glr%d%n2,wvl_descr%Glr%d%n3,&
1478 : & wvl_den%denspot%dpbox%n3p,&
1479 : & wvl_den%denspot%dpbox%i3s+wvl_den%denspot%dpbox%i3xcsh,&
1480 : & wvl_den%denspot%dpbox%ndims(1),wvl_den%denspot%dpbox%ndims(2),&
1481 : & rhov,vhartr,gxyz,wvl_descr)
1482 : ! call local_forces(me, wvl_descr%atoms, xcart, &
1483 : ! & wvl_den%denspot%dpbox%hgrids(1), wvl_den%denspot%dpbox%hgrids(2), &
1484 : ! & wvl_den%denspot%dpbox%hgrids(3), &
1485 : ! & wvl_descr%Glr%d%n1, wvl_descr%Glr%d%n2, wvl_descr%Glr%d%n3, &
1486 : ! & wvl_den%denspot%dpbox%n3p, wvl_den%denspot%dpbox%i3s + wvl_den%denspot%dpbox%i3xcsh, &
1487 : ! & wvl_den%denspot%dpbox%ndims(1), wvl_den%denspot%dpbox%ndims(2), &
1488 : ! & rhov, vhartr,gxyz,locstrten,charge)
1489 :
1490 : ! Pending: floc,locstrten and charge are not used here.
1491 : ! Pending: put mpi_enreg%nscatterarr... in object denspot, initialize object, etc.
1492 :
1493 : if (nproc > 1) then
1494 : call xmpi_sum(gxyz, comm, ierr)
1495 : end if
1496 :
1497 : ! Forces should be in reduced coordinates.
1498 : do ia = 1, natom, 1
1499 : do igeo = 1, 3, 1
1500 : grtn(igeo, ia) = - rprimd(1, igeo) * gxyz(1, ia) &
1501 : & - rprimd(2, igeo) * gxyz(2, ia) &
1502 : & - rprimd(3, igeo) * gxyz(3, ia)
1503 : end do
1504 : end do
1505 :
1506 : ! Deallocate local variables
1507 : ABI_FREE(vhartr)
1508 : ABI_FREE(rhov)
1509 : ABI_FREE(gxyz)
1510 :
1511 : !----------------------------------------------------------------------
1512 :
1513 : else ! option switch
1514 : message = 'Internal error, option should be 1 or 2!'
1515 : ABI_ERROR(message)
1516 : end if
1517 :
1518 : #else
1519 0 : BIGDFT_NOTENABLED_ERROR()
1520 : if (.false.) write(std_out,*) option,natom,nfft,nspden,mpi_enreg%me,&
1521 : & wvl_den%symObj,wvl_descr%h(1),rprimd(1,1),efield(1),grtn(1,1),vpsp(1),xcart(1,1)
1522 : #endif
1523 :
1524 0 : end subroutine mklocl_wavelets
1525 : !!***
1526 :
1527 : !----------------------------------------------------------------------
1528 :
1529 : !!****f* mklocl_wavelets/local_forces_wvl
1530 : !! NAME
1531 : !! local_forces_wvl
1532 : !!
1533 : !! FUNCTION
1534 : !!
1535 : !! INPUTS
1536 : !! hxh,hyh,hzh=wavelet grid spacings
1537 : !! iproc=current MPI process number
1538 : !! n1,n2,n3=number of wavelet points in each direction
1539 : !! n1i,n2i=size of intermediate xy wvl grid
1540 : !! n3pi=number of xy wvl planes handled by current MPI process
1541 : !! i3s=starting index of local potential for current MPI process
1542 : !! natom=number of atoms
1543 : !! pot(*)=Hartree ionic potential
1544 : !! rho(*)=electronic density
1545 : !! rxyz(3,natom)=cartesian coordinates of atoms
1546 : !! wvl=wavelet BigDFT object
1547 : !!
1548 : !! OUTPUT
1549 : !! floc(3,natom)=local ionic potential contribution to forces
1550 : !!
1551 : !! SOURCE
1552 :
1553 : subroutine local_forces_wvl(iproc,natom,rxyz,hxh,hyh,hzh,n1,n2,n3,n3pi,i3s,n1i,n2i,&
1554 : & rho,pot,floc,wvl)
1555 :
1556 : use defs_wvltypes
1557 : #if defined HAVE_BIGDFT
1558 : use BigDFT_API, only : PSPCODE_PAW,ind_positions
1559 : #endif
1560 :
1561 : !Arguments -------------------------------
1562 : !scalars
1563 : integer,intent(in) :: i3s,iproc,n1,n1i,n2,n2i,n3,n3pi,natom
1564 : real(dp),intent(in) :: hxh,hyh,hzh
1565 : type(wvl_internal_type),intent(in) :: wvl
1566 : !arrays
1567 : real(dp),intent(in) :: rxyz(3,natom)
1568 : real(dp),dimension(*),intent(in) :: rho,pot
1569 : real(dp),intent(out) :: floc(3,natom)
1570 :
1571 : !Local variables -------------------------
1572 : #if defined HAVE_BIGDFT
1573 : !scalars
1574 : integer :: i1,i2,i3,iat,iex,iey,iez,iloc,ind,isx,isy,isz,ityp
1575 : integer :: j1,j2,j3,msz=0
1576 : integer :: nbl1,nbr1,nbl2,nbr2,nbl3,nbr3,nloc
1577 : logical :: perx,pery,perz,gox,goy,goz,USE_PAW
1578 : real(dp) :: arg,charge,cutoff,dvhgh,forceloc,fxerf,fyerf,fzerf,fxgau,fygau,fzgau
1579 : real(dp) :: forceleaked,prefactor,r2,rhoel,rloc,rloc2,rx,ry,rz,rzero,tt,vel,x,xp,y,z
1580 : !arrays
1581 : real(dp) :: cprime(4),dvpawdr(1),rr(1)
1582 : real(dp),pointer :: psppar(:,:),rad(:),vloc(:),d2vloc(:)
1583 : #endif
1584 :
1585 : ! *********************************************************************
1586 :
1587 : #if defined HAVE_BIGDFT
1588 :
1589 : if (iproc==0) write(std_out,'(a)',advance='no') ' Calculate local forces...'
1590 :
1591 : !PAW or NCPP ?
1592 : USE_PAW=any(wvl%atoms%npspcode==PSPCODE_PAW)
1593 :
1594 : !Conditions for periodicity in the three directions
1595 : perx=(wvl%atoms%astruct%geocode /= 'F')
1596 : pery=(wvl%atoms%astruct%geocode == 'P')
1597 : perz=(wvl%atoms%astruct%geocode /= 'F')
1598 : call ext_buffers(perx,nbl1,nbr1)
1599 : call ext_buffers(pery,nbl2,nbr2)
1600 : call ext_buffers(perz,nbl3,nbr3)
1601 :
1602 : forceleaked=zero
1603 :
1604 : do iat=1,natom
1605 : ityp=wvl%atoms%astruct%iatype(iat)
1606 :
1607 : ! Coordinates of the center
1608 : rx=rxyz(1,iat)
1609 : ry=rxyz(2,iat)
1610 : rz=rxyz(3,iat)
1611 :
1612 : ! Initialization of the forces
1613 : ! ion-electron term, error function part
1614 : fxerf=zero
1615 : fyerf=zero
1616 : fzerf=zero
1617 : ! ion-electron term, gaussian part
1618 : fxgau=zero
1619 : fygau=zero
1620 : fzgau=zero
1621 :
1622 : ! Building array of coefficients of the derivative of the gaussian part
1623 : psppar => wvl%atoms%psppar(:,:,ityp)
1624 : cprime(1)=2._dp*wvl%atoms%psppar(0,2,ityp)-wvl%atoms%psppar(0,1,ityp)
1625 : cprime(2)=4._dp*wvl%atoms%psppar(0,3,ityp)-wvl%atoms%psppar(0,2,ityp)
1626 : cprime(3)=6._dp*wvl%atoms%psppar(0,4,ityp)-wvl%atoms%psppar(0,3,ityp)
1627 : cprime(4)=-wvl%atoms%psppar(0,4,ityp)
1628 :
1629 : ! Determine number of local terms (HGH pot)
1630 : nloc=0
1631 : do iloc=1,4
1632 : if (wvl%atoms%psppar(0,iloc,ityp).ne.zero) nloc=iloc
1633 : end do
1634 :
1635 : ! Some constants depending on the atom type
1636 : rloc=wvl%atoms%psppar(0,0,ityp) ; rloc2=rloc**2
1637 : charge=real(wvl%atoms%nelpsp(ityp),kind=dp)
1638 : prefactor=charge/(2._dp*pi*sqrt(2._dp*pi)*rloc**5)
1639 :
1640 : ! PAW specifics
1641 : if (USE_PAW) then
1642 : msz=wvl%rholoc%msz(ityp)
1643 : rad => wvl%rholoc%rad(1:msz,ityp)
1644 : vloc => wvl%rholoc%d(1:msz,3,ityp)
1645 : d2vloc => wvl%rholoc%d(1:msz,4,ityp)
1646 : rzero=rad(1);if (rzero<=1.d-10) rzero=rad(2)
1647 : end if
1648 :
1649 : ! Maximum extension of the gaussian
1650 : cutoff=10._dp*rloc
1651 : isx=floor((rx-cutoff)/hxh)
1652 : isy=floor((ry-cutoff)/hyh)
1653 : isz=floor((rz-cutoff)/hzh)
1654 : iex=ceiling((rx+cutoff)/hxh)
1655 : iey=ceiling((ry+cutoff)/hyh)
1656 : iez=ceiling((rz+cutoff)/hzh)
1657 :
1658 : ! Calculate the forces near the atom due to the gaussian
1659 : ! and error function parts of the potential
1660 : if (n3pi>0) then
1661 : do i3=isz,iez
1662 : z=real(i3,kind=dp)*hzh-rz
1663 : call ind_positions(perz,i3,n3,j3,goz)
1664 : j3=j3+nbl3+1
1665 : do i2=isy,iey
1666 : y=real(i2,kind=dp)*hyh-ry
1667 : call ind_positions(pery,i2,n2,j2,goy)
1668 : do i1=isx,iex
1669 : x=real(i1,kind=dp)*hxh-rx
1670 : call ind_positions(perx,i1,n1,j1,gox)
1671 :
1672 : r2=x**2+y**2+z**2
1673 : xp=exp(-0.5_dp*r2/rloc2)
1674 :
1675 : if ((j3>=i3s.and.j3<=i3s+n3pi-1) .and. (gox.and.goy)) then
1676 : ind=j1+1+nbl1+(j2+nbl2)*n1i+(j3-i3s+1-1)*n1i*n2i
1677 :
1678 : ! Short range part
1679 : rhoel=rho(ind)
1680 : ! HGH: V_S^prime=gaussian
1681 : if (.not.USE_PAW) then
1682 : if (nloc/=0) then
1683 : arg=r2/rloc2
1684 : tt=cprime(nloc)
1685 : do iloc=nloc-1,1,-1
1686 : tt=arg*tt+cprime(iloc)
1687 : end do
1688 : forceloc=xp*tt*rhoel
1689 : else
1690 : forceloc=zero
1691 : end if
1692 : ! PAW: V_PAW^prime-V_L^prime
1693 : else
1694 : rr(1)=sqrt(r2)
1695 :
1696 : if (rr(1)>=rzero) then
1697 : call paw_splint_der(msz,rad,vloc,d2vloc,1,rr,dvpawdr)
1698 : call calcdVloc_wvl(dvhgh,rr(1),rloc,charge)
1699 : forceloc=rhoel*rloc2*(dvpawdr(1)-dvhgh)/rr(1)
1700 : else
1701 : forceloc=rhoel*rloc2*dvloc_zero_wvl(charge,rloc,msz,rad,vloc,d2vloc)
1702 : end if
1703 : end if
1704 :
1705 : fxgau=fxgau+forceloc*x
1706 : fygau=fygau+forceloc*y
1707 : fzgau=fzgau+forceloc*z
1708 :
1709 : ! Long range part: error function
1710 : vel=pot(ind)
1711 : fxerf=fxerf+xp*vel*x
1712 : fyerf=fyerf+xp*vel*y
1713 : fzerf=fzerf+xp*vel*z
1714 :
1715 : else if ((.not.goz).and.(nloc>0)) then
1716 : arg=r2/rloc2
1717 : tt=cprime(nloc)
1718 : do iloc=nloc-1,1,-1
1719 : tt=arg*tt+cprime(iloc)
1720 : end do
1721 : forceleaked=forceleaked+prefactor*xp*tt*rho(1)
1722 : end if
1723 :
1724 : end do ! i1
1725 : end do ! i2
1726 : end do ! i3
1727 : end if ! n3pi>0
1728 :
1729 : ! Final result of the forces
1730 : floc(1,iat)=(hxh*hyh*hzh*prefactor)*fxerf+(hxh*hyh*hzh/rloc2)*fxgau
1731 : floc(2,iat)=(hxh*hyh*hzh*prefactor)*fyerf+(hxh*hyh*hzh/rloc2)*fygau
1732 : floc(3,iat)=(hxh*hyh*hzh*prefactor)*fzerf+(hxh*hyh*hzh/rloc2)*fzgau
1733 :
1734 : end do ! iat
1735 :
1736 : forceleaked=forceleaked*hxh*hyh*hzh
1737 : if (iproc.eq.0) write(std_out,'(a,1pe12.5)') 'done. Leaked force: ',forceleaked
1738 :
1739 : #else
1740 : BIGDFT_NOTENABLED_ERROR()
1741 : if (.false.) write(std_out,*) i3s,iproc,n1,n1i,n2,n2i,n3,n3pi,natom,hxh,hyh,hzh,&
1742 : & rxyz(1,1),floc(1,1),rho(1),pot(1),wvl%h(1)
1743 : #endif
1744 :
1745 : CONTAINS
1746 : !!***
1747 :
1748 : !----------------------------------------------------------------------
1749 :
1750 : !!****f* mklocl_wavelets/calcdVloc_wvl
1751 : !! NAME
1752 : !! calcdVloc_wvl
1753 : !!
1754 : !! FUNCTION
1755 : !! Compute 1st-derivative of long-range HGH local ionic potential (derf)
1756 : !!
1757 : !! INPUTS
1758 : !!
1759 : !! OUTPUT
1760 : !!
1761 : !! SOURCE
1762 :
1763 : subroutine calcdVloc_wvl(yy,xx,rloc,Z)
1764 :
1765 : !Arguments ------------------------------------
1766 : !scalars
1767 : real(dp),intent(in) :: xx,rloc,Z
1768 : real(dp),intent(out) :: yy
1769 :
1770 : !Local variables-------------------------------
1771 : !scalars
1772 : real(dp):: arg,tt
1773 :
1774 : ! *************************************************************************
1775 :
1776 : arg=xx/(sqrt(2._dp)*rloc)
1777 : call derf_ab(tt,arg)
1778 : yy=(Z/(xx**2))* ( tt - 2._dp/sqrt(pi)*arg*exp(-arg**2) )
1779 :
1780 : end subroutine calcdVloc_wvl
1781 : !!***
1782 :
1783 : !----------------------------------------------------------------------
1784 :
1785 : !!****f* mklocl_wavelets/dvloc_zero_wvl
1786 : !! NAME
1787 : !! dvloc_zero_wvl
1788 : !!
1789 : !! FUNCTION
1790 : !! Use a quadratic interpolation to get limit of (1/x).dVloc(x)/dx at x->0
1791 : !!
1792 : !! INPUTS
1793 : !!
1794 : !! OUTPUT
1795 : !!
1796 : !! SOURCE
1797 :
1798 : function dvloc_zero_wvl(charge,rloc,msz,rad,vloc,d2vloc)
1799 :
1800 :
1801 : !Arguments ------------------------------------
1802 : !scalars
1803 : integer,intent(in) :: msz
1804 : real(dp) :: dvloc_zero_wvl
1805 : real(dp),intent(in) :: charge,rloc
1806 : !arrays
1807 : real(dp) :: rad(msz),vloc(msz),d2vloc(msz)
1808 :
1809 : !Local variables-------------------------------
1810 : !scalars
1811 : real(dp) :: y1,y2,y3,zz=0._dp
1812 : !arrays
1813 : real(dp) :: ll(3),xx(3),yy(3)
1814 :
1815 : ! *************************************************************************
1816 :
1817 : !Select 3 points x1,x2,x3 near 0
1818 : if (rad(1)>1.d-10) then
1819 : xx(1:3)=rad(1:3)
1820 : else
1821 : xx(1:3)=rad(2:4)
1822 : end if
1823 :
1824 : !Find the corresponding values of y=(V^PAW(x)-V^HGH(x))/x
1825 : call paw_splint_der(msz,rad,vloc,d2vloc,3,xx,yy)
1826 : call calcdVloc_wvl(y1,xx(1),rloc,charge)
1827 : call calcdVloc_wvl(y2,xx(2),rloc,charge)
1828 : call calcdVloc_wvl(y3,xx(3),rloc,charge)
1829 : yy(1)=(yy(1)-y1)/xx(1)
1830 : yy(2)=(yy(2)-y2)/xx(2)
1831 : yy(3)=(yy(3)-y3)/xx(3)
1832 :
1833 : !Find a polynomial of the form (z=0):
1834 : !P(z) = y1.L1(z) + y2.L2(z) + y3.L3(z)
1835 :
1836 : !L1(z) = (z-x2)(z-x3)/((x1-x2)(x1-x3))
1837 : ll(1)=(zz-xx(2))*(zz-xx(3))/((xx(1)-xx(2))*(xx(1)-xx(3)))
1838 : !L2(z) = (z-x1)(z-x3)/((x2-x1)(x2-x3))
1839 : ll(2)=(zz-xx(1))*(zz-xx(3))/((xx(2)-xx(1))*(xx(2)-xx(3)))
1840 : !L3(z) = (z-x1)(z-x2)/((x3-x1)(x3-x2))
1841 : ll(3)=(zz-xx(1))*(zz-xx(2))/((xx(3)-xx(1))*(xx(3)-xx(2)))
1842 :
1843 : dvloc_zero_wvl=yy(1)*ll(1)+yy(2)*ll(2)+yy(3)*ll(3)
1844 :
1845 : end function dvloc_zero_wvl
1846 : !!***
1847 :
1848 : end subroutine local_forces_wvl
1849 : !!***
1850 :
1851 : end module m_mklocl_realspace
1852 : !!***
|