Branch data Line data Source code
1 : : !!****m* ABINIT/m_barevcoul
2 : : !! NAME
3 : : !! m_barevcoul
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 1999-2026 ABINIT group ()
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.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_barevcoul
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_errors
27 : : use m_xmpi
28 : :
29 : : use m_fstrings, only : sjoin
30 : : use defs_abitypes, only : MPI_type
31 : : use m_numeric_tools, only : arth, l2norm, OPERATOR(.x.)
32 : : use m_geometry, only : normv
33 : : use m_crystal, only : crystal_t
34 : : use m_fft, only : zerosym
35 : : !use m_gsphere, only : gsphere_t
36 : :
37 : : ! Cut-off methods modules
38 : : !use m_cutoff_sphere, only : cutoff_sphere
39 : : !use m_cutoff_slab, only : cutoff_slab
40 : : !use m_cutoff_cylinder, only : cutoff_cylinder
41 : :
42 : : implicit none
43 : :
44 : : private
45 : : !!***
46 : :
47 : : !!****t* m_barevcoul/vcut_t
48 : : !! NAME
49 : : !! vcoul_t
50 : : !!
51 : : !! FUNCTION
52 : : !!
53 : : !! SOURCE
54 : :
55 : : type,public :: vcut_t
56 : :
57 : : integer :: nfft
58 : : ! Number of points in FFT grid
59 : :
60 : : integer :: ng
61 : : ! Number of G-vectors
62 : :
63 : : real(dp) :: alpha(3)
64 : : ! Lenght of the finite slab
65 : :
66 : : real(dp) :: rcut
67 : : ! Cutoff radius
68 : :
69 : : real(dp) :: i_sz
70 : : ! Value of the integration of the Coulomb singularity 4\pi/V_BZ \int_BZ d^3q 1/q^2
71 : :
72 : : real(dp) :: hcyl
73 : : ! Length of the finite cylinder along the periodic dimension
74 : :
75 : : real(dp) :: ucvol
76 : : ! Volume of the unit cell
77 : :
78 : : character(len=50) :: mode
79 : : ! String defining the cutoff mode, possible values are: sphere,cylinder,slab,crystal
80 : :
81 : : integer :: pdir(3)
82 : : ! 1 if the system is periodic along this direction
83 : :
84 : : real(dp) :: boxcenter(3)
85 : : ! 1 if the point in inside the cutoff region 0 otherwise
86 : : ! Reduced coordinates of the center of the box (input variable)
87 : :
88 : : real(dp) :: vcutgeo(3)
89 : : ! For each reduced direction gives the length of the finite system
90 : : ! 0 if the system is infinite along that particular direction
91 : : ! negative value to indicate that a finite size has to be used
92 : :
93 : : real(dp) :: rprimd(3,3)
94 : : ! Lattice vectors in real space.
95 : :
96 : : real(dp),allocatable :: qibz(:,:)
97 : : ! qibz(3,nqibz)
98 : : ! q-points in the IBZ.
99 : :
100 : : real(dp),allocatable :: barev(:)
101 : : ! barev(nfft)
102 : : ! Bare Coulomb potential on the FFT grid
103 : : ! A cut might be applied.
104 : :
105 : : end type vcut_t
106 : :
107 : : public :: barevcoul
108 : : !!***
109 : :
110 : : contains
111 : : !!***
112 : :
113 : : !----------------------------------------------------------------------
114 : :
115 : : !!****f* ABINIT/barevcoul
116 : : !! NAME
117 : : !! barevcoul
118 : : !!
119 : : !! FUNCTION
120 : : !! Compute bare coulomb term in G-space on the FFT mesh i.e. 4pi/(G+q)**2 for a specified q-point
121 : : !!
122 : : !! INPUTS
123 : : !! qpoint(3)=reduced coordinates for the phonon wavelength
124 : : !! gsqcut=cutoff value on G**2 for sphere inside fft box. (gsqcut=(boxcut**2)*ecut/(2.d0*(Pi**2))
125 : : !! icutcoul=Option for the Coulomb potential cutoff technique
126 : : !! gmet(3,3)=metrix tensor in G space in Bohr**-2.
127 : : !! izero=if 1, unbalanced components of V(q,g) are set to zero # Used by the PAW library
128 : : !! nfft=Total number of FFT grid points.
129 : : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
130 : : !! comm=MPI communicator.
131 : : !!
132 : : !! OUTPUT
133 : : !! barev(nfft)=4pi/(G+q)**2, q+G=0 component is set carefully
134 : : !!
135 : : !! NOTES
136 : : !! This routine operates on the full FFT mesh. DO NOT PASS MPI_TYPE
137 : : !! One can easily implemente MPI-FFT by just calling this routine and then
138 : : !! extracting the G-vectors treated by the node.
139 : : !!
140 : : !! SOURCE
141 : :
142 : 214238 : subroutine barevcoul(rcut,icutcoul,qpoint,gsqcut,gmet,nfft,nkpt_bz,ngfft,ucvol,izero,barev,shortrange)
143 : :
144 : : !Arguments ------------------------------------
145 : : !scalars
146 : : integer,intent(in) :: icutcoul,nfft,nkpt_bz,izero
147 : : real(dp),intent(in) :: rcut,gsqcut,ucvol
148 : : logical,intent(in),optional:: shortrange
149 : : !arrays
150 : : integer,intent(in) :: ngfft(18)
151 : : integer :: ng!!!!
152 : : real(dp),intent(in) :: qpoint(3)
153 : : real(dp),intent(inout) :: gmet(3,3)
154 : : real(dp),intent(inout) :: barev(nfft)
155 : : !real(dp) :: a1(3),a2(3),a3(3)
156 : : real(dp) :: b1(3),b2(3),b3(3),rmet(3,3) !,gprimd(3,3),
157 : 214238 : type(MPI_type) :: mpi_enreg !!!!
158 [ + + + + : 11140376 : type(crystal_t) :: Cryst !!!!
+ + + + +
+ + + + +
+ + + + ]
159 : : !type(gsphere_t) :: Gsph
160 : : !Local variables-------------------------------
161 : : !scalars
162 : : integer,parameter :: empty(3,3)=zero
163 : : integer,parameter :: cplex1=1
164 : : integer :: comm
165 : : integer :: ii1,i1,i2,i23,i3,id1,id2,id3,icutcoul_local
166 : : integer :: ig,ig1,ig2,ig3,ig1min,ig1max,ig2min,ig2max,ig3min,ig3max
167 : : integer :: ii,ing,n1,n2,n3,npar,npt
168 : : integer :: opt_cylinder,opt_slab,test
169 : : integer :: qeq0,qeq05
170 : : real(dp),parameter :: tolfix=1.000000001e0_dp ! Same value as the one used in hartre
171 : : real(dp) :: check,step
172 : : real(dp) :: cutoff,gqg2p3,gqgm12,gqgm13,gqgm23,gs,gs2,gs3,rcut0
173 : : real(dp) :: bz_plane,dx,integ,q0_vol,q0_volsph
174 : : character(len=500) :: msg
175 : : !arrays
176 : : integer :: id(3), gamma_pt(3,1)
177 : 214238 : real(dp),allocatable :: gq(:,:),gpq(:),gpq2(:)
178 : 214238 : real(dp),allocatable :: vcfit(:,:),xx(:),yy(:)
179 : 214238 : real(dp),allocatable :: cov(:,:),par(:),qfit(:,:),sigma(:),var(:),qcart(:,:)
180 : 214238 : type(vcut_t) :: vcut !!!!
181 : : !
182 : 214238 : comm=mpi_enreg%comm_world
183 : : !
184 : : ! === Save dimension and other useful quantities in vcut% ===
185 [ + + ]: 856952 : vcut%nfft = PRODUCT(ngfft(1:3)) ! Number of points in the FFT mesh.
186 : : ! ng and gvec are not used yet we don't want to use them without being defined
187 : 214238 : ng = -1
188 : 214238 : vcut%ng = ng ! Number of G-vectors in the Coulomb matrix elements.
189 : 214238 : vcut%rcut = rcut ! Cutoff radius for cylinder.
190 : 214238 : vcut%hcyl = zero ! Length of finite cylinder (Rozzi"s method, default is Beigi).
191 : 214238 : vcut%ucvol = ucvol ! Unit cell volume.
192 : :
193 : : !FBruneval: comment the definitions below since Cryst and dtset have never been initialized!
194 : : !vcut%rprimd = Cryst%rprimd(:,:) ! Dimensional direct lattice.
195 : : !vcut%boxcenter = dtset%boxcenter ! boxcenter at the moment is supposed to be at the origin.
196 : : !vcut%vcutgeo = dtset%vcutgeo(:) ! Info on the orientation and extension of the cutoff region.
197 : : !
198 : : ! === Define geometry and cutoff radius (if used) ===
199 : 214238 : vcut%mode='NONE'
200 : 214238 : icutcoul_local=icutcoul
201 : :
202 : : ! for short-range exchange (e.g. HSE06), enforce ERFC
203 [ + + ]: 214238 : if (PRESENT(shortrange)) then
204 [ - + ]: 81956 : if (shortrange) then
205 : : icutcoul_local=5
206 : : end if
207 : : end if
208 : : ! -------------------------------------
209 : :
210 [ + + ]: 132282 : if (icutcoul_local == 0) vcut%mode = 'SPHERE'
211 [ - + ]: 214238 : if (icutcoul_local == 1) vcut%mode = 'CYLINDER'
212 [ - + ]: 214238 : if (icutcoul_local == 2) vcut%mode = 'SLAB'
213 [ + + ]: 214238 : if (icutcoul_local == 3) vcut%mode = 'CRYSTAL'
214 [ - + ]: 214238 : if (icutcoul_local == 4) vcut%mode = 'ERF'
215 [ + + ]: 214238 : if (icutcoul_local == 5) vcut%mode = 'ERFC'
216 [ - + ]: 214238 : if (icutcoul_local == 6) vcut%mode = 'AUXILIARY_FUNCTION'
217 [ - + ]: 214238 : if (icutcoul_local == 7) vcut%mode = 'AUX_GB'
218 : :
219 : : !Initialize a few quantities
220 : 214238 : n1=ngfft(1); n2=ngfft(2); n3=ngfft(3)
221 : 214238 : cutoff = gsqcut * tolfix
222 [ + + ]: 907950866 : barev=zero
223 : :
224 : : !Some peculiar values of q: q=0 or q on the BZ edge
225 [ + + ]: 214238 : qeq0=0; if (qpoint(1)**2+qpoint(2)**2+qpoint(3)**2<1.d-15) qeq0=1
226 : 201255 : qeq05=0
227 : : if (qeq0==0) then
228 [ + + + + : 201255 : if (abs(abs(qpoint(1))-half)<tol12.or.abs(abs(qpoint(2))-half)<tol12.or. &
+ + ]
229 : 102711 : & abs(abs(qpoint(3))-half)<tol12) qeq05=1
230 : : end if
231 : :
232 : : !In order to speed the routine, precompute the components of g+q
233 : : !Also check if the booked space was large enough...
234 : :
235 [ - + + - : 642714 : ABI_MALLOC(gq,(3,max(n1,n2,n3)))
+ - + - -
+ - + ]
236 [ - + + - : 642714 : ABI_MALLOC(gpq,(nfft))
+ - + - -
+ - + ]
237 [ - + + - : 428476 : ABI_MALLOC(gpq2,(nfft))
- + - + ]
238 : :
239 [ + + ]: 856952 : do ii=1,3
240 : 642714 : id(ii)=ngfft(ii)/2+2
241 [ + + ]: 10749122 : do ing=1,ngfft(ii)
242 : 9892170 : ig=ing-(ing/id(ii))*ngfft(ii)-1
243 : 10534884 : gq(ii,ing)=ig+qpoint(ii)
244 : : end do
245 : : end do
246 : 214238 : ig1max=-1;ig2max=-1;ig3max=-1
247 : 214238 : ig1min=n1;ig2min=n2;ig3min=n3
248 : :
249 : 214238 : id1=n1/2+2;id2=n2/2+2;id3=n3/2+2
250 : :
251 : : ! Triple loop on each dimension
252 [ + + ]: 3506684 : do i3=1,n3
253 : 3292446 : ig3=i3-(i3/id3)*n3-1
254 : : ! Precompute some products that do not depend on i2 and i1
255 : 3292446 : gs3=gq(3,i3)*gq(3,i3)*gmet(3,3)
256 : 3292446 : gqgm23=gq(3,i3)*gmet(2,3)*2
257 : 3292446 : gqgm13=gq(3,i3)*gmet(1,3)*2
258 [ + + ]: 55868246 : do i2=1,n2
259 : 52361562 : ig2=i2-(i2/id2)*n2-1
260 : 52361562 : i23=n1*(i2-1 +(n2)*(i3-1))
261 : 52361562 : gs2=gs3+ gq(2,i2)*(gq(2,i2)*gmet(2,2)+gqgm23)
262 : 52361562 : gqgm12=gq(2,i2)*gmet(1,2)*2
263 : 52361562 : gqg2p3=gqgm13+gqgm12
264 : :
265 [ + + ]: 960098190 : do i1=1,n1
266 : 907736628 : ii=i1+i23
267 : 907736628 : gpq(ii)= gs2 + gq(1,i1)*(gq(1,i1)*gmet(1,1)+gqg2p3)
268 [ + + ]: 960098190 : if (gpq(ii)>=tol4) then
269 : : ! gpq2 contains 4*pi / |q+G|**2
270 : 907723645 : gpq2(ii) = piinv/gpq(ii)
271 : : end if
272 : : end do
273 : :
274 : : !
275 : : ! Next part looks for ig1min,ig1max that are needed by zerosym
276 : : ! Do the test that eliminates the Gamma point outside of the inner loop
277 : 52361562 : ii1=1
278 [ + + - + ]: 52361562 : if (i23==0 .and. qeq0==1 .and. ig2==0 .and. ig3==0) then
279 : 52361562 : ii1=2
280 : : end if
281 : :
282 : : ! Final inner loop on the first dimension (note the lower limit)
283 [ + + ]: 963377653 : do i1=ii1,n1
284 : 907723645 : gs = gs2+ gq(1,i1)*(gq(1,i1)*gmet(1,1)+gqg2p3)
285 : :
286 : : !ii=i1+i23
287 : :
288 [ + + ]: 960085207 : if (gs<=cutoff) then
289 : : ! Identify min/max indexes (to cancel unbalanced contributions later)
290 : : ! Count (q+g)-vectors with similar norm
291 [ + + + + ]: 297652559 : if ((qeq05==1).and.(izero==1)) then
292 : 6333066 : ig1=i1-(i1/id1)*n1-1
293 : 6333066 : ig1max=max(ig1max,ig1); ig1min=min(ig1min,ig1)
294 : 6333066 : ig2max=max(ig2max,ig2); ig2min=min(ig2min,ig2)
295 : 6333066 : ig3max=max(ig3max,ig3); ig3min=min(ig3min,ig3)
296 : : end if
297 : :
298 : : end if ! Cut-off
299 : : end do ! End loop on i1
300 : : end do
301 : : end do
302 : :
303 : :
304 [ + + ]: 907950866 : barev(:)=zero
305 : :
306 : : ! MG: This triggers SIGFPE as cryst is not initialized
307 : : !a1=Cryst%rprimd(:,1); b1=two_pi*gprimd(:,1)
308 : : !a2=Cryst%rprimd(:,2); b2=two_pi*gprimd(:,2)
309 : : !a3=Cryst%rprimd(:,3); b3=two_pi*gprimd(:,3)
310 : :
311 : 215534 : select case(TRIM(vcut%mode))
312 : : case ('CRYSTAL', 'AUXILIARY_FUNCTION', "AUX_GB")
313 [ + - ]: 1296 : if (vcut%mode == "CRYSTAL") then
314 : : ! Analytic integration of 4pi/q^2 over the volume element:
315 : : ! $4pi/V \int_V d^3q 1/q^2 =4pi bz_geometric_factor V^(-2/3)$
316 : : ! i_sz=4*pi*bz_geometry_factor*q0_vol**(-two_thirds) where q0_vol= V_BZ/N_k
317 : : ! bz_geometry_factor: sphere=7.79, fcc=7.44, sc=6.188, bcc=6.946, wz=5.255 (see gwa.pdf, appendix A.4)
318 : 1296 : q0_vol = two_pi**3 / (nkpt_bz * ucvol)
319 : 1296 : vcut%i_sz = four_pi*7.44*q0_vol**(-two_thirds)
320 : :
321 : : !TODO FBruneval: cryst is not available here, find a workaround!
322 : : !else if (vcut%mode == "AUXILIARY_FUNCTION") then
323 : : ! ! Numerical integration of the exact-exchange divergence through the
324 : : ! ! auxiliary function of Carrier et al. PRB 75, 205126 (2007) [[cite:Carrier2007]].
325 : : ! vcut%i_sz = carrier_isz(cryst, 1, qpoint, rcut, comm)
326 : :
327 : : !else if (vcut%mode == "AUX_GB") then
328 : : ! ! We use the auxiliary function of a Gygi-Baldereschi variant [[cite:Gigy1986]]
329 : : ! vcut%i_sz = gygi_baldereschi_isz(cryst, 1, qpoint, vc_ecut, ng, gvec)
330 : :
331 : : else
332 : 0 : ABI_ERROR(sjoin("Need treatment of 1/q^2 singularity! for mode", vcut%mode))
333 : : end if
334 : :
335 [ + + ]: 5309712 : do ig=1,nfft
336 [ + + ]: 5309712 : if (abs(gpq(ig))<tol4) then
337 : 162 : barev(ig) = vcut%i_sz
338 [ + + ]: 5308254 : else if (gpq(ig)<=cutoff) then
339 : 1574640 : barev(ig) = gpq2(ig)
340 : : end if
341 : : end do
342 : :
343 : :
344 : : case('SPHERE') ! Spherical cutoff
345 : :
346 : : !
347 : : ! Treatment of the divergence at q+g=zero
348 : : !
349 : : ! rcut is not set (rcut<=0), use the default Spencer-Alavi definition:
350 [ + + ]: 130986 : if ( rcut < tol8 ) then
351 : 129594 : rcut0= (three*nkpt_bz*ucvol/four_pi)**(one/three)
352 : : else
353 : : rcut0 = rcut
354 : : end if
355 : :
356 [ + + ]: 574623786 : do ig=1,nfft
357 [ + + ]: 574623786 : if (abs(gpq(ig))<tol4) then
358 : 8429 : barev(ig) = two_pi*rcut0**two
359 [ + + ]: 574484371 : else if (gpq(ig)<=cutoff) then
360 : 206086387 : barev(ig) = gpq2(ig) * (one - cos( rcut0*sqrt(four_pi/gpq2(ig)) ) )
361 : : end if
362 : : end do
363 : :
364 : : case('CYLINDER')
365 : : !FBruneval: not working. For instance, Cryst is never initialized
366 : 0 : ABI_BUG("Cylinder cutoff coding is not finalized")
367 : :
368 [ # # # # ]: 0 : test=COUNT(ABS(vcut%vcutgeo)>tol6)
369 [ # # ]: 0 : ABI_CHECK(test==1,'Wrong cutgeo for cylinder')
370 : :
371 : : ! === Beigi method is the default one, i.e infinite cylinder of radius rcut ===
372 : : ! * Negative values to use Rozzi method with finite cylinder of extent hcyl.
373 [ # # ]: 0 : opt_cylinder=1; vcut%hcyl=zero; vcut%pdir(:)=0
374 [ # # ]: 0 : do ii=1,3
375 : 0 : check=vcut%vcutgeo(ii)
376 [ # # ]: 0 : if (ABS(check)>tol6) then
377 : 0 : vcut%pdir(ii)=1
378 [ # # ]: 0 : if (check<zero) then ! use Rozzi's method.
379 [ # # # # : 0 : vcut%hcyl=ABS(check)*NORM2(Cryst%rprimd(:,ii))
# # ]
380 : 0 : opt_cylinder=2
381 : : end if
382 : : end if
383 : : end do
384 : :
385 [ # # # # ]: 0 : test=COUNT(vcut%pdir==1)
386 [ # # ]: 0 : ABI_CHECK((test==1),'Wrong pdir for cylinder')
387 [ # # ]: 0 : if (vcut%pdir(3)/=1) then
388 : 0 : ABI_ERROR("The cylinder must be along the z-axis")
389 : : end if
390 : :
391 : 0 : ABI_BUG("cutoff cylinder API has changed!")
392 : :
393 : : ! call cutoff_cylinder(nfft,gq,ng,Gsph%gvec,vcut%rcut,vcut%hcyl,vcut%pdir,&
394 : : !& vcut%boxcenter,Cryst%rprimd,barev,opt_cylinder,comm)
395 : :
396 : : ! === If Beigi, treat the limit q--> 0 ===
397 [ # # ]: 0 : if (opt_cylinder==1) then
398 : 0 : npar=8; npt=100 ; gamma_pt=RESHAPE((/0,0,0/),(/3,1/))
399 [ # # ]: 0 : ABI_MALLOC(qfit,(3,npt))
400 [ # # ]: 0 : ABI_MALLOC(vcfit,(1,npt))
401 [ # # ]: 0 : if (nfft==1) then
402 : 0 : ABI_ERROR("nfft == 1 not supported when Beigi's method is used")
403 : : endif
404 [ # # # # ]: 0 : qfit(:,:)=zero
405 [ # # ]: 0 : step=half/(npt*(nfft-1)) ; qfit(3,:)=arth(tol6,step,npt)
406 : :
407 : : !call cutoff_cylinder(npt,qfit,1,gamma_pt,vcut%rcut,vcut%hcyl,vcut%pdir,&
408 : : ! vcut%boxcenter,Cryst%rprimd,vcfit,opt_cylinder,comm)
409 : :
410 [ # # ]: 0 : ABI_MALLOC(xx,(npt))
411 [ # # ]: 0 : ABI_MALLOC(yy,(npt))
412 [ # # ]: 0 : ABI_MALLOC(sigma,(npt))
413 [ # # ]: 0 : ABI_MALLOC(par,(npar))
414 [ # # ]: 0 : ABI_MALLOC(var,(npar))
415 [ # # ]: 0 : ABI_MALLOC(cov,(npar,npar))
416 [ # # ]: 0 : do ii=1,npt
417 : 0 : xx(ii)=normv(qfit(:,ii),gmet,'G')
418 : : end do
419 [ # # ]: 0 : ABI_FREE(qfit)
420 [ # # # # ]: 0 : sigma=one ; yy(:)=vcfit(1,:)
421 [ # # ]: 0 : ABI_FREE(vcfit)
422 : :
423 : 0 : bz_plane=l2norm(b1.x.b2)
424 : 0 : dx=(xx(2)-xx(1))
425 : 0 : integ=yy(2)*dx*3.0/2.0
426 [ # # ]: 0 : integ=integ + SUM(yy(3:npt-2))*dx
427 : 0 : integ=integ+yy(npt-1)*dx*3.0/2.0
428 : 0 : write(std_out,*)' simple integral',integ
429 : 0 : q0_volsph=(two_pi)**3/(nkpt_bz*ucvol)
430 : 0 : q0_vol=bz_plane*two*xx(npt)
431 : 0 : write(std_out,*)' q0 sphere : ',q0_volsph,' q0_vol cyl ',q0_vol
432 : 0 : vcut%i_sz=bz_plane*two*integ/q0_vol
433 : 0 : write(std_out,*)' spherical approximation ',four_pi*7.44*q0_volsph**(-two_thirds)
434 : 0 : write(std_out,*)' Cylindrical cutoff value ',vcut%i_sz
435 : :
436 : 0 : ABI_FREE(xx)
437 : 0 : ABI_FREE(yy)
438 [ # # ]: 0 : ABI_FREE(sigma)
439 [ # # ]: 0 : ABI_FREE(par)
440 [ # # ]: 0 : ABI_FREE(var)
441 [ # # ]: 0 : ABI_FREE(cov)
442 : :
443 : : else
444 : : ! In Rozzi"s method the lim q+G --> 0 is finite.
445 : 0 : vcut%i_sz=barev(1)
446 : : end if
447 : :
448 : : CASE('SLAB')
449 : : !FBruneval: not working. For instance, Cryst is never initialized
450 : 0 : ABI_BUG("Slab cutoff coding is not finalized")
451 : :
452 [ # # # # ]: 0 : test=COUNT(vcut%vcutgeo/=zero)
453 [ # # ]: 0 : ABI_CHECK(test==2,"Wrong vcutgeo")
454 : : !
455 : : ! Two methods available
456 : : !
457 : : ! === Default is Beigi"s method ===
458 [ # # ]: 0 : opt_slab=1; vcut%alpha(:)=zero
459 [ # # # # : 0 : if (ANY(vcut%vcutgeo<zero)) opt_slab=2
# # ]
460 [ # # ]: 0 : vcut%pdir(:)=zero
461 [ # # ]: 0 : do ii=1,3
462 : 0 : check=vcut%vcutgeo(ii)
463 [ # # ]: 0 : if (ABS(check)>zero) then ! Use Rozzi"s method with a finite slab along x-y
464 : 0 : vcut%pdir(ii)=1
465 [ # # # # ]: 0 : if (check<zero) vcut%alpha(ii)=normv(check*Cryst%rprimd(:,ii),rmet,'R')
466 : : end if
467 : : end do
468 : :
469 : : ! Beigi"s method: the slab must be along x-y and R must be L_Z/2.
470 [ # # ]: 0 : if (opt_slab==1) then
471 [ # # # # : 0 : ABI_CHECK(ALL(vcut%pdir == (/1,1,0/)),"Surface must be in the x-y plane")
# # ]
472 : : !vcut%rcut = half*SQRT(DOT_PRODUCT(a3,a3))
473 : : end if
474 : :
475 : 0 : ABI_BUG("cutoff surface API has changed!")
476 : : !call cutoff_slab(nfft,gq,ng,Gsph%gvec,gprimd,vcut%rcut,&
477 : : ! vcut%boxcenter,vcut%pdir,vcut%alpha,barev,opt_slab)
478 : :
479 : : !
480 : : ! === If Beigi, treat the limit q--> 0 ===
481 [ # # ]: 0 : if (opt_slab==1) then
482 : : ! Integrate numerically in the plane close to 0
483 : 0 : npt=100 ! Number of points in 1D
484 : : gamma_pt=RESHAPE((/0,0,0/),(/3,1/)) ! Gamma point
485 [ # # ]: 0 : ABI_MALLOC(qfit,(3,npt))
486 [ # # ]: 0 : ABI_MALLOC(qcart,(3,npt))
487 [ # # ]: 0 : ABI_MALLOC(vcfit,(1,npt))
488 [ # # ]: 0 : if (nfft==1) then
489 : 0 : ABI_ERROR("nfft == 1 not supported when Beigi's method is used")
490 : : endif
491 [ # # # # ]: 0 : qfit(:,:)=zero
492 [ # # # # ]: 0 : qcart(:,:)=zero
493 : : ! Size of the third vector
494 : 0 : bz_plane=l2norm(b3)
495 : 0 : q0_volsph=(two_pi)**3/(nkpt_bz*ucvol)
496 : : ! radius that gives the same volume as q0_volsph
497 : : ! Let's assume that c is perpendicular to the plane
498 : : ! We also assume isotropic BZ around gamma
499 : 0 : step=sqrt((q0_volsph/bz_plane)/pi)/npt
500 : :
501 : : !step=half/(npt*(Qmesh%nibz-1))
502 : : ! Let's take qpoints along 1 line, the vcut does depend only on the norm
503 [ # # ]: 0 : qcart(1,:)=arth(tol6,step,npt)
504 : :
505 [ # # ]: 0 : do ii = 1,npt
506 [ # # ]: 0 : qfit(:,ii) = MATMUL(TRANSPOSE(Cryst%rprimd),qcart(:,ii))/(2*pi)
507 : : end do
508 : :
509 : 0 : ABI_BUG("cutoff surface API has changed!")
510 : :
511 : : ! call cutoff_slab(npt,qfit,1,gamma_pt,gprimd,vcut%rcut,&
512 : : ! vcut%boxcenter,vcut%pdir,vcut%alpha,vcfit,opt_slab)
513 : :
514 [ # # ]: 0 : ABI_MALLOC(xx,(npt))
515 [ # # ]: 0 : ABI_MALLOC(yy,(npt))
516 [ # # ]: 0 : ABI_MALLOC(sigma,(npt))
517 [ # # ]: 0 : do ii=1,npt
518 : : !xx(ii)=qfit(1,:)
519 : 0 : xx(ii)=normv(qfit(:,ii),gmet,'G')
520 : : end do
521 [ # # ]: 0 : ABI_FREE(qfit)
522 [ # # ]: 0 : sigma=one
523 [ # # ]: 0 : yy(:)=vcfit(1,:)
524 : : !yy(:)=one
525 [ # # ]: 0 : ABI_FREE(vcfit)
526 : 0 : dx=(xx(2)-xx(1))
527 : : ! integ = \int dr r f(r)
528 : 0 : integ=xx(2)*yy(2)*dx*3.0/2.0
529 [ # # ]: 0 : integ=integ + DOT_PRODUCT(xx(3:npt-2),yy(3:npt-2))*dx
530 : 0 : integ=integ+xx(npt-1)*yy(npt-1)*dx*3.0/2.0
531 : 0 : write(std_out,*)' simple integral',integ
532 : 0 : q0_vol=bz_plane*pi*xx(npt)**2
533 : 0 : write(std_out,*)' q0 sphere : ',q0_volsph,' q0_vol cyl ',q0_vol
534 : 0 : vcut%i_sz=bz_plane*2*pi*integ/q0_vol
535 : 0 : write(std_out,*)' spherical approximation ',four_pi*7.44*q0_volsph**(-two_thirds)
536 : 0 : write(std_out,*)' Cylindrical cutoff value ',vcut%i_sz
537 : :
538 : 0 : ABI_FREE(xx)
539 : 0 : ABI_FREE(yy)
540 : : else
541 : : ! In Rozzi"s method the lim q+G --> 0 is finite.
542 : 0 : vcut%i_sz=barev(1)
543 : : end if
544 : :
545 : : CASE('ERF')
546 : :
547 [ # # ]: 0 : do ig=1,nfft
548 [ # # ]: 0 : if (abs(gpq(ig))<tol4) then
549 : : !FIXME FBruneval check this value, ERFC value was wrong, so why not this one.
550 : 0 : barev(ig) = zero ! Stupid definition to remember something should be done here.
551 [ # # ]: 0 : else if (gpq(ig)<=cutoff) then
552 : : !FIXME FBruneval shortrange does not make sense here (it is an optional argument that may not be present)
553 : : ! and ERF is long range any way
554 [ # # ]: 0 : if (shortrange) then
555 : 0 : barev(ig) = + gpq2(ig) * exp( -pi * rcut**2 /gpq2(ig) )
556 : : end if
557 : : end if
558 : : end do
559 : :
560 : : CASE('ERFC')
561 : :
562 [ + + ]: 328017368 : do ig=1,nfft
563 [ + + ]: 328017368 : if (abs(gpq(ig))<tol4) then
564 : : !FBruneval there was a wrong value here
565 : 4392 : barev(ig) = pi * rcut**2
566 [ + + ]: 327931020 : else if (gpq(ig)<=cutoff) then
567 : : ! gpq2 is 4 pi / (q+G)**2
568 : : ! 4 pi / (q+G)**2 * [ 1 - exp( -1/4 * Rc**2 * (q+G)**2 ) ]
569 : 89991532 : barev(ig) = gpq2(ig) * ( one - exp( -pi * rcut**2 / gpq2(ig) ) )
570 : : end if
571 : : end do
572 : :
573 : : case default
574 : 0 : write(msg,'(3a)')'No cut-off applied to the Coulomb Potential.', ch10, &
575 : 0 : 'Either icutcoul value not allowed or not defined.'
576 [ + + - - : 214238 : ABI_WARNING(msg)
- + - ]
577 : : end select
578 : :
579 [ + + ]: 214238 : if (izero==1) then
580 : : ! Set contribution of unbalanced components to zero
581 [ + + ]: 11548 : if (qeq0==1) then !q=0
582 : 2047 : call zerosym(barev,cplex1,n1,n2,n3)
583 [ + + ]: 9501 : else if (qeq05==1) then
584 : : !q=1/2; this doesn't work in parallel
585 [ + - ]: 5229 : ig1=-1;if (mod(n1,2)==0) ig1=1+n1/2
586 [ + - ]: 5229 : ig2=-1;if (mod(n2,2)==0) ig2=1+n2/2
587 [ + - ]: 5229 : ig3=-1;if (mod(n3,2)==0) ig3=1+n3/2
588 [ + + ]: 5229 : if (abs(abs(qpoint(1))-half)<tol12) then
589 [ + + ]: 2988 : if (abs(ig1min)<abs(ig1max)) ig1=abs(ig1max)
590 [ + + ]: 2988 : if (abs(ig1min)>abs(ig1max)) ig1=n1-abs(ig1min)
591 : : end if
592 [ + + ]: 5229 : if (abs(abs(qpoint(2))-half)<tol12) then
593 [ + + ]: 2988 : if (abs(ig2min)<abs(ig2max)) ig2=abs(ig2max)
594 [ + + ]: 2988 : if (abs(ig2min)>abs(ig2max)) ig2=n2-abs(ig2min)
595 : : end if
596 [ + + ]: 5229 : if (abs(abs(qpoint(3))-half)<tol12) then
597 [ + - ]: 2988 : if (abs(ig3min)<abs(ig3max)) ig3=abs(ig3max)
598 [ - + ]: 2988 : if (abs(ig3min)>abs(ig3max)) ig3=n3-abs(ig3min)
599 : : end if
600 : 5229 : call zerosym(barev,cplex1,n1,n2,n3,ig1=ig1,ig2=ig2,ig3=ig3)
601 : : end if
602 : : end if
603 : :
604 [ - + ]: 214238 : ABI_FREE(gq)
605 [ - + ]: 214238 : ABI_FREE(gpq)
606 [ - + ]: 214238 : ABI_FREE(gpq2)
607 : :
608 [ - + - + : 214238 : end subroutine barevcoul
- + - + ]
609 : : !!***
610 : :
611 [ # # # # : 0 : end module m_barevcoul
# # # # #
# # # #
# ]
612 : : !!***
|