Branch data Line data Source code
1 : : !!****m* ABINIT/m_gwr
2 : : !! NAME
3 : : !! m_gwr
4 : : !!
5 : : !! FUNCTION
6 : : !! Objects and procedures implementing the GW method in real-space and imaginary time.
7 : : !!
8 : : !! NOTES
9 : : !! Memory and workload are distributed using a 4D cartesian grid: (g/r, tau, k-points, spin).
10 : : !!
11 : : !! Inside the g/r communicator, we use PBLAS matrices to store G, tchi and W
12 : : !! using a 1D processor grid and block distribution along columns.
13 : : !! A 2D grid, indeed, would require MPI-FFT or some communication before performing the FFTs along columns.
14 : : !!
15 : : !! Let's assume for simplicity that we have only two MPI procs in the g/r communicator.
16 : : !! Matrices in (g,g') space are distributed along columns so that the g-index is local
17 : : !! and we can use sequential zero-padded FFTs to transform from g to r in the unit cell:
18 : : !!
19 : : !! g'-axis
20 : : !! |--------------------
21 : : !! | | |
22 : : !! g-axis | P0 | P1 |
23 : : !! | | |
24 : : !! |--------------------
25 : : !!
26 : : !! The results of the FFT transform along g are stored in another PBLAS matrix with the same layout:
27 : : !!
28 : : !! g'-axis
29 : : !! |--------------------
30 : : !! | | |
31 : : !! r-axis | P0 | P1 |
32 : : !! | | |
33 : : !! |--------------------
34 : : !!
35 : : !! At this point, we call ptrans to MPI transpose the (r, g') matrix, and we end up with:
36 : : !!
37 : : !! r-axis
38 : : !! |--------------------
39 : : !! | | |
40 : : !! g'-axis | P0 | P1 |
41 : : !! | | |
42 : : !! |--------------------
43 : : !!
44 : : !! Differences with respect to the quartic GW code formulated in frequency-domain (real axis)
45 : : !!
46 : : !! - in GWR, the k-mesh must be Gamma-centered when the supercell-method is used.
47 : : !! Convolutions can use shifted k-meshes, although this part should be tests.
48 : : !! - All the two-point functions are defined on k/q-centered g-spheres while GW uses a single Gamma-centered sphere.
49 : : !! - The frequency/tau meshes are automatically defined by gwr_ntau and the KS energies up to nband (minimax meshes).
50 : : !!
51 : : !! Technical problems:
52 : : !!
53 : : !! - it's not clear to me that one can use vc(Sq, SG) when a cutoff is used as the cutoff breaks
54 : : !! the spherical symmetry of vc(r). Besides, when symmetries are used to reconstruct the term for q in the BZ,
55 : : !! one might have to take into account umklapps. Use cache?
56 : : !!
57 : : !! - Treatment of the anisotropic behaviour of Wc. This part is badly coded in GW, in the sense that
58 : : !! we use a finite small q when computing Wc for q --> 0. This breaks the symmetry of the system
59 : : !! and QP degeneracies. The equations needed to express the angular dependency of W(q) for q --> 0
60 : : !! are well known but one has to pass through the Adler-Wiser expression.
61 : : !! Possible solution: Compute heads and wings using a WFK_fine wavefunction file with dense k-mesh and less bands.
62 : : !! The dipole matrix elements are computed with the DFPT routines, still we need to
63 : : !! recode a lot of stuff that is already done in cchi0q0, especially symmetries.
64 : : !! Note, however, that tchi is Hermitian along the imaginary axis, expect for omega = 0 in metals
65 : : !! but I don't think the minmax grids contain omega = 0.
66 : : !!
67 : : !! - In principle, it's possible to compute QP correction along a k-path if a new WFK file is provided.
68 : : !! The correlated part is evaluated in real-space in the super-cell.
69 : : !! For Sigma_x, we need a specialized routine that can handle arbitrary q, especially at the level of v(q, G)
70 : : !! but I don't know if this approach will give smooth bands
71 : : !! as we don't have q --> 0 when k does not belong to the k-mesh.
72 : : !!
73 : : !! - New routine to compute oscillator matrix elements with NC/PAW and PBLAS matrices.
74 : : !! It can be used to compute tchi head/wings as well as Sigma_x + interface with coupled-cluster codes.
75 : : !!
76 : : !! - Decide whether we should use VASP conventions for G and the analytic continuation or the "standard" ones by Godby.
77 : : !! The standard ones are consistent with Hedin's notations and correspond to the ones used in the legacy GW code.
78 : : !! On the other hand, VASP notations make life easier if one has to implement PAW as all the equations
79 : : !! have been already derived.
80 : : !!
81 : : !! - Address nspinor = 2 and PBLAS distribution as MPI proc can have both spinors in memory
82 : : !! In other words, we should store the first/last index in gvec for each spinor
83 : : !!
84 : : !! - Optimization for Gamma-only. Memory and c -> r FFTs
85 : : !!
86 : : !! - Need to extend FFT API to avoid scaling if isign = -1. Also fft_ug and fft_ur should accept isign
87 : : !! optional argument. Refactoring of all the FFT routines used in the GW code is needed
88 : : !! in order to exploit R2C, C2R (e.g. chi0(q=0) and GPU version.
89 : : !!
90 : : !! - Use round-robin distribution instead of blocked-distribution to improve load balance?
91 : : !!
92 : : !! - For nspinor = 2, we use 4 Scalapack matrices to store G^k_ab(g,g') instead of a single matrix of shape (2*npw, 2*npw)
93 : : !!
94 : : !! - Memory peaks:
95 : : !!
96 : : !! (env3.9) [magianto@uan01 /scratch/project_465000061/magianto/DDIAGO_ZnO]
97 : : !! $~/git_repos/abinit/tests/Scripts/abimem.py peaks abimem_rank0.mocc
98 : : !! [0] <var=gt_scbox, A@m_gwr.F90:3395, addr=0x14aa53673010, size_mb=379.688>
99 : : !! [1] <var=xsum, A@xmpi_sum.finc:2551, addr=0x14aa2fce9010, size_mb=379.688>
100 : : !! [2] <var=gt_scbox, A@m_gwr.F90:4338, addr=0x14aa4f64f010, size_mb=379.688>
101 : : !! [3] <var=allcg_k, A@m_wfd.F90:4631, addr=0x14aa56b57010, size_mb=217.865>
102 : : !! [5] <var=wct_scbox, A@m_gwr.F90:4339, addr=0x14aa43876010, size_mb=189.844>
103 : : !! [6] <var=xsum, A@xmpi_sum.finc:2476, addr=0x14aa31bb0010, size_mb=189.844>
104 : : !! [7] <var=cg_k, A@m_wfd.F90:4623, addr=0x14aa64535010, size_mb=108.932>
105 : : !!
106 : : !! TODO
107 : : !! - Remove cryst%timrev, use kptopt and qptopt
108 : : !! - Sig_c breaks QP degeneracies due to fixed q0.
109 : : !!
110 : : !! NOTES:
111 : : !!
112 : : !! 1) _slk_mat_t is a CPP macro defined in abi_common.h that allows us to use PBLAS in single/double precision
113 : : !! Be careful when using c_f_pointer because there's no type checking.
114 : : !!
115 : : !! COPYRIGHT
116 : : !! Copyright (C) 1999-2026 ABINIT group (MG)
117 : : !! This file is distributed under the terms of the
118 : : !! GNU General Public License, see ~abinit/COPYING
119 : : !! or http://www.gnu.org/copyleft/gpl.txt .
120 : : !!
121 : : !! SOURCE
122 : :
123 : : #if defined HAVE_CONFIG_H
124 : : #include "config.h"
125 : : #endif
126 : :
127 : : #include "abi_common.h"
128 : :
129 : : ! nvtx related macro definition
130 : : #include "nvtx_macros.h"
131 : :
132 : : module m_gwr
133 : :
134 : : use, intrinsic :: iso_c_binding
135 : : use defs_basis
136 : : use m_abicore
137 : : use m_errors
138 : : use m_xmpi
139 : : use m_xomp
140 : : use m_hdr
141 : : use m_ebands
142 : : use netcdf
143 : : use m_nctk
144 : : use m_dtfil
145 : : use m_yaml
146 : : use m_sigtk
147 : : use m_hide_blas
148 : : #if defined(HAVE_GPU_MARKERS)
149 : : use m_nvtx_data
150 : : #endif
151 : :
152 : : use defs_datatypes, only : pseudopotential_type
153 : : use defs_abitypes, only : mpi_type
154 : : use m_gwdefs, only : GW_TOL_DOCC, GW_TOLQ0, GW_TOL_W0, GW_Q0_DEFAULT, cone_gw, czero_gw, j_gw, sigijtab_t, &
155 : : sigijtab_free, g0g0w
156 : : use m_time, only : cwtime, cwtime_report, sec2str, timab
157 : : use m_io_tools, only : iomode_from_fname, get_unit, file_exists, open_file, write_units
158 : : use m_pstat, only : pstat_proc
159 : : use m_numeric_tools, only : blocked_loop, get_diag, isdiagmat, arth, print_arr, imin_loc, imax_loc, &
160 : : c2r, linfit, bisect, hermitianize
161 : : use m_copy, only : alloc_copy
162 : : use m_geometry, only : normv, vdotw, spinrot_cmat
163 : : use m_fstrings, only : sjoin, itoa, strcat, ktoa, ltoa, ftoa, string_in, yesno
164 : : use m_sort, only : sort_rvals, sort_gvecs, sort_dp
165 : : use m_krank, only : krank_t, get_ibz2bz, star_from_ibz_idx
166 : : use m_crystal, only : crystal_t
167 : : use m_dtset, only : dataset_type
168 : : use m_cplxtools, only : cplx_mat_plus_bc
169 : : use m_fftcore, only : get_kg, sphereboundary, getng, print_ngfft, fftcore_set_mixprec, ngfft_seq
170 : : use m_cgtk, only : cgtk_rotate
171 : : use m_cgtools, only : cg_zdotc
172 : : use m_mpinfo, only : initmpi_seq, destroy_mpi_enreg
173 : : use m_kg, only : getcut
174 : : use m_fft, only : fftbox_plan3_t, uplan_t, fft_ug, fft_ur, fourdp
175 : : use m_fft_mesh, only : calc_ceikr, calc_ceigr
176 : : use m_kpts, only : kpts_ibz_from_kptrlatt, kpts_timrev_from_kptopt, kpts_map, kpts_map_print, kpts_pack_in_stars
177 : : use m_bz_mesh, only : littlegroup_t, findqg0, kmesh_t
178 : : use m_gsphere, only : kg_map, gsphere_t
179 : : use m_melemts, only : melements_t
180 : : use m_ioarr, only : fftdatar_write
181 : : use m_slk, only : slkmat_dp_t, slkmat_sp_t, slk_processor_t, slk_array_free, slk_array_set_zero, slk_array_gpu_set_zero,&
182 : : slk_array_locmem_mb, block_dist_1d, slk_pgemm
183 : : use m_wfk, only : wfk_read_ebands, wfk_t
184 : : use m_wfd, only : wfd_t, wfdgw_t
185 : : use m_ddk, only : ddkop_t
186 : : use m_pawtab, only : pawtab_type
187 : : use m_pawcprj, only : pawcprj_type
188 : : use m_vcoul, only : vcgen_t
189 : : use m_vkbr, only : vkbr_t, vkbr_free, vkbr_init, nc_ihr_comm
190 : : use m_chi0tk, only : chi0_bbp_mask, accumulate_head_wings_imagw, symmetrize_afm_chi0
191 : : use m_sigx, only : sigx_symmetrize
192 : : use m_dyson_solver, only : sigma_pade_t
193 : : use minimax_grids, only : gx_minimax_grid
194 : : use m_occ, only : get_fact_spin_tol_empty
195 : :
196 : : implicit none
197 : :
198 : : private
199 : : !!***
200 : :
201 : : !!****t* m_gwr/desc_t
202 : : !! NAME
203 : : !! desc_t
204 : : !!
205 : : !! FUNCTION
206 : : !! Parameters related to a two-point function such as
207 : : !! gvectors, tables used for zero padded FFTs and matrix elements of the Coulomb interaction.
208 : : !!
209 : : !! SOURCE
210 : :
211 : : type,public :: desc_t
212 : :
213 : : integer :: istwfk = 1
214 : : ! Storage mode for this k/q point.
215 : :
216 : : integer :: npw = -1
217 : : ! Total number of plane-waves for this k/q-point.
218 : :
219 : : integer :: ig0 = -1
220 : : ! Index of g=0 in gvec.
221 : :
222 : : logical :: kin_sorted
223 : : ! True if gvec are sorted by |k+g|^2/2
224 : :
225 : : integer,allocatable :: gvec(:,:)
226 : : ! (3, npw)
227 : : ! G-vectors in reduced coordinates.
228 : : ! Note that this array is global i.e. it is not MPI-distributed inside the PBLAS communicator.
229 : :
230 : : integer,allocatable :: gbound(:,:)
231 : : ! (2*mgfft+8, 2)
232 : : ! sphere boundary info for zero-padded FFT
233 : :
234 : : integer,allocatable :: g2box(:)
235 : : ! (npw)
236 : : ! Index of gvec in the supercell FFT box.
237 : :
238 : : integer :: cached_sc_ngfft(6) = -1
239 : :
240 : : complex(gwp),allocatable :: vc_sqrt_eps(:)
241 : : ! (npw)
242 : : ! Square root of the Coulomb interaction in reciprocal space.
243 : : ! Allocated and computed for tchi/W descriptors.
244 : : ! A Coulomb cutoff might be applied but NOT the MC technique
245 : :
246 : : complex(gwp),allocatable :: vc_sqrt_sigma(:)
247 : : ! (npw)
248 : : ! Square root of the Coulomb interaction in reciprocal space.
249 : : ! Allocated and computed for Sigma descriptors.
250 : : ! A Coulomb cutoff might be applied. MC technique can be used here
251 : :
252 : : integer,allocatable :: rottb(:,:,:)
253 : : ! rottb(ng,timrev,nsym)
254 : : ! rottb(G,I,S) is the index of (SI) G in the array gvec
255 : : ! where I is either the identity or the inversion.
256 : :
257 : : integer,allocatable :: rottbm1(:,:,:)
258 : : ! rottb(ng,timrev,nsym)
259 : : ! rottbm1(G,I,S) is the index of IS{^-1} G in the array gvec
260 : :
261 : : complex(gwp),allocatable :: phmGt(:,:)
262 : : ! phmGt(ng,nsym)
263 : : ! Phase factor e^{-i2\pi(G.\tau)} where $\tau$ is the fractional translation associated to isym.
264 : :
265 : : complex(gwp),allocatable :: phmSGt(:,:)
266 : : ! phmSGt(ng,nsym)
267 : : ! Phase factor e^{-i2\pi(SG.\tau)} where S is one of the symmetry properties in reciprocal space.
268 : :
269 : : contains
270 : :
271 : : procedure :: init => desc_init
272 : : ! Initialize the object
273 : :
274 : : procedure :: copy => desc_copy
275 : : ! Copy object.
276 : :
277 : : procedure :: to_scbox => desc_to_scbox
278 : : ! Insert cg_k array defined on the k-centered g-sphere with npw vectors inside the FFT box.
279 : :
280 : : procedure :: get_vc_sqrt => desc_get_vc_sqrt
281 : : ! Compute square root of vc(q,g).
282 : :
283 : : procedure :: free => desc_free
284 : : ! Free memory.
285 : : end type desc_t
286 : :
287 : : interface desc_array_free
288 : : module procedure desc_array1_free
289 : : end interface desc_array_free
290 : : !!***
291 : :
292 : : !----------------------------------------------------------------------
293 : :
294 : : !!****t* m_gwr/est_t
295 : : !! NAME
296 : : !! est_t
297 : : !!
298 : : !! FUNCTION
299 : : !! Memory is given in Mb
300 : : !!
301 : : !! SOURCE
302 : :
303 : : type, public :: est_t
304 : :
305 : : real(dp) :: mem_green_gg = zero
306 : : real(dp) :: mem_green_rg = zero
307 : : real(dp) :: mem_chi_gg = zero
308 : : real(dp) :: mem_chi_rg = zero
309 : : real(dp) :: mem_ugb = zero
310 : : real(dp) :: mem_total = zero
311 : : real(dp) :: efficiency = zero
312 : : real(dp) :: speedup = zero
313 : :
314 : : contains
315 : : procedure :: print => est_print
316 : : end type est_t
317 : : !!***
318 : :
319 : : !----------------------------------------------------------------------
320 : :
321 : : !!****t* m_gwr/gwr_t
322 : : !! NAME
323 : : !! gwr_t
324 : : !!
325 : : !! FUNCTION
326 : : !! This object provides the high-level API used to perform the different steps of the GWR algorithm.
327 : : !!
328 : : !! SOURCE
329 : :
330 : : type, public :: gwr_t
331 : :
332 : : integer :: nsppol = 1, nspinor = -1, nsig_ab = -1, nspden = -1
333 : : ! Number of independent spin polarizations, number of spinor components and spin densities.
334 : :
335 : : integer :: natom = -1
336 : : ! Number of atoms
337 : :
338 : : integer :: usepaw = -1
339 : : ! 0 if NC pseudos. 1 if PAW is used (not yet supported).
340 : :
341 : : integer :: my_nspins = -1
342 : : ! Number of independent spin polarizations treated by this MPI proc
343 : :
344 : : integer :: nkbz = -1, nkibz = -1
345 : : ! Number of k-points in the BZ/IBZ
346 : :
347 : : integer :: my_nkibz = -1, my_nkbz = -1
348 : : ! Number of k-points in the IBZ/BZ stored by this MPI proc.
349 : :
350 : : integer :: uc_batch_size = -1
351 : : ! Max number of unit cell FFT-transforms done in batch mode.
352 : :
353 : : integer :: sc_batch_size = -1
354 : : ! Max number of supercell-cell FFT-transforms done in batch mode.
355 : :
356 : : integer,allocatable :: my_kbz_inds(:)
357 : : ! (my_nkbz)
358 : : ! List of k-BZ indices treated by this proc.
359 : :
360 : : integer,allocatable :: my_kibz_inds(:)
361 : : ! (my_nkibz)
362 : : ! List of k-IBZ indices treated by this proc.
363 : :
364 : : integer :: nqbz = -1, nqibz = -1
365 : : ! Number of q-points in the BZ/IBZ
366 : :
367 : : integer :: my_nqibz = -1, my_nqbz = -1
368 : : ! Number of q-points in the IBZ/BZ stored by this MPI proc.
369 : :
370 : : integer,allocatable :: my_qibz_inds(:)
371 : : ! (my_nqibz)
372 : : ! List of q-IBZ indices treated by this proc.
373 : :
374 : : integer,allocatable :: my_qbz_inds(:)
375 : : ! (my_nqbz)
376 : : ! List of q-IBZ indices treated by this proc.
377 : :
378 : : integer :: ntau = -1
379 : : ! Total number of imaginary time points.
380 : :
381 : : integer :: my_ntau = -1
382 : : ! Number of imaginary time/frequency points treated by this MPI rank.
383 : :
384 : : integer :: nkcalc
385 : : ! Number of Sigma_nk k-points computed
386 : : ! TODO: Should be spin dependent + max_nkcalc
387 : :
388 : : integer :: max_nbcalc
389 : : ! Maximum number of bands computed (max over nkcalc and spin).
390 : :
391 : : integer :: nwr = -1
392 : : ! Number of frequency points along the real axis for Sigma(w) and spectral function A(w)
393 : : ! Odd number so that the mesh is centered on the KS energy.
394 : :
395 : : !real(dp) :: i_sz = huge(one)
396 : : ! Value of the integration of the Coulomb singularity 4\pi/V_BZ \int_BZ d^3q 1/q^2
397 : :
398 : : real(dp) :: wr_step = -one
399 : : ! Step of the linear mesh along the real axis (Ha units).
400 : :
401 : : real(dp) :: q0(3) = GW_Q0_DEFAULT
402 : : ! The small q for the treatment of q --> 0
403 : :
404 : : real(dp),allocatable :: kcalc(:,:)
405 : : ! kcalc(3, nkcalc)
406 : : ! List of k-points where the self-energy is computed.
407 : :
408 : : logical :: idle_proc = .False.
409 : : ! True if there are idle procs i.e. if processes in the input_comm have been excluded.
410 : :
411 : : !logical :: use_shmem_for_k = .False.
412 : : !logical :: use_mpi_for_k = .False.
413 : :
414 : : integer,allocatable :: bstart_ks(:,:)
415 : : ! bstart_ks(nkcalc, nsppol)
416 : : ! Initial KS band index included in self-energy matrix elements for each k-point in kcalc.
417 : : ! Depends on spin because all degenerate states should be included when symsigma /= 0 is used.
418 : :
419 : : integer,allocatable :: bstop_ks(:,:)
420 : : ! bstop_ks(nkcalc, nsppol)
421 : :
422 : : integer,allocatable :: nbcalc_ks(:,:)
423 : : ! nbcalc_ks(nkcalc, nsppol)
424 : : ! Number of bands included in self-energy matrix elements for each k-point in kcalc.
425 : : ! Depends on spin because all degenerate states should be included when symsigma /= 0 is used.
426 : :
427 : : integer,allocatable :: kcalc2ibz(:,:)
428 : : !kcalc2ibz(nkcalc, 6))
429 : : ! Mapping ikcalc --> IBZ as reported by listkk.
430 : :
431 : : logical :: use_supercell_for_tchi = .True.
432 : : ! True if we are using the supercell formalism for tchi
433 : : ! False if we are using the mixed-space approach with convolutions in k-space.
434 : :
435 : : logical :: use_supercell_for_sigma = .True.
436 : : ! True if we are using the supercell formalism for sigma
437 : : ! False if we are using the mixed-space approach with convolutions in k-space.
438 : :
439 : : integer :: ngkpt(3) = -1, ngqpt(3) = -1
440 : : ! Number of divisions in k/q meshes.
441 : :
442 : : integer,allocatable :: my_spins(:)
443 : : ! (my_nspins)
444 : : ! Indirect table giving the spin indices treated by this MPI rank.
445 : : ! Used only in the collinear case with nsppol = 2.
446 : :
447 : : integer,allocatable :: my_itaus(:)
448 : : ! (my_ntau)
449 : : ! Indirect table giving the tau indices treated by this MPI rank.
450 : :
451 : : integer,allocatable :: tau_master(:)
452 : : ! (ntau)
453 : : ! The rank of the MPI proc in tau_comm treating itau.
454 : :
455 : : integer, allocatable :: np_qibz(:)
456 : : ! (nqibz)
457 : : ! Number of processors in kpt_comm treating iq_ibz
458 : :
459 : : integer, allocatable :: np_kibz(:)
460 : : ! (nkibz)
461 : : ! Number of processors in kpt_comm treating ik_ibz
462 : :
463 : : logical, allocatable :: itreat_ikibz(:)
464 : : ! (nkibz)
465 : : ! True if this MPI rank treats ik_ibz
466 : :
467 : : logical, allocatable :: itreat_iqibz(:)
468 : : ! (nqibz)
469 : : ! True if this MPI rank treats iq_ibz
470 : :
471 : : real(dp),allocatable :: tau_mesh(:), tau_wgs(:)
472 : : ! (ntau)
473 : : ! Imaginary tau mesh and integration weights.
474 : :
475 : : real(dp),allocatable :: iw_mesh(:), iw_wgs(:)
476 : : ! (ntau)
477 : : ! Imaginary frequency mesh and integration weights
478 : :
479 : : real(dp),allocatable :: cosft_wt(:,:)
480 : : ! (ntau, ntau)
481 : : ! weights for cosine transform. (i tau --> i omega)
482 : :
483 : : real(dp),allocatable :: cosft_tw(:,:)
484 : : ! (ntau, ntau)
485 : : ! weights for sine transform (i iomega --> i tau)
486 : :
487 : : real(dp),allocatable :: sinft_wt(:,:)
488 : : ! (ntau, ntau)
489 : : ! weights for sine transform (i tau --> i omega)
490 : :
491 : : real(dp) :: te_min = -one, te_max = one
492 : : ! min and Max transition energy in Ha.
493 : :
494 : : real(dp) :: ft_max_error(3) = -one
495 : : ! Max error due to inhomogenous FT.
496 : :
497 : : real(dp) :: cosft_duality_error = -one
498 : : ! Max_{ij} |CT CT^{-1} - I|
499 : :
500 : : integer :: green_mpw = -1
501 : : ! Max number of g-vectors for Green's function over k-points.
502 : :
503 : : integer :: tchi_mpw = -1
504 : : ! Max number of g-vectors for tchi over q-points.
505 : :
506 : : !integer :: sigma_mpw = -1
507 : : ! Max number of g-vectors for Sigma over q-points.
508 : :
509 : : integer :: g_ngfft(18) = -1, g_mgfft = -1, g_nfft = -1
510 : : ! FFT mesh for the Green's function.
511 : :
512 : : !integer :: chi_ngfft(18) = -1, chi_mgfft = -1, chi_nfft = -1
513 : : !integer :: sig_ngfft(18) = -1, sig_mgfft = -1, sig_nfft = -1
514 : :
515 : : integer :: mg0(3) = [2, 2, 2]
516 : : ! Max shifts to account for umklapps.
517 : :
518 : : type(desc_t),allocatable :: green_desc_kibz(:)
519 : : ! (nkibz)
520 : : ! Descriptor for Green's functions
521 : :
522 : : type(desc_t),allocatable :: tchi_desc_qibz(:)
523 : : ! (nqibz)
524 : : ! Descriptor for tchi. NB: The g-vectors are sorted by |q+g|^2/2
525 : :
526 : : integer,allocatable :: chinpw_qibz(:)
527 : : ! Number of PWs in tchi for each q-point in the IBZ (available on all procs)
528 : :
529 : : !type(desc_t),allocatable :: sigma_desc_kibz(:)
530 : : ! (nkibz)
531 : : ! Descriptor for self-energy
532 : :
533 : : integer :: coords_stgk(4) = 0
534 : : ! Cartesian coordinates of this processor in the Cartesian grid.
535 : :
536 : : type(xcomm_t) :: comm
537 : : ! Communicator with all MPI procs involved in the computation
538 : : ! NB: gwr%comm%value is not necessarly the same as the input_comm
539 : : ! we may decide to remove some procs from input_comm before createring the Cartesian grid.
540 : :
541 : : type(xcomm_t) :: spin_comm
542 : : ! MPI communicator over spins.
543 : :
544 : : type(xcomm_t) :: kpt_comm
545 : : ! MPI communicator for k/q-point distribution.
546 : :
547 : : type(xcomm_t) :: g_comm
548 : : ! MPI communicator for g/r distribution
549 : :
550 : : type(xcomm_t) :: tau_comm
551 : : ! MPI communicator for imag time distribution
552 : :
553 : : type(xcomm_t) :: gtau_comm
554 : : ! MPI communicator for g/tau 2D subgrid.
555 : :
556 : : type(xcomm_t) :: kg_comm
557 : : ! MPI communicator for g/g 2D subgrid.
558 : :
559 : : type(xcomm_t) :: kts_comm
560 : : ! MPI communicator for tau/kpoint/spin 3D grid
561 : :
562 : : type(xcomm_t) :: kgt_comm
563 : : ! MPI communicator for g/tau/kpoint 3D grid
564 : :
565 : : type(dataset_type), pointer :: dtset => null()
566 : : ! Input variables.
567 : :
568 : : type(datafiles_type), pointer :: dtfil => null()
569 : : ! Names of input/output files and prefixes.
570 : :
571 : : type(crystal_t), pointer :: cryst => null()
572 : : ! Crystal structure.
573 : :
574 : : integer :: scf_iteration = 1
575 : : ! Internal counter used to implement self-consistency
576 : : ! For the time being, only self-consistency in energies is supported.
577 : :
578 : : integer,allocatable :: ks_vbik(:,:)
579 : : ! (gwr%ks_ebands%nkpt, gwr%ks_ebands%nsppol)
580 : : ! KS valence band indices.
581 : :
582 : : type(ebands_t), pointer :: ks_ebands => null()
583 : : ! initial KS energies
584 : :
585 : : type(gaps_t) :: ks_gaps
586 : : ! Info on the KS gaps.
587 : :
588 : : type(ebands_t) :: qp_ebands
589 : : ! QP energies
590 : :
591 : : type(ebands_t) :: qp_ebands_prev
592 : : ! QP energies of the previous iteration. Used if self-consistency.
593 : :
594 : : type(pseudopotential_type), pointer :: psps => null()
595 : : ! NC Pseudos data
596 : :
597 : : type(pawtab_type), pointer :: pawtab(:) => null()
598 : : ! PAW data
599 : :
600 : : type(mpi_type),pointer :: mpi_enreg => null()
601 : : ! Sequential mpi_type needed to invoke ABINIT routines requiring it.
602 : :
603 : : type(slk_processor_t) :: g_slkproc
604 : : ! 1D PBLAS grid to block-distribute matrices along columns inside gcomm.
605 : :
606 : : type(__slkmat_t),allocatable :: gt_kibz(:,:,:,:,:)
607 : : ! (2, nkibz, ntau, nsppol, nsig_ab)
608 : : ! Occupied/Empty Green's function G_k(g,g')
609 : :
610 : : type(__slkmat_t),allocatable :: tchi_qibz(:,:,:)
611 : : ! (nqibz, ntau, nsppol)
612 : : ! Irreducible polarizability tchi_q(g,g')
613 : :
614 : : character(len=10) :: tchi_space = "none"
615 : : ! Defines if the tchi_qibz matrix stores Chi in tau or iomega domain.
616 : : ! "none", "itau", "iomega"
617 : :
618 : : type(__slkmat_t),allocatable :: wc_qibz(:,:,:)
619 : : ! (nqibz, ntau, nsppol)
620 : : ! Correlated screened Coulomb interaction summed over collinear spins
621 : : ! Replicated across spin_comm if nsppol == 2.
622 : :
623 : : character(len=10) :: wc_space = "none"
624 : : ! Defines if the wc_qibz matrix stores W in tau or iomega domain.
625 : : ! "none", "itau", "iomega"
626 : :
627 : : !type(__slkmat_t),allocatable :: em1_qibz(:,:,:)
628 : : ! Inverse dielectric matrix at omega = 0
629 : : ! (nqibz, nsppol)
630 : : ! Replicated across the tau comm and the spin comm if nsppol == 2.
631 : :
632 : : type(__slkmat_t),allocatable :: sigc_kibz(:,:,:,:,:)
633 : : ! (2, nkibz, ntau, nsppol, nsig_ab)
634 : :
635 : : character(len=10) :: sigc_space = "none"
636 : : ! Defines if the sigc_kibz matrix stores Sigma in tau or iomega domain.
637 : : ! "none", "itau", "iomega"
638 : :
639 : : type(__slkmat_t),allocatable :: ugb(:,:) !, nato_ugb(:,:)
640 : : ! (nkibz, nsppol)
641 : : ! Fourier components of the KS wavefunctions stored in a PBLAS matrix
642 : : ! Bands are distributed in the g_comm communicator in a round-robin fashion.
643 : : ! hence they are REPLICATED over tau_comm as this leads to better scalability in terms of flops.
644 : : ! Distributing bands inside the 2D gtau_comm, indeed, allows one to reduce memory further
645 : : ! but then the pzgemm used to build G explodes. Also. tau parallelism is high-level in GWR so it's not a good idea
646 : : ! to mix it with low-level just to make memory for ugb scale better.
647 : : ! The size of ugb is negligible when compared to G and Chi.
648 : :
649 : : type(slk_processor_t) :: gtau_slkproc
650 : : ! Scalapack grid with (g,tau) processors
651 : :
652 : : integer :: ugb_nband = -1
653 : : ! Number of bands in ugb.
654 : :
655 : : type(vcgen_t) :: vcgen_eps
656 : : ! Object used to compute Coulomb term vc(q,g) in epsilon.
657 : :
658 : : type(vcgen_t) :: vcgen_sigma
659 : : ! Object used to compute Coulomb term vc(q,g) in Sigma
660 : :
661 : : logical :: has_vcgen_sigma = .False.
662 : : ! True if vcgen_sigma is allocated
663 : :
664 : : character(len=fnlen) :: gwrnc_path = ABI_NOFILE
665 : : ! Path to the GWR.nc file with output results.
666 : :
667 : : logical :: gwrnc_write = .True.
668 : : ! Activate/deactivate the output of the GWR.nc file.
669 : :
670 : : real(dp),allocatable :: kbz(:,:)
671 : : ! (3, nkbz)
672 : : ! Reduced coordinates of the k-points in the full BZ.
673 : :
674 : : real(dp), contiguous, pointer :: kibz(:,:) => null()
675 : : ! (3, nkibz)
676 : : ! Reduced coordinates of the k-points in the IBZ
677 : :
678 : : integer,allocatable :: kbz2ibz(:,:)
679 : : ! (6, nkbz)
680 : : ! Mapping kBZ to IBZ (symrec conventions)
681 : :
682 : : integer,allocatable :: kbz2ibz_symrel(:,:)
683 : : ! (6, nkbz)
684 : : ! Mapping kBZ to IBZ (symrel conventions)
685 : :
686 : : real(dp), contiguous, pointer :: wtk(:) => null()
687 : : ! (nkibz)
688 : : ! Weights of the k-points in the IBZ (normalized to one).
689 : :
690 : : real(dp),allocatable :: qbz(:,:)
691 : : ! (3, nqbz)
692 : : ! Reduced coordinates of the q-points in the full BZ.
693 : :
694 : : integer,allocatable :: qbz2ibz(:,:)
695 : : ! (6, nqbz)
696 : : ! Mapping qBZ to IBZ (symrec conventions)
697 : :
698 : : real(dp),allocatable :: qibz(:,:)
699 : : ! (3, nqibz)
700 : : ! Reduced coordinates of the q-points in the IBZ (full symmetry of the system).
701 : :
702 : : real(dp),allocatable :: wtq(:)
703 : : ! (nqibz)
704 : : ! Weights of the q-points in the IBZ (normalized to one).
705 : :
706 : : complex(dp),allocatable :: chi0_head_myw(:,:,:)
707 : : ! (3,3,my_ntau)
708 : : ! Head of the irred. polarizability in i.omega space.
709 : : ! Note that spins have been summed over.
710 : :
711 : : complex(dp),allocatable :: chi0_uwing_myw(:,:,:), chi0_lwing_myw(:,:,:)
712 : : ! (3, npw_chi_gamma, my_ntau)
713 : : ! Upper wings of the irred. polarizability in i omega space.
714 : : ! Note that spins have been summed over.
715 : :
716 : : type(wfdgw_t) :: kcalc_wfd
717 : : ! wavefunction descriptor with the KS states where QP corrections are wanted.
718 : :
719 : : type(hdr_type) :: wfk_hdr
720 : : ! header of the WFK file
721 : : ! IMPORTANT: Don't use wkf_hdr%npwarr to get the number of PW as we might have used ecutwfn < ecut.
722 : :
723 : : type(melements_t) :: ks_me !, qp_me
724 : : ! Matrix elements of the different potentials in the KS basis set.
725 : :
726 : : type(degtab_t),allocatable :: degtab(:,:)
727 : : ! (nkcalc, nsppol)
728 : : ! Table used to average QP results in the degenerate subspace if symsigma == 1
729 : :
730 : : integer :: b1gw = -1, b2gw = -1
731 : : ! b1gw = minval(gwr%bstart_ks); b2gw = maxval(gwr%bstop_ks)
732 : :
733 : : logical :: sig_diago
734 : : ! True if Sigma_ matrices are diagonal in the band indices (default)
735 : :
736 : : complex(dp),allocatable :: sigx_mat(:,:,:,:)
737 : : ! (b1gw:b2gw, ?, nkcalc, nsppol)
738 : : ! Matrix elements of <i|\Sigma_x|j>. The second dimension depends on sig_diago
739 : :
740 : : !complex(dp),allocatable :: sigc_it_mat(:,:,:,:,:)
741 : : ! (2, ntau, max_nbcalc, nkcalc, nsppol*nsig_ab))
742 : : ! Matrix elements of <i|\Sigma_c(itau)|j>. The second dimension depends on sig_diago
743 : :
744 : : complex(dp),allocatable :: sigc_iw_mat(:,:,:,:,:)
745 : : ! Matrix elements of <i|\Sigma_c(i omega)|j>
746 : : ! (ntau, b1gw:b2gw, ?, nkcalc, nsppol). The second dimension depends on sig_diago
747 : :
748 : : contains
749 : :
750 : : procedure :: init => gwr_init
751 : : ! Initialize the object.
752 : :
753 : : procedure :: rotate_gpm => gwr_rotate_gpm
754 : : ! Reconstruct the Green's functions in the BZ from the IBZ.
755 : :
756 : : procedure :: gk_to_scbox => gwr_gk_to_scbox
757 : : ! Insert G_k(g',r) in the FFT box of the supercell: k+g' index.
758 : :
759 : : procedure :: wcq_to_scbox => gwr_wcq_to_scbox
760 : : ! Insert W_q(g',r) in the FFT box of the supercell: q+g' index.
761 : :
762 : : procedure :: get_myk_green_gpr => gwr_get_myk_green_gpr
763 : : ! G_k(g,g') --> G_k(g',r) for each k in the BZ treated by this MPI proc for given spin and tau.
764 : :
765 : : procedure :: get_gkbz_rpr_pm => gwr_get_gkbz_rpr_pm
766 : : ! Compute G_k(r',r) with (r, r') in the unit cell and k in the full BZ.
767 : :
768 : : procedure :: rotate_wc => gwr_rotate_wc
769 : : ! Reconstruct Wc(q) in the BZ from the IBZ.
770 : :
771 : : procedure :: get_myq_wc_gpr => gwr_get_myq_wc_gpr
772 : : ! W_q(g,g') --> W_q(g',r) for each q in the BZ treated by this MPI procs for given spin and tau.
773 : :
774 : : procedure :: get_wc_rpr_qbz => gwr_get_wc_rpr_qbz
775 : : ! Compute Wc_q(r',r') with q in the BZ
776 : :
777 : : procedure :: rpr_to_ggp => gwr_rpr_to_ggp
778 : : ! F_{r',r} --> F_{g,g'}
779 : :
780 : : procedure :: cos_transform => gwr_cos_transform
781 : : ! Inhomogeneous cosine transform.
782 : :
783 : : procedure :: malloc_free_mats => gwr_malloc_free_mats
784 : : ! Allocate/Deallocate matrices for G/tchi/Sigma
785 : :
786 : : procedure :: free => gwr_free
787 : : ! Free memory.
788 : :
789 : : procedure :: print => gwr_print
790 : : ! Print info on the object.
791 : :
792 : : procedure :: print_mem => gwr_print_mem
793 : : ! Print memory required by PBLAS matrices.
794 : :
795 : : procedure :: print_trace => gwr_print_trace
796 : : ! Print trace of matrices for testing purposes.
797 : :
798 : : procedure :: load_kcalc_wfd => gwr_load_kcalc_wfd
799 : : ! Load the KS states for Sigma_nk from the WFK file
800 : :
801 : : procedure :: read_ugb_from_wfk => gwr_read_ugb_from_wfk
802 : : ! Read wavefunctions from WFK file.
803 : :
804 : : procedure :: build_green => gwr_build_green
805 : : ! Build Green's functions in imaginary time from the %ugb matrices stored in memory.
806 : :
807 : : procedure :: build_tchi => gwr_build_tchi
808 : : ! Build the irreducible polarizability
809 : :
810 : : procedure :: redistrib_gt_kibz => gwr_redistrib_gt_kibz
811 : : ! Redistribute/deallocate G_k
812 : :
813 : : procedure :: redistrib_mats_qibz => gwr_redistrib_mats_qibz
814 : : ! Redistribute/deallocate tchi_q or Wc_q
815 : :
816 : : procedure :: build_wc => gwr_build_wc
817 : : ! Build the correlated part of the screened interaction.
818 : :
819 : : procedure :: build_sigmac => gwr_build_sigmac
820 : : ! Build the correlated part of the self-energy GWc
821 : : ! and compute matrix elements in the KS representation.
822 : :
823 : : procedure :: rpa_energy => gwr_rpa_energy
824 : : ! Compute RPA energy.
825 : :
826 : : procedure :: gamma_gw => gwr_gamma_gw
827 : : ! TODO: Work in progress.
828 : :
829 : : procedure :: build_chi0_head_and_wings => gwr_build_chi0_head_and_wings
830 : : ! Compute head and wings of chi0
831 : :
832 : : procedure :: build_sigxme => gwr_build_sigxme
833 : : ! Compute matrix elements of the exchange part.
834 : :
835 : : procedure :: get_u_ngfft => gwr_get_u_ngfft
836 : : ! Compute FFT mesh from boxcutmin
837 : :
838 : : procedure :: run_g0w0 => gwr_run_g0w0
839 : : ! Compute QP corrections with one-shot G0W0.
840 : :
841 : : procedure :: run_chi0 => gwr_run_chi0
842 : : ! Compute CHI0 only.
843 : :
844 : : procedure :: run_energy_scf => gwr_run_energy_scf
845 : : ! Compute QP corrections with energy-only self-consistent GW
846 : :
847 : : procedure :: check_scf_cycle => gwr_check_scf_cycle
848 : : ! Check SCF cycle for convergence.
849 : :
850 : : procedure :: ncwrite_tchi_wc => gwr_ncwrite_tchi_wc
851 : : ! Write tchi or wc to netcdf file
852 : :
853 : : end type gwr_t
854 : : !!***
855 : :
856 : : ! Handy named costants (private stuff)
857 : : integer,private,parameter :: LOG_MODR = 500, LOG_MODK = 5
858 : : integer,private,parameter :: istwfk1 = 1, ndat1 = 1, me_fft0 = 0, paral_fft0 = 0, nproc_fft1 = 1
859 : : integer,private,parameter :: OP_COPY = 0, OP_ACC = 1
860 : : integer,private,parameter :: CHI_FIT = 1, SIGMA_FIT = 2
861 : :
862 : : contains
863 : : !!***
864 : :
865 : : !----------------------------------------------------------------------
866 : :
867 : : !!****f* m_gwr/gwr_init
868 : : !! NAME
869 : : !! gwr_init
870 : : !!
871 : : !! FUNCTION
872 : : !! Initialize the gwr object.
873 : : !!
874 : : !! INPUTS
875 : : !! dtset<dataset_type>=All input variables for this dataset.
876 : : !! dtfil<datafiles_type>=Variables related to files.
877 : : !! cryst=Crystalline structure
878 : : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
879 : : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
880 : : !! ke_ebands=KS energies
881 : : !! mpi_enreg=information about MPI parallelization (FAKE one as GWR has its own MPI algo)
882 : : !! input_comm=MPI communicator
883 : : !!
884 : : !! OUTPUT
885 : : !!
886 : : !! SOURCE
887 : :
888 : 0 : subroutine gwr_init(gwr, dtset, dtfil, cryst, psps, pawtab, ks_ebands, mpi_enreg, input_comm)
889 : :
890 : : !Arguments ------------------------------------
891 : : !scalars
892 : : class(gwr_t),target,intent(out) :: gwr
893 : : type(dataset_type),target,intent(in) :: dtset
894 : : type(datafiles_type),target,intent(in) :: dtfil
895 : : type(crystal_t),target,intent(in) :: cryst
896 : : type(pseudopotential_type),target,intent(in) :: psps
897 : : type(pawtab_type),target,intent(in) :: pawtab(psps%ntypat*psps%usepaw)
898 : : type(ebands_t),target,intent(in) :: ks_ebands
899 : : type(mpi_type),target,intent(in) :: mpi_enreg
900 : : integer,intent(inout) :: input_comm
901 : :
902 : : !Local variables-------------------------------
903 : : !scalars
904 : : integer,parameter :: qptopt1 = 1, master = 0, ndims = 4
905 : : integer :: my_it, my_ikf, ii, kptopt, my_iki, my_iqi, itau, spin, my_iqf
906 : : integer :: my_nshiftq, iq_bz, iq_ibz, npw_, ncid, smat_bsize1, smat_bsize2
907 : : integer :: comm_cart, me_cart, ierr, all_nproc, my_rank, qprange_, gap_err, ncerr, omp_nt
908 : : integer :: cnt, ikcalc, ndeg, mband, bstop, nbsum, jj, gw_icutcoul_
909 : : integer :: ik_ibz, ik_bz, isym_k, trev_k, g0_k(3)
910 : : integer :: ip_g, ip_k, ip_t, ip_s, np_g, np_k, np_t, np_s, isym, itim
911 : : real(dp) :: cpu, wall, gflops, wmax, delta, abs_rerr, exact_int, eval_int, drude_plasmon_freq
912 : : real(dp) :: prev_efficiency, prev_speedup, regterm, prev_dual_error
913 : : logical :: isirr_k, changed, q_is_gamma, reorder, can_use_kshifts
914 : : character(len=5000) :: msg
915 : 0 : type(krank_t) :: qrank, krank_ibz
916 : : type(est_t) :: est
917 [ # # # # : 0 : type(kmesh_t) :: Kmesh, Qmesh
# # # # ]
918 : : !arrays
919 : : integer :: qptrlatt(3,3), dims_kgts(ndims), try_dims_kgts(ndims), indkk_k(6,1), units(2)
920 : 0 : integer,allocatable :: gvec_(:,:),degblock(:,:), degblock_all(:,:,:,:), ndeg_all(:,:), iwork(:,:), got(:)
921 : : real(dp) :: my_shiftq(3,1), kk_ibz(3), kk_bz(3), qq_bz(3), qq_ibz(3), kk(3), tsec(2), qbz(3), sq(3)
922 [ # # ]: 0 : real(dp),allocatable :: wtk(:), kibz(:,:)
923 : : logical :: periods(ndims), keepdim(ndims)
924 : : ! *************************************************************************
925 : :
926 : 0 : call cwtime(cpu, wall, gflops, "start")
927 : 0 : call timab(1920, 1, tsec)
928 : :
929 : 0 : all_nproc = xmpi_comm_size(input_comm); my_rank = xmpi_comm_rank(input_comm)
930 [ # # ]: 0 : units = [std_out, ab_out]
931 : :
932 : : ! Keep a reference to other objects to simplify the internal API.
933 : 0 : gwr%dtset => dtset; gwr%dtfil => dtfil; gwr%cryst => cryst; gwr%psps => psps; gwr%pawtab => pawtab
934 : 0 : gwr%ks_ebands => ks_ebands; gwr%kibz => ks_ebands%kptns; gwr%wtk => ks_ebands%wtk; gwr%mpi_enreg => mpi_enreg
935 : :
936 : : ! Initialize qp_ebands with KS values.
937 : 0 : call ks_ebands%copy(gwr%qp_ebands)
938 : 0 : call ks_ebands%copy(gwr%qp_ebands_prev)
939 : :
940 [ # # # # : 0 : ABI_MALLOC(gwr%ks_vbik, (gwr%ks_ebands%nkpt, gwr%ks_ebands%nsppol))
# # # # #
# # # # #
# # # # ]
941 [ # # # # : 0 : gwr%ks_vbik(:,:) = gwr%ks_ebands%get_valence_idx()
# # ]
942 : :
943 : : ! Useful dimensions.
944 : 0 : gwr%nspinor = dtset%nspinor; gwr%nsppol = dtset%nsppol; gwr%nspden = dtset%nspden
945 : 0 : gwr%nsig_ab = gwr%nspinor ** 2 !! TODO HT: One day we only need 3
946 : 0 : gwr%natom = dtset%natom; gwr%usepaw = dtset%usepaw
947 : 0 : gwr%sig_diago = .True.
948 [ # # ]: 0 : if (string_in(gwr%dtset%gwr_task, "GAMMA_GW")) gwr%sig_diago = .False.
949 : :
950 : : ! Decide whether one should use supercells or convolutions in the BZ.
951 : 0 : gwr%use_supercell_for_tchi = .True.
952 [ # # ]: 0 : if (gwr%dtset%gwr_chi_algo == 0) then
953 : : ! Automatic selection
954 : 0 : ABI_ERROR("Not implemented Error")
955 : : else
956 : 0 : gwr%use_supercell_for_tchi = gwr%dtset%gwr_chi_algo == 1
957 : : end if
958 : :
959 [ # # ]: 0 : if (gwr%dtset%gwr_sigma_algo == 0) then
960 : : ! Automatic selection
961 : 0 : ABI_ERROR("Not implemented Error")
962 : : else
963 : 0 : gwr%use_supercell_for_sigma = gwr%dtset%gwr_sigma_algo == 1
964 : : end if
965 : :
966 : : ! Set q0 for long-wavelength limit
967 [ # # # # ]: 0 : if (dtset%gw_nqlwl /= 0) gwr%q0 = dtset%gw_qlwl(:, 1)
968 : :
969 : 0 : mband = ks_ebands%mband; nbsum = dtset%nband(1)
970 [ # # ]: 0 : ABI_CHECK_IRANGE(nbsum, 1, mband, "Invalid nbsum")
971 : :
972 : : ! Define frequency mesh for sigma(w_real) and spectral functions.
973 : : ! Note that in GWR computing quantities on the real-axis is really cheap
974 : : ! so we can use very dense meshes without affecting performance.
975 : : ! The default for nfresp and freqspmax is zero.
976 : : ! Here we compute wr_step and nwrt so that we have e0 +- the expected plasmom frequency
977 : 0 : drude_plasmon_freq = sqrt(four_pi * ks_ebands%nelect / cryst%ucvol)
978 [ # # ]: 0 : wmax = dtset%freqspmax; if (abs(wmax) < tol6) wmax = two * drude_plasmon_freq
979 : 0 : gwr%nwr = dtset%nfreqsp
980 [ # # ]: 0 : if (gwr%nwr == 0) gwr%nwr = nint(wmax / (0.05_dp * eV_Ha))
981 [ # # ]: 0 : if (mod(gwr%nwr, 2) == 0) gwr%nwr = gwr%nwr + 1
982 : 0 : gwr%wr_step = wmax / (gwr%nwr - 1)
983 : :
984 : : ! =======================
985 : : ! Setup k-mesh and q-mesh
986 : : ! =======================
987 : :
988 : : ! Get full kBZ associated to ks_ebands
989 : : call kpts_ibz_from_kptrlatt(cryst, ks_ebands%kptrlatt, ks_ebands%kptopt, ks_ebands%nshiftk, ks_ebands%shiftk, &
990 [ # # # # : 0 : gwr%nkibz, kibz, wtk, gwr%nkbz, gwr%kbz) !, bz2ibz=bz2ibz)
# # ]
991 : : !new_kptrlatt=gwr%kptrlatt, new_shiftk=gwr%kshift,
992 : : !bz2ibz=new%ind_qbz2ibz) # FIXME
993 [ # # ]: 0 : ABI_FREE(wtk)
994 : :
995 : : ! In principle kibz should be equal to ks_ebands%kptns.
996 [ # # ]: 0 : ABI_CHECK_IEQ(gwr%nkibz, ks_ebands%nkpt, "nkibz != ks_ebands%nkpt")
997 [ # # # # : 0 : ABI_CHECK(all(abs(ks_ebands%kptns - kibz) < tol12), "ks_ebands%kibz != kibz")
# # # # ]
998 : :
999 [ # # # # ]: 0 : can_use_kshifts = .not. gwr%use_supercell_for_tchi .and. .not. gwr%use_supercell_for_sigma
1000 : : !can_use_kshifts = .False.
1001 : :
1002 [ # # # # : 0 : if (.not. (isdiagmat(ks_ebands%kptrlatt) .and. ks_ebands%nshiftk == 1) .and. .not. can_use_kshifts) then
# # ]
1003 : 0 : ABI_ERROR("GWR code requires ngkpt with one shift!")
1004 : : end if
1005 [ # # ]: 0 : gwr%ngkpt = get_diag(ks_ebands%kptrlatt)
1006 : :
1007 : : ! Note symrec convention here.
1008 : 0 : kptopt = ks_ebands%kptopt
1009 : 0 : call krank_ibz%from_kptrlatt(gwr%nkibz, kibz, ks_ebands%kptrlatt, compute_invrank=.False.)
1010 : :
1011 [ # # # # : 0 : ABI_MALLOC(gwr%kbz2ibz, (6, gwr%nkbz))
# # # # #
# # # #
# ]
1012 [ # # ]: 0 : if (kpts_map("symrec", kptopt, cryst, krank_ibz, gwr%nkbz, gwr%kbz, gwr%kbz2ibz) /= 0) then
1013 : 0 : ABI_ERROR("Cannot map kBZ to IBZ!")
1014 : : end if
1015 : :
1016 : : ! Order kbz by stars and rearrange entries in kbz2ibz table.
1017 : 0 : call kpts_pack_in_stars(gwr%nkbz, gwr%kbz, gwr%kbz2ibz)
1018 [ # # ]: 0 : if (my_rank == master) then
1019 : 0 : call kpts_map_print(units, " Mapping kBZ --> kIBZ", "symrec", gwr%kbz, kibz, gwr%kbz2ibz, gwr%dtset%prtvol)
1020 : : end if
1021 : :
1022 : : !call get_ibz2bz(gwr%nkibz, gwr%nkbz, gwr%kbz2ibz, kibz2bz, msg, ierr)
1023 : : !ABI_CHECK(ierr == 0, sjoin("Something wrong in symmetry tables for k-points", ch10, msg))
1024 : :
1025 : : ! Table with symrel conventions for the symmetrization of the wfs.
1026 [ # # # # : 0 : ABI_MALLOC(gwr%kbz2ibz_symrel, (6, gwr%nkbz))
# # # # #
# # # #
# ]
1027 [ # # ]: 0 : if (kpts_map("symrel", kptopt, cryst, krank_ibz, gwr%nkbz, gwr%kbz, gwr%kbz2ibz_symrel) /= 0) then
1028 : 0 : ABI_ERROR("Cannot map kBZ to IBZ!")
1029 : : end if
1030 : :
1031 : : ! Here we set up the q-mesh for chi and w and the corresponding symmetry tables.
1032 : : ! Supercell algos require Gamma-centered meshes with ngqpt so that we can easily insert q+G in the FFT box
1033 : : ! Convolution algos can handle multiple shifts in the k-mesh.
1034 : : ! After this block we should know IBZ, BZ, weights and qbz2ibz mapping
1035 [ # # ]: 0 : if (.not. can_use_kshifts) then
1036 : :
1037 : : ! Setup IBZ q-points, weights and BZ. Always use q --> -q symmetry even in systems without inversion
1038 [ # # # # ]: 0 : my_nshiftq = 1; my_shiftq = zero; qptrlatt = ks_ebands%kptrlatt
1039 : : call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt1, my_nshiftq, my_shiftq, & ! in
1040 [ # # # # : 0 : gwr%nqibz, gwr%qibz, gwr%wtq, gwr%nqbz, gwr%qbz) ! out
# # ]
1041 : :
1042 [ # # # # : 0 : ABI_CHECK(all(abs(gwr%qibz(:,1)) < tol16), "First qpoint in qibz should be Gamma!")
# # ]
1043 [ # # ]: 0 : gwr%ngqpt = get_diag(qptrlatt)
1044 : :
1045 : : ! Table with symrec conventions for the symmetrization of chi.
1046 [ # # # # : 0 : ABI_MALLOC(gwr%qbz2ibz, (6, gwr%nqbz))
# # # # #
# # # #
# ]
1047 : :
1048 : 0 : call qrank%from_kptrlatt(gwr%nqibz, gwr%qibz, qptrlatt, compute_invrank=.False.)
1049 [ # # ]: 0 : if (kpts_map("symrec", qptopt1, cryst, qrank, gwr%nqbz, gwr%qbz, gwr%qbz2ibz) /= 0) then
1050 : 0 : ABI_ERROR("Cannot map qBZ to IBZ!")
1051 : : end if
1052 : 0 : call qrank%free()
1053 : :
1054 : : else
1055 : : ! === Create basic data types for the calculation ===
1056 : : ! Kmesh defines the k-point sampling for the wavefunctions.
1057 : : ! Qmesh defines the q-point sampling for chi0, all possible differences k1-k2 reduced to the IBZ.
1058 : : ! TODO Kmesh%bz should be in [-half, half[ but this modification is painful!
1059 : 0 : call Kmesh%init(cryst, gwr%nkibz, kibz, dtset%kptopt, wrap_1zone=.FALSE.)
1060 : :
1061 : : ! Some required information are not filled up inside kmesh_init. So doing it here, even though it is not clean
1062 [ # # # # ]: 0 : Kmesh%kptrlatt(:,:) = Dtset%kptrlatt(:,:)
1063 : 0 : Kmesh%nshift = Dtset%nshiftk
1064 [ # # # # : 0 : ABI_MALLOC(Kmesh%shift, (3, Kmesh%nshift))
# # # # #
# # # #
# ]
1065 [ # # # # ]: 0 : Kmesh%shift(:,:) = Dtset%shiftk(:,1:Dtset%nshiftk)
1066 : : !call Kmesh%print(units, header="K-mesh for the wavefunctions", prtvol=Dtset%prtvol)
1067 : :
1068 : : ! === Find Q-mesh ===
1069 : : ! Stop if a nonzero umklapp is needed to reconstruct the BZ.
1070 : : ! epsilon^-1(Sq) indeed should be symmetrized in csigme using a different expression (G-G_o is needed)
1071 : 0 : call qmesh%find_qmesh(cryst, Kmesh)
1072 : : !call qmesh%print(units, "Q-mesh for the screening function", prtvol=dtset%prtvol)
1073 : :
1074 : : ! Transfer data from qmesh to gwr.
1075 : 0 : gwr%nqibz = qmesh%nibz
1076 : 0 : gwr%nqbz = qmesh%nbz
1077 : :
1078 [ # # ]: 0 : call alloc_copy(qmesh%ibz, gwr%qibz)
1079 [ # # ]: 0 : call alloc_copy(qmesh%wt, gwr%wtq)
1080 [ # # ]: 0 : call alloc_copy(qmesh%bz, gwr%qbz)
1081 : :
1082 [ # # # # : 0 : ABI_CHECK(all(abs(gwr%qibz(:,1)) < tol16), "First qpoint in qibz should be Gamma!")
# # ]
1083 [ # # ]: 0 : gwr%ngqpt = -1
1084 : :
1085 : : ! Table with symrec conventions for the symmetrization of chi.
1086 [ # # # # : 0 : ABI_MALLOC(gwr%qbz2ibz, (6, gwr%nqbz))
# # # # #
# # # #
# ]
1087 : :
1088 [ # # ]: 0 : do iq_bz=1,Qmesh%nbz
1089 : 0 : call qmesh%get_bz_item(iq_bz, qbz, iq_ibz, isym, itim)
1090 : 0 : gwr%qbz2ibz(1, iq_bz) = iq_ibz
1091 : 0 : gwr%qbz2ibz(2, iq_bz) = isym
1092 [ # # ]: 0 : gwr%qbz2ibz(3:5, iq_bz) = zero
1093 : : ! Note different conventions from itim between the Qmesh routines used in conventional GW and Abinit routines.
1094 [ # # ]: 0 : gwr%qbz2ibz(6, iq_bz) = merge(0, 1, itim == 1)
1095 [ # # # # : 0 : sq = (3-2*itim) * MATMUL(cryst%symrec(:,:,isym), qmesh%ibz(:,iq_ibz))
# # # # #
# # # #
# ]
1096 [ # # # # : 0 : if (ANY(ABS(qbz-sq) > 1.0d-4)) then
# # ]
1097 : : write(msg,'(a,3f6.3,a,3f6.3,2a,9i3,a,i2,2a)')&
1098 : 0 : ' qpoint ',qbz,' is the symmetric of ',qmesh%ibz(:,iq_ibz),ch10,&
1099 : 0 : ' through operation ',cryst%symrec(:,:,isym),' and itim ',itim,ch10,&
1100 : 0 : ' however a non zero umklapp G_o vector is required and this is not yet allowed'
1101 : 0 : ABI_ERROR(msg)
1102 : : end if
1103 : : end do
1104 : 0 : call kmesh%free(); call qmesh%free()
1105 : : end if
1106 : :
1107 : : ! Order qbz by stars and rearrange entries in qbz2ibz table.
1108 : 0 : call kpts_pack_in_stars(gwr%nqbz, gwr%qbz, gwr%qbz2ibz)
1109 [ # # ]: 0 : if (my_rank == master) then
1110 : 0 : call kpts_map_print(units, " Mapping qBZ --> qIBZ", "symrec", gwr%qbz, gwr%qibz, gwr%qbz2ibz, gwr%dtset%prtvol)
1111 : : end if
1112 : :
1113 : : ! ==========================
1114 : : ! Setup k-points in Sigma_nk
1115 : : ! ==========================
1116 [ # # # # : 0 : gwr%ks_gaps = ks_ebands%get_gaps(gap_err)
# # # # #
# # # # #
# # ]
1117 : :
1118 [ # # ]: 0 : if (my_rank == master) call gwr%ks_gaps%print(units, header="Kohn-Sham gaps and band edges from IBZ mesh")
1119 : :
1120 : : ! TODO: nkcalc should be spin dependent.
1121 : : ! This piece of code is taken from m_sigmaph.
1122 : : ! In principle one should use the same algorithm in setup_sigma (legacy GW code).
1123 [ # # ]: 0 : if (dtset%nkptgw /= 0) then
1124 : : ! Treat the k-points and bands specified in the input file via kptgw and bdgw.
1125 [ # # # # : 0 : call sigtk_kcalc_from_nkptgw(dtset, mband, gwr%nkcalc, gwr%kcalc, gwr%bstart_ks, gwr%nbcalc_ks)
# # ]
1126 : :
1127 : : else
1128 [ # # # # : 0 : if (any(abs(dtset%sigma_erange) > zero)) then
# # ]
1129 : : ! Use sigma_erange and (optionally) sigma_ngkpt
1130 : : call sigtk_kcalc_from_erange(dtset, cryst, ks_ebands, gwr%ks_gaps, &
1131 [ # # # # : 0 : gwr%nkcalc, gwr%kcalc, gwr%bstart_ks, gwr%nbcalc_ks, input_comm)
# # ]
1132 : :
1133 : : else
1134 : : ! Use qp_range to select the interesting k-points and the corresponding bands.
1135 : : !
1136 : : ! 0 --> Compute the QP corrections only for the fundamental and the direct gap.
1137 : : ! +num --> Compute the QP corrections for all the k-points in the irreducible zone and include `num`
1138 : : ! bands above and below the Fermi level.
1139 : : ! -num --> Compute the QP corrections for all the k-points in the irreducible zone.
1140 : : ! Include all occupied states and `num` empty states.
1141 : :
1142 : 0 : qprange_ = dtset%gw_qprange
1143 [ # # # # ]: 0 : if (gap_err /= 0 .and. qprange_ == 0) then
1144 : 0 : ABI_WARNING("Cannot compute fundamental and direct gap (likely metal). Will replace qprange 0 with qprange 1")
1145 : 0 : qprange_ = 1
1146 : : end if
1147 : :
1148 [ # # ]: 0 : if (qprange_ /= 0) then
1149 [ # # # # : 0 : call sigtk_kcalc_from_qprange(dtset, cryst, ks_ebands, qprange_, gwr%nkcalc, gwr%kcalc, gwr%bstart_ks, gwr%nbcalc_ks)
# # ]
1150 : : else
1151 : : ! qprange is not specified in the input.
1152 : : ! Include direct and fundamental KS gap or include states depending on the position wrt band edges.
1153 [ # # # # : 0 : call sigtk_kcalc_from_gaps(dtset, ks_ebands, gwr%ks_gaps, gwr%nkcalc, gwr%kcalc, gwr%bstart_ks, gwr%nbcalc_ks)
# # ]
1154 : : end if
1155 : : end if
1156 : :
1157 : : end if ! nkptgw /= 0
1158 : :
1159 : : ! Include all degenerate states and map kcalc to the IBZ. NB: This part is copied from sigmaph.
1160 : :
1161 : : ! The k-point and the symmetries connecting the BZ k-point to the IBZ.
1162 [ # # # # : 0 : ABI_MALLOC(gwr%kcalc2ibz, (gwr%nkcalc, 6))
# # # # #
# # # #
# ]
1163 : :
1164 : : ! Workspace arrays used to compute degeneracy tables.
1165 [ # # # # : 0 : ABI_ICALLOC(degblock_all, (2, mband, gwr%nkcalc, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1166 [ # # # # : 0 : ABI_ICALLOC(ndeg_all, (gwr%nkcalc, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# ]
1167 : :
1168 : 0 : ierr = 0
1169 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
1170 : : ! Note symrel and use_symrel.
1171 : : ! These are the conventions for the symmetrization of the wavefunctions used in cgtk_rotate.
1172 [ # # ]: 0 : kk = gwr%kcalc(:, ikcalc)
1173 : :
1174 [ # # ]: 0 : if (kpts_map("symrel", kptopt, cryst, krank_ibz, 1, kk, indkk_k) /= 0) then
1175 : : write(msg, '(5a)' ) &
1176 [ # # ]: 0 : "The WFK file cannot be used to compute self-energy corrections at k-point: ",trim(ktoa(kk)),ch10,&
1177 : 0 : "The k-point cannot be generated from a symmetrical one.", ch10
1178 : 0 : ABI_ERROR(msg)
1179 : : end if
1180 : :
1181 : : ! TODO: Invert dims and update abipy
1182 [ # # ]: 0 : gwr%kcalc2ibz(ikcalc, :) = indkk_k(:, 1)
1183 : :
1184 : 0 : ik_ibz = indkk_k(1,1); isym_k = indkk_k(2,1)
1185 [ # # ]: 0 : trev_k = indkk_k(6,1); g0_k = indkk_k(3:5,1)
1186 [ # # # # : 0 : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
# # # # ]
1187 : : !kk_ibz = ks_ebands%kptns(:,ik_ibz)
1188 : : if (.not. isirr_k) then
1189 : 0 : ABI_WARNING(sjoin("The k-point in Sigma_{nk} must be in the IBZ but got:", ktoa(kk)))
1190 : 0 : ierr = ierr + 1
1191 : : end if
1192 : :
1193 : : ! We will have to average the QP corrections over degenerate states if symsigma=1 is used.
1194 : : ! Here we make sure that all the degenerate states are included.
1195 : : ! Store also band indices of the degenerate sets, used to average final results.
1196 [ # # ]: 0 : if (abs(gwr%dtset%symsigma) == 1) then
1197 : 0 : cnt = 0
1198 [ # # ]: 0 : do spin=1,gwr%nsppol
1199 : 0 : bstop = gwr%bstart_ks(ikcalc, spin) + gwr%nbcalc_ks(ikcalc, spin) - 1
1200 : : call ks_ebands%enclose_degbands(ik_ibz, spin, gwr%bstart_ks(ikcalc, spin), bstop, changed, gwr%dtset%symsigma_de, &
1201 [ # # ]: 0 : degblock=degblock)
1202 [ # # ]: 0 : if (changed) then
1203 : 0 : gwr%nbcalc_ks(ikcalc, spin) = bstop - gwr%bstart_ks(ikcalc, spin) + 1
1204 : 0 : cnt = cnt + 1
1205 [ # # ]: 0 : if (cnt < 5) then
1206 : : write(msg,'(2(a,i0),2a,2(1x,i0))') &
1207 : 0 : "Not all the degenerate states for ikcalc: ",ikcalc,", spin: ",spin,ch10, &
1208 : 0 : "were included in the bdgw set. bdgw has been automatically changed to: ",gwr%bstart_ks(ikcalc, spin), bstop
1209 : 0 : ABI_COMMENT(msg)
1210 : : end if
1211 : : write(msg,'(2(a,i0),2a)') &
1212 : 0 : "The number of included states: ", bstop, &
1213 : 0 : " is larger than the number of bands in the input ",dtset%nband(ik_ibz + (spin-1)*ks_ebands%nkpt),ch10,&
1214 : 0 : "Action: Increase nband."
1215 [ # # ]: 0 : ABI_CHECK(bstop <= dtset%nband(ik_ibz + (spin-1)*ks_ebands%nkpt), msg)
1216 : : end if
1217 : :
1218 : : ! Store band indices used for averaging (shifted by bstart_ks)
1219 : 0 : ndeg = size(degblock, dim=2)
1220 : 0 : ndeg_all(ikcalc, spin) = ndeg
1221 [ # # # # ]: 0 : degblock_all(:, 1:ndeg, ikcalc, spin) = degblock(:, 1:ndeg)
1222 : :
1223 [ # # ]: 0 : ABI_FREE(degblock)
1224 : : end do
1225 : : end if ! symsigma
1226 : : end do ! ikcalc
1227 : :
1228 [ # # ]: 0 : ABI_CHECK(ierr == 0, "kptgw wavevectors must be in the IBZ read from the WFK file.")
1229 : :
1230 : : ! Build degtab tables to average self-energy matrix element if symsigma /= 0
1231 [ # # ]: 0 : if (abs(gwr%dtset%symsigma) == 1) then
1232 [ # # # # : 0 : ABI_MALLOC(gwr%degtab, (gwr%nkcalc, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1233 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
1234 [ # # ]: 0 : do spin=1,gwr%nsppol
1235 : 0 : ndeg = ndeg_all(ikcalc, spin)
1236 [ # # # # : 0 : ABI_MALLOC(gwr%degtab(ikcalc, spin)%bids, (ndeg))
# # # # #
# # # # #
# # # # #
# ]
1237 [ # # ]: 0 : do ii=1,ndeg
1238 : 0 : cnt = degblock_all(2, ii, ikcalc, spin) - degblock_all(1, ii, ikcalc, spin) + 1
1239 [ # # # # : 0 : ABI_MALLOC(gwr%degtab(ikcalc, spin)%bids(ii)%vals, (cnt))
# # # # #
# # # #
# ]
1240 : : ! Note that we start to count bands from bstart_ks(ikcalc, spin)
1241 : : gwr%degtab(ikcalc, spin)%bids(ii)%vals = [(jj, jj= &
1242 [ # # # # : 0 : degblock_all(1, ii, ikcalc, spin), degblock_all(2, ii, ikcalc, spin))]
# # # # #
# # # # #
# # ]
1243 : : end do
1244 : : end do
1245 : : end do
1246 : : end if
1247 : :
1248 [ # # ]: 0 : ABI_FREE(degblock_all)
1249 [ # # ]: 0 : ABI_FREE(ndeg_all)
1250 : :
1251 : : ! Now we can finally compute max_nbcalc.
1252 [ # # # # ]: 0 : gwr%max_nbcalc = maxval(gwr%nbcalc_ks)
1253 [ # # # # : 0 : ABI_MALLOC(gwr%bstop_ks, (gwr%nkcalc, gwr%nsppol))
# # # # #
# # # # #
# # # # ]
1254 [ # # # # : 0 : gwr%bstop_ks = gwr%bstart_ks + gwr%nbcalc_ks - 1
# # # # #
# # # ]
1255 [ # # # # : 0 : gwr%b1gw = minval(gwr%bstart_ks); gwr%b2gw = maxval(gwr%bstop_ks)
# # # # ]
1256 : :
1257 : 0 : call krank_ibz%free()
1258 [ # # ]: 0 : ABI_FREE(kibz) ! Deallocate kibz here because krank_ibz keeps a reference to this array.
1259 : :
1260 : : ! ================================
1261 : : ! Setup tau/omega mesh and weights
1262 : : ! ================================
1263 : : ! Compute min/max transition energy taking into account nsppol if any.
1264 [ # # # # : 0 : gwr%te_min = minval(gwr%ks_gaps%cb_min - gwr%ks_gaps%vb_max)
# # # # ]
1265 [ # # # # : 0 : gwr%te_max = maxval(ks_ebands%eig(nbsum,:,:) - ks_ebands%eig(1,:,:))
# # # # #
# # # ]
1266 [ # # ]: 0 : if (gwr%te_min <= tol6) then
1267 : 0 : gwr%te_min = tol6
1268 : 0 : ABI_ERROR("System is metallic or with a very small fundamental gap! Check energies in WFK file!")
1269 : : end if
1270 : 0 : gwr%ntau = dtset%gwr_ntau
1271 : :
1272 : 0 : regterm = dtset%gwr_regterm
1273 [ # # ]: 0 : if (regterm > -tol16) then
1274 : 0 : call wrtout(std_out, sjoin("Computing minimax grid with user-provided regterm:", ftoa(regterm)))
1275 : : call gx_minimax_grid(gwr%ntau, gwr%te_min, gwr%te_max, & ! in
1276 : : gwr%tau_mesh, gwr%tau_wgs, gwr%iw_mesh, gwr%iw_wgs, & ! out args allocated by the routine.
1277 : : gwr%cosft_wt, gwr%cosft_tw, gwr%sinft_wt, &
1278 [ # # # # : 0 : gwr%ft_max_error, gwr%cosft_duality_error, ierr, regterm=regterm)
# # # # #
# # # #
# ]
1279 [ # # ]: 0 : ABI_CHECK(ierr == 0, "Error in gx_minimax_grid")
1280 : : else
1281 : 0 : regterm = zero
1282 : 0 : call wrtout(std_out, sjoin("Computing minimax grid with user-provided regterm:", ftoa(regterm)))
1283 : : call gx_minimax_grid(gwr%ntau, gwr%te_min, gwr%te_max, & ! in
1284 : : gwr%tau_mesh, gwr%tau_wgs, gwr%iw_mesh, gwr%iw_wgs, & ! out args allocated by the routine.
1285 : : gwr%cosft_wt, gwr%cosft_tw, gwr%sinft_wt, &
1286 [ # # # # : 0 : gwr%ft_max_error, gwr%cosft_duality_error, ierr, regterm=regterm)
# # # # #
# # # #
# ]
1287 [ # # ]: 0 : ABI_CHECK(ierr == 0, "Error in gx_minimax_grid")
1288 : :
1289 : : ! If duality error is big, use regterm = 1e-6
1290 [ # # ]: 0 : if (gwr%cosft_duality_error > half) then
1291 [ # # ]: 0 : ABI_SFREE(gwr%tau_mesh)
1292 [ # # ]: 0 : ABI_SFREE(gwr%tau_wgs)
1293 [ # # ]: 0 : ABI_SFREE(gwr%iw_mesh)
1294 [ # # ]: 0 : ABI_SFREE(gwr%iw_wgs)
1295 [ # # ]: 0 : ABI_SFREE(gwr%cosft_wt)
1296 [ # # ]: 0 : ABI_SFREE(gwr%cosft_tw)
1297 [ # # ]: 0 : ABI_SFREE(gwr%sinft_wt)
1298 : 0 : regterm = tol6
1299 : 0 : call wrtout(std_out, sjoin("LARGE duality error -> recomputing minimax grid with regterm:", ftoa(regterm)))
1300 : 0 : prev_dual_error = gwr%cosft_duality_error
1301 : : call gx_minimax_grid(gwr%ntau, gwr%te_min, gwr%te_max, & ! in
1302 : : gwr%tau_mesh, gwr%tau_wgs, gwr%iw_mesh, gwr%iw_wgs, & ! out args allocated by the routine.
1303 : : gwr%cosft_wt, gwr%cosft_tw, gwr%sinft_wt, &
1304 [ # # # # : 0 : gwr%ft_max_error, gwr%cosft_duality_error, ierr, regterm=regterm)
# # # # #
# # # #
# ]
1305 [ # # ]: 0 : ABI_CHECK(ierr == 0, "Error in gx_minimax_grid")
1306 : :
1307 [ # # ]: 0 : if (gwr%cosft_duality_error > prev_dual_error) then
1308 : 0 : ABI_WARNING("Using regterm didn't decrease the duality error")
1309 : : end if
1310 : : end if
1311 : : end if
1312 : :
1313 [ # # ]: 0 : if (gwr%comm%me == 0) then
1314 : : ! Print some info on errors.
1315 : 0 : write(std_out, "(3a)")ch10, " Computing F(delta) = \int_0^{\infty} dw / (w^2 + delta^2) = pi/2/delta ", ch10
1316 : 0 : write(std_out, "(*(a12,2x))")"delta", "numeric", "exact", "abs_rerr (%)"
1317 [ # # ]: 0 : do ii=1,10
1318 : 0 : delta = (ii * gwr%te_min)
1319 [ # # ]: 0 : eval_int = sum(gwr%iw_wgs(:) / (gwr%iw_mesh(:)**2 + delta**2))
1320 : 0 : exact_int = pi / (two * delta)
1321 : 0 : abs_rerr = 100 * abs(eval_int - exact_int) / exact_int
1322 : 0 : write(std_out, "(*(es12.5,2x))") delta, eval_int, exact_int, abs_rerr
1323 : : end do
1324 : :
1325 : 0 : write(std_out, "(3a)")ch10," Computing F(w) = \int_0^{\infty} e^{-w tau} dtau", ch10
1326 : 0 : write(std_out, "(*(a12,2x))")"w", "numeric", "exact", "abs_rerr (%)"
1327 [ # # ]: 0 : do itau=1,gwr%ntau
1328 [ # # ]: 0 : eval_int = sum(gwr%tau_wgs(:) * exp(-gwr%tau_mesh(:) * gwr%iw_mesh(itau)))
1329 : 0 : exact_int = one / gwr%iw_mesh(itau)
1330 : 0 : abs_rerr = 100 * abs(eval_int - exact_int) / exact_int
1331 : 0 : write(std_out, "(*(es12.5,2x))") gwr%iw_mesh(itau), eval_int, exact_int, abs_rerr
1332 : : end do
1333 : 0 : write(std_out, "(a)")
1334 : : end if
1335 : :
1336 : : ! =========================================
1337 : : ! Find FFT mesh and max number of g-vectors
1338 : : ! =========================================
1339 : : ! Note the usage of gwr_boxcutmin and the loops over the full BZ.
1340 [ # # # # ]: 0 : gwr%g_ngfft = gwr%dtset%ngfft; gwr%g_ngfft(1:6) = 0 ! Allow user to specify fftalg
1341 : :
1342 : 0 : gwr%green_mpw = -1
1343 [ # # ]: 0 : do ik_bz=1,gwr%nkbz
1344 [ # # ]: 0 : kk_bz = gwr%kbz(:, ik_bz)
1345 [ # # ]: 0 : call get_kg(kk_bz, istwfk1, dtset%ecutwfn, gwr%cryst%gmet, npw_, gvec_)
1346 [ # # ]: 0 : ABI_FREE(gvec_)
1347 : : call getng(dtset%gwr_boxcutmin, dtset%chksymtnons, dtset%ecutwfn, cryst%gmet, &
1348 : : kk_bz, me_fft0, gwr%g_mgfft, gwr%g_nfft, gwr%g_ngfft, nproc_fft1, cryst%nsym, paral_fft0, &
1349 : 0 : cryst%symrel, cryst%tnons, gpu_option=gwr%dtset%gpu_option, unit=dev_null)
1350 : 0 : gwr%green_mpw = max(gwr%green_mpw, npw_)
1351 : : end do
1352 : :
1353 : 0 : gwr%tchi_mpw = -1
1354 [ # # ]: 0 : do iq_bz=1,gwr%nqbz
1355 [ # # ]: 0 : qq_bz = gwr%qbz(:, iq_bz)
1356 [ # # ]: 0 : call get_kg(qq_bz, istwfk1, dtset%ecuteps, gwr%cryst%gmet, npw_, gvec_)
1357 [ # # ]: 0 : ABI_FREE(gvec_)
1358 : : call getng(dtset%gwr_boxcutmin, dtset%chksymtnons, dtset%ecuteps, cryst%gmet, &
1359 : : qq_bz, me_fft0, gwr%g_mgfft, gwr%g_nfft, gwr%g_ngfft, nproc_fft1, cryst%nsym, &
1360 : 0 : paral_fft0, cryst%symrel, cryst%tnons, gpu_option=gwr%dtset%gpu_option, unit=dev_null)
1361 : 0 : gwr%tchi_mpw = max(gwr%tchi_mpw, npw_)
1362 [ # # ]: 0 : if (iq_bz == 1) then
1363 [ # # # # : 0 : ABI_CHECK(all(abs(qq_bz) < tol16), "First qpoint in the qbz should be Gamma!")
# # ]
1364 : : end if
1365 : : end do
1366 : :
1367 : : ! No augmentation of workspace arrays.
1368 [ # # ]: 0 : gwr%g_ngfft(4:6) = gwr%g_ngfft(1:3)
1369 : :
1370 : : ! ========================
1371 : : ! === MPI DISTRIBUTION ===
1372 : : ! ========================
1373 : : !
1374 : : ! Here we define the following quantities:
1375 : : ! - np_k, np_g, np_t, np_s
1376 : : ! - gwr%comm and gwr%idle_proc
1377 : : !
1378 : : ! NB: Do not use input_comm after this section as idle processors return immediately.
1379 : :
1380 [ # # # # : 0 : if (any(dtset%gwr_np_kgts /= 0)) then
# # ]
1381 : : ! Use grid from input file.
1382 : 0 : np_k = dtset%gwr_np_kgts(1); np_g = dtset%gwr_np_kgts(2); np_t = dtset%gwr_np_kgts(3); np_s = dtset%gwr_np_kgts(4)
1383 : : !call xmpi_comm_multiple_of(product(dtset%gwr_np_kgts), input_comm, gwr%idle_proc, gwr%comm)
1384 : : !if (gwr%idle_proc) return
1385 : 0 : gwr%comm = xcomm_from_mpi_int(input_comm)
1386 : 0 : all_nproc = gwr%comm%nproc
1387 : :
1388 : : else
1389 : : ! Automatic grid generation.
1390 : : !
1391 : : ! Priorities | MPI Scalability | Memory
1392 : : ! ==================================================================================================
1393 : : ! spin (if any) | excellent | scales
1394 : : ! g/r (PBLAS) | network-intensive ! scales
1395 : : ! tau | excellent | scales
1396 : : ! kbz | newtwork-intensive | scales (depends on the BZ -> IBZ mapping)
1397 : :
1398 : 0 : gwr%comm = xcomm_from_mpi_int(input_comm)
1399 : 0 : all_nproc = gwr%comm%nproc
1400 : : !call xmpi_comm_multiple_of(gwr%ntau * gwr%dtset%nsppol, input_comm, gwr%idle_proc, gwr%comm)
1401 : : !if (gwr%idle_proc) return
1402 : : !all_nproc = xmpi_comm_size(gwr%comm)
1403 : :
1404 : : ! Start from a configuration that minimizes memory i.e use all procs for g-parallelism,
1405 : : ! then check whether it's possible to move some procs to the other levels
1406 : : ! without spoiling parallel efficiency and/or increasing memory per MPI proc.
1407 : : ! Only master rank works here for consistency reasons.
1408 [ # # ]: 0 : if (my_rank == master) then
1409 [ # # ]: 0 : dims_kgts = [1, all_nproc, 1, 1]
1410 : 0 : est = estimate(gwr, dims_kgts)
1411 : 0 : prev_efficiency = est%efficiency; prev_speedup = est%speedup
1412 : 0 : call wrtout(units, sjoin("- Optimizing MPI grid with mem_per_cpu_mb:", ftoa(mem_per_cpu_mb), "[Mb]"), pre_newlines=1)
1413 : 0 : call wrtout(units, "- Use `abinit run.abi --mem-per-cpu=4G` to set mem_per_cpu_mb in the submission script")
1414 : 0 : write(msg, "(a,4(a4,2x),3(a12,2x))") "- ", "np_k", "np_g", "np_t", "np_s", "memb_per_cpu", "efficiency", "speedup"
1415 : 0 : call wrtout(units, msg)
1416 : 0 : ip_k = dims_kgts(1); ip_g = dims_kgts(2); ip_t = dims_kgts(3); ip_s = dims_kgts(4)
1417 : 0 : write(msg, "(a,4(i4,2x),3(es12.5,2x))") "- ", ip_k, ip_g, ip_t, ip_s, est%mem_total, est%efficiency, est%speedup
1418 : 0 : call wrtout(units, msg)
1419 : :
1420 [ # # ]: 0 : do ip_s=1,gwr%nsppol
1421 [ # # ]: 0 : do ip_t=1,gwr%ntau
1422 [ # # ]: 0 : if (mod(gwr%ntau, ip_t) /= 0) cycle ! ip_t should divide gwr%ntau.
1423 [ # # ]: 0 : do ip_k=1,gwr%nkbz
1424 [ # # ]: 0 : if (mod(gwr%nkbz, ip_k) /= 0) cycle ! ip_k is should divide gwr%nkbz.
1425 [ # # ]: 0 : do ip_g=1,gwr%green_mpw
1426 [ # # ]: 0 : try_dims_kgts = [ip_k, ip_g, ip_t, ip_s]
1427 [ # # # # : 0 : if (product(try_dims_kgts) /= all_nproc .or. all(try_dims_kgts == dims_kgts)) cycle
# # # # ]
1428 : : !ABI_CHECK(block_dist_1d(gwr%green_mpw, ip_g, col_bsize, msg), msg)
1429 : 0 : est = estimate(gwr, try_dims_kgts)
1430 : : !if (est%mem_total < mem_per_cpu_mb * 0.8_dp .and. est%efficiency > prev_efficiency) then
1431 [ # # # # ]: 0 : if (est%mem_total < mem_per_cpu_mb * 0.8_dp .and. est%speedup > prev_speedup) then
1432 : 0 : prev_efficiency = est%efficiency; prev_speedup = est%speedup; dims_kgts = try_dims_kgts
1433 : : end if
1434 : 0 : write(msg,"(a,4(i4,2x),3(es12.5,2x))")"- ", ip_k, ip_g, ip_t, ip_s, est%mem_total, est%efficiency, est%speedup
1435 : 0 : call wrtout(units, msg)
1436 : : end do
1437 : : end do
1438 : : end do
1439 : : end do
1440 : : end if ! master
1441 : :
1442 : 0 : call xmpi_bcast(dims_kgts, master, gwr%comm%value, ierr)
1443 : 0 : np_k = dims_kgts(1); np_g = dims_kgts(2); np_t = dims_kgts(3); np_s = dims_kgts(4)
1444 : :
1445 [ # # ]: 0 : if (my_rank == master) then
1446 : 0 : est = estimate(gwr, dims_kgts)
1447 : 0 : call wrtout(units, "-")
1448 : 0 : call wrtout(units, "- Selected MPI grid:")
1449 : 0 : ip_k = dims_kgts(1); ip_g = dims_kgts(2); ip_t = dims_kgts(3); ip_s = dims_kgts(4)
1450 : 0 : write(msg, "(a,4(a4,2x),3(a12,2x))") "- ", "np_k", "np_g", "np_t", "np_s", "memb_per_cpu", "efficiency", "speedup"
1451 : 0 : call wrtout(units, msg)
1452 : 0 : write(msg, "(a,4(i4,2x),3(es12.5,2x))")"- ", ip_k, ip_g, ip_t, ip_s, est%mem_total, est%efficiency, est%speedup
1453 : 0 : call wrtout(units, msg, newlines=1)
1454 : 0 : call est%print(units)
1455 : : end if
1456 : : end if
1457 : :
1458 : : ! ================================
1459 : : ! Build MPI grid and communicators
1460 : : ! ================================
1461 [ # # ]: 0 : dims_kgts = [np_k, np_g, np_t, np_s]
1462 [ # # ]: 0 : gwr%dtset%gwr_np_kgts = dims_kgts
1463 : 0 : periods(:) = .False.; reorder = .False.
1464 : :
1465 : : ! Consistency check.
1466 [ # # # # ]: 0 : if (product(dims_kgts) /= all_nproc) then
1467 : : write(msg, "(a,i0,3a, 5(a,1x,i0))") &
1468 : 0 : "Cannot create 4D Cartesian grid with total nproc: ", all_nproc, ch10, &
1469 : 0 : "Idle MPI processes are not supported. The product of the `nproc_*` vars should be equal to nproc while is it:", ch10, &
1470 [ # # ]: 0 : "k_nproc (", np_k, ") x g_nproc (", np_g, ") x tau_nproc (", np_t,") x spin_nproc (", np_s, ") == ", product(dims_kgts)
1471 : 0 : ABI_ERROR(msg)
1472 : : end if
1473 : :
1474 : : !!! FIXME HT: rewrite spin logic in redistribution routines
1475 [ # # # # ]: 0 : if (gwr%nspinor == 2 .and. np_s == 2) then
1476 : 0 : ABI_ERROR("Spin parallelism is not supported for nspinor=2 for now!")
1477 : : end if
1478 : :
1479 : : #ifdef HAVE_MPI
1480 : : block
1481 : : !integer,parameter :: k=1, g=2, t=3, s=4 ! Bad placement
1482 : : integer,parameter :: k=4, g=3, t=2, s=1 ! Much better placement
1483 [ # # # # ]: 0 : dims_kgts = dims_kgts(4:1:-1)
1484 : 0 : call MPI_CART_CREATE(gwr%comm%value, ndims, dims_kgts, periods, reorder, comm_cart, ierr)
1485 : :
1486 : : ! Find the index and coordinates of the current processor
1487 : 0 : call MPI_COMM_RANK(comm_cart, me_cart, ierr)
1488 : 0 : call MPI_CART_COORDS(comm_cart, me_cart, ndims, gwr%coords_stgk, ierr)
1489 : :
1490 : : ! k-point communicator
1491 : 0 : keepdim = .False.; keepdim(k) = .True.; call gwr%kpt_comm%from_cart_sub(comm_cart, keepdim)
1492 : : ! g-communicator
1493 : 0 : keepdim = .False.; keepdim(g) = .True.; call gwr%g_comm%from_cart_sub(comm_cart, keepdim)
1494 : : ! tau-communicator
1495 : 0 : keepdim = .False.; keepdim(t) = .True.; call gwr%tau_comm%from_cart_sub(comm_cart, keepdim)
1496 : : ! spin-communicator
1497 : 0 : keepdim = .False.; keepdim(s) = .True.; call gwr%spin_comm%from_cart_sub(comm_cart, keepdim)
1498 : : ! Communicator for the g-tau 2D grid.
1499 : 0 : keepdim = .False.; keepdim(g) = .True.; keepdim(t) = .True.; call gwr%gtau_comm%from_cart_sub(comm_cart, keepdim)
1500 : : ! Communicator for the k-g 2D grid.
1501 : 0 : keepdim = .False.; keepdim(k) = .True.; keepdim(g) = .True.; call gwr%kg_comm%from_cart_sub(comm_cart, keepdim)
1502 : : ! Communicator for the k-g-tau 3D subgrid.
1503 [ # # ]: 0 : keepdim = .True.; keepdim(s) = .False.; call gwr%kgt_comm%from_cart_sub(comm_cart, keepdim)
1504 : : ! Communicator for the k-tau-spin 3D subgrid.
1505 [ # # ]: 0 : keepdim = .True.; keepdim(g) = .False.; call gwr%kts_comm%from_cart_sub(comm_cart, keepdim)
1506 : 0 : call xmpi_comm_free(comm_cart)
1507 : : end block
1508 : : #endif
1509 : :
1510 : 0 : call wrtout(units, sjoin("P kpt_comm can use shmem:", yesno(gwr%kpt_comm%can_use_shmem())))
1511 : 0 : call wrtout(units, sjoin("P g_comm can use shmem:", yesno(gwr%g_comm%can_use_shmem())))
1512 : 0 : call wrtout(units, sjoin("P tau_comm can use shmem:", yesno(gwr%tau_comm%can_use_shmem())))
1513 : 0 : call wrtout(units, sjoin("P spin_comm can use shmem", yesno(gwr%spin_comm%can_use_shmem())))
1514 : : !call gwr%kpt_comm%print_names(); call gwr%g_comm%print_names()
1515 : :
1516 : : ! Define batch sizes for FFT transforms taking into account k-point parallelism, OpenMP threads and GPUs.
1517 : 0 : omp_nt = xomp_get_num_threads(open_parallel=.True.)
1518 : :
1519 [ # # ]: 0 : if (gwr%dtset%gwr_ucsc_batch(1) > 0) then
1520 : : ! Take it from input file (user is always right)
1521 : 0 : gwr%uc_batch_size = gwr%dtset%gwr_ucsc_batch(1) * omp_nt
1522 : : else
1523 : : ! Automatic detection
1524 : 0 : gwr%uc_batch_size = 1 * omp_nt
1525 [ # # ]: 0 : if (gwr%dtset%gpu_option /= ABI_GPU_DISABLED) then
1526 : : ! TODO: Optimize
1527 : 0 : gwr%uc_batch_size = 4 * omp_nt
1528 : : !gwr%uc_batch_size = 1
1529 : : end if
1530 : : end if
1531 : :
1532 [ # # ]: 0 : if (gwr%dtset%gwr_ucsc_batch(2) > 0) then
1533 : : ! Take it from input file (user is always right)
1534 : 0 : gwr%sc_batch_size = gwr%dtset%gwr_ucsc_batch(2) * omp_nt
1535 : : else
1536 : : ! Automatic detection
1537 : 0 : gwr%sc_batch_size = 1 * omp_nt
1538 [ # # ]: 0 : if (gwr%dtset%gpu_option /= ABI_GPU_DISABLED) then
1539 : : ! TODO: Optimize
1540 : 0 : gwr%sc_batch_size = 4 * omp_nt
1541 : : !gwr%sc_batch_size = 1
1542 : : end if
1543 : : end if
1544 : :
1545 : : ! Make sure all procs agree.
1546 : : !call xmpi_min_ip(gwr%sc_batch_size, gwr%comm%value, ierr)
1547 : : !call xmpi_min_ip(gwr%uc_batch_size, gwr%comm%value, ierr)
1548 : :
1549 [ # # ]: 0 : if (my_rank == master) then
1550 [ # # ]: 0 : call print_ngfft([std_out], gwr%g_ngfft, header="FFT mesh for Green's function")
1551 : 0 : call wrtout(units, sjoin("- FFT uc_batch_size:", itoa(gwr%uc_batch_size)))
1552 : 0 : call wrtout(units, sjoin("- FFT sc_batch_size:", itoa(gwr%sc_batch_size)))
1553 : : end if
1554 : :
1555 : : ! Block-distribute dimensions and allocate redirection table local index --> global index.
1556 [ # # ]: 0 : call xmpi_split_block(gwr%ntau, gwr%tau_comm%value, gwr%my_ntau, gwr%my_itaus)
1557 [ # # ]: 0 : ABI_CHECK(gwr%my_ntau > 0, "my_ntau == 0, decrease number of procs for tau level")
1558 : :
1559 : : ! Store the rank of the MPI proc in tau_comm treating the itau index.
1560 [ # # # # : 0 : ABI_MALLOC(gwr%tau_master, (gwr%ntau))
# # # # #
# # # #
# ]
1561 [ # # ]: 0 : gwr%tau_master = -1
1562 [ # # ]: 0 : do my_it=1,gwr%my_ntau
1563 : 0 : itau = gwr%my_itaus(my_it); gwr%tau_master(itau) = gwr%tau_comm%me
1564 : : end do
1565 : 0 : call xmpi_max_ip(gwr%tau_master, gwr%tau_comm%value, ierr)
1566 [ # # # # : 0 : ABI_CHECK(all(gwr%tau_master > -1), "tau_master!")
# # ]
1567 : :
1568 [ # # ]: 0 : call xmpi_split_block(gwr%nsppol, gwr%spin_comm%value, gwr%my_nspins, gwr%my_spins)
1569 [ # # ]: 0 : ABI_CHECK(gwr%my_nspins > 0, "my_nspins == 0, decrease number of MPI procs for spin level")
1570 : :
1571 : : ! Distribute k-points in the full BZ and build redirection tables.
1572 : : ! Finally, find the number of IBZ k-points treated by this MPI rank.
1573 [ # # ]: 0 : call xmpi_split_block(gwr%nkbz, gwr%kpt_comm%value, gwr%my_nkbz, gwr%my_kbz_inds)
1574 [ # # ]: 0 : ABI_CHECK(gwr%my_nkbz > 0, "my_nkbz == 0, decrease number of MPI procs for k-point level")
1575 : :
1576 : : ! Compute np_kibz
1577 [ # # # # : 0 : ABI_ICALLOC(gwr%np_kibz, (gwr%nkibz))
# # # # #
# # # # #
# # ]
1578 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
1579 : 0 : ik_bz = gwr%my_kbz_inds(my_ikf); ik_ibz = gwr%kbz2ibz(1, ik_bz)
1580 : 0 : gwr%np_kibz(ik_ibz) = 1
1581 : : end do
1582 : :
1583 [ # # # # ]: 0 : gwr%my_nkibz = count(gwr%np_kibz > 0)
1584 [ # # # # : 0 : ABI_MALLOC(gwr%my_kibz_inds, (gwr%my_nkibz))
# # # # #
# # # #
# ]
1585 : 0 : ii = 0
1586 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
1587 [ # # ]: 0 : if (gwr%np_kibz(ik_ibz) > 0) then
1588 : 0 : ii = ii + 1; gwr%my_kibz_inds(ii) = ik_ibz
1589 : : end if
1590 : : end do
1591 : :
1592 : 0 : call xmpi_sum(gwr%np_kibz, gwr%kpt_comm%value, ierr)
1593 : :
1594 : : ! Build table to distribute iterations over ik_ibz as kIBZ might be replicated across MPI procs.
1595 [ # # # # : 0 : ABI_ICALLOC(iwork, (gwr%kpt_comm%nproc, gwr%nkibz))
# # # # #
# # # # #
# # # # #
# # # ]
1596 [ # # # # : 0 : ABI_ICALLOC(got, (gwr%kpt_comm%nproc))
# # # # #
# # # # #
# # ]
1597 [ # # ]: 0 : do my_iki=1,gwr%my_nkibz
1598 : 0 : ik_ibz = gwr%my_kibz_inds(my_iki)
1599 : 0 : iwork(gwr%kpt_comm%me + 1, ik_ibz) = 1
1600 : : end do
1601 : 0 : call xmpi_sum(iwork, gwr%kpt_comm%value, ierr)
1602 : :
1603 [ # # # # : 0 : ABI_MALLOC(gwr%itreat_ikibz, (gwr%nkibz))
# # # # #
# # # #
# ]
1604 [ # # ]: 0 : gwr%itreat_ikibz = .False.
1605 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
1606 [ # # # # ]: 0 : ii = imin_loc(got, mask=iwork(:, ik_ibz) /= 0); got(ii) = got(ii) + 1
1607 [ # # ]: 0 : if (ii == gwr%kpt_comm%me + 1) gwr%itreat_ikibz(ik_ibz) = .True.
1608 : : end do
1609 [ # # ]: 0 : ABI_FREE(got)
1610 [ # # ]: 0 : ABI_FREE(iwork)
1611 : :
1612 : : ! Distribute q-points in full BZ, transfer symmetry tables.
1613 : : ! Finally find the number of my IBZ q-points that should be stored in memory.
1614 [ # # ]: 0 : call xmpi_split_block(gwr%nqbz, gwr%kpt_comm%value, gwr%my_nqbz, gwr%my_qbz_inds)
1615 : :
1616 : : ! Compute np_qibz
1617 [ # # # # : 0 : ABI_ICALLOC(gwr%np_qibz, (gwr%nqibz))
# # # # #
# # # # #
# # ]
1618 [ # # ]: 0 : do my_iqf=1,gwr%my_nqbz
1619 : 0 : iq_bz = gwr%my_qbz_inds(my_iqf); iq_ibz = gwr%qbz2ibz(1, iq_bz)
1620 : 0 : gwr%np_qibz(iq_ibz) = 1
1621 : : end do
1622 : :
1623 [ # # # # ]: 0 : gwr%my_nqibz = count(gwr%np_qibz > 0)
1624 [ # # # # : 0 : ABI_MALLOC(gwr%my_qibz_inds, (gwr%my_nqibz))
# # # # #
# # # #
# ]
1625 : 0 : ii = 0
1626 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
1627 [ # # ]: 0 : if (gwr%np_qibz(iq_ibz) > 0) then
1628 : 0 : ii = ii + 1; gwr%my_qibz_inds(ii) = iq_ibz
1629 : : end if
1630 : : end do
1631 : :
1632 : 0 : call xmpi_sum(gwr%np_qibz, gwr%kpt_comm%value, ierr)
1633 : :
1634 : : ! Build table to distribute iterations over iq_ibz as qIBZ might be replicated.
1635 [ # # # # : 0 : ABI_ICALLOC(iwork, (gwr%kpt_comm%nproc, gwr%nqibz))
# # # # #
# # # # #
# # # # #
# # # ]
1636 [ # # # # : 0 : ABI_ICALLOC(got, (gwr%kpt_comm%nproc))
# # # # #
# # # # #
# # ]
1637 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
1638 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
1639 : 0 : iwork(gwr%kpt_comm%me + 1, iq_ibz) = 1
1640 : : end do
1641 : 0 : call xmpi_sum(iwork, gwr%kpt_comm%value, ierr)
1642 : :
1643 [ # # # # : 0 : ABI_MALLOC(gwr%itreat_iqibz, (gwr%nqibz))
# # # # #
# # # #
# ]
1644 [ # # ]: 0 : gwr%itreat_iqibz = .False.
1645 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
1646 [ # # # # ]: 0 : ii = imin_loc(got, mask=iwork(:, iq_ibz) /= 0); got(ii) = got(ii) + 1
1647 [ # # ]: 0 : if (ii == gwr%kpt_comm%me + 1) gwr%itreat_iqibz(iq_ibz) = .True.
1648 : : end do
1649 [ # # ]: 0 : ABI_FREE(got)
1650 [ # # ]: 0 : ABI_FREE(iwork)
1651 : :
1652 : : ! Initialize Coulomb interaction.
1653 : : ! Note: MC integration should not be used when computing epsilon, only when integrating in q-space.
1654 : 0 : gw_icutcoul_ = dtset%gw_icutcoul
1655 : :
1656 : 0 : gwr%has_vcgen_sigma = .False.
1657 [ # # ]: 0 : if (any(gw_icutcoul_ == [14, 15, 16])) then
1658 : 0 : gw_icutcoul_ = mod(gw_icutcoul_, 10); gwr%has_vcgen_sigma = .True.
1659 : : end if
1660 : :
1661 : : call gwr%vcgen_eps%init(cryst, ks_ebands%kptrlatt, gwr%nkbz, gwr%nqibz, gwr%nqbz, gwr%qbz, &
1662 : 0 : dtset%gw_rcut, gw_icutcoul_, dtset%vcutgeo, gwr%comm%value)
1663 : :
1664 [ # # ]: 0 : if (gwr%has_vcgen_sigma) then
1665 : : ! Note dtset%gw_icutcoul here.
1666 : : call gwr%vcgen_sigma%init(cryst, ks_ebands%kptrlatt, gwr%nkbz, gwr%nqibz, gwr%nqbz, gwr%qbz, &
1667 : 0 : dtset%gw_rcut, dtset%gw_icutcoul, dtset%vcutgeo, gwr%comm%value)
1668 : : end if
1669 : :
1670 : : ! Now we know the value of g_ngfft. Setup tables for zero-padded FFTs.
1671 : : ! Build descriptors for Green's functions and tchi and setup tables for zero-padded FFTs.
1672 [ # # # # : 0 : ABI_MALLOC(gwr%green_desc_kibz, (gwr%nkibz))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1673 : :
1674 [ # # ]: 0 : do my_iki=1,gwr%my_nkibz
1675 [ # # ]: 0 : ik_ibz = gwr%my_kibz_inds(my_iki); kk_ibz = gwr%kibz(:, ik_ibz)
1676 : 0 : call gwr%green_desc_kibz(ik_ibz)%init(kk_ibz, istwfk1, dtset%ecutwfn, gwr, kin_sorted=.False.)
1677 : : end do
1678 : :
1679 [ # # # # : 0 : ABI_MALLOC(gwr%tchi_desc_qibz, (gwr%nqibz))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1680 [ # # # # : 0 : ABI_ICALLOC(gwr%chinpw_qibz, (gwr%nqibz))
# # # # #
# # # # #
# # ]
1681 : :
1682 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
1683 [ # # ]: 0 : iq_ibz = gwr%my_qibz_inds(my_iqi); qq_ibz = gwr%qibz(:, iq_ibz)
1684 : : ! Note ecuteps instead of ecut. Also, sort the g-vectors by |q+g|^2/2 when q is in the IBZ to facilitate
1685 : : ! the extrapolation of the RPA energy as a function of ecut_chi
1686 : 0 : call gwr%tchi_desc_qibz(iq_ibz)%init(qq_ibz, istwfk1, dtset%ecuteps, gwr, kin_sorted=.True., rot=.True.)
1687 : :
1688 : : ! Compute sqrt(vc(q,G))
1689 : 0 : associate (desc_q => gwr%tchi_desc_qibz(iq_ibz))
1690 : 0 : if (gwr%itreat_iqibz(iq_ibz)) gwr%chinpw_qibz(iq_ibz) = desc_q%npw
1691 : 0 : q_is_gamma = (normv(qq_ibz, gwr%cryst%gmet, "G") < GW_TOLQ0)
1692 : 0 : call desc_q%get_vc_sqrt(qq_ibz, q_is_gamma, gwr, "epsilon", gwr%gtau_comm%value)
1693 [ # # # # ]: 0 : if (gwr%has_vcgen_sigma) then
1694 : 0 : call desc_q%get_vc_sqrt(qq_ibz, q_is_gamma, gwr, "sigma", gwr%gtau_comm%value)
1695 : : end if
1696 : : end associate
1697 : : end do
1698 : :
1699 : : ! Collect npwq on all procs
1700 : 0 : call xmpi_sum(gwr%chinpw_qibz, gwr%comm%value, ierr)
1701 : :
1702 : : ! Init 1D PBLAS grid to block-distribute matrices along columns.
1703 [ # # ]: 0 : call gwr%g_slkproc%init(gwr%g_comm%value, grid_dims=[1, gwr%g_comm%nproc])
1704 [ # # ]: 0 : call gwr%gtau_slkproc%init(gwr%gtau_comm%value, grid_dims=[1, gwr%gtau_comm%nproc])
1705 : :
1706 : : ! ==================================
1707 : : ! Allocate arrays of PBLAS matrices
1708 : : ! ==================================
1709 [ # # # # : 0 : ABI_MALLOC(gwr%gt_kibz, (2, gwr%nkibz, gwr%ntau, gwr%nsppol, gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1710 [ # # # # : 0 : ABI_MALLOC(gwr%tchi_qibz, (gwr%nqibz, gwr%ntau, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1711 [ # # # # : 0 : ABI_MALLOC(gwr%sigc_kibz, (2, gwr%nkibz, gwr%ntau, gwr%nsppol, gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1712 : :
1713 : : ! ====================================
1714 : : ! Create netcdf file to store results
1715 : : ! ====================================
1716 : 0 : gwr%gwrnc_write = .True.
1717 : : !gwr%gwrnc_write = .False.
1718 [ # # ]: 0 : gwr%gwrnc_path = strcat(dtfil%filnam_ds(4), "_GWR.nc")
1719 : :
1720 [ # # # # ]: 0 : if (my_rank == master .and. gwr%gwrnc_write) then
1721 : 0 : call gwr%print(units)
1722 [ # # ]: 0 : NCF_CHECK(nctk_open_create(ncid, gwr%gwrnc_path, xmpi_comm_self))
1723 : : ! Write structure and ebands
1724 [ # # ]: 0 : NCF_CHECK(cryst%ncwrite(ncid))
1725 [ # # ]: 0 : NCF_CHECK(ks_ebands%ncwrite(ncid))
1726 : :
1727 : : ! Add GWR dimensions.
1728 : 0 : smat_bsize1 = gwr%b2gw - gwr%b1gw + 1
1729 [ # # ]: 0 : smat_bsize2 = merge(1, gwr%b2gw - gwr%b1gw + 1, gwr%sig_diago)
1730 : : ncerr = nctk_def_dims(ncid, [ &
1731 : : nctkdim_t("nsppol", gwr%nsppol), &
1732 : : nctkdim_t("nspin_channel", gwr%nsppol*gwr%nsig_ab),&
1733 : : nctkdim_t("nsig_ab", gwr%nsig_ab),&
1734 : : nctkdim_t("ntau", gwr%ntau), &
1735 : : nctkdim_t("nwr", gwr%nwr), &
1736 : : nctkdim_t("chi_mpw", gwr%tchi_mpw), &
1737 : : nctkdim_t("nqibz", gwr%nqibz), &
1738 : : nctkdim_t("nqbz", gwr%nqbz), &
1739 : : nctkdim_t("nkcalc", gwr%nkcalc), &
1740 : : nctkdim_t("max_nbcalc", gwr%max_nbcalc), &
1741 : : nctkdim_t("smat_bsize1", smat_bsize1), &
1742 : : nctkdim_t("smat_bsize2", smat_bsize2) &
1743 [ # # ]: 0 : ], defmode=.True.)
1744 [ # # ]: 0 : NCF_CHECK(ncerr)
1745 : :
1746 : : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
1747 : : "gwr_completed", "sig_diago", "b1gw", "b2gw", "symsigma", "symchi", "scf_iteration" &
1748 [ # # ]: 0 : ])
1749 [ # # ]: 0 : NCF_CHECK(ncerr)
1750 : :
1751 : : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
1752 : : "wr_step", "ecuteps", "ecut", "ecutwfn", "ecutsigx", "gwr_boxcutmin", &
1753 : : "gwr_max_hwtene", "min_transition_energy_eV", "max_transition_energy_eV", &
1754 : : "eratio", "ft_max_err_t2w_cos", "ft_max_err_w2t_cos", "ft_max_err_t2w_sin", &
1755 : : "cosft_duality_error", "regterm" &
1756 [ # # ]: 0 : ])
1757 [ # # ]: 0 : NCF_CHECK(ncerr)
1758 : :
1759 : : ! Define arrays with results.
1760 : : ncerr = nctk_def_arrays(ncid, [ &
1761 : : nctkarr_t("gwr_task", "char", "character_string_length"), &
1762 : : nctkarr_t("tau_mesh", "dp", "ntau"), &
1763 : : nctkarr_t("tau_wgs", "dp", "ntau"), &
1764 : : nctkarr_t("iw_mesh", "dp", "ntau"), &
1765 : : nctkarr_t("iw_wgs", "dp", "ntau"), &
1766 : : nctkarr_t("cosft_wt", "dp", "ntau, ntau"), &
1767 : : nctkarr_t("cosft_tw", "dp", "ntau, ntau"), &
1768 : : nctkarr_t("sinft_wt", "dp", "ntau, ntau"), &
1769 : : !nctkarr_t("ngqpt", "int", "three"), &
1770 : : nctkarr_t("bstart_ks", "int", "nkcalc, nsppol"), &
1771 : : nctkarr_t("bstop_ks", "int", "nkcalc, nsppol"), &
1772 : : nctkarr_t("kcalc", "dp", "three, nkcalc"), &
1773 : : nctkarr_t("kcalc2ibz", "int", "nkcalc, six") &
1774 [ # # ]: 0 : ])
1775 [ # # ]: 0 : NCF_CHECK(ncerr)
1776 : :
1777 : : ! ======================================================
1778 : : ! Write data that do not depend on the (kpt, spin) loop.
1779 : : ! ======================================================
1780 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(ncid))
1781 : : ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
1782 : : "gwr_completed", "sig_diago", "b1gw", "b2gw", "symsigma", "symchi", "scf_iteration"], &
1783 [ # # # # : 0 : [0, merge(1, 0, gwr%sig_diago), gwr%b1gw, gwr%b2gw, gwr%dtset%symsigma, dtset%symchi, gwr%scf_iteration])
# # ]
1784 [ # # ]: 0 : NCF_CHECK(ncerr)
1785 : :
1786 : : ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: &
1787 : : "wr_step", "ecuteps", "ecut", "ecutwfn", "ecutsigx", "gwr_boxcutmin", &
1788 : : "gwr_max_hwtene", "min_transition_energy_eV", "max_transition_energy_eV", &
1789 : : "eratio", "ft_max_err_t2w_cos", "ft_max_err_w2t_cos", "ft_max_err_t2w_sin", &
1790 : : "cosft_duality_error", "regterm"], &
1791 : : [gwr%wr_step, dtset%ecuteps, dtset%ecut, dtset%ecutwfn, dtset%ecutsigx, dtset%gwr_boxcutmin, &
1792 : : dtset%gwr_max_hwtene, gwr%te_min * Ha_eV, gwr%te_max * Ha_eV, gwr%te_max / gwr%te_min, &
1793 : : gwr%ft_max_error(1), gwr%ft_max_error(2), gwr%ft_max_error(3), gwr%cosft_duality_error, regterm &
1794 [ # # # # ]: 0 : ])
1795 [ # # ]: 0 : NCF_CHECK(ncerr)
1796 : :
1797 [ # # # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("gwr_task"), trim(dtset%gwr_task)))
1798 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("tau_mesh"), gwr%tau_mesh))
1799 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("tau_wgs"), gwr%tau_wgs))
1800 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("iw_mesh"), gwr%iw_mesh))
1801 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("iw_wgs"), gwr%iw_wgs))
1802 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("cosft_wt"), gwr%cosft_wt))
1803 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("cosft_tw"), gwr%cosft_tw))
1804 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("sinft_wt"), gwr%sinft_wt))
1805 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("bstart_ks"), gwr%bstart_ks))
1806 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("bstop_ks"), gwr%bstop_ks))
1807 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("kcalc"), gwr%kcalc))
1808 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("kcalc2ibz"), gwr%kcalc2ibz))
1809 [ # # ]: 0 : NCF_CHECK(nf90_close(ncid))
1810 : : end if ! master
1811 : :
1812 : 0 : call cwtime_report(" gwr_init:", cpu, wall, gflops)
1813 [ # # # # : 0 : call timab(1920, 2, tsec)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1814 : :
1815 : : contains
1816 : 0 : integer function vid(vname)
1817 : : character(len=*),intent(in) :: vname
1818 : 0 : vid = nctk_idname(ncid, vname)
1819 : : end function vid
1820 : :
1821 : : end subroutine gwr_init
1822 : : !!***
1823 : :
1824 : : !----------------------------------------------------------------------
1825 : :
1826 : : !!****f* m_gwr/estimate
1827 : : !! NAME
1828 : : !! estimate
1829 : : !!
1830 : : !! FUNCTION
1831 : : !! Estimate memory requirements and the parallel speedup of a given `np_kgts` configuration.
1832 : : !!
1833 : : !! SOURCE
1834 : :
1835 : 0 : type(est_t) pure function estimate(gwr, np_kgts) result(est)
1836 : :
1837 : : !Arguments ------------------------------------
1838 : : class(gwr_t),intent(in) :: gwr
1839 : : integer,intent(in) :: np_kgts(4)
1840 : :
1841 : : !Local variables-------------------------------
1842 : : real(dp) :: np_k, np_g, np_t, np_s, w_k, w_g, w_t, w_s, np_tot
1843 : : ! *************************************************************************
1844 : :
1845 : : ! Use real quantities to avoid integer division
1846 : 0 : np_k = np_kgts(1); np_g = np_kgts(2); np_t = np_kgts(3); np_s = np_kgts(4)
1847 [ # # ]: 0 : np_tot = product(real(np_kgts))
1848 : :
1849 : : ! NB: array dimensioned with nkibz and nqibz do not scale as 1/np_k as we distribute the BZ, IBZ points might be replicated.
1850 : :
1851 : : !!! FIXME HT: Here we should recalculate with nsig_ab
1852 : : ! Resident memory in Mb for G(g,g',+/-tau) and chi(g,g',tau)
1853 : 0 : est%mem_green_gg = two * two * (one*gwr%nspinor*gwr%green_mpw)**2 * two*gwr%ntau * gwr%nkibz * gwr%nsppol * gwp*b2Mb / np_tot
1854 : 0 : est%mem_chi_gg = two * (one*gwr%tchi_mpw)**2 * gwr%ntau * gwr%nqibz * gwp*b2Mb / (np_g * np_t * np_k)
1855 : 0 : est%mem_ugb = two * gwr%green_mpw * gwr%nspinor * gwr%dtset%nband(1) * gwr%nkibz * gwr%nsppol * gwp*b2Mb / np_tot
1856 : :
1857 : : ! Temporary memory allocated inside the tau loops.
1858 : : ! This is the chunck we have to minimize by increasing np_g and/or np_k to avoid going OOM.
1859 : 0 : est%mem_green_rg = two * two * gwr%nspinor**2 * gwr%green_mpw * gwr%g_nfft * gwr%nkbz * gwr%nsppol * gwp*b2Mb / (np_g * np_k)
1860 : 0 : est%mem_chi_rg = two * gwr%tchi_mpw * gwr%g_nfft * gwr%nqbz * gwp*b2Mb / (np_g * np_k)
1861 : :
1862 : 0 : est%mem_total = est%mem_green_gg + est%mem_chi_gg + est%mem_ugb + est%mem_green_rg + est%mem_chi_rg
1863 : :
1864 : : ! Estimate speedup and parallel efficiency using heuristic weights. Note g_nfft instead of green_mpw.
1865 : 0 : w_k = 0.799_dp; w_g = 0.899_dp; w_t = 1.1_dp; w_s = 1.2_dp
1866 : :
1867 : : ! Promote kpt parallelism under particular circumstances.
1868 [ # # # # ]: 0 : if (gwr%nkbz > 4**3) w_k = w_g + tol2 * merge(+1, -5, np_k < 5)
1869 : :
1870 : : est%speedup = speedup(gwr%nkbz, nint(np_k), w_k) * speedup(gwr%g_nfft, nint(np_g), w_g) * &
1871 : 0 : speedup(gwr%ntau, nint(np_t), w_t) * speedup(gwr%nsppol, nint(np_s), w_s)
1872 : 0 : est%efficiency = est%speedup / np_tot
1873 : :
1874 : : contains
1875 : :
1876 : 0 : real(dp) pure function speedup(size, np, weight)
1877 : : ! Expected speedup for a `size` problem and `np` processes
1878 : : integer,intent(in) :: size, np
1879 : : real(dp),intent(in) :: weight
1880 [ # # ]: 0 : if (np == 1) then
1881 : : speedup = one
1882 : : else
1883 [ # # ]: 0 : speedup = (weight*size) / (one* ((size / np) + merge(0, 1, mod(size, np) == 0)))
1884 : : end if
1885 : 0 : end function speedup
1886 : :
1887 : : end function estimate
1888 : : !!***
1889 : :
1890 : : !----------------------------------------------------------------------
1891 : :
1892 : : !!****f* m_gwr/est_print
1893 : : !! NAME
1894 : : !! est_print
1895 : : !!
1896 : : !! FUNCTION
1897 : : !! Print memory estimate.
1898 : : !!
1899 : : !! SOURCE
1900 : :
1901 [ # # ]: 0 : subroutine est_print(est, units)
1902 : :
1903 : : !Arguments ------------------------------------
1904 : : class(est_t), intent(in) :: est
1905 : : integer,intent(in) :: units(:)
1906 : :
1907 : : !Local variables-------------------------------
1908 : : character(len=4),parameter :: fmt = "f8.1"
1909 : : ! *************************************************************************
1910 : :
1911 : 0 : call wrtout(units, "- Resident memory in Mb for G(g,g',+/-tau) and chi(g,g',tau):")
1912 : 0 : call wrtout(units, sjoin("- G_k(g,g,tau): ", ftoa(est%mem_green_gg, fmt=fmt)))
1913 : 0 : call wrtout(units, sjoin("- Chi_q(g,g,tau): ", ftoa(est%mem_chi_gg, fmt=fmt)))
1914 : 0 : call wrtout(units, sjoin("- u_k(g,b): ", ftoa(est%mem_ugb, fmt=fmt)))
1915 : 0 : call wrtout(units, "- Temporary memory allocated inside the tau loops:")
1916 : 0 : call wrtout(units, sjoin("- G_k(r,g): ", ftoa(est%mem_green_rg, fmt=fmt)))
1917 : 0 : call wrtout(units, sjoin("- chi_q(r,g): ", ftoa(est%mem_chi_rg, fmt=fmt)))
1918 : :
1919 : 0 : end subroutine est_print
1920 : : !!***
1921 : :
1922 : : !----------------------------------------------------------------------
1923 : :
1924 : : !!****f* m_gwr/gwr_malloc_free_mats
1925 : : !! NAME
1926 : : !! gwr_malloc_free_mats
1927 : : !!
1928 : : !! FUNCTION
1929 : : !! Allocate/Free PBLAS matrices according to `what` for the set of k/q-points selected by `mask_ibz`.
1930 : : !!
1931 : : !! INPUTS
1932 : : !! mask_ibz
1933 : : !! what
1934 : : !! action
1935 : : !!
1936 : : !! SOURCE
1937 : :
1938 [ # # ]: 0 : subroutine gwr_malloc_free_mats(gwr, mask_ibz, what, action)
1939 : :
1940 : : !Arguments ------------------------------------
1941 : : class(gwr_t), target, intent(inout) :: gwr
1942 : : integer,intent(in) :: mask_ibz(:)
1943 : : character(len=*),intent(in) :: what, action
1944 : :
1945 : : !Local variables-------------------------------
1946 : : integer :: my_is, my_it, ipm, npw, col_bsize, itau, spin, ik_ibz, iq_ibz, iab
1947 : : !integer :: ii, num_pm, ipm_list__(2)
1948 : : type(__slkmat_t), pointer :: mat
1949 : : character(len=500) :: msg !, gpu_action
1950 : : ! *************************************************************************
1951 : :
1952 [ # # ]: 0 : ABI_CHECK(string_in(action, "malloc, free"), sjoin("Invalid action:", action))
1953 : :
1954 : : !gpu_action = "None"; if (gwr%dtset%gpu_option == ABI_GPU_OPENMP) gpu_action = "alloc"
1955 : :
1956 : : !num_pm = 2; ipm_list__ = [1, 2]
1957 : : !if (present(ipm_list)) then
1958 : : ! num_pm = size(ipm_list)
1959 : : ! ABI_CHECK_IRANGE(num_pm, 1, 2, "num_pm not in [1, 2]")
1960 : : ! ipm_list__(1:num_pm) = ipm_list(:)
1961 : : !end if
1962 : :
1963 [ # # ]: 0 : do my_is=1,gwr%my_nspins
1964 : 0 : spin = gwr%my_spins(my_is)
1965 [ # # ]: 0 : do my_it=1,gwr%my_ntau
1966 : 0 : itau = gwr%my_itaus(my_it)
1967 : : ! NB: all the PBLAS matrices are MPI distributed over g' in blocks if action == "malloc"
1968 : :
1969 : 0 : select case (what)
1970 : : case ("green")
1971 : : ! ========================
1972 : : ! Allocate/free G_k(g,g', +-itau)
1973 : : ! ========================
1974 [ # # ]: 0 : ABI_CHECK_IEQ(size(mask_ibz), gwr%nkibz, "wrong mask size")
1975 : :
1976 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
1977 [ # # ]: 0 : if (mask_ibz(ik_ibz) == 0) cycle
1978 : 0 : npw = gwr%green_desc_kibz(ik_ibz)%npw
1979 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
1980 [ # # ]: 0 : do iab=1,gwr%nsig_ab
1981 : 0 : associate (gt => gwr%gt_kibz(:, ik_ibz, itau, spin, iab))
1982 [ # # ]: 0 : do ipm=1,2
1983 [ # # # # ]: 0 : if (action == "malloc") call gt(ipm)%init(npw, npw, gwr%g_slkproc, istwfk1, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
1984 [ # # ]: 0 : if (action == "free") call gt(ipm)%free()
1985 : : end do
1986 : : end associate
1987 : : end do
1988 : : end do
1989 : :
1990 : : case ("tchi", "wc")
1991 : : ! ===========================
1992 : : ! Allocate/free tchi_q(g,g', +itau)
1993 : : ! ===========================
1994 [ # # ]: 0 : ABI_CHECK_IEQ(size(mask_ibz), gwr%nqibz, "wrong mask size")
1995 : :
1996 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
1997 [ # # ]: 0 : if (mask_ibz(iq_ibz) == 0) cycle
1998 : 0 : npw = gwr%tchi_desc_qibz(iq_ibz)%npw
1999 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
2000 [ # # ]: 0 : if (what == "tchi") mat => gwr%tchi_qibz(iq_ibz, itau, spin)
2001 [ # # ]: 0 : if (what == "wc") mat => gwr%wc_qibz(iq_ibz, itau, spin)
2002 [ # # # # ]: 0 : if (action == "malloc") call mat%init(npw, npw, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
2003 [ # # ]: 0 : if (action == "free") call mat%free()
2004 : : end do
2005 : :
2006 : : case ("sigma")
2007 : : ! ================================
2008 : : ! Allocate/free sigmac_kibz(g,g', +- itau)
2009 : : ! ================================
2010 [ # # ]: 0 : ABI_CHECK_IEQ(size(mask_ibz), gwr%nkibz, "wrong mask size")
2011 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
2012 [ # # ]: 0 : if (mask_ibz(ik_ibz) == 0) cycle
2013 : 0 : npw = gwr%tchi_desc_qibz(iq_ibz)%npw
2014 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
2015 [ # # ]: 0 : do iab=1,gwr%nsig_ab
2016 : 0 : associate (sigc => gwr%sigc_kibz(:, ik_ibz, itau, spin, iab))
2017 [ # # ]: 0 : do ipm=1,2
2018 [ # # # # ]: 0 : if (action == "malloc") call sigc(ipm)%init(npw, npw, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
2019 [ # # ]: 0 : if (action == "free") call sigc(ipm)%free()
2020 : : end do
2021 : : end associate
2022 : : end do
2023 : : end do
2024 : :
2025 : : case default
2026 [ # # # # ]: 0 : ABI_ERROR(sjoin("Invalid what:", what))
2027 : : end select
2028 : :
2029 : : end do ! my_it
2030 : : end do ! my_is
2031 : :
2032 : 0 : call wrtout(std_out, "")
2033 [ # # ]: 0 : call gwr%print_mem([std_out])
2034 : :
2035 : 0 : end subroutine gwr_malloc_free_mats
2036 : : !!***
2037 : :
2038 : : !----------------------------------------------------------------------
2039 : :
2040 : : !!****f* m_gwr/gwr_free
2041 : : !! NAME
2042 : : !! gwr_free
2043 : : !!
2044 : : !! FUNCTION
2045 : : !! Free dynamic memory in gwr object.
2046 : : !!
2047 : : !! SOURCE
2048 : :
2049 : 0 : subroutine gwr_free(gwr)
2050 : :
2051 : : !Arguments ------------------------------------
2052 : : class(gwr_t), intent(inout) :: gwr
2053 : : ! *************************************************************************
2054 : :
2055 [ # # ]: 0 : ABI_SFREE(gwr%ks_vbik)
2056 [ # # ]: 0 : ABI_SFREE(gwr%kbz)
2057 [ # # ]: 0 : ABI_SFREE(gwr%kbz2ibz)
2058 [ # # ]: 0 : ABI_SFREE(gwr%kbz2ibz_symrel)
2059 [ # # ]: 0 : ABI_SFREE(gwr%qbz2ibz)
2060 [ # # ]: 0 : ABI_SFREE(gwr%my_kbz_inds)
2061 [ # # ]: 0 : ABI_SFREE(gwr%my_kibz_inds)
2062 [ # # ]: 0 : ABI_SFREE(gwr%my_qbz_inds)
2063 [ # # ]: 0 : ABI_SFREE(gwr%my_qibz_inds)
2064 [ # # ]: 0 : ABI_SFREE(gwr%qbz)
2065 [ # # ]: 0 : ABI_SFREE(gwr%qibz)
2066 [ # # ]: 0 : ABI_SFREE(gwr%wtq)
2067 [ # # ]: 0 : ABI_SFREE(gwr%chi0_head_myw)
2068 [ # # ]: 0 : ABI_SFREE(gwr%chi0_uwing_myw)
2069 [ # # ]: 0 : ABI_SFREE(gwr%chi0_lwing_myw)
2070 [ # # ]: 0 : ABI_SFREE(gwr%my_spins)
2071 [ # # ]: 0 : ABI_SFREE(gwr%my_itaus)
2072 [ # # ]: 0 : ABI_SFREE(gwr%tau_master)
2073 [ # # ]: 0 : ABI_SFREE(gwr%np_kibz)
2074 [ # # ]: 0 : ABI_SFREE(gwr%itreat_ikibz)
2075 [ # # ]: 0 : ABI_SFREE(gwr%np_qibz)
2076 [ # # ]: 0 : ABI_SFREE(gwr%itreat_iqibz)
2077 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%tau_mesh)
2078 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%tau_wgs)
2079 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%iw_mesh)
2080 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%iw_wgs)
2081 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%cosft_tw)
2082 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%cosft_wt)
2083 [ # # ]: 0 : ABI_SFREE_NOCOUNT(gwr%sinft_wt)
2084 [ # # ]: 0 : ABI_SFREE(gwr%kcalc)
2085 [ # # ]: 0 : ABI_SFREE(gwr%bstart_ks)
2086 [ # # ]: 0 : ABI_SFREE(gwr%bstop_ks)
2087 [ # # ]: 0 : ABI_SFREE(gwr%nbcalc_ks)
2088 [ # # ]: 0 : ABI_SFREE(gwr%kcalc2ibz)
2089 [ # # ]: 0 : ABI_SFREE(gwr%sigx_mat)
2090 [ # # ]: 0 : ABI_SFREE(gwr%sigc_iw_mat)
2091 [ # # ]: 0 : ABI_SFREE(gwr%chinpw_qibz)
2092 : :
2093 : 0 : call gwr%ks_gaps%free()
2094 : 0 : call gwr%qp_ebands%free()
2095 : 0 : call gwr%qp_ebands_prev%free()
2096 : 0 : call gwr%kcalc_wfd%free()
2097 : 0 : call gwr%wfk_hdr%free()
2098 : :
2099 : : ! Free descriptors
2100 [ # # ]: 0 : if (allocated(gwr%green_desc_kibz)) then
2101 : 0 : call desc_array_free(gwr%green_desc_kibz)
2102 [ # # # # : 0 : ABI_FREE(gwr%green_desc_kibz)
# # # # #
# # # # #
# # # # #
# # # #
# ]
2103 : : end if
2104 [ # # ]: 0 : if (allocated(gwr%tchi_desc_qibz)) then
2105 : 0 : call desc_array_free(gwr%tchi_desc_qibz)
2106 [ # # # # : 0 : ABI_FREE(gwr%tchi_desc_qibz)
# # # # #
# # # # #
# # # # #
# # # #
# ]
2107 : : end if
2108 : :
2109 : : ! Free PBLAS matrices
2110 [ # # ]: 0 : if (allocated(gwr%gt_kibz)) then
2111 : 0 : call slk_array_free(gwr%gt_kibz)
2112 [ # # # # : 0 : ABI_FREE(gwr%gt_kibz)
# # # # #
# ]
2113 : : end if
2114 [ # # ]: 0 : if (allocated(gwr%tchi_qibz)) then
2115 : 0 : call slk_array_free(gwr%tchi_qibz)
2116 [ # # # # : 0 : ABI_FREE(gwr%tchi_qibz)
# # # # #
# ]
2117 : : end if
2118 [ # # ]: 0 : if (allocated(gwr%wc_qibz)) then
2119 : 0 : call slk_array_free(gwr%wc_qibz)
2120 [ # # # # : 0 : ABI_FREE(gwr%wc_qibz)
# # # # #
# ]
2121 : : end if
2122 [ # # ]: 0 : if (allocated(gwr%sigc_kibz)) then
2123 : 0 : call slk_array_free(gwr%sigc_kibz)
2124 [ # # # # : 0 : ABI_FREE(gwr%sigc_kibz)
# # # # #
# ]
2125 : : end if
2126 : : ! Release the scalapack pressor.
2127 : 0 : call gwr%g_slkproc%free()
2128 : :
2129 [ # # ]: 0 : if (allocated(gwr%ugb)) then
2130 : 0 : call slk_array_free(gwr%ugb)
2131 [ # # # # : 0 : ABI_FREE(gwr%ugb)
# # # # #
# ]
2132 : : end if
2133 : : !if (allocated(gwr%nato_ugb)) then
2134 : : ! call slk_array_free(gwr%nato_ugb)
2135 : : ! ABI_FREE(gwr%nato_ugb)
2136 : : !end if
2137 : 0 : call gwr%gtau_slkproc%free()
2138 : :
2139 : : ! datatypes.
2140 : 0 : call gwr%ks_me%free()
2141 : 0 : call gwr%vcgen_eps%free()
2142 [ # # ]: 0 : if (gwr%has_vcgen_sigma) call gwr%vcgen_sigma%free()
2143 : :
2144 [ # # ]: 0 : if (allocated(gwr%degtab)) then
2145 : 0 : call degtab_array_free(gwr%degtab)
2146 [ # # # # : 0 : ABI_FREE(gwr%degtab)
# # # # #
# # # ]
2147 : : end if
2148 : :
2149 : : ! Free MPI communicators
2150 : 0 : call gwr%spin_comm%free(); call gwr%g_comm%free(); call gwr%tau_comm%free()
2151 : 0 : call gwr%kpt_comm%free(); call gwr%gtau_comm%free(); call gwr%kg_comm%free()
2152 : 0 : call gwr%kgt_comm%free(); call gwr%kts_comm%free(); call gwr%comm%free()
2153 : :
2154 : 0 : end subroutine gwr_free
2155 : : !!***
2156 : :
2157 : : ! Free array of desc_t objects.
2158 [ # # ]: 0 : subroutine desc_array1_free(desc_array1)
2159 : : type(desc_t),intent(inout) :: desc_array1(:)
2160 : : integer :: ii
2161 : :
2162 [ # # ]: 0 : do ii=1,size(desc_array1, dim=1)
2163 : 0 : call desc_array1(ii)%free()
2164 : : end do
2165 : 0 : end subroutine desc_array1_free
2166 : :
2167 : : !----------------------------------------------------------------------
2168 : :
2169 : : !!****f* m_gwr/gwr_load_kcalc_wfd
2170 : : !! NAME
2171 : : !! gwr_load_kcalc_wfd
2172 : : !!
2173 : : !! FUNCTION
2174 : : !! Load the KS states to compute Sigma_nk from the WFK file
2175 : : !!
2176 : : !! INPUTS
2177 : : !! wfk_path=Name of the WFK file.
2178 : : !!
2179 : : !! OUTPUT
2180 : : !! tmp_kstab
2181 : : !!
2182 : : !! SOURCE
2183 : :
2184 : 0 : subroutine gwr_load_kcalc_wfd(gwr, wfk_path, tmp_kstab)
2185 : :
2186 : : !Arguments ------------------------------------
2187 : : class(gwr_t),intent(inout) :: gwr
2188 : : character(len=*),intent(in) :: wfk_path
2189 : : integer,allocatable,intent(out) :: tmp_kstab(:,:,:)
2190 : :
2191 : : !Local variables-------------------------------
2192 : : !scalars
2193 : : integer :: mband, nkibz, nsppol, spin, ik_ibz, ikcalc
2194 : : real(dp) :: cpu, wall, gflops
2195 : : !character(len=5000) :: msg
2196 : : type(ebands_t) :: ks_ebands
2197 : 0 : type(hdr_type) :: wfk_hdr
2198 : : !arrays
2199 : 0 : integer,allocatable :: nband(:,:), wfd_istwfk(:)
2200 : 0 : logical,allocatable :: bks_mask(:,:,:), keep_ur(:,:,:)
2201 : : ! *************************************************************************
2202 : :
2203 : 0 : call cwtime(cpu, wall, gflops, "start")
2204 : :
2205 : : associate (wfd => gwr%kcalc_wfd, dtset => gwr%dtset)
2206 : :
2207 : 0 : ks_ebands = wfk_read_ebands(wfk_path, gwr%comm%value, out_hdr=wfk_hdr)
2208 : 0 : call wfk_hdr%vs_dtset(dtset)
2209 : :
2210 : : ! TODO: Add more consistency checks e.g. nkibz,...
2211 : : !cryst = wfk_hdr%get_crystal()
2212 : : !call cryst%print(header="crystal structure from WFK file")
2213 : :
2214 : 0 : nkibz = ks_ebands%nkpt; nsppol = ks_ebands%nsppol
2215 : :
2216 : : ! Don't take mband from ks_ebands but compute it from gwr%bstop_ks
2217 [ # # # # ]: 0 : mband = maxval(gwr%bstop_ks) !; mband = ks_ebands%mband
2218 : :
2219 : : ! Initialize the wave function descriptor.
2220 : : ! Only wavefunctions for the symmetrical imagine of the k wavevectors
2221 : : ! treated by this MPI rank are stored.
2222 [ # # # # : 0 : ABI_MALLOC(nband, (nkibz, nsppol))
# # # # #
# # # # #
# # ]
2223 [ # # # # : 0 : ABI_MALLOC(bks_mask, (mband, nkibz, nsppol))
# # # # #
# # # # #
# # # # #
# ]
2224 [ # # # # : 0 : ABI_MALLOC(keep_ur, (mband, nkibz, nsppol))
# # # # #
# # # # #
# # ]
2225 [ # # # # : 0 : nband = mband; bks_mask = .False.; keep_ur = .False.
# # # # #
# # # # #
# # ]
2226 : :
2227 [ # # # # : 0 : ABI_ICALLOC(tmp_kstab, (2, nkibz, nsppol))
# # # # #
# # # # #
# # # # #
# # # #
# ]
2228 : :
2229 [ # # ]: 0 : do spin=1,gwr%nsppol
2230 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc ! TODO: Should be spin dependent!
2231 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
2232 : 0 : associate (b1 => gwr%bstart_ks(ikcalc, spin), b2 => gwr%bstop_ks(ikcalc, spin))
2233 [ # # ]: 0 : tmp_kstab(:, ik_ibz, spin) = [b1, b2]
2234 [ # # ]: 0 : bks_mask(b1:b2, ik_ibz, spin) = .True.
2235 : : end associate
2236 : : end do
2237 : : end do
2238 : :
2239 : : ! Impose istwfk = 1 for all k-points.
2240 : : ! wfd_read_wfk will handle a possible conversion if the WFK contains istwfk /= 1.
2241 [ # # # # : 0 : ABI_MALLOC(wfd_istwfk, (nkibz))
# # # # #
# # # ]
2242 [ # # ]: 0 : wfd_istwfk = 1
2243 : :
2244 : : call wfd%init(gwr%cryst, gwr%pawtab, gwr%psps, keep_ur, mband, nband, nkibz, dtset%nsppol, bks_mask, &
2245 : : dtset%nspden, dtset%nspinor, dtset%ecutwfn, dtset%ecutsm, dtset%dilatmx, wfd_istwfk, ks_ebands%kptns, gwr%g_ngfft, &
2246 [ # # # # : 0 : dtset%nloalg, dtset%prtvol, dtset%pawprtvol, gwr%comm%value)
# # # # ]
2247 : :
2248 [ # # ]: 0 : call wfd%print([std_out], header="Wavefunctions for GWR calculation")
2249 : :
2250 [ # # ]: 0 : ABI_FREE(nband)
2251 [ # # ]: 0 : ABI_FREE(keep_ur)
2252 [ # # ]: 0 : ABI_FREE(wfd_istwfk)
2253 [ # # ]: 0 : ABI_FREE(bks_mask)
2254 : :
2255 : 0 : call ks_ebands%free(); call wfk_hdr%free()
2256 : :
2257 : : ! Read KS wavefunctions.
2258 : 0 : call wfd%read_wfk(wfk_path, iomode_from_fname(wfk_path))
2259 : : end associate
2260 : :
2261 : 0 : call cwtime_report(" gwr_load_kcalc_from_wfk:", cpu, wall, gflops)
2262 : 0 : call pstat_proc%print(_PSTAT_ARGS_)
2263 : :
2264 [ # # # # : 0 : end subroutine gwr_load_kcalc_wfd
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
2265 : : !!***
2266 : :
2267 : : !----------------------------------------------------------------------
2268 : :
2269 : : !!****f* m_gwr/gwr_read_ugb_from_wfk
2270 : : !! NAME
2271 : : !! gwr_read_ugb_from_wfk
2272 : : !!
2273 : : !! FUNCTION
2274 : : !! Read wavefunctions from the WFK file `wfk_path` and store them in gwr%ugb (MPI distributed).
2275 : : !!
2276 : : !! SOURCE
2277 : :
2278 : 0 : subroutine gwr_read_ugb_from_wfk(gwr, wfk_path)
2279 : :
2280 : : !Arguments ------------------------------------
2281 : : class(gwr_t),target,intent(inout) :: gwr
2282 : : character(len=*),intent(in) :: wfk_path
2283 : :
2284 : : !Local variables-------------------------------
2285 : : !scalars
2286 : : integer,parameter :: formeig0 = 0, master = 0
2287 : : integer :: mband, min_nband, nkibz, nsppol, my_is, my_iki, spin, ik_ibz, ierr, bcast_comm, color
2288 : : integer :: npw_k, mpw_disk, istwf_k, il_b, ib, band, iloc, cg_spad, gw_spad
2289 : : integer :: nbsum, npwsp, npw_k_disk, npwsp_disk, bstart, bstop, band_step, nb, nmiss, ig, igw, spinor, icg
2290 : : logical :: print_time
2291 : : real(dp) :: cpu, wall, gflops, cpu_green, wall_green, gflops_green
2292 : : complex(gwp) :: cdum
2293 : : character(len=5000) :: msg
2294 : : logical :: have_band, need_block_ks, io_in_kcomm, cut_ug
2295 : : type(ebands_t) :: wfk_ebands
2296 [ # # ]: 0 : type(wfk_t) :: wfk
2297 : : type(dataset_type),pointer :: dtset
2298 : : type(xcomm_t), pointer :: io_comm
2299 : : !arrays
2300 : : integer :: units(2)
2301 : 0 : integer,allocatable :: kg_k_disk(:,:), gf2wfd(:)
2302 : : !logical,allocatable :: bmask(:)
2303 : : real(dp) :: kk_ibz(3), tsec(2)
2304 : 0 : real(dp),target,allocatable :: cg_work(:,:,:)
2305 : 0 : real(dp),contiguous, pointer :: cg_k(:,:)
2306 : : ! *************************************************************************
2307 : :
2308 [ # # ]: 0 : units = [std_out, ab_out]
2309 : 0 : call cwtime(cpu, wall, gflops, "start")
2310 : 0 : call timab(1921, 1, tsec)
2311 : :
2312 : 0 : dtset => gwr%dtset
2313 : 0 : wfk_ebands = wfk_read_ebands(wfk_path, gwr%comm%value, out_hdr=gwr%wfk_hdr)
2314 : 0 : call gwr%wfk_hdr%vs_dtset(dtset)
2315 : :
2316 : : ! TODO: Add more consistency checks e.g. nkibz,...
2317 : : !cryst = gwr%wfk_hdr%get_crystal()
2318 : : !call cryst%print(header="crystal structure from WFK file")
2319 : :
2320 : : ! TODO: Could read the wavefunctions twice and use ecutwfc for sigma_c and ecut for sigma_x.
2321 [ # # ]: 0 : nkibz = wfk_ebands%nkpt; nsppol = wfk_ebands%nsppol; mband = wfk_ebands%mband; min_nband = minval(wfk_ebands%nband)
2322 : :
2323 : 0 : nbsum = dtset%nband(1)
2324 [ # # ]: 0 : if (nbsum > min_nband) then
2325 : 0 : ABI_ERROR(sjoin("WFK file contains", itoa(min_nband), "states while you're asking for:", itoa(nbsum)))
2326 : 0 : nbsum = min_nband
2327 : : end if
2328 : 0 : call wfk_ebands%free()
2329 : :
2330 : 0 : cut_ug = (abs(gwr%dtset%ecut - gwr%dtset%ecutwfn) > tol3)
2331 [ # # ]: 0 : if (cut_ug) then
2332 : 0 : call wrtout(units, sjoin(" Cutting u(g) as ecutwfn:", ftoa(gwr%dtset%ecutwfn), " < ecut: ", ftoa(gwr%dtset%ecut)))
2333 : : end if
2334 : :
2335 : : ! ==============================================
2336 : : ! Build Green's functions in g-space for given k
2337 : : ! ==============================================
2338 : :
2339 : : ! for tau > 0:
2340 : : !
2341 : : ! G_k(r,r',itau) = i \sum_b^{occ} psi_b(r) \psi_b^*(r') exp(e_b tau)
2342 : : !
2343 : : ! for tau < 0:
2344 : : !
2345 : : ! G_k(r,r',itau) = -i \sum_b^{empty} psi_b(r) \psi_b^*(r') exp(e_b tau)
2346 : : !
2347 : : ! NB: G_k is constructed for k in the IBZ, then we rotate the k-point to obtain G_k in the BZ.
2348 : : !
2349 : : ! TODO:
2350 : : ! 1) Make sure that gvec in gwr and wfd agree with each other.
2351 : : ! 2) May implement trick used in gwst to add empty states approximated with LC of PWs.
2352 : :
2353 : : ! Select occupied or empty G.
2354 : : ! if (eig_nk < -tol6) then
2355 : : ! !ipm = 1
2356 : : ! !gt_cfact = j_dpc * exp(gwr%tau_mesh(itau) * eig_nk)
2357 : : ! ! Vasp convention
2358 : : ! ipm = 2
2359 : : ! gt_cfact = exp(gwr%tau_mesh(itau) * eig_nk)
2360 : : ! else if (eig_nk > tol6) then
2361 : : ! !ipm = 2
2362 : : ! !gt_cfact = -j_dpc * exp(-gwr%tau_mesh(itau) * eig_nk)
2363 : : ! ! Vasp convention
2364 : : ! ipm = 1
2365 : : ! gt_cfact = -exp(-gwr%tau_mesh(itau) * eig_nk)
2366 : : ! else
2367 : : ! ABI_WARNING("Metallic system of semiconductor with Fermi level inside bands!!!!")
2368 : : ! end if
2369 : :
2370 : 0 : call wrtout(std_out, sjoin(" Reading KS states with nbsum:", itoa(nbsum), "..."), do_flush=.True.)
2371 : :
2372 : : ! Init set of (npwsp, nbsum) PBLAS matrix distributed within the g_comm communicator.
2373 : : ! and distribute it over bands so that each proc reads a subset of bands in read_band_block
2374 : : ! Note size_blocs below that corresponds to a round-robin distribution along the band axis.
2375 : :
2376 [ # # # # : 0 : ABI_MALLOC(gwr%ugb, (gwr%nkibz, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
2377 : 0 : gwr%ugb_nband = nbsum
2378 : :
2379 [ # # ]: 0 : do my_is=1,gwr%my_nspins
2380 : 0 : spin = gwr%my_spins(my_is)
2381 [ # # ]: 0 : do my_iki=1,gwr%my_nkibz
2382 : 0 : ik_ibz = gwr%my_kibz_inds(my_iki)
2383 : 0 : npw_k = gwr%green_desc_kibz(ik_ibz)%npw; npwsp = npw_k * gwr%nspinor
2384 : 0 : call gwr%ugb(ik_ibz, spin)%init(npwsp, gwr%ugb_nband, gwr%g_slkproc, istwfk1, size_blocs=[-1, 1])
2385 : : end do
2386 : : end do
2387 [ # # ]: 0 : call gwr%print_mem([std_out])
2388 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
2389 : :
2390 [ # # ]: 0 : mpw_disk = maxval(gwr%wfk_hdr%npwarr)
2391 [ # # # # : 0 : ABI_MALLOC(kg_k_disk, (3, mpw_disk))
# # # # #
# # # ]
2392 : :
2393 : : ! Master reads and broadcasts. Much faster on lumi
2394 : 0 : call wrtout(std_out, " Using IO version based on master reads and brodcasts ...")
2395 : 0 : io_comm => gwr%comm; io_in_kcomm = .False.
2396 : 0 : io_comm => gwr%kpt_comm; io_in_kcomm = .True.
2397 : :
2398 [ # # ]: 0 : if (io_comm%me == master) then
2399 : 0 : call wfk%open_read(wfk_path, formeig0, iomode_from_fname(wfk_path), get_unit(), xmpi_comm_self)
2400 : : end if
2401 : :
2402 : : ! TODO This to maximize the size of cg_work and decrease number of IO operations.
2403 : : !min_mem_mb = pstat_proc%pstat_min_mem_mb_per_proc(gwr%comm)
2404 : :
2405 [ # # ]: 0 : do spin=1,gwr%nsppol
2406 [ # # # # : 0 : if (io_in_kcomm .and. .not. any(gwr%my_spins == spin)) cycle
# # ]
2407 : :
2408 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
2409 [ # # # # : 0 : print_time = gwr%comm%me == 0 .and. (ik_ibz < LOG_MODK .or. mod(ik_ibz, LOG_MODK) == 0)
# # ]
2410 : 0 : if (print_time) call cwtime(cpu_green, wall_green, gflops_green, "start")
2411 : 0 : kk_ibz = gwr%kibz(:, ik_ibz)
2412 : 0 : npw_k = gwr%green_desc_kibz(ik_ibz)%npw
2413 : 0 : npw_k_disk = gwr%wfk_hdr%npwarr(ik_ibz); istwf_k = gwr%wfk_hdr%istwfk(ik_ibz); npwsp_disk = npw_k_disk * gwr%nspinor
2414 : :
2415 [ # # ]: 0 : ABI_CHECK_IEQ(istwf_k, 1, "istwfk_k should be 1")
2416 : : ! See m_wfd for calls to convert to istwfk 1
2417 : : !change_gsphere = istwfk_disk /= wfd%istwfk(ik_ibz)
2418 : :
2419 : : ! Create communicator with master and all procs requiring this (k,s) block (color == 1)
2420 [ # # # # : 0 : need_block_ks = any(gwr%my_spins == spin) .and. any(gwr%my_kibz_inds == ik_ibz)
# # # # ]
2421 [ # # # # ]: 0 : color = merge(1, 0, (need_block_ks .or. io_comm%me == master))
2422 : 0 : call xmpi_comm_split(io_comm%value, color, io_comm%me, bcast_comm, ierr)
2423 : :
2424 : : ! TODO: Optimize this part
2425 : : ! Find band_step that gives good compromise between memory and efficiency.
2426 : : !band_step = memb_limited_step(1, nbsum, 2*npwsp_disk, xmpi_bsize_dp, min_mem_mb * 0.8_dp)
2427 : 0 : band_step = 200
2428 : :
2429 [ # # ]: 0 : do bstart=1, nbsum, band_step
2430 : 0 : bstop = min(bstart + band_step - 1, nbsum); nb = bstop - bstart + 1
2431 : :
2432 [ # # # # : 0 : ABI_MALLOC(cg_work, (2, npwsp_disk, nb)) ! This array is always in double precision.
# # # # #
# # # # #
# # # # ]
2433 [ # # ]: 0 : if (io_comm%me == master) then
2434 [ # # ]: 0 : call c_f_pointer(c_loc(cg_work), cg_k, shape=[2, npwsp_disk * nb])
2435 [ # # ]: 0 : call wfk%read_band_block([bstart, bstop], ik_ibz, spin, xmpio_single, kg_k=kg_k_disk, cg_k=cg_k)
2436 : : end if
2437 : :
2438 [ # # ]: 0 : if (color == 1) then
2439 : 0 : call xmpi_bcast(kg_k_disk, master, bcast_comm, ierr)
2440 : 0 : call xmpi_bcast(cg_work, master, bcast_comm, ierr)
2441 : : endif
2442 : :
2443 : : ! Copy my portion of cg_work to buffer_cplx (here we have dp --> sp conversion).
2444 [ # # ]: 0 : if (need_block_ks) then
2445 : : associate (ugb => gwr%ugb(ik_ibz, spin), desc_k => gwr%green_desc_kibz(ik_ibz))
2446 : :
2447 : : ! Table with the correspondence btw the k-centered sphere of the WFK file
2448 : : ! and the one used in wfd (possibly smaller due to ecutwfn).
2449 : 0 : if (cut_ug .and. bstart == 1) then
2450 [ # # # # : 0 : ABI_MALLOC(gf2wfd, (npw_k_disk))
# # # # #
# # # #
# ]
2451 : 0 : call kg_map(npw_k, desc_k%gvec, npw_k_disk, kg_k_disk, gf2wfd, nmiss)
2452 : : end if
2453 : :
2454 [ # # # # ]: 0 : do band=bstart, bstop
2455 : 0 : ib = band - bstart + 1
2456 [ # # ]: 0 : call ugb%glob2loc(1, band, iloc, il_b, have_band); if (.not. have_band) cycle
2457 : :
2458 [ # # ]: 0 : if (.not. cut_ug) then
2459 [ # # ]: 0 : if (band == bstart) then
2460 [ # # # # : 0 : ABI_CHECK(all(kg_k_disk(:,1:npw_k_disk) == desc_k%gvec), "kg_k_disk != desc_k%gvec")
# # # # ]
2461 : : end if
2462 [ # # ]: 0 : ugb%buffer_cplx(:, il_b) = cmplx(cg_work(1,:,ib), cg_work(2,:,ib), kind=gwp)
2463 : :
2464 : : else
2465 : : !ugb%buffer_cplx(:, il_b) = zero
2466 [ # # ]: 0 : do spinor=1,gwr%nspinor
2467 : 0 : cg_spad = (spinor-1) * npw_k_disk
2468 : 0 : gw_spad = (spinor-1) * npw_k
2469 [ # # ]: 0 : do ig=1,npw_k_disk
2470 : 0 : icg = ig + cg_spad
2471 : 0 : igw = gf2wfd(ig) + gw_spad
2472 [ # # ]: 0 : if (gf2wfd(ig) /= 0) then
2473 : 0 : ugb%buffer_cplx(igw, il_b) = cmplx(cg_work(1,icg,ib), cg_work(2,icg,ib), kind=gwp)
2474 : : end if
2475 : : end do
2476 : : end do ! spinor
2477 : :
2478 : : ! Re-normalize wavefunctions..
2479 : 0 : cdum = xdotc(npw_k*gwr%nspinor, ugb%buffer_cplx(:,il_b), 1, ugb%buffer_cplx(:,il_b), 1)
2480 [ # # ]: 0 : if (istwf_k > 1) then
2481 : 0 : cdum = two * DBLE(cdum)
2482 : : associate (ug1 => ugb%buffer_cplx(1,il_b))
2483 [ # # ]: 0 : if (istwf_k == 2) cdum = cdum - conjg(ug1) * ug1
2484 : : end associate
2485 : : end if
2486 : 0 : cdum = one / sqrt(cdum)
2487 : 0 : call xscal(npw_k*gwr%nspinor, cdum, ugb%buffer_cplx(:,il_b), 1)
2488 : : !print *, "new norm:", xdotc(npw_k*gwr%nspinor, ugb%buffer_cplx(:,il_b), 1, ugb%buffer_cplx(:,il_b), 1)
2489 : : end if
2490 : :
2491 : : end do ! band
2492 : : end associate
2493 : : end if
2494 : :
2495 [ # # # # ]: 0 : ABI_FREE(cg_work)
2496 : : end do ! bstart
2497 : :
2498 [ # # ]: 0 : ABI_SFREE(gf2wfd)
2499 : 0 : call xmpi_comm_free(bcast_comm)
2500 : :
2501 [ # # ]: 0 : if (print_time) then
2502 : 0 : write(msg,'(4x,2(a,i0),a)')" Read ugb_k: ik_ibz [", ik_ibz, "/", gwr%nkibz, "]"
2503 [ # # ]: 0 : call cwtime_report(msg, cpu_green, wall_green, gflops_green); if (ik_ibz == LOG_MODK) call wrtout(std_out, " ...")
2504 : : end if
2505 : : end do ! ik_ibz
2506 : : end do ! spin
2507 [ # # ]: 0 : if (io_comm%me == master) call wfk%close()
2508 : :
2509 [ # # ]: 0 : ABI_FREE(kg_k_disk)
2510 [ # # ]: 0 : call gwr%print_mem([std_out])
2511 : :
2512 : 0 : call cwtime_report(" gwr_read_ugb_from_wfk:", cpu, wall, gflops)
2513 : 0 : call timab(1921, 2, tsec)
2514 : :
2515 [ # # # # : 0 : end subroutine gwr_read_ugb_from_wfk
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
2516 : : !!***
2517 : :
2518 : : !----------------------------------------------------------------------
2519 : :
2520 : : !!****f* m_gwr/gwr_build_green
2521 : : !! NAME
2522 : : !! gwr_build_green
2523 : : !!
2524 : : !! FUNCTION
2525 : : !! Build Green's functions in imaginary time from the gwr%ugb matrices stored in memory.
2526 : : !! Store only G_k for the IBZ k-points treated by this MPI proc.
2527 : : !!
2528 : : !! INPUTS
2529 : : !! free_ugb: True if the gwr%ugb wavefunctions should be deallocated before returning.
2530 : : !!
2531 : : !! SOURCE
2532 : :
2533 : 0 : subroutine gwr_build_green(gwr, free_ugb)
2534 : :
2535 : : !Arguments ------------------------------------
2536 : : class(gwr_t),target,intent(inout) :: gwr
2537 : : logical,intent(in) :: free_ugb
2538 : :
2539 : : !Local variables-------------------------------
2540 : : !scalars
2541 : : integer :: my_is, my_iki, spin, ik_ibz, band, itau, ipm, il_b, npw, isgn, my_it, nbsum !, ig_glob, ig_loc, jg_loc, nb_occ
2542 : : integer :: ii, icomp
2543 : : real(dp), parameter :: eratio = 0.95_dp
2544 : : real(dp) :: eig_nk, cpu, wall, gflops, cpu_k, wall_k, gflops_k !, f_nk
2545 : : logical :: print_time, compute_svd
2546 : : character(len=500) :: msg
2547 : : real(dp) :: gt_rfact, s2_sum, s2_sum_all
2548 [ # # # # : 0 : type(__slkmat_t), target :: work_gb(gwr%nspinor), green, u_mat, vt_mat
# # # # #
# # # # #
# # # # #
# # # ]
2549 : 0 : real(gwp),allocatable :: s_vals(:)
2550 : : !arrays
2551 : 0 : integer :: mask_kibz(gwr%nkibz), units(2) !, ija(2), ijb(2)
2552 : : !integer :: occ_idx(gwr%ks_ebands%nkpt, gwr%ks_ebands%nsppol)
2553 : : real(dp) :: tsec(2) , kk_ibz(3) !, kg(3)
2554 : 0 : real(dp),contiguous, pointer :: qp_eig(:,:,:), qp_occ(:,:,:)
2555 : : integer :: iab, iiab, jiab, ispinor !,i, j
2556 : : integer, parameter :: spinor_idxs(2, 4) = RESHAPE([1, 1, 2, 2, 1, 2, 2, 1], [2, 4])
2557 : : ! *************************************************************************
2558 : :
2559 : 0 : call cwtime(cpu, wall, gflops, "start")
2560 : 0 : call timab(1922, 1, tsec)
2561 [ # # ]: 0 : units = [std_out, ab_out]
2562 : 0 : nbsum = gwr%dtset%nband(1)
2563 : :
2564 : : ! Use KS or QP energies depending on the iteration state.
2565 [ # # ]: 0 : if (gwr%scf_iteration == 1) then
2566 : : call wrtout(units, " Building Green's functions from KS orbitals and KS energies...", &
2567 : 0 : pre_newlines=2, newlines=1, do_flush=.True.)
2568 : 0 : qp_eig => gwr%ks_ebands%eig; qp_occ => gwr%ks_ebands%occ
2569 [ # # ]: 0 : msg = sjoin("Fermi energy is not set to zero! fermie:", ftoa(gwr%ks_ebands%fermie))
2570 [ # # ]: 0 : ABI_CHECK(abs(gwr%ks_ebands%fermie) < tol12, msg)
2571 : :
2572 : : !occ_idx = gwr%ks_ebands%get_occupied()
2573 : :
2574 : : ! Allocate my Green's functions in IBZ if this is the first iteration.
2575 [ # # # # ]: 0 : mask_kibz = 0; mask_kibz(gwr%my_kibz_inds(:)) = 1
2576 : 0 : call gwr%malloc_free_mats(mask_kibz, "green", "malloc")
2577 : :
2578 : : else
2579 : : call wrtout(units, " Building Green's functions from KS orbitals and QP energies...", &
2580 : 0 : pre_newlines=2, newlines=1, do_flush=.True.)
2581 : 0 : qp_eig => gwr%qp_ebands%eig; qp_occ => gwr%qp_ebands%occ
2582 [ # # ]: 0 : msg = sjoin("Fermi energy is not set to zero! fermie:", ftoa(gwr%qp_ebands%fermie))
2583 [ # # ]: 0 : ABI_CHECK(abs(gwr%qp_ebands%fermie) < tol12, msg)
2584 : :
2585 : : !occ_idx = gwr%qp_ebands%get_occupied()
2586 : : end if
2587 : :
2588 [ # # ]: 0 : ABI_CHECK(allocated(gwr%ugb), "gwr%ugb array should be allocated!")
2589 : 0 : compute_svd = .False.
2590 : : !compute_svd = .True.
2591 : :
2592 [ # # ]: 0 : do my_is=1,gwr%my_nspins
2593 : 0 : spin = gwr%my_spins(my_is)
2594 : : ! Loop over my k-points in the IBZ
2595 [ # # ]: 0 : do my_iki=1,gwr%my_nkibz
2596 [ # # # # : 0 : print_time = gwr%comm%me == 0 .and. (my_iki < LOG_MODK .or. mod(my_iki, LOG_MODK) == 0)
# # ]
2597 : 0 : if (print_time) call cwtime(cpu_k, wall_k, gflops_k, "start")
2598 : 0 : ik_ibz = gwr%my_kibz_inds(my_iki)
2599 : 0 : kk_ibz = gwr%kibz(:, ik_ibz)
2600 : 0 : associate (ugb_ks => gwr%ugb(ik_ibz, spin), desc_k => gwr%green_desc_kibz(ik_ibz))
2601 : 0 : npw = desc_k%npw
2602 : : ! Init output of pzgemm in g-communicator
2603 : 0 : call green%init(npw, npw, gwr%g_slkproc, istwfk1) ! size_blocs=[-1, col_bsize])
2604 : :
2605 : : ! Loop over my_ntau as pzgemm is MPI-parallelized inside g_comm.
2606 [ # # ]: 0 : do my_it=1,gwr%my_ntau
2607 : 0 : itau = gwr%my_itaus(my_it)
2608 [ # # ]: 0 : do ipm=1,2
2609 [ # # ]: 0 : do ispinor = 1, gwr%nspinor
2610 [ # # ]: 0 : call ugb_ks%cut(npw, ugb_ks%size_global(2), work_gb(ispinor), ija=[(ispinor - 1)*npw + 1, 1])
2611 : :
2612 : : !work_gb(my_is)%buffer_cplx = gwr %ugb(ik_ibz, spin)%buffer_cplx
2613 : :
2614 : : !call ugb_ks%change_size_blocs(work_gb, size_blocs=, processor=)
2615 : : !call work_gb%copy(green, empty=.True.)
2616 : :
2617 : : ! Loop over my_ntau as pzgemm is MPI-parallelized inside g_comm.
2618 : : ! do my_it=1,gwr%my_ntau
2619 : : ! itau = gwr%my_itaus(my_it)
2620 : : ! do ipm=1,2
2621 : : ! Multiply my columns by exponentials in imaginary time.
2622 : : ! work_gb%buffer_cplx = ugb_ks%buffer_cplx
2623 : :
2624 : : !!!$OMP PARALLEL DO PRIVATE(band, f_nk, eig_nk, gt_rfact)
2625 : : !$OMP PARALLEL DO PRIVATE(band, eig_nk, gt_rfact)
2626 [ # # ]: 0 : do il_b = 1, work_gb(ispinor)%size_local(2)
2627 : 0 : band = work_gb(ispinor)%loc2gcol(il_b)
2628 : : !f_nk = qp_occ(band, ik_ibz, spin)
2629 : 0 : eig_nk = qp_eig(band, ik_ibz, spin)
2630 : 0 : gt_rfact = zero
2631 [ # # ]: 0 : if (ipm == 2) then
2632 [ # # ]: 0 : if (eig_nk < -tol6) gt_rfact = exp(gwr%tau_mesh(itau) * eig_nk)
2633 : : else
2634 [ # # ]: 0 : if (eig_nk > tol6) gt_rfact = exp(-gwr%tau_mesh(itau) * eig_nk)
2635 : : end if
2636 : :
2637 : : !work_gb%buffer_cplx(:,il_b) = work_gb%buffer_cplx(:,il_b) * sqrt(gt_rfact)
2638 : 0 : call xscal(npw, real(sqrt(gt_rfact), kind=gwp), work_gb(ispinor)%buffer_cplx(:, il_b), 1)
2639 : : end do ! il_b
2640 : : end do !ispinor
2641 : : ! end do ! ipm
2642 : : ! end do ! itau
2643 : :
2644 : : ! Now build G(g,g',ipm) with PZGEMM.
2645 [ # # ]: 0 : isgn = merge(1, -1, ipm == 2)
2646 [ # # ]: 0 : do iab = 1, gwr%nsig_ab
2647 : 0 : iiab = spinor_idxs(1, iab)
2648 : 0 : jiab = spinor_idxs(2, iab)
2649 : :
2650 : : ! TODO: optimize this part
2651 : : ! This wont' work for metals
2652 : : !nb_occ = occ_idx(ik_ibz, spin)
2653 : : ! nb_occ = -1
2654 : : !if (ipm == 1) then
2655 : : ! ija = [1, nb_occ]; ijb = ija
2656 : : !else
2657 : : ! ija = [nb_occ+1, gwr%ugb_nband]; ijb = ija
2658 : : !end if
2659 : 0 : call slk_pgemm("N", "C", work_gb(iiab), isgn*cone_gw, work_gb(jiab), czero_gw, green)
2660 : :
2661 : : ! SVD. NB: green matrix in destroyed in output.
2662 : : if (compute_svd) then
2663 : : call green%svd("N", "N", u_mat, s_vals, vt_mat)
2664 : : s2_sum_all = sum(s_vals**2)
2665 : : icomp = -1
2666 : : do ii=1,size(s_vals)
2667 : : s2_sum = sum(s_vals(1:ii)**2)
2668 : : if (icomp == -1 .and. s2_sum / s2_sum_all > eratio) icomp = ii
2669 : : !write(std_out, *)ii, s_vals(ii), 100 * s2_sum / s2_sum_all
2670 : : end do
2671 : : write(std_out, "(a,i0,2a,3(a,1x,i0))") &
2672 : : "SVD: For ik_ibz: ", ik_ibz, ", kpt: ", trim(ktoa(kk_ibz)), ", itau: ", itau, ", ipm: ", ipm, ", spin: ", spin
2673 : : write(std_out, "(a,i0,2(a,f5.2),a,i0)") &
2674 : : "SVD: Need ", icomp, " vectors with frac: ", (100.0_dp * icomp) / size(s_vals), &
2675 : : "% to reach eratio: ", eratio, ", G matrix size: ", size(s_vals)
2676 : : ABI_FREE(s_vals)
2677 : : end if
2678 : :
2679 : : ! Redistribute data.
2680 : 0 : call gwr%gt_kibz(ipm, ik_ibz, itau, spin, iab)%take_from(green)
2681 : : end do ! iab
2682 : 0 : call slk_array_free(work_gb)
2683 : :
2684 : : end do ! ipm
2685 : : end do ! my_it
2686 : :
2687 : 0 : call green%free()
2688 : : ! Free wavefunctions if asked for.
2689 [ # # ]: 0 : if (free_ugb) call ugb_ks%free()
2690 : :
2691 [ # # ]: 0 : if (print_time) then
2692 : 0 : write(msg,'(4x,3(a,i0),a)')"G_ikbz [", my_iki, "/", gwr%my_nkibz, "] (tot: ", gwr%nkibz, ")"
2693 [ # # ]: 0 : call cwtime_report(msg, cpu_k, wall_k, gflops_k); if (my_iki == LOG_MODK) call wrtout(std_out, " ...")
2694 : : end if
2695 : : end associate
2696 : : end do ! my_iki
2697 : : end do ! my_is
2698 : :
2699 [ # # ]: 0 : if (gwr%dtset%prtvol > 0) call gwr%print_trace(units, "gt_kibz")
2700 [ # # ]: 0 : call gwr%print_mem([std_out])
2701 : :
2702 : 0 : call cwtime_report(" gwr_build_green:", cpu, wall, gflops)
2703 : 0 : call timab(1922, 2, tsec)
2704 : :
2705 : : !if (compute_svd) stop "compute_svd"
2706 : :
2707 [ # # # # ]: 0 : end subroutine gwr_build_green
2708 : : !!***
2709 : :
2710 : : !----------------------------------------------------------------------
2711 : :
2712 : : !!****f* m_gwr/gwr_gk_to_scbox
2713 : : !! NAME
2714 : : !! gwr_gk_to_scbox
2715 : : !!
2716 : : !! FUNCTION
2717 : : !! Insert G_k(g',r) in the FFT box of the supercell: k+g' index.
2718 : : !!
2719 : : !! INPUTS
2720 : : !! select_my_kbz: Mask used to select a subset of gwr%my_nkbz k-points.
2721 : : !!
2722 : : !! OUTPUT
2723 : : !!
2724 : : !! SOURCE
2725 : :
2726 [ # # ]: 0 : subroutine gwr_gk_to_scbox(gwr, sc_ngfft, select_my_kbz, desc_mykbz, green_scgvec, my_ir, ndat, gt_gpr, gt_scbox, gt_scbox_win)
2727 : :
2728 : : !Arguments ------------------------------------
2729 : : class(gwr_t),target,intent(in) :: gwr
2730 : : integer,intent(in) :: sc_ngfft(18)
2731 : : logical,intent(in) :: select_my_kbz(gwr%my_nkbz)
2732 : : integer,intent(out) :: green_scgvec(3, gwr%green_mpw)
2733 : : type(desc_t),intent(inout) :: desc_mykbz(gwr%my_nkbz)
2734 : : type(__slkmat_t),intent(in) :: gt_gpr(2, gwr%my_nkbz)
2735 : : integer,intent(in) :: my_ir, ndat
2736 : : complex(gwp), intent(out) :: gt_scbox(product(sc_ngfft(4:6)), gwr%sc_batch_size, 2)
2737 : : integer,optional,intent(inout) :: gt_scbox_win
2738 : :
2739 : : !Local variables-------------------------------
2740 : 0 : integer :: my_ikf, ik_bz, ipm, gg(3), idat, iepoch, ii, idat_list(gwr%kpt_comm%nproc), ierr ! ig,
2741 : : !real(dp) :: tsec(2) !, cpu, wall, gflops
2742 : : ! *************************************************************************
2743 : :
2744 : : !call cwtime(cpu, wall, gflops, "start")
2745 : : !call timab(1929, 1, tsec)
2746 : :
2747 : : ! Take the union of (k,g') for k in the BZ.
2748 : : ! Note gwr%ngkpt instead of gwr%ngqpt.
2749 [ # # ]: 0 : if (.not. present(gt_scbox_win)) then
2750 : : ! Zero output array.
2751 [ # # # # : 0 : gt_scbox = czero_gw
# # ]
2752 : :
2753 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
2754 : : if (.not. select_my_kbz(my_ikf)) continue
2755 : 0 : ik_bz = gwr%my_kbz_inds(my_ikf); gg = nint(gwr%kbz(:,ik_bz) * gwr%ngkpt)
2756 [ # # ]: 0 : do ipm=1,2
2757 : : call desc_mykbz(my_ikf)%to_scbox(gwr%kbz(:, ik_bz), gwr%ngkpt, sc_ngfft, ndat, &
2758 : 0 : gt_gpr(ipm, my_ikf)%buffer_cplx(1,my_ir), gt_scbox(:,:,ipm))
2759 : : end do
2760 : : end do ! my_ikf
2761 : :
2762 : : else
2763 : : ! Each MPI proc operates on a different idat vector at each epoch
2764 [ # # # # : 0 : idat_list = cshift([(ii, ii=1,gwr%kpt_comm%nproc)], shift=-gwr%kpt_comm%me)
# # # # ]
2765 : :
2766 [ # # ]: 0 : do iepoch=1,gwr%kpt_comm%nproc
2767 : 0 : call xmpi_win_fence(XMPI_MODE_NOPRECEDE, gt_scbox_win, ierr) ! Start the RMA epoch
2768 : 0 : idat = idat_list(iepoch)
2769 [ # # ]: 0 : if (idat > ndat) goto 10
2770 [ # # ]: 0 : if (iepoch == 1) then
2771 : : ! Zero output array.
2772 [ # # ]: 0 : do ipm=1,2
2773 [ # # ]: 0 : gt_scbox(:,idat,ipm) = czero_gw
2774 : : end do
2775 : : end if
2776 : :
2777 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
2778 : : if (.not. select_my_kbz(my_ikf)) continue
2779 : 0 : ik_bz = gwr%my_kbz_inds(my_ikf); gg = nint(gwr%kbz(:, ik_bz) * gwr%ngkpt)
2780 [ # # ]: 0 : do ipm=1,2
2781 : : call desc_mykbz(my_ikf)%to_scbox(gwr%kbz(:, ik_bz), gwr%ngkpt, sc_ngfft, ndat1, &
2782 : 0 : gt_gpr(ipm, my_ikf)%buffer_cplx(1,my_ir+idat-1), gt_scbox(:,idat,ipm))
2783 : : end do
2784 : : end do ! my_ikf
2785 : : 10 continue
2786 : : !call xmpi_barrier(gwr%kpt_comm%value)
2787 : : !IF (.not. MPI_ASYNC_PROTECTS_NONBLOCKING) CALL MPI_F_SYNC_REG(gt_scbox)
2788 : 0 : call xmpi_win_fence(XMPI_MODE_NOSUCCEED, gt_scbox_win, ierr) ! End the RMA epoch
2789 : : end do ! iepoch
2790 : : end if
2791 : :
2792 : : !call cwtime_report(" gwr_gk_to_scbox:", cpu, wall, gflops)
2793 : : !call timab(1929, 2, tsec)
2794 : :
2795 : 0 : end subroutine gwr_gk_to_scbox
2796 : : !!***
2797 : :
2798 : : !----------------------------------------------------------------------
2799 : :
2800 : : !!****f* m_gwr/gwr_wcq_to_scbox
2801 : : !! NAME
2802 : : !! gwr_wcq_to_scbox
2803 : : !!
2804 : : !! FUNCTION
2805 : : !! Insert W_q(g',r) in the FFT box of the supercell: q+g' index.
2806 : : !!
2807 : : !! INPUTS
2808 : : !! select_my_qbz: Mask used to select a subset of gwr%my_qkbz q-points.
2809 : : !!
2810 : : !! OUTPUT
2811 : : !!
2812 : : !! SOURCE
2813 : :
2814 : 0 : subroutine gwr_wcq_to_scbox(gwr, sc_ngfft, select_my_qbz, desc_myqbz, wc_scgvec, my_ir, ndat, &
2815 [ # # ]: 0 : wc_gpr, wct_scbox, wct_scbox_win)
2816 : :
2817 : : !Arguments ------------------------------------
2818 : : class(gwr_t),target,intent(in) :: gwr
2819 : : integer,intent(in) :: sc_ngfft(18)
2820 : : logical,intent(in) :: select_my_qbz(gwr%my_nqbz)
2821 : : integer,intent(out) :: wc_scgvec(3, gwr%tchi_mpw)
2822 : : type(desc_t),intent(inout) :: desc_myqbz(gwr%my_nqbz)
2823 : : type(__slkmat_t),intent(in) :: wc_gpr(gwr%my_nqbz)
2824 : : integer,intent(in) :: my_ir, ndat
2825 : : complex(gwp),intent(out) :: wct_scbox(product(sc_ngfft(4:6)), gwr%sc_batch_size)
2826 : : !complex(gwp),intent(out) :: wct_scbox(:,:)
2827 : : integer,optional,intent(inout) :: wct_scbox_win
2828 : :
2829 : : !Local variables-------------------------------
2830 : 0 : integer :: my_iqf, iq_bz, idat, iepoch, ii, idat_list(gwr%kpt_comm%nproc), ierr ! gg(3), ig,
2831 : : !real(dp) :: tsec(2) !, cpu, wall, gflops
2832 : : ! *************************************************************************
2833 : :
2834 : : !call timab(1930, 1, tsec)
2835 : :
2836 : : ! Take the union of (q,g') for q in the BZ. Note gwr%ngqpt instead of gwr%ngkpt.
2837 : :
2838 [ # # ]: 0 : if (.not. present(wct_scbox_win)) then
2839 [ # # # # ]: 0 : wct_scbox = czero_gw
2840 [ # # ]: 0 : do my_iqf=1,gwr%my_nqbz
2841 : : if (.not. select_my_qbz(my_iqf)) continue
2842 : 0 : iq_bz = gwr%my_qbz_inds(my_iqf)
2843 : :
2844 : : call desc_myqbz(my_iqf)%to_scbox(gwr%qbz(:,iq_bz), gwr%ngqpt, sc_ngfft, ndat, &
2845 : 0 : wc_gpr(my_iqf)%buffer_cplx(1,my_ir), wct_scbox)
2846 : : end do ! my_iqf
2847 : :
2848 : : else
2849 : : ! Each MPI proc operates on a different idat vector at each epoch
2850 [ # # # # : 0 : idat_list = cshift([(ii, ii=1,gwr%kpt_comm%nproc)], shift=-gwr%kpt_comm%me)
# # # # ]
2851 : :
2852 [ # # ]: 0 : do iepoch=1,gwr%kpt_comm%nproc
2853 : 0 : call xmpi_win_fence(XMPI_MODE_NOPRECEDE, wct_scbox_win, ierr) ! Start the RMA epoch
2854 : 0 : idat = idat_list(iepoch)
2855 [ # # ]: 0 : if (idat > ndat) goto 10
2856 [ # # # # ]: 0 : if (iepoch == 1) wct_scbox(:,idat) = czero_gw
2857 : :
2858 [ # # ]: 0 : do my_iqf=1,gwr%my_nkbz
2859 : : if (.not. select_my_qbz(my_iqf)) continue
2860 : 0 : iq_bz = gwr%my_qbz_inds(my_iqf)
2861 : : call desc_myqbz(my_iqf)%to_scbox(gwr%qbz(:,iq_bz), gwr%ngqpt, sc_ngfft, ndat1, &
2862 : 0 : wc_gpr(my_iqf)%buffer_cplx(1,my_ir+idat-1), wct_scbox(:,idat))
2863 : : end do ! my_iqf
2864 : : 10 continue
2865 : : !call xmpi_barrier(gwr%kpt_comm%value)
2866 : : !IF (.not. MPI_ASYNC_PROTECTS_NONBLOCKING) CALL MPI_F_SYNC_REG(wct_scbox)
2867 : 0 : call xmpi_win_fence(XMPI_MODE_NOSUCCEED, wct_scbox_win, ierr) ! End the RMA epoch
2868 : : end do ! iepoch
2869 : : end if
2870 : :
2871 : : !call timab(1930, 2, tsec)
2872 : :
2873 : 0 : end subroutine gwr_wcq_to_scbox
2874 : : !!***
2875 : :
2876 : : !----------------------------------------------------------------------
2877 : :
2878 : : !!****f* m_gwr/gwr_rotate_gpm
2879 : : !! NAME
2880 : : !! gwr_rotate_gpm
2881 : : !!
2882 : : !! FUNCTION
2883 : : !! Reconstruct the Green's functions in the BZ from the IBZ.
2884 : : !!
2885 : : !! INPUTS
2886 : : !! ik_bz = Index of the k-point in the BZ
2887 : : !! itau = tau index (global index)
2888 : : !! spin = spin index (global index)
2889 : : !! [ipm_list]=Optional list of ipm indices to be considered, e.g. ipm_list=[2] to compute the -tau component.
2890 : : !!
2891 : : !! OUTPUT
2892 : : !! desc_kbz = Descriptor in the BZ
2893 : : !! gt_pm(2) = Gk(+/-tau)
2894 : : !!
2895 : : !! NOTES
2896 : : !!
2897 : : !! * Remember the symmetry properties of \tilde\espilon^{-1}
2898 : : !!
2899 : : !! If q_bz = S q_ibz + G0:
2900 : : !!
2901 : : !! $\epsilon^{-1}_{SG1-G0, SG2-G0}(q_bz) = e^{+iS(G2-G1).\tau} \epsilon^{-1}_{G1, G2)}(q)
2902 : : !!
2903 : : !! If time-reversal symmetry can be used then:
2904 : : !!
2905 : : !! $\epsilon^{-1}_{G1,G2}(-q_bz) = e^{+i(G1-G2).\tau} \epsilon^{-1}_{-S^{-1}(G1+Go), -S^{-1}(G2+G0)}^*(q)
2906 : : !!
2907 : : !! In the present implementation we are not considering a possible umklapp vector G0 in the
2908 : : !! expression Sq = q+G0. Treating this case would require some changes in the G-sphere
2909 : : !! since we have to consider G - G0. The code however stops in sigma if a nonzero G0 is required
2910 : : !! to reconstruct the BZ.
2911 : : !!
2912 : : !! SOURCE
2913 : :
2914 [ # # # # : 0 : subroutine gwr_rotate_gpm(gwr, ik_bz, itau, spin, desc_kbz, gt_pm, ipm_list)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
2915 : :
2916 : : !Arguments ------------------------------------
2917 : : class(gwr_t),intent(in) :: gwr
2918 : : integer,intent(in) :: ik_bz, spin, itau
2919 : : type(desc_t),intent(out) :: desc_kbz
2920 : : type(__slkmat_t),intent(out) :: gt_pm(2, gwr%nsig_ab)
2921 : : integer,optional,intent(in) :: ipm_list(:)
2922 : :
2923 : : !Local variables-------------------------------
2924 : : !scalars
2925 : : integer :: ig1, ig2, il_g1, il_g2, ipm, ik_ibz, isym_k, trev_k, g0_k(3), tsign_k, ii, num_pm, ipm_list__(2)
2926 : : integer :: iab, iiab, jiab
2927 : : logical :: isirr_k
2928 : : !arrays
2929 : : integer :: g1(3), g2(3)
2930 : : real(dp) :: tnon(3), spinrot_k(4) !, cpu, wall, gflops
2931 : : complex(dp) :: ph2, ph1, spinrot_cmat1(2,2), spinrot_cmat2(2,2), tmp_mat(2,2)
2932 : : integer, parameter :: spinor_idxs(2, 4) = RESHAPE([1, 1, 2, 2, 1, 2, 2, 1], [2, 4])
2933 : : ! *************************************************************************
2934 : :
2935 : : !call cwtime(cpu, wall, gflops, "start")
2936 : 0 : num_pm = 2; ipm_list__ = [1, 2]
2937 [ # # ]: 0 : if (present(ipm_list)) then
2938 : 0 : num_pm = size(ipm_list)
2939 [ # # ]: 0 : ABI_CHECK_IRANGE(num_pm, 1, 2, "num_pm not in [1, 2]")
2940 [ # # ]: 0 : ipm_list__(1:num_pm) = ipm_list(:)
2941 : : end if
2942 : :
2943 : 0 : ik_ibz = gwr%kbz2ibz(1, ik_bz); isym_k = gwr%kbz2ibz(2, ik_bz)
2944 [ # # ]: 0 : trev_k = gwr%kbz2ibz(6, ik_bz); g0_k = gwr%kbz2ibz(3:5, ik_bz)
2945 [ # # # # : 0 : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
# # # # ]
2946 [ # # ]: 0 : tsign_k = merge(1, -1, trev_k == 0)
2947 : : !ABI_CHECK(all(g0_k == 0), sjoin("For kbz:", ktoa(gwr%kbz(:, ik_bz)), "g0_k:", ltoa(g0_k), " != 0"))
2948 : :
2949 : : ! Copy descriptor from IBZ
2950 : : associate (desc_kibz => gwr%green_desc_kibz(ik_ibz))
2951 : 0 : call desc_kibz%copy(desc_kbz)
2952 : :
2953 [ # # ]: 0 : if (isirr_k) then
2954 : : ! Copy the PBLAS matrices with the two Green's functions and we are done.
2955 [ # # ]: 0 : do ii=1,num_pm
2956 : 0 : ipm = ipm_list__(ii)
2957 [ # # ]: 0 : do iab=1,gwr%nsig_ab
2958 : 0 : call gwr%gt_kibz(ipm, ik_ibz, itau, spin, iab)%copy(gt_pm(ipm, iab))
2959 : : end do
2960 : : end do
2961 : : goto 10
2962 : : end if
2963 : :
2964 : : ! From:
2965 : : !
2966 : : ! u_{Sk}(Sg) = e^{-i(Sk+Sg).tnon} u_k(g)
2967 : : !
2968 : : ! and
2969 : : !
2970 : : ! u_{k+g0}(g-g0) = u_k(g)
2971 : : !
2972 : : ! one obtains:
2973 : : !
2974 : : ! G_{Sk+g0}(Sg-g0,Sg'-g0) = e^{-i tnon.S(g-g')} G_k{g,g'}
2975 : : !
2976 : : ! For time-reversal, we have u_{-k}(g) = u_{k}{-g}^*
2977 : : !
2978 : : ! G_{-k}(-g,-g') = [G_k(g,g')]*
2979 : :
2980 : : !ABI_WARNING_IF(trev_k == 0, "green: trev_k /= 0 should be tested")
2981 : :
2982 : : ! Rotate gvec, recompute gbound and rotate vc_sqrt_eps
2983 : : ! TODO: 1) Handle TR and routine to rotate tchi/W including vc_sqrt_eps
2984 : : ! 2) Make sure that the FFT box is large enough to accommodate umklapps
2985 : :
2986 : 0 : desc_kbz%ig0 = -1
2987 : : !$OMP PARALLEL DO
2988 [ # # ]: 0 : do ig1=1,desc_kbz%npw
2989 [ # # # # : 0 : desc_kbz%gvec(:,ig1) = tsign_k * matmul(gwr%cryst%symrec(:,:,isym_k), desc_kibz%gvec(:,ig1)) - g0_k
# # # # #
# # # # #
# # ]
2990 [ # # # # : 0 : if (all(desc_kbz%gvec(:,ig1) == 0)) desc_kbz%ig0 = ig1
# # ]
2991 : : end do
2992 : 0 : desc_kbz%kin_sorted = .False.
2993 [ # # ]: 0 : ABI_CHECK(desc_kbz%ig0 /= -1, "Cannot find g=0 after rotation!")
2994 : :
2995 : 0 : call sphereboundary(desc_kbz%gbound, desc_kbz%istwfk, desc_kbz%gvec, gwr%g_mgfft, desc_kbz%npw)
2996 : :
2997 : : ! Get G_k with k in the BZ.
2998 [ # # ]: 0 : tnon = gwr%cryst%tnons(:, isym_k)
2999 [ # # ]: 0 : do ii=1,num_pm
3000 : 0 : ipm = ipm_list__(ii)
3001 [ # # ]: 0 : do iab=1,gwr%nsig_ab
3002 : 0 : call gwr%gt_kibz(ipm, ik_ibz, itau, spin, iab)%copy(gt_pm(ipm, iab))
3003 : : end do
3004 : : ! associate (gk_i => gwr%gt_kibz(ipm, ik_ibz, itau, spin, :), gk_f => gt_pm(ipm, :))
3005 : : !!$OMP PARALLEL DO PRIVATE(ig1, g2, ph2, ig1, g2, ph1)
3006 [ # # ]: 0 : do il_g2=1, gt_pm(ipm, 1)%size_local(2)
3007 : 0 : ig2 = mod(gt_pm(ipm, 1)%loc2gcol(il_g2) - 1, desc_kbz%npw) + 1
3008 [ # # ]: 0 : g2 = desc_kbz%gvec(:,ig2)
3009 [ # # ]: 0 : ph2 = exp(+j_dpc * two_pi * dot_product(g2, tnon))
3010 [ # # ]: 0 : do il_g1=1, gt_pm(ipm, 1)%size_local(1)
3011 : 0 : ig1 = mod(gt_pm(ipm, 1)%loc2grow(il_g1) - 1, desc_kbz%npw) + 1
3012 [ # # ]: 0 : g1 = desc_kbz%gvec(:,ig1)
3013 [ # # ]: 0 : ph1 = exp(-j_dpc * two_pi * dot_product(g1, tnon))
3014 [ # # ]: 0 : if (gwr%nspinor == 1) then
3015 : 0 : gt_pm(ipm, 1)%buffer_cplx(il_g1, il_g2) = gwr%gt_kibz(ipm, ik_ibz, itau, spin, 1)%buffer_cplx(il_g1, il_g2) * ph1 * ph2
3016 : : else
3017 [ # # ]: 0 : spinrot_k = gwr%cryst%spinrot(:, isym_k)
3018 : :
3019 : 0 : spinrot_cmat1(1,1) = spinrot_k(1) - j_dpc*spinrot_k(4)
3020 : 0 : spinrot_cmat1(1,2) =-spinrot_k(3) - j_dpc*spinrot_k(2)
3021 : 0 : spinrot_cmat1(2,1) = spinrot_k(3) - j_dpc*spinrot_k(2)
3022 : 0 : spinrot_cmat1(2,2) = spinrot_k(1) + j_dpc*spinrot_k(4)
3023 : :
3024 : 0 : spinrot_cmat2(1,1) = spinrot_k(1) + j_dpc*spinrot_k(4)
3025 : 0 : spinrot_cmat2(1,2) = spinrot_k(3) + j_dpc*spinrot_k(2)
3026 : 0 : spinrot_cmat2(2,1) =-spinrot_k(3) + j_dpc*spinrot_k(2)
3027 : 0 : spinrot_cmat2(2,2) = spinrot_k(1) - j_dpc*spinrot_k(4)
3028 : :
3029 [ # # ]: 0 : do iab=1,gwr%nsig_ab
3030 : 0 : iiab = spinor_idxs(1, iab); jiab = spinor_idxs(2, iab)
3031 : 0 : tmp_mat(iiab, jiab) = gwr%gt_kibz(ipm, ik_ibz, itau, spin, iab)%buffer_cplx(il_g1, il_g2)
3032 : : end do
3033 [ # # # # : 0 : tmp_mat = matmul(spinrot_cmat1, matmul(tmp_mat, spinrot_cmat2)) * ph1 * ph2
# # # # #
# # # # #
# # ]
3034 [ # # ]: 0 : do iab=1,gwr%nsig_ab
3035 : 0 : iiab = spinor_idxs(1, iab); jiab = spinor_idxs(2, iab)
3036 : 0 : gt_pm(ipm, iab)%buffer_cplx(il_g1, il_g2) = tmp_mat(iiab, jiab)
3037 : : end do
3038 : : end if
3039 [ # # ]: 0 : if (trev_k == 1) then
3040 [ # # ]: 0 : if (gwr%nspinor == 1) then
3041 : 0 : gt_pm(ipm, 1)%buffer_cplx(il_g1, il_g2) = conjg(gt_pm(ipm, 1)%buffer_cplx(il_g1, il_g2))
3042 : : else
3043 : 0 : gt_pm(ipm, 1)%buffer_cplx(il_g1, il_g2) = conjg(tmp_mat(2, 2))
3044 : 0 : gt_pm(ipm, 2)%buffer_cplx(il_g1, il_g2) = conjg(tmp_mat(1, 1))
3045 : 0 : gt_pm(ipm, 3)%buffer_cplx(il_g1, il_g2) = - conjg(tmp_mat(2, 1))
3046 : 0 : gt_pm(ipm, 4)%buffer_cplx(il_g1, il_g2) = - conjg(tmp_mat(1, 2))
3047 : : end if
3048 : : end if
3049 : : end do
3050 : : end do
3051 : : ! end associate
3052 : : end do ! ii
3053 : : end associate
3054 : :
3055 : : 10 continue
3056 : : !call cwtime_report(" gwr_rotate_gpm:", cpu, wall, gflops)
3057 : :
3058 : 0 : end subroutine gwr_rotate_gpm
3059 : : !!***
3060 : :
3061 : : !----------------------------------------------------------------------
3062 : :
3063 : : !!****f* m_gwr/gwr_get_myk_green_gpr
3064 : : !! NAME
3065 : : !! gwr_get_myk_green_gpr
3066 : : !!
3067 : : !! FUNCTION
3068 : : !! Use FFTs to compute G_k(g,g') --> G_k(g',r) for each k in the BZ treated by this MPI proc for given spin and tau.
3069 : : !!
3070 : : !! 1) FFT Transform the first index and multiply by e^{ik.r}:
3071 : : !!
3072 : : !! G_k(g,g') --> G_k(r,g') = e^{ik.r} \sum_g e^{ig.r} G_k(g,g')
3073 : : !!
3074 : : !! NB: This is a local operation.
3075 : : !!
3076 : : !! 2) MPI transpose the matrix to go from (r,g') to (g',r) distribution.
3077 : : !!
3078 : : !! INPUTS
3079 : : !! select_my_kbz: Mask used to select a subset of gwr%my_nkbz k-points.
3080 : : !!
3081 : : !! OUTPUT
3082 : : !!
3083 : : !! SOURCE
3084 : :
3085 [ # # # # : 0 : subroutine gwr_get_myk_green_gpr(gwr, itau, spin, select_my_kbz, desc_mykbz, gt_gpr)
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
3086 : :
3087 : : !Arguments ------------------------------------
3088 : : class(gwr_t),intent(in) :: gwr
3089 : : integer,intent(in) :: itau, spin
3090 : : logical,intent(in) :: select_my_kbz(gwr%my_nkbz)
3091 : : type(desc_t),intent(out) :: desc_mykbz(gwr%my_nkbz)
3092 : : type(__slkmat_t),intent(inout) :: gt_gpr(2, gwr%my_nkbz, gwr%nsig_ab)
3093 : :
3094 : : !Local variables-------------------------------
3095 : : !scalars
3096 : : integer :: my_ikf, ik_bz, ig2, ipm, npw, col_bsize, ndat, gpu_option, gpu_mode, iab
3097 : : logical :: k_is_gamma
3098 : : real(dp) :: kk_bz(3), cpu, wall, gflops, mem_mb
3099 : 0 : complex(gwp),allocatable :: ceikr(:)
3100 : : character(len=500) :: msg, gpu_action
3101 [ # # # # : 0 : type(__slkmat_t) :: rgp, gt_pm(2, gwr%nsig_ab)
# # # # #
# # # # #
# # # # #
# # # #
# ]
3102 : 0 : type(uplan_t) :: uplan_k
3103 : : ! *************************************************************************
3104 : :
3105 : 0 : call cwtime(cpu, wall, gflops, "start")
3106 : 0 : gpu_option = gwr%dtset%gpu_option
3107 [ # # ]: 0 : gpu_action = "None"; if (gpu_option == ABI_GPU_OPENMP) gpu_action = "alloc"
3108 : :
3109 : 0 : mem_mb = two * gwr%my_nkbz * two * gwp * gwr%g_nfft * gwr%green_mpw * b2Mb / gwr%g_slkproc%grid%nprocs
3110 : 0 : call wrtout(std_out, sjoin(" Estimated local memory for Green's functions: ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
3111 : :
3112 [ # # # # : 0 : ABI_MALLOC(ceikr, (gwr%g_nfft))
# # # # #
# # # ]
3113 : : #ifdef HAVE_OPENMP_OFFLOAD
3114 : : !$OMP TARGET ENTER DATA MAP(alloc:ceikr) IF (gpu_option == ABI_GPU_OPENMP)
3115 : : #endif
3116 : :
3117 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
3118 : : if (.not. select_my_kbz(my_ikf)) continue
3119 : 0 : ik_bz = gwr%my_kbz_inds(my_ikf)
3120 [ # # ]: 0 : kk_bz = gwr%kbz(:, ik_bz)
3121 : 0 : k_is_gamma = normv(kk_bz, gwr%cryst%gmet, "G") < GW_TOLQ0
3122 [ # # ]: 0 : if (.not. k_is_gamma) then
3123 : 0 : call calc_ceikr(kk_bz, gwr%g_ngfft, gwr%g_nfft, 1, ceikr)
3124 : : #ifdef HAVE_OPENMP_OFFLOAD
3125 : : !$omp target update to(ceikr) if (gpu_option == ABI_GPU_OPENMP)
3126 : : #endif
3127 : : end if
3128 : :
3129 : : ! Get G_kbz(+/- itau) in the BZ.
3130 : 0 : call gwr%rotate_gpm(ik_bz, itau, spin, desc_mykbz(my_ikf), gt_pm)
3131 : :
3132 : 0 : associate (desc_k => desc_mykbz(my_ikf))
3133 : : call uplan_k%init(desc_k%npw, 1, gwr%uc_batch_size, gwr%g_ngfft, desc_k%istwfk, &
3134 : 0 : desc_k%gvec, gwp, gpu_option)
3135 : :
3136 [ # # ]: 0 : do ipm=1,2
3137 [ # # ]: 0 : do iab=1,gwr%nsig_ab
3138 : : ! Allocate rgp PBLAS matrix to store G_kbz(r,g')
3139 : : ! Here we're gonna have a lot of memory allocated due to loop over the full BZ!.
3140 : 0 : associate (g_gp => gt_pm(ipm, iab))
3141 : 0 : npw = desc_k%npw
3142 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
3143 [ # # ]: 0 : call rgp%init(gwr%g_nfft, npw, gwr%g_slkproc, desc_k%istwfk, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
3144 : :
3145 : : ! Perform FFT G_k(g,g') -> G_k(r,g') and store results in rgp.
3146 : 0 : gpu_mode = 1
3147 [ # # # # : 0 : do ig2=1, g_gp%size_local(2), gwr%uc_batch_size
# # # # ]
3148 : 0 : ndat = blocked_loop(ig2, g_gp%size_local(2), gwr%uc_batch_size)
3149 [ # # ]: 0 : if (k_is_gamma) then
3150 : 0 : call uplan_k%execute_gr(ndat, g_gp%buffer_cplx(:, ig2), rgp%buffer_cplx(:, ig2), gpu_mode=gpu_mode)
3151 : : else
3152 : 0 : call uplan_k%execute_gr(ndat, g_gp%buffer_cplx(:, ig2), rgp%buffer_cplx(:, ig2), phase_r=ceikr, gpu_mode=gpu_mode)
3153 : : end if
3154 : : end do ! ig2
3155 : :
3156 : : ! MPI transpose: G_k(r,g') -> G_k(g',r)
3157 : 0 : call rgp%ptrans("N", gt_gpr(ipm, my_ikf, iab), free=.True.)
3158 : : end associate
3159 : : end do ! iab
3160 : : end do ! ipm
3161 : :
3162 : 0 : call uplan_k%free(); call slk_array_free(gt_pm)
3163 : : end associate
3164 : : end do ! my_ikf
3165 : :
3166 [ # # # # : 0 : mem_mb = sum(slk_array_locmem_mb(gt_gpr))
# # ]
3167 : 0 : call wrtout(std_out, sjoin(" Local memory for G_kbz(g',r,itau): ", ftoa(mem_mb, fmt="f8.1"), "[Mb] <<< MEM"))
3168 : :
3169 : : #ifdef HAVE_OPENMP_OFFLOAD
3170 : : !$OMP TARGET EXIT DATA MAP(delete: ceikr) if (gpu_option == ABI_GPU_OPENMP)
3171 : : #endif
3172 [ # # ]: 0 : ABI_FREE(ceikr)
3173 : :
3174 : 0 : call cwtime_report(" gwr_get_myk_green_gpr:", cpu, wall, gflops)
3175 : :
3176 [ # # # # : 0 : end subroutine gwr_get_myk_green_gpr
# # # # #
# ]
3177 : : !!***
3178 : :
3179 : : !----------------------------------------------------------------------
3180 : :
3181 : : !!****f* m_gwr/gwr_get_gkbz_rpr_pm
3182 : : !! NAME
3183 : : !! gwr_get_gkbz_rpr_pm
3184 : : !!
3185 : : !! FUNCTION
3186 : : !! Compute G_k(r',r) from G_k(g,g') for k in the BZ and given spin and tau.
3187 : : !! Note that the output matrix `gk_rpr_pm` is transposed i.e. (r',r) instead of (r,r').
3188 : : !!
3189 : : !! INPUTS
3190 : : !!
3191 : : !! OUTPUT
3192 : : !!
3193 : : !! SOURCE
3194 : :
3195 : 0 : subroutine gwr_get_gkbz_rpr_pm(gwr, ik_bz, itau, spin, gk_rpr_pm, &
3196 [ # # # # : 0 : g0, ipm_list) ! optional
# # ]
3197 : :
3198 : : !Arguments ------------------------------------
3199 : : class(gwr_t),intent(in) :: gwr
3200 : : integer,intent(in) :: ik_bz, itau, spin
3201 : : type(__slkmat_t),intent(inout) :: gk_rpr_pm(2, gwr%nsig_ab)
3202 : : integer,optional,intent(in) :: g0(3), ipm_list(:)
3203 : :
3204 : : !Local variables-------------------------------
3205 : : !scalars
3206 : : integer :: ig2, ipm, npw, col_bsize, ir1, ndat, ii, num_pm, ipm_list__(2), gpu_option, gpu_mode, iab
3207 : : logical :: have_g0
3208 : : !real(dp) :: cpu, wall, gflops
3209 [ # # # # : 0 : type(__slkmat_t) :: rgp, gt_pm(2, gwr%nsig_ab), gpr
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
3210 [ # # ]: 0 : type(desc_t) :: desc_kbz
3211 : 0 : type(uplan_t) :: uplan_k
3212 : 0 : complex(gwp),allocatable :: ceig0r(:), conjg_ceig0r(:)
3213 : : character(len=500) :: msg, gpu_action
3214 : : ! *************************************************************************
3215 : :
3216 : : !call cwtime(cpu, wall, gflops, "start")
3217 : : ABI_NVTX_START_RANGE(NVTX_GWR_GKBZ_RPR_PM)
3218 : :
3219 : 0 : gpu_option = gwr%dtset%gpu_option
3220 : :
3221 : 0 : num_pm = 2; ipm_list__ = [1, 2]
3222 [ # # ]: 0 : if (present(ipm_list)) then
3223 : 0 : num_pm = size(ipm_list)
3224 [ # # ]: 0 : ABI_CHECK_IRANGE(num_pm, 1, 2, "num_pm not in [1, 2]")
3225 [ # # ]: 0 : ipm_list__(1:num_pm) = ipm_list
3226 : : end if
3227 : :
3228 : 0 : have_g0 = .False.
3229 [ # # ]: 0 : if (present(g0)) then
3230 : : ! NB: Non-zero g0, requires the application of the phase.
3231 [ # # # # : 0 : if (any(g0 /= 0)) then
# # ]
3232 : 0 : have_g0 = .True.
3233 [ # # # # : 0 : ABI_MALLOC(ceig0r, (gwr%g_nfft))
# # # # #
# # # ]
3234 [ # # ]: 0 : call calc_ceigr(-g0, gwr%g_nfft, 1, gwr%g_ngfft, ceig0r)
3235 [ # # # # : 0 : ABI_MALLOC(conjg_ceig0r, (gwr%g_nfft))
# # # # #
# # # ]
3236 [ # # # # : 0 : conjg_ceig0r = conjg(ceig0r)
# # # # ]
3237 : : #ifdef HAVE_OPENMP_OFFLOAD
3238 : : !$OMP TARGET ENTER DATA MAP(alloc:ceig0r, conjg_ceig0r) IF (gpu_option == ABI_GPU_OPENMP)
3239 : : !$omp target update to(ceig0r, conjg_ceig0r) if (gpu_option == ABI_GPU_OPENMP)
3240 : : #endif
3241 : : end if
3242 : : end if
3243 : :
3244 : : ! Get G_k(g,g', +/- itau) in the BZ.
3245 : 0 : call gwr%rotate_gpm(ik_bz, itau, spin, desc_kbz, gt_pm, ipm_list=ipm_list__(1:num_pm))
3246 : :
3247 : : call uplan_k%init(desc_kbz%npw, 1, gwr%uc_batch_size, gwr%g_ngfft, desc_kbz%istwfk, &
3248 : 0 : desc_kbz%gvec, gwp, gpu_option)
3249 : :
3250 [ # # ]: 0 : gpu_action = "None"; if (gpu_option == ABI_GPU_OPENMP) gpu_action = "alloc"
3251 : :
3252 : : ! For each tau in imp_list__
3253 [ # # ]: 0 : do ii=1,num_pm
3254 : 0 : ipm = ipm_list__(ii)
3255 : : ! Allocate temporary rgp PBLAS matrix to store G(r,g')
3256 : 0 : npw = desc_kbz%npw
3257 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
3258 [ # # ]: 0 : do iab=1,gwr%nsig_ab
3259 [ # # ]: 0 : call rgp%init(gwr%g_nfft, npw, gwr%g_slkproc, desc_kbz%istwfk, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
3260 : : associate (g_gp => gt_pm(ipm, iab))
3261 : 0 : gpu_mode = 1
3262 [ # # # # : 0 : do ig2=1, g_gp%size_local(2), gwr%uc_batch_size
# # # # ]
3263 : : ! G_k(g,g') -> G_k(r,g') and store results in rgp.
3264 : 0 : ndat = blocked_loop(ig2, g_gp%size_local(2), gwr%uc_batch_size)
3265 [ # # ]: 0 : if (have_g0) then
3266 : 0 : call uplan_k%execute_gr(ndat, g_gp%buffer_cplx(:,ig2), rgp%buffer_cplx(:,ig2), phase_r=ceig0r, gpu_mode=gpu_mode)
3267 : : else
3268 : 0 : call uplan_k%execute_gr(ndat, g_gp%buffer_cplx(:,ig2), rgp%buffer_cplx(:,ig2), gpu_mode=gpu_mode)
3269 : : end if
3270 : : end do ! ig2
3271 : : end associate
3272 : :
3273 : : ! MPI transpose: G_k(r,g') -> G_k(g',r) and transform g' index.
3274 : 0 : call rgp%ptrans("N", gpr, free=.True.)
3275 : :
3276 : : gpu_mode = 1
3277 [ # # # # : 0 : do ir1=1, gpr%size_local(2), gwr%uc_batch_size
# # # # ]
3278 : : ! G_k(g',r) -> G_k(r',r) and store results in rgp.
3279 : 0 : ndat = blocked_loop(ir1, gpr%size_local(2), gwr%uc_batch_size)
3280 [ # # ]: 0 : if (have_g0) then
3281 : : call uplan_k%execute_gr(ndat, gpr%buffer_cplx(:,ir1), gk_rpr_pm(ipm, iab)%buffer_cplx(:,ir1), &
3282 : 0 : isign=-1, iscale=0, phase_r=conjg_ceig0r, gpu_mode=gpu_mode)
3283 : : else
3284 : : call uplan_k%execute_gr(ndat, gpr%buffer_cplx(:,ir1), gk_rpr_pm(ipm, iab)%buffer_cplx(:,ir1), &
3285 : 0 : isign=-1, iscale=0, gpu_mode=gpu_mode)
3286 : : end if
3287 : : end do ! ir1
3288 : 0 : call gpr%free()
3289 : : end do
3290 : : end do ! ii
3291 : :
3292 : 0 : call slk_array_free(gt_pm); call desc_kbz%free(); call uplan_k%free()
3293 : :
3294 [ # # ]: 0 : if (have_g0) then
3295 : : #ifdef HAVE_OPENMP_OFFLOAD
3296 : : !$OMP TARGET EXIT DATA MAP(delete: ceig0r, conjg_ceig0r) if (gpu_option == ABI_GPU_OPENMP)
3297 : : #endif
3298 [ # # ]: 0 : ABI_FREE(ceig0r)
3299 [ # # ]: 0 : ABI_FREE(conjg_ceig0r)
3300 : : end if
3301 : :
3302 : : ! FIXME: Transfer data from CPU to GPU.
3303 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) then
3304 [ # # ]: 0 : do ii=1,num_pm
3305 : 0 : ipm = ipm_list__(ii)
3306 [ # # ]: 0 : do iab=1,gwr%nsig_ab
3307 : 0 : call gk_rpr_pm(ipm, iab)%gpu_map("update_to")
3308 : : end do
3309 : : end do
3310 : : end if
3311 : :
3312 : : ABI_NVTX_END_RANGE()
3313 : : !call cwtime_report(" gwr_get_gkbz_rpr_pm:", cpu, wall, gflops)
3314 : :
3315 [ # # # # : 0 : end subroutine gwr_get_gkbz_rpr_pm
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
3316 : : !!***
3317 : :
3318 : : !----------------------------------------------------------------------
3319 : :
3320 : : !! !!****f* m_gwr/gwr_ggp_to_rpr
3321 : : !! !! NAME
3322 : : !! !! gwr_ggp_to_rpr
3323 : : !! !!
3324 : : !! !! FUNCTION
3325 : : !! !! Helper function to FFT transform a two-point function: F_{g,g'} --> F_{r',r}
3326 : : !! !!
3327 : : !! !! INPUTS
3328 : : !! !!
3329 : : !! !! OUTPUT
3330 : : !! !!
3331 : : !! !! SOURCE
3332 : : !!
3333 : : !! !subroutine gwr_ggp_to_rpr(gwr, desc, g_gp, rp_r)
3334 : : !! !
3335 : : !! !!Arguments ------------------------------------
3336 : : !! ! class(gwr_t),intent(in) :: gwr
3337 : : !! ! type(desc_t),intent(in) :: desc
3338 : : !! ! type(__slkmat_t),intent(in) :: g_gp
3339 : : !! ! type(__slkmat_t),intent(inout) :: rp_r
3340 : : !! !
3341 : : !! !!Local variables-------------------------------
3342 : : !! ! integer :: ig2, npw, nrsp, col_bsize, ir1, ndat
3343 : : !! ! type(__slkmat_t) :: rgp, gpr
3344 : : !! ! character(len=500) :: msg
3345 : : !! ! type(uplan_t) :: uplan_k
3346 : : !! !! *************************************************************************
3347 : : !! !
3348 : : !! ! ABI_ERROR("Not Implemented Error")
3349 : : !! !
3350 : : !! ! ! Allocate intermediate rgp PBLAS matrix to store F(r,g')
3351 : : !! ! npw = desc%npw
3352 : : !! ! nrsp = gwr%g_nfft * gwr%nspinor
3353 : : !! ! ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
3354 : : !! ! call rgp%init(nrsp, npw, gwr%g_slkproc, desc%istwfk, size_blocs=[-1, col_bsize])
3355 : : !! !
3356 : : !! ! call uplan_k%init(desc%npw, gwr%nspinor, gwr%uc_batch_size, gwr%g_ngfft, desc%istwfk, &
3357 : : !! ! desc%gvec, gwp, gwr%dtset%gpu_option)
3358 : : !! !
3359 : : !! ! ! F(g,g') --> F(r,g') and store results in rgp.
3360 : : !! ! do ig2=1, g_gp%size_local(2), gwr%uc_batch_size
3361 : : !! ! ndat = blocked_loop(ig2, g_gp%size_local(2), gwr%uc_batch_size)
3362 : : !! ! call uplan_k%execute_gr(ndat, g_gp%buffer_cplx(:,ig2), rgp%buffer_cplx(:,ig2))
3363 : : !! ! end do
3364 : : !! !
3365 : : !! ! ! F(r,g') --> F(g',r)
3366 : : !! ! call rgp%ptrans("N", gpr, free=.True.)
3367 : : !! !
3368 : : !! ! ! F(g',r) --> F(r',r) and store results in rp_r.
3369 : : !! ! do ir1=1, gpr%size_local(2), gwr%uc_batch_size
3370 : : !! ! ndat = blocked_loop(ir1, gpr%size_local(2), gwr%uc_batch_size)
3371 : : !! ! call uplan_k%execute_gr(ndat, gpr%buffer_cplx(:,ir1), rp_r%buffer_cplx(:,ir1), isign=-1, iscale=0)
3372 : : !! ! end do
3373 : : !! !
3374 : : !! ! call uplan_k%free()
3375 : : !! ! call gpr%free()
3376 : : !! !
3377 : : !! !end subroutine gwr_ggp_to_rpr
3378 : : !! !!!***
3379 : :
3380 : : !----------------------------------------------------------------------
3381 : :
3382 : : !!****f* m_gwr/gwr_rpr_to_ggp
3383 : : !! NAME
3384 : : !! gwr_rpr_to_ggp
3385 : : !!
3386 : : !! FUNCTION
3387 : : !! Helper function to FFT a two-point function: F_{r',r} --> F_{g,g'}
3388 : : !! Note that rp_r is destroyed in output.
3389 : : !!
3390 : : !! INPUTS
3391 : : !!
3392 : : !! OUTPUT
3393 : : !!
3394 : : !! SOURCE
3395 : :
3396 : 0 : subroutine gwr_rpr_to_ggp(gwr, desc, rp_r, rfact, g_gp)
3397 : :
3398 : : !Arguments ------------------------------------
3399 : : class(gwr_t),intent(in) :: gwr
3400 : : type(desc_t),intent(in) :: desc
3401 : : real(dp),intent(in) :: rfact
3402 : : class(__slkmat_t),intent(inout) :: rp_r, g_gp
3403 : :
3404 : : !Local variables-------------------------------
3405 : : integer :: ig2, npw, nr, col_bsize, ir2, ndat, isign, gpu_option, gpu_mode
3406 [ # # # # : 0 : type(__slkmat_t) :: r_gp, gp_r
# # # # #
# # # ]
3407 : : character(len=500) :: msg, gpu_action
3408 : 0 : type(uplan_t) :: uplan_k
3409 : : ! *************************************************************************
3410 : :
3411 : : ABI_NVTX_START_RANGE(NVTX_GWR_RPR_TO_GGP)
3412 : :
3413 : : ! Allocate intermediate gp_r PBLAS matrix to store F(g',r)
3414 : 0 : npw = desc%npw; nr = gwr%g_nfft
3415 [ # # ]: 0 : ABI_CHECK(block_dist_1d(nr, gwr%g_comm%nproc, col_bsize, msg), msg)
3416 : :
3417 : 0 : gpu_option = gwr%dtset%gpu_option
3418 [ # # ]: 0 : gpu_action = "None"; if (gpu_option == ABI_GPU_OPENMP) gpu_action = "alloc"
3419 [ # # ]: 0 : call gp_r%init(npw, nr, gwr%g_slkproc, desc%istwfk, size_blocs=[-1, col_bsize])
3420 : :
3421 : : call uplan_k%init(desc%npw, 1, gwr%uc_batch_size, gwr%g_ngfft, desc%istwfk, desc%gvec, gwp, &
3422 : 0 : 0)
3423 : : !gwr%dtset%gpu_option) ! FIXME GPU option
3424 : :
3425 : 0 : isign = +1 ! This should be ok
3426 : : !isign = -1
3427 : :
3428 [ # # ]: 0 : if (gwr%dtset%gpu_option == ABI_GPU_OPENMP) call rp_r%gpu_map("update_from") ! FIXME
3429 : :
3430 : : ! F(r',r) --> F(g',r) and store results in gp_r.
3431 : 0 : gpu_mode = 1
3432 [ # # # # : 0 : do ir2=1, rp_r%size_local(2), gwr%uc_batch_size
# # # # ]
3433 : 0 : ndat = blocked_loop(ir2, rp_r%size_local(2), gwr%uc_batch_size)
3434 : : call uplan_k%execute_rg(ndat, rp_r%buffer_cplx(:,ir2), gp_r%buffer_cplx(:,ir2), &
3435 : 0 : isign=isign, iscale=0, gpu_mode=gpu_mode)
3436 : : end do
3437 : :
3438 : : ! F(g',r) --> F(r,g')
3439 : : !call gp_r%ptrans("N", r_gp, free=.True.)
3440 : : ! FIXME: I don't know why but C is needed here.
3441 : 0 : call gp_r%ptrans("C", r_gp, free=.True.)
3442 : :
3443 : : ! F(r,g') --> F(g,g') and store results in g_gp.
3444 : : gpu_mode = 1
3445 [ # # # # : 0 : do ig2=1, g_gp%size_local(2), gwr%uc_batch_size
# # # # ]
3446 : 0 : ndat = blocked_loop(ig2, g_gp%size_local(2), gwr%uc_batch_size)
3447 : : call uplan_k%execute_rg(ndat, r_gp%buffer_cplx(:,ig2), g_gp%buffer_cplx(:,ig2), &
3448 : 0 : isign=-isign, iscale=0, gpu_mode=gpu_mode)
3449 : : end do
3450 : :
3451 : : ! Scale output.
3452 [ # # # # ]: 0 : g_gp%buffer_cplx = g_gp%buffer_cplx * rfact
3453 : :
3454 [ # # ]: 0 : if (gwr%dtset%gpu_option == ABI_GPU_OPENMP) call g_gp%gpu_map("update_to") ! FIXME
3455 : :
3456 : 0 : call uplan_k%free(); call r_gp%free()
3457 : : ABI_NVTX_END_RANGE()
3458 : :
3459 [ # # # # : 0 : end subroutine gwr_rpr_to_ggp
# # # # #
# # # #
# ]
3460 : : !!***
3461 : :
3462 : : !----------------------------------------------------------------------
3463 : :
3464 : : !!****f* m_gwr/gwr_rotate_wc
3465 : : !! NAME
3466 : : !! gwr_rotate_wc
3467 : : !!
3468 : : !! FUNCTION
3469 : : !! Reconstruct Wc(q,g,g') in the BZ from the IBZ.
3470 : : !!
3471 : : !! INPUTS
3472 : : !!
3473 : : !! OUTPUT
3474 : : !!
3475 : : !! SOURCE
3476 : :
3477 [ # # # # : 0 : subroutine gwr_rotate_wc(gwr, iq_bz, itau, spin, desc_qbz, wc_qbz)
# # # # #
# # # # #
# # # # #
# ]
3478 : :
3479 : : !Arguments ------------------------------------
3480 : : class(gwr_t),intent(inout) :: gwr
3481 : : integer,intent(in) :: iq_bz, itau, spin
3482 : : type(desc_t),intent(out) :: desc_qbz
3483 : : type(__slkmat_t),intent(inout) :: wc_qbz
3484 : :
3485 : : !Local variables-------------------------------
3486 : : !scalars
3487 : : integer :: ig1, ig2, il_g1, il_g2, iq_ibz, isym_q, trev_q, tsign_q
3488 : : logical :: isirr_q, q_is_gamma
3489 : : !arrays
3490 : : integer :: g1(3), g2(3), g0_q(3)
3491 : : real(dp) :: tnon(3), qq_bz(3)
3492 : : complex(dp) :: ph2, ph1
3493 : : ! *************************************************************************
3494 : :
3495 : : ABI_NVTX_START_RANGE(NVTX_GWR_ROTATE_WC)
3496 [ # # ]: 0 : ABI_CHECK(gwr%wc_space == "itau", sjoin("wc_space:", gwr%wc_space, " != itau"))
3497 : :
3498 [ # # ]: 0 : qq_bz = gwr%qbz(:, iq_bz)
3499 : 0 : q_is_gamma = normv(qq_bz, gwr%cryst%gmet, "G") < GW_TOLQ0
3500 : :
3501 : 0 : iq_ibz = gwr%qbz2ibz(1, iq_bz); isym_q = gwr%qbz2ibz(2, iq_bz)
3502 [ # # ]: 0 : trev_q = gwr%qbz2ibz(6, iq_bz); g0_q = gwr%qbz2ibz(3:5, iq_bz)
3503 [ # # # # : 0 : isirr_q = (isym_q == 1 .and. trev_q == 0 .and. all(g0_q == 0))
# # # # ]
3504 [ # # ]: 0 : tsign_q = merge(1, -1, trev_q == 0)
3505 : : ! TODO: Understand why legacy GW does not need umklapp
3506 : : !ABI_CHECK(all(g0_q == 0), sjoin("For qbz:", ktoa(gwr%qbz(:, iq_bz)), "g0_q:", ltoa(g0_q), " != 0"))
3507 : :
3508 : : ! Copy descriptor from IBZ
3509 : : associate (desc_qibz => gwr%tchi_desc_qibz(iq_ibz))
3510 : 0 : call desc_qibz%copy(desc_qbz)
3511 : :
3512 [ # # ]: 0 : if (isirr_q) then
3513 : : ! Copy the PBLAS matrix in wc_qbz and we are done.
3514 : 0 : call gwr%wc_qibz(iq_ibz, itau, spin)%copy(wc_qbz); goto 10
3515 : : end if
3516 : :
3517 : : !ABI_WARNING_IF(trev_q == 0, "trev_q should be tested")
3518 : : ! rotate gvec, recompute gbound and rotate vc_sqrt_eps.
3519 : : ! TODO: 1) Handle TR and routine to rotate tchi/W including vc_sqrt_eps
3520 : : ! 2) Make sure that FFT box is large enough to accomodate umklapps
3521 : 0 : desc_qbz%ig0 = -1
3522 [ # # ]: 0 : do ig1=1,desc_qbz%npw
3523 [ # # # # : 0 : desc_qbz%gvec(:,ig1) = tsign_q * matmul(gwr%cryst%symrec(:,:,isym_q), desc_qibz%gvec(:,ig1)) - g0_q
# # # # #
# # # # #
# # ]
3524 [ # # # # : 0 : if (all(desc_qbz%gvec(:,ig1) == 0)) desc_qbz%ig0 = ig1
# # ]
3525 : : end do
3526 : 0 : desc_qbz%kin_sorted = .False.
3527 [ # # ]: 0 : ABI_CHECK(desc_qbz%ig0 /= -1, "Cannot find g = 0 after g-vector rotation!")
3528 : :
3529 : 0 : call sphereboundary(desc_qbz%gbound, desc_qbz%istwfk, desc_qbz%gvec, gwr%g_mgfft, desc_qbz%npw)
3530 : :
3531 : : ! Compute sqrt(vc(q,G))
3532 : : ! TODO: rotate vc_sqrt_eps
3533 : : ! vc(Sq, Sg) = vc(q, g)
3534 : : ! vc(-q, -g) = vc(q, g)
3535 : 0 : call desc_qbz%get_vc_sqrt(qq_bz, q_is_gamma, gwr, "sigma", gwr%gtau_comm%value)
3536 : :
3537 : : ! Get Wc_q with q in the BZ.
3538 [ # # ]: 0 : tnon = gwr%cryst%tnons(:, isym_q)
3539 : 0 : associate (wq_i => gwr%wc_qibz(iq_ibz, itau, spin), wq_f => wc_qbz)
3540 : 0 : call wq_i%copy(wc_qbz)
3541 : :
3542 : : !!!$OMP PARALLEL DO PRIVATE(ig2, g2, ph2, ig1, g2, ph1)
3543 [ # # ]: 0 : do il_g2=1, wq_f%size_local(2)
3544 : 0 : ig2 = mod(wq_f%loc2gcol(il_g2) - 1, desc_qbz%npw) + 1
3545 [ # # ]: 0 : g2 = desc_qbz%gvec(:,ig2)
3546 [ # # ]: 0 : ph2 = exp(+j_dpc * two_pi * dot_product(g2, tnon))
3547 [ # # ]: 0 : do il_g1=1, wq_f%size_local(1)
3548 : 0 : ig1 = mod(wq_f%loc2grow(il_g1) - 1, desc_qbz%npw) + 1
3549 [ # # ]: 0 : g1 = desc_qbz%gvec(:,ig1)
3550 [ # # ]: 0 : ph1 = exp(-j_dpc * two_pi * dot_product(g1, tnon))
3551 : 0 : wq_f%buffer_cplx(il_g1, il_g2) = wq_i%buffer_cplx(il_g1, il_g2) * ph1 * ph2
3552 [ # # ]: 0 : if (trev_q == 1) wq_f%buffer_cplx(il_g1, il_g2) = conjg(wq_f%buffer_cplx(il_g1, il_g2))
3553 : : end do
3554 : : end do
3555 : : end associate
3556 : : end associate
3557 : :
3558 : : 10 continue
3559 : : ABI_NVTX_END_RANGE()
3560 : :
3561 : 0 : end subroutine gwr_rotate_wc
3562 : : !!***
3563 : :
3564 : : !----------------------------------------------------------------------
3565 : :
3566 : : !!****f* m_gwr/gwr_get_myq_wc_gpr
3567 : : !! NAME
3568 : : !! gwr_get_myq_wc_gpr
3569 : : !!
3570 : : !! FUNCTION
3571 : : !! Use FFTs to compute: Wc_q(g,g') --> Wc_q(g',r)
3572 : : !! for each q in the BZ treated by this MPI proc for given `spin` and `itau` index:
3573 : : !!
3574 : : !! 1) FFT Transform the first index: Wc(g,g',it) --> Wc(r,g',it) (local operation)
3575 : : !! 2) MPI transposition: Wc(r,g',it) --> Wc(g',r,it)
3576 : : !!
3577 : : !! INPUTS
3578 : : !! select_my_qbz: Mask used to select a subset of gwr%my_qkbz q-points.
3579 : : !!
3580 : : !! OUTPUT
3581 : : !!
3582 : : !! SOURCE
3583 : :
3584 [ # # # # : 0 : subroutine gwr_get_myq_wc_gpr(gwr, itau, spin, select_my_qbz, desc_myqbz, wc_gpr)
# # # # #
# # # # #
# # # # #
# # # #
# ]
3585 : :
3586 : : !Arguments ------------------------------------
3587 : : class(gwr_t),intent(inout) :: gwr
3588 : : integer,intent(in) :: itau, spin
3589 : : logical,intent(in) :: select_my_qbz(gwr%my_nqbz)
3590 : : type(desc_t),target,intent(out) :: desc_myqbz(gwr%my_nqbz)
3591 : : type(__slkmat_t),intent(inout) :: wc_gpr(gwr%my_nqbz)
3592 : :
3593 : : !Local variables-------------------------------
3594 : : !scalars
3595 : : integer :: my_iqf, iq_bz, ig2, npw, col_bsize, ndat, gpu_option, gpu_mode
3596 : : real(dp) :: cpu, wall, gflops, mem_mb, qq_bz(3)
3597 : : logical :: q_is_gamma
3598 : : character(len=500) :: msg, gpu_action
3599 [ # # # # : 0 : type(__slkmat_t) :: rgp, wc_qbz
# # # # #
# # # ]
3600 : 0 : type(uplan_t) :: uplan_q
3601 : 0 : complex(gwp),allocatable :: ceiqr(:)
3602 : : ! *************************************************************************
3603 : :
3604 : 0 : call cwtime(cpu, wall, gflops, "start")
3605 : : ABI_NVTX_START_RANGE(NVTX_GWR_MYQ_WW_GPR)
3606 : :
3607 : 0 : gpu_option = gwr%dtset%gpu_option
3608 : :
3609 [ # # # # : 0 : ABI_MALLOC(ceiqr, (gwr%g_nfft))
# # # # #
# # # ]
3610 : : #ifdef HAVE_OPENMP_OFFLOAD
3611 : : !$OMP TARGET ENTER DATA MAP(alloc:ceiqr) IF (gpu_option == ABI_GPU_OPENMP)
3612 : : #endif
3613 : :
3614 [ # # ]: 0 : gpu_action = "None"; if (gpu_option == ABI_GPU_OPENMP) gpu_action = "alloc"
3615 : :
3616 [ # # ]: 0 : do my_iqf=1,gwr%my_nqbz
3617 : : if (.not. select_my_qbz(my_iqf)) continue
3618 [ # # ]: 0 : iq_bz = gwr%my_qbz_inds(my_iqf); qq_bz = gwr%qbz(:, iq_bz)
3619 : 0 : q_is_gamma = normv(qq_bz, gwr%cryst%gmet, "G") < GW_TOLQ0
3620 [ # # ]: 0 : if (.not. q_is_gamma) then
3621 : 0 : call calc_ceikr(qq_bz, gwr%g_ngfft, gwr%g_nfft, 1, ceiqr)
3622 : : #ifdef HAVE_OPENMP_OFFLOAD
3623 : : !$omp target update to(ceiqr) if (gpu_option == ABI_GPU_OPENMP)
3624 : : #endif
3625 : : end if
3626 : :
3627 : : ! Get Wc_q in the BZ.
3628 : 0 : call gwr%rotate_wc(iq_bz, itau, spin, desc_myqbz(my_iqf), wc_qbz)
3629 : : associate (desc_q => desc_myqbz(my_iqf))
3630 : :
3631 : : ! Allocate rgp PBLAS matrix to store Wc_q(r, g')
3632 : 0 : npw = desc_q%npw
3633 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
3634 [ # # ]: 0 : call rgp%init(gwr%g_nfft, npw, gwr%g_slkproc, desc_q%istwfk, size_blocs=[-1, col_bsize])
3635 : :
3636 : : call uplan_q%init(desc_q%npw, 1, gwr%uc_batch_size, gwr%g_ngfft, desc_q%istwfk, &
3637 : 0 : desc_q%gvec, gwp, gpu_option)
3638 : :
3639 : : ! FFT and store results in rgp
3640 : 0 : gpu_mode = 1
3641 [ # # # # : 0 : do ig2=1,wc_qbz%size_local(2), gwr%uc_batch_size
# # # # ]
3642 : 0 : ndat = blocked_loop(ig2, wc_qbz%size_local(2), gwr%uc_batch_size)
3643 : :
3644 [ # # ]: 0 : if (q_is_gamma) then
3645 : 0 : call uplan_q%execute_gr(ndat, wc_qbz%buffer_cplx(:, ig2), rgp%buffer_cplx(:, ig2), gpu_mode=gpu_mode)
3646 : : else
3647 : 0 : call uplan_q%execute_gr(ndat, wc_qbz%buffer_cplx(:, ig2), rgp%buffer_cplx(:, ig2), phase_r=ceiqr, gpu_mode=gpu_mode)
3648 : : end if
3649 : : end do ! ig2
3650 : :
3651 : 0 : call uplan_q%free()
3652 : :
3653 : : ! MPI transposition: Wc(r,g') -> Wc(g',r)
3654 : 0 : call rgp%ptrans("N", wc_gpr(my_iqf), free=.True.)
3655 : : end associate
3656 : 0 : call wc_qbz%free()
3657 : :
3658 : : !if (gpu_option == ABI_GPU_OPENMP) call wc_gpr(my_iqf)%gpu_map("update_to")
3659 : : end do ! my_iqf
3660 : :
3661 : : #ifdef HAVE_OPENMP_OFFLOAD
3662 : : !$OMP TARGET EXIT DATA MAP(delete: ceiqr) if (gpu_option == ABI_GPU_OPENMP)
3663 : : #endif
3664 [ # # ]: 0 : ABI_FREE(ceiqr)
3665 : :
3666 [ # # ]: 0 : mem_mb = sum(slk_array_locmem_mb(wc_gpr))
3667 : 0 : call wrtout(std_out, sjoin(" Local memory for Wc(g',r):", ftoa(mem_mb, fmt="f8.1"), "[Mb] <<< MEM"))
3668 : 0 : call cwtime_report(" gwr_get_myq_wc_gpr:", cpu, wall, gflops)
3669 : :
3670 : : ABI_NVTX_END_RANGE()
3671 : :
3672 [ # # # # : 0 : end subroutine gwr_get_myq_wc_gpr
# # # # #
# # # #
# ]
3673 : : !!***
3674 : :
3675 : : !----------------------------------------------------------------------
3676 : :
3677 : : !!****f* m_gwr/gwr_get_wc_rpr_qbz
3678 : : !! NAME
3679 : : !! gwr_get_wc_rpr_qbz
3680 : : !!
3681 : : !! FUNCTION
3682 : : !! Compute Wc_q(r',r') for q in the BZ
3683 : : !!
3684 : : !! INPUTS
3685 : : !!
3686 : : !! OUTPUT
3687 : : !!
3688 : : !! SOURCE
3689 : :
3690 : 0 : subroutine gwr_get_wc_rpr_qbz(gwr, g0_q, iq_bz, itau, spin, wc_rpr)
3691 : :
3692 : : !Arguments ------------------------------------
3693 : : class(gwr_t),intent(inout) :: gwr
3694 : : integer,intent(in) :: g0_q(3)
3695 : : integer,intent(in) :: iq_bz, itau, spin
3696 : : type(__slkmat_t),intent(inout) :: wc_rpr
3697 : :
3698 : : !Local variables-------------------------------
3699 : : !scalars
3700 : : integer :: ig2, npw, nr, col_bsize, ir1, ndat, gpu_option, gpu_mode
3701 : : character(len=500) :: msg, gpu_action
3702 [ # # ]: 0 : type(desc_t) :: desc_qbz
3703 [ # # # # : 0 : type(__slkmat_t) :: wc_ggp, rgp, gpr
# # # # #
# # # # #
# # # # ]
3704 : 0 : type(uplan_t) :: uplan_k
3705 : 0 : complex(gwp),allocatable :: ceig0r(:), conjg_ceig0r(:)
3706 : : ! *************************************************************************
3707 : :
3708 : : ABI_NVTX_START_RANGE(NVTX_GWR_WC_RPR_QBZ)
3709 : :
3710 : 0 : gpu_option = gwr%dtset%gpu_option
3711 [ # # ]: 0 : gpu_action = "None"; if (gpu_option == ABI_GPU_OPENMP) gpu_action = "alloc"
3712 : :
3713 : : ! NB: Non-zero g0, requires the application of the phase.
3714 [ # # # # : 0 : if (any(g0_q /= 0)) then
# # ]
3715 [ # # # # : 0 : ABI_MALLOC(ceig0r, (gwr%g_nfft))
# # # # #
# # # ]
3716 [ # # # # : 0 : ABI_MALLOC(conjg_ceig0r, (gwr%g_nfft))
# # # # ]
3717 [ # # ]: 0 : call calc_ceigr(-g0_q, gwr%g_nfft, 1, gwr%g_ngfft, ceig0r)
3718 [ # # # # ]: 0 : conjg_ceig0r = conjg(ceig0r)
3719 : : #ifdef HAVE_OPENMP_OFFLOAD
3720 : : !$OMP TARGET ENTER DATA MAP(alloc:ceig0r, conjg_ceig0r) IF (gpu_option == ABI_GPU_OPENMP)
3721 : : !$omp target update to(ceig0r, conjg_ceig0r) if (gpu_option == ABI_GPU_OPENMP)
3722 : : #endif
3723 : : end if
3724 : :
3725 : : ! Get W_q(g,g') in the BZ.
3726 : 0 : call gwr%rotate_wc(iq_bz, itau, spin, desc_qbz, wc_ggp)
3727 : :
3728 : : ! Allocate rgp PBLAS matrix to store Wc(r,g')
3729 : 0 : nr = gwr%g_nfft
3730 : 0 : npw = desc_qbz%npw
3731 [ # # ]: 0 : ABI_CHECK(block_dist_1d(npw, gwr%g_comm%nproc, col_bsize, msg), msg)
3732 [ # # ]: 0 : call rgp%init(nr, npw, gwr%g_slkproc, desc_qbz%istwfk, size_blocs=[-1, col_bsize]) ! , gpu_action=gpu_action)
3733 : :
3734 : : call uplan_k%init(desc_qbz%npw, 1, gwr%uc_batch_size, gwr%g_ngfft, desc_qbz%istwfk, &
3735 : 0 : desc_qbz%gvec, gwp, gpu_option)
3736 : :
3737 : : ! FFT Wc(g,g') -> Wc(r,g') and store results in rgp
3738 : 0 : gpu_mode = 1
3739 [ # # # # : 0 : do ig2=1,wc_ggp%size_local(2), gwr%uc_batch_size
# # # # ]
3740 : 0 : ndat = blocked_loop(ig2, wc_ggp%size_local(2), gwr%uc_batch_size)
3741 : :
3742 [ # # # # : 0 : if (any(g0_q /= 0)) then
# # ]
3743 : : call uplan_k%execute_gr(ndat, wc_ggp%buffer_cplx(:,ig2), rgp%buffer_cplx(:,ig2), &
3744 : 0 : phase_r=ceig0r, gpu_mode=gpu_mode)
3745 : : else
3746 : : call uplan_k%execute_gr(ndat, wc_ggp%buffer_cplx(:,ig2), rgp%buffer_cplx(:,ig2), &
3747 : 0 : gpu_mode=gpu_mode)
3748 : : end if
3749 : : end do ! ig2
3750 : :
3751 : : ! MPI transpose: Wc(r,g') -> Wc(g',r)
3752 : 0 : call rgp%ptrans("N", gpr, free=.True.)
3753 : :
3754 : : ! Wc_q(g',r) -> Wc_q(r',r) and store results in wc_rgp.
3755 : : gpu_mode = 1
3756 [ # # # # : 0 : do ir1=1,gpr%size_local(2), gwr%uc_batch_size
# # # # ]
3757 : 0 : ndat = blocked_loop(ir1, gpr%size_local(2), gwr%uc_batch_size)
3758 [ # # # # : 0 : if (any(g0_q /= 0)) then
# # ]
3759 : : call uplan_k%execute_gr(ndat, gpr%buffer_cplx(:, ir1), wc_rpr%buffer_cplx(:, ir1), &
3760 : 0 : isign=-1, iscale=0, phase_r=conjg_ceig0r, gpu_mode=gpu_mode)
3761 : : else
3762 : : call uplan_k%execute_gr(ndat, gpr%buffer_cplx(:, ir1), wc_rpr%buffer_cplx(:, ir1), &
3763 : 0 : isign=-1, iscale=0, gpu_mode=gpu_mode)
3764 : : end if
3765 : : end do ! ir1
3766 : :
3767 : 0 : call uplan_k%free(); call gpr%free(); call desc_qbz%free(); call wc_ggp%free()
3768 : :
3769 [ # # # # : 0 : if (any(g0_q /= 0)) then
# # ]
3770 : : #ifdef HAVE_OPENMP_OFFLOAD
3771 : : !$OMP TARGET EXIT DATA MAP(delete: ceig0r, conjg_ceig0r) if (gpu_option == ABI_GPU_OPENMP)
3772 : : #endif
3773 [ # # ]: 0 : ABI_SFREE(ceig0r)
3774 [ # # ]: 0 : ABI_SFREE(conjg_ceig0r)
3775 : : end if
3776 : :
3777 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) call wc_rpr%gpu_map("update_to")
3778 : : ABI_NVTX_END_RANGE()
3779 : :
3780 [ # # # # : 0 : end subroutine gwr_get_wc_rpr_qbz
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
3781 : : !!***
3782 : :
3783 : : !----------------------------------------------------------------------
3784 : :
3785 : : !!****f* m_gwr/gwr_cos_transform
3786 : : !! NAME
3787 : : !! gwr_cos_transform
3788 : : !!
3789 : : !! FUNCTION
3790 : : !! Perform cosine transform.
3791 : : !!
3792 : : !! INPUTS
3793 : : !! what: "tchi" or "wc"
3794 : : !! mode: "iw2t" for omega to tau or "it2w" for tau to omega.
3795 : : !! [sum_spins]: True to sum the two spin-channgels when what == "tchi". Default: False.
3796 : : !!
3797 : : !! SOURCE
3798 : :
3799 : 0 : subroutine gwr_cos_transform(gwr, what, mode, sum_spins)
3800 : :
3801 : : !Arguments ------------------------------------
3802 : : class(gwr_t),target,intent(inout) :: gwr
3803 : : character(len=*),intent(in) :: what, mode
3804 : : logical,optional,intent(in) :: sum_spins
3805 : :
3806 : : !Local variables-------------------------------
3807 : : !scalars
3808 : : integer, parameter :: TAU_SPACE = 0, W_SPACE = 1
3809 : : integer :: my_iqi, my_is, ig1, ig2, my_it, ierr, iq_ibz, itau, spin, it0, iw, cnt
3810 : : integer :: ndat, idat, loc1_size, loc2_size, batch_size, from_space, units(2)
3811 : : real(dp) :: cpu, wall, gflops !, min_abs_err, max_abs_err
3812 : : complex(dp) :: cval
3813 : : logical :: sum_spins_, do_chi_fit
3814 : : !arrays
3815 : 0 : integer :: mask_qibz(gwr%nqibz)
3816 : 0 : real(dp), contiguous, pointer :: weights_ptr(:,:)
3817 : 0 : real(dp),allocatable :: beta_r(:,:)
3818 : 0 : complex(dp) :: wgt_globmy(gwr%ntau, gwr%my_ntau) ! Complex instead of real to be able to call ZGEMM.
3819 : 0 : complex(dp),allocatable :: cwork_myit(:,:,:), glob_cwork(:,:,:), alpha_c(:,:)
3820 : 0 : type(__slkmat_t), pointer :: mats(:)
3821 : : ! *************************************************************************
3822 : :
3823 [ # # ]: 0 : units = [std_out, ab_out]
3824 : :
3825 : : ABI_NVTX_START_RANGE(NVTX_GWR_COS_TRANSFORM)
3826 : 0 : call cwtime(cpu, wall, gflops, "start")
3827 : :
3828 [ # # ]: 0 : sum_spins_ = .False.; if (present(sum_spins)) sum_spins_ = sum_spins
3829 : :
3830 : 0 : call wrtout(std_out, sjoin(" Performing cosine transform. what:", what, ", mode:", mode))
3831 [ # # # # ]: 0 : mask_qibz = 0; mask_qibz(gwr%my_qibz_inds(:)) = 1
3832 : :
3833 : : ! Target weights depending on mode.
3834 : 0 : select case(mode)
3835 : : case ("iw2t")
3836 : : ! From omega to tau
3837 : 0 : from_space = W_SPACE
3838 [ # # ]: 0 : if (what == "tchi") then
3839 [ # # ]: 0 : ABI_CHECK(gwr%tchi_space == "iomega", sjoin("mode:", mode, "with what:", what, "and tchi_space:", gwr%tchi_space))
3840 : 0 : gwr%tchi_space = "itau"
3841 : : end if
3842 [ # # ]: 0 : if (what == "wc") then
3843 [ # # ]: 0 : ABI_CHECK(gwr%wc_space == "iomega", sjoin("mode:", mode, "with what:", what, "and wc_space:", gwr%wc_space))
3844 : 0 : gwr%wc_space = "itau"
3845 : : end if
3846 : 0 : weights_ptr => gwr%cosft_tw
3847 : :
3848 : : case ("it2w")
3849 : : ! From tau to omega
3850 : 0 : from_space = TAU_SPACE
3851 [ # # ]: 0 : if (what == "tchi") then
3852 [ # # ]: 0 : ABI_CHECK(gwr%tchi_space == "itau", sjoin("mode:", mode, " with what:", what, "and tchi_space:", gwr%tchi_space))
3853 : 0 : gwr%tchi_space = "iomega"
3854 : : end if
3855 [ # # ]: 0 : if (what == "wc") then
3856 [ # # ]: 0 : ABI_CHECK(gwr%wc_space == "itau", sjoin("mode:", mode, " with what:", what, "and wc_space:", gwr%wc_space))
3857 : 0 : gwr%wc_space = "iomega"
3858 : : end if
3859 : 0 : weights_ptr => gwr%cosft_wt
3860 : :
3861 : : case default
3862 [ # # # ]: 0 : ABI_ERROR(sjoin("Wrong mode:", mode))
3863 : : end select
3864 : :
3865 : : ! Extract my weights from global array.
3866 [ # # ]: 0 : do my_it=1,gwr%my_ntau
3867 : 0 : itau = gwr%my_itaus(my_it)
3868 [ # # ]: 0 : do iw=1,gwr%ntau
3869 : 0 : wgt_globmy(iw, my_it) = weights_ptr(iw, itau)
3870 : : end do
3871 : : end do
3872 : :
3873 : 0 : do_chi_fit = (iand(gwr%dtset%gwr_fit, CHI_FIT) /= 0)
3874 [ # # ]: 0 : if (do_chi_fit) then
3875 : 0 : call wrtout(units, " Activating fit of matrix elements in tau/iw space")
3876 : : end if
3877 : :
3878 : : ! Perform inhomogeneous FT in parallel.
3879 [ # # ]: 0 : do my_is=1,gwr%my_nspins
3880 : 0 : spin = gwr%my_spins(my_is)
3881 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
3882 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
3883 : 0 : associate (desc_q => gwr%tchi_desc_qibz(iq_ibz))
3884 : :
3885 : 0 : mats => null()
3886 : 0 : if (what == "tchi") mats => gwr%tchi_qibz(iq_ibz, :, spin)
3887 [ # # ]: 0 : if (what =="wc") mats => gwr%wc_qibz(iq_ibz, :, spin)
3888 [ # # ]: 0 : ABI_CHECK(associated(mats), sjoin("Invalid value for what:", what))
3889 : :
3890 : : ! Use the first itau index to get the size of the local buffer.
3891 : : ! Block over ig2 to reduce the number of MPI calls and take advantage of ZGEMM.
3892 : 0 : it0 = gwr%my_itaus(1)
3893 : 0 : loc1_size = mats(it0)%size_local(1)
3894 : 0 : loc2_size = mats(it0)%size_local(2)
3895 : :
3896 : : ! batch_size in terms of columns
3897 : : ! TODO: Determine batch_size automatically to avoid going OOM
3898 : 0 : batch_size = 48
3899 : : !batch_size = loc2_size
3900 : :
3901 [ # # # # : 0 : ABI_MALLOC(cwork_myit, (gwr%my_ntau, loc1_size, batch_size))
# # # # #
# # # # #
# # # # ]
3902 [ # # # # : 0 : ABI_MALLOC(glob_cwork, (gwr%ntau, loc1_size, batch_size))
# # # # #
# # # # #
# # # # #
# ]
3903 : :
3904 [ # # ]: 0 : if (do_chi_fit) then
3905 : : ! Allocate coefficients for the fit.
3906 [ # # # # : 0 : ABI_MALLOC(beta_r, (loc1_size, batch_size))
# # # # #
# # # # #
# # ]
3907 [ # # # # : 0 : ABI_MALLOC(alpha_c, (loc1_size, batch_size))
# # # # #
# # # # #
# # ]
3908 : : end if
3909 : :
3910 [ # # # # ]: 0 : do ig2=1,mats(it0)%size_local(2), batch_size
3911 : 0 : ndat = blocked_loop(ig2, mats(it0)%size_local(2), batch_size)
3912 : :
3913 : : ! TODO
3914 : : ! When fit mode is activated, collect all tau/omega points for this set of (g1, g2) inside tau_comm
3915 : : ! Each MPI rank performs the fit locally using the first point and all the points treated by the rank.
3916 : : ! compute loss functions of all the fits and find the one leading to the minimum loss.
3917 [ # # ]: 0 : if (do_chi_fit) then
3918 [ # # # # : 0 : glob_cwork = zero
# # ]
3919 [ # # ]: 0 : do idat=1,ndat
3920 [ # # ]: 0 : do my_it=1,gwr%my_ntau
3921 : 0 : itau = gwr%my_itaus(my_it)
3922 [ # # ]: 0 : do ig1=1,mats(it0)%size_local(1)
3923 : 0 : glob_cwork(itau, ig1, idat) = mats(itau)%buffer_cplx(ig1, ig2+idat-1)
3924 : : end do
3925 : : end do
3926 : : end do
3927 : 0 : call xmpi_sum(glob_cwork, gwr%tau_comm%value, ierr)
3928 : :
3929 : : ! Start the fit
3930 [ # # # # : 0 : cnt = 0; beta_r = zero; alpha_c = zero
# # # # ]
3931 [ # # ]: 0 : do idat=1,ndat
3932 [ # # ]: 0 : do ig1=1,mats(it0)%size_local(1)
3933 [ # # ]: 0 : cnt = cnt + 1; if (gwr%tau_comm%skip(cnt)) cycle ! MPI parallelism inside tau_comm
3934 [ # # ]: 0 : if (from_space == TAU_SPACE) then
3935 : : call fit_tau_exp(gwr%ntau, gwr%tau_mesh, gwr%tau_wgs, glob_cwork(:,ig1,idat), &
3936 : 0 : alpha_c(ig1,idat), beta_r(ig1,idat), ierr)
3937 [ # # ]: 0 : else if (from_space == W_SPACE) then
3938 : : call fit_iomega(gwr%ntau, gwr%iw_mesh, gwr%iw_wgs, glob_cwork(:,ig1,idat), &
3939 : 0 : alpha_c(ig1,idat), beta_r(ig1,idat), ierr)
3940 : : else
3941 : 0 : ABI_ERROR(sjoin("Invalid from_space:", itoa(from_space)))
3942 : : end if
3943 : : !if (from_space == W_SPACE) print *, "my_it, alpha, beta", alpha_c(ig1,idat), beta_r(ig1,idat)
3944 : : end do ! ig1
3945 : : end do ! idat
3946 : 0 : call xmpi_sum(alpha_c, gwr%tau_comm%value, ierr)
3947 : 0 : call xmpi_sum(beta_r, gwr%tau_comm%value, ierr)
3948 : : end if ! do_chi_fit
3949 : :
3950 : : ! Extract (g1, g2) matrix elements as a function of tau/omega
3951 : : !!$OMP PARALLEL DO PRIVATE(itau, cval) COLLAPSE(2)
3952 [ # # ]: 0 : do idat=1,ndat
3953 [ # # ]: 0 : do my_it=1,gwr%my_ntau
3954 : 0 : itau = gwr%my_itaus(my_it)
3955 : 0 : cval = zero
3956 [ # # ]: 0 : do ig1=1,mats(it0)%size_local(1)
3957 [ # # ]: 0 : if (do_chi_fit) then
3958 : : ! Evaluate the fit and remove it from the signal.
3959 [ # # ]: 0 : if (from_space == TAU_SPACE) then
3960 : 0 : cval = fit_tau_exp_eval("func", gwr%tau_mesh(itau), alpha_c(ig1,idat), beta_r(ig1,idat))
3961 [ # # ]: 0 : else if (from_space == W_SPACE) then
3962 : 0 : cval = fit_iomega_eval("func", gwr%iw_mesh(itau), alpha_c(ig1,idat), beta_r(ig1,idat))
3963 : : end if
3964 : : if (from_space == W_SPACE .and. any(my_it == [1, gwr%my_ntau])) then
3965 : : !if (from_space == TAU_SPACE .and. any(my_it == [1, gwr%my_ntau])) then
3966 : : !print * "beta_r, alpha:", beta_r(ig1,idat), alpha_c(ig1,idat)
3967 : : !write(*, "(a,i3,1x, *(es12.5,2x))") "my_it abs_diff_1", my_it, abs(cval - mats(itau)%buffer_cplx(ig1, ig2+idat-1)), &
3968 : : ! cval, mats(itau)%buffer_cplx(ig1, ig2+idat-1)
3969 : : end if
3970 : : end if
3971 : 0 : cwork_myit(my_it, ig1, idat) = mats(itau)%buffer_cplx(ig1, ig2+idat-1) - cval
3972 : : end do
3973 : : end do
3974 : : end do
3975 : :
3976 : : ! Compute contribution to itau matrix,
3977 : : call ZGEMM("N", "N", gwr%ntau, loc1_size*ndat, gwr%my_ntau, cone, &
3978 : 0 : wgt_globmy, gwr%ntau, cwork_myit, gwr%my_ntau, czero, glob_cwork, gwr%ntau)
3979 : :
3980 : 0 : call xmpi_sum(glob_cwork, gwr%tau_comm%value, ierr)
3981 : :
3982 : : ! Update my local (g1, g2) entry to have it in imaginary-frequency.
3983 : : !!$OMP PARALLEL DO PRIVATE(itau, cval) COLLAPSE(2)
3984 [ # # ]: 0 : do idat=1,ndat
3985 [ # # ]: 0 : do my_it=1,gwr%my_ntau
3986 : 0 : itau = gwr%my_itaus(my_it)
3987 : 0 : cval = zero
3988 [ # # ]: 0 : do ig1=1,mats(it0)%size_local(1)
3989 : :
3990 [ # # ]: 0 : if (do_chi_fit) then
3991 : : ! Add Fourier transform of the fitted model.
3992 [ # # ]: 0 : if (from_space == TAU_SPACE) then
3993 : 0 : cval = fit_tau_exp_eval("ft", gwr%iw_mesh(itau), alpha_c(ig1,idat), beta_r(ig1,idat))
3994 [ # # ]: 0 : else if (from_space == W_SPACE) then
3995 : 0 : cval = fit_iomega_eval("ft", gwr%tau_mesh(itau), alpha_c(ig1,idat), beta_r(ig1,idat))
3996 : : end if
3997 : : !if (from_space == W_SPACE .and. my_it == 1) then
3998 : : !if (from_space == TAU_SPACE .and. my_it == 1) then
3999 : : ! !print *, "beta_r, alpha:", beta_r(ig1,idat), alpha_c(ig1,idat)
4000 : : ! print *, "my_it, abs_diff_2", my_it, abs(cval - mats(itau)%buffer_cplx(ig1, ig2+idat-1)), &
4001 : : ! cval - mats(itau)%buffer_cplx(ig1, ig2+idat-1)
4002 : : !end if
4003 : : end if
4004 : : !if (from_space == TAU_SPACE) then
4005 : : !if (from_space == W_SPACE) then
4006 : : !write(200, *)"mats:", mats(itau)%buffer_cplx(ig1, ig2+idat-1)
4007 : : !write(300, *)"cval", cval
4008 : : !end if
4009 : :
4010 : 0 : mats(itau)%buffer_cplx(ig1, ig2+idat-1) = glob_cwork(itau, ig1, idat) + cval
4011 : : end do ! ig1
4012 : : end do ! my_it
4013 : : end do ! idat
4014 : :
4015 : : end do ! ig2
4016 : :
4017 [ # # ]: 0 : ABI_FREE(cwork_myit)
4018 [ # # ]: 0 : ABI_FREE(glob_cwork)
4019 [ # # ]: 0 : ABI_SFREE(alpha_c)
4020 [ # # # # ]: 0 : ABI_SFREE(beta_r)
4021 : : end associate
4022 : : end do ! my_iqi
4023 : : end do ! my_is
4024 : : !stop
4025 : :
4026 [ # # ]: 0 : if (sum_spins_) then ! gwr%nsppol == 2 .and.
4027 : : ! Sum over spin channels.
4028 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
4029 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
4030 [ # # ]: 0 : do my_is=1,gwr%my_nspins
4031 : 0 : spin = gwr%my_spins(my_is)
4032 : 0 : mats => null()
4033 [ # # ]: 0 : if (what == "tchi") mats => gwr%tchi_qibz(iq_ibz,:,spin)
4034 : : !if (what =="wc") mats => gwr%wc_qibz(iq_ibz, :, spin)
4035 [ # # ]: 0 : ABI_CHECK(associated(mats), sjoin("Invalid value for what:", what))
4036 : :
4037 [ # # ]: 0 : do my_it=1,gwr%my_ntau
4038 : 0 : itau = gwr%my_itaus(my_it)
4039 : :
4040 [ # # ]: 0 : if (gwr%nsppol == 1 .and. gwr%nspinor == 1) then
4041 [ # # # # ]: 0 : mats(itau)%buffer_cplx = two * mats(itau)%buffer_cplx
4042 : :
4043 [ # # ]: 0 : else if (gwr%nsppol == 2) then
4044 [ # # ]: 0 : if (gwr%spin_comm%nproc > 1) then
4045 : : ! Spins are distributed thus we have to sum them.
4046 : 0 : call xmpi_sum(mats(itau)%buffer_cplx, gwr%spin_comm%value, ierr)
4047 : : else
4048 : : ! Spins are not distributed. This should happen only in sequential.
4049 [ # # ]: 0 : if (spin == 1) then
4050 [ # # # # : 0 : mats(itau)%buffer_cplx = mats(itau)%buffer_cplx + gwr%tchi_qibz(iq_ibz,itau,spin+1)%buffer_cplx
# # ]
4051 [ # # # # : 0 : gwr%tchi_qibz(iq_ibz,itau,spin+1)%buffer_cplx = mats(itau)%buffer_cplx
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4052 : : end if
4053 : : end if
4054 : : end if
4055 : :
4056 : : end do ! my_it
4057 : : end do ! my_is
4058 : : end do ! my_iqi
4059 : : end if
4060 : :
4061 : : ABI_NVTX_END_RANGE()
4062 : 0 : call cwtime_report(" gwr_cos_transform:", cpu, wall, gflops)
4063 : :
4064 [ # # # # : 0 : end subroutine gwr_cos_transform
# # ]
4065 : : !!***
4066 : :
4067 : : !!****f* m_gwr/fit_tau_exp
4068 : : !! NAME
4069 : : !!
4070 : : !! FUNCTION
4071 : : !! Fit values in imaginary time using A exp^{-b t} with A complex and b real and > 0.
4072 : : !! The fit passes through the first tau point, the second point is selected by
4073 : : !! minimizing the "distance" between the fit and the ab-initio results cvals.
4074 : : !!
4075 : : !! b = -\frac{\ln(y_n / y_0)}{\tau_n - \tau_0},
4076 : : !! A = y_0 e^{b \tau_0}
4077 : : !!
4078 : : !! SOURCE
4079 : :
4080 : 0 : subroutine fit_tau_exp(ntau, tau_mesh, tau_wgs, cvals, alpha_c, beta_r, ierr)
4081 : :
4082 : : !Arguments ------------------------------------
4083 : : integer,intent(in) :: ntau
4084 : : real(dp),intent(in) :: tau_mesh(ntau), tau_wgs(ntau)
4085 : : complex(dp),intent(in) :: cvals(ntau)
4086 : : complex(dp),intent(out) :: alpha_c
4087 : : real(dp),intent(out) :: beta_r
4088 : : integer,intent(out) :: ierr
4089 : :
4090 : : !Local variables-------------------------------
4091 : : integer :: ii
4092 : : real(dp) :: loss, min_loss, my_beta_r
4093 : 0 : complex(dp) :: cfit(ntau), zz, my_alpha_c
4094 : : ! *************************************************************************
4095 : :
4096 : 0 : min_loss = huge(one); alpha_c = zero; beta_r = zero
4097 [ # # ]: 0 : do ii=2,ntau
4098 : : ! Find my_beta_r. Note that we take the real part of the log to avoid oscillatory behaviour in the exp.
4099 : 0 : zz = -log(cvals(ii) / cvals(1)) / (tau_mesh(ii) - tau_mesh(1))
4100 : 0 : my_beta_r = real(zz)
4101 : 0 : my_alpha_c = cvals(1) * exp(+my_beta_r * tau_mesh(1))
4102 : : ! Compute loss function.
4103 [ # # ]: 0 : cfit(:) = my_alpha_c * exp(-my_beta_r * tau_mesh)
4104 [ # # ]: 0 : loss = sum(tau_wgs * abs(cvals - cfit)**2)
4105 [ # # ]: 0 : if (loss < min_loss) then
4106 : 0 : min_loss = loss; alpha_c = my_alpha_c; beta_r = my_beta_r
4107 : : end if
4108 : : end do
4109 : :
4110 : : ! If something goes wrong, disable the fit.
4111 : 0 : ierr = 0
4112 [ # # ]: 0 : if (beta_r <= tol12) then
4113 : 0 : alpha_c = zero; beta_r = tol6; ierr = 1
4114 : : end if
4115 : :
4116 : 0 : end subroutine fit_tau_exp
4117 : : !!***
4118 : :
4119 : : !!****f* m_gwr/fit_tau_exp_eval
4120 : : !! NAME
4121 : : !!
4122 : : !! FUNCTION
4123 : : !! Exalute tau fit or it's Fourier transform.
4124 : : !!
4125 : : !! SOURCE
4126 : :
4127 : 0 : pure complex(dp) function fit_tau_exp_eval(what, xx, alpha_c, beta_r) result(cval)
4128 : :
4129 : : !Arguments ------------------------------------
4130 : : character(len=*),intent(in) :: what
4131 : : real(dp),intent(in) :: xx, beta_r
4132 : : complex(dp),intent(in) :: alpha_c
4133 : : ! *************************************************************************
4134 : :
4135 : 0 : select case (what)
4136 : : case ("func")
4137 : 0 : cval = alpha_c * exp(-beta_r * xx)
4138 : : case ("ft")
4139 : : ! \mathcal{F}\{A e^{-b |t|} \}(\omega) = \frac{2A b}{b^2 + \omega^2}
4140 : : !cval = (two * alpha_c * beta_r) / (beta_r**2 + xx**2)
4141 : : ! Cosine-transform.
4142 : 0 : cval = (alpha_c * two * beta_r) / (beta_r**2 + xx**2)
4143 : : case default
4144 [ # # # ]: 0 : cval = huge(one)
4145 : : end select
4146 : :
4147 : 0 : end function fit_tau_exp_eval
4148 : : !!***
4149 : :
4150 : : !!****f* m_gwr/fit_iomega
4151 : : !! NAME
4152 : : !!
4153 : : !! FUNCTION
4154 : : !! To fit the function
4155 : : !!
4156 : : !! f(\omega) = \frac{A}{b^2 + \omega^2}
4157 : : !!
4158 : : !! to pass through two given points (\omega_1, y_1) and (\omega_2, y_2), follow these steps.
4159 : : !!
4160 : : !! A = \frac{y_1 y_2 (\omega_2^2 - \omega_1^2)}{y_1 - y_2}.
4161 : : !! b^2 = \frac{y_2 \omega_2^2 - y_1 \omega_1^2}{y_1 - y_2},
4162 : : !!
4163 : : !! SOURCE
4164 : :
4165 : 0 : subroutine fit_iomega(ntau, iw_mesh, iw_wgs, cvals, alpha_c, beta_r, ierr)
4166 : :
4167 : : !Arguments ------------------------------------
4168 : : integer,intent(in) :: ntau
4169 : : real(dp),intent(in) :: iw_mesh(ntau), iw_wgs(ntau)
4170 : : complex(dp),intent(in) :: cvals(ntau)
4171 : : complex(dp),intent(out) :: alpha_c
4172 : : real(dp),intent(out) :: beta_r
4173 : : integer,intent(out) :: ierr
4174 : :
4175 : : !Local variables-------------------------------
4176 : : integer :: ii
4177 : : real(dp) :: loss, min_loss, w0, wn, b2 ! my_beta_r,
4178 : 0 : complex(dp) :: my_alpha_c, cfit(ntau), f0, fn ! zz, b2_cplx,
4179 : : ! *************************************************************************
4180 : :
4181 : 0 : min_loss = huge(one); w0 = iw_mesh(1); f0 = cvals(1); alpha_c = czero; beta_r = zero
4182 : :
4183 [ # # ]: 0 : do ii=2,ntau
4184 : : ! Find alpha_c and beta_r
4185 : 0 : wn = iw_mesh(ii); fn = cvals(ii)
4186 : : !b2_cplx = (f0*w0**2 - fn*wn**2) / (fn - f0)
4187 : : !b2 = real(b2)
4188 : 0 : b2 = (real(f0) * w0**2 - real(fn) * wn**2) / (real(fn) - real(f0))
4189 : : !print *, "b2:", b2
4190 : :
4191 [ # # ]: 0 : if (b2 <= tol12) then
4192 : : b2 = tol12; my_alpha_c = zero
4193 : : else
4194 : : !my_alpha_c = f0*fn * (wn**2 - w0**2) / (f0 - fn)
4195 : : !print *, "b2:", b2
4196 : : !my_alpha_c = f0 *((fn*wn**2 - f0*w0**2)/(f0 - fn) + w0**2)
4197 : 0 : my_alpha_c = f0 * (b2 + w0**2)
4198 : : end if
4199 : :
4200 : : ! Compute loss function.
4201 [ # # ]: 0 : cfit(:) = my_alpha_c / (b2 + iw_mesh**2)
4202 [ # # ]: 0 : loss = sum(iw_wgs * abs(cvals - cfit)**2)
4203 [ # # ]: 0 : if (loss < min_loss) then
4204 : 0 : min_loss = loss; alpha_c = my_alpha_c; beta_r = sqrt(b2)
4205 : : end if
4206 : : end do
4207 : :
4208 : : ! DEBUG: disable the fit
4209 : : !beta_r = zero; alpha_c = zero
4210 : :
4211 [ # # ]: 0 : ierr = 0; if (b2 <= tol12) ierr = 1
4212 : :
4213 : : !if (alpha_c /= zero) then
4214 : : ! print *, "beta_r, alpha_c", beta_r, alpha_c, min_loss
4215 : : !end if
4216 : :
4217 : : ! If something goes wrong, disable the fit.
4218 : : !beta_r = zero; alpha_c = zero
4219 : : !if ((my_beta_r) > zero) then
4220 : : ! beta_r = my_beta_r
4221 : : ! alpha_c = my_alpha_c
4222 : : !end if
4223 : :
4224 : 0 : end subroutine fit_iomega
4225 : : !!***
4226 : :
4227 : : !!****f* m_gwr/fit_iomega_eval
4228 : : !! NAME
4229 : : !!
4230 : : !! FUNCTION
4231 : : !!
4232 : : !! SOURCE
4233 : :
4234 : 0 : pure complex(dp) function fit_iomega_eval(what, xx, alpha_c, beta_r) result(cval)
4235 : :
4236 : : !Arguments ------------------------------------
4237 : : character(len=*),intent(in) :: what
4238 : : real(dp),intent(in) :: xx, beta_r
4239 : : complex(dp),intent(in) :: alpha_c
4240 : : ! *************************************************************************
4241 : :
4242 : 0 : select case (what)
4243 : : case ("func")
4244 : 0 : cval = alpha_c / (beta_r**2 + xx**2)
4245 : : case ("ft")
4246 : 0 : cval = zero
4247 [ # # ]: 0 : if (alpha_c /= zero) then
4248 : : !cval = alpha_c * exp(-beta_r * abs(xx))
4249 : : ! TODO: check sign in prefactor
4250 : : !cval = (alpha_c / (two * beta_r)) * exp(-beta_r * abs(xx))
4251 : : !cval = - (alpha_c / (two * beta_r)) * exp(-beta_r * abs(xx))
4252 : : ! Cosine-transform
4253 : 0 : cval = (alpha_c / (two * beta_r)) * exp(-beta_r * abs(xx))
4254 : : end if
4255 : :
4256 : : case default
4257 [ # # # ]: 0 : cval = huge(one)
4258 : : end select
4259 : :
4260 : 0 : end function fit_iomega_eval
4261 : : !!***
4262 : :
4263 : : !----------------------------------------------------------------------
4264 : :
4265 : : !!****f* m_gwr/desc_init
4266 : : !! NAME
4267 : : !! desc_init
4268 : : !!
4269 : : !! FUNCTION
4270 : : !! Initialize the descriptor.
4271 : : !!
4272 : : !! INPUTS
4273 : : !!
4274 : : !! OUTPUT
4275 : : !!
4276 : : !! SOURCE
4277 : :
4278 : 0 : subroutine desc_init(desc, kk, istwfk, ecut, gwr, kin_sorted, rot)
4279 : :
4280 : : !Arguments ------------------------------------
4281 : : class(desc_t),intent(inout) :: desc
4282 : : real(dp),intent(in) :: kk(3)
4283 : : integer,intent(in) :: istwfk
4284 : : real(dp),intent(in) :: ecut
4285 : : class(gwr_t),intent(in) :: gwr
4286 : : logical,optional,intent(in) :: kin_sorted, rot
4287 : :
4288 : : !Local variables-------------------------------
4289 : : integer :: ig, ig1, ig2, itim, isym, istep_forward, istep_backward, grot(3)
4290 : : ! character(len=256) :: msg
4291 : : logical :: found, rot__
4292 : 0 : real(dp),allocatable :: gnorm(:)
4293 : 0 : integer,allocatable :: igvec(:)
4294 : : ! *************************************************************************
4295 : :
4296 [ # # ]: 0 : desc%kin_sorted = .False.; if (present(kin_sorted)) desc%kin_sorted = kin_sorted
4297 [ # # ]: 0 : rot__ = .False.; if (present(rot)) rot__ = rot
4298 : 0 : desc%istwfk = istwfk
4299 [ # # ]: 0 : call get_kg(kk, desc%istwfk, ecut, gwr%cryst%gmet, desc%npw, desc%gvec, kin_sorted=desc%kin_sorted)
4300 : :
4301 [ # # # # : 0 : ABI_MALLOC(desc%gbound, (2 * gwr%g_mgfft + 8, 2))
# # # # #
# # # # #
# # # # ]
4302 : 0 : call sphereboundary(desc%gbound, desc%istwfk, desc%gvec, gwr%g_mgfft, desc%npw)
4303 : :
4304 : : ! Find the index of g = 0.
4305 : 0 : desc%ig0 = -1
4306 [ # # ]: 0 : do ig=1,desc%npw
4307 [ # # # # : 0 : if (all(desc%gvec(:,ig) == 0)) then
# # ]
4308 : 0 : desc%ig0 = ig; exit
4309 : : end if
4310 : : end do
4311 : :
4312 [ # # ]: 0 : if (rot__) then
4313 [ # # # # : 0 : ABI_ICALLOC(desc%rottb, (desc%npw, gwr%cryst%timrev, gwr%cryst%nsym))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
4314 [ # # # # : 0 : ABI_ICALLOC(desc%rottbm1, (desc%npw, gwr%cryst%timrev, gwr%cryst%nsym))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
4315 [ # # # # : 0 : ABI_CALLOC(desc%phmGt, (desc%npw, gwr%cryst%nsym))
# # # # #
# # # # #
# # # # #
# # # ]
4316 [ # # # # : 0 : ABI_CALLOC(desc%phmSGt, (desc%npw, gwr%cryst%nsym))
# # # # #
# # # # #
# # # # #
# # # ]
4317 : : ! Fast sort for norm(desc%gvec) and store indices in igvec.
4318 [ # # # # : 0 : ABI_MALLOC(gnorm, (desc%npw))
# # # # #
# # # ]
4319 [ # # # # : 0 : ABI_MALLOC(igvec, (desc%npw))
# # # # #
# # # ]
4320 : :
4321 [ # # ]: 0 : do ig=1,desc%npw
4322 : 0 : igvec(ig) = ig
4323 : 0 : gnorm(ig) = normv(desc%gvec(:,ig), gwr%cryst%gmet, "G") ** 2
4324 : : end do
4325 : :
4326 : 0 : call sort_dp(desc%npw, gnorm, igvec, tol14)
4327 : :
4328 [ # # ]: 0 : ABI_FREE(gnorm)
4329 : :
4330 [ # # ]: 0 : do ig1=1,desc%npw
4331 [ # # ]: 0 : do itim=1,gwr%cryst%timrev
4332 [ # # ]: 0 : do isym=1,gwr%cryst%nsym
4333 [ # # # # : 0 : grot=(3-2*itim)*MATMUL(gwr%cryst%symrec(:,:,isym),desc%gvec(:,ig1))
# # # # #
# # # ]
4334 : 0 : found=.FALSE.
4335 : : ! * Loop on the shell of ig1 to speed up the search.
4336 : : istep_forward = ig1; istep_backward = ig1
4337 [ # # # # ]: 0 : do while (istep_forward <= desc%npw .or. istep_backward >= 1)
4338 [ # # ]: 0 : if (istep_forward <= desc%npw) then
4339 : 0 : ig2 = igvec(istep_forward)
4340 [ # # # # : 0 : if (ALL(ABS(grot(:)-desc%gvec(:,ig2))==0)) then
# # ]
4341 : 0 : found=.TRUE.
4342 : 0 : desc%rottb(ig1,itim,isym)=ig2
4343 : 0 : desc%rottbm1(ig2,itim,isym)=ig1
4344 [ # # ]: 0 : desc%phmGt(ig1,isym) = exp(-j_dpc*two_pi*DOT_PRODUCT(desc%gvec(:,ig1), gwr%cryst%tnons(:,isym)))
4345 [ # # ]: 0 : desc%phmSGt(ig1,isym) = exp(-j_dpc*two_pi*DOT_PRODUCT(grot(:), gwr%cryst%tnons(:,isym)))
4346 : 0 : exit
4347 : : end if
4348 : : end if
4349 [ # # ]: 0 : if (istep_backward >= 1) then
4350 : 0 : ig2 = igvec(istep_backward)
4351 [ # # # # : 0 : if (ALL(ABS(grot(:)-desc%gvec(:,ig2))==0)) then
# # ]
4352 : 0 : found=.TRUE.
4353 : 0 : desc%rottb(ig1,itim,isym)=ig2
4354 : 0 : desc%rottbm1(ig2,itim,isym)=ig1
4355 [ # # ]: 0 : desc%phmGt(ig1,isym) = exp(-j_dpc*two_pi*DOT_PRODUCT(desc%gvec(:,ig1), gwr%cryst%tnons(:,isym)))
4356 [ # # ]: 0 : desc%phmSGt(ig1,isym) = exp(-j_dpc*two_pi*DOT_PRODUCT(grot(:), gwr%cryst%tnons(:,isym)))
4357 : 0 : exit
4358 : : end if
4359 : : end if
4360 : 0 : istep_forward = istep_forward + 1
4361 : 0 : istep_backward = istep_backward - 1
4362 : : end do
4363 : : ! if (.not.found) then
4364 : : ! write(msg,'(3a,i5,a,i5,1x,2(3i10,a),a,i3,a,i3)')&
4365 : : ! 'G-shell not closed',ch10,&
4366 : : ! ' Initial G vector ',ig1,'/',desc%npw,desc%gvec(:,ig1),' Rotated G vector ',grot(:),ch10,&
4367 : : ! ' Through sym ',isym,' and itim ',itim
4368 : : ! ABI_ERROR(msg)
4369 : : ! end if
4370 : : end do ! itim
4371 : : end do ! isym
4372 : : end do ! ig1
4373 : :
4374 [ # # ]: 0 : ABI_FREE(igvec)
4375 : :
4376 : : end if ! rot__
4377 : :
4378 : 0 : end subroutine desc_init
4379 : : !!***
4380 : :
4381 : : !----------------------------------------------------------------------
4382 : :
4383 : : !!****f* m_gwr/desc_get_vc_sqrt
4384 : : !! NAME
4385 : : !! desc_get_vc_sqrt
4386 : : !!
4387 : : !! FUNCTION
4388 : : !! Compute square root of the Coulomb interaction vc(q,g).
4389 : : !!
4390 : : !! SOURCE
4391 : :
4392 : 0 : subroutine desc_get_vc_sqrt(desc, qpt, q_is_gamma, gwr, mode, comm)
4393 : :
4394 : : !Arguments ------------------------------------
4395 : : class(desc_t),intent(inout) :: desc
4396 : : real(dp),intent(in) :: qpt(3)
4397 : : logical, intent(in) :: q_is_gamma
4398 : : class(gwr_t),intent(in) :: gwr
4399 : : character(len=*),intent(in) :: mode
4400 : : integer,intent(in) :: comm
4401 : : ! *************************************************************************
4402 : :
4403 : : ABI_UNUSED([q_is_gamma])
4404 : :
4405 [ # # # # ]: 0 : if (mode == "epsilon" .or. .not. gwr%has_vcgen_sigma) then
4406 [ # # ]: 0 : if (allocated(desc%vc_sqrt_eps)) return
4407 [ # # # # : 0 : ABI_MALLOC(desc%vc_sqrt_eps, (desc%npw))
# # # # #
# # # #
# ]
4408 : 0 : call gwr%vcgen_eps%get_vc_sqrt(qpt, desc%npw, desc%gvec, gwr%q0, gwr%cryst, desc%vc_sqrt_eps, comm)
4409 : :
4410 [ # # ]: 0 : else if (mode == "sigma") then
4411 [ # # ]: 0 : if (allocated(desc%vc_sqrt_sigma)) return
4412 [ # # # # : 0 : ABI_MALLOC(desc%vc_sqrt_sigma, (desc%npw))
# # # # #
# # # #
# ]
4413 : 0 : call gwr%vcgen_sigma%get_vc_sqrt(qpt, desc%npw, desc%gvec, gwr%q0, gwr%cryst, desc%vc_sqrt_sigma, comm)
4414 : :
4415 : : else
4416 : 0 : ABI_ERROR(sjoin("Invalid mode:", mode))
4417 : : end if
4418 : :
4419 : : end subroutine desc_get_vc_sqrt
4420 : : !!***
4421 : :
4422 : : !----------------------------------------------------------------------
4423 : :
4424 : : !!****f* m_gwr/desc_copy
4425 : : !! NAME
4426 : : !! desc_copy
4427 : : !!
4428 : : !! FUNCTION
4429 : : !! Copy object
4430 : : !! NB: cannot use obj1 = obj2 syntax because ABINIT memory-leak detector
4431 : : !! won't see the allocation automatically performed by the compiler.
4432 : : !!
4433 : : !! SOURCE
4434 : :
4435 [ # # ]: 0 : subroutine desc_copy(in_desc, new_desc)
4436 : :
4437 : : !Arguments ------------------------------------
4438 : : class(desc_t),intent(in) :: in_desc
4439 : : class(desc_t),intent(out) :: new_desc
4440 : : ! *************************************************************************
4441 : :
4442 : 0 : call new_desc%free()
4443 : :
4444 : 0 : new_desc%istwfk = in_desc%istwfk
4445 : 0 : new_desc%npw = in_desc%npw
4446 : 0 : new_desc%ig0 = in_desc%ig0
4447 : 0 : new_desc%kin_sorted = in_desc%kin_sorted
4448 : :
4449 [ # # ]: 0 : call alloc_copy(in_desc%gvec, new_desc%gvec)
4450 [ # # ]: 0 : call alloc_copy(in_desc%gbound, new_desc%gbound)
4451 [ # # # # ]: 0 : if (allocated(in_desc%vc_sqrt_eps)) call alloc_copy(in_desc%vc_sqrt_eps, new_desc%vc_sqrt_eps)
4452 [ # # # # ]: 0 : if (allocated(in_desc%vc_sqrt_sigma)) call alloc_copy(in_desc%vc_sqrt_sigma, new_desc%vc_sqrt_sigma)
4453 : :
4454 [ # # ]: 0 : if (allocated(in_desc%g2box)) then
4455 [ # # ]: 0 : call alloc_copy(in_desc%g2box, new_desc%g2box)
4456 [ # # ]: 0 : new_desc%cached_sc_ngfft = in_desc%cached_sc_ngfft
4457 : : end if
4458 : :
4459 : 0 : end subroutine desc_copy
4460 : : !!***
4461 : :
4462 : : !----------------------------------------------------------------------
4463 : :
4464 : : !!****f* m_gwr/desc_to_scbox
4465 : : !! NAME
4466 : : !! desc_to_scbox
4467 : : !!
4468 : : !! FUNCTION
4469 : : !! Insert cg_k array defined on the k-centered g-sphere with npw vectors inside the FFT box.
4470 : : !! The main difference wrt to sphere is that cfft is not initialized to zero. See notes below.
4471 : : !!
4472 : : !! INPUTS
4473 : : !! sc_ngfft:
4474 : : !! n1,n2,n3=physical dimension of the FFT box
4475 : : !! n4,n5,n6=memory dimension of cfft
4476 : : !! npw=number of G vectors in basis at this k point
4477 : : !! ndat=number of items to process
4478 : : !! cg(npw*ndat)= contains values for npw G vectors in basis sphere
4479 : : !!
4480 : : !! OUTPUT
4481 : : !! cfft(n4,n5,n6*ndat) = array on FFT box filled with cg data
4482 : : !! Note that cfft is intent(inout) so that we can add contributions from different k-points.
4483 : : !!
4484 : : !! SOURCE
4485 : :
4486 : 0 : subroutine desc_to_scbox(desc, kk, ngkpt, sc_ngfft, ndat, cg, cfft)
4487 : :
4488 : : !Arguments ------------------------------------
4489 : : !scalars
4490 : : class(desc_t),intent(inout) :: desc
4491 : : real(dp),intent(in) :: kk(3)
4492 : : integer,intent(in) :: ngkpt(3)
4493 : : integer,intent(in) :: sc_ngfft(6), ndat
4494 : : !arrays
4495 : : complex(gwp),intent(in) :: cg(desc%npw, ndat)
4496 : : complex(gwp),intent(inout) :: cfft(sc_ngfft(4)*sc_ngfft(5)*sc_ngfft(6),ndat)
4497 : :
4498 : : !Local variables-------------------------------
4499 : : integer :: n1, n2, n3, n4, n5, n6, i1, i2, i3, idat, ipw, kg(3), gg(3), ifft, npw
4500 : : logical :: compute_mapping
4501 : : !real(dp) :: tsec(2)
4502 : : ! *************************************************************************
4503 : :
4504 : : ! TODO: Add op_type
4505 : : !call timab(1931, 1, tsec)
4506 : :
4507 : 0 : npw = desc%npw
4508 : 0 : n1 = sc_ngfft(1); n2 = sc_ngfft(2); n3 = sc_ngfft(3)
4509 : 0 : n4 = sc_ngfft(4); n5 = sc_ngfft(5); n6 = sc_ngfft(6)
4510 [ # # ]: 0 : gg = nint(kk * ngkpt)
4511 : :
4512 [ # # # # : 0 : compute_mapping = .not. allocated(desc%g2box) .or. any(desc%cached_sc_ngfft /= sc_ngfft(1:6))
# # # # ]
4513 : :
4514 : : ! FIXME This is not thread safe
4515 : : if (compute_mapping) then
4516 [ # # # # : 0 : ABI_REMALLOC(desc%g2box, (npw))
# # # # #
# # # # #
# # ]
4517 [ # # ]: 0 : desc%cached_sc_ngfft = sc_ngfft(1:6)
4518 [ # # ]: 0 : do ipw=1,npw
4519 [ # # ]: 0 : kg = gg + ngkpt * desc%gvec(:,ipw) ! k+g
4520 : 0 : i1 = modulo(kg(1), n1)
4521 : 0 : i2 = modulo(kg(2), n2)
4522 : 0 : i3 = modulo(kg(3), n3)
4523 : 0 : desc%g2box(ipw) = 1 + i1 + n4*(i2+i3*n5)
4524 : : end do
4525 : : end if
4526 : :
4527 : : !do ipw=1,npw
4528 : : ! if (any(desc%gvec(:,ipw) > sc_ngfft(1:3)/2) .or. any(desc%gvec(:,ipw) < -(sc_ngfft(1:3)-1)/2) ) then
4529 : : ! ABI_ERROR(sjoin(" The G-vector: ",ltoa(desc%gvec(:, ipw))," falls outside the FFT box. Increase boxcutmin (?)"))
4530 : : ! end if
4531 : : !end do
4532 : :
4533 : : ! Insert cg into cfft
4534 : : !$OMP PARALLEL DO PRIVATE(ifft) IF (ndat > 1)
4535 [ # # ]: 0 : do idat=1,ndat
4536 [ # # ]: 0 : do ipw=1,npw
4537 : 0 : ifft = desc%g2box(ipw)
4538 : 0 : cfft(ifft,idat) = cg(ipw,idat)
4539 : : end do
4540 : : end do
4541 : :
4542 : : !call timab(1931, 2, tsec)
4543 : :
4544 : 0 : end subroutine desc_to_scbox
4545 : : !!***
4546 : :
4547 : : !----------------------------------------------------------------------
4548 : :
4549 : : !!****f* m_gwr/desc_free
4550 : : !! NAME
4551 : : !! desc_free
4552 : : !!
4553 : : !! FUNCTION
4554 : : !! Free memory
4555 : : !!
4556 : : !! SOURCE
4557 : :
4558 : 0 : subroutine desc_free(desc)
4559 : :
4560 : : !Arguments ------------------------------------
4561 : : class(desc_t),intent(inout) :: desc
4562 : : ! *************************************************************************
4563 : :
4564 [ # # ]: 0 : ABI_SFREE(desc%gvec)
4565 [ # # ]: 0 : ABI_SFREE(desc%gbound)
4566 [ # # ]: 0 : ABI_SFREE(desc%vc_sqrt_eps)
4567 [ # # ]: 0 : ABI_SFREE(desc%vc_sqrt_sigma)
4568 [ # # ]: 0 : ABI_SFREE(desc%g2box)
4569 [ # # ]: 0 : ABI_SFREE(desc%rottb)
4570 [ # # ]: 0 : ABI_SFREE(desc%rottbm1)
4571 [ # # ]: 0 : ABI_SFREE(desc%phmGt)
4572 [ # # ]: 0 : ABI_SFREE(desc%phmSGt)
4573 [ # # ]: 0 : desc%cached_sc_ngfft = -1
4574 : :
4575 : 0 : end subroutine desc_free
4576 : : !!***
4577 : :
4578 : : !----------------------------------------------------------------------
4579 : :
4580 : : !!****f* m_gwr/gwr_print
4581 : : !! NAME
4582 : : !! gwr_print
4583 : : !!
4584 : : !! FUNCTION
4585 : : !! Print info on the gwr object.
4586 : : !!
4587 : : !! INPUTS
4588 : : !!
4589 : : !! SOURCE
4590 : :
4591 : 0 : subroutine gwr_print(gwr, units, header)
4592 : :
4593 : : !Arguments ------------------------------------
4594 : : class(gwr_t),intent(in) :: gwr
4595 : : integer,intent(in) :: units(:)
4596 : : character(len=*),optional,intent(in) :: header
4597 : :
4598 : : !Local variables-------------------------------
4599 : : integer :: ii
4600 : : character(len=500) :: msg
4601 : : type(yamldoc_t) :: ydoc
4602 : : ! *********************************************************************
4603 : :
4604 [ # # # # ]: 0 : msg = ' ==== Info on the gwr_t object ==== '; if (present(header)) msg=' ==== '//trim(adjustl(header))//' ==== '
4605 : 0 : call wrtout(units, msg)
4606 : :
4607 : 0 : ydoc = yamldoc_open('GWR_params') !, width=11, real_fmt='(3f8.3)')
4608 : 0 : call ydoc%add_string("gwr_task", gwr%dtset%gwr_task)
4609 : 0 : call ydoc%add_int("nband", gwr%dtset%nband(1))
4610 : 0 : call ydoc%add_int("ntau", gwr%ntau)
4611 : 0 : call ydoc%add_int1d("ngkpt", gwr%ngkpt)
4612 : 0 : call ydoc%add_int1d("ngqpt", gwr%ngqpt)
4613 [ # # ]: 0 : msg = "supercell"; if (.not. gwr%use_supercell_for_tchi) msg = "BZ-convolutions"
4614 : 0 : call ydoc%add_string("chi_algo", msg)
4615 [ # # ]: 0 : msg = "supercell"; if (.not. gwr%use_supercell_for_sigma) msg = "BZ-convolutions"
4616 : 0 : call ydoc%add_string("sigma_algo", msg)
4617 : 0 : call ydoc%add_int("nkibz", gwr%nkibz)
4618 : 0 : call ydoc%add_int("nqibz", gwr%nqibz)
4619 : 0 : call ydoc%add_int("inclvkb", gwr%dtset%inclvkb)
4620 : 0 : call ydoc%add_real1d("q0", gwr%q0) ! "for long-wavelenght limit"))
4621 : 0 : call ydoc%add_int("gw_icutcoul", gwr%dtset%gw_icutcoul)
4622 : 0 : call ydoc%add_int("green_mpw", gwr%green_mpw)
4623 : 0 : call ydoc%add_int("tchi_mpw", gwr%tchi_mpw)
4624 : 0 : call ydoc%add_int1d("g_ngfft", gwr%g_ngfft(1:6))
4625 : 0 : call ydoc%add_real("gwr_boxcutmin", gwr%dtset%gwr_boxcutmin)
4626 : 0 : call ydoc%add_int1d("P gwr_np_kgts", gwr%dtset%gwr_np_kgts)
4627 : 0 : call ydoc%add_int1d("P np_kibz", gwr%np_kibz)
4628 : 0 : call ydoc%add_int1d("P np_qibz", gwr%np_qibz)
4629 : : ! Print Max error due to the inhomogeneous FT.
4630 : 0 : call ydoc%add_real("min_transition_energy_eV", gwr%te_min * Ha_eV)
4631 : 0 : call ydoc%add_real("max_transition_energy_eV", gwr%te_max * Ha_eV)
4632 : 0 : call ydoc%add_real("eratio", gwr%te_max / gwr%te_min)
4633 : 0 : call ydoc%add_real("ft_max_err_t2w_cos", gwr%ft_max_error(1))
4634 : 0 : call ydoc%add_real("ft_max_err_w2t_cos", gwr%ft_max_error(2))
4635 : 0 : call ydoc%add_real("ft_max_err_t2w_sin", gwr%ft_max_error(3))
4636 : 0 : call ydoc%add_real("cosft_duality_error", gwr%cosft_duality_error)
4637 : : ! Print imaginary time/frequency mesh with weights.
4638 : 0 : call ydoc%open_tabular("Minimax imaginary tau/omega mesh in a.u.", comment="tau, weight(tau), omega, weight(omega)")
4639 [ # # ]: 0 : do ii=1,gwr%ntau
4640 : 0 : write(msg, "(i0, 4(es12.5,2x))")ii, gwr%tau_mesh(ii), gwr%tau_wgs(ii), gwr%iw_mesh(ii), gwr%iw_wgs(ii)
4641 : 0 : call ydoc%add_tabular_line(msg)
4642 : : end do
4643 : :
4644 : 0 : call ydoc%write_units_and_free(units)
4645 : :
4646 [ # # # # ]: 0 : end subroutine gwr_print
4647 : : !!***
4648 : :
4649 : : !!****f* m_gwr/gwr_print_mem
4650 : : !! NAME
4651 : : !! gwr_print_mem
4652 : : !!
4653 : : !! FUNCTION
4654 : : !! Print memory allocated for matrices.
4655 : : !!
4656 : : !! SOURCE
4657 : :
4658 [ # # ]: 0 : subroutine gwr_print_mem(gwr, units)
4659 : :
4660 : : !Arguments ------------------------------------
4661 : : class(gwr_t),intent(in) :: gwr
4662 : : integer,intent(in) :: units(:)
4663 : :
4664 : : !Local variables-------------------------------
4665 : : !scalars
4666 : : real(dp) :: mem_mb
4667 : : !character(len=500) :: msg
4668 : : ! *********************************************************************
4669 : :
4670 [ # # ]: 0 : if (allocated(gwr%gt_kibz)) then
4671 [ # # # # : 0 : mem_mb = sum(slk_array_locmem_mb(gwr%gt_kibz))
# # # # #
# ]
4672 [ # # ]: 0 : if (mem_mb > zero) then
4673 : 0 : call wrtout(units, sjoin("- Local memory for G(g,g',kibz,itau): ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4674 : : end if
4675 : : end if
4676 [ # # ]: 0 : if (allocated(gwr%tchi_qibz)) then
4677 [ # # # # : 0 : mem_mb = sum(slk_array_locmem_mb(gwr%tchi_qibz))
# # ]
4678 [ # # ]: 0 : if (mem_mb > zero) then
4679 : 0 : call wrtout(units, sjoin("- Local memory for Chi(g,g',qibz,itau): ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4680 : : end if
4681 : : end if
4682 [ # # ]: 0 : if (allocated(gwr%wc_qibz)) then
4683 [ # # # # : 0 : mem_mb = sum(slk_array_locmem_mb(gwr%wc_qibz))
# # ]
4684 [ # # ]: 0 : if (mem_mb > zero) then
4685 : 0 : call wrtout(units, sjoin("- Local memory for Wc(g,g,qibz,itau): ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4686 : : end if
4687 : : end if
4688 [ # # ]: 0 : if (allocated(gwr%sigc_kibz)) then
4689 [ # # # # : 0 : mem_mb = sum(slk_array_locmem_mb(gwr%sigc_kibz))
# # # # #
# ]
4690 [ # # ]: 0 : if (mem_mb > zero) then
4691 : 0 : call wrtout(units, sjoin("- Local memory for Sigma_c(g,g',kibz,itau): ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4692 : : end if
4693 : : end if
4694 [ # # ]: 0 : if (allocated(gwr%ugb)) then
4695 [ # # # # ]: 0 : mem_mb = sum(slk_array_locmem_mb(gwr%ugb))
4696 [ # # ]: 0 : if (mem_mb > zero) then
4697 : 0 : call wrtout(units, sjoin('- Local memory for u_gb wavefunctions: ', ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4698 : : end if
4699 : : end if
4700 : 0 : call wrtout(units, " ")
4701 : :
4702 : 0 : end subroutine gwr_print_mem
4703 : : !!***
4704 : :
4705 : : !----------------------------------------------------------------------
4706 : :
4707 : : !!****f* m_gwr/gwr_build_tchi
4708 : : !! NAME
4709 : : !! gwr_build_tchi
4710 : : !!
4711 : : !! FUNCTION
4712 : : !! High-level routine to compute the irreducible polarizability.
4713 : : !!
4714 : : !! SOURCE
4715 : :
4716 : 0 : subroutine gwr_build_tchi(gwr)
4717 : :
4718 : : !Arguments ------------------------------------
4719 : : class(gwr_t),target,intent(inout) :: gwr
4720 : :
4721 : : !Local variables-------------------------------
4722 : : !scalars
4723 : : integer :: my_is, my_it, my_ikf, ig, my_ir, my_nr, nr, npw, ncol_glob, col_bsize, my_iqi, gt_scbox_win, gpu_option, iab
4724 : : integer :: idat, ndat, max_ndat, sc_nfft, sc_nfftsp, spin, ik_bz, iq_ibz, ikq_ibz, ikq_bz, ierr, ipm, itau, ig2, ifft !, ii
4725 : : integer :: use_umklp, gpu_mode ! ik_ibz, isym_k, trev_k, tsign_k, ! g0_k(3),
4726 : : !integer :: my_ikf_start, my_ikf_stop !, nkf_batch_size, nkf_now, op_type
4727 : : integer :: itim, isym
4728 : : integer(kind=XMPI_ADDRESS_KIND) :: buf_count
4729 : : real(dp) :: cpu_tau, wall_tau, gflops_tau, cpu_all, wall_all, gflops_all, cpu_ir, wall_ir, gflops_ir
4730 : : real(dp) :: cpu_ikf, wall_ikf, gflops_ikf
4731 : : real(dp) :: tchi_rfact, mem_mb, local_max, max_abs_imag_chit
4732 : : real(gwp) :: wtqp, wtqm
4733 : : complex(gwp) :: head_q
4734 : : complex(dp) :: chq(3), wng(3)
4735 : : logical :: q_is_gamma, use_shmem_for_k, use_mpi_for_k, print_time, keep_tchim !, doit ! isirr_k,
4736 : : character(len=5000) :: msg
4737 : : character(len=50) :: gpu_action
4738 : : type(desc_t),pointer :: desc_q ! desc_k,
4739 [ # # # # : 0 : type(__slkmat_t) :: chi_rgp
# # ]
4740 : : type(c_ptr) :: void_ptr
4741 : : !arrays
4742 : 0 : integer :: sc_ngfft(18), gg(3), g0_kq(3), mask_qibz(gwr%nqibz), need_kibz(gwr%nkibz), got_kibz(gwr%nkibz), units(2)
4743 : 0 : integer,allocatable :: green_scgvec(:,:), chi_scgvec(:,:)
4744 : 0 : logical :: select_my_kbz(gwr%my_nkbz)
4745 : : real(dp) :: kk_bz(3), kpq_bz(3), qq_ibz(3), tsec(2)
4746 : 0 : complex(gwp) ABI_ASYNC, contiguous, pointer :: gt_scbox(:,:,:)
4747 : 0 : complex(gwp),allocatable :: low_wing_q(:), up_wing_q(:), cemiqr(:)
4748 : : !complex(gwp),contiguous, pointer :: buf_cplx(:,:)
4749 [ # # # # : 0 : type(__slkmat_t) :: gkq_rpr_pm(2, gwr%nsig_ab), gk_rpr_pm(2, gwr%nsig_ab), work2, work1, chiq_ggp
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4750 : 0 : type(__slkmat_t),target,allocatable :: gt_gpr(:,:,:), chiq_gpr(:), chiq_rpr(:)
4751 : 0 : type(desc_t),target,allocatable :: desc_mykbz(:)
4752 : 0 : type(littlegroup_t),allocatable :: ltg_qibz(:)
4753 : : type(fftbox_plan3_t) :: green_plan
4754 : 0 : type(uplan_t) :: uplan_q
4755 : : ! *************************************************************************
4756 : :
4757 : 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
4758 : 0 : call timab(1923, 1, tsec)
4759 : :
4760 [ # # ]: 0 : units = [std_out, ab_out]
4761 : 0 : gpu_option = gwr%dtset%gpu_option
4762 : :
4763 [ # # ]: 0 : ABI_CHECK(gwr%tchi_space == "none", sjoin("tchi_space: ", gwr%tchi_space, " != none"))
4764 : 0 : gwr%tchi_space = "itau"
4765 : :
4766 : : ! Allocate tchi_q(g,g') matrices
4767 [ # # # # ]: 0 : mask_qibz = 0; mask_qibz(gwr%my_qibz_inds(:)) = 1
4768 [ # # ]: 0 : call gwr%print_mem([std_out])
4769 : :
4770 : 0 : call gwr%malloc_free_mats(mask_qibz, "tchi", "malloc")
4771 : 0 : max_abs_imag_chit = zero
4772 : :
4773 : : ! Setup FFT mesh in the supercell.
4774 [ # # ]: 0 : sc_ngfft = gwr%g_ngfft
4775 [ # # # # ]: 0 : sc_ngfft(1:3) = gwr%ngkpt * gwr%g_ngfft(1:3); sc_ngfft(4:6) = sc_ngfft(1:3)
4776 [ # # ]: 0 : sc_nfft = product(sc_ngfft(1:3)); sc_nfftsp = sc_nfft !* gwr%nspinor
4777 : :
4778 [ # # ]: 0 : if (gwr%use_supercell_for_tchi) then
4779 : : ! ============================
4780 : : ! Chi algorithm with supercell
4781 : : ! ============================
4782 : 0 : call print_chi_header()
4783 : :
4784 : : ! Be careful when using the FFT plan with ndat as ndat can change inside the loop if we start to block.
4785 : : ! Perhaps the safest approach would be to generate the plan on the fly.
4786 : 0 : max_ndat = gwr%sc_batch_size
4787 [ # # # # ]: 0 : use_mpi_for_k = gwr%sc_batch_size == gwr%kpt_comm%nproc .and. gwr%kpt_comm%nproc > 1
4788 : : !use_mpi_for_k = .False.
4789 : :
4790 [ # # # # ]: 0 : use_shmem_for_k = gwr%sc_batch_size == gwr%kpt_comm%nproc .and. gwr%kpt_comm%nproc > 1
4791 [ # # # # ]: 0 : use_shmem_for_k = use_shmem_for_k .and. gwr%kpt_comm%can_use_shmem()
4792 [ # # ]: 0 : if (gwr%dtset%userie == 234) use_shmem_for_k = .False.
4793 : : #ifndef HAVE_MPI_ALLOCATE_SHARED_CPTR
4794 : : use_shmem_for_k = .False.
4795 : : #endif
4796 : :
4797 [ # # ]: 0 : if (use_shmem_for_k) then
4798 : 0 : buf_count = 2 * (sc_nfftsp * max_ndat * 2)
4799 : 0 : call gwr%kpt_comm%allocate_shared_master(buf_count, gwp, xmpi_info_null, void_ptr, gt_scbox_win)
4800 [ # # ]: 0 : call c_f_pointer(void_ptr, gt_scbox, shape=[sc_nfftsp, max_ndat, 2])
4801 : : end if
4802 : :
4803 : 0 : call wrtout(std_out, sjoin(" use_mpi_for_k:", yesno(use_mpi_for_k)))
4804 : 0 : call wrtout(std_out, sjoin(" use_shmem_for_k:", yesno(use_shmem_for_k)))
4805 : 0 : mem_mb = (sc_nfftsp * max_ndat * 2 * gwp) * b2Mb
4806 : 0 : call wrtout(std_out, sjoin(" Memory for gt_scbox array:", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4807 : :
4808 [ # # ]: 0 : if (.not. use_shmem_for_k) then
4809 [ # # # # : 0 : ABI_MALLOC(gt_scbox, (sc_nfftsp, max_ndat, 2))
# # # # #
# # # # #
# # # # ]
4810 : : #ifdef HAVE_OPENMP_OFFLOAD
4811 : : !$OMP TARGET ENTER DATA MAP(alloc:gt_scbox(1:sc_nfftsp,1:max_ndat,1:2)) IF (gpu_option == ABI_GPU_OPENMP)
4812 : : #endif
4813 : : end if
4814 : :
4815 : : ! Build plan for dense FFTs.
4816 : 0 : call green_plan%from_ngfft(sc_ngfft, max_ndat*2, gpu_option)
4817 : :
4818 : : ! The g-vectors in the supercell for G and tchi.
4819 [ # # # # : 0 : ABI_MALLOC(green_scgvec, (3, gwr%green_mpw))
# # # # #
# # # ]
4820 [ # # # # : 0 : ABI_MALLOC(chi_scgvec, (3, gwr%tchi_mpw))
# # # # #
# # # ]
4821 [ # # # # : 0 : ABI_MALLOC(gt_gpr, (2, gwr%my_nkbz, gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
4822 [ # # # # : 0 : ABI_MALLOC(chiq_gpr, (gwr%my_nqibz))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4823 [ # # # # : 0 : ABI_MALLOC(desc_mykbz, (gwr%my_nkbz))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
4824 : :
4825 [ # # # # : 0 : ABI_MALLOC(cemiqr, (gwr%g_nfft)) ! The phase e^{-iq.r} in the unit cell.
# # # # #
# # # ]
4826 : : #ifdef HAVE_OPENMP_OFFLOAD
4827 : : !$OMP TARGET ENTER DATA MAP(alloc:cemiqr) IF (gpu_option == ABI_GPU_OPENMP)
4828 : : #endif
4829 : :
4830 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
4831 : 0 : call wrtout(std_out, " Allocating PBLAS arrays for tchi_q(g',r) for all q in the IBZ treated by this MPI rank.")
4832 : 0 : call wrtout(std_out, " Here we're gonna have a big allocation peak...")
4833 : : ! TODO: To reduce memory one could use a diagonal approximation for chi at large G so that we can use a smaller ecuteps.
4834 : :
4835 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
4836 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
4837 : 0 : npw = gwr%tchi_desc_qibz(iq_ibz)%npw
4838 : 0 : ncol_glob = gwr%g_nfft
4839 [ # # ]: 0 : ABI_CHECK(block_dist_1d(ncol_glob, gwr%g_comm%nproc, col_bsize, msg), msg)
4840 [ # # ]: 0 : call chiq_gpr(my_iqi)%init(npw, gwr%g_nfft, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize])
4841 [ # # # # ]: 0 : if (gwr%comm%me == 0 .and. mod(my_iqi, 2) == 0) call pstat_proc%print(_PSTAT_ARGS_)
4842 : : end do
4843 : :
4844 [ # # ]: 0 : mem_mb = sum(slk_array_locmem_mb(chiq_gpr))
4845 : 0 : call wrtout(std_out, sjoin(" Local memory for Chi_q(g',r) matrices: ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
4846 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
4847 : :
4848 [ # # ]: 0 : select_my_kbz = .True.
4849 : : !nkf_batch_size = gwr%my_nkbz
4850 : :
4851 : : ! Loop over my spins and my taus.
4852 [ # # ]: 0 : do my_is=1,gwr%my_nspins
4853 : 0 : spin = gwr%my_spins(my_is)
4854 [ # # ]: 0 : do my_it=1,gwr%my_ntau
4855 : 0 : call cwtime(cpu_tau, wall_tau, gflops_tau, "start")
4856 : 0 : itau = gwr%my_itaus(my_it)
4857 : :
4858 : : ! TODO: To reduce memory one could allocate and then accumulate chi only for a subset of k-points in the BZ
4859 : : ! inside an extra loop over k-groups. This increase the number of FFTs by ngroups but memory decreases
4860 : : ! get_myk_green_gpr should receive a mask and box2gsph should accumulate for ik_group > 1.
4861 : : ! First of all, I need to undestand if get_myk_green_gpr is responsible for the OOM (very likely)
4862 : :
4863 : : ! This trick cannot be used for chi as we have GG but it might be implemented for GW
4864 : : ! where Sigma = G1_k W + G2_k W + G3_k W ...
4865 : :
4866 : : !do my_ikf_start=1, gwr%my_nkbz, nkf_batch_size
4867 : : ! nkf_now = blocked_loop(my_ikf_start, gwr%my_nkbz, nkf_batch_size)
4868 : : ! my_ikf_stop = min(my_ikf_start + nkf_now, gwr%my_nkbz)
4869 : : ! !select_my_kbz = .False.; select_my_kbz(my_ifk_start:my_ifk_stop) = .True.
4870 : : ! !op_type = OP_COPY; if (my_ifk_start /= 0) op_type = OP_SUM
4871 : : !end do ! my_ifk_start
4872 : :
4873 : : ! G_k(g,g') --> G_k(g',r) e^{ik.r} for each k in the BZ treated by me.
4874 : 0 : call gwr%get_myk_green_gpr(itau, spin, select_my_kbz, desc_mykbz, gt_gpr)
4875 [ # # # # ]: 0 : if (my_it == 1 .and. gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
4876 : :
4877 : : ! Loop over r in the unit cell that is now MPI-distributed inside g_comm.
4878 : : ! This is a bottleneck but perhaps one can take advantage of localization.
4879 : : ! Also, one can save all the FFTs in a matrix G(mnfft * ndat, my_nkbz) multiply by the e^{-ikr} phase
4880 : : ! and then use zgemm to compute Out(r,L) = [e^{-ikr}G_k(r)] e^{-ikL} with precomputed e^{-iLk} phases.
4881 : 0 : my_nr = gt_gpr(1,1,1)%size_local(2)
4882 [ # # # # : 0 : do my_ir=1, my_nr, gwr%sc_batch_size
# # # # ]
4883 : 0 : ndat = blocked_loop(my_ir, my_nr, gwr%sc_batch_size)
4884 [ # # # # : 0 : print_time = (gwr%comm%me == 0 .and. (my_ir <= 6 * gwr%sc_batch_size .or. mod(my_ir, LOG_MODR) == 0))
# # ]
4885 : 0 : if (print_time) call cwtime(cpu_ir, wall_ir, gflops_ir, "start")
4886 [ # # ]: 0 : do iab=1, gwr%nsig_ab
4887 : :
4888 : : ! TODO: GPU version
4889 [ # # ]: 0 : if (.not. use_shmem_for_k) then
4890 : :
4891 : : ! Insert G_k(g',r) in G'-space in the supercell FFT box (ndat vectors starting at my_ir).
4892 : 0 : call gwr%gk_to_scbox(sc_ngfft, select_my_kbz, desc_mykbz, green_scgvec, my_ir, ndat, gt_gpr(:,:,iab), gt_scbox)
4893 : : #ifdef HAVE_OPENMP_OFFLOAD
4894 : : !$omp target update to(gt_scbox(1:sc_nfftsp,1:max_ndat,1:2)) if (gpu_option == ABI_GPU_OPENMP)
4895 : : #endif
4896 : :
4897 [ # # ]: 0 : if (.not. use_mpi_for_k) then
4898 : : ! G(G',r) --> G(R',r) = sum_{k,g'} e^{-i(k+g').R'} G_k(g',r)
4899 [ # # ]: 0 : if (gwr%kpt_comm%nproc > 1) call xmpi_sum(gt_scbox, gwr%kpt_comm%value, ierr)
4900 : 0 : call green_plan%execute(gt_scbox(:,1,1), -1, max_ndat*2, iscale=0)
4901 : :
4902 : : ! Compute tchi(R',r) for this r and store it in (:,:,1). Note that results are real so one might use r2c FFT.
4903 : : ! Then back to tchi(G'=q+g',r) immediately with isign + 1.
4904 : : !gt_scbox(:,:,1) = gt_scbox(:,:,1) * conjg(gt_scbox(:,:,2))
4905 : : #ifdef HAVE_OPENMP_OFFLOAD
4906 : : !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:gt_scbox(1:sc_nfftsp,1:max_ndat,1:2)) IF (gpu_option == ABI_GPU_OPENMP)
4907 : : #endif
4908 [ # # ]: 0 : do idat=1,max_ndat
4909 [ # # ]: 0 : do ifft=1,sc_nfftsp
4910 : 0 : gt_scbox(ifft,idat,1) = gt_scbox(ifft,idat,1) * conjg(gt_scbox(ifft,idat,2))
4911 : : end do
4912 : : end do
4913 : : !max_abs_imag_chit = max(max_abs_imag_chit, maxval(abs(aimag(gt_scbox(:,:,1)))))
4914 : :
4915 : 0 : call green_plan%execute(gt_scbox(:,1,1), +1, max_ndat*2)
4916 : : #ifdef HAVE_OPENMP_OFFLOAD
4917 : : !$omp target update from(gt_scbox(1:sc_nfftsp,1:max_ndat,1:2)) if (gpu_option == ABI_GPU_OPENMP)
4918 : : #endif
4919 : :
4920 : : else
4921 : : ! Reduce one G_k(tau) on the idat-1 proc and perform ndat FFTs in parallel.
4922 : : ! Finally, broadcast from the (idat-1) proc inside gwr%kpt_comm.
4923 [ # # ]: 0 : do ipm=1,2
4924 [ # # ]: 0 : do idat=1,ndat
4925 : 0 : call xmpi_sum_master(gt_scbox(:,idat,ipm), idat-1, gwr%kpt_comm%value, ierr)
4926 : : end do
4927 : : end do
4928 : 0 : idat = gwr%kpt_comm%me + 1
4929 [ # # ]: 0 : do ipm=1,2
4930 : 0 : call green_plan%execute(gt_scbox(:,idat,ipm), -1, ndat=1, iscale=0)
4931 : : end do
4932 [ # # ]: 0 : gt_scbox(:,idat,1) = gt_scbox(:,idat,1) * conjg(gt_scbox(:,idat,2))
4933 : 0 : call green_plan%execute(gt_scbox(:,idat,1), +1, ndat=1)
4934 [ # # ]: 0 : do idat=1,ndat
4935 : 0 : call xmpi_bcast(gt_scbox(:,idat,1), idat-1, gwr%kpt_comm%value, ierr)
4936 : : end do
4937 : : end if
4938 : :
4939 : : else
4940 : : ! use_shmem_for_k --> MPI shared window version. Only gt_scbox is shared.
4941 : :
4942 : : call gwr%gk_to_scbox(sc_ngfft, select_my_kbz, desc_mykbz, green_scgvec, my_ir, ndat, gt_gpr(:,:,iab), gt_scbox, &
4943 : 0 : gt_scbox_win=gt_scbox_win)
4944 : :
4945 : : ! Now each MPI proc operates on different idat entries.
4946 : : !IF (.not. MPI_ASYNC_PROTECTS_NONBLOCKING) CALL MPI_F_SYNC_REG(gt_scbox)
4947 : 0 : call xmpi_win_fence(XMPI_MODE_NOPRECEDE, gt_scbox_win, ierr) ! Start the RMA epoch
4948 : 0 : idat = gwr%kpt_comm%me + 1
4949 [ # # ]: 0 : if (idat <= ndat) then
4950 [ # # ]: 0 : do ipm=1,2
4951 : 0 : call green_plan%execute(gt_scbox(:,idat,ipm), -1, ndat=1, iscale=0)
4952 : : end do
4953 [ # # ]: 0 : gt_scbox(:,idat,1) = gt_scbox(:,idat,1) * conjg(gt_scbox(:,idat,2))
4954 : 0 : call green_plan%execute(gt_scbox(:,idat,1), +1, ndat=1)
4955 : : end if
4956 : : !IF (.not. MPI_ASYNC_PROTECTS_NONBLOCKING) CALL MPI_F_SYNC_REG(gt_scbox)
4957 : : !call xmpi_barrier(gwr%kpt_comm%value)
4958 : 0 : call xmpi_win_fence(XMPI_MODE_NOSUCCEED, gt_scbox_win, ierr) ! End the RMA epoch
4959 : : end if
4960 : :
4961 : : ! Now extract tchi_q(g',r) on the ecuteps (q+g)-sphere from the FFT box in the supercell
4962 : : ! and save data in chiq_gpr PBLAS matrix. Only my q-points in the IBZ are considered.
4963 : : ! Alternatively, one can avoid the above FFT, use zero-padded to go from the supercell
4964 : : ! to the ecuteps g-sphere inside the my_iqi loop. This approach should play well with k-point parallelism.
4965 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
4966 [ # # ]: 0 : iq_ibz = gwr%my_qibz_inds(my_iqi); qq_ibz = gwr%qibz(:, iq_ibz); desc_q => gwr%tchi_desc_qibz(iq_ibz)
4967 [ # # ]: 0 : gg = nint(qq_ibz * gwr%ngqpt)
4968 [ # # ]: 0 : do ig=1,desc_q%npw
4969 [ # # ]: 0 : chi_scgvec(:,ig) = gg + gwr%ngqpt(:) * desc_q%gvec(:,ig) ! q+g
4970 : : end do
4971 : : call box2gsph(merge(OP_COPY, OP_ACC, iab == 1),&
4972 : : sc_ngfft, desc_q%npw, ndat, chi_scgvec, &
4973 [ # # ]: 0 : gt_scbox(:,1,1), chiq_gpr(my_iqi)%buffer_cplx(:,my_ir))
4974 : : ! TODO:
4975 : : !call desc_q%box2gsph(qq_ibz, gwr%ngqpt, sc_ngfft, gwr%nspinor * ndat, &
4976 : : ! gt_scbox(:,1,1), chiq_gpr(my_iqi)%buffer_cplx(:,my_ir))
4977 : : end do ! my_iqi
4978 : : end do ! iab
4979 : :
4980 [ # # ]: 0 : if (print_time) then
4981 : 0 : write(msg,'(4x,3(a,i0),a)')"Chi my_ir [", my_ir, "/", my_nr, "] (tot: ", gwr%g_nfft, ")"
4982 : 0 : call cwtime_report(msg, cpu_ir, wall_ir, gflops_ir)
4983 : : end if
4984 : : end do ! my_ir (end cpu intensive loop)
4985 : :
4986 : : ! Free descriptors and PBLAS matrices in kBZ.
4987 : 0 : call desc_array_free(desc_mykbz); call slk_array_free(gt_gpr)
4988 : :
4989 : : ! Now we have tchi_q(g',r).
4990 : : ! For each IBZ q-point treated by this MPI proc, do:
4991 : : !
4992 : : ! 1) MPI transpose to have tchi_q(r,g')
4993 : : ! 2) FFT along the first dimension to get tchi_q(g,g') and store it in gwr%tchi_qibz
4994 : : !
4995 : 0 : tchi_rfact = one / gwr%g_nfft / gwr%cryst%ucvol / (gwr%nkbz * gwr%nqbz)
4996 : :
4997 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
4998 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
4999 : 0 : q_is_gamma = normv(gwr%qibz(:,iq_ibz), gwr%cryst%gmet, "G") < GW_TOLQ0
5000 : 0 : desc_q => gwr%tchi_desc_qibz(iq_ibz)
5001 : :
5002 : : ! Note the minus sign in q.
5003 [ # # # # ]: 0 : call calc_ceikr(-gwr%qibz(:,iq_ibz), gwr%g_ngfft, gwr%g_nfft, 1, cemiqr)
5004 [ # # ]: 0 : cemiqr = cemiqr * tchi_rfact
5005 : : #ifdef HAVE_OPENMP_OFFLOAD
5006 : : !$omp target update to(cemiqr) if (gpu_option == ABI_GPU_OPENMP)
5007 : : #endif
5008 : :
5009 : : ! MPI-transposition: tchi_q(g',r) => tchi_q(r,g')
5010 : 0 : call chiq_gpr(my_iqi)%ptrans("N", chi_rgp)
5011 : :
5012 : : ! FFT tchi_q(r,g') --> tchi_q(g,g'). Results stored in gwr%tchi_qibz.
5013 : : call uplan_q%init(desc_q%npw, 1, gwr%uc_batch_size, gwr%g_ngfft, istwfk1, &
5014 : 0 : desc_q%gvec, gwp, gpu_option)
5015 : :
5016 : 0 : gpu_mode = 1
5017 [ # # # # : 0 : do ig2=1, chi_rgp%size_local(2), gwr%uc_batch_size
# # # # ]
5018 : 0 : ndat = blocked_loop(ig2, chi_rgp%size_local(2), gwr%uc_batch_size)
5019 : :
5020 : : call uplan_q%execute_rg(ndat, chi_rgp%buffer_cplx(:, ig2), &
5021 : 0 : gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx(:, ig2), phase_r=cemiqr, gpu_mode=gpu_mode)
5022 : : end do ! ig2
5023 : :
5024 : 0 : call uplan_q%free()
5025 : 0 : call chi_rgp%free()
5026 : :
5027 : 0 : call gwr%tchi_qibz(iq_ibz, itau, spin)%set_imag_diago_to_zero(local_max)
5028 : : end do ! my_iqi
5029 : :
5030 : 0 : write(msg,'(3(a,i0),a)')" My itau [", my_it, "/", gwr%my_ntau, "] (tot: ", gwr%ntau, ")"
5031 : 0 : call cwtime_report(msg, cpu_tau, wall_tau, gflops_tau, end_str=ch10)
5032 : : end do ! my_it
5033 : : end do ! my_is
5034 : :
5035 [ # # ]: 0 : if (use_shmem_for_k) then
5036 : 0 : call xmpi_win_free(gt_scbox_win, ierr)
5037 : : else
5038 : : #ifdef HAVE_OPENMP_OFFLOAD
5039 : : !$OMP TARGET EXIT DATA MAP(delete: gt_scbox(1:sc_nfftsp,1:max_ndat,1:2)) if (gpu_option == ABI_GPU_OPENMP)
5040 : : #endif
5041 [ # # ]: 0 : ABI_FREE(gt_scbox)
5042 : : end if
5043 : :
5044 [ # # ]: 0 : ABI_FREE(green_scgvec)
5045 [ # # ]: 0 : ABI_FREE(chi_scgvec)
5046 [ # # # # : 0 : ABI_FREE(gt_gpr)
# # # # #
# ]
5047 [ # # # # : 0 : ABI_FREE(desc_mykbz)
# # # # #
# # # # #
# # # # #
# # # #
# ]
5048 : 0 : call slk_array_free(chiq_gpr)
5049 [ # # # # : 0 : ABI_FREE(chiq_gpr)
# # # # #
# ]
5050 : 0 : call green_plan%free()
5051 : :
5052 : : #ifdef HAVE_OPENMP_OFFLOAD
5053 : : !$OMP TARGET EXIT DATA MAP(delete:cemiqr) IF (gpu_option == ABI_GPU_OPENMP)
5054 : : #endif
5055 [ # # ]: 0 : ABI_FREE(cemiqr)
5056 : :
5057 : : else ! not gwr%use_supercell_for_tchi
5058 : : ! ===================================================================
5059 : : ! Mixed-space algorithm in the unit cell with convolutions in k-space
5060 : : ! ===================================================================
5061 : 0 : call print_chi_header()
5062 : :
5063 : 0 : call wrtout(std_out, " Allocating memory for G_k(r',r) and chi_q(r',r)...")
5064 : 0 : call wrtout(std_out, " Here we're gonna have a big allocation peak...")
5065 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
5066 : :
5067 : : ! Need all nqibz matrices in chi_q here as the iq_ibz loop is the innermost one unlike in the legacy GW code.
5068 : 0 : nr = gwr%g_nfft
5069 [ # # ]: 0 : col_bsize = nr / gwr%g_comm%nproc; if (mod(nr, gwr%g_comm%nproc) /= 0) col_bsize = col_bsize + 1
5070 : 0 : tchi_rfact = one / gwr%cryst%ucvol
5071 : :
5072 : 0 : gpu_action = "None";
5073 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) then
5074 : 0 : gpu_action = "alloc"; call wrtout(std_out, " Allocating Chi_q(r,r', +tau) on the GPU...")
5075 : : end if
5076 : :
5077 [ # # # # : 0 : ABI_MALLOC(chiq_rpr, (gwr%nqibz))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
5078 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5079 [ # # ]: 0 : call chiq_rpr(iq_ibz)%init(nr, nr, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize], gpu_action=gpu_action)
5080 : : end do
5081 : :
5082 : 0 : call pstat_proc%print(_PSTAT_ARGS_)
5083 : :
5084 : : ! Allocate G_k(r',r, +/- tau) and G_kq(r',r, +/- tau)
5085 : : ! TODO: Can save memory here as we don't need +/- tau for each k+q.
5086 [ # # ]: 0 : do ipm=1,2
5087 [ # # ]: 0 : do iab=1,gwr%nsig_ab
5088 [ # # ]: 0 : call gk_rpr_pm(ipm, iab)%init(nr, nr, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
5089 [ # # ]: 0 : call gkq_rpr_pm(ipm, iab)%init(nr, nr, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize]) !, gpu_action=gpu_action)
5090 : : end do
5091 : : end do
5092 : :
5093 [ # # # # : 0 : mem_mb = sum(slk_array_locmem_mb(chiq_rpr)) + sum(slk_array_locmem_mb(gk_rpr_pm)) + sum(slk_array_locmem_mb(gkq_rpr_pm))
# # # # #
# ]
5094 : 0 : call wrtout(std_out, sjoin(" Local memory for Chi_q(r',r) (gt_gpr): ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
5095 : 0 : call pstat_proc%print(_PSTAT_ARGS_)
5096 : :
5097 : : ! The little group is needed when symchi == 1 (default)
5098 : : ! If use_umklp == 1 then symmetries requiring an umklapp to preserve qibz are included as well.
5099 : : ! TODO: Note that TR is not yet supported so timrev is set to 1 even if TR has been used to generate the GS IBZ.
5100 [ # # # # : 0 : ABI_MALLOC(ltg_qibz, (gwr%nqibz))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
5101 : 0 : use_umklp = 0
5102 : : !gw_timrev = kpts_timrev_from_kptopt(gwr%ks_ebands%kptopt) + 1
5103 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5104 : : call ltg_qibz(iq_ibz)%init(gwr%qibz(:,iq_ibz), gwr%nkbz, gwr%kbz, gwr%cryst, use_umklp, &
5105 : 0 : npwe=gwr%tchi_desc_qibz(iq_ibz)%npw, gvec=gwr%tchi_desc_qibz(iq_ibz)%gvec)
5106 : : !call ltg_qibz(iq_ibz)%init(gwr%qibz(:,iq_ibz), gwr%nkbz, gwr%kbz, gwr%cryst, use_umklp, npwe=0, timrev=1)
5107 [ # # # # ]: 0 : if (gwr%comm%me == 0) call ltg_qibz(iq_ibz)%print([std_out], prtvol=gwr%dtset%prtvol)
5108 : : end do
5109 : :
5110 : : ! Compute mask with the k+q points in the IBZ required by this MPI proc.
5111 [ # # ]: 0 : need_kibz = 0
5112 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
5113 [ # # ]: 0 : ik_bz = gwr%my_kbz_inds(my_ikf); kk_bz = gwr%kbz(:, ik_bz)
5114 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5115 [ # # # # ]: 0 : qq_ibz = gwr%qibz(:, iq_ibz); kpq_bz = kk_bz + qq_ibz
5116 : 0 : call findqg0(ikq_bz, g0_kq, kpq_bz, gwr%nkbz, gwr%kbz, gwr%mG0)
5117 : : ! TODO: here I may need to take into account the umklapp
5118 : : !ABI_CHECK(all(g0_kq == 0), sjoin("g0_kq != 0, kk_bz", ktoa(kpq_bz), "qq_ibz:", ktoa(qq_ibz)))
5119 : 0 : ikq_ibz = gwr%kbz2ibz(1, ikq_bz)
5120 : 0 : need_kibz(ikq_ibz) = 1
5121 : : end do
5122 : : end do
5123 : :
5124 : : ! Begin loop over spin and tau points.
5125 [ # # ]: 0 : do my_is=1,gwr%my_nspins
5126 : 0 : spin = gwr%my_spins(my_is)
5127 [ # # ]: 0 : do my_it=1,gwr%my_ntau
5128 : 0 : call cwtime(cpu_tau, wall_tau, gflops_tau, "start")
5129 : 0 : itau = gwr%my_itaus(my_it)
5130 : :
5131 : : ! Redistribute G_k(g,g') with k in the IBZ so that each MPI proc
5132 : : ! can reconstruct G_{k+q} in the BZ inside the MPI-distributed loops.
5133 : : ! TODO: support for ipm_list else we have a memory leak.
5134 : 0 : call gwr%redistrib_gt_kibz(itau, spin, need_kibz, got_kibz, "communicate") !ipm_list=
5135 [ # # # # ]: 0 : if (my_it == 1 .and. gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
5136 : :
5137 : : ! Sum over my k-points in the BZ.
5138 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) then
5139 : 0 : call slk_array_gpu_set_zero(chiq_rpr)
5140 : : else
5141 [ # # ]: 0 : call slk_array_set_zero(chiq_rpr)
5142 : : end if
5143 : :
5144 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
5145 [ # # # # : 0 : print_time = gwr%comm%me == 0 .and. (my_ikf <= LOG_MODK .or. mod(my_ikf, LOG_MODK) == 0)
# # ]
5146 : 0 : if (print_time) call cwtime(cpu_ikf, wall_ikf, gflops_ikf, "start")
5147 [ # # ]: 0 : ik_bz = gwr%my_kbz_inds(my_ikf); kk_bz = gwr%kbz(:, ik_bz)
5148 : :
5149 : : ! Use symmetries to get G_kbz(g,g') from the IBZ, then G_kbz(g,g') -> G_kbz(r',r).
5150 : : ! TODO: here I may need to take into account the umklapp
5151 : 0 : call gwr%get_gkbz_rpr_pm(ik_bz, itau, spin, gk_rpr_pm, ipm_list=[1]) ! g0=??
5152 : :
5153 : : ! Accumulate contribution to chi_q(r',r) with q in the IBZ.
5154 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5155 [ # # # # ]: 0 : if (gwr%dtset%symchi /= 0 .and. ltg_qibz(iq_ibz)%ibzq(ik_bz) == 0) cycle
5156 [ # # # # ]: 0 : qq_ibz = gwr%qibz(:,iq_ibz); kpq_bz = kk_bz + qq_ibz
5157 : :
5158 : 0 : call findqg0(ikq_bz, g0_kq, kpq_bz, gwr%nkbz, gwr%kbz, gwr%mG0)
5159 : : ! TODO: here I may need to take into account the umklapp if k+q is outside the BZ.
5160 : : !ABI_CHECK(all(g0_kq == 0), sjoin("g0_kq != 0, kk_bz", ktoa(kpq_bz), "qq_ibz:", ktoa(qq_ibz)))
5161 : :
5162 : : ! Use symmetries to get G_kqbz(g,g') from the IBZ, then G_kqbz(g,g') -> G_kqbz(r',r).
5163 : : ! Note that only G_kq(-itau) is needed.
5164 : 0 : call gwr%get_gkbz_rpr_pm(ikq_bz, itau, spin, gkq_rpr_pm, g0=g0_kq, ipm_list=[2])
5165 : :
5166 : : ! The weight depends on q_ibz and the symmetries of the little group of qq_ibz.
5167 : 0 : wtqp = one / gwr%nkbz; wtqm = zero
5168 [ # # ]: 0 : if (gwr%dtset%symchi /= 0) then
5169 [ # # ]: 0 : wtqp = (one * sum(ltg_qibz(iq_ibz)%wtksym(1,:,ik_bz))) / gwr%nkbz
5170 [ # # ]: 0 : wtqm = (one * sum(ltg_qibz(iq_ibz)%wtksym(2,:,ik_bz))) / gwr%nkbz
5171 : : !ABI_CHECK(wtqm == zero, sjoin("TR is not yet implemented:, wqtm:", ftoa(wtqm)))
5172 : : end if
5173 : :
5174 : : ! Accumulate.
5175 : :
5176 : : !chiq_rpr(iq_ibz)%buffer_cplx = chiq_rpr(iq_ibz)%buffer_cplx + &
5177 : : ! wtqp * gk_rpr_pm(1)%buffer_cplx * conjg(gkq_rpr_pm(2)%buffer_cplx) ! RECHECK EQ. This one works but requires ptrans with C
5178 : : ! !wtqp * gkq_rpr_pm(1)%buffer_cplx * conjg(gk_rpr_pm(2)%buffer_cplx) ! This should be OK
5179 [ # # ]: 0 : do iab=1,gwr%nsig_ab
5180 : : call cplx_mat_plus_bc(chiq_rpr(iq_ibz)%bufsize, chiq_rpr(iq_ibz)%buffer_cplx(:,1), &
5181 : 0 : wtqp+wtqm, "C", gkq_rpr_pm(2, iab)%buffer_cplx(:,1), gk_rpr_pm(1, iab)%buffer_cplx(:,1), gpu_option)
5182 : : end do ! iab
5183 : :
5184 : : end do ! iq_ibz
5185 : :
5186 [ # # ]: 0 : if (print_time) then
5187 : 0 : write(msg,'(4x,3(a,i0),a)')"Chi my_ikf [", my_ikf, "/", gwr%my_nkbz, "] (tot: ", gwr%nkbz, ")"
5188 : 0 : call cwtime_report(msg, cpu_ikf, wall_ikf, gflops_ikf)
5189 : : end if
5190 : : end do ! my_ikf
5191 : :
5192 : : ! Deallocate got_kibz Green's functions.
5193 : 0 : call gwr%redistrib_gt_kibz(itau, spin, need_kibz, got_kibz, "free")
5194 : :
5195 : : ! From chi_q(r',r) to chi_q(g,g') for each q in the IBZ.
5196 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5197 : 0 : call xmpi_sum(chiq_rpr(iq_ibz)%buffer_cplx, gwr%kpt_comm%value, ierr)
5198 : : end do
5199 : :
5200 : 0 : tchi_rfact = one / gwr%cryst%ucvol
5201 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5202 [ # # # # : 0 : if (.not. any(iq_ibz == gwr%my_qibz_inds)) cycle
# # ]
5203 : 0 : call gwr%tchi_qibz(iq_ibz, itau, spin)%copy(chiq_ggp, empty=.True.)
5204 : 0 : call gwr%rpr_to_ggp(gwr%tchi_desc_qibz(iq_ibz), chiq_rpr(iq_ibz), tchi_rfact, chiq_ggp)
5205 : 0 : call chiq_ggp%copy(work1, empty=.True.)
5206 : :
5207 : : ! Here we symmetrize chi0 to get the integral in the BZ.
5208 : : ! This section is needed only if symchi /= 0.
5209 : : ! TODO: Timrev should be tested. At present is disabled.
5210 : : associate(desc => gwr%tchi_desc_qibz(iq_ibz), ltg => ltg_qibz(iq_ibz))
5211 : 0 : call gwr%rpr_to_ggp(gwr%tchi_desc_qibz(iq_ibz), chiq_rpr(iq_ibz), tchi_rfact, chiq_ggp)
5212 [ # # ]: 0 : do itim=1, ltg%timrev
5213 [ # # ]: 0 : do isym=1, ltg%nsym_sg
5214 [ # # ]: 0 : if (ltg%preserve(itim,isym) /= 1) cycle
5215 : : associate(sglist => desc%rottbm1(ltg%igmG0(1:desc%npw, itim, isym), itim, isym), &
5216 : 0 : phase => desc%phmGt(:, isym))
5217 : 0 : call slk_array_set_zero(work1)
5218 : : ! (g,g') --> (Sg, g')
5219 [ # # ]: 0 : do ig2=1,work1%size_local(2)
5220 [ # # ]: 0 : if (itim == 1) then
5221 [ # # ]: 0 : work1%buffer_cplx(:,ig2) = chiq_ggp%buffer_cplx(sglist, ig2) * phase
5222 : : else
5223 [ # # ]: 0 : work1%buffer_cplx(:,ig2) = GWPC_CONJG(chiq_ggp%buffer_cplx(sglist, ig2)) * phase
5224 : : end if
5225 : : end do
5226 : : ! (Sg, g') --> (g', Sg)
5227 : 0 : call work1%ptrans("C", work2, free=.False.)
5228 : : ! (g', Sg) --> (Sg', Sg)
5229 [ # # ]: 0 : do ig2=1,work2%size_local(2)
5230 [ # # # # : 0 : work2%buffer_cplx(:,ig2) = work2%buffer_cplx(sglist, ig2) * phase
# # ]
5231 : : end do
5232 : : ! (Sg', Sg) --> (Sg, Sg')
5233 : 0 : call work2%ptrans("C", work1, free=.True.)
5234 [ # # # # : 0 : gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx(:,:) = gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx(:,:)+work1%buffer_cplx(:,:)
# # # # #
# ]
5235 : : end associate
5236 : : end do ! isym
5237 : : end do ! itim
5238 : :
5239 : 0 : call work1%free()
5240 : : gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx(:,:) = gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx(:,:) &
5241 [ # # # # ]: 0 : & / ltg%nsym_ltg
5242 : :
5243 : : end associate
5244 : 0 : call chiq_ggp%free()
5245 : : end do ! iq_ibz
5246 : :
5247 : 0 : write(msg,'(3(a,i0),a)')" My itau [", my_it, "/", gwr%my_ntau, "] (tot: ", gwr%ntau, ")"
5248 : 0 : call cwtime_report(msg, cpu_tau, wall_tau, gflops_tau)
5249 : : end do ! my_it
5250 : : end do ! spin
5251 : :
5252 : : ! Free memory
5253 : 0 : call slk_array_free(gk_rpr_pm); call slk_array_free(gkq_rpr_pm); call slk_array_free(chiq_rpr)
5254 [ # # # # : 0 : ABI_FREE(chiq_rpr)
# # # # #
# ]
5255 : :
5256 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5257 : 0 : call ltg_qibz(iq_ibz)%free()
5258 : : end do
5259 [ # # # # : 0 : ABI_FREE(ltg_qibz)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
5260 : 0 : call wrtout(std_out, " Mixed space algorithm for chi completed.")
5261 : :
5262 : : end if ! super cell or mixed space algorithm.
5263 : : !call wrtout(std_out, sjoin(" max_abs_imag_chit", ftoa(max_abs_imag_chit)))
5264 : :
5265 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
5266 : :
5267 : : ! Print trace of chi_q(i tau) matrices for testing purposes.
5268 [ # # ]: 0 : if (gwr%dtset%prtvol > 0) call gwr%print_trace(units, "tchi_qibz")
5269 : :
5270 : : ! Write tchi(i tau). NB: this option is not documented in the docs.
5271 : 0 : keep_tchim = .False.
5272 [ # # ]: 0 : if (gwr%dtset%prtsuscep == -1) then
5273 [ # # ]: 0 : call gwr%ncwrite_tchi_wc("tchi", "tau", keep_tchim, trim(gwr%dtfil%filnam_ds(4))//'_TCHIM.nc')
5274 : 0 : keep_tchim = .True.
5275 : : end if
5276 : :
5277 : : ! Transform irreducible tchi from imaginary tau to imaginary omega.
5278 : : ! Also, sum over spins to get total tchi if collinear spin.
5279 : 0 : call gwr%cos_transform("tchi", "it2w", sum_spins=.True.)
5280 : :
5281 [ # # ]: 0 : if (gwr%kpt_comm%me == 0) then
5282 : : ! ===================================================
5283 : : ! ==== Construct head and wings from the tensor =====
5284 : : ! ===================================================
5285 : : associate (desc_q0 => gwr%tchi_desc_qibz(1), mat_ts => gwr%tchi_qibz(1,:,:))
5286 : 0 : ABI_CHECK_IEQ(desc_q0%ig0, 1, "ig0 should be 1")
5287 [ # # # # : 0 : ABI_MALLOC(up_wing_q, (desc_q0%npw))
# # # # #
# # # ]
5288 [ # # # # : 0 : ABI_MALLOC(low_wing_q, (desc_q0%npw))
# # # # ]
5289 : :
5290 [ # # # # ]: 0 : do my_is=1,gwr%my_nspins
5291 : 0 : spin = gwr%my_spins(my_is)
5292 [ # # ]: 0 : do my_it=1,gwr%my_ntau
5293 : 0 : itau = gwr%my_itaus(my_it)
5294 : :
5295 [ # # ]: 0 : do ig=2,desc_q0%npw
5296 [ # # ]: 0 : wng = gwr%chi0_uwing_myw(:,ig, my_it)
5297 : 0 : up_wing_q(ig) = vdotw(gwr%q0, wng, gwr%cryst%gmet, "G")
5298 [ # # ]: 0 : wng = gwr%chi0_lwing_myw(:,ig,my_it)
5299 : 0 : low_wing_q(ig) = vdotw(gwr%q0, wng, gwr%cryst%gmet, "G")
5300 : : end do
5301 [ # # # # : 0 : chq = matmul(gwr%chi0_head_myw(:,:,my_it), gwr%q0)
# # # # #
# ]
5302 : 0 : head_q = vdotw(gwr%q0, chq, gwr%cryst%gmet, "G")
5303 : :
5304 : 0 : call mat_ts(itau, spin)%set_head_and_wings(head_q, low_wing_q, up_wing_q)
5305 : : end do ! my_it
5306 : : end do ! my_is
5307 : : end associate
5308 [ # # ]: 0 : ABI_FREE(up_wing_q)
5309 [ # # ]: 0 : ABI_FREE(low_wing_q)
5310 : : end if
5311 : :
5312 : : ! Print trace of chi_q(i omega) matrices for testing purposes.
5313 [ # # ]: 0 : if (gwr%dtset%prtvol > 0) call gwr%print_trace(units, "tchi_qibz")
5314 : :
5315 : : ! Write file with chi0(i omega).
5316 [ # # ]: 0 : if (abs(gwr%dtset%prtsuscep) == 1) then
5317 [ # # ]: 0 : call gwr%ncwrite_tchi_wc("tchi", "omega", keep_tchim, trim(gwr%dtfil%filnam_ds(4))//'_TCHIM.nc')
5318 : : end if
5319 : :
5320 : 0 : call cwtime_report(" gwr_build_tchi:", cpu_all, wall_all, gflops_all)
5321 [ # # # # : 0 : call timab(1923, 2, tsec)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
5322 : :
5323 : : contains
5324 : :
5325 : 0 : subroutine print_chi_header()
5326 [ # # ]: 0 : if (gwr%comm%me /= 0) return
5327 [ # # ]: 0 : if (gwr%use_supercell_for_tchi) then
5328 : 0 : call wrtout(std_out, " Building chi0(r,R, itau) in the supercell with FFTs ", pre_newlines=2)
5329 : : else
5330 : 0 : call wrtout(std_out, " Building chi_q(r,r', itau) with convolutions in k-space:", pre_newlines=2)
5331 : : end if
5332 : 0 : call wrtout(std_out, sjoin(" gwr_np_kgts:", ltoa(gwr%dtset%gwr_np_kgts)))
5333 : 0 : call wrtout(std_out, sjoin(" ngkpt:", ltoa(gwr%ngkpt), ", ngqpt:", ltoa(gwr%ngqpt)))
5334 : 0 : call wrtout(std_out, sjoin(" gwr_boxcutmin:", ftoa(gwr%dtset%gwr_boxcutmin)))
5335 : 0 : call wrtout(std_out, sjoin(" sc_ngfft:", ltoa(sc_ngfft(1:8))))
5336 : 0 : call wrtout(std_out, sjoin(" my_ntau:", itoa(gwr%my_ntau), ", ntau:", itoa(gwr%ntau)))
5337 : 0 : call wrtout(std_out, sjoin(" my_nkbz:", itoa(gwr%my_nkbz), ", nkbz:", itoa(gwr%nkbz)))
5338 : 0 : call wrtout(std_out, sjoin(" my_nkibz:", itoa(gwr%my_nkibz), ", nkibz:", itoa(gwr%nkibz)))
5339 : 0 : call wrtout(std_out, sjoin("- FFT uc_batch_size:", itoa(gwr%uc_batch_size)))
5340 : 0 : call wrtout(std_out, sjoin("- FFT sc_batch_size:", itoa(gwr%sc_batch_size)), do_flush=.True.)
5341 : : end subroutine print_chi_header
5342 : :
5343 : : end subroutine gwr_build_tchi
5344 : : !!***
5345 : :
5346 : : !----------------------------------------------------------------------
5347 : :
5348 : : !!****f* m_gwr/gwr_redistrib_gt_kibz
5349 : : !! NAME
5350 : : !! gwr_redistrib_gt_kibz
5351 : : !!
5352 : : !! FUNCTION
5353 : : !! Redistribute/deallocate G_k
5354 : : !!
5355 : : !! If action == "communicate":
5356 : : !! Redistribute G_k for fixed (itau, spin) according to `need_kibz` table.
5357 : : !! Also, set got_kibz to 1 for each IBZ k-point that has been received.
5358 : : !!
5359 : : !! If action == "free":
5360 : : !! Use input `got_kibz` array to deallocate matrices received in a previous call.
5361 : : !!
5362 : : !! INPUTS
5363 : : !!
5364 : : !! OUTPUT
5365 : : !!
5366 : : !! SOURCE
5367 : :
5368 : 0 : subroutine gwr_redistrib_gt_kibz(gwr, itau, spin, need_kibz, got_kibz, action)
5369 : :
5370 : : !Arguments ------------------------------------
5371 : : class(gwr_t),target,intent(inout) :: gwr
5372 : : integer,intent(in) :: itau, spin, need_kibz(gwr%nkibz)
5373 : : integer,intent(inout) :: got_kibz(gwr%nkibz)
5374 : : character(len=*),intent(in) :: action
5375 : : !integer,optional,intent(in) :: ipm_list(:)
5376 : :
5377 : : !Local variables-------------------------------
5378 : 0 : integer :: ik_ibz, ipm, ierr, do_mpi_kibz(gwr%nkibz), sender_kibz(gwr%nkibz)
5379 : : integer :: bcast_comm, sender_in_bcast_comm, color, iab
5380 : : logical :: im_sender
5381 : : !integer :: num_pm, ipm_list__(2)
5382 : : real(dp) :: kk_ibz(3), cpu, wall, gflops
5383 : 0 : complex(gwp),contiguous, pointer :: ck_ptr(:,:)
5384 : : ! *************************************************************************
5385 : :
5386 : 0 : call cwtime(cpu, wall, gflops, "start")
5387 : :
5388 : : !num_pm = 2; ipm_list__ = [1, 2]
5389 : : !if (present(ipm_list)) then
5390 : : ! num_pm = size(ipm_list)
5391 : : ! ABI_CHECK_IRANGE(num_pm, 1, 2, "num_pm not in [1, 2]")
5392 : : ! ipm_list__(1:num_pm) = ipm_list(:)
5393 : : !end if
5394 : :
5395 : : select case (action)
5396 : : case ("communicate")
5397 [ # # ]: 0 : do_mpi_kibz = need_kibz
5398 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
5399 [ # # ]: 0 : if (allocated(gwr%green_desc_kibz(ik_ibz)%gvec)) do_mpi_kibz(ik_ibz) = 0
5400 : : end do
5401 : 0 : call xmpi_sum(do_mpi_kibz, gwr%kpt_comm%value, ierr)
5402 : : !do_mpi_kibz = 1
5403 : :
5404 : : ! All procs enter the loop. Sender_kibz stores the rank of the sender in gwr%kpt_comm
5405 [ # # # # ]: 0 : got_kibz = 0; sender_kibz(:) = huge(1)
5406 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
5407 [ # # ]: 0 : if (do_mpi_kibz(ik_ibz) == 0) cycle
5408 [ # # ]: 0 : kk_ibz = gwr%kibz(:, ik_ibz)
5409 [ # # ]: 0 : if (allocated(gwr%green_desc_kibz(ik_ibz)%gvec)) sender_kibz(ik_ibz) = gwr%kpt_comm%me
5410 [ # # # # ]: 0 : if (need_kibz(ik_ibz) /= 0 .and. .not. allocated(gwr%green_desc_kibz(ik_ibz)%gvec)) then
5411 : : ! NB: Use same args as those used to init the descriptors in gwr_init
5412 : : ! so that the ordering of gvec is consistent across MPI procs.
5413 : 0 : got_kibz(ik_ibz) = 1
5414 : 0 : call gwr%green_desc_kibz(ik_ibz)%init(kk_ibz, istwfk1, gwr%dtset%ecutwfn, gwr)
5415 : : end if
5416 : : end do
5417 : :
5418 : : ! Define the sender for each kibz in do_mpi_kibz.
5419 : 0 : call xmpi_min_ip(sender_kibz, gwr%kpt_comm%value, ierr)
5420 : :
5421 : : ! Allocate memory
5422 : 0 : call gwr%malloc_free_mats(got_kibz, "green", "malloc")
5423 : :
5424 : : ! MPI communication
5425 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
5426 [ # # ]: 0 : if (do_mpi_kibz(ik_ibz) == 0) cycle
5427 : :
5428 : : ! Create subcommunicators with color and bcast only inside subcomm.
5429 : 0 : im_sender = gwr%kpt_comm%me == sender_kibz(ik_ibz)
5430 [ # # # # ]: 0 : color = merge(1, 0, im_sender .or. need_kibz(ik_ibz) /= 0)
5431 : 0 : call xmpi_comm_split(gwr%kpt_comm%value, color, gwr%kpt_comm%me, bcast_comm, ierr)
5432 : :
5433 [ # # ]: 0 : if (color == 1) then
5434 : 0 : sender_in_bcast_comm = xmpi_comm_translate_rank(gwr%kpt_comm%value, sender_kibz(ik_ibz), bcast_comm)
5435 [ # # ]: 0 : do ipm=1,2
5436 [ # # ]: 0 : do iab=1,gwr%nsig_ab
5437 : 0 : ck_ptr => gwr%gt_kibz(ipm, ik_ibz, itau, spin, iab)%buffer_cplx
5438 : 0 : call xmpi_bcast(ck_ptr, sender_in_bcast_comm, bcast_comm, ierr)
5439 : : end do
5440 : : end do
5441 : : end if
5442 : 0 : call xmpi_comm_free(bcast_comm)
5443 : : end do
5444 : :
5445 : : case ("free")
5446 : : ! Use got_kibz to free previously allocated memory.
5447 [ # # ]: 0 : do ik_ibz=1,gwr%nkibz
5448 [ # # ]: 0 : if (got_kibz(ik_ibz) == 1) call gwr%green_desc_kibz(ik_ibz)%free()
5449 : : end do
5450 : 0 : call gwr%malloc_free_mats(got_kibz, "green", "free")
5451 : :
5452 : : case default
5453 [ # # # ]: 0 : ABI_ERROR(sjoin("Invalid action:", action))
5454 : : end select
5455 : :
5456 [ # # ]: 0 : if (action == "communicate") call cwtime_report(" gwr_redistrib_gt_kibz:", cpu, wall, gflops)
5457 : :
5458 : 0 : end subroutine gwr_redistrib_gt_kibz
5459 : : !!***
5460 : :
5461 : : !!****f* m_gwr/gwr_redistrib_mats_qibz
5462 : : !! NAME
5463 : : !! gwr_redistrib_mats_qibz
5464 : : !!
5465 : : !! FUNCTION
5466 : : !! If action == "communicate":
5467 : : !! Redistribute chi_q (wc_q) for fixed (itau, spin) according to `need_qibz` table.
5468 : : !! Also, set `got_qibz` to 1 for each IBZ q-point that has been received.
5469 : : !! If action == "free":
5470 : : !! Use `got_qibz` to deallocate matrices received in a previous call with "communicate".
5471 : : !!
5472 : : !! INPUTS
5473 : : !!
5474 : : !! OUTPUT
5475 : : !!
5476 : : !! SOURCE
5477 : :
5478 : 0 : subroutine gwr_redistrib_mats_qibz(gwr, what, itau, spin, need_qibz, got_qibz, action)
5479 : :
5480 : : !Arguments ------------------------------------
5481 : : class(gwr_t),target,intent(inout) :: gwr
5482 : : character(len=*),intent(in) :: what
5483 : : integer,intent(in) :: itau, spin, need_qibz(gwr%nqibz)
5484 : : integer,intent(inout) :: got_qibz(gwr%nqibz)
5485 : : character(len=*),intent(in) :: action
5486 : :
5487 : : !Local variables-------------------------------
5488 : 0 : integer :: iq_ibz, ierr, bcast_comm, color, do_mpi_qibz(gwr%nqibz), sender_qibz(gwr%nqibz), sender_in_bcast_comm
5489 : : logical :: im_sender
5490 : : logical, parameter :: timeit = .False.
5491 : : real(dp) :: qq_ibz(3), cpu, wall, gflops
5492 : 0 : complex(gwp),contiguous, pointer :: cq_ptr(:,:)
5493 : : ! *************************************************************************
5494 : :
5495 [ # # ]: 0 : ABI_CHECK(what == "tchi" .or. what == "wc", sjoin("Invalid what:", what))
5496 : : if (timeit) call cwtime(cpu, wall, gflops, "start")
5497 : :
5498 : : select case (action)
5499 : : case ("communicate")
5500 [ # # ]: 0 : do_mpi_qibz = need_qibz
5501 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5502 : 0 : select case (what)
5503 : : case ("tchi")
5504 [ # # ]: 0 : if (allocated(gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx)) do_mpi_qibz(iq_ibz) = 0
5505 : : case ("wc")
5506 [ # # ]: 0 : if (allocated(gwr%wc_qibz(iq_ibz, itau, spin)%buffer_cplx)) do_mpi_qibz(iq_ibz) = 0
5507 : : case default
5508 [ # # # ]: 0 : ABI_ERROR(sjoin("Invalid what:", what))
5509 : : end select
5510 : : end do
5511 : :
5512 : 0 : call xmpi_sum(do_mpi_qibz, gwr%kpt_comm%value, ierr)
5513 : : !do_mpi_qibz = 1
5514 : :
5515 : : ! All procs enter the loop. Sender_qibz stores the rank of the sender in gwr%kpt_comm
5516 [ # # # # ]: 0 : got_qibz = 0; sender_qibz(:) = huge(1)
5517 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5518 [ # # ]: 0 : if (do_mpi_qibz(iq_ibz) == 0) cycle
5519 [ # # ]: 0 : qq_ibz = gwr%qibz(:, iq_ibz)
5520 [ # # ]: 0 : if (allocated(gwr%tchi_desc_qibz(iq_ibz)%gvec)) sender_qibz(iq_ibz) = gwr%kpt_comm%me
5521 [ # # # # ]: 0 : if (need_qibz(iq_ibz) /= 0 .and. .not. allocated(gwr%tchi_desc_qibz(iq_ibz)%gvec)) then
5522 : : ! NB: Use same args as those used to init the descriptors in gwr_init
5523 : : ! so that gvec ordering is consistent across MPI procs.
5524 : 0 : got_qibz(iq_ibz) = 1
5525 : 0 : call gwr%tchi_desc_qibz(iq_ibz)%init(qq_ibz, istwfk1, gwr%dtset%ecuteps, gwr, kin_sorted=.True.)
5526 : : end if
5527 : : end do
5528 : :
5529 : : ! Define the sender for each qibz in do_mpi_qibz
5530 : 0 : call xmpi_min_ip(sender_qibz, gwr%kpt_comm%value, ierr)
5531 : :
5532 : : ! Allocate memory
5533 : 0 : call gwr%malloc_free_mats(got_qibz, what, "malloc")
5534 : :
5535 : : ! MPI communication
5536 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5537 [ # # ]: 0 : if (do_mpi_qibz(iq_ibz) == 0) cycle
5538 : :
5539 : : ! Create subcommunicators with color and bcast only inside subcomm.
5540 : 0 : im_sender = gwr%kpt_comm%me == sender_qibz(iq_ibz)
5541 [ # # # # ]: 0 : color = merge(1, 0, im_sender .or. need_qibz(iq_ibz) /= 0)
5542 : 0 : call xmpi_comm_split(gwr%kpt_comm%value, color, gwr%kpt_comm%me, bcast_comm, ierr)
5543 : :
5544 [ # # ]: 0 : if (color == 1) then
5545 [ # # ]: 0 : if (what == "tchi") cq_ptr => gwr%tchi_qibz(iq_ibz, itau, spin)%buffer_cplx
5546 [ # # ]: 0 : if (what == "wc") cq_ptr => gwr%wc_qibz(iq_ibz, itau, spin)%buffer_cplx
5547 : 0 : sender_in_bcast_comm = xmpi_comm_translate_rank(gwr%kpt_comm%value, sender_qibz(iq_ibz), bcast_comm)
5548 : 0 : call xmpi_bcast(cq_ptr, sender_in_bcast_comm, bcast_comm, ierr)
5549 : : end if
5550 : 0 : call xmpi_comm_free(bcast_comm)
5551 : : end do ! iq_ibz
5552 : :
5553 : : case ("free")
5554 : : ! Use got_qibz table to free previously allocated memory
5555 [ # # ]: 0 : do iq_ibz=1,gwr%nqibz
5556 [ # # ]: 0 : if (got_qibz(iq_ibz) /= 0) call gwr%tchi_desc_qibz(iq_ibz)%free()
5557 : : end do
5558 : 0 : call gwr%malloc_free_mats(got_qibz, what, "free")
5559 : :
5560 : : case default
5561 [ # # # ]: 0 : ABI_ERROR(sjoin("Invalid action:", action))
5562 : : end select
5563 : :
5564 : : if (timeit) call cwtime_report(" gwr_redistrib_mats_qibz:", cpu, wall, gflops)
5565 : :
5566 [ # # ]: 0 : end subroutine gwr_redistrib_mats_qibz
5567 : : !!***
5568 : :
5569 : : !----------------------------------------------------------------------
5570 : :
5571 : : !!****f* m_gwr/gwr_print_trace
5572 : : !! NAME
5573 : : !! gwr_print_trace
5574 : : !!
5575 : : !! FUNCTION
5576 : : !! Print traces of PBLAS matrices to units.
5577 : : !! NB: This is a global routine that should be called by all procs inside gwr%comm.
5578 : : !!
5579 : : !! INPUTS
5580 : : !!
5581 : : !! OUTPUT
5582 : : !!
5583 : : !! SOURCE
5584 : :
5585 [ # # ]: 0 : subroutine gwr_print_trace(gwr, units, what)
5586 : :
5587 : : !Arguments ------------------------------------
5588 : : class(gwr_t),target,intent(inout) :: gwr
5589 : : integer,intent(in) :: units(:)
5590 : : character(len=*),intent(in) :: what
5591 : :
5592 : : !Local variables-------------------------------
5593 : : integer,parameter :: master = 0
5594 : : integer :: my_is, spin, my_it, itau, iq_ibz, ierr, my_iqi, my_iki, ik_ibz, ipm, iab
5595 : : character(len=5000) :: comment
5596 : 0 : complex(dp),allocatable :: ctrace3(:,:,:), ctrace5(:,:,:,:,:) !, ctrace4(:,:,:,:)
5597 : 0 : type(__slkmat_t),contiguous, pointer :: mats(:,:,:)
5598 : : ! *************************************************************************
5599 : :
5600 : : ! NB: The same q/k point in the IBZ might be available on different procs in kpt_comm
5601 : : ! hence we have to rescale the trace before summing the results in gwr%comm.
5602 : 0 : comment = "Invalid space!"
5603 : :
5604 : 0 : select case (what)
5605 : : case ("tchi_qibz", "wc_qibz")
5606 : : ! Trace of tchi or Wc
5607 [ # # # # : 0 : ABI_CALLOC(ctrace3, (gwr%nqibz, gwr%ntau, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
5608 : :
5609 [ # # ]: 0 : if (what == "tchi_qibz") then
5610 : 0 : mats => gwr%tchi_qibz
5611 [ # # ]: 0 : if (gwr%tchi_space == "iomega") comment = " (iq_ibz, iomega) table"
5612 [ # # ]: 0 : if (gwr%tchi_space == "itau") comment = " (iq_ibz, itau) table"
5613 [ # # ]: 0 : else if (what == "wc_qibz") then
5614 : 0 : mats => gwr%wc_qibz
5615 [ # # ]: 0 : if (gwr%wc_space == "iomega") comment = " (iq_ibz, iomega) table"
5616 [ # # ]: 0 : if (gwr%wc_space == "itau") comment = " (iq_ibz, itau) table"
5617 : : end if
5618 : :
5619 [ # # ]: 0 : do my_is=1,gwr%my_nspins
5620 : 0 : spin = gwr%my_spins(my_is)
5621 [ # # ]: 0 : do my_it=1,gwr%my_ntau
5622 : 0 : itau = gwr%my_itaus(my_it)
5623 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
5624 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
5625 : 0 : ctrace3(iq_ibz, itau, spin) = mats(iq_ibz, itau, spin)%get_trace() / gwr%np_qibz(iq_ibz)
5626 : : end do
5627 : : end do
5628 : : end do
5629 : :
5630 : 0 : call xmpi_sum_master(ctrace3, 0, gwr%kts_comm%value, ierr)
5631 : :
5632 [ # # ]: 0 : if (gwr%comm%me == master) then
5633 [ # # ]: 0 : do spin=1,gwr%nsppol
5634 : 0 : call wrtout(units, sjoin(" Trace of:", what, "for spin:", itoa(spin), "for testing purposes:"))
5635 : 0 : call wrtout(units, comment, pre_newlines=2)
5636 : 0 : call print_arr(units, ctrace3(:,:,spin))
5637 : : end do
5638 : : end if
5639 [ # # ]: 0 : ABI_FREE(ctrace3)
5640 : :
5641 : : case ("gt_kibz")
5642 : : ! Trace of Green's functions.
5643 [ # # # # : 0 : ABI_CALLOC(ctrace5, (gwr%nkibz, gwr%ntau, 2, gwr%nsppol, gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
5644 : :
5645 [ # # ]: 0 : do my_is=1,gwr%my_nspins
5646 : 0 : spin = gwr%my_spins(my_is)
5647 [ # # ]: 0 : do my_it=1,gwr%my_ntau
5648 : 0 : itau = gwr%my_itaus(my_it)
5649 [ # # ]: 0 : do my_iki=1,gwr%my_nkibz
5650 : 0 : ik_ibz = gwr%my_kibz_inds(my_iki)
5651 [ # # ]: 0 : do ipm=1,2
5652 [ # # ]: 0 : do iab=1,gwr%nsig_ab
5653 : 0 : ctrace5(ik_ibz, itau, ipm, spin, iab) = gwr%gt_kibz(ipm, ik_ibz, itau, spin, iab)%get_trace() / gwr%np_kibz(ik_ibz)
5654 : : end do
5655 : : end do
5656 : : end do
5657 : : end do
5658 : : end do
5659 : 0 : comment = " (ik_ibz, itau) table"
5660 : :
5661 : 0 : call xmpi_sum_master(ctrace5, master, gwr%kts_comm%value, ierr)
5662 : :
5663 [ # # ]: 0 : if (gwr%comm%me == master) then
5664 [ # # ]: 0 : do spin=1,gwr%nsppol
5665 [ # # ]: 0 : do ipm=1,2
5666 [ # # ]: 0 : do iab=1,gwr%nsig_ab
5667 [ # # ]: 0 : if (gwr%nspinor == 2) then
5668 : 0 : call wrtout(units, sjoin(" Trace of:", what, "for ipm:", itoa(ipm), ", spin:", itoa(spin), ", iab:", itoa(iab), "for testing purposes:"))
5669 : : else
5670 : 0 : call wrtout(units, sjoin(" Trace of:", what, "for ipm:", itoa(ipm), ", spin:", itoa(spin), "for testing purposes:"))
5671 : : end if
5672 : 0 : call wrtout(units, comment, newlines=1)
5673 : 0 : call print_arr(units, ctrace5(:,:, ipm, spin, iab))
5674 : : end do
5675 : : end do
5676 : : end do
5677 : : end if
5678 [ # # ]: 0 : ABI_FREE(ctrace5)
5679 : :
5680 : : case default
5681 : 0 : ABI_ERROR(sjoin("Invalid value of what:", what))
5682 : : end select
5683 : :
5684 [ # # # # : 0 : end subroutine gwr_print_trace
# # # ]
5685 : : !!***
5686 : :
5687 : : !----------------------------------------------------------------------
5688 : :
5689 : : !!****f* m_gwr/gwr_build_wc
5690 : : !! NAME
5691 : : !! gwr_build_wc
5692 : : !!
5693 : : !! FUNCTION
5694 : : !! Compute Wc(i tau,g,g') from tchi(i omega,g,g')
5695 : : !!
5696 : : !! INPUTS
5697 : : !!
5698 : : !! OUTPUT
5699 : : !!
5700 : : !! SOURCE
5701 : :
5702 : 0 : subroutine gwr_build_wc(gwr)
5703 : :
5704 : : !Arguments ------------------------------------
5705 : : class(gwr_t),target,intent(inout) :: gwr
5706 : :
5707 : : !Local variables-------------------------------
5708 : : !scalars
5709 : : integer,parameter :: master = 0
5710 : : integer :: my_iqi, my_it, my_is, iq_ibz, spin, itau, iw, ierr, npwe
5711 : : integer :: il_g1, il_g2, ig1, ig2, iglob1, iglob2, ig0
5712 : : real(dp) :: cpu_all, wall_all, gflops_all, cpu_q, wall_q, gflops_q, i_sz !, cpu_tmp, wall_tmp, gflops_tmp
5713 : : logical :: q_is_gamma, free_tchi, print_time, keep_wcimw
5714 : : character(len=5000) :: msg
5715 : : complex(dp) :: vcs_g1, vcs_g2
5716 [ # # # # : 0 : type(__slkmat_t) :: em1
# # ]
5717 : : type(yamldoc_t) :: ydoc
5718 : : !arrays
5719 : : integer :: units(2)
5720 : : real(dp) :: qq_ibz(3), tsec(2)
5721 : 0 : complex(dp) :: em1_wq(gwr%ntau, gwr%nqibz), eps_wq(gwr%ntau, gwr%nqibz)
5722 : : ! *************************************************************************
5723 : :
5724 : : ABI_NVTX_START_RANGE(NVTX_GWR_BUILD_WC)
5725 [ # # ]: 0 : units = [std_out, ab_out]
5726 : :
5727 : 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
5728 : 0 : call timab(1924, 1, tsec)
5729 : 0 : call wrtout(units, " Building correlated screening Wc(i omega) ...", pre_newlines=2)
5730 : :
5731 : 0 : call gwr%vcgen_eps%print(units, " Info on Coulomb term used in epsilon and W", gwr%dtset%prtvol)
5732 : :
5733 [ # # ]: 0 : ABI_CHECK(gwr%tchi_space == "iomega", sjoin("tchi_space: ", gwr%tchi_space, " != iomega"))
5734 : :
5735 [ # # ]: 0 : if (allocated(gwr%wc_qibz)) then
5736 : 0 : call slk_array_free(gwr%wc_qibz)
5737 [ # # # # : 0 : ABI_FREE(gwr%wc_qibz)
# # # # #
# ]
5738 : 0 : gwr%wc_space = "none"
5739 : : end if
5740 : :
5741 [ # # ]: 0 : ABI_CHECK(gwr%wc_space == "none", sjoin("wc_space: ", gwr%wc_space, " != none"))
5742 : 0 : gwr%wc_space = "iomega"
5743 : :
5744 : : ! =======================================
5745 : : ! Allocate PBLAS arrays for wc_qibz(g,g')
5746 : : ! =======================================
5747 : : ! Note that we have already summed tchi over spin.
5748 : : ! Also, G=0 corresponds to iglob = 1 as only q-points in the IBZ are treated here.
5749 : : ! This is not true for the other q-points in the full BZ as we may have a non-zero umklapp g0_q.
5750 [ # # # # : 0 : ABI_MALLOC(gwr%wc_qibz, (gwr%nqibz, gwr%ntau, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
5751 : :
5752 : 0 : free_tchi = .True.; if (free_tchi) gwr%tchi_space = "none"
5753 [ # # # # : 0 : em1_wq = zero; eps_wq = zero
# # # # ]
5754 : :
5755 : : ! If possible, use 2d rectangular grid of processors for diagonalization.
5756 : : !call slkproc_4diag%init(gwr%g_comm%value)
5757 : :
5758 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
5759 [ # # # # : 0 : print_time = gwr%comm%me == 0 .and. (my_iqi <= LOG_MODK .or. mod(my_iqi, LOG_MODK) == 0)
# # ]
5760 : 0 : if (print_time) call cwtime(cpu_q, wall_q, gflops_q, "start")
5761 [ # # ]: 0 : iq_ibz = gwr%my_qibz_inds(my_iqi); qq_ibz = gwr%qibz(:, iq_ibz)
5762 : 0 : q_is_gamma = normv(qq_ibz, gwr%cryst%gmet, "G") < GW_TOLQ0
5763 : :
5764 : : associate (desc_q => gwr%tchi_desc_qibz(iq_ibz))
5765 : 0 : ig0 = desc_q%ig0
5766 : 0 : npwe = desc_q%npw
5767 : :
5768 : : ! The spin loop is needed so that procs in different pools can operate
5769 : : ! on their own matrix that has been already summed over (collinear) spins.
5770 [ # # ]: 0 : do my_is=1,gwr%my_nspins
5771 : 0 : spin = gwr%my_spins(my_is)
5772 [ # # ]: 0 : do my_it=1,gwr%my_ntau
5773 : 0 : itau = gwr%my_itaus(my_it)
5774 : :
5775 : : ! Build symmetrized RPA epsilon: 1 - Vc^{1/2} chi0 Vc^{1/2}
5776 : : ! Note vc_sqrt_eps here.
5777 : 0 : associate (wc => gwr%wc_qibz(iq_ibz, itau, spin))
5778 : 0 : call gwr%tchi_qibz(iq_ibz, itau, spin)%copy(wc)
5779 : 0 : if (free_tchi) call gwr%tchi_qibz(iq_ibz, itau, spin)%free()
5780 : :
5781 [ # # ]: 0 : do il_g2=1,wc%size_local(2)
5782 : 0 : iglob2 = wc%loc2gcol(il_g2)
5783 : 0 : ig2 = mod(iglob2 - 1, desc_q%npw) + 1
5784 : 0 : vcs_g2 = desc_q%vc_sqrt_eps(ig2)
5785 [ # # ]: 0 : do il_g1=1,wc%size_local(1)
5786 : 0 : iglob1 = wc%loc2grow(il_g1)
5787 : 0 : ig1 = mod(iglob1 - 1, desc_q%npw) + 1
5788 : 0 : vcs_g1 = desc_q%vc_sqrt_eps(ig1)
5789 : 0 : wc%buffer_cplx(il_g1, il_g2) = -wc%buffer_cplx(il_g1, il_g2) * vcs_g1 * vcs_g2
5790 [ # # ]: 0 : if (iglob1 == iglob2) then
5791 : 0 : wc%buffer_cplx(il_g1, il_g2) = one + wc%buffer_cplx(il_g1, il_g2)
5792 [ # # ]: 0 : if (iglob1 == ig0 .and. iglob2 == ig0) then
5793 : : ! Store epsilon_{iw, iq_ibz}(0, 0). Rescale by np_qibz because we will MPI reduce this array.
5794 : 0 : eps_wq(itau, iq_ibz) = wc%buffer_cplx(il_g1, il_g2) / gwr%np_qibz(iq_ibz)
5795 : : end if
5796 : : end if
5797 : : end do ! il_g1
5798 : : end do ! il_g2
5799 : :
5800 : : ! Invert symmetrized epsilon.
5801 : : ! NB: PZGETRF requires square block cyclic decomposition along the two axes
5802 : : ! hence we have to redistribute the data before calling invert and then
5803 : : ! go back to colum-distribution, that is: wc --> em1 --> wc
5804 : :
5805 : 0 : call wc%change_size_blocs(em1) ! processor=slkproc_4diag
5806 : : ! Use hpd_invert as eps along imag axis is always hermitian.
5807 : : !call em1%invert()
5808 : 0 : call em1%hpd_invert("U")
5809 : 0 : call wc%take_from(em1, free=.True.) ! processor=wc%processor)
5810 : :
5811 : : !call wrtout(std_out, sjoin(" e-1 at q:", ktoa(qq_ibz), "i omega:", ftoa(gwr%iw_mesh(itau) * Ha_eV), "eV"))
5812 : : !call print_arr(units, wc%buffer_cplx)
5813 : :
5814 : : ! Build Wc(q, iw) = e^{-1}_q(g,g',iw) - delta_{gg'} v_q(g,g') by removing bare vc.
5815 [ # # ]: 0 : do il_g2=1,wc%size_local(2)
5816 : 0 : iglob2 = wc%loc2gcol(il_g2)
5817 : 0 : ig2 = mod(iglob2 - 1, desc_q%npw) + 1
5818 : 0 : vcs_g2 = desc_q%vc_sqrt_eps(ig2)
5819 [ # # ]: 0 : if (gwr%has_vcgen_sigma) vcs_g2 = desc_q%vc_sqrt_sigma(ig2)
5820 [ # # ]: 0 : do il_g1=1,wc%size_local(1)
5821 : 0 : iglob1 = wc%loc2grow(il_g1)
5822 : 0 : ig1 = mod(iglob1 - 1, desc_q%npw) + 1
5823 : 0 : vcs_g1 = desc_q%vc_sqrt_eps(ig1)
5824 [ # # ]: 0 : if (gwr%has_vcgen_sigma) vcs_g1 = desc_q%vc_sqrt_sigma(ig1)
5825 : :
5826 [ # # ]: 0 : if (iglob1 == ig0 .and. iglob2 == ig0) then
5827 : : ! Store epsilon^{-1}_{iw, iq_ibz}(0, 0). Rescale by np_qibz because we will MPI reduce this array.
5828 : 0 : em1_wq(itau, iq_ibz) = wc%buffer_cplx(il_g1, il_g2) / gwr%np_qibz(iq_ibz)
5829 : : end if
5830 : :
5831 : : ! Subtract exchange part.
5832 [ # # ]: 0 : if (iglob1 == iglob2) wc%buffer_cplx(il_g1, il_g2) = wc%buffer_cplx(il_g1, il_g2) - one
5833 : :
5834 : : ! Handle divergence in Wc for q --> 0
5835 : : ! Here we always use vcgen_eps
5836 : 0 : i_sz = gwr%vcgen_eps%i_sz
5837 [ # # ]: 0 : if (gwr%has_vcgen_sigma) i_sz = gwr%vcgen_sigma%i_sz
5838 : :
5839 [ # # # # ]: 0 : if (q_is_gamma .and. (iglob1 == ig0 .or. iglob2 == ig0)) then
5840 [ # # ]: 0 : if (iglob1 == ig0 .and. iglob2 == ig0) then
5841 : 0 : vcs_g1 = sqrt(i_sz); vcs_g2 = sqrt(i_sz)
5842 [ # # ]: 0 : else if (iglob1 == ig0) then
5843 : 0 : vcs_g1 = sqrt(i_sz)
5844 [ # # ]: 0 : else if (iglob2 == ig0) then
5845 : 0 : vcs_g2 = sqrt(i_sz)
5846 : : end if
5847 : : end if
5848 : :
5849 : 0 : wc%buffer_cplx(il_g1, il_g2) = wc%buffer_cplx(il_g1, il_g2) * vcs_g1 * vcs_g2 / gwr%cryst%ucvol
5850 : : end do ! il_g1
5851 : : end do ! il_g2
5852 : : end associate
5853 : :
5854 : : end do ! my_it
5855 : : end do ! my_is
5856 : : end associate
5857 : :
5858 [ # # ]: 0 : if (print_time) then
5859 : 0 : write(msg,'(4x,2(a,i0),a)')"My iq_ibz [", my_iqi, "/", gwr%my_nqibz, "]"
5860 : 0 : call cwtime_report(msg, cpu_q, wall_q, gflops_q)
5861 : : end if
5862 : : end do ! my_iqi
5863 : :
5864 : : !call slkproc_4diag%free()
5865 : :
5866 : 0 : call xmpi_sum_master(em1_wq, master, gwr%kgt_comm%value, ierr)
5867 : 0 : call xmpi_sum_master(eps_wq, master, gwr%kgt_comm%value, ierr)
5868 : :
5869 [ # # ]: 0 : if (gwr%comm%me == master) then
5870 : : ! Print results to ab_out for testing purposes.
5871 : 0 : ydoc = yamldoc_open('EMACRO_WITHOUT_LOCAL_FIELDS') !, width=11, real_fmt='(3f8.3)')
5872 : 0 : call ydoc%open_tabular("epsilon_{iw, q -> Gamma}(0,0)") ! comment="(iomega, iq_ibz)")
5873 [ # # ]: 0 : do iw=1,gwr%ntau
5874 : 0 : write(msg, "(3(es16.8,2x))") gwr%iw_mesh(iw), real(eps_wq(iw, 1)), aimag(eps_wq(iw, 1))
5875 : 0 : call ydoc%add_tabular_line(msg)
5876 : : end do
5877 : 0 : call ydoc%write_units_and_free(units)
5878 : :
5879 : 0 : ydoc = yamldoc_open('EMACRO_WITH_LOCAL_FIELDS') !, width=11, real_fmt='(3f8.3)')
5880 : 0 : call ydoc%open_tabular("epsilon_{iw, q -> Gamma}(0,0)") !, comment="(iomega, iq_ibz)")
5881 [ # # ]: 0 : do iw=1,gwr%ntau
5882 : 0 : write(msg, "(3(es16.8,2x))") gwr%iw_mesh(iw), real(em1_wq(iw, 1)), aimag(em1_wq(iw, 1))
5883 : 0 : call ydoc%add_tabular_line(msg)
5884 : : end do
5885 : 0 : call ydoc%write_units_and_free(units)
5886 : : end if
5887 : :
5888 : : ! Print trace of wc_q(iomega) matrices for testing purposes.
5889 [ # # ]: 0 : if (gwr%dtset%prtvol > 0) call gwr%print_trace(units, "wc_qibz")
5890 : :
5891 : : ! Write file with Wc(i omega)
5892 : 0 : keep_wcimw = .False.
5893 [ # # ]: 0 : if (gwr%dtset%prtsuscep == -1) then
5894 [ # # ]: 0 : call gwr%ncwrite_tchi_wc("wc", "omega", keep_wcimw, trim(gwr%dtfil%filnam_ds(4))//'_WCIM.nc')
5895 : 0 : keep_wcimw = .True.
5896 : : end if
5897 : :
5898 : : ! Cosine transform from iomega to itau to get Wc(i tau)
5899 : 0 : call gwr%cos_transform("wc", "iw2t")
5900 : :
5901 : : ! Print trace of wc_q(itau) matrices for testing purposes.
5902 : : ! if (gwr%dtset%prtvol > 0) call gwr%print_trace(units, "wc_qibz")
5903 : :
5904 : : ! Write file with Wc(i tau)
5905 [ # # ]: 0 : if (abs(gwr%dtset%prtsuscep) == 1) then
5906 [ # # ]: 0 : call gwr%ncwrite_tchi_wc("wc", "tau", keep_wcimw, trim(gwr%dtfil%filnam_ds(4))//'_WCIM.nc')
5907 : : end if
5908 : :
5909 : : ! Print trace of wc_q(iomega) matrices for testing purposes.
5910 : : !if (gwr%dtset%prtvol > 0) call gwr%print_trace(units, "wc_qibz")
5911 : :
5912 : 0 : call cwtime_report(" gwr_build_wc:", cpu_all, wall_all, gflops_all)
5913 : 0 : call timab(1924, 2, tsec)
5914 : : ABI_NVTX_END_RANGE()
5915 : :
5916 [ # # # # ]: 0 : end subroutine gwr_build_wc
5917 : : !!***
5918 : :
5919 : : !----------------------------------------------------------------------
5920 : :
5921 : : !!****f* m_gwr/gwr_build_sigmac
5922 : : !! NAME
5923 : : !! gwr_build_sigmac
5924 : : !!
5925 : : !! FUNCTION
5926 : : !! Build Sigma_c(i tau) and compute matrix elements in the KS basis set.
5927 : : !!
5928 : : !! INPUTS
5929 : : !!
5930 : : !! OUTPUT
5931 : : !!
5932 : : !! SOURCE
5933 : :
5934 : 0 : subroutine gwr_build_sigmac(gwr)
5935 : :
5936 : : !Arguments ------------------------------------
5937 : : class(gwr_t),target,intent(inout) :: gwr
5938 : :
5939 : : !Local variables-------------------------------
5940 : : !scalars
5941 : : integer,parameter :: master = 0
5942 : : integer :: my_is, my_it, spin, ikcalc_ibz, ik_ibz, sc_nfft, my_ir, my_nr, iw, idat, max_ndat, ndat, ii, jj, irow, iab, iiab, jiab, itim
5943 : : integer :: iq_ibz, iq_bz, itau, ierr, ibc, ib1, ib2, bmin, bmax, band, band1, ifft, gpu_option
5944 : : integer :: band2, band2_start, band2_stop, nbc
5945 : : integer :: my_ikf, ipm, ik_bz, ikcalc, uc_ir, ir, ncid, col_bsize, nr, sc_nfftsp, iter_ncid
5946 : : integer :: isym_k, trev_k, g0_k(3), tsign_k !, b1gw, b2gw, ! my_iqi, sc_ir, ig, my_iqf
5947 : : integer :: gt_request, wct_request
5948 : : integer :: band_val, ibv, unt_it, unt_iw, unt_rw ! ncerr,
5949 : : integer(kind=XMPI_ADDRESS_KIND) :: buf_count
5950 : : integer :: gt_scbox_win, wct_scbox_win, use_umklp, ideg, nstates, nb1, nb2, nspinor
5951 : : integer(c_size_t) :: bufsize
5952 : : !integer :: my_ikf_start, my_ikf_stop, nkf_batch_size, nkf_now, op_type
5953 : : real(dp) :: e0, ks_gap, qp_gap, qp_pade_gap, sigx, vxc_val, vu, v_meanf, eshift, sigma_fact
5954 : : real(dp) :: cpu_tau, wall_tau, gflops_tau, cpu_all, wall_all, gflops_all !, cpu, wall, gflops
5955 : : real(dp) :: mem_mb, cpu_ir, wall_ir, gflops_ir, cpu_ikf, wall_ikf, gflops_ikf
5956 : : real(dp) :: max_abs_imag_wct, max_abs_re_wct, sck_ucvol, scq_ucvol, beta_r
5957 : : real(gwp) :: wtqm, wtqp
5958 : : complex(dp) :: zz, zsc, sigc_e0__, dsigc_de0, z_e0, sig_xc, hhartree_bk, qp_ene, qp_ene_prev, alpha_c, sigc_zsc
5959 : : logical :: k_is_gamma, use_shmem_for_k, use_mpi_for_k, isirr_k, do_sigma_fit
5960 : : logical :: compute_this_kbz, print_time, sigc_is_herm, band_inversion ! define,
5961 : : character(len=500) :: msg, gpu_action
5962 : 0 : type(gaps_t) :: new_gaps
5963 : : type(yamldoc_t) :: ydoc
5964 : : type(c_ptr) :: void_ptr
5965 : 0 : type(sigma_pade_t) :: spade
5966 : : !arrays
5967 : 0 : integer :: sc_ngfft(18), need_qibz(gwr%nqibz), got_qibz(gwr%nqibz), units(2), dat_units(3), g0_q(3) ! gg(3),
5968 : 0 : integer,allocatable :: green_scgvec(:,:), wc_scgvec(:,:)
5969 : 0 : logical :: select_my_kbz(gwr%my_nkbz), select_my_qbz(gwr%my_nqbz)
5970 : : real(dp) :: kk_bz(3), kcalc_bz(3), qq_bz(3), tsec(2) !, qq_ibz(3)
5971 : 0 : real(dp),allocatable :: betas_r(:,:,:), zcut_pm(:,:,:)
5972 : : complex(gwp) :: cpsi_r, sigc_pm(2)
5973 : 0 : complex(dp) :: odd_t(gwr%ntau), even_t(gwr%ntau), avg_2ntau(2,gwr%ntau), cvals(gwr%ntau)
5974 : 0 : complex(dp),target,allocatable :: sigc_it_mat(:,:,:,:,:,:), alphas_c(:,:,:)
5975 : 0 : complex(gwp),allocatable :: loc_cwork(:)
5976 : 0 : complex(gwp) ABI_ASYNC, contiguous, pointer :: gt_scbox(:,:,:), wct_scbox(:,:)
5977 : 0 : complex(gwp),allocatable :: uc_psir_bk(:,:,:), scph1d_kcalc(:,:,:), uc_ceikr(:), ur(:), ucpsi_r(:)
5978 [ # # # # : 0 : type(__slkmat_t) :: gt_gpr(2, gwr%my_nkbz, gwr%nsig_ab), gk_rpr_pm(2, gwr%nsig_ab), wc_rpr, wc_gpr(gwr%my_nqbz)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
5979 [ # # # # : 0 : type(__slkmat_t), target :: sigc_rpr(2,2,gwr%nkcalc, gwr%nsig_ab)
# # # # #
# # # # #
# # # # #
# # # ]
5980 [ # # # # : 0 : type(desc_t), target :: desc_mykbz(gwr%my_nkbz), desc_myqbz(gwr%my_nqbz)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
5981 : : type(fftbox_plan3_t) :: green_plan, wt_plan
5982 [ # # # # : 0 : type(littlegroup_t) :: ltg_kcalc(gwr%nkcalc)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
5983 : : integer, parameter :: spinor_idxs(2, 4) = RESHAPE([1, 1, 2, 2, 1, 2, 2, 1], [2, 4])
5984 : 0 : integer,allocatable :: iperm(:)
5985 : 0 : real(dp),allocatable :: sorted_qpe(:)
5986 : 0 : real(dp) :: e0_kcalc(gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol), rw_mesh(gwr%nwr)
5987 : 0 : real(dp) :: spfunc_diag(gwr%nwr, gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol)
5988 : 0 : integer :: pade_solver_ierr(gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol)
5989 : 0 : real(dp) :: ks_gaps(gwr%nkcalc, gwr%nsppol), qpz_gaps(gwr%nkcalc, gwr%nsppol), qp_pade_gaps(gwr%nkcalc, gwr%nsppol)
5990 : 0 : complex(dp) :: ze0_kcalc(gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol)
5991 : 0 : complex(dp) :: sigc_e0(gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol)
5992 : 0 : complex(dp) :: qpz_ene(gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol), imag_zmesh(gwr%ntau)
5993 : 0 : complex(dp) :: qp_pade(gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol)
5994 : 0 : complex(dp) :: sigxc_rw_diag(gwr%nwr, gwr%b1gw:gwr%b2gw, gwr%nkcalc, gwr%nsppol)
5995 : : !complex(gwp),contiguous, pointer :: buf_cplx(:,:)
5996 : 0 : type(sigijtab_t),allocatable :: Sigxij_tab(:,:), Sigcij_tab(:,:)
5997 : : ! *************************************************************************
5998 : :
5999 : 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
6000 : 0 : call timab(1925, 1, tsec)
6001 : :
6002 : 0 : nspinor = gwr%nspinor
6003 [ # # ]: 0 : units = [std_out, ab_out]
6004 : 0 : gpu_option = gwr%dtset%gpu_option
6005 [ # # ]: 0 : if (gwr%sig_diago) then
6006 : 0 : call wrtout(units, " Computing diagonal matrix elements of Sigma_c", pre_newlines=1)
6007 : : else
6008 : 0 : call wrtout(units, " Computing diagonal + off-diagonal matrix elements of Sigma_c", pre_newlines=1)
6009 : : end if
6010 : :
6011 [ # # ]: 0 : if (gwr%has_vcgen_sigma) then
6012 : 0 : call gwr%vcgen_sigma%print(units, " Info on Coulomb term used in Sigma_c", gwr%dtset%prtvol)
6013 : : else
6014 : 0 : call gwr%vcgen_eps%print(units, " Info on Coulomb term used in Sigma_c", gwr%dtset%prtvol)
6015 : : end if
6016 : :
6017 [ # # ]: 0 : ABI_CHECK(gwr%wc_space == "itau", sjoin("wc_space: ", gwr%wc_space, " != itau"))
6018 : :
6019 : : !mask_kibz = 0; mask_kibz(gwr%my_kibz_inds(:)) = 1
6020 : : !call gwr%malloc_free_mats(mask_kibz, "sigma" "malloc")
6021 : :
6022 : : !if (gwr%scf_iteration == 1) then
6023 : : !else
6024 : : !end if
6025 : :
6026 : : ! Set FFT mesh in the supercell.
6027 : : ! Be careful when using the FFT plan as ndat can change inside the loop if we start to block.
6028 : : ! Perhaps the safest approach would be to generate the plan on the fly.
6029 : :
6030 [ # # ]: 0 : sc_ngfft = gwr%g_ngfft
6031 [ # # ]: 0 : sc_ngfft(1:3) = gwr%ngkpt * gwr%g_ngfft(1:3)
6032 [ # # ]: 0 : sc_ngfft(4:6) = sc_ngfft(1:3)
6033 [ # # ]: 0 : sc_nfft = product(sc_ngfft(1:3)); sc_nfftsp = sc_nfft !* gwr%nspinor
6034 : : !sc_mgfft = maxval(sc_ngfft(1:3))
6035 [ # # ]: 0 : sck_ucvol = gwr%cryst%ucvol * product(gwr%ngkpt)
6036 [ # # ]: 0 : scq_ucvol = gwr%cryst%ucvol * product(gwr%ngqpt)
6037 : :
6038 : : ! Set FFT mesh used to compute u(r) in the unit cell.
6039 : 0 : call gwr%kcalc_wfd%change_ngfft(gwr%cryst, gwr%psps, gwr%g_ngfft)
6040 : :
6041 : : ! Table for \Sigmac_ij matrix elements.
6042 : 0 : sigc_is_herm = .False.
6043 : : call sigtk_sigma_tables(gwr%nkcalc, gwr%nkibz, gwr%nsppol, gwr%bstart_ks, gwr%bstop_ks, gwr%kcalc2ibz(:,1), &
6044 : 0 : gwr%sig_diago, sigc_is_herm, sigxij_tab, sigcij_tab)
6045 : :
6046 : 0 : call sigijtab_free(Sigxij_tab)
6047 [ # # # # : 0 : ABI_FREE(Sigxij_tab)
# # # # #
# # # ]
6048 : :
6049 : : ! Allocate matrix elements Sigmac_(itau) in the KS basis set.
6050 : 0 : ii = gwr%b1gw; jj = gwr%b2gw
6051 [ # # ]: 0 : if (gwr%sig_diago) then
6052 : 0 : ii = 1; jj = 1
6053 : : end if
6054 [ # # # # : 0 : ABI_CALLOC(sigc_it_mat, (2, gwr%ntau, gwr%b1gw:gwr%b2gw, ii:jj, gwr%nkcalc, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
6055 [ # # # # : 0 : ABI_RECALLOC(gwr%sigc_iw_mat, (gwr%ntau, gwr%b1gw:gwr%b2gw, ii:jj, gwr%nkcalc, gwr%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
6056 : :
6057 : 0 : do_sigma_fit = (iand(gwr%dtset%gwr_fit, SIGMA_FIT) /= 0)
6058 [ # # # # : 0 : ABI_CALLOC(alphas_c, (2, gwr%b1gw:gwr%b2gw, ii:jj))
# # # # #
# # # # #
# # # # #
# # # ]
6059 [ # # # # : 0 : ABI_CALLOC(betas_r, (2, gwr%b1gw:gwr%b2gw, ii:jj))
# # # # #
# # # # #
# # # # #
# # # ]
6060 [ # # # # : 0 : ABI_CALLOC(zcut_pm, (2, gwr%b1gw:gwr%b2gw, ii:jj))
# # # # #
# # # # #
# # # # ]
6061 [ # # # # : 0 : zcut_pm = gwr%dtset%zcut
# # ]
6062 : :
6063 [ # # ]: 0 : if (do_sigma_fit) then
6064 : 0 : call wrtout(units, " Activating fit of sigma matrix elements in tau space")
6065 : : end if
6066 : :
6067 : 0 : max_abs_imag_wct = zero; max_abs_re_wct = zero
6068 [ # # ]: 0 : call gwr%print_mem([std_out])
6069 : :
6070 [ # # ]: 0 : if (gwr%use_supercell_for_sigma) then
6071 : :
6072 : : ! NOTE:
6073 : : ! There are two possibilities here:
6074 : : !
6075 : : ! 1) Compute the matrix elements of Sigma_c in the KS basis set by integrating over the real-space supercell.
6076 : : !
6077 : : ! 2) Compute and store Sigma_c^k(g,g',iomega) and then compute the matrix elements in g-space.
6078 : : !
6079 : : ! The first option requires less memory provided we are interested in a small set of KS states.
6080 : : ! The second option is interesting if we need to compute several matrix elements, including off-diagonal terms.
6081 : 0 : call print_sigma_header()
6082 : :
6083 : 0 : max_ndat = gwr%sc_batch_size
6084 : : use_mpi_for_k = gwr%sc_batch_size > 1 .and. gwr%sc_batch_size == gwr%kpt_comm%nproc
6085 : 0 : use_mpi_for_k = .False.
6086 : :
6087 [ # # # # ]: 0 : use_shmem_for_k = gwr%sc_batch_size == gwr%kpt_comm%nproc .and. gwr%kpt_comm%nproc > 1
6088 [ # # # # ]: 0 : use_shmem_for_k = use_shmem_for_k .and. gwr%kpt_comm%can_use_shmem()
6089 : : #ifndef HAVE_MPI_ALLOCATE_SHARED_CPTR
6090 : : use_shmem_for_k = .False.
6091 : : #endif
6092 : :
6093 [ # # ]: 0 : if (use_shmem_for_k) then
6094 : 0 : buf_count = 2 * (sc_nfftsp * max_ndat * 2)
6095 : 0 : call gwr%kpt_comm%allocate_shared_master(buf_count, gwp, xmpi_info_null, void_ptr, gt_scbox_win)
6096 [ # # ]: 0 : call c_f_pointer(void_ptr, gt_scbox, shape=[sc_nfftsp, max_ndat, 2])
6097 : 0 : buf_count = 2 * (sc_nfftsp * max_ndat)
6098 : 0 : call gwr%kpt_comm%allocate_shared_master(buf_count, gwp, xmpi_info_null, void_ptr, wct_scbox_win)
6099 [ # # ]: 0 : call c_f_pointer(void_ptr, wct_scbox, shape=[sc_nfftsp, max_ndat])
6100 : : end if
6101 : :
6102 : 0 : call wrtout(std_out, sjoin(" use_mpi_for_k:", yesno(use_mpi_for_k)))
6103 : 0 : call wrtout(std_out, sjoin(" use_shmem_for_k:", yesno(use_shmem_for_k)))
6104 : 0 : mem_mb = 3 * (sc_nfftsp * max_ndat * gwp) * b2Mb
6105 : 0 : call wrtout(std_out, sjoin(" Memory for gt_scbox/wct_scbox arrays:", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
6106 : :
6107 [ # # ]: 0 : if (.not. use_shmem_for_k) then
6108 [ # # # # : 0 : ABI_CALLOC(gt_scbox, (sc_nfft, max_ndat, 2))
# # # # #
# # # # #
# # # # #
# # # #
# ]
6109 [ # # # # : 0 : ABI_CALLOC(wct_scbox, (sc_nfft, max_ndat))
# # # # #
# # # # #
# # # # #
# ]
6110 : : #ifdef HAVE_OPENMP_OFFLOAD
6111 : : !$OMP TARGET ENTER DATA MAP(to:gt_scbox(1:sc_nfft,1:max_ndat,1:2), wct_scbox(1:sc_nfft,1:max_ndat)) IF (gpu_option == ABI_GPU_OPENMP)
6112 : : #endif
6113 : : end if
6114 : :
6115 : : ! Build plans for dense FFTs.
6116 : 0 : call green_plan%from_ngfft(sc_ngfft, max_ndat*2, gpu_option)
6117 : 0 : call wt_plan%from_ngfft(sc_ngfft, max_ndat, gpu_option)
6118 : :
6119 : 0 : sigma_fact = one / (sck_ucvol * scq_ucvol)
6120 : :
6121 : : ! The g-vectors in the supercell for G and tchi.
6122 [ # # # # : 0 : ABI_MALLOC(green_scgvec, (3, gwr%green_mpw))
# # # # #
# # # ]
6123 [ # # # # : 0 : ABI_MALLOC(wc_scgvec, (3, gwr%tchi_mpw))
# # # # #
# # # ]
6124 : :
6125 [ # # # # ]: 0 : select_my_kbz = .True.; select_my_qbz = .True.
6126 : :
6127 [ # # ]: 0 : do my_is=1,gwr%my_nspins
6128 : 0 : spin = gwr%my_spins(my_is)
6129 : :
6130 : : ! Load wavefunctions for GW corrections in the unit cell.
6131 : : ! TODO: MPI distribute or use MPI shared memory
6132 [ # # # # ]: 0 : bmin = minval(gwr%bstart_ks(:, spin)); bmax = maxval(gwr%bstop_ks(:, spin))
6133 [ # # # # : 0 : ABI_MALLOC_OR_DIE(uc_psir_bk, (gwr%g_nfft * gwr%nspinor, bmin:bmax, gwr%nkcalc), ierr)
# # # # #
# # # # #
# # # # #
# # # ]
6134 [ # # # # : 0 : ABI_MALLOC(ur, (gwr%g_nfft * gwr%nspinor))
# # # # #
# # # ]
6135 [ # # # # : 0 : ABI_MALLOC(uc_ceikr, (gwr%g_nfft * gwr%nspinor))
# # # # ]
6136 [ # # # # : 0 : ABI_MALLOC(ucpsi_r, (gwr%g_nfft))
# # # # #
# # # ]
6137 : :
6138 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6139 [ # # ]: 0 : kcalc_bz = gwr%kcalc(:, ikcalc); ikcalc_ibz = gwr%kcalc2ibz(ikcalc, 1) ! NB: Assuming wfs in the IBZ.
6140 : : ! Compute e^{ik.r} phases in the unit cell.
6141 : 0 : call calc_ceikr(kcalc_bz, gwr%g_ngfft, gwr%g_nfft, gwr%nspinor, uc_ceikr)
6142 : :
6143 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6144 : 0 : call gwr%kcalc_wfd%get_ur(band, ikcalc_ibz, spin, ur)
6145 [ # # ]: 0 : uc_psir_bk(:, band, ikcalc) = ur * uc_ceikr
6146 : : end do
6147 : : end do ! ikcalc
6148 : :
6149 [ # # ]: 0 : ABI_FREE(ur)
6150 [ # # ]: 0 : ABI_FREE(uc_ceikr)
6151 : :
6152 : : ! Pre-compute one-dimensional factors to get 3d e^{ik.L}
6153 [ # # ]: 0 : call get_1d_sc_phases(gwr%ngkpt, gwr%nkcalc, gwr%kcalc, scph1d_kcalc)
6154 : :
6155 : : ! Construct Sigma(itau) in the supercell.
6156 [ # # ]: 0 : do my_it=1,gwr%my_ntau
6157 : 0 : call cwtime(cpu_tau, wall_tau, gflops_tau, "start")
6158 : 0 : itau = gwr%my_itaus(my_it)
6159 : :
6160 : : ! G_k(g,g') --> G_k(g',r) e^{ik.r} for each k in the BZ treated by me.
6161 : 0 : call gwr%get_myk_green_gpr(itau, spin, select_my_kbz, desc_mykbz, gt_gpr)
6162 [ # # # # ]: 0 : if (my_it == 1 .and. gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
6163 : :
6164 : : ! Wc_q(g,g') --> Wc_q(g',r) e^{iq.r} for each q in the BZ treated by me.
6165 : 0 : call gwr%get_myq_wc_gpr(itau, spin, select_my_qbz, desc_myqbz, wc_gpr)
6166 [ # # # # ]: 0 : if (my_it == 1 .and. gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
6167 : :
6168 : 0 : my_nr = gt_gpr(1,1,1)%size_local(2)
6169 [ # # ]: 0 : ABI_CHECK(my_nr == wc_gpr(1)%size_local(2), "my_nr != wc_gpr(1)%size_local(2)")
6170 : :
6171 : : ! Loop over r in the unit cell that is now MPI-distributed inside g_comm.
6172 [ # # # # : 0 : do my_ir=1, my_nr, gwr%sc_batch_size
# # # # ]
6173 [ # # # # : 0 : print_time = (gwr%comm%me == 0 .and. (my_ir <= 3 * gwr%sc_batch_size .or. mod(my_ir, LOG_MODR) == 0))
# # ]
6174 : 0 : if (print_time) call cwtime(cpu_ir, wall_ir, gflops_ir, "start")
6175 : 0 : ndat = blocked_loop(my_ir, my_nr, gwr%sc_batch_size)
6176 : 0 : uc_ir = gt_gpr(1,1,1)%loc2gcol(my_ir) ! FIXME: This won't work if nspinor 2
6177 : :
6178 [ # # ]: 0 : if (.not. use_shmem_for_k) then
6179 : : ! Insert Wc_q(g',r) in G'-space in the supercell FFT box (ndat vectors starting at my_ir)
6180 : 0 : call gwr%wcq_to_scbox(sc_ngfft, select_my_qbz, desc_myqbz, wc_scgvec, my_ir, ndat, wc_gpr, wct_scbox)
6181 : : #ifdef HAVE_OPENMP_OFFLOAD
6182 : : !$omp target update to(wct_scbox(1:sc_nfft,1:max_ndat)) if (gpu_option == ABI_GPU_OPENMP)
6183 : : #endif
6184 [ # # ]: 0 : if (gwr%kpt_comm%nproc > 1) call xmpi_isum_ip(wct_scbox, gwr%kpt_comm%value, wct_request, ierr)
6185 : :
6186 : : ! Wc(G',r) --> Wc(R',r)
6187 [ # # ]: 0 : if (gwr%kpt_comm%nproc > 1) call xmpi_wait(wct_request, ierr)
6188 : 0 : call wt_plan%execute(wct_scbox(:,1), -1, max_ndat, iscale=0)
6189 : : else
6190 : : call gwr%wcq_to_scbox(sc_ngfft, select_my_qbz, desc_myqbz, wc_scgvec, my_ir, ndat, wc_gpr, wct_scbox, &
6191 : 0 : wct_scbox_win=wct_scbox_win)
6192 : : end if
6193 : :
6194 : : ! TODO: Should block using nproc in kpt_comm, scatter data and perform multiple FFTs in parallel.
6195 [ # # ]: 0 : do iab=1,gwr%nsig_ab
6196 : 0 : iiab = spinor_idxs(1, iab); jiab = spinor_idxs(2, iab)
6197 [ # # ]: 0 : if (.not. use_shmem_for_k) then
6198 : :
6199 : : ! Insert G_k(g',r) in G'-space in the supercell FFT box (ndat vectors starting at my_ir).
6200 : 0 : call gwr%gk_to_scbox(sc_ngfft, select_my_kbz, desc_mykbz, green_scgvec, my_ir, ndat, gt_gpr(:,:,iab), gt_scbox)
6201 : : #ifdef HAVE_OPENMP_OFFLOAD
6202 : : !$omp target update to(gt_scbox(1:sc_nfft,1:max_ndat,1:2)) if (gpu_option == ABI_GPU_OPENMP)
6203 : : #endif
6204 [ # # ]: 0 : if (gwr%kpt_comm%nproc > 1) call xmpi_isum_ip(gt_scbox, gwr%kpt_comm%value, gt_request, ierr)
6205 : :
6206 : : ! G(G',r) --> G(R',r)
6207 [ # # ]: 0 : if (gwr%kpt_comm%nproc > 1) call xmpi_wait(gt_request, ierr)
6208 : 0 : call green_plan%execute(gt_scbox(:,1,1), -1, max_ndat*2, iscale=0)
6209 : :
6210 : : ! Use gt_scbox to store GW (R',r, +/- i tau) for this set of ndat r-point
6211 : : !gt_scbox(:,:,1) = gt_scbox(:,:,1) * wct_scbox(:,:) * sigma_fact
6212 : : !gt_scbox(:,:,2) = gt_scbox(:,:,2) * wct_scbox(:,:) * sigma_fact
6213 : : #ifdef HAVE_OPENMP_OFFLOAD
6214 : : !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(3) MAP(to:gt_scbox(1:sc_nfft,1:max_ndat,1:2), wct_scbox(1:sc_nfft,1:max_ndat)) if (gpu_option == ABI_GPU_OPENMP)
6215 : : #endif
6216 [ # # ]: 0 : do ipm=1,2
6217 [ # # ]: 0 : do idat=1,max_ndat
6218 [ # # ]: 0 : do ifft=1,sc_nfft
6219 : 0 : gt_scbox(ifft,idat,ipm) = gt_scbox(ifft,idat,ipm) * wct_scbox(ifft,idat) * sigma_fact
6220 : : end do
6221 : : end do
6222 : : end do
6223 : : #ifdef HAVE_OPENMP_OFFLOAD
6224 : : !$omp target update from(gt_scbox(1:sc_nfft,1:max_ndat,1:2)) if (gpu_option == ABI_GPU_OPENMP)
6225 : : #endif
6226 : : !print *, "Maxval abs imag G:", maxval(abs(aimag(gt_scbox)))
6227 : :
6228 : : else
6229 : : ! use_shmem_for_k --> MPI shared window version. Only gt_scbox are wct_scbox are shared.
6230 : : call gwr%gk_to_scbox(sc_ngfft, select_my_kbz, desc_mykbz, green_scgvec, my_ir, ndat, gt_gpr(:,:,iab), gt_scbox, &
6231 : 0 : gt_scbox_win=gt_scbox_win)
6232 : :
6233 : : ! Now each MPI proc operates on different idat entries.
6234 : 0 : call xmpi_win_fence(XMPI_MODE_NOSUCCEED, gt_scbox_win, ierr) ! Start the RMA epoch
6235 : 0 : idat = gwr%kpt_comm%me + 1
6236 [ # # ]: 0 : if (idat <= ndat) then
6237 : 0 : call wt_plan%execute(wct_scbox(:,idat), -1, ndat=1, iscale=0)
6238 [ # # ]: 0 : do ipm=1,2
6239 : 0 : call green_plan%execute(gt_scbox(:,idat,ipm), -1, ndat=1, iscale=0)
6240 [ # # # # : 0 : gt_scbox(:,idat,ipm) = gt_scbox(:,idat,ipm) * wct_scbox(:,idat) * sigma_fact
# # ]
6241 : : end do
6242 : : end if
6243 : : !IF (.not. MPI_ASYNC_PROTECTS_NONBLOCKING) CALL MPI_F_SYNC_REG(gt_scbox)
6244 : : !call xmpi_barrier(gwr%kpt_comm%value)
6245 : 0 : call xmpi_win_fence(XMPI_MODE_NOPRECEDE, gt_scbox_win, ierr) ! End the RMA epoch
6246 : : end if
6247 : :
6248 : : ! Integrate Sigma matrix elements in the R-supercell for ndat r-points and accumulate.
6249 : : ! possibly including off-diagonal terms.
6250 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6251 [ # # ]: 0 : if (gwr%kpt_comm%skip(ikcalc)) cycle ! FIXME: Temporary hack till I find a better MPI algo for k-points.
6252 : 0 : k_is_gamma = normv(gwr%kcalc(:,ikcalc), gwr%cryst%gmet, "G") < GW_TOLQ0
6253 : :
6254 [ # # ]: 0 : do band2=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6255 [ # # ]: 0 : do irow=1,Sigcij_tab(ikcalc, spin)%col(band2)%size1
6256 : 0 : band1 = Sigcij_tab(ikcalc, spin)%col(band2)%bidx(irow)
6257 [ # # ]: 0 : do idat=1,ndat
6258 : : !if (use_shmem_for_k .and. idat /= gwr%kpt_comm + 1) cycle
6259 : 0 : ir = uc_ir + idat - 1
6260 : 0 : cpsi_r = conjg(uc_psir_bk((iiab-1)*gwr%g_nfft + ir, band1, ikcalc))
6261 [ # # # # : 0 : ucpsi_r = uc_psir_bk((jiab-1)*gwr%g_nfft+1:jiab*gwr%g_nfft, band2, ikcalc)
# # # # ]
6262 [ # # ]: 0 : do ipm=1,2
6263 : : call sc_sum(gwr%ngkpt, gwr%g_ngfft, scph1d_kcalc(:,:,ikcalc), k_is_gamma, &
6264 : 0 : cpsi_r, gt_scbox(:,idat,ipm), ucpsi_r, sigc_pm(ipm))
6265 : : end do
6266 [ # # ]: 0 : if (gwr%sig_diago) then
6267 [ # # ]: 0 : sigc_it_mat(:, itau,band1,1,ikcalc,spin) = sigc_it_mat(:,itau,band1,1,ikcalc,spin) + sigc_pm(:)
6268 : : else
6269 [ # # ]: 0 : sigc_it_mat(:,itau,band1,band2,ikcalc,spin) = sigc_it_mat(:,itau,band1,band2,ikcalc,spin) + sigc_pm(:)
6270 : : end if
6271 : : end do ! idat
6272 : : end do
6273 : : end do ! band2
6274 : : end do ! ikcalc
6275 : : end do ! iab
6276 : :
6277 : : !if (use_shmem_for_k) call xmpi_sum
6278 : :
6279 [ # # ]: 0 : if (print_time) then
6280 : 0 : write(msg,'(4x,3(a,i0),a)')"Sigma_c my_ir [", my_ir, "/", my_nr, "] (tot: ", gwr%g_nfft, ")"
6281 : 0 : call cwtime_report(msg, cpu_ir, wall_ir, gflops_ir)
6282 : : end if
6283 : : end do ! my_ir
6284 : :
6285 : : ! Free descriptors and PBLAS matrices in kBZ and qBZ.
6286 : 0 : call desc_array_free(desc_mykbz); call desc_array_free(desc_myqbz)
6287 : 0 : call slk_array_free(gt_gpr); call slk_array_free(wc_gpr)
6288 : :
6289 : 0 : write(msg,'(1x,3(a,i0),a)')"Sigma_c my_itau [", my_it, "/", gwr%my_ntau, "] (tot: ", gwr%ntau, ")"
6290 : 0 : call cwtime_report(msg, cpu_tau, wall_tau, gflops_tau, end_str=ch10)
6291 : : end do ! my_it
6292 : :
6293 [ # # ]: 0 : ABI_FREE(scph1d_kcalc)
6294 [ # # ]: 0 : ABI_FREE(ucpsi_r)
6295 [ # # ]: 0 : ABI_FREE(uc_psir_bk)
6296 : : end do ! my_is
6297 : :
6298 [ # # # # : 0 : sigc_it_mat = -sigc_it_mat * (gwr%cryst%ucvol / gwr%g_nfft) ** 2
# # # # #
# # # ]
6299 : :
6300 : : !call wrtout(std_out, sjoin(" Maxval abs re W:", ftoa(max_abs_re_wct)))
6301 : : !call wrtout(std_out, sjoin(" Maxval abs imag W:", ftoa(max_abs_imag_wct)))
6302 [ # # ]: 0 : if (.not. use_shmem_for_k) then
6303 : : #ifdef HAVE_OPENMP_OFFLOAD
6304 : : !$OMP TARGET EXIT DATA MAP(delete: gt_scbox(1:sc_nfft,1:max_ndat,1:2), wct_scbox(1:sc_nfft,1:max_ndat)) if (gpu_option == ABI_GPU_OPENMP)
6305 : : #endif
6306 [ # # ]: 0 : ABI_FREE(gt_scbox)
6307 [ # # ]: 0 : ABI_FREE(wct_scbox)
6308 : : else
6309 : 0 : call xmpi_win_free(gt_scbox_win, ierr)
6310 : 0 : call xmpi_win_free(wct_scbox_win, ierr)
6311 : : end if
6312 : :
6313 : 0 : call green_plan%free(); call wt_plan%free()
6314 : :
6315 [ # # ]: 0 : ABI_FREE(green_scgvec)
6316 [ # # ]: 0 : ABI_FREE(wc_scgvec)
6317 : :
6318 : : else
6319 : : ! ===================================================================
6320 : : ! Mixed-space algorithm in the unit cell with convolutions in k-space
6321 : : ! ===================================================================
6322 : 0 : call print_sigma_header()
6323 : :
6324 : : ! Define tables to account for symmetries:
6325 : : ! - when looping over the BZ, we only need to include the union of IBZ_x for x in kcalc.
6326 : : ! - when accumulating the self-energy, we have to use weights that depend on x.
6327 : :
6328 : : ! The little group is needed when symsigma == 1
6329 : : ! If use_umklp == 1 then symmetries requiring an umklapp to preserve k_gw are included as well.
6330 : : ! Note that TR is not yet supported so timrev is set to 1 even if TR has been used to generate the GS IBZ.
6331 : 0 : use_umklp = 1
6332 : : !gw_timrev = kpts_timrev_from_kptopt(gwr%ks_ebands%kptopt) + 1
6333 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6334 : 0 : call ltg_kcalc(ikcalc)%init(gwr%kcalc(:,ikcalc), gwr%nkbz, gwr%kbz, gwr%cryst, use_umklp, npwe=0)
6335 [ # # # # ]: 0 : if (gwr%comm%me == 0 .and. gwr%dtset%symsigma /= 0) then
6336 [ # # ]: 0 : call ltg_kcalc(ikcalc)%print([std_out], prtvol=gwr%dtset%prtvol)
6337 : : end if
6338 : : end do
6339 : :
6340 : 0 : call wrtout(std_out, " Allocating PBLAS matrices to store Wc_q(r',r,tau), and Sigma_kcalc(r',r,+/-tau) in the unit cell.")
6341 : 0 : nr = gwr%g_nfft
6342 [ # # ]: 0 : col_bsize = nr / gwr%g_comm%nproc; if (mod(nr, gwr%g_comm%nproc) /= 0) col_bsize = col_bsize + 1
6343 : :
6344 [ # # ]: 0 : call wc_rpr%init(nr, nr, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize])
6345 : :
6346 : 0 : gpu_action = "None"
6347 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) then
6348 : 0 : gpu_action = "alloc"; call wrtout(std_out, " Allocating Sigma_k(r,r', +/-tau) on the GPU...")
6349 : : end if
6350 : :
6351 [ # # ]: 0 : do ipm=1,2
6352 [ # # ]: 0 : do iab=1,gwr%nsig_ab
6353 [ # # ]: 0 : call gk_rpr_pm(ipm, iab)%init(nr, nr, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize])
6354 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6355 [ # # ]: 0 : do itim=1,2
6356 [ # # ]: 0 : call sigc_rpr(itim,ipm,ikcalc, iab)%init(nr, nr, gwr%g_slkproc, 1, size_blocs=[-1, col_bsize], gpu_action=gpu_action)
6357 : : end do
6358 : : end do
6359 : : end do
6360 : : end do
6361 : :
6362 [ # # # # : 0 : mem_mb = slk_array_locmem_mb(wc_rpr) + sum(slk_array_locmem_mb(gk_rpr_pm)) + sum(slk_array_locmem_mb(sigc_rpr))
# # # # #
# # # ]
6363 : 0 : call wrtout(std_out, sjoin(" Local memory for PBLAS (r,r') matrices: ", ftoa(mem_mb, fmt="f8.1"), ' [Mb] <<< MEM'))
6364 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
6365 : :
6366 : 0 : ii = sigc_rpr(1,1,1,1)%size_local(2)
6367 [ # # # # : 0 : ABI_MALLOC(loc_cwork, (ii))
# # # # #
# # # ]
6368 : :
6369 [ # # ]: 0 : do my_is=1,gwr%my_nspins
6370 : 0 : spin = gwr%my_spins(my_is)
6371 : :
6372 : : ! Load wavefunctions for GW corrections in the real-space unit cell.
6373 : : ! TODO: MPI distribute or use MPI shared memory
6374 [ # # # # ]: 0 : bmin = minval(gwr%bstart_ks(:, spin)); bmax = maxval(gwr%bstop_ks(:, spin))
6375 [ # # # # : 0 : ABI_MALLOC_OR_DIE(uc_psir_bk, (nr * gwr%nspinor, bmin:bmax, gwr%nkcalc), ierr)
# # # # #
# # # # #
# # # # #
# # # ]
6376 : : #ifdef HAVE_OPENMP_OFFLOAD
6377 : : !$OMP TARGET ENTER DATA MAP(alloc:uc_psir_bk) IF (gpu_option == ABI_GPU_OPENMP)
6378 : : #endif
6379 : :
6380 : : !! !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(ikcalc_ibz)
6381 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6382 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6383 : 0 : ikcalc_ibz = gwr%kcalc2ibz(ikcalc, 1) ! NB: Assuming wfs in IBZ
6384 : 0 : call gwr%kcalc_wfd%get_ur(band, ikcalc_ibz, spin, uc_psir_bk(:, band, ikcalc))
6385 : : end do
6386 : : end do
6387 : : #ifdef HAVE_OPENMP_OFFLOAD
6388 : : !$omp target update to(uc_psir_bk) if (gpu_option == ABI_GPU_OPENMP)
6389 : : #endif
6390 : :
6391 [ # # ]: 0 : need_qibz = 0
6392 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
6393 [ # # ]: 0 : ik_bz = gwr%my_kbz_inds(my_ikf); kk_bz = gwr%kbz(:, ik_bz)
6394 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6395 [ # # ]: 0 : qq_bz = gwr%kcalc(:,ikcalc) - kk_bz !; qq_bz = -qq_bz
6396 : : ! TODO: here I may need to take into account the umklapp
6397 : 0 : call findqg0(iq_bz, g0_q, qq_bz, gwr%nqbz, gwr%qbz, gwr%mG0)
6398 : : !ABI_CHECK(all(g0_q == 0), sjoin("g0_q != 0, kcalc", ktoa(gwr%kcalc(:,ikcalc)), "kk_bz:", ktoa(kk_bz)))
6399 : 0 : iq_ibz = gwr%qbz2ibz(1, iq_bz)
6400 : 0 : need_qibz(iq_ibz) = 1
6401 : : end do
6402 : : end do
6403 : :
6404 : : ! Construct Sigma(itau) using convolutions in k-space and real-space representation in the unit cell.
6405 [ # # ]: 0 : do my_it=1,gwr%my_ntau
6406 : 0 : call cwtime(cpu_tau, wall_tau, gflops_tau, "start")
6407 : 0 : itau = gwr%my_itaus(my_it)
6408 : :
6409 : : ! Redistribute W_q(g,g') in the IBZ so that each MPI proc can reconstruct Wc_q in the BZ inside the loops
6410 : 0 : call gwr%redistrib_mats_qibz("wc", itau, spin, need_qibz, got_qibz, "communicate")
6411 [ # # # # ]: 0 : if (my_it == 1 .and. gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
6412 : :
6413 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) then
6414 : 0 : call slk_array_gpu_set_zero(sigc_rpr)
6415 : : end if
6416 : : !else
6417 [ # # # # : 0 : call slk_array_set_zero(sigc_rpr)
# # # # ]
6418 : : !end if
6419 : :
6420 : : ! Sum over my k-points in the BZ.
6421 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
6422 [ # # # # : 0 : print_time = (gwr%comm%me == 0 .and. (my_ikf <= LOG_MODK .or. mod(my_ikf, LOG_MODK) == 0))
# # ]
6423 : 0 : if (print_time) call cwtime(cpu_ikf, wall_ikf, gflops_ikf, "start")
6424 [ # # ]: 0 : ik_bz = gwr%my_kbz_inds(my_ikf); kk_bz = gwr%kbz(:,ik_bz)
6425 : :
6426 : 0 : ik_ibz = gwr%kbz2ibz(1, ik_bz); isym_k = gwr%kbz2ibz(2, ik_bz)
6427 : 0 : trev_k = gwr%kbz2ibz(6, ik_bz); g0_k = gwr%kbz2ibz(3:5, ik_bz)
6428 : : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
6429 : : tsign_k = merge(1, -1, trev_k == 0)
6430 : : !if (.not. isirr_k) cycle
6431 : :
6432 : : ! Skip this BZ k-point if it is not in the IBZ(ikcalc) of some ikcalc.
6433 : 0 : compute_this_kbz = .True.
6434 [ # # ]: 0 : if (gwr%dtset%symsigma /= 0) then
6435 : 0 : compute_this_kbz = .False.
6436 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6437 [ # # ]: 0 : if (ltg_kcalc(ikcalc)%ibzq(ik_bz) == 1) then
6438 : : compute_this_kbz = .True.; exit
6439 : : end if
6440 : : end do
6441 : : end if
6442 [ # # ]: 0 : if (.not. compute_this_kbz) cycle ! my_ikf loop
6443 : :
6444 : : ! Use symmetries to get G_kbz from the IBZ then G_k(g,g') --> G_k(r',r)
6445 : 0 : call gwr%get_gkbz_rpr_pm(ik_bz, itau, spin, gk_rpr_pm)
6446 : :
6447 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6448 [ # # # # ]: 0 : if (gwr%dtset%symsigma /= 0 .and. ltg_kcalc(ikcalc)%ibzq(ik_bz) == 0) cycle ! FIXME: iq_bz or ikq?
6449 [ # # ]: 0 : qq_bz = gwr%kcalc(:, ikcalc) - kk_bz !; qq_bz = -qq_bz
6450 : : ! TODO: here I may need to take into account the umklapp
6451 : 0 : call findqg0(iq_bz, g0_q, qq_bz, gwr%nqbz, gwr%qbz, gwr%mG0)
6452 : : !ABI_CHECK(all(g0_q == 0), sjoin("g0_q != 0", ktoa(gwr%kcalc(:,ikcalc)), "kk_bz", ktoa(kk_bz)))
6453 : : !iq_ibz = gwr%qbz2ibz(1, iq_bz)
6454 : 0 : call gwr%get_wc_rpr_qbz(g0_q, iq_bz, itau, spin, wc_rpr)
6455 : :
6456 : : ! The integration weight depends on ikcalc.
6457 : 0 : wtqp = one / gwr%nkbz; wtqm = zero
6458 [ # # ]: 0 : if (gwr%dtset%symsigma /= 0) then
6459 : : ! If symsigma, sum only q"s in IBZ_k, then symmetrize the matrix elements.
6460 : : ! In this case elements are weighted according to wtqp and wtqm. wtqm is for time-reversal.
6461 : : associate (ltg_k => ltg_kcalc(ikcalc))
6462 [ # # ]: 0 : wtqp = (one * sum(ltg_k%wtksym(1,:,ik_bz))) / gwr%nkbz ! FIXME: iq_bz or ik_bz?
6463 [ # # ]: 0 : wtqm = (one * sum(ltg_k%wtksym(2,:,ik_bz))) / gwr%nkbz
6464 : : end associate
6465 : : end if
6466 : :
6467 [ # # ]: 0 : do ipm=1,2
6468 : : !sigc_rpr(1,ipm,ikcalc)%buffer_cplx = sigc_rpr(1,ipm,ikcalc)%buffer_cplx + &
6469 : : ! wtqp * gk_rpr_pm(ipm)%buffer_cplx * wc_rpr%buffer_cplx
6470 [ # # ]: 0 : do iab=1,gwr%nsig_ab
6471 : 0 : bufsize = sigc_rpr(1,ipm,ikcalc,iab)%bufsize
6472 : : call cplx_mat_plus_bc(bufsize, sigc_rpr(1,ipm,ikcalc,iab)%buffer_cplx(:,1), &
6473 : : wtqp, "N", gk_rpr_pm(ipm,iab)%buffer_cplx(:,1), wc_rpr%buffer_cplx(:,1), &
6474 : 0 : gpu_option)
6475 : :
6476 : : call cplx_mat_plus_bc(bufsize, sigc_rpr(2,ipm,ikcalc,iab)%buffer_cplx(:,1), &
6477 : : wtqm, "N", gk_rpr_pm(ipm,iab)%buffer_cplx(:,1), wc_rpr%buffer_cplx(:,1), &
6478 : 0 : gpu_option)
6479 : :
6480 : : !sigc_rpr(1, ipm, ikcalc)%buffer_cplx = sigc_rpr(1, ipm, ikcalc)%buffer_cplx + &
6481 : : ! (wtqp + wtqm) * real(gk_rpr_pm(ipm)%buffer_cplx * wc_rpr%buffer_cplx, kind=gwp) &
6482 : : ! + (wtqp - wtqm) * j_gw * aimag(gk_rpr_pm(ipm)%buffer_cplx * wc_rpr%buffer_cplx)
6483 : : end do ! iab
6484 : : end do ! ipm
6485 : :
6486 : : end do ! ikcalc
6487 : :
6488 [ # # ]: 0 : if (print_time) then
6489 : 0 : write(msg,'(4x,3(a,i0),a)')"Sigma_c my_ikf [", my_ikf, "/", gwr%my_nkbz, "] (tot: ", gwr%nkbz, ")"
6490 : 0 : call cwtime_report(msg, cpu_ikf, wall_ikf, gflops_ikf)
6491 : : end if
6492 : : end do ! my_ikf
6493 : :
6494 : : ! Deallocate extra Wc matrices defined by got_qibz.
6495 : 0 : call gwr%redistrib_mats_qibz("wc", itau, spin, need_qibz, got_qibz, "free")
6496 : :
6497 : : ! Integrate self-energy matrix elements in the unit cell.
6498 : : ! Remember that Sigma is stored as (r',r) and that the second dimension is MPI-distributed.
6499 : : ! In case of k or g distribution, sigc_pm is a partial 6d integral that will be ALL_REDUCED in gwr%comm afterwards.
6500 : : ! TODO: Off-diagonal terms although this is not the most efficient algorithm
6501 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6502 [ # # ]: 0 : do iab=1,gwr%nsig_ab
6503 : 0 : iiab = spinor_idxs(1, iab); jiab = spinor_idxs(2, iab)
6504 [ # # ]: 0 : if (gpu_option == ABI_GPU_OPENMP) then
6505 [ # # ]: 0 : do ipm=1,2
6506 [ # # ]: 0 : do itim=1,2
6507 : 0 : call sigc_rpr(itim,ipm,ikcalc,iab)%gpu_map("update_from")
6508 : : end do
6509 : : end do
6510 : : end if
6511 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6512 : : call sig_braket_ur(sigc_rpr(:,:,ikcalc,iab), gwr%g_nfft, &
6513 : : uc_psir_bk((jiab-1)*gwr%g_nfft+1:jiab*gwr%g_nfft, band, ikcalc), &
6514 : : uc_psir_bk((iiab-1)*gwr%g_nfft+1:iiab*gwr%g_nfft, band, ikcalc), &
6515 : 0 : sigc_pm, loc_cwork)
6516 [ # # # # ]: 0 : if (gwr%sig_diago) sigc_it_mat(:, itau, band, 1, ikcalc, spin) = sigc_it_mat(:, itau, band, 1, ikcalc, spin) + sigc_pm(:)
6517 : : end do ! band
6518 : : end do ! iab
6519 : : end do ! ikcalc
6520 : :
6521 : 0 : write(msg,'(3(a,i0),a)')" Sigma_c my_itau [", my_it, "/", gwr%my_ntau, "] (tot: ", gwr%ntau, ")"
6522 : 0 : call cwtime_report(msg, cpu_tau, wall_tau, gflops_tau)
6523 : : end do ! my_it
6524 : :
6525 : : #ifdef HAVE_OPENMP_OFFLOAD
6526 : : !$OMP TARGET EXIT DATA MAP(delete:uc_psir_bk) IF (gpu_option == ABI_GPU_OPENMP)
6527 : : #endif
6528 [ # # ]: 0 : ABI_FREE(uc_psir_bk)
6529 : : end do ! my_is
6530 : :
6531 [ # # # # : 0 : sigc_it_mat = -sigc_it_mat * (one/gwr%g_nfft) ** 2
# # # # #
# # # ]
6532 : :
6533 [ # # ]: 0 : ABI_FREE(loc_cwork)
6534 : 0 : call wc_rpr%free(); call slk_array_free(sigc_rpr); call slk_array_free(gk_rpr_pm)
6535 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6536 : 0 : call ltg_kcalc(ikcalc)%free()
6537 : : end do
6538 : 0 : call wrtout(std_out, " Mixed space algorithm for sigma completed")
6539 : : end if
6540 : :
6541 [ # # ]: 0 : if (gwr%comm%me == 0) call pstat_proc%print(_PSTAT_ARGS_)
6542 : :
6543 : 0 : call sigijtab_free(Sigcij_tab)
6544 [ # # # # : 0 : ABI_FREE(Sigcij_tab)
# # # # #
# # # ]
6545 : :
6546 : : ! Collect results and average
6547 : 0 : call xmpi_sum(sigc_it_mat, gwr%comm%value, ierr)
6548 : :
6549 : : ! Average over degenerate states.
6550 : : ! if (gwr%dtset%symsigma == +1 .and. .not. gwr%use_supercell_for_sigma) then
6551 [ # # ]: 0 : if (gwr%dtset%symsigma == +1) then
6552 : 0 : call wrtout(std_out, " Symsigma 1 --> Averaging Sig_c matrix elements within degenerate subspaces.")
6553 [ # # ]: 0 : ABI_CHECK(gwr%sig_diago, "symsigma = 1 requires diagonal Sigma_c")
6554 [ # # ]: 0 : do spin=1,gwr%nsppol
6555 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6556 [ # # ]: 0 : do ideg=1,size(gwr%degtab(ikcalc, spin)%bids)
6557 : 0 : associate (bids => gwr%degtab(ikcalc, spin)%bids(ideg)%vals)
6558 : 0 : nstates = size(bids)
6559 [ # # # # : 0 : avg_2ntau = sum(sigc_it_mat(:,:,bids(:), 1,ikcalc, spin), dim=3) / nstates
# # ]
6560 [ # # ]: 0 : do ii=1,nstates
6561 [ # # # # ]: 0 : sigc_it_mat(:,:,bids(ii), 1,ikcalc, spin) = avg_2ntau
6562 : : end do
6563 : : end associate
6564 : : end do ! ideg
6565 : : end do
6566 : : end do
6567 : : end if ! symsigma == +1
6568 : :
6569 : : ! Store matrix elements of Sigma_c(it), separate even and odd part
6570 : : ! then use sine/cosine transform to get Sigma_c(i omega).
6571 : : ! Finally, perform analytic continuation with Pade' to go to the real-frequency axis
6572 : : ! for computing QP corrections and spectral functions. All procs execute this part as it's very cheap.
6573 : :
6574 [ # # ]: 0 : imag_zmesh(:) = j_dpc * gwr%iw_mesh
6575 : :
6576 : : ! Save previous QP bands in qp_ebands_prev (needed for self-consistency)
6577 : : ! In the loop below, we also update gwr%qp_ebands%eig with the QP results and recompute occ/fermie.
6578 [ # # # # : 0 : gwr%qp_ebands_prev%eig = gwr%qp_ebands%eig
# # # # #
# # # # #
# # # # #
# # # ]
6579 [ # # # # : 0 : gwr%qp_ebands_prev%occ = gwr%qp_ebands%occ
# # # # #
# # # # #
# # # # #
# # # ]
6580 : :
6581 [ # # # # : 0 : e0_kcalc = zero; spfunc_diag = zero; pade_solver_ierr = 0; ze0_kcalc = zero; sigc_e0 = zero
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
6582 [ # # # # : 0 : qpz_ene = zero; qp_pade = zero; sigxc_rw_diag = zero
# # # # #
# # # # #
# # # # #
# ]
6583 [ # # # # : 0 : ks_gaps = -one; qpz_gaps = -one ; qp_pade_gaps = -one
# # # # #
# # # ]
6584 : :
6585 [ # # ]: 0 : do spin=1,gwr%nsppol
6586 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6587 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
6588 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6589 : 0 : ibc = band - gwr%bstart_ks(ikcalc, spin) + 1
6590 : 0 : nb1 = gwr%bstop_ks(ikcalc, spin) - gwr%bstart_ks(ikcalc, spin) + 1
6591 : :
6592 : : ! FT Sigma(itau) --> Sigma(iw)
6593 : 0 : band2_start = 1; band2_stop = 1
6594 [ # # ]: 0 : if (.not. gwr%sig_diago) then
6595 : 0 : band2_start = gwr%bstart_ks(ikcalc, spin); band2_stop = gwr%bstop_ks(ikcalc, spin)
6596 : : end if
6597 : :
6598 [ # # ]: 0 : do band2=band2_start, band2_stop
6599 : 0 : associate (cvals_pmt => sigc_it_mat(:, :, band, band2, ikcalc, spin))
6600 : 0 : ib2 = band2 - band2_start + 1
6601 : 0 : nb2 = band2_stop - band2_start + 1
6602 : :
6603 : 0 : if (do_sigma_fit) then
6604 [ # # ]: 0 : cvals = cvals_pmt(1,:)
6605 : 0 : call fit_tau_exp(gwr%ntau, gwr%tau_mesh, gwr%tau_wgs, cvals, alpha_c, beta_r, ierr)
6606 : 0 : alphas_c(1,band, band2) = alpha_c; betas_r(1,band,band2) = beta_r
6607 : 0 : zcut_pm(1, band, band2) = gwr%dtset%zcut
6608 : : ! Remove the fit from the ab-initio data.
6609 [ # # ]: 0 : cvals_pmt(1,:) = cvals_pmt(1,:) - alpha_c * exp(-beta_r * gwr%tau_mesh)
6610 [ # # ]: 0 : if (gwr%comm%value == master) then
6611 : 0 : write(100, "(a,2(i0,1x))")"# +tau fit for band, band2: ", band, band2
6612 : 0 : write(100, *)"# alpha_c, beta_r: ", alpha_c, beta_r
6613 [ # # ]: 0 : do ii=1,gwr%ntau
6614 [ # # # # ]: 0 : zz = alpha_c * exp(-beta_r * gwr%tau_mesh(ii)); write(100, *) c2r(cvals_pmt(1,ii)), c2r(zz), abs(cvals_pmt(1,ii) - zz)
6615 : : end do
6616 : : end if
6617 : : ! TODO: Recheck this part, in particular the order of -tau
6618 [ # # ]: 0 : cvals = cvals_pmt(2,:)
6619 : 0 : call fit_tau_exp(gwr%ntau, gwr%tau_mesh, gwr%tau_wgs, cvals, alpha_c, beta_r, ierr)
6620 : 0 : alphas_c(2, band, band2) = alpha_c; betas_r(2, band, band2) = beta_r
6621 : 0 : zcut_pm(2, band, band2) = gwr%dtset%zcut
6622 : : ! Remove the fit from the ab-initio data.
6623 [ # # ]: 0 : cvals_pmt(2,:) = cvals_pmt(2,:) - alpha_c * exp(-beta_r * gwr%tau_mesh)
6624 [ # # ]: 0 : if (gwr%comm%value == master) then
6625 : 0 : write(101, "(a,2(i0,1x))")"# -tau fit for band, band2: ", band, band2
6626 : 0 : write(101, *)"# alpha_c, beta_r: ", alpha_c, beta_r
6627 [ # # ]: 0 : do ii=1,gwr%ntau
6628 [ # # # # ]: 0 : zz = alpha_c * exp(-beta_r * gwr%tau_mesh(ii)); write(101, *) c2r(cvals_pmt(2,ii)), c2r(zz), abs(cvals_pmt(2,ii) - zz)
6629 : : end do
6630 : : end if
6631 : : end if ! do_sigma_fit
6632 : :
6633 : : ! f(t) = E(t) + O(t) = (f(t) + f(-t)) / 2 + (f(t) - f(-t)) / 2
6634 [ # # # # ]: 0 : even_t = (cvals_pmt(1,:) + cvals_pmt(2,:)) / two; odd_t = (cvals_pmt(1,:) - cvals_pmt(2,:)) / two
6635 [ # # # # : 0 : gwr%sigc_iw_mat(:, band, band2, ikcalc, spin) = matmul(gwr%cosft_wt, even_t) + j_dpc * matmul(gwr%sinft_wt, odd_t)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
6636 : : end associate
6637 : : end do ! band2
6638 : :
6639 : : ! NB: e0 is always set to the KS energy even in case of self-consistency.
6640 : 0 : e0 = gwr%ks_ebands%eig(band, ik_ibz, spin)
6641 [ # # ]: 0 : if ( gwr%sig_diago) sigx = gwr%sigx_mat(band, 1, ikcalc, spin)
6642 [ # # ]: 0 : if (.not. gwr%sig_diago) sigx = gwr%sigx_mat(band, band, ikcalc, spin)
6643 : :
6644 : : ! Note vxc[n_val] instead of vxc[n_val + n_nlcc] with the model core charge.
6645 [ # # ]: 0 : if (gwr%nspinor == 2) then
6646 [ # # ]: 0 : vxc_val = SUM(gwr%ks_me%vxcval(band, band, ik_ibz, :))
6647 : : else
6648 : 0 : vxc_val = gwr%ks_me%vxcval(band, band, ik_ibz, spin)
6649 : : end if
6650 [ # # ]: 0 : vu = zero; if (gwr%dtset%usepawu /= 0) vu = gwr%ks_me%vu(band, band, ik_ibz, spin)
6651 : 0 : v_meanf = vxc_val + vu
6652 : :
6653 [ # # ]: 0 : band2 = merge(1, band, gwr%sig_diago)
6654 : :
6655 : : call spade%init(gwr%ntau, imag_zmesh, gwr%sigc_iw_mat(:, band, band2, ikcalc, spin), &
6656 : 0 : alphas_c(:, band, band2), betas_r(:, band, band2), zcut_pm(:, band, band2))
6657 : 0 : spade%do_sigma_fit = do_sigma_fit
6658 : :
6659 : : ! Solve the QP equation with Newton-Rapson starting from e0.
6660 : 0 : zz = cmplx(e0, zero)
6661 : 0 : call spade%qp_solve(e0, v_meanf, sigx, zz, zsc, sigc_zsc, msg, ierr)
6662 : 0 : qp_pade(band, ikcalc, spin) = zsc
6663 : 0 : pade_solver_ierr(band, ikcalc, spin) = ierr
6664 [ # # ]: 0 : ABI_WARNING_IF(ierr /= 0, msg)
6665 : :
6666 : 0 : call spade%eval(zz, sigc_e0__, dvdz=dsigc_de0)
6667 : :
6668 : : ! Z = (1 - dSigma / domega(E0))^{-1}
6669 : 0 : z_e0 = one / (one - dsigc_de0)
6670 : :
6671 : : ! Compute linearized QP solution and store results
6672 : 0 : qp_ene = e0 + z_e0 * (sigc_e0__ + sigx - v_meanf)
6673 : 0 : qpz_ene(band, ikcalc, spin) = qp_ene
6674 : 0 : e0_kcalc(band, ikcalc, spin) = e0
6675 : 0 : sigc_e0(band, ikcalc, spin) = sigc_e0__
6676 : 0 : ze0_kcalc(band, ikcalc, spin) = z_e0
6677 : :
6678 : : ! IMPORTANT: Here we update qp_ebands%eig with the new ones obtained with the linearized QP equation.
6679 : 0 : gwr%qp_ebands%eig(band, ik_ibz, spin) = real(qp_ene)
6680 : :
6681 : : ! Compute Spectral function using linear mesh **centered** around KS e0.
6682 : 0 : rw_mesh = arth(e0 - gwr%wr_step * (gwr%nwr / 2), gwr%wr_step, gwr%nwr)
6683 : 0 : hhartree_bk = gwr%ks_ebands%eig(band, ik_ibz, spin) - v_meanf
6684 [ # # ]: 0 : do iw=1,gwr%nwr
6685 : 0 : zz = rw_mesh(iw)
6686 : 0 : call spade%eval(zz, sigc_e0__)
6687 : 0 : sig_xc = sigx + sigc_e0__
6688 : 0 : sigxc_rw_diag(iw, band, ikcalc, spin) = sig_xc
6689 : :
6690 : : spfunc_diag(iw, band, ikcalc, spin) = one / pi * abs(aimag(sigc_e0__)) &
6691 : 0 : / ( (real(rw_mesh(iw) - hhartree_bk - sig_xc)) ** 2 + (aimag(sigc_e0__)) ** 2) ! / Ha_eV
6692 : :
6693 : : !Sr%hhartree = hdft - KS_me%vxcval
6694 : : !spfunc_diag(iw, band, ikcalc, spin) = &
6695 : : ! one / pi * abs(aimag(sigc_e0__)) &
6696 : : ! /( (real(rw_mesh(iw) - Sr%hhartree(ib, ib, ik_ibz, spin) - sigx_xc)) ** 2 &
6697 : : ! +(aimag(sigc_e0__)) ** 2) / Ha_eV
6698 : : end do ! iw
6699 : 0 : call spade%free()
6700 : :
6701 : : end do ! band
6702 : : end do ! ikcalc
6703 : : end do ! spin
6704 : :
6705 [ # # ]: 0 : ABI_SFREE(alphas_c)
6706 [ # # ]: 0 : ABI_SFREE(betas_r)
6707 [ # # ]: 0 : ABI_SFREE(zcut_pm)
6708 : :
6709 [ # # ]: 0 : if (gwr%nkcalc == gwr%nkibz) then
6710 : : ! Shift the bands that are not explicitly included in the SCF calculation.
6711 : : ! using the correction evaluated at bstop_ks/bstart_ks to accelerate self-consistent calculations.
6712 [ # # ]: 0 : do spin=1,gwr%nsppol
6713 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6714 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
6715 : 0 : band = gwr%bstop_ks(ikcalc, spin)
6716 [ # # ]: 0 : if (band + 1 <= size(gwr%qp_ebands%eig, dim=1)) then
6717 : 0 : eshift = gwr%qp_ebands%eig(band, ik_ibz, spin) - gwr%qp_ebands_prev%eig(band, ik_ibz, spin)
6718 : 0 : call wrtout(std_out, sjoin(" Correcting bands >= ", itoa(band+1), " with eshift:", ftoa(eshift * Ha_meV), "(meV)"))
6719 [ # # ]: 0 : gwr%qp_ebands%eig(band + 1:, ik_ibz, spin) = gwr%qp_ebands%eig(band + 1:, ik_ibz, spin) + eshift
6720 : : end if
6721 : 0 : band = gwr%bstart_ks(ikcalc, spin)
6722 [ # # ]: 0 : if (band > 1) then ! unlikely
6723 : 0 : eshift = gwr%qp_ebands%eig(band, ik_ibz, spin) - gwr%qp_ebands_prev%eig(band, ik_ibz, spin)
6724 : 0 : call wrtout(std_out, sjoin(" Correcting bands < ", itoa(band), " with eshift:", ftoa(eshift * Ha_meV), "(meV)"))
6725 [ # # ]: 0 : gwr%qp_ebands%eig(:band - 1, ik_ibz, spin) = gwr%qp_ebands%eig(:band - 1, ik_ibz, spin) + eshift
6726 : : end if
6727 : : end do
6728 : : end do
6729 : :
6730 : : ! Recompute occupancies and set fermie to zero.
6731 : : ! FIXME: Possible problem here if the QP energies are not ordered!
6732 : 0 : call gwr%qp_ebands%update_occ(gwr%dtset%spinmagntarget, prtvol=gwr%dtset%prtvol, fermie_to_zero=.True.)
6733 : : end if
6734 : :
6735 [ # # ]: 0 : if (gwr%comm%me == 0) then
6736 : : ! Master writes results to ab_out, std_out and GWR.nc
6737 [ # # # # : 0 : if (any(pade_solver_ierr /= 0)) then
# # # # #
# ]
6738 : : ! Write warning if QP solver failed.
6739 [ # # # # : 0 : ierr = count(pade_solver_ierr /= 0)
# # # # ]
6740 [ # # ]: 0 : call wrtout([ab_out, std_out], sjoin(" WARNING: QP solver failed for:", itoa(ierr), "states"))
6741 : : end if
6742 : :
6743 [ # # ]: 0 : call write_notations([std_out, ab_out])
6744 [ # # ]: 0 : do spin=1,gwr%nsppol
6745 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6746 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
6747 : :
6748 : 0 : ydoc = yamldoc_open('GWR_SelfEnergy_ee', width=11, real_fmt='(3f8.3)')
6749 : 0 : call ydoc%add_real1d('kpoint', gwr%kcalc(:, ikcalc))
6750 : 0 : call ydoc%add_int('spin', spin, int_fmt="(i1)")
6751 : 0 : call ydoc%add_int('gwr_scf_iteration', gwr%scf_iteration)
6752 : 0 : call ydoc%add_string('gwr_task', gwr%dtset%gwr_task)
6753 : :
6754 : : ! Compute gaps assuming KS band indices.
6755 : 0 : band_val = gwr%ks_vbik(ik_ibz, spin)
6756 : 0 : nbc = gwr%bstop_ks(ikcalc, spin) - gwr%bstart_ks(ikcalc, spin) + 1
6757 : 0 : ib1 = gwr%bstart_ks(ikcalc, spin); ib2 = gwr%bstop_ks(ikcalc, spin)
6758 : :
6759 [ # # # # ]: 0 : if (band_val >= gwr%bstart_ks(ikcalc, spin) .and. band_val + 1 <= gwr%bstop_ks(ikcalc, spin)) then
6760 : 0 : ibv = band_val - gwr%bstart_ks(ikcalc, spin) + 1
6761 : 0 : ks_gap = gwr%ks_ebands%eig(band_val+1, ik_ibz, spin) - gwr%ks_ebands%eig(band_val, ik_ibz, spin)
6762 : :
6763 : : ! This to detect a possible band inversion and compute qp_gaps accordingly.
6764 : 0 : band_inversion = .False.
6765 [ # # # # : 0 : call sort_rvals(nbc, real(qpz_ene(ib1:, ikcalc, spin)), iperm, sorted_qpe, tol=tol6)
# # # # #
# ]
6766 : :
6767 [ # # # # ]: 0 : if (iperm(ibv) /= ibv .or. iperm(ibv + 1) /= ibv + 1) then
6768 : 0 : band_inversion = .True.
6769 : 0 : call ydoc%add_int('QP_VBM_band', iperm(ibv) + gwr%bstart_ks(ikcalc, spin) - 1)
6770 : 0 : call ydoc%add_int('QP_CBM_band', iperm(ibv+1) + gwr%bstart_ks(ikcalc, spin) - 1)
6771 : 0 : qp_gap = sorted_qpe(ibv+1) - sorted_qpe(ibv)
6772 : 0 : qp_pade_gap = qp_pade(band_val+1, ikcalc, spin) - qp_pade(band_val, ikcalc, spin)
6773 : : else
6774 : 0 : call ydoc%add_int('QP_VBM_band', ibv + gwr%bstart_ks(ikcalc, spin) - 1)
6775 : 0 : call ydoc%add_int('QP_CBM_band', ibv+1 + gwr%bstart_ks(ikcalc, spin) - 1)
6776 : 0 : qp_gap = gwr%qp_ebands%eig(band_val+1, ik_ibz, spin) - gwr%qp_ebands%eig(band_val, ik_ibz, spin)
6777 : 0 : qp_pade_gap = qp_pade(band_val+1, ikcalc, spin) - qp_pade(band_val, ikcalc, spin)
6778 : : end if
6779 : 0 : ABI_FREE(iperm)
6780 [ # # ]: 0 : ABI_FREE(sorted_qpe)
6781 : :
6782 : 0 : call ydoc%add_real('KS_gap', ks_gap * Ha_eV)
6783 : 0 : call ydoc%add_real('QP_gap', qp_gap * Ha_eV)
6784 : 0 : call ydoc%add_real('Delta_QP_KS', (qp_gap - ks_gap) * Ha_eV)
6785 : 0 : ks_gaps(ikcalc, spin)= ks_gap
6786 : 0 : qpz_gaps(ikcalc, spin) = qp_gap
6787 : 0 : qp_pade_gaps(ikcalc, spin) = qp_pade_gap
6788 : : end if
6789 : :
6790 : 0 : call ydoc%open_tabular('data') !, tag='SigmaeeData')
6791 : 0 : write(msg, "(a5, *(a9))") "Band", "E0", "<VxcDFT>", "SigX", "SigC(E0)", "Z", "E-E0", "E-Eprev", "E", "Occ(E)"
6792 : 0 : call ydoc%add_tabular_line(msg)
6793 : :
6794 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6795 : 0 : ibc = band - gwr%bstart_ks(ikcalc, spin) + 1
6796 : 0 : e0 = gwr%ks_ebands%eig(band, ik_ibz, spin)
6797 : 0 : qp_ene = gwr%qp_ebands%eig(band, ik_ibz, spin)
6798 : 0 : qp_ene_prev = gwr%qp_ebands_prev%eig(band, ik_ibz, spin)
6799 [ # # ]: 0 : if ( gwr%sig_diago) sigx = gwr%sigx_mat(band, 1, ikcalc, spin)
6800 [ # # ]: 0 : if (.not. gwr%sig_diago) sigx = gwr%sigx_mat(band, band, ikcalc, spin)
6801 [ # # ]: 0 : if (gwr%nspinor == 2) then
6802 [ # # ]: 0 : vxc_val = SUM(gwr%ks_me%vxcval(band, band, ik_ibz, :))
6803 : : else
6804 : 0 : vxc_val = gwr%ks_me%vxcval(band, band, ik_ibz, spin)
6805 : : end if
6806 : :
6807 : : write(msg,'(i5, *(f9.3))') &
6808 : 0 : band, & ! Band
6809 : 0 : e0 * Ha_eV, & ! E0
6810 : 0 : real(vxc_val)*Ha_eV, & ! <VxcDFT>
6811 : 0 : real(sigx) * Ha_eV, & ! SigX
6812 : 0 : real(sigc_e0(band, ikcalc, spin)) * Ha_eV, & ! SigC(E0)
6813 : 0 : real(ze0_kcalc(band, ikcalc, spin)), & ! Z
6814 : 0 : (real(qp_ene - e0)) * Ha_eV, & ! E-E0
6815 : 0 : real(qp_ene - qp_ene_prev) * Ha_eV, & ! E-Eprev
6816 : 0 : real(qp_ene) * Ha_eV, & ! E
6817 : 0 : gwr%qp_ebands%occ(band, ik_ibz, spin) ! Occ(E)
6818 : 0 : call ydoc%add_tabular_line(msg)
6819 : : end do
6820 : :
6821 [ # # ]: 0 : call ydoc%write_units_and_free([std_out, ab_out])
6822 : : end do ! ikcalc
6823 : : end do ! spin
6824 : :
6825 : : ! Print KS and QP gaps
6826 : 0 : call gwr%ks_gaps%print(units, header="Kohn-Sham gaps and band edges from IBZ mesh")
6827 : :
6828 [ # # # # : 0 : new_gaps = gwr%qp_ebands%get_gaps(ierr)
# # # # #
# # # # #
# # ]
6829 : 0 : write(msg,"(a,i0,a)")" QP gaps and band edges taking into account Sigma_nk corrections for ",gwr%nkcalc," k-points"
6830 : 0 : call new_gaps%print(units, header=msg)
6831 [ # # ]: 0 : if (ierr /= 0) then
6832 : 0 : ABI_WARNING("Cannot compute QP fundamental and direct gap (likely metal)")
6833 : : end if
6834 : 0 : call new_gaps%free()
6835 : :
6836 : : ! Write results to text files.
6837 [ # # ]: 0 : if (open_file(strcat(gwr%dtfil%filnam_ds(4), '_SIGC_IT'), msg, newunit=unt_it, action="write") /= 0) then
6838 : 0 : ABI_ERROR(msg)
6839 : : end if
6840 : 0 : write(unt_it, "(a)")"# Diagonal elements of Sigma_c(i tau, +/-) in atomic units"
6841 : 0 : write(unt_it, "(a)")"# tau Re/Im Sigma_c(+itau) Re/Im Sigma_c(-itau)"
6842 : :
6843 [ # # ]: 0 : if (open_file(strcat(gwr%dtfil%filnam_ds(4), '_SIGXC_IW'), msg, newunit=unt_iw, action="write") /= 0) then
6844 : 0 : ABI_ERROR(msg)
6845 : : end if
6846 : 0 : write(unt_iw, "(a)")"# Diagonal elements of Sigma_xc(i omega) in eV units"
6847 : 0 : write(unt_iw, "(a)")"# omega Re/Im Sigma_c(i omega)"
6848 : :
6849 [ # # ]: 0 : if (open_file(strcat(gwr%dtfil%filnam_ds(4), '_SIGXC_RW'), msg, newunit=unt_rw, action="write") /= 0) then
6850 : 0 : ABI_ERROR(msg)
6851 : : end if
6852 : 0 : write(unt_rw, "(a)")"# Diagonal elements of Sigma_xc(omega) in eV units and spectral function A(omega)"
6853 : 0 : write(unt_rw, "(a)")"# omega Re/Im Sigma_xc(omega), A(omega)"
6854 : :
6855 [ # # ]: 0 : dat_units = [unt_it, unt_iw, unt_rw]
6856 : 0 : call write_units(dat_units, "# Fermi energy set to zero. Energies in eV")
6857 : 0 : call write_units(dat_units, sjoin("# nkcalc:", itoa(gwr%nkcalc), ", nsppol:", itoa(gwr%nsppol)))
6858 : :
6859 : : ! TODO: Improve file format. Add compatibility with gnuplot format for datasets?
6860 [ # # ]: 0 : do spin=1,gwr%nsppol
6861 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
6862 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
6863 : 0 : call write_units(dat_units, sjoin("# kpt:", ktoa(gwr%kcalc(:, ikcalc)), "spin:", itoa(spin)))
6864 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
6865 : 0 : ibc = band - gwr%bstart_ks(ikcalc, spin) + 1
6866 : 0 : e0 = gwr%ks_ebands%eig(band, ik_ibz, spin)
6867 [ # # ]: 0 : band2 = merge(1, band, gwr%sig_diago)
6868 : 0 : sigx = gwr%sigx_mat(band, band2, ikcalc, spin)
6869 : :
6870 : 0 : call write_units(dat_units, sjoin("# band:", itoa(band), ", spin:", itoa(spin)))
6871 : 0 : call write_units(dat_units, sjoin("# sigx_ev:", ftoa(sigx * Ha_eV)))
6872 : :
6873 [ # # ]: 0 : do itau=1,gwr%ntau
6874 : : ! FIXME itau is not ordered
6875 : : write(unt_it, "(*(es16.8))") &
6876 : 0 : gwr%tau_mesh(itau), &
6877 [ # # ]: 0 : c2r(sigc_it_mat(1, itau, band, band2, ikcalc, spin)), &
6878 [ # # ]: 0 : c2r(sigc_it_mat(2, itau, band, band2, ikcalc, spin))
6879 : : write(unt_iw, "(*(es16.8))") &
6880 : 0 : gwr%iw_mesh(itau) * Ha_eV, &
6881 [ # # ]: 0 : (c2r(gwr%sigc_iw_mat(itau, band, band2, ikcalc, spin) + sigx)) * Ha_eV
6882 : : end do
6883 : :
6884 : : ! Write Sigma_xc(omega) and A(omega)
6885 [ # # ]: 0 : rw_mesh = arth(e0 - gwr%wr_step * (gwr%nwr / 2), gwr%wr_step, gwr%nwr) * Ha_eV
6886 [ # # ]: 0 : do iw=1,gwr%nwr
6887 : : write(unt_rw, "(*(es16.8))") &
6888 : 0 : rw_mesh(iw), &
6889 [ # # ]: 0 : c2r(sigxc_rw_diag(iw, band, ikcalc, spin)) * Ha_eV, &
6890 : 0 : spfunc_diag(iw, band, ikcalc, spin) / Ha_eV
6891 : : end do
6892 : : end do
6893 : : end do
6894 : : end do
6895 : :
6896 : 0 : close(unt_it); close(unt_iw); close(unt_rw)
6897 : :
6898 : : ! ======================
6899 : : ! Add results to GWR.nc
6900 : : ! ======================
6901 [ # # ]: 0 : if (gwr%gwrnc_write) then
6902 [ # # ]: 0 : NCF_CHECK(nctk_open_modify(ncid, gwr%gwrnc_path, xmpi_comm_self))
6903 : :
6904 : : ! Define arrays with results.
6905 : : ! TODO: Add matrix elements of vxc, have to trasfer data from vxcval to nkcalc packing
6906 : 0 : call ncwrite_sigmac(ncid)
6907 : :
6908 : : if (.true.) then
6909 [ # # ]: 0 : NCF_CHECK(nf90_def_grp(ncid, strcat("iter", itoa(gwr%scf_iteration)), iter_ncid))
6910 : 0 : call ncwrite_sigmac(iter_ncid)
6911 : : end if
6912 : :
6913 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("scf_iteration"), gwr%scf_iteration))
6914 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("gwr_completed"), 1))
6915 [ # # ]: 0 : NCF_CHECK(nf90_close(ncid))
6916 : : end if
6917 : : end if ! master
6918 : :
6919 [ # # ]: 0 : ABI_FREE(sigc_it_mat)
6920 : : !ABI_FREE(sigc_iw_mat)
6921 : :
6922 : 0 : call cwtime_report(" gwr_build_sigmac:", cpu_all, wall_all, gflops_all)
6923 [ # # # # : 0 : call timab(1925, 2, tsec)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
6924 : :
6925 : : contains
6926 : 0 : integer function vid(vname)
6927 : : character(len=*),intent(in) :: vname
6928 : 0 : vid = nctk_idname(ncid, vname)
6929 : : end function vid
6930 : :
6931 : 0 : subroutine print_sigma_header()
6932 : :
6933 [ # # ]: 0 : if (gwr%comm%me /= 0) return
6934 [ # # ]: 0 : if (gwr%use_supercell_for_sigma) then
6935 : 0 : call wrtout(std_out, sjoin(" Building Sigma_c in the supercell with FFT mesh:", ltoa(sc_ngfft(1:3))), pre_newlines=2)
6936 : : else
6937 [ # # ]: 0 : call wrtout([std_out,ab_out], " Building Sigma_c with convolutions in k-space:", pre_newlines=2)
6938 : : end if
6939 : 0 : call wrtout(std_out, sjoin(" gwr_np_kgts:", ltoa(gwr%dtset%gwr_np_kgts)))
6940 : 0 : call wrtout(std_out, sjoin(" ngkpt:", ltoa(gwr%ngkpt), " ngqpt:", ltoa(gwr%ngqpt)))
6941 : 0 : call wrtout(std_out, sjoin(" gwr_boxcutmin:", ftoa(gwr%dtset%gwr_boxcutmin)))
6942 : 0 : call wrtout(std_out, sjoin(" my_ntau:", itoa(gwr%my_ntau), "ntau:", itoa(gwr%ntau)))
6943 : 0 : call wrtout(std_out, sjoin(" my_nkbz:", itoa(gwr%my_nkbz), "nkibz:", itoa(gwr%nkibz)))
6944 : 0 : call wrtout(std_out, sjoin("- FFT uc_batch_size:", itoa(gwr%uc_batch_size)))
6945 : 0 : call wrtout(std_out, sjoin("- FFT sc_batch_size:", itoa(gwr%sc_batch_size)), do_flush=.True.)
6946 : :
6947 : : end subroutine print_sigma_header
6948 : :
6949 : 0 : subroutine ncwrite_sigmac(myncid)
6950 : : integer,intent(in) :: myncid
6951 : : !logical,intent(in), optional :: mydefine
6952 : : integer :: myncerr
6953 : :
6954 : : ! Write Sigma_c to GWR.nc
6955 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(myncid))
6956 : : ! if (.not. present(mydefine) .or. mydefine) then
6957 : : if (.true.) then
6958 : : myncerr = nctk_def_arrays(myncid, [ &
6959 : : nctkarr_t("e0_kcalc", "dp", "smat_bsize1, nkcalc, nsppol"), &
6960 : : nctkarr_t("ze0_kcalc", "dp", "two, smat_bsize1, nkcalc, nsppol"), &
6961 : : !nctkarr_t("vxc_kcalc", "dp", "two, smat_bsize1, nkcalc, nsppol"), &
6962 : : nctkarr_t("qpz_ene", "dp", "two, smat_bsize1, nkcalc, nsppol"), &
6963 : : nctkarr_t("qp_pade", "dp", "two, smat_bsize1, nkcalc, nsppol"), &
6964 : : nctkarr_t("pade_solver_ierr", "int", "smat_bsize1, nkcalc, nsppol"), &
6965 : : nctkarr_t("ks_gaps", "dp", "nkcalc, nsppol"), &
6966 : : nctkarr_t("qpz_gaps", "dp", "nkcalc, nsppol"), &
6967 : : nctkarr_t("qp_pade_gaps", "dp", "nkcalc, nsppol"), &
6968 : : nctkarr_t("sigx_mat", "dp", "two, smat_bsize1, smat_bsize2, nkcalc, nsppol"), &
6969 : : nctkarr_t("sigc_it_mat", "dp", "two, two, ntau, smat_bsize1, smat_bsize2, nkcalc, nsppol"), &
6970 : : nctkarr_t("sigc_iw_mat", "dp", "two, ntau, smat_bsize1, smat_bsize2, nkcalc, nsppol"), &
6971 : : nctkarr_t("sigxc_rw_diag", "dp", "two, nwr, smat_bsize1, nkcalc, nsppol"), &
6972 : : nctkarr_t("spfunc_diag", "dp", "nwr, smat_bsize1, nkcalc, nsppol") &
6973 [ # # ]: 0 : ])
6974 [ # # ]: 0 : NCF_CHECK(myncerr)
6975 : : end if
6976 : : ! Write data.
6977 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(myncid))
6978 [ # # ]: 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "e0_kcalc"), e0_kcalc))
6979 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "ze0_kcalc"), c2r(ze0_kcalc)))
# # ]
6980 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "sigx_mat"), c2r(gwr%sigx_mat(:,:,:,1:gwr%nsppol))))
# # ]
6981 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "qpz_ene"), c2r(qpz_ene)))
# # ]
6982 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "qp_pade"), c2r(qp_pade)))
# # ]
6983 [ # # ]: 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "pade_solver_ierr"), pade_solver_ierr))
6984 [ # # ]: 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "ks_gaps"), ks_gaps))
6985 [ # # ]: 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "qpz_gaps"), qpz_gaps))
6986 [ # # ]: 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "qp_pade_gaps"), qp_pade_gaps))
6987 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "sigc_it_mat"), c2r(sigc_it_mat)))
# # ]
6988 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "sigc_iw_mat"), c2r(gwr%sigc_iw_mat)))
# # ]
6989 [ # # # # : 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "sigxc_rw_diag"), c2r(sigxc_rw_diag)))
# # ]
6990 [ # # ]: 0 : NCF_CHECK(nf90_put_var(myncid, nctk_idname(myncid, "spfunc_diag"), spfunc_diag))
6991 : :
6992 : 0 : end subroutine ncwrite_sigmac
6993 : :
6994 : : end subroutine gwr_build_sigmac
6995 : : !!***
6996 : :
6997 : : !!****f* m_gwr/write_notations
6998 : : !! NAME
6999 : : !! write_notations
7000 : : !!
7001 : : !! FUNCTION
7002 : : !! Write the meaning of the different columns.
7003 : : !!
7004 : : !! SOURCE
7005 : :
7006 [ # # ]: 0 : subroutine write_notations(units)
7007 : : integer,intent(in) :: units(:)
7008 : : integer :: ii, unt
7009 : :
7010 [ # # ]: 0 : do ii=1,size(units)
7011 : 0 : unt = units(ii)
7012 : 0 : write(unt,"(a)")repeat("=", 80)
7013 : 0 : write(unt,"(a)")" QP results (energies in eV)"
7014 : 0 : write(unt,"(a)")" Notations:"
7015 : 0 : write(unt,"(a)")" E0: Kohn-Sham energy"
7016 : 0 : write(unt,"(a)")" <VxcDFT>: Matrix elements of Vxc[n_val] without non-linear core correction (if any)"
7017 : 0 : write(unt,"(a)")" SigX: Matrix elements of Sigma_x"
7018 : 0 : write(unt,"(a)")" SigC(E0): Matrix elements of Sigma_c at E0"
7019 : 0 : write(unt,"(a)")" Z: Renormalization factor"
7020 : 0 : write(unt,"(a)")" E-E0: Difference between the QP and the KS energy."
7021 : 0 : write(unt,"(a)")" E-Eprev: Difference between QP energy at iteration i and i-1"
7022 : 0 : write(unt,"(a)")" E: Quasi-particle energy"
7023 : 0 : write(unt,"(a)")" Occ(E): Occupancy of QP state"
7024 : : !write(unt,"(a)")" SE1(eKS): Real part of the self-energy computed at the KS energy, SE2 for imaginary part."
7025 : 0 : write(unt,"(a)")" "
7026 : 0 : write(unt,"(a)")" "
7027 : : end do
7028 : 0 : end subroutine write_notations
7029 : : !!***
7030 : :
7031 : : !----------------------------------------------------------------------
7032 : :
7033 : : !!****f* m_gwr/sig_braket_ur
7034 : : !! NAME
7035 : : !! sig_braket_ur
7036 : : !!
7037 : : !! FUNCTION
7038 : : !! Integrate self-energy matrix elements in the unit cell.
7039 : : !!
7040 : : !! INPUTS
7041 : : !!
7042 : : !! OUTPUT
7043 : : !!
7044 : : !! SOURCE
7045 : :
7046 : 0 : subroutine sig_braket_ur(sig_rpr, nfftsp, ur_bra_glob, ur_ket_glob, sigm_pm, loc_cwork)
7047 : :
7048 : : !Arguments ------------------------------------
7049 : : type(__slkmat_t),intent(in) :: sig_rpr(2,2)
7050 : : integer,intent(in) :: nfftsp
7051 : : complex(gwp),intent(in) :: ur_bra_glob(nfftsp)
7052 : : complex(gwp),intent(in) :: ur_ket_glob(nfftsp)
7053 : :
7054 : : complex(gwp),intent(out) :: sigm_pm(2)
7055 : : complex(gwp),intent(inout) :: loc_cwork(sig_rpr(1,1)%size_local(2))
7056 : :
7057 : : !Local variables-------------------------------
7058 : : integer :: ipm, ir1, il_r1, nrows, ncols, itim
7059 : : !complex(gwp),allocatable :: loc_cwork(:)
7060 : : ! *************************************************************************
7061 : :
7062 : : ABI_NVTX_START_RANGE(NVTX_GWR_BRAKET_UR)
7063 : :
7064 : : ! (r',r) with r' local and r-index PBLAS-distributed.
7065 : 0 : sigm_pm = czero_gw
7066 [ # # ]: 0 : do itim=1,2
7067 [ # # ]: 0 : do ipm=1,2
7068 : 0 : associate (rp_r => sig_rpr(itim,ipm))
7069 : : ! Integrate over r'
7070 : : !ABI_CHECK_IEQ(nfftsp, rp_r%size_local(1), "First dimension should be local to each MPI proc!")
7071 : : !ABI_MALLOC(loc_cwork, (rp_r%size_local(2)))
7072 : : !loc_cwork(:) = matmul(transpose(rp_r%buffer_cplx), ur_glob)
7073 : :
7074 : 0 : nrows = rp_r%size_local(1); ncols = rp_r%size_local(2)
7075 : 0 : call xgemv('T', nrows, ncols, cone_gw, rp_r%buffer_cplx, nrows, ur_ket_glob, 1, czero_gw, loc_cwork, 1)
7076 : :
7077 : : ! Integrate over r. Note complex conjugate.
7078 [ # # ]: 0 : do il_r1=1,rp_r%size_local(2)
7079 : 0 : ir1 = rp_r%loc2gcol(il_r1)
7080 [ # # ]: 0 : if (itim == 1) then
7081 : 0 : sigm_pm(ipm) = sigm_pm(ipm) + conjg(ur_bra_glob(ir1)) * loc_cwork(il_r1)
7082 : : else
7083 : 0 : sigm_pm(ipm) = sigm_pm(ipm) + ur_bra_glob(ir1) * conjg(loc_cwork(il_r1))
7084 : : end if
7085 : : end do
7086 : : !ABI_FREE(loc_cwork)
7087 : : end associate
7088 : : end do
7089 : : end do
7090 : :
7091 : : ABI_NVTX_END_RANGE()
7092 : :
7093 : 0 : end subroutine sig_braket_ur
7094 : : !!***
7095 : :
7096 : : !----------------------------------------------------------------------
7097 : :
7098 : : !!****f* m_gwr/gwr_rpa_energy
7099 : : !! NAME
7100 : : !! gwr_rpa_energy
7101 : : !!
7102 : : !! FUNCTION
7103 : : !! Compute the correlated part of the total energy within ACFDT.
7104 : : !!
7105 : : !! INPUTS
7106 : : !!
7107 : : !! OUTPUT
7108 : : !!
7109 : : !! SOURCE
7110 : :
7111 : 0 : subroutine gwr_rpa_energy(gwr)
7112 : :
7113 : : !Arguments ------------------------------------
7114 : : class(gwr_t),target,intent(inout) :: gwr
7115 : :
7116 : : !Local variables-------------------------------
7117 : : !scalars
7118 : : integer,parameter :: master = 0
7119 : : integer :: my_is, my_iqi, my_it, itau, spin, iq_ibz, ii, ierr, ig, ncut, icut, mat_size
7120 : : integer :: il_g1, il_g2, ig1, ig2, npw_q, ig0, ncid, ncerr
7121 : : logical :: q_is_gamma, print_time
7122 : : real(dp) :: weight, qq_ibz(3), estep, aa, bb, rmsq, ecut_soft, damp, tsec(2)
7123 : : real(dp) :: cpu_all, wall_all, gflops_all, cpu_q, wall_q, gflops_q, cpu_cut, wall_cut, gflops_cut
7124 : : complex(dp) :: vcs_g1, vcs_g2
7125 : : type(desc_t),pointer :: desc_q
7126 : : character(len=500) :: msg
7127 : : !arrays
7128 [ # # # # : 0 : type(__slkmat_t) :: chi_tmp, dummy_vec, chi_4diag
# # # # #
# # # # #
# # # # ]
7129 : : type(slk_processor_t) :: proc_4diag
7130 : 0 : real(gwp),allocatable :: eig(:)
7131 : 0 : real(dp),allocatable :: kin_qg(:), ec_rpa(:), ec_mp2(:), ecut_chi(:)
7132 : : ! *************************************************************************
7133 : :
7134 : 0 : call gwr%build_chi0_head_and_wings()
7135 : 0 : call gwr%build_green(free_ugb=.True.)
7136 : 0 : call gwr%build_tchi()
7137 : :
7138 : : ! Compute RPA energy for ncut cutoff energies in order to extrapolate for ecuteps --> oo
7139 : : ! See also calc_rpa_functional in m_screening_driver
7140 : 0 : ncut = max(1, gwr%dtset%gwr_rpa_ncut) ! Usually 5
7141 : 0 : estep = -gwr%dtset%ecuteps * 0.05_dp
7142 : :
7143 : 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
7144 : 0 : call timab(1928, 1, tsec)
7145 : 0 : call wrtout(std_out, sjoin(" Begin computation of RPA energy with gwr_rpa_ncut:", itoa(ncut), " ..."))
7146 [ # # ]: 0 : ABI_CHECK(gwr%tchi_space == "iomega", sjoin("tchi_space:", gwr%tchi_space, "!= iomega"))
7147 : :
7148 [ # # # # : 0 : ABI_CALLOC(ec_rpa, (ncut))
# # # # #
# # # ]
7149 [ # # # # : 0 : ABI_CALLOC(ec_mp2, (ncut))
# # # # #
# ]
7150 [ # # # # : 0 : ABI_MALLOC(ecut_chi, (ncut))
# # # # ]
7151 [ # # ]: 0 : ecut_chi = arth(gwr%dtset%ecuteps + tol12, estep, ncut)
7152 : :
7153 : : ! Polarizability has been summed over spins inside build_tchi.
7154 : : ! The loop over spins is needed to parallelize the loop over my_iqi if nsppol == 2.
7155 [ # # ]: 0 : do my_is=1,gwr%my_nspins
7156 : 0 : spin = gwr%my_spins(my_is)
7157 [ # # # # ]: 0 : if (gwr%spin_comm%nproc == 1 .and. spin == 2) cycle
7158 : :
7159 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
7160 [ # # ]: 0 : if (gwr%spin_comm%skip(my_iqi)) cycle
7161 [ # # # # : 0 : print_time = gwr%comm%me == 0 .and. (my_iqi < LOG_MODK .or. mod(my_iqi, LOG_MODK) == 0)
# # ]
7162 : 0 : if (print_time) call cwtime(cpu_q, wall_q, gflops_q, "start")
7163 : :
7164 [ # # ]: 0 : iq_ibz = gwr%my_qibz_inds(my_iqi); qq_ibz = gwr%qibz(:, iq_ibz)
7165 : 0 : q_is_gamma = normv(qq_ibz, gwr%cryst%gmet, "G") < GW_TOLQ0
7166 : : !if (q_is_gamma) then
7167 : : ! call wrtout([std_out, ab_out], "RPA: Ignoring q==0"); cycle
7168 : : !end if
7169 : :
7170 : : ! iq_ibz might be replicated inside gwr%kpt_comm.
7171 [ # # ]: 0 : if (.not. gwr%itreat_iqibz(iq_ibz)) cycle
7172 : :
7173 : 0 : desc_q => gwr%tchi_desc_qibz(iq_ibz)
7174 [ # # ]: 0 : ABI_CHECK(desc_q%kin_sorted, "g-vectors are not sorted by |q+g|^2/2 !")
7175 : 0 : npw_q = desc_q%npw; ig0 = desc_q%ig0
7176 : :
7177 [ # # # # : 0 : ABI_MALLOC(kin_qg, (npw_q))
# # # # #
# # # #
# ]
7178 [ # # ]: 0 : do ig=1,npw_q
7179 [ # # ]: 0 : kin_qg(ig) = half * normv(qq_ibz + desc_q%gvec(:,ig), gwr%cryst%gmet, "G") ** 2
7180 : : end do
7181 : :
7182 [ # # ]: 0 : do my_it=1,gwr%my_ntau
7183 : 0 : itau = gwr%my_itaus(my_it)
7184 : 0 : associate (tchi => gwr%tchi_qibz(iq_ibz, itau, spin))
7185 : 0 : if (my_it == 1) then
7186 : : ! Allocate workspace. NB: npw_q is the total number of PWs for this q.
7187 : 0 : call tchi%copy(chi_tmp)
7188 : : !ABI_CHECK_IEQ(npw_q, tchi%sizeb_global(1), "npw_q")
7189 [ # # # # : 0 : ABI_MALLOC(eig, (npw_q))
# # # # #
# ]
7190 : : end if
7191 : :
7192 [ # # ]: 0 : do icut=1,ncut
7193 : 0 : call cwtime(cpu_cut, wall_cut, gflops_cut, "start")
7194 : :
7195 : : ! Damp Coulomb kernel in order to have smooth E(V).
7196 : : ! See also https://www.vasp.at/wiki/index.php/ENCUTGWSOFT
7197 : : ! and Harl's PhD thesis available at: https://utheses.univie.ac.at/detail/2259
7198 : 0 : ecut_soft = 0.8_dp * ecut_chi(icut)
7199 : :
7200 : : ! TODO: Contribution due to the head for q --> 0 is ignored.
7201 : : ! This is not optimal but consistent with calc_rpa_functional
7202 [ # # ]: 0 : do il_g2=1,tchi%size_local(2)
7203 : : !ig2 = mod(tchi%loc2gcol(il_g2) - 1, desc_q%npw) + 1
7204 : 0 : ig2 = tchi%loc2gcol(il_g2)
7205 : 0 : damp = one
7206 : : !if (kin_qg(ig2) > ecut_soft) then
7207 : : ! damp = sqrt(half * (one + cos(pi * (kin_qg(ig2) - ecut_soft) / (ecut_chi(icut) - ecut_soft))))
7208 : : !end if
7209 : 0 : vcs_g2 = desc_q%vc_sqrt_eps(ig2) * damp
7210 [ # # ]: 0 : if (q_is_gamma .and. ig2 == ig0) vcs_g2 = zero
7211 : :
7212 [ # # ]: 0 : do il_g1=1,tchi%size_local(1)
7213 : : !ig1 = mod(tchi%loc2grow(il_g1) - 1, desc_q%npw) + 1
7214 : 0 : ig1 = tchi%loc2grow(il_g1)
7215 : 0 : damp = one
7216 : : !if (kin_qg(ig1) > ecut_soft) then
7217 : : ! damp = sqrt(half * (one + cos(pi * (kin_qg(ig1) - ecut_soft) / (ecut_chi(icut) - ecut_soft))))
7218 : : !end if
7219 : 0 : vcs_g1 = desc_q%vc_sqrt_eps(ig1) * damp
7220 [ # # ]: 0 : if (q_is_gamma .and. ig1 == ig0) vcs_g1 = zero
7221 : :
7222 : 0 : chi_tmp%buffer_cplx(il_g1, il_g2) = tchi%buffer_cplx(il_g1, il_g2) * vcs_g1 * vcs_g2
7223 : : end do
7224 : : end do
7225 : :
7226 : : ! Diagonalize sub-matrix and perform integration in imaginary frequency.
7227 : : ! Eq (6) in 10.1103/PhysRevB.81.115126
7228 : : ! NB: have to build chi_tmp inside loop over icut as matrix is destroyed by pzheev.
7229 : 0 : mat_size = bisect(kin_qg, ecut_chi(icut))
7230 : :
7231 : : ! Change size block and, if possible, use 2D rectangular grid of processors for diagonalization
7232 : 0 : call proc_4diag%init(chi_tmp%processor%comm)
7233 : 0 : call chi_tmp%change_size_blocs(chi_4diag, processor=proc_4diag)
7234 : : !call chi_4diag%copy(dummy_vec)
7235 : 0 : call chi_4diag%heev("N", "U", dummy_vec, eig, mat_size=mat_size)
7236 : 0 : call chi_4diag%free()
7237 : : !call dummy_vec%free()
7238 : 0 : call proc_4diag%free()
7239 : :
7240 : : ! TODO: ELPA
7241 : : !call compute_eigen_problem(processor, matrix, results, eigen, comm, istwf_k, nev)
7242 : :
7243 [ # # ]: 0 : if (xmpi_comm_rank(chi_tmp%processor%comm) == 0) then
7244 : 0 : weight = gwr%wtq(iq_ibz) * gwr%iw_wgs(itau) / two_pi
7245 [ # # ]: 0 : do ii=1,mat_size
7246 : 0 : ec_rpa(icut) = ec_rpa(icut) + weight * (log(one - eig(ii)) + eig(ii))
7247 : : ! second order Moeller Plesset.
7248 : 0 : ec_mp2(icut) = ec_mp2(icut) - weight * eig(ii) ** 2 / two
7249 : : !if (eig(ii) > zero) then
7250 : : ! write(msg, "(a, es16.8)")"Positive eigenvalue:", eig(ii)
7251 : : ! ABI_ERROR(msg)
7252 : : !end if
7253 : : end do
7254 : : end if
7255 : :
7256 : 0 : write(msg,'(4x,2(a,i0),a)')"icut [", icut, "/", ncut, "]"
7257 : 0 : call cwtime_report(msg, cpu_cut, wall_cut, gflops_cut)
7258 : : end do ! icut
7259 : :
7260 [ # # # # ]: 0 : if (my_it == gwr%my_ntau) then
7261 : : ! Free workspace
7262 : 0 : call chi_tmp%free()
7263 [ # # ]: 0 : ABI_FREE(eig)
7264 : : end if
7265 : : end associate
7266 : : end do ! my_it
7267 : :
7268 [ # # ]: 0 : ABI_FREE(kin_qg)
7269 [ # # ]: 0 : if (print_time) then
7270 : 0 : write(msg,'(4x,2(a,i0),a)')"My iqi [", my_iqi, "/", gwr%my_nqibz, "]"
7271 : 0 : call cwtime_report(msg, cpu_q, wall_q, gflops_q)
7272 : : end if
7273 : : end do ! my_iqi
7274 : : end do ! my_is
7275 : :
7276 : : ! Collect results on the master node.
7277 : 0 : call xmpi_sum_master(ec_rpa, master, gwr%comm%value, ierr)
7278 : 0 : call xmpi_sum_master(ec_mp2, master, gwr%comm%value, ierr)
7279 : :
7280 [ # # ]: 0 : if (gwr%comm%me == master) then
7281 : : ! Print results to ab_out.
7282 : : ! TODO: Add metadata: nband, nqbz...
7283 : 0 : write(ab_out, "(4a16)")"ecut_chi", "ecut_chi^(-3/2)", "RPA Ec (eV)", "RPA Ec (Ha)"
7284 [ # # ]: 0 : do icut=ncut,1,-1
7285 : 0 : write(ab_out, "(*(es16.8))") ecut_chi(icut), ecut_chi(icut) ** (-three/two), ec_rpa(icut) * Ha_eV, ec_rpa(icut)
7286 : : end do
7287 [ # # ]: 0 : if (ncut > 1) then
7288 : : ! Add last line with extrapolated value.
7289 [ # # # # ]: 0 : rmsq = linfit(ncut, ecut_chi(:) ** (-three/two), ec_rpa, aa, bb)
7290 : 0 : write(ab_out, "(2a16,*(es16.8))") "oo", "0", bb * Ha_eV, bb
7291 : : end if
7292 : :
7293 : : ! ======================
7294 : : ! Add results to GWR.nc
7295 : : ! ======================
7296 [ # # ]: 0 : if (gwr%gwrnc_write) then
7297 [ # # ]: 0 : NCF_CHECK(nctk_open_modify(ncid, gwr%gwrnc_path, xmpi_comm_self))
7298 [ # # ]: 0 : ncerr = nctk_def_dims(ncid, [nctkdim_t("ncut", ncut)], defmode=.True.)
7299 [ # # ]: 0 : NCF_CHECK(ncerr)
7300 : :
7301 : : ncerr = nctk_def_arrays(ncid, [ &
7302 : : nctkarr_t("ecut_chi", "dp", "ncut"), &
7303 : : nctkarr_t("ec_rpa_ecut", "dp", "ncut"), &
7304 : : nctkarr_t("ec_mp2_ecut", "dp", "ncut") &
7305 [ # # ]: 0 : ])
7306 [ # # ]: 0 : NCF_CHECK(ncerr)
7307 : :
7308 : : ! Write data.
7309 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(ncid))
7310 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("ecut_chi"), ecut_chi))
7311 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("ec_rpa_ecut"), ec_rpa))
7312 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("ec_mp2_ecut"), ec_mp2))
7313 : : end if
7314 : : end if ! master
7315 : :
7316 [ # # ]: 0 : ABI_FREE(ec_rpa)
7317 [ # # ]: 0 : ABI_FREE(ec_mp2)
7318 [ # # ]: 0 : ABI_FREE(ecut_chi)
7319 : :
7320 : 0 : call cwtime_report(" gwr_rpa_energy:", cpu_all, wall_all, gflops_all)
7321 [ # # # # : 0 : call timab(1928, 2, tsec)
# # # # #
# # # # #
# # # # #
# ]
7322 : :
7323 : : contains
7324 : 0 : integer function vid(vname)
7325 : : character(len=*),intent(in) :: vname
7326 : 0 : vid = nctk_idname(ncid, vname)
7327 : : end function vid
7328 : :
7329 : : end subroutine gwr_rpa_energy
7330 : : !!***
7331 : :
7332 : : !----------------------------------------------------------------------
7333 : :
7334 : : !!****f* m_gwr/gwr_run_g0w0
7335 : : !! NAME
7336 : : !! gwr_run_g0w0
7337 : : !!
7338 : : !! FUNCTION
7339 : : !! Driver to compute QP energies within the G0W0 approximation and minimax meshes along the imaginary axis.
7340 : : !!
7341 : : !! INPUTS
7342 : : !! [free_ugb]: True if array with empty KS states should be freed as soon as possibile. Default: True
7343 : : !!
7344 : : !! OUTPUT
7345 : : !!
7346 : : !! SOURCE
7347 : :
7348 : 0 : subroutine gwr_run_g0w0(gwr, free_ugb)
7349 : :
7350 : : !Arguments ------------------------------------
7351 : : class(gwr_t),intent(inout) :: gwr
7352 : : logical,optional,intent(in) :: free_ugb
7353 : :
7354 : : !Local variables-------------------------------
7355 : : logical :: free_ugb__
7356 : : ! *************************************************************************
7357 : :
7358 : : ! Use ugb wavefunctions and the Lehmann representation to compute head/wings and Sigma_x matrix elements.
7359 : 0 : call gwr%build_chi0_head_and_wings()
7360 : 0 : call gwr%build_sigxme()
7361 : :
7362 : : ! Now compute G(itau) from ugb and start the GWR algorithm.
7363 [ # # ]: 0 : free_ugb__ = .True.; if (present(free_ugb)) free_ugb__ = free_ugb
7364 : 0 : call gwr%build_green(free_ugb=free_ugb__)
7365 : 0 : call gwr%build_tchi()
7366 : 0 : call gwr%build_wc()
7367 : 0 : call gwr%build_sigmac()
7368 : :
7369 : 0 : end subroutine gwr_run_g0w0
7370 : : !!***
7371 : :
7372 : : !!****f* m_gwr/gwr_run_chi0
7373 : : !! NAME
7374 : : !! gwr_run_chi0
7375 : : !!
7376 : : !! FUNCTION
7377 : : !! Driver to compute CHI0 along the imaginary axis.
7378 : : !!
7379 : : !! INPUTS
7380 : : !! [free_ugb]: True if array with empty KS states should freed as soon as possibile. Default: True
7381 : : !!
7382 : : !! OUTPUT
7383 : : !!
7384 : : !! SOURCE
7385 : :
7386 : 0 : subroutine gwr_run_chi0(gwr, free_ugb)
7387 : :
7388 : : !Arguments ------------------------------------
7389 : : class(gwr_t),intent(inout) :: gwr
7390 : : logical,optional,intent(in) :: free_ugb
7391 : :
7392 : : !Local variables-------------------------------
7393 : : logical :: free_ugb__
7394 : : ! *************************************************************************
7395 : :
7396 : : ! Use ugb wavefunctions and the Lehmann representation to compute head/wings.
7397 : 0 : call gwr%build_chi0_head_and_wings()
7398 : :
7399 : : ! Now compute G(itau) from ugb and start the GWR algorithm for chi.
7400 [ # # ]: 0 : free_ugb__ = .True.; if (present(free_ugb)) free_ugb__ = free_ugb
7401 : 0 : call gwr%build_green(free_ugb=free_ugb__)
7402 : 0 : call gwr%build_tchi()
7403 : :
7404 : 0 : end subroutine gwr_run_chi0
7405 : : !!***
7406 : :
7407 : : !----------------------------------------------------------------------
7408 : :
7409 : : !!****f* m_gwr/gwr_run_energy_scf
7410 : : !! NAME
7411 : : !! gwr_run_energy_scf
7412 : : !!
7413 : : !! FUNCTION
7414 : : !! Compute QP energies within energy-only self-consistent GW approximation
7415 : : !! and minimax meshes along the imaginary axis.
7416 : : !!
7417 : : !! INPUTS
7418 : : !!
7419 : : !! OUTPUT
7420 : : !!
7421 : : !! SOURCE
7422 : :
7423 : 0 : subroutine gwr_run_energy_scf(gwr)
7424 : :
7425 : : !Arguments ------------------------------------
7426 : : class(gwr_t),intent(inout) :: gwr
7427 : :
7428 : : !Local variables-------------------------------
7429 : : integer,parameter :: master = 0
7430 : : integer :: units(2)
7431 : : logical :: converged
7432 : : character(len=500) :: msg
7433 : : ! *************************************************************************
7434 : :
7435 : : ! TODO:
7436 : : ! To implement restart capabilities we need to read scf_iteration, qp_ebands and gwr_task from GWR.nc
7437 : : ! build_sigmac should be responsible for writing checkpoint data with qp_ebands at each iteration.
7438 [ # # ]: 0 : units = [std_out, ab_out]
7439 : :
7440 [ # # ]: 0 : ABI_CHECK_IEQ(gwr%nkcalc, gwr%nkibz, "For energy-only GW, one should include all k-points in the IBZ")
7441 : :
7442 : 0 : select case (gwr%dtset%gwr_task)
7443 : : case ("EGEW")
7444 : 0 : converged = .False.
7445 : 0 : call wrtout(units, " Begin energy-only self-consistency in both G and W (EGEW)")
7446 [ # # # # ]: 0 : do while (.not. converged .and. gwr%scf_iteration <= gwr%dtset%gwr_nstep)
7447 : 0 : call gwr%run_g0w0(free_ugb=.False.)
7448 : 0 : gwr%scf_iteration = gwr%scf_iteration + 1
7449 : 0 : call gwr%check_scf_cycle(converged)
7450 : : end do
7451 : :
7452 : : case ("EGW0")
7453 : 0 : call wrtout(units, " Begin energy-only self-consistency in G (EGW0)")
7454 : 0 : call gwr%run_g0w0(free_ugb=.False.)
7455 : 0 : converged = .False.
7456 [ # # # # ]: 0 : do while (.not. converged .and. gwr%scf_iteration <= gwr%dtset%gwr_nstep)
7457 : 0 : gwr%scf_iteration = gwr%scf_iteration + 1
7458 : 0 : call gwr%build_green(free_ugb=.False.)
7459 : 0 : call gwr%build_sigxme() ! NB: This should not change in semiconductors
7460 : 0 : call gwr%build_sigmac()
7461 : 0 : call gwr%check_scf_cycle(converged)
7462 : : end do
7463 : :
7464 : : case ("G0EW")
7465 : : ! This is more difficult to implement as we need to store G0 and eG
7466 : : ! and then use G only for chi and not in Sigma
7467 : 0 : call wrtout(units, " Begin energy-only self-consistency in W (G0EW)")
7468 : 0 : ABI_ERROR("G0EW is not yet implemented")
7469 : 0 : call gwr%run_g0w0(free_ugb=.False.)
7470 : 0 : converged = .False.
7471 [ # # # # ]: 0 : do while (.not. converged .and. gwr%scf_iteration <= gwr%dtset%gwr_nstep)
7472 : 0 : gwr%scf_iteration = gwr%scf_iteration + 1
7473 : : !call gwr%build_green(free_ugb=.False.)
7474 : 0 : call gwr%build_chi0_head_and_wings()
7475 : 0 : call gwr%build_tchi()
7476 : 0 : call gwr%build_wc()
7477 : 0 : call gwr%build_sigmac()
7478 : 0 : call gwr%check_scf_cycle(converged)
7479 : : end do
7480 : :
7481 : : case default
7482 [ # # # # ]: 0 : ABI_ERROR(sjoin("Invalid gwr_task:", gwr%dtset%gwr_task))
7483 : : end select
7484 : :
7485 [ # # ]: 0 : if (gwr%comm%me == master) then
7486 [ # # ]: 0 : if (converged) then
7487 : : write(msg, "(1x,4a,i0,a,f8.3,a)") &
7488 : 0 : trim(gwr%dtset%gwr_task), " self-consistent loop:", ch10, &
7489 : 0 : " Convergence achieved at iteration: ", gwr%scf_iteration, &
7490 : 0 : " with gwr_tolqpe: ",gwr%dtset%gwr_tolqpe * Ha_meV, " (meV)"
7491 : 0 : call wrtout(units, msg)
7492 : : else
7493 : : write(msg, "(1x,4a,f8.3,3a,i0,a)") &
7494 : 0 : trim(gwr%dtset%gwr_task), " self-consistent loop:", ch10, &
7495 : 0 : " WARNING: Could not converge with gwr_tolqpe: ",gwr%dtset%gwr_tolqpe * Ha_meV, " (meV)", ch10, &
7496 : 0 : " after: ", gwr%dtset%gwr_nstep, " steps"
7497 : 0 : call wrtout(units, msg)
7498 : : end if
7499 : : end if
7500 : :
7501 : 0 : end subroutine gwr_run_energy_scf
7502 : : !!***
7503 : :
7504 : : !----------------------------------------------------------------------
7505 : :
7506 : : !!****f* m_gwr/check_scf_cyle
7507 : : !! NAME
7508 : : !! check_scf_cycle
7509 : : !!
7510 : : !! FUNCTION
7511 : : !!
7512 : : !! INPUTS
7513 : : !!
7514 : : !! OUTPUT
7515 : : !!
7516 : : !! SOURCE
7517 : :
7518 : 0 : subroutine gwr_check_scf_cycle(gwr, converged)
7519 : :
7520 : : !Arguments ------------------------------------
7521 : : class(gwr_t),intent(in) :: gwr
7522 : : logical,intent(out) :: converged
7523 : :
7524 : : !Local variables-------------------------------
7525 : : integer,parameter :: master = 0
7526 : : integer :: spin, ikcalc, ik_ibz, band, ib, jb
7527 : : character(len=500) :: msg
7528 : 0 : real(dp) :: max_adiff, adiff(gwr%qp_ebands%mband)
7529 : : integer :: units(2)
7530 : : ! *************************************************************************
7531 : :
7532 [ # # ]: 0 : max_adiff = -one; converged = .True.; units = [std_out, ab_out]
7533 : :
7534 [ # # ]: 0 : if (gwr%comm%me == master) then
7535 : 0 : call wrtout(units, sjoin(" Checking for convergence at iteration:", itoa(gwr%scf_iteration)))
7536 : : end if
7537 : :
7538 : : associate (now => gwr%qp_ebands, prev => gwr%qp_ebands_prev)
7539 [ # # ]: 0 : do spin=1,gwr%nsppol
7540 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc ! TODO: Should be spin dependent!
7541 : : ! Compute max abs difference between QP at iteration i and i-1.
7542 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
7543 : 0 : ib = gwr%bstart_ks(ikcalc, spin); jb = gwr%bstop_ks(ikcalc, spin)
7544 [ # # # # ]: 0 : adiff = zero; adiff(ib:jb) = abs(now%eig(ib:jb, ik_ibz, spin) - prev%eig(ib:jb, ik_ibz, spin))
7545 [ # # # # : 0 : band = maxloc(adiff, dim=1)
# # # # #
# ]
7546 : 0 : max_adiff = max(max_adiff, adiff(band))
7547 [ # # ]: 0 : if (adiff(band) > gwr%dtset%gwr_tolqpe) converged = .False.
7548 [ # # ]: 0 : if (gwr%comm%me == master) then
7549 : : ! Write info
7550 [ # # ]: 0 : write(msg, "(a,i0,1x,2a,i0)") " For k-point: ", ik_ibz, trim(ktoa(now%kptns(:,ik_ibz))),", spin: ", spin
7551 : 0 : call wrtout(units, msg)
7552 : 0 : write(msg, "(4x,a,es12.5,a,i0)")"max(abs(E_i - E_{i-1})): ", adiff(band) * Ha_meV, " (meV) for band: ", band
7553 : 0 : call wrtout(units, msg)
7554 : : end if
7555 : : end do
7556 : : end do
7557 : : end associate
7558 : :
7559 : : ! Make sure that all MPI procs agree on this!
7560 : 0 : call xmpi_land(converged, gwr%comm%value)
7561 : :
7562 [ # # ]: 0 : if (gwr%comm%me == master) then
7563 : 0 : write(msg, "(a,i0,a)") "QP gaps at iteration: ",gwr%scf_iteration," (Fermi energy set to zero)"
7564 : 0 : call gwr%qp_ebands%print_gaps(units, header=msg)
7565 [ # # ]: 0 : if (.not. converged) then
7566 : 0 : call wrtout(units," Not converged --> start new iteration ...")
7567 : : !else
7568 : : ! call wrtout(units, sjoin(" Convergence achieved at iteration", itoa(gwr%scf_iteration)))
7569 : : end if
7570 : : ! TODO: Increment scf_iteration in GWR.nc
7571 : : end if
7572 : :
7573 : 0 : end subroutine gwr_check_scf_cycle
7574 : : !!***
7575 : :
7576 : : !----------------------------------------------------------------------
7577 : :
7578 : : !!****f* m_gwr/gwr_ncwrite_tchi_wc
7579 : : !! NAME
7580 : : !! gwr_ncwrite_tchi_wc
7581 : : !!
7582 : : !! FUNCTION
7583 : : !! Write tchi or wc to netcdf file
7584 : : !!
7585 : : !! INPUTS
7586 : : !! what: "tchi" or "wc"
7587 : : !! wt_space: "omega" or "tau"
7588 : : !!
7589 : : !! OUTPUT
7590 : : !!
7591 : : !! SOURCE
7592 : :
7593 : 0 : subroutine gwr_ncwrite_tchi_wc(gwr, what, wt_space, keep_file, filepath)
7594 : :
7595 : : !Arguments ------------------------------------
7596 : : class(gwr_t),target,intent(in) :: gwr
7597 : : logical,intent(in) :: keep_file
7598 : : character(len=*),intent(in) :: what, wt_space, filepath
7599 : :
7600 : : !Local variables-------------------------------
7601 : : !scalars
7602 : : integer,parameter :: master = 0
7603 : : integer :: my_is, my_iqi, my_it, spin, iq_ibz, itau, npwtot_q, my_ncols, my_gcol_start, ncid, ncerr, var_id !, ierr
7604 : : real(dp) :: cpu, wall, gflops
7605 : : !arrays
7606 : 0 : real(dp), contiguous, pointer :: fptr(:,:,:)
7607 : 0 : type(__slkmat_t), pointer :: mats(:)
7608 : : ! *************************************************************************
7609 : :
7610 : : ! Cannot reuse SCR.nc/SUSC.nc fileformat as:
7611 : : ! - hscr_new requires ep% instance
7612 : : ! - old file formats assume Gamma-centered G vectors.
7613 : :
7614 : 0 : call cwtime(cpu, wall, gflops, "start")
7615 : :
7616 [ # # ]: 0 : if (gwr%comm%me == master) then
7617 : 0 : call wrtout(std_out, sjoin(" Writing", what, "with wt_space:", wt_space, "to:", filepath))
7618 [ # # ]: 0 : if (keep_file) then
7619 [ # # ]: 0 : NCF_CHECK(nctk_open_modify(ncid, filepath, xmpi_comm_self))
7620 : : else
7621 [ # # ]: 0 : NCF_CHECK(nctk_open_create(ncid, filepath, xmpi_comm_self))
7622 : : end if
7623 : :
7624 : : ! Write structure and qp_ebands
7625 [ # # ]: 0 : NCF_CHECK(gwr%cryst%ncwrite(ncid))
7626 [ # # ]: 0 : NCF_CHECK(gwr%qp_ebands%ncwrite(ncid))
7627 : :
7628 : : ! Add dimensions.
7629 : : ncerr = nctk_def_dims(ncid, [ &
7630 : : nctkdim_t("nsppol", gwr%nsppol), nctkdim_t("ntau", gwr%ntau), nctkdim_t("mpw", gwr%tchi_mpw), &
7631 : : nctkdim_t("nqibz", gwr%nqibz), nctkdim_t("nqbz", gwr%nqbz)], &
7632 [ # # ]: 0 : defmode=.True.)
7633 [ # # ]: 0 : NCF_CHECK(ncerr)
7634 : :
7635 : : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
7636 : : "gwr_completed" &
7637 [ # # ]: 0 : ])
7638 : :
7639 : : ! Define arrays with results.
7640 : : ! TODO: Add metadata for mats: spin sum, vc cutoff, t/w mesh, handle nspinor 2
7641 : : ncerr = nctk_def_arrays(ncid, [ &
7642 : : nctkarr_t("ngkpt", "int", "three"), &
7643 : : nctkarr_t("ngqpt", "int", "three"), &
7644 : : nctkarr_t("qibz", "dp", "three, nqibz"), &
7645 : : nctkarr_t("wtq", "dp", "nqibz"), &
7646 : : nctkarr_t("tau_mesh", "dp", "ntau"), &
7647 : : nctkarr_t("tau_wgs", "dp", "ntau"), &
7648 : : nctkarr_t("iw_mesh", "dp", "ntau"), &
7649 : : nctkarr_t("iw_wgs", "dp", "ntau"), &
7650 : : nctkarr_t("gvecs", "int", "three, mpw, nqibz"), &
7651 : : nctkarr_t("chinpw_qibz", "int", "nqibz") &
7652 [ # # ]: 0 : ])
7653 [ # # ]: 0 : NCF_CHECK(ncerr)
7654 : :
7655 [ # # ]: 0 : if (wt_space == "omega") then
7656 [ # # # # : 0 : NCF_CHECK(nctk_def_arrays(ncid, [nctkarr_t("mats_w", "dp", "two, mpw, mpw, ntau, nqibz, nsppol")]))
# # ]
7657 [ # # ]: 0 : else if (wt_space == "tau") then
7658 [ # # # # : 0 : NCF_CHECK(nctk_def_arrays(ncid, [nctkarr_t("mats_tau", "dp", "two, mpw, mpw, ntau, nqibz, nsppol")]))
# # ]
7659 : : end if
7660 : :
7661 : : ! Write global arrays.
7662 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(ncid))
7663 : :
7664 : : ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
7665 : : "gwr_completed"], &
7666 [ # # ]: 0 : [0])
7667 [ # # ]: 0 : NCF_CHECK(ncerr)
7668 : :
7669 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("ngkpt"), gwr%ngkpt))
7670 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("ngqpt"), gwr%ngqpt))
7671 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("qibz"), gwr%qibz))
7672 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("wtq"), gwr%wtq))
7673 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("tau_mesh"), gwr%tau_mesh))
7674 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("tau_wgs"), gwr%tau_wgs))
7675 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("iw_mesh"), gwr%iw_mesh))
7676 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("iw_wgs"), gwr%iw_wgs))
7677 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("chinpw_qibz"), gwr%chinpw_qibz))
7678 [ # # ]: 0 : NCF_CHECK(nf90_close(ncid))
7679 : : end if
7680 : :
7681 : 0 : call xmpi_barrier(gwr%comm%value)
7682 : :
7683 : : ! Reopen the file in gwr%comm.
7684 [ # # ]: 0 : NCF_CHECK(nctk_open_modify(ncid, filepath, gwr%comm%value))
7685 : :
7686 [ # # ]: 0 : if (wt_space == "omega") then
7687 [ # # ]: 0 : NCF_CHECK(nctk_prepare_mpiio(ncid, "mats_w"))
7688 [ # # ]: 0 : else if (wt_space == "tau") then
7689 [ # # ]: 0 : NCF_CHECK(nctk_prepare_mpiio(ncid, "mats_tau"))
7690 : : end if
7691 : :
7692 [ # # ]: 0 : do my_is=1,gwr%my_nspins
7693 : 0 : spin = gwr%my_spins(my_is)
7694 [ # # ]: 0 : do my_iqi=1,gwr%my_nqibz
7695 : 0 : iq_ibz = gwr%my_qibz_inds(my_iqi)
7696 : :
7697 : : ! The same q-point in the IBZ might be stored on different pools.
7698 : : ! To avoid writing the same array multiple times, we use itreat_qibz
7699 : : ! to select the procs inside gwr%kpt_comm who are gonna write this iq_ibz q-point.
7700 [ # # ]: 0 : if (.not. gwr%itreat_iqibz(iq_ibz)) cycle
7701 : :
7702 : 0 : associate (desc_q => gwr%tchi_desc_qibz(iq_ibz))
7703 : 0 : npwtot_q = desc_q%npw
7704 : :
7705 [ # # ]: 0 : if (spin == 1 .and. gwr%gtau_comm%me == 0) then
7706 : : ! Write all G-vectors for this q
7707 [ # # # # : 0 : NCF_CHECK(nf90_put_var(ncid, vid("gvecs"), desc_q%gvec, start=[1,1,iq_ibz], count=[3,npwtot_q,1]))
# # # # #
# ]
7708 : : end if
7709 : :
7710 : 0 : mats => null()
7711 [ # # ]: 0 : if (what == "tchi") mats => gwr%tchi_qibz(iq_ibz, :, spin)
7712 [ # # ]: 0 : if (what == "wc") mats => gwr%wc_qibz(iq_ibz, :, spin)
7713 [ # # ]: 0 : ABI_CHECK(associated(mats), sjoin("Invalid value for what:", what))
7714 : :
7715 [ # # # # ]: 0 : do my_it=1,gwr%my_ntau
7716 : 0 : itau = gwr%my_itaus(my_it)
7717 : :
7718 : : ! FIXME: Assuming PBLAS matrix distributed in contiguous blocks along the column index.
7719 : : ! This part must be changed if we use round robin distribution.
7720 : 0 : my_ncols = mats(itau)%size_local(2)
7721 : 0 : my_gcol_start = mats(itau)%loc2gcol(1)
7722 : :
7723 : : ! FIXME: This is wrong if spc
7724 : : !call c_f_pointer(c_loc(mats(itau)%buffer_cplx), fptr, shape=[2, npwtot_q, my_ncols])
7725 [ # # # # : 0 : ABI_MALLOC(fptr, (2, npwtot_q, my_ncols))
# # # # #
# # # # #
# # ]
7726 [ # # # # ]: 0 : fptr(1,:,:) = dble(mats(itau)%buffer_cplx)
7727 [ # # # # ]: 0 : fptr(2,:,:) = aimag(mats(itau)%buffer_cplx)
7728 : :
7729 [ # # ]: 0 : if (wt_space == "omega") then
7730 : 0 : var_id = vid("mats_w")
7731 [ # # ]: 0 : else if (wt_space == "tau") then
7732 : 0 : var_id = vid("mats_tau")
7733 : : else
7734 : 0 : ABI_ERROR(sjoin("Invalid wt_space:", wt_space))
7735 : : end if
7736 : :
7737 : : ncerr = nf90_put_var(ncid, var_id, fptr, &
7738 : : start=[1, 1, my_gcol_start, itau, iq_ibz, spin], &
7739 [ # # # # ]: 0 : count=[2, npwtot_q, my_ncols, 1, 1, 1])
7740 : : !stride=[1, gwr%g_comm%nproc, 1, 1, 1])
7741 [ # # ]: 0 : ABI_FREE(fptr)
7742 [ # # ]: 0 : NCF_CHECK(ncerr)
7743 : : end do
7744 : : end associate
7745 : : end do ! my_iqi
7746 : : end do ! my_is
7747 : :
7748 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, vid("gwr_completed"), 1))
7749 [ # # ]: 0 : NCF_CHECK(nf90_close(ncid))
7750 : 0 : call cwtime_report(" gwr_ncwrite_tchi_wc:", cpu, wall, gflops)
7751 : :
7752 : : contains
7753 : 0 : integer function vid(vname)
7754 : : character(len=*),intent(in) :: vname
7755 : 0 : vid = nctk_idname(ncid, vname)
7756 : : end function vid
7757 : :
7758 : : end subroutine gwr_ncwrite_tchi_wc
7759 : : !!***
7760 : :
7761 : : !----------------------------------------------------------------------
7762 : :
7763 : : !!****f* m_gwr/gsph2box
7764 : : !! NAME
7765 : : !! gsph2box
7766 : : !!
7767 : : !! FUNCTION
7768 : : !! Insert cg_k array defined on the k-centered g-sphere with npw vectors inside the FFT box.
7769 : : !! The main difference wrt to sphere is that cfft is not initialized to zero. See notes below.
7770 : : !!
7771 : : !! INPUTS
7772 : : !! ngfft:
7773 : : !! n1,n2,n3=physical dimension of the FFT box
7774 : : !! n4,n5,n6=memory dimension of cfft
7775 : : !! npw=number of G vectors in basis at this k point
7776 : : !! ndat=number of items to process
7777 : : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
7778 : : !! cg(npw*ndat)= contains values for npw G vectors in basis sphere
7779 : : !!
7780 : : !! OUTPUT
7781 : : !! cfft(n4,n5,n6*ndat) = array on FFT box filled with cg data
7782 : : !! Note that cfft is intent(inout) so that we can add contributions from different k-points.
7783 : : !!
7784 : : !! SOURCE
7785 : :
7786 : : subroutine gsph2box(ngfft, npw, ndat, kg_k, cg, cfft)
7787 : :
7788 : : !Arguments ------------------------------------
7789 : : !scalars
7790 : : integer,intent(in) :: ngfft(6), npw, ndat
7791 : : !arrays
7792 : : integer,intent(in) :: kg_k(3, npw)
7793 : : complex(gwp),intent(in) :: cg(npw * ndat)
7794 : : complex(gwp),target,intent(inout) :: cfft(ngfft(4)*ngfft(5)*ngfft(6)*ndat)
7795 : :
7796 : : !Local variables-------------------------------
7797 : : integer :: n1, n2, n3, n4, n5, n6, i1, i2, i3, idat, ipw
7798 : : complex(gwp),contiguous,pointer :: cfft_ptr(:,:,:,:)
7799 : : ! *************************************************************************
7800 : :
7801 : : !call timab(1931, 1, tsec)
7802 : : n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
7803 : : n4 = ngfft(4); n5 = ngfft(5); n6 = ngfft(6)
7804 : : call c_f_pointer(c_loc(cfft), cfft_ptr, shape=[n4, n5, n6, ndat])
7805 : :
7806 : : ! Insert cg into cfft
7807 : : !$OMP PARALLEL DO PRIVATE(i1, i2, i3) IF (ndat > 1)
7808 : : do idat=1,ndat
7809 : : do ipw=1,npw
7810 : : i1 = modulo(kg_k(1, ipw), n1) + 1
7811 : : i2 = modulo(kg_k(2, ipw), n2) + 1
7812 : : i3 = modulo(kg_k(3, ipw), n3) + 1
7813 : : !if (any(kg_k(:,ipw) > ngfft(1:3)/2) .or. any(kg_k(:,ipw) < -(ngfft(1:3)-1)/2) ) then
7814 : : ! ABI_ERROR(sjoin("The G-vector: ",ltoa(kg_k(:, ipw))," falls outside the FFT box. Increase boxcutmin (?)"))
7815 : : !end if
7816 : : cfft_ptr(i1,i2,i3,idat) = cg(ipw+npw*(idat-1))
7817 : : end do
7818 : : end do
7819 : : !call timab(1931, 2, tsec)
7820 : :
7821 : : end subroutine gsph2box
7822 : : !!***
7823 : :
7824 : : !----------------------------------------------------------------------
7825 : :
7826 : : !!****f* m_gwr/box2gsph
7827 : : !! NAME
7828 : : !! box2gsph
7829 : : !!
7830 : : !! FUNCTION
7831 : : !! Extract cg_k array defined on the k-centered g-sphere with npw vectors from the FFT box.
7832 : : !!
7833 : : !! INPUTS
7834 : : !! op_type: OP_COPY to transfer data, OP_ACC to transfer and accumulate
7835 : : !! ngfft:
7836 : : !! n1,n2,n3=physical dimension of the FFT box
7837 : : !! n4,n5,n6=memory dimension of cfft
7838 : : !! npw=number of G vectors in basis at this k point
7839 : : !! ndat=number of items to process
7840 : : !! kg_k(3,npw)=integer coordinates of G vectors in basis sphere
7841 : : !! cfft(n4,n5,n6, ndat) = array on FFT box
7842 : : !!
7843 : : !! SIZE
7844 : : !! cg(npw*ndat)= contains values for npw G vectors in basis sphere. See also op_type
7845 : : !!
7846 : : !! SOURCE
7847 : :
7848 : 0 : subroutine box2gsph(op_type, ngfft, npw, ndat, kg_k, cfft, cg)
7849 : :
7850 : : !Arguments ------------------------------------
7851 : : !scalars
7852 : : integer,intent(in) :: op_type, ngfft(6), npw, ndat
7853 : : !arrays
7854 : : integer,intent(in) :: kg_k(3, npw)
7855 : : complex(gwp),target,intent(in) :: cfft(ngfft(4)*ngfft(5)*ngfft(6)*ndat)
7856 : : complex(gwp),intent(inout) :: cg(npw*ndat)
7857 : :
7858 : : !Local variables-------------------------------
7859 : : integer :: n1, n2, n3, n4, n5, n6, i1, i2, i3, idat, ipw, icg
7860 : 0 : complex(gwp),contiguous,pointer :: cfft_ptr(:,:,:,:)
7861 : : ! *************************************************************************
7862 : :
7863 : 0 : n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
7864 : 0 : n4 = ngfft(4); n5 = ngfft(5); n6 = ngfft(6)
7865 [ # # ]: 0 : call c_f_pointer(c_loc(cfft), cfft_ptr, shape=[n4, n5, n6, ndat])
7866 : :
7867 : 0 : select case (op_type)
7868 : :
7869 : : case (OP_COPY)
7870 : : ! Extract cg from cfft, ignoring components outside range of cg sphere
7871 : : !$OMP PARALLEL DO PRIVATE(i1, i2, i3, icg) IF (ndat > 1)
7872 [ # # ]: 0 : do idat=1,ndat
7873 [ # # ]: 0 : do ipw=1,npw
7874 : 0 : i1 = modulo(kg_k(1, ipw), n1) + 1
7875 : 0 : i2 = modulo(kg_k(2, ipw), n2) + 1
7876 : 0 : i3 = modulo(kg_k(3, ipw), n3) + 1
7877 : : !if (any(kg_k(:,ipw) > ngfft(1:3)/2) .or. any(kg_k(:,ipw) < -(ngfft(1:3)-1)/2) ) then
7878 : : ! ABI_ERROR(sjoin("The G-vector: ",ltoa(kg_k(:, ipw))," falls outside the FFT box. Increase boxcutmin (?)"))
7879 : : !end if
7880 : 0 : icg = ipw + (idat - 1) * npw
7881 : 0 : cg(icg) = cfft_ptr(i1, i2, i3, idat)
7882 : : end do
7883 : : end do
7884 : :
7885 : : case (OP_ACC)
7886 : : ! Extract cg from cfft, ignoring components outside range of cg sphere and accumulate
7887 : : !$OMP PARALLEL DO PRIVATE(i1, i2, i3, icg) IF (ndat > 1)
7888 [ # # ]: 0 : do idat=1,ndat
7889 [ # # ]: 0 : do ipw=1,npw
7890 : 0 : i1 = modulo(kg_k(1, ipw), n1) + 1
7891 : 0 : i2 = modulo(kg_k(2, ipw), n2) + 1
7892 : 0 : i3 = modulo(kg_k(3, ipw), n3) + 1
7893 : : !if (any(kg_k(:,ipw) > ngfft(1:3)/2) .or. any(kg_k(:,ipw) < -(ngfft(1:3)-1)/2) ) then
7894 : : ! ABI_ERROR(sjoin("The G-vector: ",ltoa(kg_k(:, ipw))," falls outside the FFT box. Increase boxcutmin (?)"))
7895 : : !end if
7896 : 0 : icg = ipw + (idat - 1) * npw
7897 : 0 : cg(icg) = cg(icg) + cfft_ptr(i1, i2, i3, idat)
7898 : : end do
7899 : : end do
7900 : :
7901 : : case default
7902 [ # # # ]: 0 : ABI_BUG(sjoin("Invalid op_type:" ,itoa(op_type)))
7903 : : end select
7904 : :
7905 : 0 : end subroutine box2gsph
7906 : : !!***
7907 : :
7908 : : !----------------------------------------------------------------------
7909 : :
7910 : : !!****f* m_gwr/gwr_build_chi0_head_and_wings
7911 : : !! NAME
7912 : : !! gwr_build_chi0_head_and_wings
7913 : : !!
7914 : : !! FUNCTION
7915 : : !! Compute head and wings of chi0 on the minimax frequency grid.
7916 : : !!
7917 : : !! SOURCE
7918 : :
7919 : 0 : subroutine gwr_build_chi0_head_and_wings(gwr)
7920 : :
7921 : : !Arguments ------------------------------------
7922 : : class(gwr_t),target,intent(inout) :: gwr
7923 : :
7924 : : !Local variables-------------------------------
7925 : : !scalars
7926 : : integer,parameter :: two_poles = 2, one_pole = 1, gwcomp0 = 0, spmeth0 = 0
7927 : : integer :: nsppol, nspinor, ierr, my_is, spin, my_ikf, itau, my_it
7928 : : integer :: ik_bz, ik_ibz, isym_k, trev_k, g0_k(3)
7929 : : !integer :: iq_bz, iq_ibz, isym_q, trev_q, g0_q(3)
7930 : : integer :: nkpt_summed, use_umklp, band1, band2, band1_start, band1_stop, band1_max
7931 : : integer :: ib, il_b2, nb, block_size, ii, mband, block_counter !,idir !, iab
7932 : : integer :: istwf_ki, npw_ki, istwf_kf, nI, nJ, nomega, io, iq, nq, dim_rtwg !ig,
7933 : : integer :: npwe, u_nfft, u_mgfft, u_mpw
7934 : : logical :: isirr_k, use_tr, is_metallic, print_time, use_ddk
7935 : : real(dp) :: spin_fact, weight, deltaf_b1b2, deltaeGW_b1b2, gwr_boxcutmin_c, zcut, qlen, eig_nk, eig_mk, e0
7936 : : real(dp) :: cpu_all, wall_all, gflops_all, cpu_k, wall_k, gflops_k
7937 : : complex(dp) :: deltaeKS_b1b2
7938 : : type(__slkmat_t),pointer :: ugb_kibz
7939 : : character(len=5000) :: msg
7940 : : type(crystal_t),pointer :: cryst
7941 : : type(dataset_type),pointer :: dtset
7942 : : type(ebands_t),pointer :: now_ebands
7943 : 0 : type(littlegroup_t) :: ltg_q
7944 : : type(desc_t),pointer :: desc_ki
7945 : : !arrays
7946 : : integer :: gmax(3), u_ngfft(18), work_ngfft(18), units(2) !, spinor_pad(2,4), spad1, spad2 !, ! g0(3),
7947 : 0 : integer,contiguous, pointer :: kg_ki(:,:)
7948 : 0 : integer,allocatable :: gvec_q0(:,:), gbound_q0(:,:), u_gbound(:,:)
7949 : : real(dp) :: kk_ibz(3), kk_bz(3), tsec(2) !, rtmp(2)
7950 : 0 : real(dp),contiguous, pointer :: qp_eig(:,:,:), qp_occ(:,:,:), ks_eig(:,:,:)
7951 : 0 : real(dp),allocatable :: work(:,:,:,:), qdirs(:,:)
7952 : 0 : logical :: gradk_not_done(gwr%nkibz)
7953 : 0 : logical,allocatable :: bbp_mask(:,:)
7954 : : complex(dp) :: chq(3)
7955 : 0 : complex(gwp) :: rhotwx(3, gwr%nspinor**2)
7956 : 0 : complex(gwp),allocatable :: ug2(:), ur1_kibz(:), ur2_kibz(:), ur_prod(:), rhotwg(:), ug1_block(:,:), ug1(:)
7957 : 0 : complex(dp) :: green_w(gwr%ntau), omega(gwr%ntau)
7958 : 0 : complex(dp),allocatable :: chi0_lwing(:,:,:), chi0_uwing(:,:,:), chi0_head(:,:,:), head_qvals(:)
7959 : 0 : real(dp), allocatable :: ddk_ug1(:,:,:), cg2_dp(:,:)
7960 : 0 : type(vkbr_t),allocatable :: vkbr(:)
7961 : 0 : type(gsphere_t) :: gsph
7962 [ # # # # : 0 : type(ddkop_t) :: ddkop
# # ]
7963 : 0 : type(pawcprj_type),allocatable :: cwaveprj(:,:)
7964 : : ! *************************************************************************
7965 : :
7966 [ # # ]: 0 : units = [std_out, ab_out]
7967 : 0 : call timab(1927, 1, tsec)
7968 : 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
7969 : 0 : call wrtout(units, sjoin(" Computing chi0 head and wings with inclvkb:", itoa(gwr%dtset%inclvkb)), pre_newlines=1)
7970 : :
7971 : 0 : nspinor = gwr%nspinor; nsppol = gwr%nsppol; dtset => gwr%dtset; cryst => gwr%cryst
7972 : 0 : use_tr = gwr%dtset%awtr == 1; zcut = gwr%dtset%zcut ! well, it's not used in g0w0 when omega is complex.
7973 : :
7974 : : ! Use KS or QP energies depending on the iteration state.
7975 [ # # ]: 0 : if (gwr%scf_iteration == 1) then
7976 : 0 : call wrtout(units, " Using KS orbitals and KS energies...", newlines=1, do_flush=.True.)
7977 : 0 : qp_eig => gwr%ks_ebands%eig; qp_occ => gwr%ks_ebands%occ
7978 : 0 : now_ebands => gwr%ks_ebands
7979 : : else
7980 : 0 : call wrtout(units, " Using KS orbitals and QP energies...", newlines=1, do_flush=.True.)
7981 : 0 : qp_eig => gwr%qp_ebands%eig; qp_occ => gwr%qp_ebands%occ
7982 : 0 : now_ebands => gwr%qp_ebands
7983 : : end if
7984 : :
7985 : 0 : ks_eig => gwr%ks_ebands%eig
7986 : 0 : mband = gwr%ks_ebands%mband
7987 : :
7988 : 0 : is_metallic = now_ebands%has_metal_scheme()
7989 : :
7990 : : ! Setup weight (2 for spin unpolarized systems, 1 for polarized).
7991 : : ! spin_fact is used to normalize the occupation factors to one.
7992 : : ! Consider also the AFM case.
7993 : 0 : select case (nsppol)
7994 : : case (1)
7995 : 0 : weight = two / gwr%nkbz; spin_fact = half
7996 [ # # ]: 0 : if (gwr%nspden == 2) then
7997 : 0 : weight = one / gwr%nkbz; spin_fact = half
7998 : : end if
7999 [ # # ]: 0 : if (nspinor == 2) then
8000 : 0 : weight = one / gwr%nkbz; spin_fact = one
8001 : : end if
8002 : : case (2)
8003 : 0 : weight = one / gwr%nkbz; spin_fact = one
8004 : : case default
8005 [ # # # ]: 0 : ABI_BUG(sjoin("Wrong nsppol:", itoa(nsppol)))
8006 : : end select
8007 : :
8008 : : ! TODO: Replace vkbr with ddk and factorize calls to DDK |bra>
8009 [ # # # # : 0 : ABI_MALLOC(vkbr, (gwr%nkibz))
# # # # #
# # # #
# ]
8010 [ # # ]: 0 : gradk_not_done = .TRUE.
8011 : :
8012 : : ! TODO: Big allocation. Might become 1b
8013 [ # # # # : 0 : ABI_MALLOC(bbp_mask, (mband, mband))
# # # # #
# # # # #
# # ]
8014 : :
8015 : : ! =========================================
8016 : : ! Find FFT mesh and max number of g-vectors
8017 : : ! =========================================
8018 : : ! TODO: Can be decreased. Consider also fftgw
8019 : 0 : gwr_boxcutmin_c = two
8020 : : !gwr_boxcutmin_c = one
8021 : 0 : call gwr%get_u_ngfft(gwr_boxcutmin_c, u_ngfft, u_nfft, u_mgfft, u_mpw, gmax)
8022 : :
8023 : : ! Init work_ngfft
8024 [ # # ]: 0 : gmax = gmax + 4 ! FIXME: this is to account for umklapp, should also consider Gamma-only and istwfk
8025 [ # # ]: 0 : gmax = 2 * gmax + 1
8026 : 0 : call ngfft_seq(work_ngfft, gmax)
8027 : : !write(std_out,*)"work_ngfft(1:3): ",work_ngfft(1:3)
8028 [ # # # # : 0 : ABI_MALLOC(work, (2, work_ngfft(4), work_ngfft(5), work_ngfft(6)))
# # # # #
# # # # #
# # # # #
# ]
8029 : :
8030 [ # # # # ]: 0 : if (gwr%comm%me == 0) call print_ngfft([std_out], u_ngfft, header="FFT mesh for chi0 head/wings computation")
8031 : :
8032 : : ! Need to broadcast G-vectors at q = 0 if k/q-point parallelism is activated.
8033 [ # # ]: 0 : if (gwr%kpt_comm%me == 0) then
8034 : 0 : npwe = gwr%tchi_desc_qibz(1)%npw
8035 [ # # ]: 0 : ABI_CHECK(gwr%tchi_desc_qibz(1)%kin_sorted, "g-vectors are not sorted by |q+g|^2/2 !")
8036 : : end if
8037 : 0 : call xmpi_bcast(npwe, 0, gwr%kpt_comm%value, ierr)
8038 [ # # # # : 0 : ABI_MALLOC(gvec_q0, (3, npwe))
# # # # #
# # # ]
8039 [ # # # # : 0 : if (gwr%kpt_comm%me == 0) gvec_q0 = gwr%tchi_desc_qibz(1)%gvec
# # # # #
# # # # #
# # # # ]
8040 : 0 : call xmpi_bcast(gvec_q0, 0, gwr%kpt_comm%value, ierr)
8041 : :
8042 : : ! This is needed to call accumulate_head_wings_imagw
8043 : 0 : call gsph%init(cryst, npwe, gvec_q0)
8044 : :
8045 [ # # # # : 0 : ABI_MALLOC(gbound_q0, (2 * u_mgfft + 8, 2))
# # # # #
# # # # #
# # ]
8046 : 0 : call sphereboundary(gbound_q0, istwfk1, gvec_q0, u_mgfft, npwe)
8047 : :
8048 : : ! Init little group to find IBZ_q
8049 : 0 : use_umklp = 0
8050 : 0 : call ltg_q%init([zero, zero, zero], gwr%nkbz, gwr%kbz, cryst, use_umklp, npwe) !, gvec=gvec_kss)
8051 : :
8052 : 0 : nkpt_summed = gwr%nkbz
8053 [ # # ]: 0 : if (dtset%symchi /= 0) then
8054 : 0 : nkpt_summed = ltg_q%nibz_ltg
8055 [ # # ]: 0 : call ltg_q%print([std_out], prtvol=dtset%prtvol)
8056 : : end if
8057 : 0 : call wrtout(std_out, sjoin(' Calculation status: ', itoa(nkpt_summed), ' k-points to be completed'))
8058 : :
8059 : : ! ============================================
8060 : : ! === Begin big fat loop over transitions ====
8061 : : ! ============================================
8062 : :
8063 : : ! NB: One might reduce the number of bands as head and wings converge fast wrt nband and slow wrt k-mesh.
8064 : : ! Should introduce a tolerance on the frequency part computed at the first minimax frequency and
8065 : : ! compute max_nband from this.
8066 : :
8067 : : ! Find band1_max from gwr_max_hwtene
8068 : 0 : band1_max = gwr%ugb_nband
8069 [ # # ]: 0 : if (gwr%dtset%gwr_max_hwtene > zero) then
8070 : : ! Set e0 to top of valence band if semiconductor else Fermi level
8071 : 0 : e0 = now_ebands%fermie
8072 [ # # # # : 0 : if (all(gwr%ks_gaps%ierr == 0)) e0 = minval(gwr%ks_gaps%vb_max)
# # # # #
# # # #
# ]
8073 [ # # ]: 0 : do band1_start=1, gwr%ugb_nband
8074 [ # # # # : 0 : if (all(qp_eig(band1_start,:,:) - e0 > gwr%dtset%gwr_max_hwtene)) then
# # # # ]
8075 : 0 : band1_max = band1_start; exit
8076 : : end if
8077 : : end do
8078 : : !else if (gwr%dtset%gwr_max_hwtene < zero) then
8079 : : ! band1_max = min(nint(-gwr%dtset%gwr_max_hwtene) gwr%ugb_nband)
8080 : : end if
8081 : :
8082 : 0 : call wrtout(std_out, sjoin(" gwr_max_hwtene:", ftoa(gwr%dtset%gwr_max_hwtene * Ha_eV), " (eV)"))
8083 : 0 : call wrtout(std_out, sjoin(" Using: ", itoa(band1_max), "/", itoa(gwr%ugb_nband), "bands for chi0 head and wings."))
8084 : :
8085 : : ! Loop on spin to calculate $\chi_{\up,\up} + \chi_{\down,\down}$
8086 : : ! TODO: nspinor 2
8087 : 0 : nI = 1; nJ = 1; nomega = gwr%ntau
8088 [ # # ]: 0 : omega(:) = j_dpc * gwr%iw_mesh(:)
8089 [ # # # # : 0 : ABI_CALLOC(chi0_lwing, (npwe*nI, nomega, 3))
# # # # #
# # # # #
# # # # #
# # # #
# ]
8090 [ # # # # : 0 : ABI_CALLOC(chi0_uwing, (npwe*nJ, nomega, 3))
# # # # #
# # # # #
# # # # ]
8091 [ # # # # : 0 : ABI_CALLOC(chi0_head, (3, 3, nomega))
# # # # #
# # # # #
# # # # ]
8092 : :
8093 [ # # # # : 0 : ABI_MALLOC(u_gbound, (2 * u_mgfft + 8, 2))
# # # # ]
8094 [ # # # # : 0 : ABI_MALLOC(ur1_kibz, (u_nfft * nspinor))
# # # # #
# # # ]
8095 [ # # # # : 0 : ABI_MALLOC(ur2_kibz, (u_nfft * nspinor))
# # # # ]
8096 [ # # # # : 0 : ABI_MALLOC(ur_prod, (u_nfft * nspinor))
# # # # ]
8097 [ # # ]: 0 : dim_rtwg = 1; if (nspinor == 2) dim_rtwg = 2 ! Can reduce size depending on Ep%nI and Ep%nj
8098 [ # # # # : 0 : ABI_MALLOC(rhotwg, (npwe * dim_rtwg))
# # # # #
# # # ]
8099 : :
8100 : : ! TODO: use ddkop instead of commutator so that we can handle SOC terms.
8101 : : use_ddk = .False.
8102 : 0 : use_ddk = gwr%dtset%userie == 432
8103 : 0 : use_ddk = .True.
8104 : : if (use_ddk) then
8105 : 0 : call wrtout(std_out, " Using DDK to compute the commutator matrix elements.")
8106 [ # # # # : 0 : call ddkop%init(dtset, gwr%cryst, gwr%pawtab, gwr%psps, gwr%mpi_enreg, u_mpw, u_ngfft)
# # # # ]
8107 : : end if
8108 : :
8109 [ # # ]: 0 : ABI_CHECK_IEQ(dtset%symchi, 1, "symchi 0 not implemented")
8110 : : if (dtset%nspinor == 2 .and. .not. use_ddk) then
8111 : : ABI_CHECK_IEQ(dtset%inclvkb, 0, "inclvkb must be 0 when nspinor == 2 as SOC term is not coded.")
8112 : : end if
8113 : :
8114 : : ! Loop over collinear spins.
8115 [ # # ]: 0 : do my_is=1,gwr%my_nspins
8116 : 0 : spin = gwr%my_spins(my_is)
8117 : :
8118 : : ! Loop over my k-points in the BZ.
8119 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
8120 : 0 : ik_bz = gwr%my_kbz_inds(my_ikf); kk_bz = gwr%kbz(:, ik_bz)
8121 : 0 : istwf_kf = 1
8122 : : !istwf_kf = gwt% ???
8123 : :
8124 [ # # # # ]: 0 : if (dtset%symchi == 1 .and. ltg_q%ibzq(ik_bz) /= 1) CYCLE ! Only IBZ_q
8125 [ # # # # : 0 : print_time = gwr%comm%me == 0 .and. (my_ikf <= LOG_MODK .or. mod(my_ikf, LOG_MODK) == 0)
# # ]
8126 : 0 : if (print_time) call cwtime(cpu_k, wall_k, gflops_k, "start")
8127 : : !write(*, *)" For kpoint:", trim(ktoa(kk_bz))
8128 : :
8129 : : ! FIXME: Be careful with the symmetry conventions here! and the interplay between umklapp in q and FFT
8130 : : ! Also, the assembly_chi0 routines assume symrec and trev_k in [1, 2]
8131 : 0 : ik_ibz = gwr%kbz2ibz_symrel(1, ik_bz); isym_k = gwr%kbz2ibz_symrel(2, ik_bz)
8132 : 0 : trev_k = gwr%kbz2ibz_symrel(6, ik_bz); g0_k = gwr%kbz2ibz_symrel(3:5, ik_bz)
8133 : : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
8134 [ # # ]: 0 : kk_ibz = gwr%kibz(:, ik_ibz)
8135 : :
8136 : 0 : ugb_kibz => gwr%ugb(ik_ibz, spin)
8137 : 0 : desc_ki => gwr%green_desc_kibz(ik_ibz)
8138 : 0 : npw_ki = desc_ki%npw
8139 : 0 : istwf_ki = desc_ki%istwfk
8140 : 0 : kg_ki => desc_ki%gvec
8141 : :
8142 [ # # # # : 0 : ABI_MALLOC(ug1, (npw_ki * nspinor))
# # # # #
# # # ]
8143 [ # # # # : 0 : ABI_MALLOC(ug2, (npw_ki * nspinor))
# # # # ]
8144 [ # # # # : 0 : ABI_MALLOC(cg2_dp, (2, npw_ki * nspinor))
# # # # #
# # # ]
8145 : :
8146 : 0 : call sphereboundary(u_gbound, istwf_ki, kg_ki, u_mgfft, npw_ki)
8147 : :
8148 [ # # # # : 0 : if (gwr%usepaw == 0 .and. dtset%inclvkb /= 0 .and. gradk_not_done(ik_ibz)) then
# # ]
8149 : : ! Include term <n,k|[Vnl,iqr]|n"k>' for q -> 0.
8150 : 0 : call vkbr_init(vkbr(ik_ibz), cryst, gwr%psps, dtset%inclvkb, istwf_ki, npw_ki, kk_ibz, kg_ki)
8151 : 0 : gradk_not_done(ik_ibz) = .FALSE.
8152 : : end if
8153 : :
8154 : : if (use_ddk) then
8155 : 0 : call ddkop%setup_spin_kpoint(gwr%dtset, gwr%cryst, gwr%psps, spin, kk_ibz, istwf_ki, npw_ki, kg_ki)
8156 : : end if
8157 : :
8158 : : call chi0_bbp_mask(ik_ibz, ik_ibz, spin, spin_fact, use_tr, &
8159 : 0 : gwcomp0, spmeth0, gwr%ugb_nband, mband, now_ebands, bbp_mask)
8160 : : !bbp_mask = .True.
8161 : :
8162 : : ! FIXME: This part should be tested with tau/g-para
8163 : : ! TODO:
8164 : : ! 1) Logic to determine block_size from memory.
8165 : : ! 2) Add support for symchi = 0
8166 : : ! 3) Invert the loops
8167 : :
8168 : 0 : block_size = min(48, gwr%ugb_nband)
8169 : :
8170 : 0 : block_counter = 0
8171 [ # # # # : 0 : do band1_start=1, gwr%ugb_nband, block_size
# # # # ]
8172 : 0 : block_counter = block_counter + 1
8173 : : ! Distribute blocks inside tau_comm as wavefunctions are replicated.
8174 [ # # ]: 0 : if (gwr%tau_comm%skip(block_counter)) cycle
8175 : :
8176 [ # # # # : 0 : if (all(.not. bbp_mask(band1_start:, :))) then
# # # # ]
8177 : : !print *, "exiting band1_start loop"
8178 : : exit
8179 : : end if
8180 : :
8181 : : !print *, "band1_start, gwr%ugb_nband, block_size", band1_start, gwr%ugb_nband, block_size
8182 : 0 : nb = blocked_loop(band1_start, gwr%ugb_nband, block_size)
8183 : 0 : band1_stop = band1_start + nb - 1
8184 [ # # ]: 0 : if (band1_stop > band1_max) exit
8185 : :
8186 : : ! Collect nb bands starting from band1_start on each proc.
8187 [ # # # # ]: 0 : call ugb_kibz%collect_cplx(npw_ki * nspinor, nb, [1, band1_start], ug1_block)
8188 : :
8189 : : ! Precompute DH_DK |psi_b1>.
8190 [ # # # # : 0 : ABI_MALLOC(ddk_ug1, (2, npw_ki * nspinor, 3))
# # # # #
# # # # #
# # ]
8191 : :
8192 : : ! Loop over "conduction" states.
8193 : : !do band1=band1_start, band1_stop
8194 [ # # ]: 0 : do ib=1,nb
8195 : 0 : band1 = band1_start + ib - 1
8196 : 0 : eig_nk = gwr%ks_ebands%eig(band1, ik_ibz, spin)
8197 : :
8198 : : ! FFT band1 from g to r
8199 [ # # # # : 0 : ug1 = ug1_block(:, ib)
# # # # ]
8200 : 0 : call fft_ug(npw_ki, u_nfft, nspinor, ndat1, u_mgfft, u_ngfft, istwf_ki, kg_ki, u_gbound, ug1, ur1_kibz)
8201 : :
8202 : : if (use_ddk) then
8203 : : ! Compute DH_DK |psi_k,bi>, store results in ddk_ug1
8204 [ # # ]: 0 : ddk_ug1(1,:,1) = real(ug1)
8205 [ # # ]: 0 : ddk_ug1(2,:,1) = aimag(ug1)
8206 : 0 : call ddkop%apply(eig_nk, npw_ki, nspinor, ddk_ug1(:,:,1), cwaveprj)
8207 : : end if
8208 : :
8209 : : ! Loop over "valence" states.
8210 : : !do band2=1,gwr%ugb_nband
8211 [ # # ]: 0 : do il_b2=1, ugb_kibz%size_local(2)
8212 : 0 : band2 = ugb_kibz%loc2gcol(il_b2)
8213 : :
8214 : 0 : eig_mk = gwr%ks_ebands%eig(band2, ik_ibz, spin)
8215 : :
8216 : 0 : deltaeKS_b1b2 = ks_eig(band1, ik_ibz, spin) - ks_eig(band2, ik_ibz, spin)
8217 : 0 : deltaf_b1b2 = spin_fact * (qp_occ(band1, ik_ibz, spin) - qp_occ(band2, ik_ibz, spin))
8218 : 0 : deltaeGW_b1b2 = qp_eig(band1, ik_ibz, spin) - qp_eig(band2, ik_ibz, spin)
8219 : :
8220 : : ! Skip negligible transitions.
8221 [ # # ]: 0 : if (abs(deltaf_b1b2) < GW_TOL_DOCC) CYCLE
8222 : : ! Adler-Wiser expression.
8223 : : ! Add small imaginary of the Time-Ordered response function but only for non-zero real omega
8224 : : ! FIXME What about metals?
8225 [ # # ]: 0 : if (.not. use_tr) then
8226 : : ! Adler-Wiser without time-reversal.
8227 [ # # ]: 0 : do io=1,nomega
8228 : 0 : green_w(io) = g0g0w(omega(io), deltaf_b1b2, deltaeGW_b1b2, zcut, GW_TOL_W0, one_pole)
8229 : : end do
8230 : :
8231 : : else
8232 [ # # ]: 0 : if (band1 < band2) CYCLE ! Here we GAIN a factor ~2
8233 : :
8234 [ # # ]: 0 : do io=1,nomega
8235 : : ! Rangel: In metals, the intra-band transitions term does not contain the antiresonant part
8236 : : ! if(abs(deltaeGW_b1b2)>GW_TOL_W0) green_w(io) = g0g0w(omega(io),deltaf_b1b2,deltaeGW_b1b2,zcut,GW_TOL_W0)
8237 [ # # ]: 0 : if (band1 == band2) green_w(io) = g0g0w(omega(io), deltaf_b1b2, deltaeGW_b1b2, zcut, GW_TOL_W0, one_pole)
8238 [ # # ]: 0 : if (band1 /= band2) green_w(io) = g0g0w(omega(io), deltaf_b1b2, deltaeGW_b1b2, zcut, GW_TOL_W0, two_poles)
8239 : : end do
8240 : : end if
8241 : :
8242 : : ! FFT band2 from g to r
8243 [ # # # # : 0 : ug2 = ugb_kibz%buffer_cplx(:, il_b2)
# # # # ]
8244 : 0 : call fft_ug(npw_ki, u_nfft, nspinor, ndat1, u_mgfft, u_ngfft, istwf_ki, kg_ki, u_gbound, ug2, ur2_kibz)
8245 : :
8246 [ # # ]: 0 : ur_prod(:) = conjg(ur1_kibz(:)) * ur2_kibz
8247 : 0 : call fft_ur(npwe, u_nfft, nspinor, ndat1, u_mgfft, u_ngfft, istwfk1, gvec_q0, gbound_q0, ur_prod, rhotwg)
8248 : : ! if nspinor == 2, sum 11, 22 terms in spin space
8249 [ # # # # ]: 0 : if (nspinor == 2) rhotwg(1:npwe) = rhotwg(1:npwe) + rhotwg(npwe+1:2*npwe)
8250 : :
8251 : : if (.not. use_ddk) then
8252 : : if (gwr%usepaw == 0 ) then
8253 : : ! Matrix elements of i[H,r] for NC pseudopotentials.
8254 : : ! NB ug1 and ug2 are kind=gwp
8255 : : rhotwx = nc_ihr_comm(vkbr(ik_ibz), cryst, gwr%psps, npw_ki, nspinor, istwf_ki, gwr%dtset%inclvkb, &
8256 : : kk_ibz, ug1, ug2, kg_ki)
8257 : : end if
8258 : : else
8259 [ # # ]: 0 : cg2_dp(1,:) = real(ug2)
8260 [ # # ]: 0 : cg2_dp(2,:) = aimag(ug2)
8261 : :
8262 : : ! DH_DK operator is Hermitian.
8263 : 0 : call ddkop%get_ihr_comm(cryst, eig_mk, istwf_ki, npw_ki, nspinor, cg2_dp, rhotwx)
8264 [ # # # # ]: 0 : rhotwx = conjg(rhotwx)
8265 : :
8266 : : ! debug section
8267 : : !do idir=1,3
8268 : : ! write(std_out, "(a, *(es12.5,2x))")"rhotwx: ", rhotwx(:, 1)
8269 : : ! write(std_out, "(a, *(es12.5,2x))")"new_rhotwx:", new_rhotwx(:, 1)
8270 : : ! !write(std_out, "(a, *(es12.5,2x))")"ratio old/new:", rhotwx(:, 1) / new_rhotwx(:, 1)
8271 : : ! do iab=1,gwr%nspinor**2
8272 : : ! if (abs(rhotwx(iab,1) - new_rhotwx(iab,1)) > tol6 .and. &
8273 : : ! (abs(rhotwx(iab,1)) > tol6 .or. abs(new_rhotwx(iab,1)) > tol6)) then
8274 : : ! write(std_out, "(a, *(es12.5,2x))")"rhotwx: ", rhotwx(iab, 1)
8275 : : ! write(std_out, "(a, *(es12.5,2x))")"new_rhotwx:", new_rhotwx(iab, 1)
8276 : : ! ABI_ERROR("Too large diff")
8277 : : ! end if
8278 : : ! end do
8279 : : !end do
8280 : : end if ! use_ddk
8281 : :
8282 : : ! Treat a possible degeneracy between v and c.
8283 : : ! Adler-Wiser expression, to be consistent here we use the KS eigenvalues (?)
8284 [ # # ]: 0 : if (abs(deltaeKS_b1b2) > GW_TOL_W0) then
8285 [ # # # # ]: 0 : rhotwx = -rhotwx / deltaeKS_b1b2
8286 : : else
8287 [ # # # # ]: 0 : rhotwx = czero_gw
8288 : : end if
8289 : :
8290 : : ! NB: Using symrec conventions here
8291 : 0 : ik_ibz = gwr%kbz2ibz(1, ik_bz); isym_k = gwr%kbz2ibz(2, ik_bz)
8292 : 0 : trev_k = gwr%kbz2ibz(6, ik_bz); g0_k = gwr%kbz2ibz(3:5, ik_bz)
8293 : 0 : trev_k = trev_k + 1 ! NB: GW routines assume trev in [1, 2]
8294 : :
8295 : : ! TODO: Metals
8296 : : ! Note: if nspinor == 2, only rhotgw(1:npwe) with the 11 + 22 sum is used.
8297 : : call accumulate_head_wings_imagw( &
8298 : : npwe, nomega, nI, nJ, dtset%symchi, &
8299 : : is_metallic, ik_bz, isym_k, trev_k, nspinor, cryst, ltg_q, gsph, &
8300 : 0 : rhotwx, rhotwg, green_w, chi0_head, chi0_lwing, chi0_uwing)
8301 : : end do ! band2
8302 : : end do ! band1
8303 : :
8304 [ # # ]: 0 : ABI_FREE(ug1_block)
8305 [ # # ]: 0 : ABI_SFREE(ddk_ug1)
8306 : : end do ! band1_start
8307 : :
8308 [ # # ]: 0 : ABI_FREE(ug1)
8309 [ # # ]: 0 : ABI_FREE(ug2)
8310 [ # # ]: 0 : ABI_FREE(cg2_dp)
8311 : :
8312 [ # # ]: 0 : if (print_time) then
8313 : 0 : write(msg,'(4x,3(a,i0),a)')"my_ikf [", my_ikf, "/", gwr%my_nkbz, "] (tot: ", gwr%nkbz, ")"
8314 [ # # ]: 0 : call cwtime_report(msg, cpu_k, wall_k, gflops_k); if (my_ikf == LOG_MODK) call wrtout(std_out, " ...")
8315 : : end if
8316 : : end do ! my_ikf
8317 : : end do ! my_is
8318 : :
8319 [ # # ]: 0 : ABI_FREE(bbp_mask)
8320 [ # # ]: 0 : ABI_FREE(gvec_q0)
8321 [ # # ]: 0 : ABI_FREE(gbound_q0)
8322 [ # # ]: 0 : ABI_FREE(work)
8323 [ # # ]: 0 : ABI_FREE(ur1_kibz)
8324 [ # # ]: 0 : ABI_FREE(ur2_kibz)
8325 [ # # ]: 0 : ABI_FREE(ur_prod)
8326 [ # # ]: 0 : ABI_FREE(rhotwg)
8327 [ # # ]: 0 : ABI_FREE(u_gbound)
8328 : :
8329 : 0 : if (use_ddk) call ddkop%free()
8330 : 0 : call vkbr_free(vkbr)
8331 [ # # # # : 0 : ABI_FREE(vkbr)
# # # # #
# ]
8332 : :
8333 : : ! Collect head and wings.
8334 : 0 : call xmpi_sum(chi0_head, gwr%comm%value, ierr)
8335 : 0 : call xmpi_sum(chi0_lwing, gwr%comm%value, ierr)
8336 : 0 : call xmpi_sum(chi0_uwing, gwr%comm%value, ierr)
8337 : :
8338 [ # # # # : 0 : chi0_head = chi0_head * weight / cryst%ucvol
# # ]
8339 : : ! Tensor in terms of reciprocal lattice vectors.
8340 [ # # ]: 0 : do io=1,nomega
8341 [ # # # # : 0 : chi0_head(:,:,io) = matmul(chi0_head(:,:,io), cryst%gmet) * (two_pi**2)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
8342 : : end do
8343 [ # # # # : 0 : chi0_lwing = chi0_lwing * weight / cryst%ucvol
# # ]
8344 [ # # # # : 0 : chi0_uwing = chi0_uwing * weight / cryst%ucvol
# # ]
8345 : :
8346 : : ! ===============================================
8347 : : ! ==== Symmetrize chi0 in case of AFM system ====
8348 : : ! ===============================================
8349 : : ! Reconstruct $chi0{\down,\down}$ from $chi0{\up,\up}$.
8350 : : ! Works only in the case of magnetic group Shubnikov type IV.
8351 [ # # ]: 0 : if (cryst%use_antiferro) then
8352 : : call symmetrize_afm_chi0(Cryst, gsph, ltg_q, npwe, nomega, &
8353 : 0 : chi0_head=chi0_head, chi0_lwing=chi0_lwing, chi0_uwing=chi0_uwing)
8354 : : end if
8355 : :
8356 [ # # # # ]: 0 : if (gwr%comm%me == 0 .and. gwr%dtset%prtvol >= 1) then
8357 : : ! Construct head and wings from the tensor and output results.
8358 : 0 : qlen = tol3
8359 : 0 : call cryst%get_redcart_qdirs(nq, qdirs, qlen=qlen)
8360 [ # # # # : 0 : ABI_MALLOC(head_qvals, (nq))
# # # # #
# # # ]
8361 : 0 : call wrtout(units, " Head of the irreducible polarizability for q --> 0", pre_newlines=1)
8362 : 0 : call wrtout(units, sjoin(" q0_len:", ftoa(qlen), "(Bohr^-1)"))
8363 : 0 : write(msg, "(*(a14))") "iomega (eV)", "[100]", "[010]", "[001]", "x", "y", "z"
8364 : 0 : call wrtout(units, msg)
8365 [ # # ]: 0 : do io=1,nomega
8366 [ # # ]: 0 : do iq=1,nq
8367 [ # # # # : 0 : chq = matmul(chi0_head(:,:,io), qdirs(:,iq))
# # # # #
# # # ]
8368 : 0 : head_qvals(iq) = vdotw(qdirs(:, iq), chq, cryst%gmet, "G")
8369 : : end do
8370 [ # # ]: 0 : write(msg, "(*(es12.5,2x))") gwr%iw_mesh(io) * Ha_eV, real(head_qvals(:))
8371 : 0 : call wrtout(units, msg)
8372 : : ! Write imag part to std_out only
8373 [ # # ]: 0 : write(msg, "(*(es12.5,2x))") gwr%iw_mesh(io) * Ha_eV, aimag(head_qvals(:))
8374 : 0 : call wrtout(std_out, msg)
8375 : : end do
8376 : 0 : call wrtout(units, " ")
8377 [ # # ]: 0 : ABI_FREE(qdirs)
8378 [ # # ]: 0 : ABI_FREE(head_qvals)
8379 : : end if
8380 : :
8381 : : ! Save quantities for later use as this routine must be called before build_tchi.
8382 [ # # ]: 0 : if (gwr%kpt_comm%me == 0) then
8383 [ # # # # : 0 : ABI_REMALLOC(gwr%chi0_head_myw, (3, 3, gwr%my_ntau) )
# # # # #
# # # # #
# # ]
8384 [ # # # # : 0 : ABI_REMALLOC(gwr%chi0_uwing_myw, (3, npwe, gwr%my_ntau) )
# # # # #
# # # # #
# # # # #
# ]
8385 [ # # # # : 0 : ABI_REMALLOC(gwr%chi0_lwing_myw, (3, npwe, gwr%my_ntau) )
# # # # #
# # # # #
# # # # #
# ]
8386 : :
8387 [ # # ]: 0 : do my_it=1,gwr%my_ntau
8388 : 0 : itau = gwr%my_itaus(my_it)
8389 [ # # # # ]: 0 : gwr%chi0_head_myw(:,:,my_it) = chi0_head(:,:,itau)
8390 [ # # ]: 0 : do ii=1,3
8391 [ # # ]: 0 : gwr%chi0_uwing_myw(ii,:,my_it) = chi0_uwing(:,itau,ii)
8392 [ # # ]: 0 : gwr%chi0_lwing_myw(ii,:,my_it) = chi0_lwing(:,itau,ii)
8393 : : end do
8394 : : end do
8395 : : end if
8396 : :
8397 [ # # ]: 0 : ABI_FREE(chi0_lwing)
8398 [ # # ]: 0 : ABI_FREE(chi0_uwing)
8399 [ # # ]: 0 : ABI_FREE(chi0_head)
8400 : 0 : call ltg_q%free()
8401 : 0 : call gsph%free()
8402 : :
8403 : 0 : call cwtime_report(" gwr_build_chi0_head_and_wings:", cpu_all, wall_all, gflops_all)
8404 : 0 : call timab(1927, 2, tsec)
8405 : :
8406 : : !if (use_ddk) stop "gwr_build_chi0_head_and_wings"
8407 : :
8408 [ # # # # : 0 : end subroutine gwr_build_chi0_head_and_wings
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
8409 : : !!***
8410 : :
8411 : : !----------------------------------------------------------------------
8412 : :
8413 : : !!****f* m_gwr/gwr_build_sigxme
8414 : : !! NAME
8415 : : !! gwr_build_sigxme
8416 : : !!
8417 : : !! FUNCTION
8418 : : !! Compute matrix elements of the exchange part.
8419 : : !!
8420 : : !! INPUTS
8421 : : !!
8422 : : !! OUTPUT
8423 : : !!
8424 : : !! SOURCE
8425 : :
8426 : 0 : subroutine gwr_build_sigxme(gwr, compute_qp)
8427 : :
8428 : : !Arguments ------------------------------------
8429 : : class(gwr_t),target,intent(inout) :: gwr
8430 : : logical,optional,intent(in) :: compute_qp
8431 : :
8432 : : !Local variables-------------------------------
8433 : : !scalars
8434 : : integer :: nsppol, nspinor, ierr, my_ikf, band_sum, ii, jj, kb, il_b, iab !ig_start, ig,
8435 : : integer :: my_is, ikcalc, ikcalc_ibz, bmin, bmax, band, istwf_k, npw_k
8436 : : integer :: spin, jb, is_idx, use_umklp, spad, wtqm, wtqp, irow, spadx1, spadx2, npwx, u_nfft, u_mgfft, u_mpw
8437 : : integer :: ik_bz, ik_ibz, isym_k, trev_k, g0_k(3)
8438 : : integer :: iq_bz, iq_ibz, isym_q, trev_q, g0_q(3)
8439 : : logical :: isirr_k, isirr_q, sigc_is_herm, compute_qp__
8440 : : real(dp) :: fact_spin, theta_mu_minus_esum, theta_mu_minus_esum2, tol_empty, tol_empty_in, gwr_boxcutmin_x, i_sz
8441 : : real(dp) :: cpu_k, wall_k, gflops_k, cpu_all, wall_all, gflops_all
8442 : : complex(gwp) :: gwpc_sigxme, gwpc_sigxme2, xdot_tmp, ctmp
8443 : : character(len=5000) :: msg
8444 : : logical :: q_is_gamma
8445 : : type(__slkmat_t),pointer :: ugb_kibz
8446 : : type(crystal_t),pointer :: cryst
8447 : : type(dataset_type),pointer :: dtset
8448 : 0 : type(littlegroup_t) :: ltg_k
8449 : : type(desc_t),pointer :: desc_ki
8450 : : !arrays
8451 : : integer :: g0(3), gmax(3), spinor_padx(2,4), u_ngfft(18), work_ngfft(18), units(2)
8452 : 0 : integer,allocatable :: gbound_kcalc(:,:), gvec_x(:,:), gbound_x(:,:), kg_k(:,:), gbound_ksum(:,:)
8453 : : real(dp) :: ksum(3), kk_ibz(3), kgw(3), kgw_m_ksum(3), qq_bz(3), tsec(2) !, kk_bz(3), q0(3) !, spinrot_kbz(4), spinrot_kgw(4)
8454 : 0 : real(dp),contiguous, pointer :: ks_eig(:,:,:), qp_eig(:,:,:), qp_occ(:,:,:), cg2_ptr(:,:) ! cg1_ptr(:,:),
8455 : 0 : real(dp),allocatable :: work(:,:,:,:), cg1_ibz(:,:) !, cg2_bz(:,:)
8456 : 0 : complex(gwp),allocatable :: vc_sqrt_qbz(:), ur_bdgw(:,:)
8457 : 0 : complex(gwp),allocatable :: rhotwg(:), rhotwgp(:), rhotwg_ki(:,:), ur_ksum(:), ur_prod(:), eig0r(:)!, ugb_kcalcibz(:)
8458 : 0 : complex(gwp),allocatable :: ug_ksum(:)
8459 : 0 : complex(dp),target,allocatable :: ug_ksum_dp(:)
8460 : 0 : complex(dp),allocatable :: sigxme_tmp(:,:,:), sigx(:,:,:,:)
8461 : 0 : type(sigijtab_t),allocatable :: Sigxij_tab(:,:), Sigcij_tab(:,:)
8462 : : type(yamldoc_t) :: ydoc
8463 : : ! *************************************************************************
8464 : :
8465 : 0 : call timab(1920, 1, tsec)
8466 : 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
8467 : :
8468 [ # # ]: 0 : units = [std_out, ab_out]
8469 [ # # ]: 0 : if (gwr%sig_diago) then
8470 : 0 : call wrtout(units, " Computing diagonal matrix elements of Sigma_x", pre_newlines=1)
8471 : : else
8472 : 0 : call wrtout(units, " Computing diagonal + off-diagonal matrix elements of Sigma_x", pre_newlines=1)
8473 : : end if
8474 : :
8475 [ # # ]: 0 : if (gwr%scf_iteration /= 1) then
8476 : : associate (now => gwr%qp_ebands, prev => gwr%qp_ebands_prev)
8477 [ # # # # : 0 : if (all(now%occ == prev%occ)) then
# # # # #
# ]
8478 : 0 : call wrtout(units, " Occupations have not changed since last iteration, skipping Sigma_x matrix elements computation...", pre_newlines=1)
8479 : : else
8480 : 0 : call wrtout(units, " Occupations have changed since last iteration, recomputing Sigma_x matrix elements...", pre_newlines=1)
8481 : : end if
8482 : : end associate
8483 : : goto 10
8484 : : end if
8485 : :
8486 [ # # ]: 0 : if (gwr%has_vcgen_sigma) then
8487 : 0 : call gwr%vcgen_sigma%print(units, " Info on Coulomb term used in Sigma_x", gwr%dtset%prtvol)
8488 : : else
8489 : 0 : call gwr%vcgen_eps%print(units, " Info on Coulomb term used in Sigma_x", dtset%prtvol)
8490 : : end if
8491 : :
8492 : 0 : nsppol = gwr%nsppol; nspinor = gwr%nspinor; cryst => gwr%cryst; dtset => gwr%dtset
8493 : :
8494 : : ! Table for \Sigmax_ij matrix elements.
8495 : 0 : sigc_is_herm = .False.
8496 : : call sigtk_sigma_tables(gwr%nkcalc, gwr%nkibz, gwr%nsppol, gwr%bstart_ks, gwr%bstop_ks, gwr%kcalc2ibz(:,1), &
8497 : 0 : gwr%sig_diago, sigc_is_herm, sigxij_tab, sigcij_tab)
8498 : :
8499 : 0 : call sigijtab_free(Sigcij_tab)
8500 [ # # # # : 0 : ABI_FREE(Sigcij_tab)
# # # # #
# # # ]
8501 : :
8502 : : ! Allocate array with Sigma_x matrix elements depending on sig_diago
8503 : 0 : ii = gwr%b1gw; jj = gwr%b2gw
8504 [ # # ]: 0 : if (gwr%sig_diago) then
8505 : 0 : ii = 1; jj = 1
8506 : : end if
8507 [ # # # # : 0 : ABI_RECALLOC(gwr%sigx_mat, (gwr%b1gw:gwr%b2gw, ii:jj, gwr%nkcalc, gwr%nsppol*gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
8508 : :
8509 : 0 : ks_eig => gwr%ks_ebands%eig
8510 [ # # ]: 0 : if (gwr%scf_iteration == 1) then
8511 : 0 : call wrtout(units, " Using KS orbitals and KS energies...", newlines=1, do_flush=.True.)
8512 : 0 : qp_eig => gwr%ks_ebands%eig; qp_occ => gwr%ks_ebands%occ
8513 : : else
8514 : 0 : call wrtout(units, " Using KS orbitals and QP energies...", newlines=1, do_flush=.True.)
8515 : 0 : qp_eig => gwr%qp_ebands%eig; qp_occ => gwr%qp_ebands%occ
8516 : : end if
8517 : :
8518 : : ! Set tolerance used to decide if a band is empty
8519 : 0 : tol_empty_in = 0.01
8520 : 0 : call get_fact_spin_tol_empty(nsppol, nspinor, tol_empty_in, fact_spin, tol_empty)
8521 : :
8522 : : ! =========================================
8523 : : ! Find FFT mesh and max number of g-vectors
8524 : : ! =========================================
8525 : 0 : gwr_boxcutmin_x = two
8526 : 0 : call gwr%get_u_ngfft(gwr_boxcutmin_x, u_ngfft, u_nfft, u_mgfft, u_mpw, gmax)
8527 : :
8528 [ # # # # ]: 0 : if (gwr%comm%me == 0) call print_ngfft([std_out], u_ngfft, header="FFT mesh for Sigma_x")
8529 : :
8530 : : ! Init work_ngfft
8531 [ # # ]: 0 : gmax = gmax + 4 ! FIXME: this is to account for umklapp, should also consider Gamma-only and istwfk
8532 [ # # ]: 0 : gmax = 2 * gmax + 1
8533 : 0 : call ngfft_seq(work_ngfft, gmax)
8534 : : !write(std_out,*)"work_ngfft(1:3): ",work_ngfft(1:3)
8535 [ # # # # : 0 : ABI_MALLOC(work, (2, work_ngfft(4), work_ngfft(5), work_ngfft(6)))
# # # # #
# # # # #
# # # # #
# ]
8536 : :
8537 [ # # ]: 0 : do my_is=1,gwr%my_nspins
8538 : 0 : spin = gwr%my_spins(my_is)
8539 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc ! TODO: Should be spin dependent!
8540 : 0 : call cwtime(cpu_k, wall_k, gflops_k, "start")
8541 : 0 : ikcalc_ibz = gwr%kcalc2ibz(ikcalc, 1)
8542 [ # # ]: 0 : kgw = gwr%kcalc(:, ikcalc)
8543 : 0 : bmin = gwr%bstart_ks(ikcalc, spin); bmax = gwr%bstop_ks(ikcalc, spin)
8544 : :
8545 : : ! ==============================================================
8546 : : ! ==== Find little group of the k-points for GW corrections ====
8547 : : ! ==============================================================
8548 : : ! * The little group is used only if symsigma == 1
8549 : : ! * If use_umklp == 1 then symmetries requiring an umklapp to preserve k_gw are included as well.
8550 : 0 : use_umklp = 1
8551 : 0 : call ltg_k%init(kgw, gwr%nqbz, gwr%qbz, cryst, use_umklp, npwe=0)
8552 : : !if (gwr%comm%me == 0) call ltg_k%print([std_out], prtvol=gwr%dtset%prtvol)
8553 : :
8554 : 0 : write(msg,'(5a)') ch10, &
8555 [ # # # # : 0 : ' Calculating <nk|Sigma_x|nk> at k: ',trim(ktoa(kgw)), ", for band range: ", trim(ltoa([bmin, bmax]))
# # ]
8556 : 0 : call wrtout(std_out, msg)
8557 : :
8558 : : ! ===============================================
8559 : : ! Load wavefunctions for Sigma_x matrix elements
8560 : : ! ===============================================
8561 : : ! All procs need ur_bdgw but the IBZ is distributed and, possibly, replicated in gwr%kpt_comm.
8562 : : ! Here we select the right procs, fill the buffer with the FFT results and then use
8563 : : ! a dumb xmpi_sum + rescaling to gather the results.
8564 : : ! FIXME: g-vectors from Green's descriptor or use another array to be able to deal with istwfk == 2?
8565 : :
8566 [ # # # # : 0 : ABI_MALLOC_OR_DIE(ur_bdgw, (u_nfft * nspinor, bmin:bmax), ierr)
# # # # #
# # # # #
# # # # #
# # # ]
8567 [ # # # # ]: 0 : ur_bdgw = czero_gw
8568 : :
8569 [ # # # # : 0 : if (any(ikcalc_ibz == gwr%my_kibz_inds)) then
# # ]
8570 : : associate (desc_kcalc => gwr%green_desc_kibz(ikcalc_ibz), ugb_kcalc => gwr%ugb(ikcalc_ibz, spin))
8571 [ # # # # : 0 : ABI_MALLOC(gbound_kcalc, (2 * u_mgfft + 8, 2))
# # # # #
# # # #
# ]
8572 : 0 : call sphereboundary(gbound_kcalc, desc_kcalc%istwfk, desc_kcalc%gvec, u_mgfft, desc_kcalc%npw)
8573 : :
8574 [ # # ]: 0 : do il_b=1,ugb_kcalc%size_local(2)
8575 [ # # ]: 0 : band = ugb_kcalc%loc2gcol(il_b); if (band < bmin .or. band > bmax) CYCLE
8576 : : call fft_ug(desc_kcalc%npw, u_nfft, nspinor, ndat1, &
8577 : : u_mgfft, u_ngfft, desc_kcalc%istwfk, desc_kcalc%gvec, gbound_kcalc, &
8578 : : gwr%ugb(ikcalc_ibz, spin)%buffer_cplx(:, il_b), & ! in
8579 : 0 : ur_bdgw(:, band)) ! out
8580 : : end do
8581 [ # # # # ]: 0 : ABI_FREE(gbound_kcalc)
8582 : : end associate
8583 : : end if
8584 : :
8585 : : ! Collect and rescale
8586 : : !call xmpi_sum(ur_bdgw, gwr%kgt_comm%value, ierr)
8587 : 0 : call xmpi_sum(ur_bdgw, gwr%kg_comm%value, ierr)
8588 [ # # # # ]: 0 : ur_bdgw = ur_bdgw / gwr%np_kibz(ikcalc_ibz)
8589 : :
8590 [ # # # # : 0 : ABI_MALLOC(ur_prod, (u_nfft * nspinor))
# # # # #
# # # ]
8591 [ # # # # : 0 : ABI_MALLOC(ur_ksum, (u_nfft * nspinor))
# # # # ]
8592 [ # # # # : 0 : ABI_MALLOC(eig0r, (u_nfft * nspinor))
# # # # ]
8593 : :
8594 [ # # # # : 0 : ABI_CALLOC(sigxme_tmp, (bmin:bmax, bmin:bmax, nsppol * gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
8595 [ # # # # : 0 : ABI_CALLOC(sigx, (2, bmin:bmax, bmin:bmax, nsppol * gwr%nsig_ab))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
8596 : :
8597 : : ! ========================================
8598 : : ! ==== Sum over my k-points in the BZ ====
8599 : : ! ========================================
8600 : :
8601 [ # # ]: 0 : do my_ikf=1,gwr%my_nkbz
8602 : 0 : ik_bz = gwr%my_kbz_inds(my_ikf)
8603 [ # # ]: 0 : ksum = gwr%kbz(:, ik_bz)
8604 : :
8605 : : ! Find the symmetrical image of ksum in the IBZ
8606 : : ! FIXME: Be careful with the symmetry conventions here and the interplay between umklapp in q and FFT
8607 : 0 : ik_ibz = gwr%kbz2ibz_symrel(1, ik_bz); isym_k = gwr%kbz2ibz_symrel(2, ik_bz)
8608 [ # # ]: 0 : trev_k = gwr%kbz2ibz_symrel(6, ik_bz); g0_k = gwr%kbz2ibz_symrel(3:5, ik_bz)
8609 [ # # # # : 0 : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
# # # # ]
8610 [ # # ]: 0 : kk_ibz = gwr%kibz(:, ik_ibz)
8611 : :
8612 : : ! Identify q and G0 where q + G0 = k_GW - ksum
8613 [ # # ]: 0 : kgw_m_ksum = kgw - ksum
8614 : 0 : call findqg0(iq_bz, g0, kgw_m_ksum, gwr%nqbz, gwr%qbz, gwr%mG0)
8615 : : !ABI_CHECK(all(g0 == 0), sjoin("g0 = ", ltoa(g0)))
8616 : :
8617 : 0 : call calc_ceigr(g0, u_nfft, nspinor, u_ngfft, eig0r)
8618 : :
8619 : : ! If symmetries are exploited, only q-points in the IBZ_k are computed.
8620 : : ! In this case elements are weighted according to wtqp and wtqm. wtqm is for time-reversal.
8621 : 0 : wtqp = 1; wtqm = 0
8622 : : !if (can_symmetrize(spin)) then
8623 [ # # ]: 0 : if (gwr%dtset%symsigma == 1) then
8624 [ # # ]: 0 : if (ltg_k%ibzq(iq_bz) /= 1) CYCLE
8625 [ # # ]: 0 : wtqp = sum(ltg_k%wtksym(1,:,iq_bz))
8626 [ # # ]: 0 : wtqm = sum(ltg_k%wtksym(2,:,iq_bz))
8627 : : end if
8628 : :
8629 [ # # ]: 0 : qq_bz = gwr%qbz(:, iq_bz)
8630 : 0 : iq_ibz = gwr%qbz2ibz(1, iq_bz); isym_q = gwr%qbz2ibz(2, iq_bz)
8631 : 0 : trev_q = gwr%qbz2ibz(6, iq_bz); g0_q = gwr%qbz2ibz(3:5, iq_bz)
8632 : : isirr_q = (isym_q == 1 .and. trev_q == 0 .and. all(g0_q == 0))
8633 : :
8634 : : ! Find the corresponding irreducible q-point.
8635 : : ! NB: non-zero umklapp G_o is not allowed. There's a check in setup_sigma
8636 : : !call qmesh%get_BZ_item(iq_bz, qbz, iq_ibz, isym_q, itim_q)
8637 : 0 : q_is_gamma = normv(qq_bz, cryst%gmet, "G") < GW_TOLQ0
8638 [ # # ]: 0 : call get_kg(qq_bz, istwfk1, dtset%ecutsigx, cryst%gmet, npwx, gvec_x)
8639 : :
8640 [ # # # # : 0 : ABI_MALLOC(gbound_x, (2*u_mgfft + 8, 2))
# # # # #
# # # # #
# # ]
8641 : 0 : call sphereboundary(gbound_x, istwfk1, gvec_x, u_mgfft, npwx)
8642 : :
8643 [ # # # # : 0 : ABI_MALLOC(rhotwg_ki, (npwx * nspinor, bmin:bmax))
# # # # #
# # # # #
# # ]
8644 [ # # # # : 0 : ABI_MALLOC(rhotwg, (npwx * nspinor))
# # # # #
# # # ]
8645 [ # # # # : 0 : ABI_MALLOC(rhotwgp, (npwx * nspinor))
# # # # ]
8646 [ # # # # : 0 : ABI_MALLOC(vc_sqrt_qbz, (npwx))
# # # # #
# # # ]
8647 [ # # ]: 0 : spinor_padx = reshape([0, 0, npwx, npwx, 0, npwx, npwx, 0], [2, 4])
8648 : :
8649 : : ! Get Fourier components of the Coulomb interaction in the BZ
8650 : : ! In 3D systems, neglecting umklapp, vc(Sq,sG)=vc(q,G)=4pi/|q+G|
8651 : : ! The same relation holds for 0-D systems, but not in 1-D or 2D systems. It depends on S.
8652 [ # # ]: 0 : if (gwr%has_vcgen_sigma) then
8653 : 0 : call gwr%vcgen_sigma%get_vc_sqrt(qq_bz, npwx, gvec_x, gwr%q0, gwr%cryst, vc_sqrt_qbz, gwr%gtau_comm%value)
8654 : : else
8655 : 0 : call gwr%vcgen_eps%get_vc_sqrt(qq_bz, npwx, gvec_x, gwr%q0, gwr%cryst, vc_sqrt_qbz, gwr%gtau_comm%value)
8656 : : end if
8657 : :
8658 : 0 : desc_ki => gwr%green_desc_kibz(ik_ibz)
8659 : :
8660 : : ! Get npw_k and kg_k for this k.
8661 [ # # ]: 0 : if (isirr_k) then
8662 : 0 : istwf_k = desc_ki%istwfk; npw_k = desc_ki%npw
8663 [ # # # # : 0 : ABI_MALLOC(kg_k, (3, npw_k))
# # # # #
# # # #
# ]
8664 [ # # # # ]: 0 : kg_k(:,:) = desc_ki%gvec
8665 : : else
8666 : 0 : istwf_k = 1
8667 [ # # ]: 0 : call get_kg(ksum, istwf_k, dtset%ecutwfn, cryst%gmet, npw_k, kg_k)
8668 : : end if
8669 : :
8670 [ # # # # : 0 : ABI_MALLOC(ug_ksum, (npw_k * nspinor))
# # # # #
# # # ]
8671 [ # # # # : 0 : ABI_MALLOC(ug_ksum_dp, (npw_k * nspinor))
# # # # ]
8672 : : !ABI_MALLOC(ugb_kcalcibz, (npw_k * nspinor))
8673 [ # # # # : 0 : ABI_MALLOC(cg1_ibz, (2, desc_ki%npw * nspinor))
# # # # #
# # # ]
8674 : : !ABI_MALLOC(cg2_bz, (2, npw_k * nspinor))
8675 : :
8676 [ # # # # : 0 : ABI_MALLOC(gbound_ksum, (2*u_mgfft+8, 2))
# # # # ]
8677 : 0 : call sphereboundary(gbound_ksum, istwf_k, kg_k, u_mgfft, npw_k)
8678 : :
8679 : : ! ==========================
8680 : : ! Sum over (occupied) bands
8681 : : ! ==========================
8682 : 0 : ugb_kibz => gwr%ugb(ik_ibz, spin)
8683 : :
8684 [ # # ]: 0 : do il_b=1,ugb_kibz%size_local(2)
8685 : : ! Distribute bands inside tau_comm as wavefunctions are replicated
8686 [ # # ]: 0 : if (gwr%tau_comm%skip(il_b)) cycle
8687 : 0 : band_sum = ugb_kibz%loc2gcol(il_b)
8688 : :
8689 : : ! Skip empty states. MRM: allow negative occ numbers.
8690 [ # # ]: 0 : if (abs(qp_occ(band_sum, ik_ibz, spin)) < tol_empty) CYCLE
8691 : :
8692 : : ! Compute ur_ksum(r) from the symmetrical image.
8693 : : ! I should rotate the g-vectors outside the loop and rotate ug here
8694 : : ! but at present I cannot use cgtk_rotate due to the symrel^T convention.
8695 : :
8696 [ # # ]: 0 : if (isirr_k) then
8697 : : !call wfd%copy_cg(ibsum_kq, ikq_ibz, spin, bra_kq)
8698 [ # # ]: 0 : ug_ksum(:) = ugb_kibz%buffer_cplx(:, il_b)
8699 : : else
8700 : : ! Reconstruct u_kq(G) from the IBZ image.
8701 : :
8702 : : ! FIXME: This is wrong if spc
8703 : 0 : call c_f_pointer(c_loc(ug_ksum_dp), cg2_ptr, shape=[2, npw_k * nspinor])
8704 : :
8705 : : !call c_f_pointer(c_loc(ugb_kibz%buffer_cplx(:, il_b)), cg1_ptr, shape=[2, desc_ki%npw * nspinor])
8706 : : !call cgtk_rotate(cryst, kk_ibz, isym_k, trev_k, g0_k, nspinor, ndat1, &
8707 : : ! desc_ki%npw, desc_ki%gvec, &
8708 : : ! npw_k, kg_k, desc_ki%istwfk, istwf_k, cg1_ptr, cg2_ptr, work_ngfft, work)
8709 : :
8710 [ # # ]: 0 : cg1_ibz(1,:) = real(ugb_kibz%buffer_cplx(:, il_b), kind=dp)
8711 [ # # ]: 0 : cg1_ibz(2,:) = real(aimag(ugb_kibz%buffer_cplx(:, il_b)), kind=dp)
8712 : : call cgtk_rotate(cryst, kk_ibz, isym_k, trev_k, g0_k, nspinor, ndat1, &
8713 : : desc_ki%npw, desc_ki%gvec, &
8714 : 0 : npw_k, kg_k, desc_ki%istwfk, istwf_k, cg1_ibz, cg2_ptr, work_ngfft, work)
8715 [ # # ]: 0 : ug_ksum(:) = ug_ksum_dp(:)
8716 : : end if
8717 : :
8718 : 0 : call fft_ug(npw_k, u_nfft, nspinor, ndat1, u_mgfft, u_ngfft, istwf_k, kg_k, gbound_ksum, ug_ksum, ur_ksum)
8719 : :
8720 [ # # # # : 0 : if (any(g0 /= 0)) ur_ksum = ur_ksum * conjg(eig0r)
# # # # #
# ]
8721 : :
8722 : : ! Get all <k-q,band_sum,s|e^{-i(q+G).r}|s,jb,k>
8723 [ # # ]: 0 : do jb=bmin,bmax
8724 : :
8725 : : ! FIXME: nspinor 2 is wrong as we have a 2x2 matrix
8726 [ # # ]: 0 : ur_prod(:) = conjg(ur_ksum(:)) * ur_bdgw(:,jb)
8727 : 0 : call fft_ur(npwx, u_nfft, nspinor, ndat1, u_mgfft, u_ngfft, istwfk1, gvec_x, gbound_x, ur_prod, rhotwg_ki(:,jb))
8728 : :
8729 : : ! Multiply by the square root of the Coulomb term
8730 : : ! In 3-D systems, the factor sqrt(4pi) is included
8731 [ # # ]: 0 : do ii=1,nspinor
8732 : 0 : spad = (ii-1) * npwx
8733 [ # # ]: 0 : rhotwg_ki(spad+1:spad+npwx,jb) = rhotwg_ki(spad+1:spad + npwx,jb) * vc_sqrt_qbz(1:npwx)
8734 : : end do
8735 : :
8736 [ # # ]: 0 : if (q_is_gamma) then
8737 : : !if (ik_bz == jk_bz) then
8738 : : ! Treat analytically the case q --> 0:
8739 : : !
8740 : : ! * The oscillator is evaluated at q = 0 as it is considered constant in the small cube around Gamma
8741 : : ! while the Colulomb term is integrated out.
8742 : : ! * If nspinor == 1, we have nonzero contribution only if band_sum == jb
8743 : : ! * If nspinor == 2, we evaluate <band_sum,up|jb,up> and <band_sum,dwn|jb,dwn>,
8744 : : ! and impose orthonormalization since npwwfn might be < npwvec.
8745 : : ! * Note the use of i_sz_resid and not i_sz, to account for the possibility
8746 : : ! to have generalized KS basis set from hybrid
8747 : :
8748 : 0 : i_sz = gwr%vcgen_eps%i_sz
8749 [ # # ]: 0 : if (gwr%has_vcgen_sigma) i_sz = gwr%vcgen_sigma%i_sz
8750 : :
8751 [ # # ]: 0 : if (nspinor == 1) then
8752 : 0 : rhotwg_ki(1, jb) = czero_gw
8753 [ # # ]: 0 : if (band_sum == jb) rhotwg_ki(1,jb) = cmplx(sqrt(i_sz), 0.0_gwp)
8754 : : !rhotwg_ki(1,jb) = czero_gw ! DEBUG
8755 : :
8756 : : else
8757 : 0 : rhotwg_ki(1, jb) = zero; rhotwg_ki(npwx+1, jb) = zero
8758 [ # # ]: 0 : if (band_sum == jb) then
8759 : : associate(ugb_kcalcibz => gwr%ugb(ikcalc_ibz, spin)%buffer_cplx(:,il_b))
8760 : 0 : ABI_CHECK(size(ug_ksum) == size(ugb_kcalcibz), "Size mismatch in Sigma_x")
8761 : 0 : ctmp = xdotc(npw_k, ug_ksum(1:), 1, ugb_kcalcibz(1:), 1)
8762 : 0 : rhotwg_ki(1, jb) = cmplx(sqrt(i_sz), 0.0_gwp) * real(ctmp)
8763 : 0 : ctmp = xdotc(npw_k, ug_ksum(npw_k+1:), 1, ugb_kcalcibz(npw_k+1:), 1)
8764 [ # # ]: 0 : rhotwg_ki(npwx+1, jb) = cmplx(sqrt(i_sz), 0.0_gwp) * real(ctmp)
8765 : : end associate
8766 : : end if
8767 : : !!!rhotwg_ki(1, jb) = zero; rhotwg_ki(npwx+1, jb) = zero
8768 : : !!! PAW is missing
8769 : : end if
8770 : : end if
8771 : :
8772 : : end do ! jb Got all matrix elements from bmin up to bmax.
8773 : :
8774 : 0 : theta_mu_minus_esum = fact_spin * qp_occ(band_sum, ik_ibz, spin)
8775 : : theta_mu_minus_esum2 = sqrt(abs(fact_spin * qp_occ(band_sum, ik_ibz, spin))) ! MBB Nat. orb. funct. approx. sqrt(occ)
8776 : :
8777 [ # # ]: 0 : if (abs(theta_mu_minus_esum / fact_spin) >= tol_empty) then ! MRM: allow negative occ numbers
8778 [ # # ]: 0 : do kb=bmin,bmax
8779 : :
8780 : : ! Copy the ket Sigma_x |phi_{k,kb}>.
8781 [ # # ]: 0 : rhotwgp(:) = rhotwg_ki(:, kb)
8782 : :
8783 : : ! Loop over the non-zero row elements of this column.
8784 : : ! If gwcalctyp < 20: only diagonal elements since QP == KS.
8785 : : ! If gwcalctyp >= 20:
8786 : : ! * Only off-diagonal elements connecting states with same character.
8787 : : ! * Only the upper triangle if HF, SEX, or COHSEX.
8788 : :
8789 [ # # ]: 0 : do irow=1,Sigxij_tab(ikcalc, spin)%col(kb)%size1
8790 : 0 : jb = Sigxij_tab(ikcalc, spin)%col(kb)%bidx(irow)
8791 [ # # ]: 0 : rhotwg(:) = rhotwg_ki(:,jb)
8792 : :
8793 : : ! Calculate bare exchange <phi_jb|Sigma_x|phi_kb>.
8794 : : ! Do the scalar product only if band_sum is occupied.
8795 [ # # ]: 0 : do iab=1,gwr%nsig_ab
8796 : 0 : spadx1 = spinor_padx(1, iab); spadx2 = spinor_padx(2, iab)
8797 : 0 : xdot_tmp = -XDOTC(npwx, rhotwg(spadx1+1:), 1, rhotwgp(spadx2+1:), 1)
8798 : 0 : gwpc_sigxme = xdot_tmp * theta_mu_minus_esum
8799 : 0 : gwpc_sigxme2 = xdot_tmp * theta_mu_minus_esum2
8800 : :
8801 : : ! Accumulate and symmetrize Sigma_x matrix elements.
8802 : : ! -wtqm comes from time-reversal (exchange of band indices)
8803 [ # # ]: 0 : is_idx = spin; if (nspinor == 2) is_idx = iab
8804 : : sigxme_tmp(jb, kb, is_idx) = sigxme_tmp(jb, kb, is_idx) + &
8805 : 0 : (wtqp + wtqm) * DBLE(gwpc_sigxme) + (wtqp - wtqm) * j_dpc * AIMAG(gwpc_sigxme)
8806 : :
8807 : 0 : sigx(1, jb, kb, is_idx) = sigx(1, jb, kb, is_idx) + wtqp * gwpc_sigxme
8808 : 0 : sigx(2, jb, kb, is_idx) = sigx(2, jb, kb, is_idx) + wtqm *CONJG(gwpc_sigxme)
8809 : : end do
8810 : : end do ! irow
8811 : :
8812 : : end do ! kb
8813 : : end if
8814 : : end do ! band_sum
8815 : :
8816 [ # # ]: 0 : ABI_FREE(gbound_x)
8817 [ # # ]: 0 : ABI_FREE(kg_k)
8818 [ # # ]: 0 : ABI_FREE(ug_ksum)
8819 [ # # ]: 0 : ABI_FREE(ug_ksum_dp)
8820 : : !ABI_FREE(ugb_kcalcibz)
8821 [ # # ]: 0 : ABI_FREE(cg1_ibz)
8822 : : !ABI_FREE(cg2_bz)
8823 [ # # ]: 0 : ABI_FREE(gbound_ksum)
8824 [ # # ]: 0 : ABI_FREE(gvec_x)
8825 [ # # ]: 0 : ABI_FREE(rhotwg_ki)
8826 [ # # ]: 0 : ABI_FREE(rhotwg)
8827 [ # # ]: 0 : ABI_FREE(rhotwgp)
8828 [ # # ]: 0 : ABI_FREE(vc_sqrt_qbz)
8829 : : end do ! my_ikf Got all diagonal (off-diagonal) matrix elements.
8830 : :
8831 : : ! Gather contributions from all the CPUs.
8832 : 0 : call xmpi_sum(sigxme_tmp, gwr%kgt_comm%value, ierr)
8833 : 0 : call xmpi_sum(sigx, gwr%kgt_comm%value, ierr)
8834 : :
8835 : : ! Multiply by constants. For 3D systems sqrt(4pi) is included in vc_sqrt_qbz.
8836 [ # # # # : 0 : sigxme_tmp = (one / (cryst%ucvol * gwr%nkbz)) * sigxme_tmp ! * Sigp%sigma_mixing
# # ]
8837 [ # # # # : 0 : sigx = (one / (cryst%ucvol * gwr%nkbz)) * sigx ! * Sigp%sigma_mixing
# # # # ]
8838 : :
8839 : : ! If we have summed over the IBZ_q, we have to average over degenerate states.
8840 : : ! Presently only diagonal terms are considered
8841 : : ! Note that here we pass ks_eig to sigx_symmetrize instead of qp_eig.
8842 : : ! The reason is that we use the eigenvalues to detect degeneracies before averaging
8843 : : ! and qp_eig may break degeneracies while ks_eig are much more accurate.
8844 : : ! Most of the breaking comes from the correlated part, likey due to the treatment of q --> 0.
8845 : :
8846 : : ! TODO QP-SCGW required a more involved approach, there is a check in sigma
8847 : : ! TODO it does not work if nspinor == 2.
8848 : :
8849 [ # # ]: 0 : if (gwr%dtset%symsigma == 1) then
8850 : 0 : call sigx_symmetrize(ikcalc_ibz, spin, bmin, bmax, nsppol, nspinor, gwr%nsig_ab, gwr%dtset%symsigma_de, ks_eig, sigx, sigxme_tmp)
8851 : : !do ii=bmin, bmax; print *, "qp_eig:", ii, qp_eig(ii, ikcalc_ibz, spin) * Ha_eV; end do
8852 : : !call sigx_symmetrize(ikcalc_ibz, spin, bmin, bmax, nsppol, nspinor, gwr%nsig_ab, gwr%dtset%symsigma_de, qp_eig, sigx, sigxme_tmp)
8853 : : end if
8854 : :
8855 : : ! Reconstruct the full sigma_x matrix from the upper triangle.
8856 [ # # ]: 0 : if (gwr%nsig_ab == 1) then
8857 : 0 : call hermitianize(sigxme_tmp(:,:,spin), "Upper")
8858 : : else
8859 : 0 : ABI_WARNING("Should hermitianize non-collinear sigma!")
8860 : : end if
8861 : :
8862 : : ! Save exchange matrix in gwr%sigx_mat taking into account sig_diago.
8863 [ # # ]: 0 : if (gwr%nsig_ab == 1) then
8864 [ # # ]: 0 : if (gwr%sig_diago) then
8865 [ # # ]: 0 : do jb=bmin,bmax
8866 : 0 : gwr%sigx_mat(jb, 1, ikcalc, spin) = sigxme_tmp(jb,jb,spin)
8867 : : end do
8868 : : else
8869 [ # # # # ]: 0 : gwr%sigx_mat(bmin:bmax, bmin:bmax, ikcalc, spin) = sigxme_tmp(bmin:bmax, bmin:bmax, spin)
8870 : : end if
8871 : : else
8872 [ # # ]: 0 : if (gwr%sig_diago) then
8873 [ # # ]: 0 : do iab=1,gwr%nsig_ab
8874 [ # # ]: 0 : do jb=bmin,bmax
8875 : 0 : gwr%sigx_mat(jb, 1, ikcalc, iab) = sigxme_tmp(jb,jb,iab)
8876 : : end do
8877 : : end do
8878 : : else
8879 [ # # # # : 0 : gwr%sigx_mat(bmin:bmax, bmin:bmax, ikcalc, :) = sigxme_tmp(bmin:bmax, bmin:bmax, :)
# # ]
8880 : : end if
8881 : : end if
8882 : :
8883 [ # # ]: 0 : ABI_FREE(ur_bdgw)
8884 [ # # ]: 0 : ABI_FREE(ur_prod)
8885 [ # # ]: 0 : ABI_FREE(ur_ksum)
8886 [ # # ]: 0 : ABI_FREE(eig0r)
8887 [ # # ]: 0 : ABI_FREE(sigxme_tmp)
8888 [ # # ]: 0 : ABI_FREE(sigx)
8889 : 0 : call ltg_k%free()
8890 : 0 : call cwtime_report(" Sigx_nk:", cpu_k, wall_k, gflops_k)
8891 : : end do ! ikcalc
8892 : : end do ! my_is
8893 : :
8894 [ # # ]: 0 : if (gwr%spin_comm%nproc > 1) call xmpi_sum(gwr%sigx_mat, gwr%spin_comm%value, ierr)
8895 [ # # # # : 0 : if (gwr%nspinor == 2) gwr%sigx_mat(:,:,:,1) = sum(gwr%sigx_mat(:,:,:,:), dim=4)
# # # # #
# # # # #
# # # # ]
8896 : :
8897 [ # # ]: 0 : ABI_FREE(work)
8898 : 0 : call sigijtab_free(Sigxij_tab)
8899 [ # # # # : 0 : ABI_FREE(Sigxij_tab)
# # # # #
# # # ]
8900 : :
8901 : : ! Compute QP results. Done usually when gwr_task == G0v i.e. Hartree-Fock with KS states.
8902 [ # # ]: 0 : compute_qp__ = .False.; if (present(compute_qp)) compute_qp__ = compute_qp
8903 [ # # # # ]: 0 : if (compute_qp__ .and. gwr%comm%me == 0) then
8904 : 0 : call write_notations(units)
8905 [ # # ]: 0 : do spin=1,gwr%nsppol
8906 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc
8907 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
8908 : 0 : ydoc = yamldoc_open('GWR_SelfEnergy_ee', width=11, real_fmt='(3f8.3)')
8909 : 0 : call ydoc%add_real1d('kpoint', gwr%kcalc(:, ikcalc))
8910 : 0 : call ydoc%add_int('spin', spin, int_fmt="(i1)")
8911 : 0 : call ydoc%add_int('gwr_scf_iteration', gwr%scf_iteration)
8912 : 0 : call ydoc%add_string('gwr_task', gwr%dtset%gwr_task)
8913 : :
8914 : : call ydoc%add_real('KS_gap', &
8915 : : (gwr%ks_ebands%eig(gwr%ks_vbik(ik_ibz, spin)+1, ik_ibz, spin) - &
8916 : 0 : gwr%ks_ebands%eig(gwr%ks_vbik(ik_ibz, spin), ik_ibz, spin)) * Ha_eV)
8917 : 0 : call ydoc%open_tabular('data') !, tag='SigmaeeData')
8918 : 0 : write(msg, "(a5, *(a9))") "Band", "E0", "SigX", "Occ(E)"
8919 : 0 : call ydoc%add_tabular_line(msg)
8920 : :
8921 [ # # ]: 0 : do band=gwr%bstart_ks(ikcalc, spin), gwr%bstop_ks(ikcalc, spin)
8922 : : write(msg,'(i5, *(f9.3))') &
8923 : 0 : band, & ! Band
8924 : 0 : gwr%ks_ebands%eig(band, ik_ibz, spin) * Ha_eV, & ! E0
8925 [ # # ]: 0 : real(gwr%sigx_mat(band, merge(1, band, gwr%sig_diago), ikcalc, spin), kind=dp) * Ha_eV, & ! SigX
8926 : 0 : gwr%qp_ebands%occ(band, ik_ibz, spin) ! Occ(E)
8927 : 0 : call ydoc%add_tabular_line(msg)
8928 : : end do
8929 : :
8930 [ # # ]: 0 : call ydoc%write_units_and_free([std_out, ab_out])
8931 : : end do ! ikcalc
8932 : : end do ! spin
8933 : : end if
8934 : :
8935 : : 10 continue
8936 : 0 : call cwtime_report(" gwr_build_sigxme:", cpu_all, wall_all, gflops_all)
8937 : 0 : call timab(1920, 2, tsec)
8938 : :
8939 [ # # # # : 0 : end subroutine gwr_build_sigxme
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
8940 : : !!***
8941 : :
8942 : : !----------------------------------------------------------------------
8943 : :
8944 : : !!****f* m_gwr/gwr_get_u_ngfft
8945 : : !! NAME
8946 : : !! gwr_get_u_ngfft
8947 : : !!
8948 : : !! FUNCTION
8949 : : !! Compute FFT mesh from boxcutmin.
8950 : : !!
8951 : : !! INPUTS
8952 : : !!
8953 : : !! OUTPUT
8954 : : !!
8955 : : !! SOURCE
8956 : :
8957 : 0 : subroutine gwr_get_u_ngfft(gwr, boxcutmin, u_ngfft, u_nfft, u_mgfft, u_mpw, gmax)
8958 : :
8959 : : !Arguments ------------------------------------
8960 : : class(gwr_t),intent(in) :: gwr
8961 : : real(dp),intent(in) :: boxcutmin
8962 : : integer,intent(out) :: u_ngfft(18), u_nfft, u_mgfft, u_mpw, gmax(3)
8963 : :
8964 : : !Local variables-------------------------------
8965 : : integer :: ik_bz, npw_, ig, ii
8966 : : real(dp) :: kk_bz(3)
8967 : 0 : integer,allocatable :: gvec_(:,:)
8968 : : ! *************************************************************************
8969 : :
8970 : : ! All MPI procs in gwr%comm execute this part.
8971 : : ! Note the loops over the full BZ to compute u_mpw
8972 : : ! FIXME: umklapp, ecutsigx and q-centered G-sphere
8973 : : ! TODO: Write new routine to compute best FFT mesh for ecut1 + ecut1. See set_mesh from GW code.
8974 : :
8975 [ # # ]: 0 : u_ngfft = gwr%dtset%ngfft ! This to allow users to specify fftalg
8976 : :
8977 : 0 : u_mpw = -1; gmax = 0
8978 [ # # ]: 0 : do ik_bz=1,gwr%nkbz
8979 [ # # ]: 0 : kk_bz = gwr%kbz(:, ik_bz)
8980 [ # # ]: 0 : call get_kg(kk_bz, istwfk1, gwr%dtset%ecutwfn, gwr%cryst%gmet, npw_, gvec_)
8981 : 0 : u_mpw = max(u_mpw, npw_)
8982 : : ! TODO: g0 umklapp here can enter into play gmax may not be large enough!
8983 [ # # ]: 0 : do ig=1,npw_
8984 [ # # ]: 0 : do ii=1,3
8985 : 0 : gmax(ii) = max(gmax(ii), abs(gvec_(ii, ig)))
8986 : : end do
8987 : : end do
8988 [ # # ]: 0 : ABI_FREE(gvec_)
8989 : : call getng(boxcutmin, gwr%dtset%chksymtnons, gwr%dtset%ecutwfn, gwr%cryst%gmet, &
8990 : : kk_bz, me_fft0, u_mgfft, u_nfft, u_ngfft, nproc_fft1, gwr%cryst%nsym, paral_fft0, &
8991 : 0 : gwr%cryst%symrel, gwr%cryst%tnons, gpu_option=gwr%dtset%gpu_option, unit=dev_null)
8992 : : end do
8993 : :
8994 [ # # ]: 0 : end subroutine gwr_get_u_ngfft
8995 : : !!***
8996 : :
8997 : : !----------------------------------------------------------------------
8998 : :
8999 : : !!****f* m_gwr/get_1d_sc_phases
9000 : : !! NAME
9001 : : !! get_1d_sc_phases
9002 : : !!
9003 : : !! FUNCTION
9004 : : !! Compute one-dimensional factors in the supercell.
9005 : : !!
9006 : : !! INPUTS
9007 : : !! sc_shape(3)=Supercell shape.
9008 : : !! nkpt=Number of k-points
9009 : : !! kpts(3,nkpt)=K-points in reduced coordinates.
9010 : : !!
9011 : : !! OUTPUT
9012 : : !! ph1d(maxval(sc_shape), 3, nkpt))
9013 : : !!
9014 : : !! SOURCE
9015 : :
9016 : 0 : subroutine get_1d_sc_phases(sc_shape, nkpt, kpts, ph1d)
9017 : :
9018 : : !Arguments ------------------------------------
9019 : : integer,intent(in) :: sc_shape(3), nkpt
9020 : : real(dp),intent(in) :: kpts(3, nkpt)
9021 : : complex(gwp),allocatable,intent(out) :: ph1d(:,:,:)
9022 : :
9023 : : !Local variables-------------------------------
9024 : : integer :: ikpt, ix, iy, iz
9025 : : real(dp) :: arg, fact, kk(3)
9026 : : ! *************************************************************************
9027 : :
9028 [ # # # # : 0 : ABI_MALLOC(ph1d, (maxval(sc_shape), 3, nkpt))
# # # # #
# # # # #
# # # # #
# ]
9029 : :
9030 [ # # ]: 0 : do ikpt=1,nkpt
9031 [ # # ]: 0 : kk = kpts(:, ikpt)
9032 : 0 : fact = two_pi * kk(1)
9033 [ # # ]: 0 : do ix=0,sc_shape(1) - 1
9034 : 0 : arg = fact * ix
9035 : 0 : ph1d(ix + 1, 1, ikpt) = cmplx(cos(arg), sin(arg), kind=gwp)
9036 : : end do
9037 : 0 : fact = two_pi * kk(2)
9038 [ # # ]: 0 : do iy=0,sc_shape(2) - 1
9039 : 0 : arg = fact * iy
9040 : 0 : ph1d(iy + 1, 2, ikpt) = cmplx(cos(arg), sin(arg), kind=gwp)
9041 : : end do
9042 : 0 : fact = two_pi * kk(3)
9043 [ # # ]: 0 : do iz=0,sc_shape(3) - 1
9044 : 0 : arg = fact * iz
9045 : 0 : ph1d(iz + 1, 3, ikpt) = cmplx(cos(arg), sin(arg), kind=gwp)
9046 : : end do
9047 : : end do ! ikpt
9048 : :
9049 : 0 : end subroutine get_1d_sc_phases
9050 : : !!***
9051 : :
9052 : : !!****f* m_gwr/sc_sum
9053 : : !! NAME
9054 : : !! sc_sum
9055 : : !!
9056 : : !! FUNCTION
9057 : : !! Compute matrix elements of the self-energy Sigma_nk in the supercell at fixed rr.
9058 : : !!
9059 : : !! INPUTS
9060 : : !! sc_shape(3)=Supercell shape.
9061 : : !! uc_ngfft(18)=Info on the FFT mesh in the unit cell.
9062 : : !! nspinor=Number of spinor componenets.
9063 : : !! ph1d=1d phase factors in the supercell
9064 : : !! k_is_gamma=Tru if k is gamma.
9065 : : !! alpha=Coeffient
9066 : : !! sc_data=Values in the supercell
9067 : : !! uc_psi=Wavefunction in the unit cell
9068 : : !!
9069 : : !! OUTPUT
9070 : : !! cout=Partial contribution to integral.
9071 : : !!
9072 : : !! SOURCE
9073 : :
9074 [ # # ]: 0 : subroutine sc_sum(sc_shape, uc_ngfft, ph1d, k_is_gamma, alpha, sc_data, uc_psi, cout)
9075 : :
9076 : : !Arguments ------------------------------------
9077 : : integer,intent(in) :: sc_shape(3), uc_ngfft(18)
9078 : : complex(gwp),intent(in) :: ph1d(maxval(sc_shape), 3)
9079 : : logical,intent(in) :: k_is_gamma
9080 : : complex(gwp),target,intent(in) :: alpha, uc_psi(uc_ngfft(1)*uc_ngfft(2)*uc_ngfft(3))
9081 : : complex(gwp),target,intent(in) :: &
9082 : : sc_data(uc_ngfft(1)*sc_shape(1)*uc_ngfft(2)*sc_shape(2)*uc_ngfft(3)*sc_shape(3))
9083 : : complex(gwp),intent(out) :: cout
9084 : :
9085 : : !Local variables-------------------------------
9086 : : integer :: il1, il2, il3, uc_n1, uc_n2, uc_n3, ix, iy, iz !, idat
9087 : : complex(gwp) :: cphase, phl32, phl3
9088 : 0 : complex(gwp),contiguous,pointer :: uc_psi_ptr(:,:,:), sc_data_ptr(:,:,:,:,:,:)
9089 : : ! *************************************************************************
9090 : :
9091 : 0 : uc_n1 = uc_ngfft(1); uc_n2 = uc_ngfft(2); uc_n3 = uc_ngfft(3)
9092 : :
9093 [ # # ]: 0 : call c_f_pointer(c_loc(uc_psi), uc_psi_ptr, shape=[uc_n1, uc_n2, uc_n3])
9094 : : call c_f_pointer(c_loc(sc_data), sc_data_ptr, &
9095 [ # # ]: 0 : shape=[uc_n1, sc_shape(1), uc_n2, sc_shape(2), uc_n3, sc_shape(3)])
9096 : :
9097 : 0 : cout = zero
9098 : :
9099 [ # # ]: 0 : if (k_is_gamma) then
9100 : : ! Don't need to multiply by e^{ik.L}
9101 [ # # ]: 0 : do il3=1,sc_shape(3)
9102 [ # # ]: 0 : do iz=1,uc_n3
9103 [ # # ]: 0 : do il2=1,sc_shape(2)
9104 [ # # ]: 0 : do iy=1,uc_n2
9105 [ # # ]: 0 : do il1=1,sc_shape(1)
9106 [ # # ]: 0 : do ix=1,uc_n1
9107 : 0 : cout = cout + uc_psi_ptr(ix, iy, iz) * sc_data_ptr(ix, il1, iy, il2, iz, il3)
9108 : : end do
9109 : : end do
9110 : : end do
9111 : : end do
9112 : : end do
9113 : : end do
9114 : :
9115 : : else
9116 : : ! Need to multiply by e^{ik.L}
9117 [ # # ]: 0 : do il3=1,sc_shape(3)
9118 : 0 : phl3 = ph1d(il3, 3)
9119 [ # # ]: 0 : do iz=1,uc_n3
9120 [ # # ]: 0 : do il2=1,sc_shape(2)
9121 : 0 : phl32 = phl3 * ph1d(il2, 2)
9122 [ # # ]: 0 : do iy=1,uc_n2
9123 [ # # ]: 0 : do il1=1,sc_shape(1)
9124 : 0 : cphase = phl32 * ph1d(il1, 1) ! e^{ik.L}
9125 [ # # ]: 0 : do ix=1,uc_n1
9126 : 0 : cout = cout + cphase * uc_psi_ptr(ix, iy, iz) * sc_data_ptr(ix, il1, iy, il2, iz, il3)
9127 : : end do
9128 : : end do
9129 : : end do
9130 : : end do
9131 : : end do
9132 : : end do
9133 : : end if
9134 : :
9135 : 0 : cout = alpha * cout
9136 : :
9137 : 0 : end subroutine sc_sum
9138 : : !!***
9139 : :
9140 : : !!****f* m_gwr/memb_limited_step
9141 : : !! NAME
9142 : : !! memb_limited_step
9143 : : !!
9144 : : !! FUNCTION
9145 : : !! Compute the amount of memory needed to process all the data between start and stop,
9146 : : !! and limits the number of steps to avoid exceeding maxmem_mb.
9147 : : !!
9148 : : !! INPUTS
9149 : : !! start, stop: integer range of indices.
9150 : : !! num_items: number of data items processed per index.
9151 : : !! bsize: size in bytes per data item.
9152 : : !! maxmem_mb: maximum allowed memory usage (in megabytes)
9153 : : !!
9154 : : !! OUTPUT
9155 : : !!
9156 : : !! SOURCE
9157 : :
9158 : : integer pure function memb_limited_step(start, stop, num_items, bsize, maxmem_mb) result(step)
9159 : : integer,intent(in) :: start, stop, num_items, bsize
9160 : : real(dp),intent(in) :: maxmem_mb
9161 : :
9162 : : !Local variables-------------------------------
9163 : : real(dp) :: totmem_mb
9164 : : ! *************************************************************************
9165 : :
9166 : : totmem_mb = one * (stop - start + 1) * num_items * bsize
9167 : : step = stop - start + 1
9168 : : if (totmem_mb > maxmem_mb) step = floor(totmem_mb / maxmem_mb)
9169 : :
9170 : : end function memb_limited_step
9171 : : !!***
9172 : :
9173 : : !----------------------------------------------------------------------
9174 : :
9175 : : !!****f* m_gwr/gwr_gamma_gw
9176 : : !! NAME
9177 : : !! gwr_gamma_gw
9178 : : !!
9179 : : !! FUNCTION
9180 : : !!
9181 : : !! INPUTS
9182 : : !! vpsp(nfft)=local psp (Hartree)
9183 : : !!
9184 : : !! OUTPUT
9185 : : !!
9186 : : !! SOURCE
9187 : :
9188 : 0 : subroutine gwr_gamma_gw(gwr, nfftf, ngfftf, vpsp)
9189 : :
9190 : : use m_gwrdm, only : calc_rdmx,calc_rdmc,natoccs,update_hdr_bst,print_tot_occ,get_chkprdm,&
9191 : : print_chkprdm,change_matrix,print_total_energy,print_band_energies
9192 : : use m_spacepar, only : hartre
9193 : :
9194 : : !Arguments ------------------------------------
9195 : : class(gwr_t),target,intent(inout) :: gwr
9196 : : integer,intent(in) :: nfftf
9197 : : !arrays
9198 : : integer,intent(in) :: ngfftf(18)
9199 : : real(dp),intent(in) :: vpsp(nfftf)
9200 : :
9201 : : !Local variables-------------------------------
9202 : : !scalars
9203 : : integer,parameter :: master = 0, cplex1 = 1, tim_fourdp5 = 5
9204 : : integer :: spin, ikcalc, ik_ibz, ib, ib1, ib2, nkibz, nsppol, mband, ierr, b1gw, b2gw
9205 : : !real(dp) :: cpu, wall, gflops
9206 : : real(dp) :: evext_energy,den_int !,coef_hyb,exc_mbb_energy eh_energy, ekin_energy,
9207 : : real(dp) :: gsqcut,boxcut,ecutf
9208 : : character(len=500) :: msg
9209 : 0 : type(hdr_type) :: Hdr_sigma
9210 : : !arrays
9211 : : integer :: units(2)
9212 : : real(dp),parameter :: k0(3) = zero
9213 : : !real(dp) :: kgw(3) ! kk_ibz(3),
9214 : 0 : real(dp),allocatable :: nat_occs(:,:), gw_rhor(:,:), gw_rhog(:,:), gw_vhartr(:)
9215 : 0 : complex(dp),allocatable :: xrdm_k_full(:,:,:), rdm_k(:,:), pot_k(:,:), nateigv(:,:,:,:), old_ks_purex(:,:), new_hartr(:,:)
9216 : 0 : complex(dp) :: omega_i(gwr%ntau)
9217 : 0 : complex(dp),allocatable :: sigcme_k(:,:,:,:)
9218 : : ! *************************************************************************
9219 : :
9220 : 0 : call gwr%run_g0w0(free_ugb=.False.)
9221 : : ! TODO: Might release some PBLAS memory for W at this point
9222 : :
9223 : : ! This section is copied from m_sigma_driver with small changes in order to intergrate it with the gwr% object.
9224 : : associate (dtset => gwr%dtset, qp_ebands => gwr%qp_ebands, ks_me => gwr%ks_me, psps => gwr%psps, &
9225 : : Wfd_nato_master => gwr%kcalc_wfd, dtfil => gwr%dtfil, cryst => gwr%cryst)
9226 : :
9227 [ # # ]: 0 : units = [std_out, ab_out]
9228 : 0 : nkibz = gwr%nkibz; nsppol = gwr%nsppol; b1gw = gwr%b1gw; b2gw = gwr%b2gw
9229 : : ! Don't take mband from ks_ebands but compute it from gwr%bstop_ks
9230 [ # # # # ]: 0 : mband = maxval(gwr%bstop_ks) !; mband = gwr%ks_ebands%mband
9231 : :
9232 : : ! Note: all subroutines of 70_gw/m_gwrdm.F90 are implemented assuming nsppol == 1
9233 [ # # ]: 0 : ABI_CHECK(dtset%nsppol == 1, "1-RDM GW correction only implemented for restricted closed-shell calculations!")
9234 [ # # ]: 0 : ABI_CHECK(.not. gwr%sig_diago, "sig_diago should be false")
9235 : :
9236 [ # # # # : 0 : ABI_CALLOC(nateigv, (mband, mband, nkibz, nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
9237 [ # # # # : 0 : ABI_CALLOC(nat_occs, (mband, nkibz))
# # # # #
# # # # #
# # # # #
# ]
9238 [ # # # # : 0 : ABI_CALLOC(xrdm_k_full, (b1gw:b2gw, b1gw:b2gw, nkibz))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
9239 : :
9240 : 0 : write(msg,'(a34,2i9)')' Bands used for the GW 1RDM arrays',b1gw,b2gw
9241 : 0 : call wrtout(units, msg)
9242 : :
9243 [ # # ]: 0 : do ik_ibz=1,nkibz
9244 [ # # ]: 0 : do ib=b1gw,b2gw
9245 : 0 : xrdm_k_full(ib,ib,ik_ibz) = qp_ebands%occ(ib,ik_ibz,1)
9246 : : end do
9247 [ # # ]: 0 : do ib=1,mband
9248 : : ! Copy initial occ numbers (in principle 2 or 0 from KS-DFT)
9249 : 0 : nat_occs(ib,ik_ibz) = qp_ebands%occ(ib,ik_ibz,1)
9250 : : ! Set to identity matrix
9251 : 0 : nateigv(ib,ib,ik_ibz,1) = cone
9252 : : end do
9253 : : end do
9254 : :
9255 [ # # ]: 0 : omega_i = j_dpc * gwr%iw_mesh
9256 : :
9257 [ # # ]: 0 : do spin=1,gwr%nsppol
9258 [ # # ]: 0 : do ikcalc=1,gwr%nkcalc ! TODO: Should be spin dependent!
9259 : : ! Index of the irred k-point
9260 : 0 : ik_ibz = gwr%kcalc2ibz(ikcalc, 1)
9261 : : !kgw = gwr%kcalc(:, ikcalc)
9262 : : ! min and max band indices for GW corrections (for this k-point)
9263 : 0 : ib1 = gwr%bstart_ks(ikcalc, spin); ib2 = gwr%bstop_ks(ikcalc, spin)
9264 : :
9265 : : ! Compute Sigma_x - Vxc or DELTA Sigma_x - Vxc
9266 : : ! where DELTA Sigma_x = Sigma_x - hyb_parameter Vx^exact for hyb Functionals.
9267 : : ! NB: Only restricted closed-shell calcs are implemented here
9268 [ # # # # : 0 : ABI_CALLOC(pot_k, (ib1:ib2, ib1:ib2))
# # # # #
# # # # #
# # # # #
# # # ]
9269 [ # # # # : 0 : ABI_CALLOC(rdm_k, (ib1:ib2, ib1:ib2))
# # # # #
# # # # #
# # # # ]
9270 [ # # # # ]: 0 : pot_k(ib1:ib2,ib1:ib2) = gwr%sigx_mat(ib1:ib2,ib1:ib2,ik_ibz,spin) - ks_me%vxcval(ib1:ib2,ib1:ib2,ik_ibz,spin)
9271 : 0 : call calc_rdmx(ib1, ib2, ik_ibz, pot_k, rdm_k, qp_ebands)
9272 : :
9273 : : ! Update the full 1RDM with the exchange corrected one for this k-point
9274 [ # # # # ]: 0 : xrdm_k_full(ib1:ib2,ib1:ib2,ik_ibz) = xrdm_k_full(ib1:ib2,ib1:ib2,ik_ibz) + rdm_k(ib1:ib2,ib1:ib2)
9275 : :
9276 : : ! Compute NAT ORBS for exchange corrected 1-RDM
9277 : : ! Only restricted closed-shell calcs
9278 [ # # ]: 0 : do ib=ib1,ib2
9279 : 0 : rdm_k(ib,ib) = rdm_k(ib,ib) + qp_ebands%occ(ib,ik_ibz,1)
9280 : : end do
9281 : 0 : call natoccs(ib1, ib2, rdm_k, nateigv, nat_occs, qp_ebands, ik_ibz, iinfo=0)
9282 : :
9283 : : ! ================
9284 : : ! Correlation part
9285 : : ! ================
9286 : : ! TODO
9287 : : !ABI_CALLOC(sigcme_k, (gwr%ntau, ib2-ib1+1, ib2-ib1+1, nsppol*gwr%nsig_ab))
9288 : : !gwr%sigc_iw_mat((gwr%ntau, ib1:, ib1:, nsppol*gwr%nsig_ab))
9289 : 0 : call calc_rdmc(ib1, ib2, ik_ibz, omega_i, gwr%iw_wgs, sigcme_k, qp_ebands, rdm_k)
9290 : : !ABI_FREE(sigcme_k)
9291 : :
9292 : : ! Update the full 1RDM with the GW corrected one for this k-point
9293 : : ! Only restricted closed-shell calcs
9294 [ # # # # ]: 0 : rdm_k(ib1:ib2,ib1:ib2) = xrdm_k_full(ib1:ib2,ib1:ib2,ik_ibz) + rdm_k(ib1:ib2,ib1:ib2)
9295 : : ! Compute nat orbs and occ numbers at k-point ik_ibz
9296 : 0 : call natoccs(ib1, ib2, rdm_k, nateigv, nat_occs, qp_ebands, ik_ibz, iinfo=1)
9297 : :
9298 [ # # ]: 0 : ABI_FREE(pot_k)
9299 [ # # ]: 0 : ABI_FREE(rdm_k)
9300 : : end do ! ikcalc
9301 : : end do ! spin
9302 : :
9303 [ # # # # : 0 : ABI_CALLOC(gw_rhor, (nfftf, dtset%nspden))
# # # # #
# # # # #
# # # # #
# ]
9304 : 0 : call gwr%wfk_hdr%copy(hdr_sigma)
9305 : :
9306 : : ! NRM WARNING: only the master has bands on Wfd_nato_master so it prints everything and computes gw_rhor
9307 : : !
9308 : : ! All procs. update the qp_ebands and the Hdr_sigma
9309 : 0 : call update_hdr_bst(Wfd_nato_master, nat_occs, b1gw, b2gw, qp_ebands, Hdr_sigma, Dtset%ngfft(1:3))
9310 : :
9311 : : ! Compute unit cell (averaged) occ = \sum _k weight_k occ_k
9312 : 0 : call print_tot_occ(qp_ebands)
9313 : :
9314 [ # # ]: 0 : if (gwr%comm%me == master) then
9315 : 0 : call Wfd_nato_master%rotate(cryst, nateigv) !, bmask=bdm_mask) ! Let it use bdm_mask and build NOs
9316 : 0 : call Wfd_nato_master%mkrho(cryst, psps, qp_ebands, ngfftf, nfftf, gw_rhor) ! Construct the density
9317 [ # # ]: 0 : if (dtset%prtwf == 1) then
9318 : : ! Print WFK file, here qp_ebands contains nat. orb. occs.
9319 : 0 : call Wfd_nato_master%write_wfk(Hdr_sigma, qp_ebands, dtfil%fnameabo_wfk, wfknocheck=.True.)
9320 : : end if
9321 [ # # ]: 0 : if (dtset%prtden == 1) then
9322 : : ! Print DEN file
9323 : : call fftdatar_write("density",dtfil%fnameabo_den,dtset%iomode,Hdr_sigma,&
9324 : 0 : Cryst,ngfftf,cplex1,nfftf,dtset%nspden,gw_rhor,gwr%mpi_enreg,ebands=qp_ebands)
9325 : : end if
9326 : : end if
9327 : 0 : call xmpi_bcast(gw_rhor, master, gwr%comm%value, ierr)
9328 : 0 : call hdr_sigma%free()
9329 : :
9330 : : ! Compute energies only if all k-points are available
9331 : : ! We need the hole 1-RDM to build Fock[GW.1RDM]!
9332 [ # # # # : 0 : ABI_CALLOC(old_ks_purex, (b1gw:b2gw, gwr%nkcalc))
# # # # #
# # # # #
# # # # #
# ]
9333 [ # # # # : 0 : ABI_CALLOC(new_hartr, (b1gw:b2gw, gwr%nkcalc))
# # # # #
# # # # #
# # ]
9334 [ # # # # : 0 : ABI_CALLOC(gw_rhog, (2, nfftf))
# # # # #
# # # # #
# # ]
9335 [ # # # # : 0 : ABI_CALLOC(gw_vhartr, (nfftf))
# # # # #
# # # #
# ]
9336 : : !
9337 : : ! A) Compute Evext = int rho(r) vext(r) dr -> simply dot product on the FFT grid
9338 : : ! Only restricted closed-shell calcs
9339 : : !
9340 : 0 : den_int = sum(gw_rhor(:,1)) * cryst%ucvol / nfftf
9341 : 0 : evext_energy = sum(gw_rhor(:,1) * vpsp(:)) * cryst%ucvol / nfftf
9342 : : !
9343 : : ! B) Coulomb <KS_i|Vh[NO]|KS_j>
9344 : : !
9345 : : ! FFT to build gw_rhog
9346 : 0 : call fourdp(1, gw_rhog, gw_rhor(:,1), -1, gwr%mpi_enreg, nfftf, ndat1, ngfftf, tim_fourdp5)
9347 : :
9348 : 0 : ecutf = dtset%ecutwfn
9349 [ # # ]: 0 : if (psps%usepaw == 1) then
9350 : 0 : ecutf = dtset%pawecutdg
9351 : 0 : call wrtout(std_out, ch10//' FFT (fine) grid used in PAW GW update:')
9352 : : end if
9353 : :
9354 : 0 : call getcut(boxcut, ecutf, cryst%gmet, gsqcut, dtset%iboxcut, std_out, k0, ngfftf)
9355 : : call hartre(1, gsqcut, dtset%icutcoul, psps%usepaw, gwr%mpi_enreg, nfftf, ngfftf, dtset%nkpt, dtset%rcut, &
9356 : 0 : gw_rhog, cryst%rprimd, dtset%vcutgeo, gw_vhartr)
9357 : :
9358 : : ! TODO
9359 [ # # ]: 0 : ABI_FREE(nateigv)
9360 [ # # ]: 0 : ABI_FREE(nat_occs)
9361 [ # # ]: 0 : ABI_FREE(xrdm_k_full)
9362 [ # # ]: 0 : ABI_FREE(gw_rhor)
9363 [ # # ]: 0 : ABI_FREE(old_ks_purex)
9364 [ # # ]: 0 : ABI_FREE(new_hartr)
9365 [ # # ]: 0 : ABI_FREE(gw_rhog)
9366 [ # # ]: 0 : ABI_FREE(gw_vhartr)
9367 : : end associate
9368 : :
9369 [ # # # # : 0 : end subroutine gwr_gamma_gw
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
9370 : : !!***
9371 : :
9372 [ # # # # : 0 : end module m_gwr
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
9373 : : !!***
|