Branch data Line data Source code
1 : : !!****m* ABINIT/m_vcoul
2 : : !! NAME
3 : : !! m_vcoul
4 : : !!
5 : : !! FUNCTION
6 : : !! This module contains the definition of the vcoul_t as well
7 : : !! as procedures to calculate the Coulomb interaction in reciprocal space
8 : : !! taking into account a possible cutoff in real space.
9 : : !! Procedures to deal with the singularity for q --> 0 are also provided.
10 : : !!
11 : : !! COPYRIGHT
12 : : !! Copyright (C) 1999-2026 ABINIT group (MG, FB)
13 : : !! This file is distributed under the terms of the
14 : : !! GNU General Public License, see ~abinit/COPYING
15 : : !! or http://www.gnu.org/copyleft/gpl.txt .
16 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
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_vcoul
27 : :
28 : : use defs_basis
29 : : use m_abicore
30 : : use m_errors
31 : : use m_xmpi
32 : : use m_splines
33 : : use m_sort
34 : :
35 : : use m_fstrings, only : sjoin, itoa
36 : : use m_special_funcs, only : abi_derf
37 : : use m_bessel, only : calck0
38 : : use m_io_tools, only : open_file
39 : : use m_gwdefs, only : GW_TOLQ0
40 : : use m_numeric_tools, only : arth, geop, imin_loc, llsfit_svd, l2norm, OPERATOR(.x.), quadrature, isdiagmat
41 : : use m_hide_lapack, only : matrginv
42 : : use m_geometry, only : normv, metric
43 : : use m_qplusg, only : cmod_qpg
44 : : use m_crystal, only : crystal_t
45 : : use m_matrix, only : matr3inv
46 : : use m_bz_mesh, only : kmesh_t
47 : : use m_gsphere, only : gsphere_t
48 : : use m_fftcore, only : get_kg
49 : : use m_dtfil, only : isfile
50 : :
51 : : ! Cut-off methods modules
52 : : use m_cutoff_sphere, only : cutoff_sphere
53 : : use m_cutoff_slab, only : cutoff_slab
54 : : use m_cutoff_cylinder, only : cutoff_cylinder
55 : :
56 : : implicit none
57 : :
58 : : public :: gw_icutcoul_to_mode
59 : : public :: carrier_isz
60 : : public :: carrier_isz_gmet
61 : : public :: integratefaux
62 : : public :: gb_isz
63 : : public :: check_isz
64 : :
65 : : private
66 : : !!***
67 : :
68 : : !!****t* m_vcoul/vcoul_t
69 : : !! NAME
70 : : !! vcoul_t
71 : : !!
72 : : !! FUNCTION
73 : : !! This data type contains the square root of the Fourier components of the Coulomb interaction
74 : : !! calculated taking into account a possible cutoff. It also stores info on the particular geometry
75 : : !! used for the cutoff as well as quantities required to deal with the Coulomb divergence for q --> 0.
76 : : !!
77 : : !! SOURCE
78 : :
79 : : type,public :: vcoul_t
80 : :
81 : : integer :: ng = -1
82 : : ! Number of G-vectors
83 : :
84 : : integer :: nqibz = -1
85 : : ! Number of irreducible q-points
86 : :
87 : : integer :: nqlwl = -1
88 : : ! Number of small q-points around Gamma
89 : :
90 : : real(dp) :: alpha(3) = -one
91 : : ! Length of the finite slab
92 : :
93 : : real(dp) :: rcut = -one
94 : : ! Cutoff radius.
95 : :
96 : : real(dp) :: i_sz = huge(one)
97 : : ! Value of the integration of the Coulomb singularity 4\pi/V_BZ \int_BZ d^3q 1/q^2
98 : :
99 : : real(dp) :: i_sz_resid = huge(one)
100 : : ! Residual difference between the i_sz in the sigma self-energy for exchange,
101 : : ! and the i_sz already present in the generalized Kohn-Sham eigenenergies
102 : : ! Initialized to the same value as i_sz
103 : :
104 : : real(dp) :: hcyl = -one
105 : : ! Length of the finite cylinder along the periodic dimension
106 : :
107 : : real(dp) :: ucvol = -one
108 : : ! Volume of the unit cell
109 : :
110 : : character(len=50) :: mode
111 : : ! String defining the cutoff mode, possible values are: sphere,cylinder,slab,crystal
112 : :
113 : : integer :: pdir(3)
114 : : ! 1 if the system is periodic along this direction
115 : :
116 : : real(dp) :: boxcenter(3) = -1
117 : : ! 1 if the point in inside the cutoff region 0 otherwise
118 : : ! Reduced coordinates of the center of the box (input variable)
119 : :
120 : : real(dp) :: vcutgeo(3) = huge(one)
121 : : ! For each reduced direction gives the length of the finite system
122 : : ! 0 if the system is infinite along this direction.
123 : : ! negative values indicate that a finite size has to be used.
124 : :
125 : : real(dp) :: rprimd(3,3) = zero
126 : : ! Lattice vectors in real space.
127 : :
128 : : real(dp),allocatable :: qibz(:,:)
129 : : ! (3, nqibz)
130 : : ! q-points in the IBZ.
131 : :
132 : : real(dp),allocatable :: qlwl(:,:)
133 : : ! (3, nqlwl)
134 : : ! q-points for the treatment of the Coulomb singularity.
135 : :
136 : : complex(gwp),allocatable :: vc_sqrt(:,:)
137 : : ! (ng, nqibz)
138 : : ! Square root of the Coulomb interaction in reciprocal space.
139 : : ! complex-valued to allow for a possible cutoff (Rozzi's method)
140 : :
141 : : complex(gwp),allocatable :: vcqlwl_sqrt(:,:)
142 : : ! (ng, nqlwl)
143 : : ! Square root of the Coulomb term calculated for small q-points
144 : :
145 : : complex(gwp),allocatable :: vc_sqrt_resid(:,:)
146 : : ! (ng, nqibz)
147 : : ! Square root of the residual difference between the Coulomb interaction in the sigma self-energy for exchange,
148 : : ! and the Coulomb interaction already present in the generalized Kohn-Sham eigenenergies (when they come from an hybrid)
149 : : ! Given in reciprocal space. At the call to vcoul_init, it is simply initialized at the value of vc_sqrt(:,:),
150 : : ! and only later modified. A cutoff might be applied.
151 : :
152 : : contains
153 : : procedure :: init => vcoul_init ! Main creation method.
154 : : procedure :: plot => vcoul_plot ! Plot vc in real and reciprocal space.
155 : : procedure :: print => vcoul_print ! Print info on the object.
156 : : procedure :: free => vcoul_free ! Free memory
157 : : end type vcoul_t
158 : : !!***
159 : :
160 : : !!****t* m_vcoul/mc_t
161 : : !! NAME
162 : : !! mc_t
163 : : !!
164 : : !! FUNCTION
165 : : !! Mimicking the BerkeleyGW technique
166 : : !! A Monte-Carlo sampling of each miniBZ surrounding each (q+G) point.
167 : : !! However:
168 : : !! - extended to multiple shifts
169 : : !! - with an adaptative number of MonteCarlo sampling points
170 : : !!
171 : : !! SOURCE
172 : :
173 : : type, public :: mc_t
174 : :
175 : : integer :: nmc_max = -1
176 : :
177 : : real(dp) :: q0sph = -one
178 : :
179 : : real(dp) :: ucvol = -one
180 : :
181 : : real(dp) :: gmet(3,3) = -one
182 : :
183 : : real(dp),allocatable :: qran(:,:)
184 : : ! (3, nmc_max)
185 : :
186 : : contains
187 : : procedure :: init => mc_init
188 : : procedure :: integrate => mc_integrate
189 : : procedure :: free => mc_free
190 : : end type mc_t
191 : : !!***
192 : :
193 : : !!****t* m_vcoul/vcgen_t
194 : : !! NAME
195 : : !! vcgen_t
196 : : !!
197 : : !! FUNCTION
198 : : !!
199 : : !! SOURCE
200 : :
201 : : type, public :: vcgen_t
202 : :
203 : : integer :: nkbz = -1
204 : : ! Number of k-points in full BZ.
205 : :
206 : : integer :: opt_cylinder
207 : :
208 : : integer :: opt_slab
209 : :
210 : : real(dp) :: alpha(3) = -one
211 : : ! Lenght of the finite surface.
212 : :
213 : : real(dp) :: rcut = -one
214 : : ! Cutoff radius.
215 : :
216 : : real(dp) :: hcyl = -one
217 : : ! Length of the finite cylinder along the periodic dimension
218 : :
219 : : character(len=50) :: mode
220 : : ! String defining the cutoff mode
221 : :
222 : : integer :: pdir(3)
223 : : ! 1 if the system is periodic along this direction
224 : :
225 : : real(dp) :: boxcenter(3) = -1
226 : : ! 1 if the point in inside the cutoff region 0 otherwise
227 : : ! Reduced coordinates of the center of the box (input variable)
228 : :
229 : : real(dp) :: vcutgeo(3) = huge(one)
230 : : ! For each reduced direction gives the length of the finite system
231 : : ! 0 if the system is infinite along this direction.
232 : : ! negative values indicate that a finite size has to be used.
233 : :
234 : : real(dp) :: i_sz = huge(one)
235 : : ! Value of the integration of the Coulomb singularity 4\pi/V_BZ \int_BZ d^3q 1/q^2
236 : :
237 : : type(mc_t) :: mc
238 : : ! Monte carlo integrator.
239 : :
240 : : contains
241 : : procedure :: init => vcgen_init ! Initialize the object
242 : : procedure :: get_vc_sqrt => vcgen_get_vc_sqrt ! Compute sqrt(vc(q,g))
243 : : procedure :: free => vcgen_free ! Free memory
244 : : procedure :: print => vcgen_print ! Print info on the object.
245 : : end type vcgen_t
246 : : !!***
247 : :
248 : : CONTAINS !========================================================================================
249 : : !!***
250 : :
251 : : !!****f* m_vcoul/gw_icutcoul_to_mode
252 : : !! NAME
253 : : !! gw_icutcoul_to_mode
254 : : !!
255 : : !! FUNCTION
256 : : !! Convert gw_icutcoul_to_mode to mode string.
257 : : !!
258 : : !! SOURCE
259 : :
260 : 412 : subroutine gw_icutcoul_to_mode(gw_icutcoul, mode)
261 : :
262 : : !Arguments ------------------------------------
263 : : integer,intent(in) :: gw_icutcoul
264 : : character(len=*),intent(out) :: mode
265 : : ! *************************************************************************
266 : :
267 [ + - ]: 412 : mode = 'NONE'
268 [ + + + - : 412 : if (gw_icutcoul == 0) mode = 'SPHERE'
+ - ]
269 [ + + + - : 412 : if (gw_icutcoul == 1) mode = 'CYLINDER'
+ - ]
270 [ - + - - : 412 : if (gw_icutcoul == 2) mode = 'SLAB'
- - ]
271 [ + + + - : 412 : if (gw_icutcoul == 3) mode = 'CRYSTAL'
+ - ]
272 [ + + + - : 412 : if (gw_icutcoul == 4) mode = 'ERF'
+ - ]
273 [ + + + - : 412 : if (gw_icutcoul == 5) mode = 'ERFC'
+ - ]
274 [ + + + - : 412 : if (gw_icutcoul == 6) mode = 'AUXILIARY_FUNCTION'
+ - ]
275 [ + + + - : 412 : if (gw_icutcoul == 7) mode = 'AUX_GB'
+ - ]
276 [ + + + - : 412 : if (gw_icutcoul == 14) mode = 'MINIBZ-ERF'
+ - ]
277 [ + + + - : 412 : if (gw_icutcoul == 15) mode = 'MINIBZ-ERFC'
+ - ]
278 [ + + + - : 412 : if (gw_icutcoul == 16) mode = 'MINIBZ'
+ - ]
279 : :
280 [ + - ]: 412 : end subroutine gw_icutcoul_to_mode
281 : : !!***
282 : :
283 : : !!****f* m_vcoul/vcoul_init
284 : : !! NAME
285 : : !! vcoul_init
286 : : !!
287 : : !! FUNCTION
288 : : !! Perform general check and initialize the data type containing information on the cutoff technique
289 : : !! Note %vc_sqrt_resid and %i_sz_resid are simply initialized at the same value as %vc_sqrt and %i_sz
290 : : !!
291 : : !! INPUTS
292 : : !! Gsph=Info of the G sphere.
293 : : !! Qmesh=Info on the q-point sampling.
294 : : !! Kmesh=Info on the k-point sampling.
295 : : !! rcut=Cutoff radius for the cylinder.
296 : : !! gw_icutcoul=Option of the cutoff technique.
297 : : !! vcutgeo(3)= Info on the orientation and extension of the cutoff region.
298 : : !! ng=Number of G-vectors to be used to describe the Coulomb interaction
299 : : !! nqlwl=Number of point around Gamma for treatment of long-wavelength limit
300 : : !! qlwl(3,nqlwl)= The nqlwl "small" q-points
301 : : !! comm=MPI communicator.
302 : : !!
303 : : !! SOURCE
304 : :
305 : 412 : subroutine vcoul_init(vcp, Gsph, Cryst, Qmesh, Kmesh, rcut, gw_icutcoul, vcutgeo, ng, nqlwl, qlwl, comm)
306 : :
307 : : !Arguments ------------------------------------
308 : : !scalars
309 : : class(vcoul_t),intent(out) :: vcp
310 : : integer,intent(in) :: ng,nqlwl, gw_icutcoul, comm
311 : : real(dp),intent(in) :: rcut
312 : : type(kmesh_t),target,intent(in) :: Kmesh, Qmesh
313 : : type(gsphere_t),target,intent(in) :: Gsph
314 : : type(crystal_t),intent(in) :: Cryst
315 : : !arrays
316 : : real(dp),intent(in) :: qlwl(3,nqlwl),vcutgeo(3)
317 : :
318 : : !Local variables-------------------------------
319 : : !scalars
320 : : integer,parameter :: master=0
321 : : integer :: nqibz, nqbz, nkbz, iqlwl, iq_ibz, opt_cylinder,my_rank,nprocs, opt_slab
322 : : real(dp) :: bz_geometry_factor,q0_vol, rcut2
323 : : character(len=500) :: msg
324 [ + + + + ]: 5356 : type(mc_t) :: mc
325 [ + + + + ]: 5356 : type(kmesh_t),target :: qmesh_k
326 : : !arrays
327 : : integer :: units(2)
328 : 412 : integer, contiguous, pointer :: gvec(:,:)
329 : : real(dp) :: a1(3),a2(3),a3(3),b1(3),b2(3),b3(3)
330 [ + - ]: 412 : real(dp),allocatable :: vcoul(:,:),vcoul_lwl(:,:)
331 : 412 : real(dp),contiguous, pointer :: qibz(:,:), qbz(:,:)
332 : : ! *************************************************************************
333 : :
334 : : !call wrtout(std_out, "in vcoul_init")
335 : 412 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
336 [ + + ]: 1236 : units = [std_out, ab_out]
337 : :
338 : 412 : nqibz = qmesh%nibz; nqbz = qmesh%nbz
339 : 412 : qibz => qmesh%ibz; qbz => qmesh%bz
340 : 412 : nkbz = kmesh%nbz
341 : :
342 : : ! Save dimension and other useful quantities in vcp
343 : 412 : vcp%ng = ng ! Number of G-vectors in the Coulomb matrix elements.
344 : 412 : vcp%nqibz = nqibz ! Number of irred q-point.
345 : 412 : vcp%nqlwl = nqlwl ! Number of small q-directions to deal with singularity and non Analytic behavior.
346 : 412 : vcp%rcut = rcut ! Cutoff radius for cylinder.
347 : 412 : vcp%hcyl = zero ! Length of finite cylinder (Rozzi"s method, default is Beigi).
348 : 412 : vcp%ucvol = cryst%ucvol ! Unit cell volume.
349 [ + + + + ]: 5356 : vcp%rprimd = Cryst%rprimd(:,:) ! Dimensional direct lattice.
350 [ + + ]: 1648 : vcp%boxcenter = zero ! Boxcenter at the moment is supposed to be at the origin.
351 [ + + ]: 1648 : vcp%vcutgeo = vcutgeo(:) ! Info on the orientation and extension of the cutoff region.
352 : :
353 : 412 : gvec => Gsph%gvec
354 : :
355 : 412 : call gw_icutcoul_to_mode(gw_icutcoul, vcp%mode)
356 : :
357 : : ! The integration of the 1/q^2 singularity with the auxiliary functions (carrier_isz, gygi_baldereschi_isz)
358 : : ! must be consistent with the BZ sum performed with the k-mesh, i.e. it must use the q-points k1-k2.
359 : : ! The q-mesh passed in can be denser, e.g. in the sigma driver when the SCR file has been computed
360 : : ! with a multi-shift k-mesh. In this case, use the q-mesh generated from the k-mesh.
361 : : ! The other modes use only nkbz or kmesh%kptrlatt for the singularity.
362 : 638 : select case (trim(vcp%mode))
363 : : case ('ERF', 'AUXILIARY_FUNCTION', 'AUX_GB')
364 [ + + + + ]: 412 : if (nqbz /= nkbz) then
365 : 3 : call qmesh_k%find_qmesh(cryst, kmesh)
366 : 3 : nqbz = qmesh_k%nbz; qbz => qmesh_k%bz
367 : 3 : write(msg,'(2a,2(a,i0))') ch10, ' vcoul_init: q-mesh is not consistent with the k-mesh,', &
368 : 6 : ' using the k1-k2 q-mesh for the q --> 0 singularity. nqbz: ', qmesh%nbz, ' --> ', nqbz
369 : 3 : call wrtout(std_out, msg)
370 : : end if
371 : : end select
372 : :
373 [ - + + - : 1236 : ABI_MALLOC(vcp%qibz, (3, nqibz))
+ - + - -
+ - + -
+ ]
374 [ + - + - : 11232 : vcp%qibz = Qmesh%ibz(:,:)
- + - - +
+ + + ]
375 [ - + + - : 1236 : ABI_MALLOC(vcp%qlwl, (3, nqlwl))
+ - + - -
+ - + -
+ ]
376 [ - + + + : 2472 : vcp%qlwl = qlwl(:,:)
+ + ]
377 : :
378 : : ! ===============================================
379 : : ! == Calculation of the FT of the Coulomb term ==
380 : : ! ===============================================
381 : : a1 = cryst%rprimd(:,1); a2 = cryst%rprimd(:,2); a3 = cryst%rprimd(:,3)
382 : : b1 = two_pi * cryst%gprimd(:,1); b2 = two_pi * cryst%gprimd(:,2); b3 = two_pi * cryst%gprimd(:,3)
383 : :
384 [ - + + - : 1648 : ABI_MALLOC(vcoul , (ng, nqibz))
- + + - +
- + - - +
- + ]
385 [ - + + - : 1648 : ABI_MALLOC(vcoul_lwl, (ng, nqlwl))
- + + - +
- + - - +
- + ]
386 : :
387 : 415 : select case (trim(vcp%mode))
388 : : case ('MINIBZ', 'MINIBZ-ERFC', 'MINIBZ-ERF')
389 : 3 : call mc%init(cryst%rprimd, cryst%ucvol, cryst%gprimd, cryst%gmet, kmesh%kptrlatt)
390 : :
391 : 3 : rcut2 = vcp%rcut**2
392 [ + + ]: 12 : do iq_ibz=1,nqibz
393 : 12 : call mc%integrate(vcp%mode, qibz(:, iq_ibz), ng, gvec, rcut2, nkbz, vcoul(:, iq_ibz), comm)
394 : : end do
395 : :
396 : : ! Treat the limit q --> 0
397 : 3 : vcp%i_sz = vcoul(1, 1)
398 : :
399 [ + + ]: 6 : do iqlwl=1,nqlwl
400 : 6 : call mc%integrate(vcp%mode, qlwl(:, iqlwl), ng, gvec, rcut2, nkbz, vcoul_lwl(:, iqlwl), comm)
401 : : end do
402 : :
403 : 3 : call mc%free()
404 : :
405 : : case ('SPHERE')
406 : : ! A non-positive value of rcut activates the recipe of Spencer & Alavi, PRB 77, 193110 (2008) [[cite:Spencer2008]].
407 [ + + ]: 46 : if (vcp%rcut < tol12) then
408 : 10 : vcp%rcut = (cryst%ucvol * nkbz * 3.d0 / four_pi) ** third
409 : 10 : write(msg,'(2a,2x,f8.4,a)')ch10,' Using calculated rcut: ',vcp%rcut,' to have same volume as the BvK crystal'
410 : 10 : call wrtout(std_out, msg)
411 : : end if
412 [ + + ]: 184 : vcp%vcutgeo = zero
413 : :
414 [ + + ]: 137 : do iq_ibz=1,nqibz
415 : 137 : call cutoff_sphere(qibz(:,iq_ibz), ng, gvec, cryst%gmet, vcp%rcut, vcoul(:,iq_ibz))
416 : : end do
417 : :
418 : : ! q-points for optical limit.
419 [ + + ]: 92 : do iqlwl=1,nqlwl
420 : 92 : call cutoff_sphere(qlwl(:,iqlwl), ng, gvec, cryst%gmet, vcp%rcut, vcoul_lwl(:,iqlwl))
421 : : end do
422 : :
423 : : ! Treat the limit q --> 0
424 : : ! The small cube is approximated by a sphere, while vc(q=0) = 2piR**2.
425 : : ! if a single q-point is used, the expression for the volume is exact.
426 : 46 : vcp%i_sz = two_pi * vcp%rcut**2
427 : :
428 : : case ('CYLINDER')
429 : 2 : call cylinder_setup(cryst, vcp%vcutgeo, vcp%hcyl, vcp%pdir, opt_cylinder)
430 : :
431 [ + + ]: 12 : do iq_ibz=1,nqibz
432 : : call cutoff_cylinder(qibz(:,iq_ibz), ng, gvec, vcp%rcut, vcp%hcyl, vcp%pdir,&
433 : 12 : vcp%boxcenter, Cryst%rprimd, vcoul(:,iq_ibz), opt_cylinder, comm)
434 : : end do
435 : :
436 : : ! q-points for optical limit.
437 [ + + ]: 4 : do iqlwl=1,nqlwl
438 : : call cutoff_cylinder(qlwl(:,iqlwl), ng, gvec, vcp%rcut, vcp%hcyl, vcp%pdir,&
439 : 4 : vcp%boxcenter, Cryst%rprimd, vcoul_lwl(:,iqlwl), opt_cylinder, comm)
440 : : end do
441 : :
442 : : ! If Beigi, treat the limit q --> 0.
443 [ + + ]: 2 : if (opt_cylinder == 1) then
444 : 1 : call beigi_cylinder_limit(opt_cylinder, cryst, nqibz, nkbz, vcp%rcut, vcp%hcyl, vcp%boxcenter, vcp%pdir, vcp%i_sz)
445 : : else
446 : : ! In Rozzi's method the lim q+G --> 0 is finite.
447 : 1 : vcp%i_sz = vcoul(1,1)
448 : : end if
449 : :
450 : : case ('SLAB')
451 : 0 : call surface_setup(cryst, vcp%vcutgeo, vcp%alpha, vcp%rcut, vcp%pdir, opt_slab)
452 : :
453 [ # # ]: 0 : do iq_ibz=1,nqibz
454 : : call cutoff_slab(qibz(:,iq_ibz), ng, gvec, cryst%gprimd, vcp%rcut, &
455 : 0 : vcp%boxcenter, vcp%pdir, vcp%alpha, vcoul(:,iq_ibz), opt_slab)
456 : : end do
457 : :
458 : : ! q-points for optical limit.
459 [ # # ]: 0 : do iqlwl=1,nqlwl
460 : : call cutoff_slab(qlwl(:,iq_ibz), ng, gvec, cryst%gprimd, vcp%rcut, &
461 : 0 : vcp%boxcenter, vcp%pdir, vcp%alpha, vcoul_lwl(:,iqlwl), opt_slab)
462 : : end do
463 : :
464 : : ! If Beigi, treat the limit q --> 0.
465 [ # # ]: 0 : if (opt_slab == 1) then
466 : : ! Integrate numerically in the plane close to 0
467 : : call beigi_surface_limit(opt_slab, cryst, nqibz, nkbz, vcp%rcut, vcp%alpha, &
468 : 0 : vcp%boxcenter, vcp%pdir, vcp%i_sz)
469 : : else
470 : : ! In Rozzi's method the lim q+G --> 0 is finite.
471 : 0 : vcp%i_sz=vcoul(1,1)
472 : : end if
473 : :
474 : : case ('CRYSTAL', 'AUXILIARY_FUNCTION', "AUX_GB")
475 [ + + ]: 2702 : do iq_ibz=1,nqibz
476 : 2361 : call cmod_qpg(nqibz, iq_ibz, qibz, ng, gvec, cryst%gprimd, vcoul(:,iq_ibz))
477 : :
478 [ + + ]: 2702 : if (iq_ibz == 1) then
479 : : ! The singularity is treated using vcoul_lwl.
480 : 341 : vcoul(1, iq_ibz) = zero
481 [ + + ]: 46131 : vcoul(2:,iq_ibz) = four_pi / vcoul(2:,iq_ibz)**2
482 : : else
483 [ + + ]: 221358 : vcoul(:,iq_ibz) = four_pi / vcoul(:,iq_ibz)**2
484 : : end if
485 : : end do ! iq_ibz
486 : :
487 : : ! q-points for optical limit.
488 [ + + ]: 682 : do iqlwl=1,nqlwl
489 : 682 : call cmod_qpg(nqlwl, iqlwl, qlwl, ng, gvec, cryst%gprimd, vcoul_lwl(:,iqlwl))
490 : : end do
491 [ + + + + ]: 46813 : vcoul_lwl = four_pi/vcoul_lwl**2
492 : :
493 : : ! Treatment of 1/q^2 singularity
494 : :
495 [ + + ]: 341 : if (vcp%mode == "CRYSTAL") then
496 : : ! Analytic integration of 4pi/q^2 over the volume element:
497 : : ! $4pi/V \int_V d^3q 1/q^2 =4pi bz_geometric_factor V^(-2/3)$
498 : : ! i_sz=4*pi*bz_geometry_factor*q0_vol**(-two_thirds) where q0_vol= V_BZ/N_k
499 : : ! bz_geometry_factor: sphere=7.79, fcc=7.44, sc=6.188, bcc=6.946, wz=5.255 (see gwa.pdf, appendix A.4)
500 : 117 : q0_vol = (two_pi) **3 / (nkbz*cryst%ucvol); bz_geometry_factor=zero
501 : 117 : vcp%i_sz = four_pi*7.44*q0_vol**(-two_thirds)
502 : :
503 [ + + ]: 224 : else if (vcp%mode == "AUXILIARY_FUNCTION") then
504 : : ! Numerical integration of the exact-exchange divergence through the
505 : : ! auxiliary function of Carrier et al. PRB 75, 205126 (2007) [[cite:Carrier2007]].
506 : 56 : vcp%i_sz = carrier_isz(cryst, nqbz, qbz, comm)
507 : :
508 [ + - ]: 168 : else if (vcp%mode == "AUX_GB") then
509 : : ! Gygi-Baldereschi method [[cite:Gygi1986]] with the Gaussian auxiliary function of [[cite:Massidda1993]]
510 : 168 : vcp%i_sz = gygi_baldereschi_isz(cryst, nqbz, qbz)
511 : :
512 : : else
513 : 0 : ABI_ERROR(sjoin("Need treatment of 1/q^2 singularity! for mode", vcp%mode))
514 : : end if
515 : :
516 : : case ('ERF')
517 : : ! Modified long-range only Coulomb interaction thanks to the error function:
518 : : ! * Vc = erf(r/rcut)/r
519 : : ! * The singularity is treated using vcoul_lwl.
520 [ + + ]: 8 : do iq_ibz=1,nqibz
521 : 6 : call cmod_qpg(nqibz, iq_ibz, qibz, ng, gvec, cryst%gprimd, vcoul(:,iq_ibz))
522 : :
523 : : ! The Fourier transform of the error function reads
524 [ + + ]: 8 : if (iq_ibz == 1) then
525 : 2 : vcoul(1, iq_ibz) = zero
526 [ + + ]: 420 : vcoul(2:,iq_ibz) = four_pi/(vcoul(2:,iq_ibz)**2) * EXP( -0.25d0 * (vcp%rcut*vcoul(2:,iq_ibz))**2 )
527 : : else
528 [ + + ]: 844 : vcoul(:,iq_ibz) = four_pi/(vcoul(:, iq_ibz)**2) * EXP( -0.25d0 * (vcp%rcut*vcoul(: ,iq_ibz))**2 )
529 : : end if
530 : : end do
531 : :
532 : : ! q-points for optical limit.
533 [ + + ]: 4 : do iqlwl=1,nqlwl
534 : 4 : call cmod_qpg(nqlwl, iqlwl, qlwl, ng, gvec, cryst%gprimd, vcoul_lwl(:,iqlwl))
535 : : end do
536 [ + + + + ]: 424 : vcoul_lwl = four_pi/(vcoul_lwl**2) * EXP( -0.25d0 * (vcp%rcut*vcoul_lwl)**2 )
537 : :
538 : : ! === Treat 1/q^2 singularity ===
539 : : ! * Gaussian auxiliary function with alfa = rcut^2/4, equal to the erf potential (exact, see gb_isz)
540 : 2 : vcp%i_sz = gygi_baldereschi_isz(cryst, nqbz, qbz, rcut=vcp%rcut)
541 : :
542 : : case ('ERFC')
543 : : ! * Use a modified short-range only Coulomb interaction thanks to the complementary error function:
544 : : ! $ V_c = [1-erf(r/r_{cut})]/r $
545 : : ! * The Fourier transform of the error function reads
546 : : ! vcoul=four_pi/(vcoul**2) * ( 1.d0 - exp( -0.25d0 * (vcp%rcut*vcoul)**2 ) )
547 [ + + ]: 143 : do iq_ibz=1,nqibz
548 : 125 : call cmod_qpg(nqibz, iq_ibz, qibz,ng, gvec, cryst%gprimd, vcoul(:,iq_ibz))
549 : :
550 [ + + ]: 143 : if (iq_ibz == 1) then
551 : 18 : vcoul(1 ,iq_ibz) = zero
552 [ + + ]: 1602 : vcoul(2:,iq_ibz) = four_pi/(vcoul(2:,iq_ibz)**2) * ( one - EXP( -0.25d0 * (vcp%rcut*vcoul(2:,iq_ibz))**2 ) )
553 : : else
554 [ + + ]: 10446 : vcoul(:, iq_ibz) = four_pi/(vcoul(:, iq_ibz)**2) * ( one - EXP( -0.25d0 * (vcp%rcut*vcoul(:, iq_ibz))**2 ) )
555 : : end if
556 : : end do ! iq_ibz
557 : :
558 : : ! q-points for optical limit.
559 [ + + ]: 36 : do iqlwl=1,nqlwl
560 : 36 : call cmod_qpg(nqlwl, iqlwl, qlwl, ng, gvec, cryst%gprimd, vcoul_lwl(:,iqlwl))
561 : : end do
562 [ + + + + ]: 1638 : vcoul_lwl = four_pi/(vcoul_lwl**2) * ( one - EXP( -0.25d0 * (vcp%rcut*vcoul_lwl)**2 ) )
563 : :
564 : : ! === Treat 1/q^2 singularity ===
565 : : ! * There is NO singularity in this case.
566 : 18 : vcp%i_sz = pi * vcp%rcut**2 ! Final result stored here
567 : :
568 : : case default
569 [ + + + - : 412 : ABI_BUG(sjoin('Unsupported cutoff mode:', vcp%mode))
+ + + - ]
570 : : end select
571 : :
572 : 412 : write(msg,'(3a,i0,a,es22.14)') ' vcoul_init: mode ', trim(vcp%mode), ', nqbz ', nqbz, ', i_sz = ', vcp%i_sz
573 : 412 : call wrtout(std_out, msg)
574 : 412 : call check_isz(vcp%i_sz, vcp%mode, "gw_icutcoul")
575 : 412 : vcp%i_sz_resid = vcp%i_sz
576 : :
577 : : ! Store final results in complex array as Rozzi's cutoff can give real negative values
578 [ - + + - : 1648 : ABI_MALLOC(vcp%vc_sqrt, (ng, nqibz))
- + + - +
- + - - +
- + - + ]
579 [ - + + - : 1236 : ABI_MALLOC(vcp%vc_sqrt_resid, (ng, nqibz))
- + + - -
+ - + -
+ ]
580 [ - + + + : 359756 : vcp%vc_sqrt = CMPLX(vcoul, zero)
+ + ]
581 [ + + + + ]: 359344 : vcp%vc_sqrt = SQRT(vcp%vc_sqrt)
582 [ + - + - : 359756 : vcp%vc_sqrt_resid = vcp%vc_sqrt
- + - - +
+ + + ]
583 [ - + ]: 412 : ABI_FREE(vcoul)
584 : :
585 [ - + + - : 1648 : ABI_MALLOC(vcp%vcqlwl_sqrt, (ng, nqlwl))
- + + - +
- + - - +
- + - + ]
586 [ + - - + : 121474 : vcp%vcqlwl_sqrt = CMPLX(vcoul_lwl, zero)
- - + + +
+ ]
587 [ + + + + ]: 121062 : vcp%vcqlwl_sqrt = SQRT(vcp%vcqlwl_sqrt)
588 [ - + ]: 412 : ABI_FREE(vcoul_lwl)
589 : 412 : call qmesh_k%free()
590 : :
591 : 412 : call vcp%print(units)
592 : : !call wrtout(std_out, " exiting vcoul_init")
593 : :
594 [ - + - + : 1236 : end subroutine vcoul_init
- + - + -
+ - + - +
- + - + -
+ - + -
+ ]
595 : : !!***
596 : :
597 : :
598 : : !!****f* m_vcoul/cylinder_setup
599 : : !! NAME
600 : : !! cylinder_setup
601 : : !!
602 : : !! FUNCTION
603 : : !!
604 : : !! SOURCE
605 : :
606 : 2 : subroutine cylinder_setup(cryst, vcutgeo, hcyl, pdir, opt_cylinder)
607 : :
608 : : type(crystal_t),intent(in) :: cryst
609 : : real(dp),intent(in) :: vcutgeo(3)
610 : : real(dp),intent(out) :: hcyl
611 : : integer,intent(out) :: pdir(3), opt_cylinder
612 : :
613 : : !Local variables-------------------------------
614 : : integer :: ii
615 : : real(dp),parameter :: tol999 = 999.0
616 : : real(dp) :: check
617 : : ! *************************************************************************
618 : :
619 [ + + + + : 8 : ABI_CHECK(count(abs(vcutgeo) > tol6) == 1, 'Wrong cutgeo for cylinder')
- + ]
620 : :
621 : : ! Beigi's method is the default one, i.e infinite cylinder of radius rcut.
622 : : ! Use negative values to use Rozzi's method with finite cylinder of extent hcyl.
623 : 2 : opt_cylinder = 1; hcyl = zero; pdir(:) = 0
624 [ + + ]: 8 : do ii=1,3
625 : 6 : check = vcutgeo(ii)
626 [ + + ]: 8 : if (abs(check) > tol6) then
627 : 2 : pdir(ii) = 1
628 [ + + ]: 2 : if (check < zero) then
629 : : ! use Rozzi's method.
630 [ + + + + : 4 : hcyl = ABS(check) * NORM2(cryst%rprimd(:,ii))
+ - ]
631 : 1 : opt_cylinder = 2
632 : : ! Check to enter the infinite Rozzi treatment
633 [ - + ]: 1 : if(vcutgeo(3) <= -tol999) hcyl = tol12
634 : : end if
635 : : end if
636 : : end do
637 : :
638 [ + + + + : 8 : ABI_CHECK((count(pdir == 1) == 1), 'Wrong pdir for cylinder')
- + ]
639 [ - + ]: 2 : if (pdir(3) /= 1) then
640 : 0 : ABI_ERROR("The cylinder must be along the z-axis")
641 : : end if
642 : :
643 : 2 : end subroutine cylinder_setup
644 : : !!***
645 : :
646 : : !!****f* m_vcoul/surface_setup
647 : : !! NAME
648 : : !! surface_setup
649 : : !!
650 : : !! FUNCTION
651 : : !!
652 : : !! SOURCE
653 : :
654 : 0 : subroutine surface_setup(cryst, vcutgeo, alpha, rcut, pdir, opt_slab)
655 : :
656 : : type(crystal_t),intent(in) :: cryst
657 : : real(dp),intent(in) :: vcutgeo(3)
658 : : real(dp),intent(out) :: alpha(3)
659 : : real(dp),intent(inout) :: rcut
660 : : integer,intent(out) :: pdir(3), opt_slab
661 : :
662 : : !Local variables-------------------------------
663 : : integer :: ii
664 : : real(dp) :: check
665 : : character(len=500) :: msg
666 : : ! *************************************************************************
667 : :
668 [ # # # # : 0 : ABI_CHECK(count(vcutgeo /= zero) == 2, "Wrong vcutgeo")
# # ]
669 : :
670 : : ! Default is Beigi's method.
671 [ # # # # : 0 : opt_slab = 1; if (any(vcutgeo < zero)) opt_slab = 2
# # ]
672 : 0 : pdir(:) = zero; alpha(:)=zero
673 [ # # ]: 0 : do ii=1,3
674 : 0 : check = vcutgeo(ii)
675 [ # # ]: 0 : if (abs(check) > zero) then
676 : : ! Use Rozzi's method with a finite surface along x-y
677 : 0 : pdir(ii) = 1
678 [ # # # # ]: 0 : if (check < zero) alpha(ii) = normv(check * cryst%rprimd(:,ii), cryst%rmet, 'R')
679 : : end if
680 : : end do
681 : :
682 : : ! In Beigi's method, the surface must be along x-y and R must be L_Z/2.
683 [ # # ]: 0 : if (opt_slab == 1) then
684 : 0 : msg = "2D Beigi method, the periodicity must be in the x-y plane. Modify vcutgeo and/or your geometry."
685 [ # # # # : 0 : ABI_CHECK(all(pdir == [1, 1, 0]), msg)
# # ]
686 [ # # ]: 0 : rcut = half*SQRT(DOT_PRODUCT(cryst%rprimd(:,3), cryst%rprimd(:,3)))
687 : : end if
688 : :
689 : 0 : end subroutine surface_setup
690 : : !!***
691 : :
692 : : !!****f* m_vcoul/integratefaux
693 : : !! NAME
694 : : !! integratefaux
695 : : !!
696 : : !! FUNCTION
697 : : !! Average over the BZ of the auxiliary function F of Carrier et al. (see faux), computed as
698 : : !! <F>_BZ = <F - F_G>_BZ + <F_G>_BZ, F_G(q) = sum_G exp(-alfa|q+G|^2)/|q+G|^2, <F_G>_BZ = ucvol/(4pi sqrt(pi alfa))
699 : : !! F - F_G is bounded and is summed on a Gamma-centred nq^3 grid; its value at q=0 is the limit
700 : : !! -<L> + alfa - sum_{G/=0} F_G(G) (see carrier_limit). The sum over the grid of the Gaussian part is exact
701 : : !! (see gb_isz), so the result does not depend on alfa: alfa = (a_min/4)^2 minimizes the number of G-vectors.
702 : : !! The error comes from the direction dependence of F near q=0 and decreases as 1/nq^3; in i_sz it is
703 : : !! multiplied by nqbz, so nq^3 >= 64 nqbz keeps it well below the remaining error of the method.
704 : : !!
705 : : !! INPUTS
706 : : !! gmet(3,3)=Reciprocal space metric (bohr^-2), without the factor (2pi)^2.
707 : : !! ucvol=Unit cell volume (bohr^3).
708 : : !! nqbz=Number of q-points of the mesh used for the BZ sum (fixes the grid nq).
709 : : !! comm=MPI communicator.
710 : : !!
711 : : !! SOURCE
712 : :
713 : 114 : real(dp) function integratefaux(gmet, ucvol, nqbz, comm)
714 : :
715 : : !Arguments ------------------------------------
716 : : integer,intent(in) :: nqbz, comm
717 : : real(dp),intent(in) :: gmet(3,3), ucvol
718 : :
719 : : !Local variables-------------------------------
720 : : real(dp),parameter :: alfa_gmax2 = 36.0_dp
721 : : integer :: ierr, nprocs, my_rank, nq, iq1, iq2, iq3, i1, i2, i3, nmax(3)
722 : : real(dp) :: alfa, amin, gmax2, lavg, fsum, qpg2, qq(3), qpg(3), rmet(3,3), rr(3)
723 : : ! *************************************************************************
724 : :
725 : 57 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
726 : :
727 : : ! Real space metric rmet = gmet^-1 (matr3inv returns the transposed inverse, gmet is symmetric).
728 : 57 : call matr3inv(gmet, rmet)
729 : :
730 : : ! Shortest lattice vector.
731 : 57 : amin = huge(one)
732 [ + + ]: 228 : do i3=-1,1
733 [ + + ]: 741 : do i2=-1,1
734 [ + + ]: 2223 : do i1=-1,1
735 [ + + ]: 1539 : if (all([i1, i2, i3] == 0)) cycle
736 [ + + ]: 5928 : rr = [i1, i2, i3]
737 [ + + + + : 24225 : amin = min(amin, SQRT(DOT_PRODUCT(rr, MATMUL(rmet, rr))))
+ + ]
738 : : end do
739 : : end do
740 : : end do
741 : :
742 : 57 : alfa = (amin / four)**2
743 : 57 : gmax2 = alfa_gmax2 / alfa
744 : : ! Box of G-vectors containing the sphere |q+G| <= gmax for all q in the BZ (|a_i| = sqrt(rmet(i,i))).
745 [ + + ]: 228 : do i1=1,3
746 [ - + ]: 228 : nmax(i1) = ceiling(SQRT(gmax2) * SQRT(rmet(i1,i1)) / two_pi) + 1
747 : : end do
748 : :
749 : : ! Even grid with nq^3 >= 64 nqbz, at least 32^3.
750 [ - + ]: 57 : nq = max(32, 2*ceiling(half*(64.0_dp*nqbz)**third))
751 : 57 : lavg = carrier_limit(gmet)
752 : :
753 : 57 : fsum = zero
754 [ + + ]: 1881 : do iq1=0,nq-1
755 [ + - ]: 1824 : if (modulo(iq1, nprocs) /= my_rank) cycle ! MPI parallelism
756 [ + + ]: 60249 : do iq2=0,nq-1
757 [ + + ]: 1927968 : do iq3=0,nq-1
758 [ + + ]: 7471104 : qq = [iq1, iq2, iq3] / DBLE(nq)
759 [ + + ]: 7471104 : qq = qq - nint(qq)
760 : : ! F - F_G at q (q=0: q --> 0 limit, averaged over the directions)
761 [ + + ]: 1867776 : if (iq1 == 0 .and. iq2 == 0 .and. iq3 == 0) then
762 : 57 : fsum = fsum - lavg + alfa
763 : : else
764 : 1867719 : fsum = fsum + faux(qq, gmet)
765 : : end if
766 [ + + ]: 22471680 : do i3=-nmax(3),nmax(3)
767 [ + + ]: 248414208 : do i2=-nmax(2),nmax(2)
768 [ + + ]: 2732556288 : do i1=-nmax(1),nmax(1)
769 [ + + ]: 9944039424 : qpg = qq + [i1, i2, i3]
770 : : ! Exclude only q + G = 0 (no threshold on |q+G|: small q+G occur for large or elongated cells)
771 [ + + + + ]: 2486009856 : if (all([iq1, iq2, iq3] == 0) .and. all([i1, i2, i3] == 0)) cycle
772 [ + + + + : 39776156784 : qpg2 = two_pi**2 * DOT_PRODUCT(qpg, MATMUL(gmet, qpg))
+ + ]
773 [ + + ]: 2712010695 : if (qpg2 <= gmax2) fsum = fsum - EXP(-alfa*qpg2)/qpg2
774 : : end do
775 : : end do
776 : : end do
777 : : end do
778 : : end do
779 : : end do
780 : :
781 : 57 : call xmpi_sum(fsum, comm, ierr)
782 : :
783 : 57 : integratefaux = fsum / DBLE(nq)**3 + ucvol/four_pi/SQRT(pi*alfa)
784 : :
785 : 57 : end function integratefaux
786 : : !!***
787 : :
788 : : !!****f* m_vcoul/faux
789 : : !! NAME
790 : : !! faux
791 : : !!
792 : : !! FUNCTION
793 : : !! Auxiliary function of Carrier et al. [[cite:Carrier2007]], periodic in the reciprocal lattice:
794 : : !! F(q) = 1/D(q), D(q) = sum_i gmet_ii 4 sin^2(pi q_i) + 2 sum_{i<j} gmet_ij sin(2pi q_i) sin(2pi q_j)
795 : : !! (q in reduced coordinates). For q --> 0, D(q) --> |q|^2 (cartesian) and F(q) --> 1/|q|^2.
796 : : !!
797 : : !! INPUTS
798 : : !! qq(3)=q-point in reduced coordinates (not a reciprocal lattice vector).
799 : : !! gmet(3,3)=Reciprocal space metric (bohr^-2), without the factor (2pi)^2.
800 : : !!
801 : : !! SOURCE
802 : :
803 : 1869037 : real(dp) pure function faux(qq, gmet)
804 : :
805 : : !Arguments ------------------------------------
806 : : real(dp),intent(in) :: qq(3), gmet(3,3)
807 : :
808 : : !Local variables-------------------------------
809 : : real(dp) :: s2(3), s(3)
810 : : ! *************************************************************************
811 : :
812 [ + + ]: 7476148 : s2 = four * SIN(pi*qq)**2
813 [ + + ]: 7476148 : s = SIN(two_pi*qq)
814 : :
815 : : faux = one / (gmet(1,1)*s2(1) + gmet(2,2)*s2(2) + gmet(3,3)*s2(3) &
816 : 1869037 : + two*(gmet(1,2)*s(1)*s(2) + gmet(2,3)*s(2)*s(3) + gmet(3,1)*s(3)*s(1)))
817 : :
818 : 1869037 : end function faux
819 : : !!***
820 : :
821 : : !----------------------------------------------------------------------
822 : :
823 : : !!****f* m_vcoul/carrier_limit
824 : : !! NAME
825 : : !! carrier_limit
826 : : !!
827 : : !! FUNCTION
828 : : !! q --> 0 limit of 1/q^2 - F(q) for the auxiliary function F of Carrier et al. (see faux), averaged over the
829 : : !! directions of q. With u_i = q.a_i, the expansion of the sine functions gives
830 : : !! F(q) = 1/q^2 - L(qhat) + O(q^2), L = -[ sum_i gmet_ii u_i^4/12 + sum_{i<j} gmet_ij (u_i^3 u_j + u_i u_j^3)/3 ]/q^4
831 : : !! and the average over directions, <x_a x_b x_c x_d> = (d_ab d_cd + d_ac d_bd + d_ad d_bc)/15, gives
832 : : !! <L> = -1/5 [ sum_i gmet_ii rmet_ii^2/12 + sum_{i<j} gmet_ij rmet_ij (rmet_ii + rmet_jj)/3 ]
833 : : !!
834 : : !! INPUTS
835 : : !! gmet(3,3)=Reciprocal space metric (bohr^-2), without the factor (2pi)^2.
836 : : !!
837 : : !! SOURCE
838 : :
839 : 116 : real(dp) function carrier_limit(gmet) result(lavg)
840 : :
841 : : !Arguments ------------------------------------
842 : : real(dp),intent(in) :: gmet(3,3)
843 : :
844 : : !Local variables-------------------------------
845 : : integer :: ii, jj
846 : : real(dp) :: rmet(3,3)
847 : : ! *************************************************************************
848 : :
849 : : ! Real space metric rmet = gmet^-1 (matr3inv returns the transposed inverse, gmet is symmetric).
850 : 116 : call matr3inv(gmet, rmet)
851 : :
852 : 116 : lavg = zero
853 [ + + ]: 464 : do ii=1,3
854 : 348 : lavg = lavg + gmet(ii,ii) * rmet(ii,ii)**2 / 12.0_dp
855 [ + + ]: 812 : do jj=ii+1,3
856 : 696 : lavg = lavg + gmet(ii,jj) * rmet(ii,jj) * (rmet(ii,ii) + rmet(jj,jj)) / three
857 : : end do
858 : : end do
859 : 116 : lavg = -lavg / five
860 : :
861 : 116 : end function carrier_limit
862 : : !!***
863 : :
864 : : !----------------------------------------------------------------------
865 : :
866 : : !!****f* m_vcoul/adapt_nmc
867 : : !! NAME
868 : : !! adapt_nmc
869 : : !!
870 : : !! FUNCTION
871 : : !! Empirical law to decrease the Monte Carlo sampling for large |q+G|, for which the accuracy is not an issue
872 : :
873 : 3393 : integer pure function adapt_nmc(nmc_max, qpg2) result(nmc)
874 : :
875 : : !Arguments ------------------------------------
876 : : integer,intent(in) :: nmc_max
877 : : real(dp),intent(in) :: qpg2
878 : : ! *************************************************************************
879 : :
880 : 3393 : nmc = NINT( nmc_max / ( 1.0_dp + 1.0_dp * qpg2**6 ) )
881 : 3393 : nmc = MIN(nmc_max, nmc)
882 : 3393 : nmc = MAX(1, nmc)
883 : :
884 : 3393 : end function adapt_nmc
885 : : !!***
886 : :
887 : : !----------------------------------------------------------------------
888 : :
889 : : !!****f* m_vcoul/vcoul_plot
890 : : !! NAME
891 : : !! vcoul_plot
892 : : !!
893 : : !! FUNCTION
894 : : !! Plot vccut(q,G) as a function of |q+G|. Calculate also vc in real space.
895 : : !!
896 : : !! INPUTS
897 : : !!
898 : : !! OUTPUT
899 : : !!
900 : : !! SOURCE
901 : :
902 : 0 : subroutine vcoul_plot(Vcp, Qmesh, Gsph, ng, vc, comm)
903 : :
904 : : !Arguments ------------------------------------
905 : : !scalars
906 : : class(vcoul_t),intent(in) :: Vcp
907 : : integer,intent(in) :: ng, comm
908 : : type(kmesh_t),intent(in) :: Qmesh
909 : : type(gsphere_t),intent(in) :: Gsph
910 : : !arrays
911 : : real(dp),intent(in) :: vc(ng,Qmesh%nibz)
912 : :
913 : : !Local variables-------------------------------
914 : : !scalars
915 : : integer,parameter :: master = 0
916 : : integer :: icount,idx_Sm1G,ierr,ig,igs,ii,iq_bz,iq_ibz,iqg,ir,isym,itim
917 : : integer :: my_start,my_stop,nqbz,nqibz,nr,ntasks,my_rank,unt
918 : : real(dp) :: arg,fact,l1,l2,l3,lmax,step,tmp,vcft,vc_bare
919 : : character(len=500) :: msg
920 : : character(len=fnlen) :: filnam
921 : : !arrays
922 : 0 : integer,allocatable :: insort(:)
923 : : real(dp) :: b1(3),b2(3),b3(3),gmet(3,3),gprimd(3,3),qbz(3),qpgc(3)
924 : 0 : real(dp),allocatable :: qpg_mod(:),rr(:,:,:),vcr(:,:),vcr_cut(:,:)
925 : : !************************************************************************
926 : :
927 [ # # ]: 0 : if (trim(Vcp%mode) /= 'CYLINDER') RETURN
928 : :
929 : 0 : my_rank = xmpi_comm_rank(comm)
930 : :
931 : 0 : nqibz=Vcp%nqibz; nqbz=Qmesh%nbz
932 [ # # # # : 0 : gmet=Gsph%gmet; gprimd=Gsph%gprimd
# # # # ]
933 : :
934 [ # # ]: 0 : b1(:)=two_pi*gprimd(:,1)
935 [ # # ]: 0 : b2(:)=two_pi*gprimd(:,2)
936 [ # # ]: 0 : b3(:)=two_pi*gprimd(:,3)
937 : :
938 : : ! Compare in Fourier space the true Coulomb with the cutted one.
939 [ # # ]: 0 : if (my_rank == master) then
940 [ # # # # : 0 : ABI_MALLOC(insort, (nqibz * ng))
# # # # #
# # # ]
941 [ # # # # : 0 : ABI_MALLOC(qpg_mod, (nqibz * ng))
# # # # #
# # # ]
942 : 0 : iqg = 1
943 [ # # ]: 0 : do iq_ibz=1,nqibz
944 [ # # ]: 0 : do ig=1,ng
945 [ # # # # ]: 0 : qpg_mod(iqg) = normv(Qmesh%ibz(:,iq_ibz) + Gsph%gvec(:,ig), gmet,'g')
946 : 0 : insort(iqg) = iqg; iqg = iqg + 1
947 : : end do
948 : : end do
949 : 0 : call sort_dp(nqibz * ng, qpg_mod, insort, tol14)
950 : :
951 : 0 : filnam='_VCoulFT_'
952 : 0 : call isfile(filnam, 'new')
953 [ # # ]: 0 : if (open_file(filnam, msg, newunit=unt, status='new', form='formatted') /= 0) then
954 : 0 : ABI_ERROR(msg)
955 : : end if
956 : : write(unt,'(a,i3,a,i6,a)')&
957 : 0 : '# |q+G| q-point (Tot no.',nqibz,') Gvec (',ng,') vc_bare(q,G) vc_cutoff(q,G) '
958 : :
959 [ # # ]: 0 : do iqg=1,nqibz*ng
960 : 0 : iq_ibz = (insort(iqg) - 1) / ng + 1
961 : 0 : ig = (insort(iqg)) - (iq_ibz-1) * ng
962 : 0 : vc_bare = zero
963 [ # # ]: 0 : if (qpg_mod(iqg) > tol16) vc_bare = four_pi / qpg_mod(iqg) ** 2
964 : : write(unt,'(f12.6,2x,3f8.4,2x,3i6,2x,2es14.6)')&
965 : 0 : qpg_mod(iqg), Qmesh%ibz(:,iq_ibz), Gsph%gvec(:,ig), vc_bare, vc(ig, iq_ibz)
966 : : end do
967 : :
968 : 0 : close(unt)
969 [ # # ]: 0 : ABI_FREE(insort)
970 [ # # ]: 0 : ABI_FREE(qpg_mod)
971 : : end if ! my_rank==master
972 : :
973 : : ! Fourier transform back to real space just to check cutoff implementation.
974 : 0 : ntasks= nqbz * ng
975 : 0 : call xmpi_split_work(ntasks, comm, my_start, my_stop)
976 : :
977 [ # # # # : 0 : l1 = NORM2(Vcp%rprimd(:,1))
# # ]
978 [ # # # # : 0 : l2 = NORM2(Vcp%rprimd(:,2))
# # ]
979 [ # # # # : 0 : l3 = NORM2(Vcp%rprimd(:,3))
# # ]
980 : :
981 : 0 : nr = 50
982 : 0 : lmax=MAX(l1,l2,l3) ; step=lmax/(nr-1)
983 : 0 : fact = one / (Vcp%ucvol * nqbz)
984 : :
985 : : ! numb coding
986 [ # # # # : 0 : ABI_CALLOC(rr, (3, nr, 3))
# # # # ]
987 [ # # ]: 0 : do ir=1,nr
988 [ # # # # ]: 0 : rr(1:3,ir,1:3)=(ir-1)*step
989 : : end do
990 : :
991 [ # # # # : 0 : ABI_CALLOC(vcr, (nr, 3))
# # ]
992 [ # # # # : 0 : ABI_CALLOC(vcr_cut, (nr, 3))
# # ]
993 : :
994 [ # # ]: 0 : do iq_bz=1,nqbz
995 : 0 : call Qmesh%get_BZ_item(iq_bz, qbz, iq_ibz, isym, itim)
996 [ # # ]: 0 : if (ABS(qbz(1))<0.01) qbz(1)=zero
997 [ # # ]: 0 : if (ABS(qbz(2))<0.01) qbz(2)=zero
998 [ # # ]: 0 : if (ABS(qbz(3))<0.01) qbz(3)=zero
999 [ # # # # : 0 : igs=1; if (ALL(qbz(:)==zero)) igs=2
# # ]
1000 [ # # ]: 0 : do ig=igs,ng
1001 : 0 : icount=ig+(iq_bz-1)*ng
1002 [ # # # # ]: 0 : if (icount < my_start .or. icount > my_stop) CYCLE
1003 : 0 : idx_Sm1G = Gsph%rottbm1(ig,itim,isym) ! IS{^-1}G
1004 : 0 : vcft=vc(idx_Sm1G,iq_ibz)
1005 [ # # # # ]: 0 : qpgc(:)=qbz(:)+Gsph%gvec(:,ig) ; qpgc(:)=b1(:)*qpgc(1)+b2(:)*qpgc(2)+b3(:)*qpgc(3)
1006 [ # # # # : 0 : tmp=NORM2(qpgc) ; tmp=tmp**2
# # ]
1007 [ # # ]: 0 : do ii=1,3
1008 [ # # ]: 0 : do ir=1,nr
1009 [ # # ]: 0 : arg=DOT_PRODUCT(rr(:,ir,ii),qpgc)
1010 : 0 : vcr_cut(ir,ii)=vcr_cut(ir,ii) + vcft*COS(arg)
1011 : 0 : vcr (ir,ii)=vcr (ir,ii) + four_pi/tmp*COS(arg)
1012 : : end do
1013 : : end do
1014 : : end do !ig
1015 : : end do !iq_ibz
1016 : :
1017 : 0 : call xmpi_sum_master(vcr_cut,master,comm,ierr)
1018 : 0 : call xmpi_sum_master(vcr ,master,comm,ierr)
1019 : :
1020 [ # # ]: 0 : if (my_rank == master) then
1021 : 0 : filnam='_VCoulR_'
1022 : 0 : call isfile(filnam, 'new')
1023 [ # # ]: 0 : if (open_file(filnam,msg,newunit=unt,status='new',form='formatted') /= 0) then
1024 : 0 : ABI_ERROR(msg)
1025 : : end if
1026 : 0 : write(unt,'(a)')'# length vc_bare(r) vc_cut(r) '
1027 [ # # ]: 0 : do ir=1,nr
1028 [ # # # # ]: 0 : write(unt,'(7es18.6)')(ir-1)*step,(fact*vcr(ir,ii),fact*vcr_cut(ir,ii),ii=1,3)
1029 : : end do
1030 : 0 : close(unt)
1031 : : end if
1032 : :
1033 [ # # ]: 0 : ABI_FREE(rr)
1034 [ # # ]: 0 : ABI_FREE(vcr)
1035 [ # # ]: 0 : ABI_FREE(vcr_cut)
1036 : :
1037 : 0 : end subroutine vcoul_plot
1038 : : !!***
1039 : :
1040 : : !----------------------------------------------------------------------
1041 : :
1042 : : !!****f* m_vcoul/vcoul_print
1043 : : !! NAME
1044 : : !! vcoul_print
1045 : : !!
1046 : : !! FUNCTION
1047 : : !! Print info on a Coulomb datatype.
1048 : : !!
1049 : : !! INPUTS
1050 : : !! units=Unit numbers for output
1051 : : !! [prtvol]=Verbosity level
1052 : : !!
1053 : : !! SOURCE
1054 : :
1055 [ - + ]: 415 : subroutine vcoul_print(Vcp, units, prtvol)
1056 : :
1057 : : !Arguments ------------------------------------
1058 : : !scalars
1059 : : class(vcoul_t),intent(in) :: Vcp
1060 : : integer,intent(in) :: units(:)
1061 : : integer,intent(in),optional :: prtvol
1062 : :
1063 : : !Local variables-------------------------------
1064 : : !scalars
1065 : : integer :: ii, my_prtvol, iqlwl
1066 : : character(len=500) :: msg
1067 : : ! *************************************************************************
1068 : :
1069 : 415 : my_prtvol=0; if (PRESENT(prtvol)) my_prtvol=prtvol
1070 : :
1071 : 416 : select case (Vcp%mode)
1072 : :
1073 : : case ('MINIBZ')
1074 : 1 : write(msg,'(3a)')ch10,' vcoul_init : cutoff-mode = ',trim(Vcp%mode)
1075 : 1 : call wrtout(units, msg)
1076 : :
1077 : : case ('MINIBZ-ERF')
1078 : 1 : write(msg,'(3a)')ch10,' vcoul_init : cutoff-mode = ',trim(Vcp%mode)
1079 : 1 : call wrtout(units, msg)
1080 : 1 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
1081 : 1 : ' === Error function cutoff === ',ch10,ch10,&
1082 : 2 : ' Cutoff radius ......... ',Vcp%rcut,' [Bohr] ',ch10
1083 : 1 : call wrtout(units, msg)
1084 : :
1085 : : case ('MINIBZ-ERFC')
1086 : 1 : write(msg,'(3a)')ch10,' vcoul_init : cutoff-mode = ',trim(Vcp%mode)
1087 : 1 : call wrtout(units, msg)
1088 : 1 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
1089 : 1 : ' === Complement Error function cutoff === ',ch10,ch10,&
1090 : 2 : ' Cutoff radius ......... ',Vcp%rcut,' [Bohr] ',ch10
1091 : 1 : call wrtout(units, msg)
1092 : :
1093 : : case ('SPHERE')
1094 : 46 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
1095 : 46 : ' === Spherical cutoff === ',ch10,ch10,&
1096 : 46 : ' Cutoff radius ......... ',Vcp%rcut,' [Bohr] ',ch10,&
1097 : 92 : ' Volume of the sphere .. ',four_pi/three*Vcp%rcut**3,' [Bohr^3] '
1098 : : !FB: This has no meaning here! & ' Sphere centered at .... ',Vcp%boxcenter,' (r.l.u) ',ch10
1099 : : !MG It might be useful if the system is not centered on the origin because in this case the
1100 : : ! matrix elements of the Coulomb have to be multiplied by a phase depending on boxcenter.
1101 : : ! I still have to decide if it is useful to code this possibility and which variable use to
1102 : : ! define the center (boxcenter is used in the tddft part).
1103 : 46 : call wrtout(units, msg)
1104 : :
1105 : : case ('CYLINDER')
1106 [ + + ]: 8 : ii=imin_loc(ABS(Vcp%pdir-1))
1107 : 2 : write(msg,'(5a,f10.4,3a,i2,2a,3f10.2,a)')ch10,&
1108 : 2 : ' === Cylindrical cutoff === ',ch10,ch10,&
1109 : 2 : ' Cutoff radius ............... ',Vcp%rcut,' [Bohr] ',ch10,&
1110 : 2 : ' Axis parallel to direction... ',ii,ch10,&
1111 : 4 : ' Passing through point ....... ',Vcp%boxcenter,' (r.l.u) '
1112 : 2 : call wrtout(units, msg)
1113 : :
1114 : 2 : write(msg,'(2a)')' Infinite length ....... ',ch10
1115 [ + + ]: 2 : if (Vcp%hcyl/=zero) write(msg,'(a,f8.5,2a)')' Finite length of ....... ',Vcp%hcyl,' [Bohr] ',ch10
1116 : 2 : call wrtout(units, msg)
1117 : :
1118 : : CASE ('SLAB')
1119 : 0 : write(msg,'(5a,f10.4,3a,3f10.2,2a)')ch10,&
1120 : 0 : ' === Surface cutoff === ',ch10,ch10,&
1121 : 0 : ' Cutoff radius .................... ',Vcp%rcut,' [Bohr] ',ch10,&
1122 : 0 : ' Central plane passing through .... ',Vcp%boxcenter,' (r.l.u) ',ch10
1123 : 0 : call wrtout(units, msg)
1124 : : !write(msg,'(a)')' Infinite length .......'
1125 : : !if (Vcp%hcyl/=zero) write(msg,'(a,f8.5,a)')' Finite length of .......',Vcp%hcyl,' [Bohr] '
1126 : : !call wrtout(units, msg)
1127 : :
1128 : : case ('AUXILIARY_FUNCTION')
1129 : 57 : write(msg,'(3a)')ch10,' vcoul_init : cutoff-mode = ',trim(Vcp%mode)
1130 : 57 : call wrtout(units, msg)
1131 : :
1132 : : case ('AUX_GB')
1133 : 170 : write(msg,'(3a)')ch10,' vcoul_init : cutoff-mode = ',trim(Vcp%mode)
1134 : 170 : call wrtout(units, msg)
1135 : :
1136 : : case ('CRYSTAL')
1137 : 117 : write(msg,'(3a)')ch10,' vcoul_init : cutoff-mode = ',trim(Vcp%mode)
1138 : 117 : call wrtout(units, msg)
1139 : :
1140 : : case ('ERF')
1141 : 2 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
1142 : 2 : ' === Error function cutoff === ',ch10,ch10,&
1143 : 4 : ' Cutoff radius ......... ',Vcp%rcut,' [Bohr] ',ch10
1144 : 2 : call wrtout(units, msg)
1145 : :
1146 : : case ('ERFC')
1147 : 18 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
1148 : 18 : ' === Complement Error function cutoff === ',ch10,ch10,&
1149 : 36 : ' Cutoff radius ......... ',Vcp%rcut,' [Bohr] ',ch10
1150 : 18 : call wrtout(units, msg)
1151 : :
1152 : : case default
1153 [ + + + + : 415 : ABI_BUG(sjoin('Unknown cutoff mode: ', Vcp%mode))
+ - + + +
+ + - ]
1154 : : end select
1155 : :
1156 [ + - ]: 415 : if (Vcp%nqlwl > 0) then
1157 : 415 : write(msg,'(a,i3)')" q-points for optical limit: ",Vcp%nqlwl
1158 : 415 : call wrtout(units, msg)
1159 [ + + ]: 830 : do iqlwl=1,Vcp%nqlwl
1160 : 415 : write(msg,'(1x,i5,a,2x,3f12.6)') iqlwl,')',Vcp%qlwl(:,iqlwl)
1161 : 830 : call wrtout(units, msg)
1162 : : end do
1163 : : end if
1164 : :
1165 : 415 : end subroutine vcoul_print
1166 : : !!***
1167 : :
1168 : : !----------------------------------------------------------------------
1169 : :
1170 : : !!****f* m_vcoul/vcoul_free
1171 : : !! NAME
1172 : : !! vcoul_free
1173 : : !!
1174 : : !! FUNCTION
1175 : : !! Free dynamic memory
1176 : : !!
1177 : : !! SOURCE
1178 : :
1179 : 412 : subroutine vcoul_free(Vcp)
1180 : :
1181 : : !Arguments ------------------------------------
1182 : : class(vcoul_t),intent(inout) :: Vcp
1183 : : ! *************************************************************************
1184 : :
1185 [ + - ]: 412 : ABI_SFREE(Vcp%qibz)
1186 [ + - ]: 412 : ABI_SFREE(Vcp%qlwl)
1187 [ + - ]: 412 : ABI_SFREE(Vcp%vc_sqrt)
1188 [ + - ]: 412 : ABI_SFREE(Vcp%vc_sqrt_resid)
1189 [ + - ]: 412 : ABI_SFREE(Vcp%vcqlwl_sqrt)
1190 : :
1191 : 412 : end subroutine vcoul_free
1192 : : !!***
1193 : :
1194 : : !----------------------------------------------------------------------
1195 : :
1196 : : !!****f* m_vcoul/mc_init
1197 : : !! NAME
1198 : : !! mc_init
1199 : : !!
1200 : : !! FUNCTION
1201 : : !!
1202 : : !! SOURCE
1203 : :
1204 : 3 : subroutine mc_init(mc, rprimd, ucvol, gprimd, gmet, kptrlatt)
1205 : :
1206 : : !Arguments ------------------------------------
1207 : : class(mc_t),intent(out) :: mc
1208 : : real(dp),intent(in) :: rprimd(3,3), ucvol, gprimd(3,3), gmet(3,3)
1209 : : integer,intent(in) :: kptrlatt(3,3)
1210 : :
1211 : : !Local variables-------------------------------
1212 : : integer,parameter :: ncell=3
1213 : : integer :: nseed, i1,i2,i3,imc
1214 : : real(dp) :: lmin,vlength, ucvol_sc
1215 : : real(dp) :: rprimd_sc(3,3),gprimd_sc(3,3),gmet_sc(3,3),rmet_sc(3,3), qcart2red(3,3), qtmp(3),qmin(3),qmin_cart(3)
1216 [ + - ]: 3 : integer, allocatable :: seed(:)
1217 : : ! *************************************************************************
1218 : :
1219 [ + + + + ]: 39 : mc%gmet = gmet; mc%ucvol = ucvol
1220 : :
1221 : : ! Supercell defined by the k-mesh
1222 [ + + + + : 156 : rprimd_sc(:,:) = MATMUL(rprimd, kptrlatt)
+ + + + +
+ ]
1223 : 3 : call metric(gmet_sc, gprimd_sc, -1, rmet_sc, rprimd_sc, ucvol_sc)
1224 : :
1225 [ + + + + ]: 39 : qcart2red(:,:) = two_pi * gprimd(:,:)
1226 : 3 : call matrginv(qcart2red, 3, 3)
1227 : :
1228 : : ! Find the largest sphere inside the miniBZ in order to integrate the divergence analytically
1229 : 3 : mc%q0sph = HUGE(one)
1230 [ + + ]: 21 : do i1 = -ncell+1, ncell
1231 : 18 : qtmp(1) = dble(i1) * 0.5_dp
1232 [ + + ]: 129 : do i2 = -ncell+1, ncell
1233 : 108 : qtmp(2) = dble(i2) * 0.5_dp
1234 [ + + ]: 774 : do i3 = -ncell+1, ncell
1235 : 648 : qtmp(3) = dble(i3) * 0.5_dp
1236 [ + + ]: 648 : if (i1 == 0 .AND. i2 == 0 .AND. i3 == 0) cycle
1237 : 645 : vlength = normv(qtmp, gmet_sc, 'G')
1238 [ + + ]: 753 : if (vlength < mc%q0sph) mc%q0sph = vlength
1239 : : enddo
1240 : : enddo
1241 : : enddo
1242 : :
1243 : : ! Setup the random vectors for the Monte Carlo sampling of the miniBZ at q = 0
1244 : 3 : mc%nmc_max = 2500000
1245 [ - + - + ]: 3 : ABI_MALLOC(mc%qran,(3, mc%nmc_max))
1246 : 3 : call random_seed(size=nseed)
1247 [ - + + - : 9 : ABI_MALLOC(seed, (nseed))
+ - + - -
+ - + -
+ ]
1248 [ + + ]: 27 : do i1=1,nseed
1249 : 27 : seed(i1) = NINT(SQRT(DBLE(i1) * 103731))
1250 : : end do
1251 : 3 : call random_seed(put=seed)
1252 : 3 : call random_number(mc%qran)
1253 [ - + ]: 3 : ABI_FREE(seed)
1254 : :
1255 : : ! Overide the first "random vector" with 0
1256 [ + + ]: 12 : mc%qran(:,1) = zero
1257 : :
1258 : : ! Fold qran into the Wignez-Seitz cell around q = 0
1259 [ + + ]: 7500000 : do imc=2,mc%nmc_max
1260 : : lmin = HUGE(one)
1261 [ + + ]: 52499979 : do i1 = -ncell+1, ncell
1262 : 44999982 : qtmp(1) = mc%qran(1,imc) + dble(i1)
1263 [ + + ]: 322499871 : do i2 = -ncell+1, ncell
1264 : 269999892 : qtmp(2) = mc%qran(2,imc) + dble(i2)
1265 [ + + ]: 1934999226 : do i3 = -ncell+1, ncell
1266 : 1619999352 : qtmp(3) = mc%qran(3,imc) + dble(i3)
1267 : 1619999352 : vlength = normv(qtmp, gmet_sc, 'G')
1268 [ + + ]: 1889999244 : if (vlength < lmin) then
1269 : 42272448 : lmin = vlength
1270 : : ! Get the q-vector in cartesian coordinates
1271 [ + + + + : 676359168 : qmin_cart(:) = two_pi * MATMUL( gprimd_sc(:,:) , qtmp )
+ + ]
1272 : : ! Transform it back to the reciprocal space
1273 [ + + + + ]: 549541824 : qmin(:) = MATMUL(qcart2red , qmin_cart)
1274 : : end if
1275 : : enddo
1276 : : enddo
1277 : : enddo
1278 : :
1279 [ + + ]: 29999991 : mc%qran(:,imc) = qmin(:)
1280 : : enddo
1281 : :
1282 [ - + ]: 3 : end subroutine mc_init
1283 : : !!***
1284 : :
1285 : : !----------------------------------------------------------------------
1286 : :
1287 : : !!****f* m_vcoul/mc_integrate
1288 : : !! NAME
1289 : : !! mc_integrate
1290 : : !!
1291 : : !! FUNCTION
1292 : : !!
1293 : : !! SOURCE
1294 : :
1295 : 12 : subroutine mc_integrate(mc, mode, qibz, ng, gvec, rcut2, nkbz, vcoul, comm)
1296 : :
1297 : : !Arguments ------------------------------------
1298 : : class(mc_t),intent(in) :: mc
1299 : : real(dp),intent(in) :: rcut2
1300 : : integer,intent(in) :: nkbz, ng, comm
1301 : : character(len=*),intent(in) :: mode
1302 : : real(dp),intent(in) :: qibz(3)
1303 : : integer,intent(in) :: gvec(3, ng)
1304 : : real(dp),intent(out) :: vcoul(ng)
1305 : :
1306 : : !Local variables-------------------------------
1307 : : integer,parameter :: master = 0
1308 : : integer :: ig, ig0, imc, nmc, my_rank, nprocs, ierr
1309 : : logical :: q_is_gamma
1310 : : real(dp) :: qpg2, qpg(3)
1311 : : ! *************************************************************************
1312 : :
1313 : 12 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
1314 [ + + + + ]: 21 : q_is_gamma = all(abs(qibz) < tol16)
1315 : :
1316 : : ! Find index of G=0 in gvec.
1317 : 12 : ig0 = -1
1318 [ + - ]: 12 : do ig=1,ng
1319 [ + + + - : 48 : if (all(gvec(:, ig) == 0)) then
- + ]
1320 : : ig0 = ig; exit
1321 : : end if
1322 : : end do
1323 [ - + ]: 12 : ABI_CHECK(ig0 /= -1, "Cannot find G=0 in gvec!")
1324 : :
1325 [ + + ]: 3408 : vcoul = zero
1326 : :
1327 : 12 : select case (trim(mode))
1328 : :
1329 : : case ('MINIBZ')
1330 [ + + ]: 1136 : do ig=1,ng
1331 [ + - ]: 1132 : if (mod(ig, nprocs) /= my_rank) cycle ! MPI parallelism.
1332 [ + + ]: 1132 : if (q_is_gamma .and. ig == ig0) cycle
1333 [ + + ]: 4524 : qpg(:) = qibz(:) + gvec(:,ig)
1334 : 1131 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1335 : 1131 : nmc = adapt_nmc(mc%nmc_max, qpg2)
1336 [ + + ]: 43850951 : do imc=1,nmc
1337 [ + + ]: 175399264 : qpg(:) = qibz(:) + gvec(:,ig) + mc%qran(:,imc)
1338 : 43849816 : qpg2 = normv(qpg, mc%gmet, 'G') ** 2
1339 : 43850948 : vcoul(ig) = vcoul(ig) + four_pi / qpg2 / REAL(nmc, dp)
1340 : : end do
1341 : : end do ! ig
1342 : :
1343 [ + + ]: 4 : if (q_is_gamma .and. my_rank == master) then
1344 : : ! Compute ig0 component
1345 : 1 : vcoul(ig0) = four_pi**2 * nkbz * mc%ucvol / ( 8.0_dp * pi**3 ) * mc%q0sph
1346 [ + + ]: 2500001 : do imc=1,mc%nmc_max
1347 [ + + ]: 10000000 : qpg(:) = qibz(:) + gvec(:,ig0) + mc%qran(:,imc)
1348 : 2500000 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1349 [ + + ]: 2500001 : if (qpg2 > mc%q0sph ** 2) vcoul(ig0) = vcoul(ig0) + four_pi / qpg2 / REAL(mc%nmc_max, dp)
1350 : : end do
1351 : : end if
1352 : :
1353 : : case ('MINIBZ-ERFC')
1354 [ + + ]: 1136 : do ig=1,ng
1355 [ + - ]: 1132 : if (mod(ig, nprocs) /= my_rank) cycle ! MPI parallelism.
1356 [ + + ]: 1132 : if (q_is_gamma .and. ig == ig0) cycle
1357 [ + + ]: 4524 : qpg(:) = qibz(:) + gvec(:,ig)
1358 : 1131 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1359 : 1131 : nmc = adapt_nmc(mc%nmc_max, qpg2)
1360 [ + + ]: 43850951 : do imc=1,nmc
1361 [ + + ]: 175399264 : qpg(:) = qibz(:) + gvec(:,ig) + mc%qran(:,imc)
1362 : 43849816 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1363 : 43850948 : vcoul(ig) = vcoul(ig) + four_pi / qpg2 / REAL(nmc,dp) * ( one - EXP( -0.25d0 * rcut2 * qpg2 ) )
1364 : : end do
1365 : : end do ! ig
1366 : :
1367 [ + + ]: 4 : if (q_is_gamma .and. my_rank == master) then
1368 : : ! Override ig0 component
1369 : : vcoul(ig0) = four_pi**2 * nkbz * mc%ucvol / ( 8.0_dp * pi**3 ) &
1370 : 1 : * ( mc%q0sph - SQRT(pi/rcut2) * abi_derf(0.5_dp*SQRT(rcut2)*mc%q0sph) )
1371 [ + + ]: 2500001 : do imc=1,mc%nmc_max
1372 [ + + ]: 10000000 : qpg(:) = qibz(:) + gvec(:,ig0) + mc%qran(:,imc)
1373 : 2500000 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1374 [ + + ]: 2500001 : if (qpg2 > mc%q0sph**2) then
1375 : 800113 : vcoul(ig0) = vcoul(ig0) + four_pi / qpg2 / REAL(mc%nmc_max,dp) * (one - EXP( -0.25d0 * rcut2 * qpg2))
1376 : : end if
1377 : : end do
1378 : : end if
1379 : :
1380 : : case ('MINIBZ-ERF')
1381 [ + + ]: 1136 : do ig=1,ng
1382 [ + - ]: 1132 : if (mod(ig, nprocs) /= my_rank) cycle ! MPI parallelism.
1383 [ + + ]: 1132 : if (q_is_gamma .and. ig == ig0) cycle
1384 [ + + ]: 4524 : qpg(:) = qibz(:) + gvec(:,ig)
1385 : 1131 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1386 : 1131 : nmc = adapt_nmc(mc%nmc_max, qpg2)
1387 [ + + ]: 43850951 : do imc=1,nmc
1388 [ + + ]: 175399264 : qpg(:) = qibz(:) + gvec(:,ig) + mc%qran(:,imc)
1389 : 43849816 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1390 : 43850948 : vcoul(ig) = vcoul(ig) + four_pi / qpg2 / REAL(nmc,dp) * EXP( -0.25d0 * rcut2 * qpg2 )
1391 : : end do
1392 : : end do ! ig
1393 : :
1394 [ + + ]: 4 : if (q_is_gamma .and. my_rank == master) then
1395 : : ! Override ig=ig0 component
1396 : 1 : vcoul(ig0) = four_pi**2 * nkbz * mc%ucvol / ( 8.0_dp * pi**3 ) * SQRT(pi/rcut2) * abi_derf(0.5_dp*SQRT(rcut2)*mc%q0sph)
1397 : :
1398 [ + + ]: 2500001 : do imc=1,mc%nmc_max
1399 [ + + ]: 10000000 : qpg(:) = qibz(:) + gvec(:,ig0) + mc%qran(:,imc)
1400 : 2500000 : qpg2 = normv(qpg, mc%gmet, 'G')**2
1401 [ + + ]: 2500001 : if (qpg2 > mc%q0sph**2) then
1402 : 800113 : vcoul(ig0) = vcoul(ig0) + four_pi / qpg2 / REAL(mc%nmc_max,dp) * EXP( -0.25d0 * rcut2 * qpg2 )
1403 : : end if
1404 : : end do
1405 : : end if
1406 : :
1407 : : case default
1408 [ + + + - ]: 12 : ABI_ERROR(sjoin("Invalid mode:", mode))
1409 : : end select
1410 : :
1411 : : ! Collect result on each MPI proc.
1412 : 12 : call xmpi_sum(vcoul, comm, ierr)
1413 : :
1414 : 12 : end subroutine mc_integrate
1415 : : !!***
1416 : :
1417 : : !----------------------------------------------------------------------
1418 : :
1419 : : !!****f* m_vcoul/mc_free
1420 : : !! NAME
1421 : : !! mc_free
1422 : : !!
1423 : : !! FUNCTION
1424 : : !! Free dynamic memory
1425 : : !!
1426 : : !! SOURCE
1427 : :
1428 : 3 : subroutine mc_free(mc)
1429 : :
1430 : : !Arguments ------------------------------------
1431 : : class(mc_t),intent(inout) :: mc
1432 : : ! *************************************************************************
1433 : :
1434 [ + - ]: 3 : ABI_SFREE(mc%qran)
1435 : :
1436 : 3 : end subroutine mc_free
1437 : : !!***
1438 : :
1439 : : !----------------------------------------------------------------------
1440 : :
1441 : : !!****f* m_vcoul/beigi_cylinder_limit
1442 : : !! NAME
1443 : : !! beigi_cylinder_limit
1444 : : !!
1445 : : !! FUNCTION
1446 : : !!
1447 : : !! SOURCE
1448 : :
1449 : 1 : subroutine beigi_cylinder_limit(opt_cylinder, cryst, nqibz, nkbz, rcut, hcyl, boxcenter, pdir, i_sz)
1450 : :
1451 : : !Arguments ------------------------------------
1452 : : integer,intent(in) :: opt_cylinder, nqibz, nkbz, pdir(3)
1453 : : type(crystal_t),intent(in) :: cryst
1454 : : real(dp),intent(in) :: rcut, hcyl, boxcenter(3)
1455 : : real(dp),intent(out) :: i_sz
1456 : :
1457 : : !Local variables-------------------------------
1458 : : integer :: ii, iq, npar, npt, gamma_pt(3,1)
1459 : : real(dp) :: step, bz_plane, dx, integ, q0_vol, q0_volsph, b1(3),b2(3),b3(3)
1460 : 1 : real(dp),allocatable :: cov(:,:),par(:),qfit(:,:),sigma(:),var(:), vcfit(:,:),xx(:),yy(:)
1461 : : ! *************************************************************************
1462 : :
1463 [ + + + + ]: 7 : b1 = two_pi * cryst%gprimd(:,1); b2 = two_pi * cryst%gprimd(:,2); b3 = two_pi * cryst%gprimd(:,3)
1464 : :
1465 : 1 : npt =100
1466 : 1 : npar=8; gamma_pt = RESHAPE(([0, 0, 0]), [3, 1])
1467 [ - + ]: 1 : ABI_MALLOC(qfit, (3, npt))
1468 [ - + ]: 1 : ABI_MALLOC(vcfit, (1, npt))
1469 [ - + ]: 1 : if (nqibz == 1) then
1470 : 0 : ABI_ERROR("nqibz == 1 not supported when Beigi's method is used")
1471 : : endif
1472 [ + + + + ]: 401 : qfit(:,:)=zero
1473 [ + + ]: 101 : step=half/(npt * (nqibz-1)) ; qfit(3,:)=arth(tol6,step,npt)
1474 : : !step=(half/(nqibz-1)/tol6)**(one/npt) ; qfit(3,:)=geop(tol6,step,npt)
1475 : :
1476 [ + + ]: 101 : do iq=1,npt
1477 : : call cutoff_cylinder(qfit(:,iq),1,gamma_pt,rcut,hcyl,pdir,boxcenter,&
1478 : 101 : Cryst%rprimd,vcfit(:,iq),opt_cylinder, xmpi_comm_self)
1479 : : end do
1480 : :
1481 [ - + ]: 1 : ABI_MALLOC(xx, (npt))
1482 [ - + ]: 1 : ABI_MALLOC(yy, (npt))
1483 [ - + ]: 1 : ABI_MALLOC(sigma, (npt))
1484 [ - + ]: 1 : ABI_MALLOC(par, (npar))
1485 [ - + ]: 1 : ABI_MALLOC(var, (npar))
1486 [ - + ]: 1 : ABI_MALLOC(cov, (npar, npar))
1487 : :
1488 [ + + ]: 101 : do ii=1,npt
1489 : 101 : xx(ii) = normv(qfit(:,ii), cryst%gmet, 'G')
1490 : : end do
1491 [ - + ]: 1 : ABI_FREE(qfit)
1492 [ + + + + ]: 201 : sigma=one ; yy(:)=vcfit(1,:)
1493 [ - + ]: 1 : ABI_FREE(vcfit)
1494 : : !call llsfit_svd(xx,yy,sigma,npar,K0fit,chisq,par,var,cov,info)
1495 : : !do ii=1,npt
1496 : : ! write(99,*)xx(ii),yy(ii),DOT_PRODUCT(par,K0fit(xx(ii),npar))
1497 : : !end do
1498 : 1 : bz_plane=l2norm(b1.x.b2)
1499 : : !integ=K0fit_int(xx(npt),par,npar)
1500 : : !write(std_out,*)' SVD fit : chi-square',chisq
1501 : : !write(std_out,*)' fit-parameters : ',par
1502 : : !write(std_out,*)' variance ',var
1503 : : !write(std_out,*)' bz_plane ',bz_plane
1504 : : !write(std_out,*)' SCD integ ',integ
1505 : : ! Here Im assuming homogeneous mesh
1506 : 1 : dx=(xx(2)-xx(1))
1507 : 1 : integ=yy(2)*dx*3.0/2.0
1508 [ + + ]: 97 : integ=integ+SUM(yy(3:npt-2))*dx
1509 : 1 : integ=integ+yy(npt-1)*dx*3.0/2.0
1510 : : !write(std_out,*)' simple integral',integ
1511 : 1 : q0_volsph = (two_pi)**3 / (nkbz * cryst%ucvol)
1512 : 1 : q0_vol=bz_plane*two*xx(npt)
1513 : : !write(std_out,*)' q0 sphere : ',q0_volsph,' q0_vol cyl ',q0_vol
1514 : 1 : i_sz = bz_plane * two * integ / q0_vol
1515 : : !write(std_out,*)' spherical approximation ',four_pi*7.44*q0_volsph**(-two_thirds)
1516 : : !write(std_out,*)' Cylindrical cutoff value ',i_sz
1517 : : !i_sz=four_pi*7.44*q0_vol**(-two_thirds)
1518 : :
1519 : 1 : ABI_FREE(xx)
1520 : 1 : ABI_FREE(yy)
1521 [ - + ]: 1 : ABI_FREE(sigma)
1522 [ - + ]: 1 : ABI_FREE(par)
1523 [ - + ]: 1 : ABI_FREE(var)
1524 [ - + ]: 1 : ABI_FREE(cov)
1525 : :
1526 : 1 : end subroutine beigi_cylinder_limit
1527 : : !!***
1528 : :
1529 : : !----------------------------------------------------------------------
1530 : :
1531 : : !!****f* m_vcoul/beigi_surface_limit
1532 : : !! NAME
1533 : : !! beigi_surface_limit
1534 : : !!
1535 : : !! FUNCTION
1536 : : !!
1537 : : !! SOURCE
1538 : :
1539 : 0 : subroutine beigi_surface_limit(opt_slab, cryst, nqibz, nkbz, rcut, alpha, boxcenter, pdir, i_sz)
1540 : :
1541 : : !Arguments ------------------------------------
1542 : : integer,intent(in) :: opt_slab, nqibz, nkbz, pdir(3)
1543 : : type(crystal_t),intent(in) :: cryst
1544 : : real(dp),intent(in) :: rcut, alpha(3), boxcenter(3)
1545 : : real(dp),intent(out) :: i_sz
1546 : :
1547 : : !Local variables-------------------------------
1548 : : integer :: ii, npt, gamma_pt(3,1)
1549 : : real(dp) :: step, bz_plane, dx, integ, q0_vol, q0_volsph, b1(3),b2(3),b3(3)
1550 : 0 : real(dp),allocatable :: qfit(:,:),sigma(:),vcfit(:,:),xx(:),yy(:), qcart(:,:)
1551 : : ! *************************************************************************
1552 : :
1553 [ # # ]: 0 : b1 = two_pi * cryst%gprimd(:,1); b2 = two_pi * cryst%gprimd(:,2); b3 = two_pi * cryst%gprimd(:,3)
1554 : :
1555 : 0 : gamma_pt=RESHAPE([0, 0, 0], [3, 1]) ! Gamma point
1556 : 0 : npt=100 ! Number of points in 1D
1557 [ # # ]: 0 : ABI_MALLOC(qfit, (3, npt))
1558 [ # # ]: 0 : ABI_MALLOC(qcart, (3, npt))
1559 [ # # ]: 0 : ABI_MALLOC(vcfit, (1, npt))
1560 [ # # ]: 0 : if (nqibz == 1) then
1561 : 0 : ABI_ERROR("nqibz == 1 not supported when Beigi's method is used")
1562 : : endif
1563 [ # # # # ]: 0 : qfit(:,:)=zero
1564 [ # # # # ]: 0 : qcart(:,:)=zero
1565 : : ! Size of the third vector
1566 : 0 : bz_plane=l2norm(b3)
1567 : 0 : q0_volsph=(two_pi)**3 / (nkbz * cryst%ucvol)
1568 : : ! radius that gives the same volume as q0_volsph
1569 : : ! Let's assume that c is perpendicular to the plane
1570 : : ! We also assume isotropic BZ around gamma
1571 : 0 : step=sqrt((q0_volsph/bz_plane)/pi)/npt
1572 : :
1573 : : !step=half/(npt*(nqibz-1))
1574 : : ! Let's take qpoints along 1 line, the vcut does depend only on the norm
1575 [ # # ]: 0 : qcart(1,:) = arth(tol6,step,npt)
1576 : :
1577 [ # # ]: 0 : do ii=1,npt
1578 [ # # ]: 0 : qfit(:,ii) = MATMUL(TRANSPOSE(Cryst%rprimd),qcart(:,ii)) / (2*pi)
1579 : : call cutoff_slab(qfit(:,ii), 1, gamma_pt, cryst%gprimd, rcut, &
1580 : 0 : boxcenter, pdir, alpha, vcfit(:,ii), opt_slab)
1581 : : end do
1582 : :
1583 [ # # ]: 0 : ABI_MALLOC(xx, (npt))
1584 [ # # ]: 0 : ABI_MALLOC(yy, (npt))
1585 [ # # ]: 0 : ABI_MALLOC(sigma, (npt))
1586 [ # # ]: 0 : do ii=1,npt
1587 : : !xx(ii)=qfit(1,:)
1588 : 0 : xx(ii) = normv(qfit(:,ii), cryst%gmet, 'G')
1589 : : end do
1590 [ # # ]: 0 : ABI_FREE(qfit)
1591 [ # # ]: 0 : sigma=one
1592 [ # # ]: 0 : yy(:)=vcfit(1,:)
1593 : : !yy(:)=one
1594 [ # # ]: 0 : ABI_FREE(vcfit)
1595 : :
1596 : 0 : dx=(xx(2)-xx(1))
1597 : : ! integ = \int dr r f(r)
1598 : 0 : integ=xx(2)*yy(2)*dx*3.0/2.0
1599 [ # # ]: 0 : integ=integ+DOT_PRODUCT(xx(3:npt-2),yy(3:npt-2))*dx
1600 : 0 : integ=integ+xx(npt-1)*yy(npt-1)*dx*3.0/2.0
1601 : : !write(std_out,*)' simple integral',integ
1602 : 0 : q0_vol=bz_plane*pi*xx(npt)**2
1603 : : !write(std_out,*)' q0 sphere : ',q0_volsph,' q0_vol cyl ',q0_vol
1604 : 0 : i_sz=bz_plane*2*pi*integ/q0_vol
1605 : : !write(std_out,*)' spherical approximation ',four_pi*7.44*q0_volsph**(-two_thirds)
1606 : : !write(std_out,*)' Cylindrical cutoff value ',i_sz
1607 : : !i_sz=four_pi*7.44*q0_vol**(-two_thirds)
1608 : 0 : ABI_FREE(xx)
1609 : 0 : ABI_FREE(yy)
1610 : :
1611 [ # # # # ]: 0 : end subroutine beigi_surface_limit
1612 : : !!***
1613 : :
1614 : : !!****f* m_vcoul/carrier_isz
1615 : : !! NAME
1616 : : !! carrier_isz
1617 : : !!
1618 : : !! FUNCTION
1619 : : !! Integral of the 1/q^2 singularity of the Coulomb interaction with the auxiliary function F of
1620 : : !! Carrier et al. [[cite:Carrier2007]] (see faux):
1621 : : !!
1622 : : !! i_sz = 4pi [ nqbz <F>_BZ - sum_{q /= 0} F(q) + <L> ]
1623 : : !!
1624 : : !! <L> is the q --> 0 limit of 1/q^2 - F(q), which depends on the direction of q and is replaced by its
1625 : : !! average over directions (see carrier_limit). <F>_BZ is computed in integratefaux.
1626 : : !! The remaining error comes from the direction dependence of F near q=0 and decreases with the number
1627 : : !! of q-points; the Gaussian auxiliary function (gygi_baldereschi_isz) does not have it.
1628 : : !!
1629 : : !! INPUTS
1630 : : !! cryst<crystal_t>=Crystal structure.
1631 : : !! nqbz=Number of q-points.
1632 : : !! qbz(3,nqbz)=q-points in reduced coordinates.
1633 : : !! comm=MPI communicator.
1634 : : !!
1635 : : !! SOURCE
1636 : :
1637 : 56 : real(dp) function carrier_isz(cryst, nqbz, qbz, comm) result(i_sz)
1638 : :
1639 : : !Arguments ------------------------------------
1640 : : type(crystal_t),intent(in) :: cryst
1641 : : integer,intent(in) :: nqbz, comm
1642 : : real(dp), intent(in) :: qbz(3, nqbz)
1643 : : !************************************************************************
1644 : :
1645 : 56 : i_sz = carrier_isz_gmet(cryst%gmet, cryst%ucvol, nqbz, qbz, comm)
1646 : :
1647 : 0 : end function carrier_isz
1648 : : !!***
1649 : :
1650 : : !!****f* m_vcoul/carrier_isz_gmet
1651 : : !! NAME
1652 : : !! carrier_isz_gmet
1653 : : !!
1654 : : !! FUNCTION
1655 : : !! Same as carrier_isz, but expressed with the metric only, so that it can be used
1656 : : !! without a crystal_t object (e.g. for the Fock operator, see fock_init).
1657 : : !! The q-points do not need to be in the first BZ: F is periodic, and q is treated as q=0
1658 : : !! if it is a reciprocal lattice vector.
1659 : : !!
1660 : : !! INPUTS
1661 : : !! gmet(3,3)=Reciprocal space metric (bohr^-2).
1662 : : !! ucvol=Unit cell volume (bohr^3).
1663 : : !! nqbz=Number of q-points.
1664 : : !! qbz(3,nqbz)=q-points in reduced coordinates.
1665 : : !! comm=MPI communicator.
1666 : : !! [favg]=<F>_BZ computed by integratefaux(gmet, ucvol, nqbz, comm), if already available
1667 : : !! (e.g. several sets of q-points with the same nqbz, see fock_init).
1668 : : !!
1669 : : !! SOURCE
1670 : :
1671 : 59 : real(dp) function carrier_isz_gmet(gmet, ucvol, nqbz, qbz, comm, favg) result(i_sz)
1672 : :
1673 : : !Arguments ------------------------------------
1674 : : integer,intent(in) :: nqbz, comm
1675 : : real(dp),intent(in) :: gmet(3,3), ucvol
1676 : : real(dp), intent(in) :: qbz(3, nqbz)
1677 : : real(dp),intent(in),optional :: favg
1678 : :
1679 : : !Local variables-------------------------------
1680 : : integer :: iq_bz
1681 : : real(dp) :: bz_geometry_factor, qred(3), fbz
1682 : : !************************************************************************
1683 : :
1684 : 59 : bz_geometry_factor = zero
1685 [ + + ]: 1436 : do iq_bz=1,nqbz
1686 : : ! Skip q = 0 (q may be a reciprocal lattice vector, q and q+G give the same F)
1687 [ + + ]: 5508 : qred = qbz(:,iq_bz) - nint(qbz(:,iq_bz))
1688 [ + + + + : 2039 : if (any(abs(qred) > tol8)) bz_geometry_factor = bz_geometry_factor - faux(qbz(:,iq_bz), gmet)
+ + ]
1689 : : end do
1690 : :
1691 [ + + ]: 59 : if (present(favg)) then
1692 : 3 : fbz = favg
1693 : : else
1694 : 56 : fbz = integratefaux(gmet, ucvol, nqbz, comm)
1695 : : end if
1696 : :
1697 : 59 : bz_geometry_factor = bz_geometry_factor + fbz * nqbz + carrier_limit(gmet)
1698 : 59 : i_sz = four_pi * bz_geometry_factor ! Final result stored here
1699 : :
1700 : 59 : end function carrier_isz_gmet
1701 : : !!***
1702 : :
1703 : : !!****f* m_vcoul/gygi_baldereschi_isz
1704 : : !! NAME
1705 : : !! gygi_baldereschi_isz
1706 : : !!
1707 : : !! FUNCTION
1708 : : !! Integral of the 1/q^2 singularity with the auxiliary-function method of Gygi and Baldereschi
1709 : : !! [[cite:Gygi1986]], using the Gaussian auxiliary function of Massidda, Posternak and Baldereschi
1710 : : !! [[cite:Massidda1993]] (Eqs. 29-31):
1711 : : !!
1712 : : !! F(q) = sum_G exp(-alfa|q+G|^2)/|q+G|^2
1713 : : !! i_sz = 4pi [ nqbz <F>_BZ - sum_{q+G /= 0} F(q+G) + alfa ]
1714 : : !!
1715 : : !! where <F>_BZ = ucvol/(4pi sqrt(pi alfa)) (Eq. 31 of [[cite:Massidda1993]]) and alfa is the
1716 : : !! q --> 0 limit of 1/q^2 - F(q), i.e. the q=0 point of the regular part of Eq. 29.
1717 : : !! This is the reciprocal-space part of the Ewald sum for the Madelung potential v_M of the
1718 : : !! Born-von Karman supercell (volume V = nqbz*ucvol): i_sz = -V*v_M, independent of alfa
1719 : : !! as long as the real-space part erfc(R/(2 sqrt(alfa)))/R is negligible for all supercell
1720 : : !! vectors R and the sum over G is converged.
1721 : : !! Since the supercell vectors are lattice vectors, alfa = (a_min/10)^2, with a_min the
1722 : : !! shortest lattice vector, makes the real-space part < erfc(5) for any q-mesh.
1723 : : !! The Gaussian width 1/sqrt(alfa) is then of the order of the BZ diameter, as in [[cite:Massidda1993]].
1724 : : !! The G-vectors are generated here up to alfa*|q+G|^2 = 36, i.e. the result does not depend
1725 : : !! on the G-sphere (ecutsigx) used for Sigma.
1726 : : !! With the optional argument rcut, i_sz is computed for the long-range potential erf(r/rcut)/r (see gb_isz).
1727 : : !!
1728 : : !! SOURCE
1729 : :
1730 : 170 : real(dp) function gygi_baldereschi_isz(cryst, nqbz, qbz, rcut) result(i_sz)
1731 : :
1732 : : !Arguments ------------------------------------
1733 : : type(crystal_t),intent(in) :: cryst
1734 : : integer,intent(in) :: nqbz
1735 : : real(dp), intent(in) :: qbz(3, nqbz)
1736 : : real(dp),intent(in),optional :: rcut
1737 : : !************************************************************************
1738 : :
1739 : 170 : i_sz = gb_isz(cryst%gmet, cryst%ucvol, nqbz, qbz, rcut=rcut)
1740 : :
1741 : : end function gygi_baldereschi_isz
1742 : : !!***
1743 : :
1744 : : !----------------------------------------------------------------------
1745 : :
1746 : : !!****f* m_vcoul/gb_isz
1747 : : !! NAME
1748 : : !! gb_isz
1749 : : !!
1750 : : !! FUNCTION
1751 : : !! Same as gygi_baldereschi_isz, but expressed with the metric only, so that it can be used
1752 : : !! without a crystal_t object (e.g. for the Fock operator of hybrid functionals).
1753 : : !! i_sz depends only on the metric, not on the orientation of the lattice:
1754 : : !! |q+G|^2 = (2pi)^2 (q+G)^T gmet (q+G), |R|^2 = R^T rmet R, rmet = gmet^-1.
1755 : : !!
1756 : : !! With rcut, i_sz is computed for the long-range potential v(q) = 4pi exp(-rcut^2 q^2/4)/q^2
1757 : : !! (erf(r/rcut)/r). For alfa = rcut^2/4, 4pi F(q+G) = v(q+G) and the q --> 0 limit of v/4pi - F vanishes:
1758 : : !! i_sz = 4pi [ nqbz <F>_BZ - sum_{q+G /= 0} F(q+G) + alfa ] - pi rcut^2
1759 : : !! This is exact for any rcut (-V times the Madelung potential of the erf interaction, which has
1760 : : !! no real-space part). alfa = max(rcut^2/4, (a_min/10)^2): for rcut < a_min/5 both values give the
1761 : : !! same result (the real-space part erfc(R/(2 sqrt(alfa)))/R is negligible), and the larger one
1762 : : !! limits the number of G-vectors. rcut = 0 gives the Coulomb result.
1763 : : !!
1764 : : !! INPUTS
1765 : : !! gmet(3,3)=Reciprocal space metric (bohr^-2), without the factor (2pi)^2.
1766 : : !! ucvol=Unit cell volume (bohr^3).
1767 : : !! nqbz=Number of q-points.
1768 : : !! qbz(3,nqbz)=q-points in reduced coordinates (q=0 must be included).
1769 : : !! [rcut]=Range of the erf potential (bohr). Coulomb interaction if not present.
1770 : : !!
1771 : : !! SOURCE
1772 : :
1773 : 173 : real(dp) function gb_isz(gmet, ucvol, nqbz, qbz, rcut) result(i_sz)
1774 : :
1775 : : !Arguments ------------------------------------
1776 : : integer,intent(in) :: nqbz
1777 : : real(dp),intent(in) :: gmet(3,3), ucvol
1778 : : real(dp), intent(in) :: qbz(3, nqbz)
1779 : : real(dp),intent(in),optional :: rcut
1780 : :
1781 : : !Local variables-------------------------------
1782 : : real(dp),parameter :: alfa_gmax2 = 36.0_dp
1783 : : integer :: iq_bz, i1, i2, i3, nmax(3)
1784 : : real(dp) :: bz_geometry_factor, intfauxgb, alfa, amin, gmax2, qpg2, qpg(3), rmet(3,3), rr(3)
1785 : : !************************************************************************
1786 : :
1787 : : ! Real space metric rmet = gmet^-1 (matr3inv returns the transposed inverse, gmet is symmetric).
1788 : 173 : call matr3inv(gmet, rmet)
1789 : :
1790 : : ! Shortest lattice vector (the shortest supercell vector cannot be shorter).
1791 : 173 : amin = huge(one)
1792 [ + + ]: 692 : do i3=-1,1
1793 [ + + ]: 2249 : do i2=-1,1
1794 [ + + ]: 6747 : do i1=-1,1
1795 [ + + ]: 4671 : if (all([i1, i2, i3] == 0)) cycle
1796 [ + + ]: 17992 : rr = [i1, i2, i3]
1797 [ + + + + : 73525 : amin = min(amin, SQRT(DOT_PRODUCT(rr, MATMUL(rmet, rr))))
+ + ]
1798 : : end do
1799 : : end do
1800 : : end do
1801 : :
1802 : 173 : alfa = (amin / ten)**2
1803 [ + + ]: 173 : if (present(rcut)) alfa = max(alfa, rcut**2/four)
1804 : 173 : gmax2 = alfa_gmax2 / alfa
1805 : :
1806 : : ! Box of G-vectors containing the sphere |q+G| <= gmax for all q in the BZ (|a_i| = sqrt(rmet(i,i))).
1807 [ + + ]: 692 : do i1=1,3
1808 [ - + ]: 692 : nmax(i1) = ceiling(SQRT(gmax2) * SQRT(rmet(i1,i1)) / two_pi) + 1
1809 : : end do
1810 : :
1811 : : bz_geometry_factor = zero
1812 [ + + ]: 8715 : do iq_bz=1,nqbz
1813 [ + + ]: 205369 : do i3=-nmax(3),nmax(3)
1814 [ + + ]: 4732654 : do i2=-nmax(2),nmax(2)
1815 [ + + ]: 109063198 : do i1=-nmax(1),nmax(1)
1816 [ + + ]: 417356344 : qpg = qbz(:,iq_bz) + [i1, i2, i3]
1817 : : ! Exclude only q + G = 0 (no threshold on |q+G|: small q+G occur for large or elongated cells)
1818 [ + + + + : 105358563 : if (all(abs(qpg) < tol8)) cycle
+ + ]
1819 [ + + + + : 1669422608 : qpg2 = two_pi**2 * DOT_PRODUCT(qpg, MATMUL(gmet, qpg))
+ + ]
1820 [ + + ]: 108866371 : if (qpg2 <= gmax2) bz_geometry_factor = bz_geometry_factor - EXP(-alfa*qpg2)/qpg2
1821 : : end do
1822 : : end do
1823 : : end do
1824 : : end do
1825 : :
1826 : 173 : intfauxgb = ucvol/four_pi/SQRT(pi*alfa)
1827 : 173 : bz_geometry_factor = bz_geometry_factor + intfauxgb * nqbz + alfa
1828 : :
1829 : 173 : i_sz = four_pi*bz_geometry_factor
1830 [ + + ]: 173 : if (present(rcut)) i_sz = i_sz - pi*rcut**2
1831 : :
1832 : 173 : end function gb_isz
1833 : : !!***
1834 : :
1835 : : !----------------------------------------------------------------------
1836 : :
1837 : : !!****f* m_vcoul/check_isz
1838 : : !! NAME
1839 : : !! check_isz
1840 : : !!
1841 : : !! FUNCTION
1842 : : !! Stop with an error if the q -> 0 term i_sz is negative. This happens for strongly anisotropic Born-von Karman
1843 : : !! supercells (unit cell times k-mesh: elongated cell or e.g. ngkpt 1 1 N), for which the q -> 0 correction
1844 : : !! has no converged limit. GW, BSE and GWR use sqrt(i_sz).
1845 : : !!
1846 : : !! INPUTS
1847 : : !! i_sz=the q -> 0 term of the Coulomb interaction.
1848 : : !! mode=Cutoff mode (e.g. AUX_GB), for the message.
1849 : : !! varname=Input variable selecting the mode (gw_icutcoul or fock_icutcoul), for the message.
1850 : : !!
1851 : : !! SOURCE
1852 : :
1853 : 421 : subroutine check_isz(i_sz, mode, varname)
1854 : :
1855 : : !Arguments ------------------------------------
1856 : : real(dp),intent(in) :: i_sz
1857 : : character(len=*),intent(in) :: mode, varname
1858 : :
1859 : : !Local variables-------------------------------
1860 : : character(len=1000) :: msg
1861 : : !************************************************************************
1862 : :
1863 [ + - ]: 421 : if (i_sz >= zero) return
1864 : :
1865 : : write(msg,'(a,es12.4,9a)') &
1866 : 0 : 'The q -> 0 term i_sz of the Coulomb interaction is negative (i_sz = ', i_sz, ', mode ', trim(mode), ').', ch10, &
1867 : 0 : 'This happens when the Born-von Karman supercell (unit cell times k-mesh) is strongly anisotropic,', ch10, &
1868 : 0 : 'e.g. an elongated cell or a k-mesh like ngkpt 1 1 N: the q -> 0 correction then has no converged limit.', ch10, &
1869 : 0 : 'Action: increase the number of k-points along the short directions of the supercell, or change '//trim(varname)//'.'
1870 : 0 : ABI_ERROR(msg)
1871 : :
1872 : : end subroutine check_isz
1873 : : !!***
1874 : :
1875 : : !----------------------------------------------------------------------
1876 : :
1877 : : !!****f* m_vcoul/vcgen_init
1878 : : !! NAME
1879 : : !! vcgen_init
1880 : : !!
1881 : : !! FUNCTION
1882 : : !!
1883 : : !! SOURCE
1884 : :
1885 [ # # ]: 0 : subroutine vcgen_init(vcgen, cryst, kptrlatt, nkbz, nqibz, nqbz, qbz, rcut, gw_icutcoul, vcutgeo, comm)
1886 : :
1887 : : !Arguments ------------------------------------
1888 : : class(vcgen_t),intent(out) :: vcgen
1889 : : type(crystal_t),intent(in) :: cryst
1890 : : integer,intent(in) :: kptrlatt(3,3), nkbz, nqibz, nqbz, gw_icutcoul
1891 : : real(dp),intent(in) :: qbz(3,nqbz), rcut, vcutgeo(3)
1892 : : integer,intent(in) :: comm
1893 : :
1894 : : !Local variables-------------------------------
1895 : : integer,parameter :: istwfk1 = 1
1896 : : integer :: gvec0(3) ! npw_,
1897 : : real(dp) :: q0_vol, bz_geometry_factor, rcut2
1898 : : character(len=500) :: msg
1899 : : real(dp) :: vcoul0(1), q_gamma(3)
1900 : : !integer,allocatable :: gvec_(:,:)
1901 : : ! *************************************************************************
1902 : :
1903 : : ! Save dimension and other useful quantities in Vcp
1904 : 0 : vcgen%rcut = rcut ! Cutoff radius for cylinder.
1905 : 0 : vcgen%hcyl = zero ! Length of finite cylinder (Rozzi's method, default is Beigi).
1906 [ # # ]: 0 : vcgen%boxcenter = zero ! Boxcenter at the moment is supposed to be at the origin.
1907 [ # # ]: 0 : vcgen%vcutgeo = vcutgeo(:) ! Info on the orientation and extension of the cutoff region.
1908 : 0 : vcgen%nkbz = nkbz
1909 : :
1910 : 0 : call gw_icutcoul_to_mode(gw_icutcoul, vcgen%mode)
1911 : 0 : q_gamma = zero
1912 : 0 : gvec0 = 0
1913 : :
1914 : 0 : select case (trim(vcgen%mode))
1915 : : case ('MINIBZ', 'MINIBZ-ERFC', 'MINIBZ-ERF')
1916 : 0 : call vcgen%mc%init(cryst%rprimd, cryst%ucvol, cryst%gprimd, cryst%gmet, kptrlatt)
1917 : 0 : rcut2 = vcgen%rcut**2
1918 : 0 : call vcgen%mc%integrate(vcgen%mode, q_gamma, 1, gvec0, rcut2, nkbz, vcoul0, xmpi_comm_self)
1919 : : ! Treat the limit q --> 0.
1920 : 0 : vcgen%i_sz = vcoul0(1)
1921 : :
1922 : : case ('SPHERE')
1923 : : ! A non-positive value of rcut activates the recipe of Spencer & Alavi, PRB 77, 193110 (2008) [[cite:Spencer2008]].
1924 [ # # ]: 0 : if (vcgen%rcut < tol12) then
1925 : 0 : vcgen%rcut = (cryst%ucvol * nkbz * 3.d0 / four_pi) ** third
1926 : 0 : write(msg,'(2a,2x,f8.4,a)')ch10,' Using calculated rcut: ',vcgen%rcut,' to have same volume as the BvK crystal'
1927 : 0 : call wrtout(std_out, msg)
1928 : : end if
1929 [ # # ]: 0 : vcgen%vcutgeo = zero
1930 : :
1931 : : ! Treat the limit q --> 0
1932 : : ! The small cube is approximated by a sphere, while vc(q=0) = 2piR**2.
1933 : : ! if a single q-point is used, the expression for the volume is exact.
1934 : 0 : vcgen%i_sz = two_pi * vcgen%rcut**2
1935 : :
1936 : : case ('CYLINDER')
1937 : 0 : call cylinder_setup(cryst, vcgen%vcutgeo, vcgen%hcyl, vcgen%pdir, vcgen%opt_cylinder)
1938 : :
1939 : : ! If Beigi, treat the limit q --> 0.
1940 [ # # ]: 0 : if (vcgen%opt_cylinder == 1) then
1941 : : call beigi_cylinder_limit(vcgen%opt_cylinder, cryst, nqibz, nkbz, &
1942 : 0 : vcgen%rcut, vcgen%hcyl, vcgen%boxcenter, vcgen%pdir, vcgen%i_sz)
1943 : : else
1944 : : ! In Rozzi's method the lim q+G --> 0 is finite.
1945 : : call cutoff_cylinder(q_gamma, 1, gvec0, vcgen%rcut, vcgen%hcyl, vcgen%pdir,&
1946 : 0 : vcgen%boxcenter, cryst%rprimd, vcoul0, vcgen%opt_cylinder, xmpi_comm_self)
1947 : 0 : vcgen%i_sz = vcoul0(1)
1948 : : end if
1949 : :
1950 : : case ('SLAB')
1951 : 0 : call surface_setup(cryst, vcgen%vcutgeo, vcgen%alpha, vcgen%rcut, vcgen%pdir, vcgen%opt_slab)
1952 : :
1953 : : ! If Beigi, treat the limit q --> 0.
1954 [ # # ]: 0 : if (vcgen%opt_slab == 1) then
1955 : : ! Integrate numerically in the plane close to 0
1956 : : call beigi_surface_limit(vcgen%opt_slab, cryst, nqibz, nkbz, vcgen%rcut, vcgen%alpha, &
1957 : 0 : vcgen%boxcenter, vcgen%pdir, vcgen%i_sz)
1958 : : else
1959 : : ! In Rozzi's method the lim q+G --> 0 is finite.
1960 : : call cutoff_slab(q_gamma, 1, gvec0, cryst%gprimd, vcgen%rcut, &
1961 : 0 : vcgen%boxcenter, vcgen%pdir, vcgen%alpha, vcoul0, vcgen%opt_slab)
1962 : 0 : vcgen%i_sz = vcoul0(1)
1963 : : end if
1964 : :
1965 : : case ('CRYSTAL', 'AUXILIARY_FUNCTION', "AUX_GB")
1966 : :
1967 [ # # ]: 0 : if (vcgen%mode == "CRYSTAL") then
1968 : : ! Analytic integration of 4pi/q^2 over the volume element:
1969 : : ! $4pi/V \int_V d^3q 1/q^2 =4pi bz_geometric_factor V^(-2/3)$
1970 : : ! i_sz=4*pi*bz_geometry_factor*q0_vol**(-two_thirds) where q0_vol= V_BZ/N_k
1971 : : ! bz_geometry_factor: sphere=7.79, fcc=7.44, sc=6.188, bcc=6.946, wz=5.255 (see gwa.pdf, appendix A.4)
1972 : 0 : q0_vol = (two_pi) **3 / (nkbz*cryst%ucvol); bz_geometry_factor=zero
1973 : 0 : vcgen%i_sz = four_pi*7.44*q0_vol**(-two_thirds)
1974 : :
1975 [ # # ]: 0 : else if (vcgen%mode == "AUXILIARY_FUNCTION") then
1976 : : ! Numerical integration of the exact-exchange divergence through the
1977 : : ! auxiliary function of Carrier et al. PRB 75, 205126 (2007) [[cite:Carrier2007]].
1978 : 0 : vcgen%i_sz = carrier_isz(cryst, nqbz, qbz, comm)
1979 : :
1980 [ # # ]: 0 : else if (vcgen%mode == "AUX_GB") then
1981 : : ! Gygi-Baldereschi method [[cite:Gygi1986]] with the Gaussian auxiliary function of [[cite:Massidda1993]]
1982 : 0 : vcgen%i_sz = gygi_baldereschi_isz(cryst, nqbz, qbz)
1983 : :
1984 : : else
1985 : 0 : ABI_ERROR(sjoin("Need treatment of 1/q^2 singularity! for mode", vcgen%mode))
1986 : : end if
1987 : :
1988 : : case ('ERF')
1989 : : ! Gaussian auxiliary function with alfa = rcut^2/4, equal to the erf potential (exact, see gb_isz)
1990 : 0 : vcgen%i_sz = gygi_baldereschi_isz(cryst, nqbz, qbz, rcut=vcgen%rcut)
1991 : :
1992 : : case ('ERFC')
1993 : : ! === Treat 1/q^2 singularity ===
1994 : : ! * There is NO singularity in this case.
1995 : 0 : vcgen%i_sz = pi * vcgen%rcut**2 ! Final result stored here
1996 : :
1997 : : case default
1998 [ # # # # : 0 : ABI_BUG(sjoin('Unsupported cutoff mode:', vcgen%mode))
# # # # ]
1999 : : end select
2000 : :
2001 : 0 : write(msg,'(3a,i0,a,es22.14)') ' vcgen_init: mode ', trim(vcgen%mode), ', nqbz ', nqbz, ', i_sz = ', vcgen%i_sz
2002 : 0 : call wrtout(std_out, msg)
2003 : 0 : call check_isz(vcgen%i_sz, vcgen%mode, "gw_icutcoul")
2004 : :
2005 : 0 : end subroutine vcgen_init
2006 : : !!***
2007 : :
2008 : : !----------------------------------------------------------------------
2009 : :
2010 : : !!****f* m_vcoul/vcgen_get_vc_sqrt
2011 : : !! NAME
2012 : : !! vcgen_get_vc_sqrt
2013 : : !!
2014 : : !! FUNCTION
2015 : : !! Compute sqrt(vc(q, g))
2016 : : !!
2017 : : !! SOURCE
2018 : :
2019 : 0 : subroutine vcgen_get_vc_sqrt(vcgen, qpt, npw, gvec, q0, cryst, vc_sqrt, comm, &
2020 : 0 : vc) ! optional
2021 : :
2022 : : !Arguments ------------------------------------
2023 : : class(vcgen_t),intent(in) :: vcgen
2024 : : real(dp),intent(in) :: qpt(3), q0(3)
2025 : : integer,intent(in) :: npw, gvec(3,npw), comm
2026 : : type(crystal_t),intent(in) :: cryst
2027 : : complex(gwp),intent(out) :: vc_sqrt(npw)
2028 : : real(dp),optional,intent(out) :: vc(npw)
2029 : :
2030 : : !Local variables-------------------------------
2031 : : integer :: ig, ig0
2032 : : real(dp) :: rcut2
2033 : : logical :: q_is_gamma
2034 : 0 : real(dp),allocatable :: vcoul(:)
2035 : : ! *************************************************************************
2036 : :
2037 : 0 : q_is_gamma = normv(qpt, cryst%gmet, "G") < GW_TOLQ0
2038 : :
2039 : : ! Find the index of G=0 in gvec.
2040 : 0 : ig0 = -1
2041 [ # # ]: 0 : do ig=1,npw
2042 [ # # # # : 0 : if (all(gvec(:,ig) == 0)) then
# # ]
2043 : : ig0 = ig; exit
2044 : : end if
2045 : : end do
2046 [ # # ]: 0 : ABI_CHECK(ig0 /= -1, "Cannot find G=0 in gvec!")
2047 : :
2048 [ # # # # : 0 : ABI_MALLOC(vcoul, (npw))
# # # # #
# # # ]
2049 : :
2050 : 0 : select case (trim(vcgen%mode))
2051 : : case ('MINIBZ', 'MINIBZ-ERFC', 'MINIBZ-ERF')
2052 : 0 : rcut2 = vcgen%rcut**2
2053 : 0 : call vcgen%mc%integrate(vcgen%mode, qpt, npw, gvec, rcut2, vcgen%nkbz, vcoul, comm)
2054 : :
2055 : : case ('SPHERE')
2056 : 0 : call cutoff_sphere(qpt, npw, gvec, cryst%gmet, vcgen%rcut, vcoul)
2057 : :
2058 : : case ('CYLINDER')
2059 : : call cutoff_cylinder(qpt, npw, gvec, vcgen%rcut, vcgen%hcyl, vcgen%pdir, &
2060 : 0 : vcgen%boxcenter, cryst%rprimd, vcoul, vcgen%opt_cylinder, comm)
2061 : :
2062 : : case ('SLAB')
2063 : : call cutoff_slab(qpt, npw, gvec, cryst%gprimd, vcgen%rcut, &
2064 : 0 : vcgen%boxcenter, vcgen%pdir, vcgen%alpha, vcoul, vcgen%opt_slab)
2065 : :
2066 : : case ('CRYSTAL', 'AUXILIARY_FUNCTION', "AUX_GB", "ERF", "ERFC")
2067 : : ! Compute |q+G| with special treatment of (q=0, g=0).
2068 [ # # ]: 0 : do ig=1,npw
2069 [ # # ]: 0 : if (q_is_gamma .and. ig == ig0) then
2070 [ # # ]: 0 : vcoul(ig) = normv(q0 + gvec(:,ig), cryst%gmet, "G")
2071 : : !print *, "q_is_gamma with ", q0, "and vcoul:", vcoul(ig); stop
2072 : : else
2073 [ # # ]: 0 : vcoul(ig) = normv(qpt + gvec(:,ig), cryst%gmet, "G")
2074 : : end if
2075 : : end do
2076 : :
2077 [ # # ]: 0 : if (vcgen%mode == "ERF") then
2078 [ # # ]: 0 : vcoul(:) = four_pi/(vcoul(:)**2) * EXP( -0.25d0 * (vcgen%rcut*vcoul(:))**2 )
2079 [ # # ]: 0 : else if (vcgen%mode == "ERFC") then
2080 [ # # ]: 0 : vcoul(:) = four_pi/(vcoul(:)**2) * ( one - EXP( -0.25d0 * (vcgen%rcut*vcoul(:))**2 ) )
2081 : : else
2082 [ # # ]: 0 : vcoul = four_pi/vcoul**2
2083 : : end if
2084 : :
2085 : : case default
2086 [ # # # # : 0 : ABI_BUG(sjoin('Unsupported cutoff mode:', vcgen%mode))
# # ]
2087 : : end select
2088 : :
2089 : : ! Store final results in complex array as Rozzi's cutoff can give real negative values
2090 [ # # ]: 0 : vc_sqrt = sqrt(cmplx(vcoul, zero))
2091 : :
2092 [ # # # # ]: 0 : if (present(vc)) vc = vcoul
2093 [ # # ]: 0 : ABI_FREE(vcoul)
2094 : :
2095 [ # # ]: 0 : end subroutine vcgen_get_vc_sqrt
2096 : : !!***
2097 : :
2098 : : !----------------------------------------------------------------------
2099 : :
2100 : : !!****f* m_vcoul/vcgen_free
2101 : : !! NAME
2102 : : !! vcgen_free
2103 : : !!
2104 : : !! FUNCTION
2105 : : !! Free dynamic memory.
2106 : : !!
2107 : : !! SOURCE
2108 : :
2109 : 0 : subroutine vcgen_free(vcgen)
2110 : :
2111 : : !Arguments ------------------------------------
2112 : : class(vcgen_t),intent(inout) :: vcgen
2113 : : ! *************************************************************************
2114 : :
2115 : 0 : call vcgen%mc%free()
2116 : :
2117 : 0 : end subroutine vcgen_free
2118 : : !!***
2119 : :
2120 : : !----------------------------------------------------------------------
2121 : :
2122 : : !!****f* m_vcoul/vcgen_print
2123 : : !! NAME
2124 : : !! vcgen_print
2125 : : !!
2126 : : !! FUNCTION
2127 : : !! Print info on the object.
2128 : : !!
2129 : : !! SOURCE
2130 : :
2131 : 0 : subroutine vcgen_print(vcgen, units, header, prtvol)
2132 : :
2133 : : !Arguments ------------------------------------
2134 : : class(vcgen_t),intent(in) :: vcgen
2135 : : integer,intent(in) :: units(:), prtvol
2136 : : character(len=*),intent(in) :: header
2137 : :
2138 : : !Local variables-------------------------------
2139 : : !scalars
2140 : : integer :: ii
2141 : : character(len=500) :: msg
2142 : : ! *************************************************************************
2143 : :
2144 : : ABI_UNUSED(prtvol)
2145 : :
2146 [ # # # # ]: 0 : msg = ch10//' === '//trim(adjustl(header))//' === '
2147 : 0 : call wrtout(units, msg)
2148 : :
2149 : 0 : select case (vcgen%mode)
2150 : :
2151 : : case ('MINIBZ')
2152 : 0 : write(msg,'(3a)')ch10,' cutoff-mode = ',trim(vcgen%mode)
2153 : 0 : call wrtout(units, msg)
2154 : :
2155 : : case ('MINIBZ-ERF')
2156 : 0 : write(msg,'(3a)')ch10,' cutoff-mode = ',trim(vcgen%mode)
2157 : 0 : call wrtout(units, msg)
2158 : 0 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
2159 : 0 : ' === Error function cutoff === ',ch10,ch10,&
2160 : 0 : ' Cutoff radius ......... ',vcgen%rcut,' [Bohr] ',ch10
2161 : 0 : call wrtout(units, msg)
2162 : :
2163 : : case ('MINIBZ-ERFC')
2164 : 0 : write(msg,'(3a)')ch10,' cutoff-mode = ',trim(vcgen%mode)
2165 : 0 : call wrtout(units, msg)
2166 : 0 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
2167 : 0 : ' === Complement Error function cutoff === ',ch10,ch10,&
2168 : 0 : ' Cutoff radius ......... ',vcgen%rcut,' [Bohr] ',ch10
2169 : 0 : call wrtout(units, msg)
2170 : :
2171 : : case ('SPHERE')
2172 : 0 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
2173 : 0 : ' === Spherical cutoff === ',ch10,ch10,&
2174 : 0 : ' Cutoff radius ......... ',vcgen%rcut,' [Bohr] ',ch10,&
2175 : 0 : ' Volume of the sphere .. ',four_pi/three*vcgen%rcut**3,' [Bohr^3] '
2176 : : !FB: This has no meaning here! & ' Sphere centered at .... ',vcgen%boxcenter,' (r.l.u) ',ch10
2177 : : !MG It might be useful if the system is not centered on the origin because in this case the
2178 : : ! matrix elements of the Coulomb have to be multiplied by a phase depending on boxcenter.
2179 : : ! I still have to decide if it is useful to code this possibility and which variable use to
2180 : : ! define the center (boxcenter is used in the tddft part).
2181 : 0 : call wrtout(units, msg)
2182 : :
2183 : : case ('CYLINDER')
2184 [ # # ]: 0 : ii=imin_loc(ABS(vcgen%pdir-1))
2185 : 0 : write(msg,'(5a,f10.4,3a,i2,2a,3f10.2,a)')ch10,&
2186 : 0 : ' === Cylindrical cutoff === ',ch10,ch10,&
2187 : 0 : ' Cutoff radius ............... ',vcgen%rcut,' [Bohr] ',ch10,&
2188 : 0 : ' Axis parallel to direction... ',ii,ch10,&
2189 : 0 : ' Passing through point ....... ',vcgen%boxcenter,' (r.l.u) '
2190 : 0 : call wrtout(units, msg)
2191 : :
2192 : 0 : write(msg,'(2a)')' Infinite length ....... ',ch10
2193 [ # # ]: 0 : if (vcgen%hcyl/=zero) write(msg,'(a,f8.5,2a)')' Finite length of ....... ',vcgen%hcyl,' [Bohr] ',ch10
2194 : 0 : call wrtout(units, msg)
2195 : :
2196 : : CASE ('SLAB')
2197 : 0 : write(msg,'(5a,f10.4,3a,3f10.2,2a)')ch10,&
2198 : 0 : ' === Surface cutoff === ',ch10,ch10,&
2199 : 0 : ' Cutoff radius .................... ',vcgen%rcut,' [Bohr] ',ch10,&
2200 : 0 : ' Central plane passing through .... ',vcgen%boxcenter,' (r.l.u) ',ch10
2201 : 0 : call wrtout(units, msg)
2202 : : !write(msg,'(a)')' Infinite length .......'
2203 : : !if (vcgen%hcyl/=zero) write(msg,'(a,f8.5,a)')' Finite length of .......',vcgen%hcyl,' [Bohr] '
2204 : : !call wrtout(units, msg)
2205 : :
2206 : : case ('AUXILIARY_FUNCTION')
2207 : 0 : write(msg,'(3a)')ch10,' cutoff-mode = ',trim(vcgen%mode)
2208 : 0 : call wrtout(units, msg)
2209 : :
2210 : : case ('AUX_GB')
2211 : 0 : write(msg,'(3a)')ch10,' cutoff-mode = ',trim(vcgen%mode)
2212 : 0 : call wrtout(units, msg)
2213 : :
2214 : : case ('CRYSTAL')
2215 : 0 : write(msg,'(3a)')ch10,' cutoff-mode = ',trim(vcgen%mode)
2216 : 0 : call wrtout(units, msg)
2217 : :
2218 : : case ('ERF')
2219 : 0 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
2220 : 0 : ' === Error function cutoff === ',ch10,ch10,&
2221 : 0 : ' Cutoff radius ......... ',vcgen%rcut,' [Bohr] ',ch10
2222 : 0 : call wrtout(units, msg)
2223 : :
2224 : : case ('ERFC')
2225 : 0 : write(msg,'(5a,f10.4,3a,f10.2,3a,3f10.5,2a)')ch10,&
2226 : 0 : ' === Complement Error function cutoff === ',ch10,ch10,&
2227 : 0 : ' Cutoff radius ......... ',vcgen%rcut,' [Bohr] ',ch10
2228 : 0 : call wrtout(units, msg)
2229 : :
2230 : : case default
2231 [ # # # # : 0 : ABI_BUG(sjoin('Unknown cutoff mode: ', vcgen%mode))
# # # # #
# # # ]
2232 : : end select
2233 : :
2234 : : !if (vcgen%nqlwl > 0) then
2235 : : ! write(msg,'(a,i3)')" q-points for optical limit: ",vcgen%nqlwl
2236 : : ! call wrtout(units, msg)
2237 : : ! do iqlwl=1,vcgen%nqlwl
2238 : : ! write(msg,'(1x,i5,a,2x,3f12.6)') iqlwl,')',vcgen%qlwl(:,iqlwl)
2239 : : ! call wrtout(units, msg)
2240 : : ! end do
2241 : : !end if
2242 : :
2243 [ # # ]: 0 : end subroutine vcgen_print
2244 : : !!***
2245 : :
2246 [ - + - - : 1242 : end module m_vcoul
+ + - + +
- - + - +
+ - - + -
+ - + ]
2247 : : !!***
|