Line data Source code
1 : !!****m* ABINIT/m_wkk
2 : !! NAME
3 : !! m_wkk
4 : !!
5 : !! FUNCTION
6 : !! Computation of the matrix elements of the screened interaction W_kk'.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2008-2026 ABINIT group (MG)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt.
13 : !!
14 : !! SOURCE
15 :
16 : #if defined HAVE_CONFIG_H
17 : #include "config.h"
18 : #endif
19 :
20 : #include "abi_common.h"
21 :
22 : module m_wkk
23 :
24 : !use, intrinsic :: iso_c_binding
25 : use defs_basis
26 : use m_abicore
27 : use m_xmpi
28 : use m_mpinfo
29 : use m_errors
30 : use m_fft
31 : use m_wfd
32 : use m_hdr
33 : use netcdf
34 : use m_nctk
35 : use m_dtset
36 : use m_dtfil
37 : use m_fstab
38 : use m_ephtk
39 :
40 : use defs_abitypes, only : mpi_type
41 : use defs_datatypes, only : pseudopotential_type
42 : use m_gwdefs, only : GW_Q0_DEFAULT, cone_gw, czero_gw
43 : use m_hide_blas, only : xgemm, xdotc
44 : use m_special_funcs, only : gaussian
45 : use m_time, only : cwtime, cwtime_report, timab, sec2str
46 : use m_fstrings, only : itoa, ftoa, sjoin, ktoa, ltoa, strcat
47 : use m_numeric_tools, only : arth, linspace ! print_arr
48 : use m_io_tools, only : iomode_from_fname
49 : use m_fftcore, only : ngfft_seq, sphereboundary, get_kg, print_ngfft
50 : use m_crystal, only : crystal_t
51 : use m_bz_mesh, only : kmesh_t, findqg0
52 : use m_htetra, only : htetra_t
53 : use m_gsphere, only : gsphere_t
54 : use m_pawtab, only : pawtab_type
55 : use m_io_screening, only : hscr_t, get_hscr_qmesh_gsph
56 : use m_vcoul, only : vcoul_t
57 : !use m_occ, only : get_fact_spin_tol_empty
58 : use m_ebands, only : ebands_t, edos_t
59 : use m_pstat, only : pstat_proc
60 : use m_sigtk, only : sigtk_multiply_by_vc_sqrt
61 : use m_screening, only : epsm1_t
62 : use m_ddk, only : ddkop_t
63 :
64 : implicit none
65 :
66 : private
67 : !!***
68 :
69 : public :: wkk_run ! Main entry point to compute Wkk' matrix elements.
70 :
71 : !----------------------------------------------------------------------
72 :
73 : contains !=====================================================
74 : !!***
75 :
76 : !----------------------------------------------------------------------
77 :
78 : !!****f* m_wkk/wkk_run
79 : !! NAME
80 : !! wkk_run
81 : !!
82 : !! FUNCTION
83 : !! Computation of the matrix elements of the screened interaction W_kk'
84 : !! between two Cooper pairs.
85 : !!
86 : !! INPUTS
87 : !! wfk0_path=String with the path to the GS unperturbed WFK file.
88 : !! dtfil<datafiles_type>=Variables related to files.
89 : !! ngfft(18),ngfftf(18)=Coarse and Fine FFT meshes.
90 : !! dtset<dataset_type>=All input variables for this dataset.
91 : !! cryst: Crystalline structure
92 : !! ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
93 : !! wfk_hdr=Header of the WFK file.
94 : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
95 : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
96 : !! comm=MPI communicator.
97 : !!
98 : !! OUTPUT
99 : !! Results are written to file in netcdf format.
100 : !!
101 : !! SOURCE
102 :
103 0 : subroutine wkk_run(wfk0_path, dtfil, ngfft, ngfftf, dtset, cryst, ebands, wfk_hdr, &
104 0 : pawtab, psps, mpi_enreg, comm)
105 :
106 : !Arguments ------------------------------------
107 : !scalars
108 : character(len=*),intent(in) :: wfk0_path
109 : type(datafiles_type),intent(in) :: dtfil
110 : type(dataset_type),intent(inout) :: dtset
111 : type(crystal_t),intent(in) :: cryst
112 : type(ebands_t),target,intent(in) :: ebands
113 : type(hdr_type),intent(in) :: wfk_hdr
114 : type(pseudopotential_type),intent(in) :: psps
115 : type(mpi_type),intent(inout) :: mpi_enreg
116 : integer,intent(in) :: comm
117 : !arrays
118 : integer,intent(in) :: ngfft(18), ngfftf(18)
119 : type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
120 :
121 : !Local variables ------------------------------
122 : !scalars
123 : integer,parameter :: LOG_MODQ = 1, LOG_MODK = 4, istwfk1 = 1, master = 0, ndat1 = 1
124 : integer :: id_required, approx_type, ikxc, option_test, nkxc, ig
125 : integer :: nkibz, my_rank, nsppol, iq_ibz, iq_bz, isym_qq, itim_qq
126 : integer :: nspinor,nprocs, ii, spin, npw_x, npw_c ! max_npw_xc, min_npw_xc, my_is, cplex, ib,
127 : integer :: bstart_k, bstop_k, nband_k, ncols, mpw, ierr !, ncerr
128 : integer :: bstart_kp, bstop_kp, nband_kp, ik_bz, bmin, bmax, max_nb
129 : integer :: ikp_ibz, isym_kp, trev_kp, npw_kp, istwf_kp, npw_kp_ibz, istwf_kp_ibz
130 : integer :: ik_ibz, isym_k, trev_k, npw_k, istwf_k, npw_k_ibz, istwf_k_ibz
131 : integer :: m_k, im_k, n_kp, in_kp, root_ncid, wkk_mode, ne
132 : integer :: nfft,nfftf,mgfft,mgfftf,nkpg_kp,nkpg_k,edos_intmeth, nqlwl, scr_iomode ! cnt,
133 : integer :: ikp_bz, my_ikp, my_nkp !, my_iq,
134 : real(dp) :: cpu_all, wall_all, gflops_all, cpu_kp, wall_kp, gflops_kp ! cpu, wall, gflops,
135 : real(dp) :: edos_step, edos_broad, e_mk, e_nkp, e_min, e_max, e_step, smear_mk, smear_nkp, faq
136 : logical :: isirr_k, isirr_kp, qq_is_gamma, remove_exchange, print_time_kp
137 0 : type(wfd_t) :: wfd
138 0 : type(kmesh_t) :: qmesh, kmesh
139 0 : type(gsphere_t),target :: gsph_x, gsph_c
140 0 : type(hscr_t),target :: hscr
141 0 : type(vcoul_t) :: vcp
142 0 : type(edos_t) :: edos
143 0 : type(epsm1_t) :: epsm1
144 0 : type(ddkop_t) :: ddkop
145 0 : type(htetra_t) :: tetra
146 : character(len=fnlen) :: screen_filepath
147 : character(len=5000) :: msg !, qkp_string
148 : !arrays
149 : integer :: g0_k(3), g0_kp(3), g0_qq(3), units(2), work_ngfft(18), gmax(3), mapl_k(6), mapl_kp(6), mg0(3)
150 0 : integer,allocatable :: kg_kp(:,:), kg_k(:,:), gbound_kp(:,:), gbound_k(:,:), gbound_c(:,:), gbound_x(:,:)
151 0 : integer,allocatable :: nband(:,:), wfd_istwfk(:)
152 0 : integer, contiguous, pointer :: kg_c(:,:), kg_x(:,:)
153 : real(dp) :: kk_ibz(3), kk_bz(3), kp_ibz(3), kp_bz(3), qq_bz(3), kk_diff(3) ! qq_ibz(3)
154 : complex(gwp) :: ctmp_gwpc
155 : character(len=fnlen) :: path
156 : !arrays
157 0 : real(dp) :: n0(ebands%nsppol)
158 0 : real(dp),allocatable :: qlwl(:,:), kpg_kp(:,:), kpg_k(:,:), ug_kp(:,:,:), ug_k(:,:) !, cg_work(:,:)
159 0 : real(dp),allocatable :: work(:,:,:,:), e_mesh(:), e_args(:), wgt_mk(:), wgt_nkp(:,:) ! vcart_ibz(:,:,:,:),
160 0 : complex(gwp),allocatable :: cwork_ur(:), rhotwg_mn_x(:,:,:), rhotwg_mn_c(:,:,:), w_rhotwg_mn_c(:,:,:)
161 0 : complex(gwp),allocatable :: vc_sqrt_gx(:), ur_nkp(:,:), ur_mk(:,:), kxcg(:,:), mu_mn(:,:)
162 0 : complex(dp),allocatable :: w_ee(:,:) ! w_kkp(:,:,:,:)
163 0 : logical,allocatable :: bks_mask(:,:,:), keep_ur(:,:,:)
164 0 : type(fstab_t),target,allocatable :: fstab(:)
165 : !************************************************************************
166 :
167 0 : ABI_CHECK(psps%usepaw == 0, "PAW not implemented")
168 0 : ABI_CHECK(dtset%nsppol == 1, "nsppol 2 implemented!")
169 0 : ABI_CHECK(dtset%nspinor == 1, "nspinor 2 implemented!")
170 :
171 : ABI_UNUSED(mpi_enreg%nproc)
172 :
173 0 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm); units = [std_out, ab_out]
174 0 : call cwtime(cpu_all, wall_all, gflops_all, "start")
175 :
176 0 : nsppol = ebands%nsppol; nspinor = ebands%nspinor
177 :
178 : ! Compute electron DOS.
179 0 : edos_intmeth = 2; if (dtset%prtdos /= 0) edos_intmeth = dtset%prtdos
180 : edos_step = dtset%dosdeltae; edos_broad = dtset%tsmear
181 0 : edos_step = 0.01 * eV_Ha; edos_broad = 0.3 * eV_Ha
182 0 : edos = ebands%get_edos(cryst, edos_intmeth, edos_step, edos_broad, comm)
183 :
184 : ! Get DOS per spin channel
185 0 : n0(:) = edos%gef(1:edos%nsppol)
186 0 : if (my_rank == master) then
187 0 : call edos%print(units)
188 0 : path = strcat(dtfil%filnam_ds(4), "_EDOS")
189 0 : call edos%write(path)
190 : end if
191 :
192 : ! Find Fermi surface k-points.
193 : ! TODO: support kptopt, change setup of k-points if tetra: fist tetra weights then k-points on the Fermi surface!
194 0 : ABI_MALLOC(fstab, (nsppol))
195 0 : call fstab_init(fstab, ebands, cryst, dtset, tetra, comm)
196 0 : call tetra%free()
197 :
198 0 : bmin = huge(1); bmax = -1
199 0 : do spin=1,nsppol
200 0 : bmin = min(bmin, fstab(spin)%bmin)
201 0 : bmax = max(bmax, fstab(spin)%bmax)
202 : end do
203 0 : max_nb = bmax - bmin + 1
204 :
205 : ! Build linear mesh for W(e,e').
206 0 : spin = 1
207 : associate (fs => fstab(spin))
208 0 : e_min = minval(ebands%eig(fs%bmin,:,spin)) - 0.1_dp * eV_Ha
209 0 : e_max = maxval(ebands%eig(fs%bmax,:,spin)) + 0.1_dp * eV_Ha
210 0 : e_step = 0.002 * eV_Ha
211 0 : ne = 1 + (e_max - e_min) / e_step
212 0 : ABI_CALLOC(w_ee, (ne, ne))
213 0 : ABI_MALLOC(e_mesh, (ne))
214 0 : ABI_MALLOC(e_args, (ne))
215 0 : ABI_MALLOC(wgt_mk, (ne))
216 0 : ABI_MALLOC(wgt_nkp, (ne, max_nb))
217 0 : e_mesh = linspace(e_min, e_max, ne)
218 : end associate
219 :
220 : ! ================
221 : ! HANDLE SCREENING
222 : ! ================
223 0 : screen_filepath = dtfil%fnameabi_scr
224 0 : ABI_CHECK(dtfil%fnameabi_scr /= ABI_NOFILE, "SCR file must be specified in input!")
225 :
226 : ! Read g-sphere for correlation and qmesh from SCR file.
227 0 : call get_hscr_qmesh_gsph(screen_filepath, dtset, cryst, hscr, qmesh, gsph_c, qlwl, comm)
228 0 : call hscr%print(units, dtset%prtvol, header="Header of the SCR file")
229 :
230 0 : nqlwl = size(qlwl, dim=2)
231 0 : if (nqlwl == 0) then
232 0 : nqlwl=1
233 0 : ABI_MALLOC(qlwl,(3,nqlwl))
234 0 : qlwl(:,nqlwl)= GW_Q0_DEFAULT
235 : write(msg,'(3a,i0,a,3f9.6)')&
236 0 : "The Header of the screening file does not contain the list of q-point for the optical limit ",ch10,&
237 0 : "Using nqlwl= ",nqlwl," and qlwl = ",qlwl(:,1)
238 0 : ABI_COMMENT(msg)
239 : end if
240 :
241 : ! Init g-sphere for the exchange part from ecutsigx.
242 0 : call gsph_c%extend(cryst, dtset%ecutsigx, gsph_x)
243 :
244 : ! Initialize Coulomb term on the IBZ of the qmesh. Use largest G-sphere.
245 0 : call kmesh%init(cryst, wfk_hdr%nkpt, wfk_hdr%kptns, dtset%kptopt)
246 0 : faq = one / (cryst%ucvol*kmesh%nbz)
247 :
248 : ! TODO:
249 : ! Here we sort the pp_mesh by stars so that we can split the pp wavevectors in blocks and therefore
250 : ! reduce the number of wavevectors in the IBZ that must be stored in memory.
251 : !call qmesh%pack_by_stars()
252 :
253 0 : npw_x = gsph_x%ng; npw_c = gsph_c%ng !; min_npw_xc = min(npw_x, npw_c); max_npw_xc = max(npw_x, npw_c)
254 0 : if (gsph_x%ng >= gsph_c%ng) then
255 : call vcp%init(gsph_x, cryst, qmesh, kmesh, dtset%rcut, dtset%gw_icutcoul, dtset%vcutgeo, dtset%ecuteps, gsph_x%ng, &
256 0 : nqlwl, qlwl, comm)
257 : else
258 : call vcp%init(gsph_c, cryst, qmesh, kmesh, dtset%rcut, dtset%gw_icutcoul, dtset%vcutgeo, dtset%ecuteps, gsph_c%ng, &
259 0 : nqlwl, qlwl, comm)
260 : end if
261 :
262 0 : ABI_FREE(qlwl)
263 :
264 0 : if (my_rank == master) then
265 0 : call kmesh%print(units, header="K-mesh for wavefunctions", prtvol=dtset%prtvol)
266 0 : call gsph_x%print(units, dtset%prtvol, header="G-sphere for exchange")
267 0 : call gsph_c%print(units, dtset%prtvol, header="G-sphere for correlation")
268 0 : call vcp%print(units, prtvol=dtset%prtvol)
269 : end if
270 0 : call kmesh%free()
271 :
272 0 : ABI_CHECK_IGE(npw_x, 1, "npw_x <= 1")
273 0 : ABI_CHECK_IGE(npw_c, 1, "npw_c <= 1")
274 :
275 : ! Note that in this case, the sphere is always Gamma-centered i.e. it does not depend on the qq wavevector
276 0 : kg_c => gsph_c%gvec(:, 1:npw_c)
277 0 : kg_x => gsph_x%gvec(:, 1:npw_x)
278 :
279 : ! Initialize the wave function descriptor.
280 : ! Only wavefunctions on the FS are stored in wfd.
281 : ! Need all k-points on the FS because of k+q, spin is not distributed for the time being.
282 : ! It would be possible to reduce the memory allocated per MPI-rank via OpenMP.
283 0 : nkibz = wfk_hdr%nkpt
284 0 : ABI_MALLOC(nband, (nkibz, nsppol))
285 0 : ABI_MALLOC(bks_mask, (dtset%mband, nkibz, nsppol))
286 0 : ABI_MALLOC(keep_ur, (dtset%mband, nkibz, nsppol))
287 0 : nband = dtset%mband; bks_mask = .False.; keep_ur = .False.
288 :
289 0 : do spin=1,ebands%nsppol
290 0 : associate (fs => fstab(spin))
291 0 : do ik_bz=1,fs%nkfs
292 0 : ik_ibz = fs%indkk_fs(1, ik_bz)
293 0 : bstart_k = fs%bstart_cnt_ibz(1, ik_ibz); nband_k = fs%bstart_cnt_ibz(2, ik_ibz)
294 0 : bks_mask(bstart_k:bstart_k+nband_k-1, ik_ibz, spin) = .True.
295 : end do
296 : end associate
297 : end do
298 :
299 : ! Impose istwfk=1 for all k points. This is also done in respfn (see inkpts)
300 : ! wfd_read_wfk will handle a possible conversion if WFK contains istwfk /= 1.
301 0 : ABI_MALLOC(wfd_istwfk, (nkibz))
302 0 : wfd_istwfk = 1
303 :
304 : call wfd%init(cryst, pawtab, psps, keep_ur, dtset%mband, nband, nkibz, nsppol, bks_mask,&
305 : dtset%nspden, nspinor, dtset%ecut, dtset%ecutsm, dtset%dilatmx, wfd_istwfk, ebands%kptns, ngfft,&
306 0 : dtset%nloalg, dtset%prtvol, dtset%pawprtvol, comm)
307 :
308 0 : call pstat_proc%print(_PSTAT_ARGS_)
309 :
310 0 : ABI_FREE(nband)
311 0 : ABI_FREE(bks_mask)
312 0 : ABI_FREE(keep_ur)
313 0 : ABI_FREE(wfd_istwfk)
314 :
315 : ! Read wavefunctions.
316 0 : call wfd%read_wfk(wfk0_path, iomode_from_fname(wfk0_path))
317 :
318 : ! TODO
319 : ! mpw is the maximum number of plane-waves over k and k+q where k and k+q are in the BZ.
320 : ! We also need the max components of the G-spheres (k, k+q) in order to allocate the workspace array work
321 : ! that will be used to symmetrize the wavefunctions in G-space.
322 : ! This is the maximum number of PWs for all possible k+q treated.
323 :
324 0 : call ephtk_get_mpw_gmax(nkibz, wfk_hdr%kptns, dtset%ecut, cryst%gmet, mpw, gmax, comm)
325 : ! FIXME
326 : !gmax = 2 * gmax
327 :
328 0 : call ddkop%init(dtset, cryst, pawtab, psps, wfd%mpi_enreg, mpw, wfd%ngfft)
329 :
330 : #if 0
331 : call cwtime(cpu, wall, gflops, "start", msg=" Computing v_nk matrix elements for all states on the FS...")
332 :
333 : ABI_CALLOC(vcart_ibz, (3, bmin:bmax, nkibz, nsppol))
334 : ABI_MALLOC(cg_work, (2, mpw * nspinor))
335 :
336 : cnt = 0
337 : do spin=1,nsppol
338 : associate (fs => fstab(spin))
339 : do ik_ibz=1,ebands%nkpt
340 : kk_ibz = ebands%kptns(:, ik_ibz)
341 : npw_k = wfd%npwarr(ik_ibz); istwf_k = wfd%istwfk(ik_ibz)
342 : ! NB: The two checks below are global --> all procs will cycle.
343 : if (all(bks_mask(:, ik_ibz, spin) .eqv. .False.)) cycle
344 : if (npw_k == 1) cycle
345 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
346 :
347 : call ddkop%setup_spin_kpoint(dtset, cryst, psps, spin, kk_ibz, istwf_k, npw_k, wfd%kdata(ik_ibz)%kg_k)
348 :
349 : do band_k=fs%bmin,fs%bmax
350 : if (.not. bks_mask(band_k, ik_ibz, spin)) cycle
351 : call wfd%copy_cg(band_k, ik_ibz, spin, cg_work)
352 : eig0nk = ebands%eig(band_k, ik_ibz, spin)
353 : vk = ddkop%get_vdiag(eig0nk, istwf_k, npw_k, wfd%nspinor, cg_work, cwaveprj0)
354 : vcart_ibz(:, band_k, ik_ibz, spin) = vk
355 : end do
356 : end do
357 : end associate
358 : end do ! spin
359 :
360 : call xmpi_sum(vcart_ibz, comm, ierr)
361 : ABI_FREE(cg_work)
362 : ABI_FREE(vcart_ibz)
363 : call cwtime_report(" Velocities", cpu, wall, gflops)
364 : #endif
365 0 : call ddkop%free()
366 :
367 0 : call ngfft_seq(work_ngfft, gmax)
368 0 : ABI_MALLOC(work, (2, work_ngfft(4), work_ngfft(5), work_ngfft(6)))
369 :
370 : ! FFT meshes from input file, not necessarily equal to the ones found in the external files.
371 : ! NB: ur arrays are always allocated with nfft and not with product(ngfft(4:6)).
372 0 : nfftf = product(ngfftf(1:3)); mgfftf = maxval(ngfftf(1:3))
373 0 : nfft = product(ngfft(1:3)) ; mgfft = maxval(ngfft(1:3))
374 :
375 0 : call print_ngfft([std_out], ngfft, header="FFT mesh")
376 :
377 : ! Set the FFT mesh
378 0 : call wfd%change_ngfft(cryst, psps, ngfft)
379 0 : call wfd%print(units, header="Wavefunctions for GWPT calculation.")
380 :
381 0 : ABI_MALLOC(gbound_kp, (2*mgfft+8, 2))
382 0 : ABI_MALLOC(gbound_k, (2*mgfft+8, 2))
383 0 : ABI_MALLOC(gbound_c, (2*mgfft+8, 2))
384 0 : ABI_MALLOC(gbound_x, (2*mgfft+8, 2))
385 :
386 : ! ====================================
387 : ! This is the g-sphere for W_{gg'}(qq)
388 : ! ====================================
389 : ! Init g-sphere for the exchange part from ecutsigx.
390 0 : call sphereboundary(gbound_c, istwfk1, kg_c, mgfft, npw_c)
391 0 : call sphereboundary(gbound_x, istwfk1, kg_x, mgfft, npw_x)
392 :
393 0 : ABI_MALLOC(vc_sqrt_gx, (npw_x))
394 :
395 : ! Allocate g-vectors centered on k, k'
396 0 : ABI_MALLOC(kg_k, (3, mpw))
397 0 : ABI_MALLOC(kg_kp, (3, mpw))
398 :
399 0 : spin = 1
400 : associate (fs => fstab(spin))
401 0 : ABI_MALLOC_OR_DIE(ur_nkp, (nfft*nspinor, fs%bmax-fs%bmin+1), ierr)
402 0 : ABI_MALLOC_OR_DIE(ur_mk, (nfft*nspinor, fs%bmax-fs%bmin+1), ierr)
403 0 : ABI_MALLOC(cwork_ur, (nfft*nspinor))
404 :
405 : ! Read symmetrized em1 from file
406 0 : id_required = 4; ikxc = 0; approx_type = 0; option_test = 0; nkxc = 0
407 0 : ABI_MALLOC(kxcg, (nfftf, nkxc))
408 0 : scr_iomode = iomode_from_fname(screen_filepath)
409 :
410 0 : call epsm1%from_file(screen_filepath, qmesh%nibz, npw_c, comm)
411 : call epsm1%mkdump(vcp, npw_c, kg_c, nkxc, kxcg, id_required, approx_type, &
412 0 : ikxc, option_test, dtfil%fnameabo_scr, scr_iomode, nfftf, ngfft, comm)
413 :
414 0 : call epsm1%malloc_epsm1_qbz(npw_c, epsm1%nomega)
415 0 : ABI_FREE(kxcg)
416 :
417 0 : call pstat_proc%print(_PSTAT_ARGS_)
418 :
419 0 : wkk_mode = 1
420 : ! Master creates the netcdf file used to store the results of the calculation.
421 0 : if (my_rank == master) then
422 0 : NCF_CHECK(nctk_open_create(root_ncid, strcat(dtfil%filnam_ds(4), "_WKK.nc") , xmpi_comm_self))
423 0 : NCF_CHECK(cryst%ncwrite(root_ncid))
424 0 : NCF_CHECK(ebands%ncwrite(root_ncid))
425 0 : NCF_CHECK(edos%ncwrite(root_ncid))
426 :
427 : !ncerr = nctk_def_dims(ncid, [ &
428 : ! nctkdim_t("smat_bsize1", smat_bsize1), nctkdim_t("smat_bsize2", smat_bsize2) &
429 : ! ], defmode=.True.)
430 : !NCF_CHECK(ncerr)
431 : !ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
432 : ! "gwr_completed", "scf_iteration" &
433 : !])
434 : !NCF_CHECK(ncerr)
435 : !ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
436 : ! "wr_step", "gwr_boxcutmin", "cosft_duality_error", "regterm" &
437 : !])
438 : !NCF_CHECK(ncerr)
439 :
440 : !ncerr = nctk_def_arrays(ncid, [ &
441 : ! nctkarr_t("gwr_task", "char", "character_string_length"), &
442 : !])
443 : !NCF_CHECK(ncerr)
444 : !NCF_CHECK(nctk_set_datamode(ncid))
445 :
446 : !ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
447 : ! "gwr_completed", "sig_diago", "b1gw", "b2gw", "symsigma", "symchi", "scf_iteration"], &
448 : ! [0, merge(1, 0, gwr%sig_diago), gwr%b1gw, gwr%b2gw, gwr%dtset%symsigma, dtset%symchi, gwr%scf_iteration])
449 : !NCF_CHECK(ncerr)
450 :
451 : !ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: &
452 : ! "wr_step", "ecuteps", "ecut", "ecutwfn", "ecutsigx", "gwr_boxcutmin", &
453 : ! "cosft_duality_error", "regterm"], &
454 : ! [gwr%wr_step, dtset%ecuteps, dtset%ecut, dtset%ecutwfn, dtset%ecutsigx, dtset%gwr_boxcutmin, &
455 : ! gwr%ft_max_error(1), gwr%ft_max_error(2), gwr%ft_max_error(3), gwr%cosft_duality_error, regterm &
456 : ! ])
457 : !NCF_CHECK(ncerr)
458 : !NCF_CHECK(nf90_put_var(ncid, vid("gwr_task"), trim(dtset%gwr_task)))
459 :
460 0 : NCF_CHECK(nf90_close(root_ncid))
461 : end if
462 0 : call xmpi_barrier(comm)
463 :
464 : ! Open WKK.nc file and go to data mode.
465 0 : NCF_CHECK(nctk_open_modify(root_ncid, strcat(dtfil%filnam_ds(4), "_WKK.nc") , comm))
466 0 : NCF_CHECK(nctk_set_datamode(root_ncid))
467 :
468 0 : mg0 = [1, 1, 1]
469 0 : remove_exchange = .True.
470 :
471 0 : ABI_CALLOC(mu_mn, (bmin:bmax, bmin:bmax))
472 :
473 : ! Loop over k'-points in the energy window.
474 0 : do ikp_bz=1,fs%nkfs
475 0 : my_ikp = ikp_bz; my_nkp = fs%nkfs
476 :
477 0 : print_time_kp = my_rank == 0 .and. (ikp_bz <= LOG_MODK .or. mod(ikp_bz, LOG_MODK) == 0)
478 0 : if (print_time_kp) call cwtime(cpu_kp, wall_kp, gflops_kp, "start")
479 :
480 : ! The k-point and the symmetries relating the BZ k-point to the IBZ.
481 0 : kp_bz = fs%kpts(:, ikp_bz)
482 0 : ikp_ibz = fs%indkk_fs(1, ikp_bz) ; isym_kp = fs%indkk_fs(2, ikp_bz)
483 0 : trev_kp = fs%indkk_fs(6, ikp_bz); g0_kp = fs%indkk_fs(3:5,ikp_bz)
484 0 : isirr_kp = (isym_kp == 1 .and. trev_kp == 0 .and. all(g0_kp == 0))
485 0 : mapl_kp = fs%indkk_fs(:, ikp_bz)
486 :
487 0 : kp_ibz = ebands%kptns(:,ikp_ibz)
488 0 : istwf_kp_ibz = wfd%istwfk(ikp_ibz); npw_kp_ibz = wfd%npwarr(ikp_ibz)
489 :
490 : ! Get npw_kp, kg_kp for this kp_bz.
491 : call wfd%get_gvec_gbound(cryst%gmet, dtset%ecut, kp_bz, ikp_ibz, isirr_kp, dtset%nloalg, & ! in
492 0 : istwf_kp, npw_kp, kg_kp, nkpg_kp, kpg_kp, gbound_kp) ! out
493 :
494 : ! Rotate from IBZ to BZ and compute ur_nkp for all n_kp bands.
495 0 : bstart_kp = fs%bstart_cnt_ibz(1, ikp_ibz); nband_kp = fs%bstart_cnt_ibz(2, ikp_ibz); bstop_kp = bstart_kp + nband_kp - 1
496 0 : ABI_CALLOC(ug_kp, (2, npw_kp*nspinor, nband_kp))
497 : call wfd%rotate_cg(bstart_kp, nband_kp, spin, kp_ibz, npw_kp, kg_kp, istwf_kp, &
498 0 : cryst, mapl_kp, gbound_kp, work_ngfft, work, ug_kp, urs_kbz=ur_nkp)
499 0 : do ii=1, nband_kp
500 : !print *, "isirr_kp:", isirr_kp
501 : !print *, "g:", sum(ug_kp(1,:,ii)**2 + ug_kp(2,:,ii)**2)
502 : !print *, "r:", sum(abs(ur_nkp(:,ii)) ** 2) / nfft ! * cryst%ucvol /
503 : end do
504 :
505 : ! Loop over k-points in the energy window.
506 0 : do ik_bz=1,fs%nkfs
507 :
508 0 : mapl_k = fs%indkk_fs(:, ik_bz)
509 0 : ik_ibz = mapl_k(1); isym_k = mapl_k(2); trev_k = mapl_k(6); g0_k = mapl_k(3:5)
510 0 : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
511 0 : kk_ibz = ebands%kptns(:, ik_ibz)
512 0 : istwf_k_ibz = wfd%istwfk(ik_ibz); npw_k_ibz = wfd%npwarr(ik_ibz)
513 :
514 0 : kk_bz = fs%kpts(:, ik_bz)
515 0 : kk_ibz = ebands%kptns(:,ik_ibz)
516 :
517 : ! Get npw_k, kg_k for this k.
518 : call wfd%get_gvec_gbound(cryst%gmet, dtset%ecut, kk_bz, ik_ibz, isirr_k, dtset%nloalg, & ! in
519 0 : istwf_k, npw_k, kg_k, nkpg_k, kpg_k, gbound_k) ! out
520 0 : ABI_FREE(kpg_k)
521 :
522 0 : bstart_k = fs%bstart_cnt_ibz(1, ik_ibz); nband_k = fs%bstart_cnt_ibz(2, ik_ibz); bstop_k = bstart_k + nband_k - 1
523 0 : ABI_MALLOC(ug_k, (2, npw_k*nspinor))
524 0 : ABI_MALLOC(rhotwg_mn_x, (npw_x*nspinor, nband_k, nband_kp))
525 :
526 0 : do m_k=bstart_k, bstop_k
527 : ! Rotate from IBZ to BZ and compute ur_mk
528 0 : im_k = m_k - bstart_k + 1
529 : call wfd%rotate_cg(m_k, ndat1, spin, kk_ibz, npw_k, kg_k, istwf_k, &
530 0 : cryst, mapl_k, gbound_k, work_ngfft, work, ug_k, urs_kbz=ur_mk(:,im_k))
531 :
532 0 : do n_kp=bstart_kp, bstop_kp
533 0 : in_kp = n_kp - bstart_kp + 1
534 0 : cwork_ur = conjg(ur_nkp(:,in_kp)) * ur_mk(:,im_k)
535 0 : call fft_ur(npw_x, nfft, nspinor, ndat1, mgfft, ngfft, istwfk1, kg_x, gbound_x, cwork_ur, rhotwg_mn_x(:, im_k, in_kp))
536 0 : call sigtk_multiply_by_vc_sqrt("N", npw_x, nspinor, ndat1, vc_sqrt_gx, rhotwg_mn_x(:, im_k, in_kp))
537 : end do
538 : end do
539 :
540 0 : ABI_FREE(ug_k)
541 :
542 : ! Identify q and G0 where q + G0 = k_GW - k_i
543 0 : kk_diff = kk_bz - kp_bz
544 :
545 0 : call findqg0(iq_bz, g0_qq, kk_diff, qmesh%nbz, qmesh%bz, mG0)
546 :
547 : ! Find the corresponding irred qq-point in qmesh.
548 0 : call qmesh%get_bz_item(iq_bz, qq_bz, iq_ibz, isym_qq, itim_qq)
549 0 : qq_is_gamma = sum(qq_bz**2) < tol14
550 :
551 : ! Find k + q in the extended zone and extract symmetry info.
552 : ! Be careful here because there are two umklapp vectors to be considered as:
553 : !
554 : ! k + q = k_bz + g0_bz = IS(k_ibz) + g0_ibz + g0_bz
555 : !
556 : ! Get Fourier components of the Coulomb interaction in the BZ
557 : ! In 3D systems, neglecting umklapp: vc(Sq,sG) = vc(q,G) = 4pi/|q+G|**2
558 : ! The same relation holds for 0-D systems, but not in 1-D or 2D systems. It depends on S.
559 : ! NOTE: vc_sqrt_gx is dimensioned with npw_x --> use rottb table from gsph_x.
560 0 : do ig=1,npw_x
561 0 : vc_sqrt_gx(gsph_x%rottb(ig, itim_qq, isym_qq)) = vcp%vc_sqrt(ig, iq_ibz)
562 : end do
563 :
564 0 : call epsm1%rotate_iqbz(iq_bz, hscr%nomega, npw_c, gsph_c, qmesh, remove_exchange)
565 :
566 : ! Compute \sum_{gg'} (M_g^{kn,k'm})^* W_{gg'}(q) M_g'^{kn,k'm} with k' = k + q.
567 : ! TODO: nspinor
568 0 : ABI_MALLOC(rhotwg_mn_c, (npw_c*nspinor, nband_k, nband_kp))
569 0 : rhotwg_mn_c(:,:,:) = rhotwg_mn_x(1:npw_c,:,:)
570 :
571 0 : ncols = nband_k * nband_kp
572 0 : ABI_MALLOC(w_rhotwg_mn_c, (npw_c*nspinor, nband_k, nband_kp))
573 :
574 : call xgemm("N", "N", npw_c, ncols, npw_c, cone_gw, epsm1%epsm1_qbz(:,:,1), npw_c, rhotwg_mn_c(:,:,1), npw_c*nspinor, &
575 0 : czero_gw, w_rhotwg_mn_c(:,:,1), npw_c)
576 :
577 : !do in_kp=1, nband_k
578 : ! do im_k=1, nband_kq
579 : ! w_rhotwg_mn_c(:,in_kp,im_k) = matmul(epsm1%epsm1_qbz(:,:,1), rhotwg_mn_c(:,im_k,in_kp))
580 : ! end do
581 : !end do
582 : !print *, " rhotwg_mn_c", maxval(abs(rhotwg_mn_c)), maxloc(abs(rhotwg_mn_c))
583 : !print *, "w_rhotwg_mn_c:", maxval(abs(w_rhotwg_mn_c))
584 :
585 : ! Precompute delta(e - e_nkp - ef).
586 0 : do n_kp=bstart_kp, bstop_kp
587 0 : in_kp = n_kp - bstart_kp + 1
588 0 : e_nkp = ebands%eig(n_kp, ik_ibz, spin)
589 0 : e_args = e_mesh - e_nkp
590 0 : smear_nkp = 0.1_dp * eV_Ha
591 0 : wgt_nkp(:, im_k) = gaussian(e_args, smear_nkp)
592 : end do
593 :
594 0 : do n_kp=bstart_kp, bstop_kp
595 0 : in_kp = n_kp - bstart_kp + 1
596 0 : e_nkp = ebands%eig(n_kp, ikp_ibz, spin)
597 : !fs%tetra_wtk(n_kp - fs%bmin + 1, ikp_ibz)
598 0 : do m_k=bstart_k, bstop_k
599 0 : im_k = m_k - bstart_k + 1
600 0 : e_mk = ebands%eig(m_k, ik_ibz, spin)
601 : !fs%tetra_wtk(m_k - fs%bmin + 1, ik_ibz)
602 0 : smear_mk = 0.1_dp * eV_Ha
603 0 : ctmp_gwpc = xdotc(npw_c*nspinor, rhotwg_mn_c(:,im_k,in_kp), 1, w_rhotwg_mn_c(:,im_k,in_kp), 1)
604 : if (remove_exchange) then
605 0 : ctmp_gwpc = ctmp_gwpc + xdotc(npw_x*nspinor, rhotwg_mn_x(:,im_k,in_kp), 1, rhotwg_mn_x(:,im_k,in_kp), 1)
606 : end if
607 0 : ctmp_gwpc = faq * ctmp_gwpc
608 : !print *, "ctmp_gwpc:", ctmp_gwpc
609 : !mu_mn(m_k, n_kp) = mu_mn(m_k, n_kp) + &
610 : ! ctmp_gwpc * gaussian(e_mk - ebands%fermie, smear_mk) * gaussian(e_mp, smear_mk)
611 : ! Computes: A := A + alpha * x * y^T
612 : !w_ee =
613 : !call dger(ne, ne, alpha, x, incx, y, incy, w_ee, lda)
614 : end do
615 : end do
616 :
617 0 : ABI_FREE(rhotwg_mn_x)
618 0 : ABI_FREE(rhotwg_mn_c)
619 0 : ABI_FREE(w_rhotwg_mn_c)
620 : end do ! ik_bz
621 :
622 0 : if (print_time_kp) then
623 0 : call inds2str(1, "My kp-point", my_ikp, my_nkp, fs%nkfs, msg)
624 0 : call cwtime_report(msg, cpu_kp, wall_kp, gflops_kp); if (ikp_bz == LOG_MODK) call wrtout(std_out, "...", do_flush=.True.)
625 : end if
626 :
627 0 : ABI_FREE(ug_kp)
628 0 : ABI_FREE(kpg_kp)
629 : end do ! ikp_bz
630 : end associate
631 :
632 0 : ABI_FREE(ur_nkp)
633 0 : ABI_FREE(ur_mk)
634 : !end do ! my_is
635 :
636 0 : call cwtime_report(" wkk calculation", cpu_all, wall_all, gflops_all, end_str=ch10)
637 :
638 0 : call xmpi_sum(w_ee, comm, ierr)
639 0 : call xmpi_sum(mu_mn, comm, ierr)
640 :
641 : if (my_rank == master) then
642 : !do m_k=bmin, bmax
643 : ! do n_kp=bmin, bmax
644 : ! call print_arr(units, mu_mn, max_r=max_nb, max_c=max_nb)
645 : ! end do
646 : !end do
647 : !call wrtout(units, sjoin("Re mu: ", ftoa(sum(real(mu_mn)))))
648 : !call wrtout(units, sjoin("Im mu: ", ftoa(sum(aimag(mu_mn)))))
649 : end if
650 :
651 : ! Set vqk_completed to 1 so that we can easily check if restarted is needed.
652 : !if (wkk_mode /= 0) then
653 : !if (my_rank == master) then
654 : ! NCF_CHECK(nf90_put_var(root_ncid, root_vid("vqk_completed"), 1))
655 : !end if
656 0 : NCF_CHECK(nf90_close(root_ncid))
657 0 : call xmpi_barrier(comm)
658 : !end if
659 :
660 : ! Output some of the results to ab_out for testing purposes
661 : !call gstore%print_for_abitests(dtset)
662 :
663 : ! Free memory
664 0 : ABI_FREE(kg_kp)
665 0 : ABI_FREE(kg_k)
666 0 : ABI_FREE(cwork_ur)
667 0 : ABI_FREE(work)
668 0 : ABI_FREE(gbound_kp)
669 0 : ABI_FREE(gbound_k)
670 0 : ABI_FREE(gbound_c)
671 0 : ABI_FREE(gbound_x)
672 0 : ABI_FREE(vc_sqrt_gx)
673 0 : ABI_FREE(w_ee)
674 0 : ABI_FREE(e_mesh)
675 0 : ABI_FREE(e_args)
676 0 : ABI_FREE(wgt_mk)
677 0 : ABI_FREE(wgt_nkp)
678 0 : ABI_FREE(mu_mn)
679 :
680 0 : call wfd%free(); call vcp%free(); call qmesh%free(); call gsph_x%free(); call gsph_c%free(); call hscr%free(); call edos%free()
681 0 : call epsm1%free()
682 :
683 0 : do spin=1,ebands%nsppol
684 0 : call fstab(spin)%free()
685 : end do
686 0 : ABI_FREE(fstab)
687 :
688 0 : call xmpi_barrier(comm) ! This to make sure that the parallel output of WKK is completed
689 0 : call cwtime_report(" wkk_run: MPI barrier before returning.", cpu_all, wall_all, gflops_all, end_str=ch10, comm=comm)
690 :
691 : contains
692 :
693 0 : subroutine inds2str(ilevel, prefix, my_ik, my_nk, nk_tot, out_str)
694 : character(len=*),intent(in) :: prefix
695 : integer,intent(in) :: ilevel, my_ik, my_nk, nk_tot
696 : character(len=*),intent(out) :: out_str
697 :
698 0 : out_str = sjoin(prefix, itoa(my_ik), "/", itoa(my_nk), "[", itoa(nk_tot), "]")
699 0 : out_str = repeat(' ', 4 * ilevel) // trim(out_str)
700 0 : end subroutine inds2str
701 :
702 : integer function root_vid(var_name)
703 : character(len=*),intent(in) :: var_name
704 : root_vid = nctk_idname(root_ncid, var_name)
705 : end function root_vid
706 :
707 : !integer function spin_vid(var_name)
708 : ! character(len=*),intent(in) :: var_name
709 : ! spin_vid = nctk_idname(spin_ncid, var_name)
710 : !end function spin_vid
711 :
712 : end subroutine wkk_run
713 : !!***
714 :
715 : end module m_wkk
716 : !!***
|