Branch data Line data Source code
1 : : !!****m* ABINIT/m_migdal_eliashberg
2 : : !! NAME
3 : : !! m_migdal_eliashberg
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 2008-2026 ABINIT group (MG)
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !!
13 : : !! SOURCE
14 : :
15 : : #if defined HAVE_CONFIG_H
16 : : #include "config.h"
17 : : #endif
18 : :
19 : : #include "abi_common.h"
20 : :
21 : : module m_migdal_eliashberg
22 : :
23 : : use defs_basis
24 : : use m_abicore
25 : : use m_xmpi
26 : : use m_errors
27 : : use m_krank
28 : : use m_htetra
29 : : use netcdf
30 : : use m_nctk
31 : : use m_crystal
32 : : use m_dtset
33 : : use m_dtfil
34 : :
35 : : use m_time, only : cwtime, cwtime_report, sec2str
36 : : use m_fstrings, only : strcat, sjoin, itoa, ftoa, ktoa, ltoa
37 : : use m_copy, only : alloc_copy
38 : : use m_numeric_tools, only : simpson_int
39 : : use m_special_funcs, only : gaussian
40 : : use m_ebands, only : ebands_t, edos_t
41 : : use m_bz_mesh, only : kpath_t
42 : : use m_geometry, only : phdispl_cart2red_nmodes
43 : : use m_ephtk, only : ephtk_gkknu_from_atm, EPHTK_WTOL
44 : : use m_gstore, only : gstore_t
45 : :
46 : : implicit none
47 : :
48 : : private
49 : :
50 : : public :: migdal_eliashberg_iso
51 : : !public :: migdal_eliashberg_aniso
52 : :
53 : : ! Internal policy for mode-resolved lambda on a q-path. When enabled, all
54 : : ! modes in a degenerate phonon subspace are assigned the subspace-averaged
55 : : ! lambda. The sum over the subspace is therefore preserved.
56 : : logical,parameter :: average_lambda_qpath_degenerate = .True.
57 : : real(dp),parameter :: lambda_qpath_degen_tol = tol6
58 : : !!***
59 : :
60 : : !----------------------------------------------------------------------
61 : :
62 : : !!****t* m_migdal_eliashberg/iso_solver_t
63 : : !! NAME
64 : : !! iso_solver_t
65 : : !!
66 : : !! FUNCTION
67 : : !!
68 : : !! NOTES
69 : : !!
70 : : !! SOURCE
71 : :
72 : : type, public :: iso_solver_t
73 : :
74 : : integer :: ntemp
75 : :
76 : : integer :: max_niter = -1
77 : : ! Maximum number of iterations.
78 : :
79 : : integer :: max_nmix = 4
80 : :
81 : : integer :: ncid
82 : :
83 : : integer :: comm = xmpi_undefined
84 : :
85 : : !integer :: niw = -1
86 : : ! Number of Matsubara frequencies.
87 : :
88 : : !real(dp) :: kt = -one
89 : : ! K * T in Ha.
90 : :
91 : : real(dp) :: tolerance = -one
92 : :
93 : : real(dp),allocatable :: zeta_iw(:), delta_iw(:)
94 : : real(dp),allocatable :: prev_zeta_iw(:), prev_delta_iw(:)
95 : : real(dp),allocatable :: delta_iw_mix(:,:)
96 : :
97 : : contains
98 : :
99 : : procedure :: free => iso_solver_free
100 : : ! Free dynamic memory
101 : :
102 : : procedure :: solve => iso_solver_solve
103 : :
104 : : end type iso_solver_t
105 : : !!***
106 : :
107 : : contains
108 : : !!***
109 : :
110 : :
111 : : !----------------------------------------------------------------------
112 : :
113 : : !!****f* m_migdal_eliashberg/migdal_eliashberg_iso
114 : : !! NAME
115 : : !! migdal_eliashber_iso
116 : : !!
117 : : !! FUNCTION
118 : : !!
119 : : !! INPUTS
120 : : !!
121 : : !! OUTPUT
122 : : !!
123 : : !! SOURCE
124 : :
125 : 0 : subroutine migdal_eliashberg_iso(gstore, dtset, dtfil)
126 : :
127 : : !Arguments ------------------------------------
128 : : !scalars
129 : : type(dataset_type),intent(in) :: dtset
130 : : type(datafiles_type),intent(in) :: dtfil
131 : : type(gstore_t),target,intent(inout) :: gstore
132 : :
133 : : !Local variables-------------------------------
134 : : !scalars
135 : : integer,parameter :: master = 0
136 : : integer :: nproc, my_rank, ierr, itemp, ntemp, niw, ncid, iw, spin
137 : : integer :: edos_intmeth
138 : : !integer :: spin, natom3, cnt !, band, ib, nb, my_ik, my_iq, my_is
139 : : !integer :: ik_ibz, ik_bz, ebands_timrev, iq_bz, iq_ibz !, ikq_ibz, ikq_bz
140 : : !integer :: ncid, spin_ncid, ncerr, gstore_fform
141 : : integer :: phmesh_size, units(2) !, iw
142 : : real(dp) :: kt, wmax, cpu, wall, gflops, edos_step, edos_broad, lambda_iso, omega_log, omega_2, alpha !, sigma, ecut, eshift, eig0nk
143 : : character(len=500) :: msg
144 : : class(crystal_t),pointer :: cryst
145 : : class(ebands_t),pointer :: ebands
146 : 0 : type(iso_solver_t) :: iso
147 : 0 : type(edos_t) :: edos
148 : : !arrays
149 : 0 : real(dp),allocatable :: ktmesh(:), lambda_ij(:), imag_w(:), imag_2w(:), phmesh(:), a2fw(:), a2fw_raw(:)
150 : 0 : real(dp),allocatable :: a2f_1mom(:), a2f_1mom_int(:)
151 : 0 : real(dp),allocatable :: phfreq_qibz(:,:), phlambda_qibz(:,:,:)
152 : 0 : real(dp),allocatable :: qpath(:,:), phfreq_qpath(:,:), phdispl_cart_qpath(:,:,:,:), phlambda_qpath(:,:,:)
153 : : !----------------------------------------------------------------------
154 : :
155 : 0 : nproc = xmpi_comm_size(gstore%comm); my_rank = xmpi_comm_rank(gstore%comm)
156 [ # # ]: 0 : units = [std_out, ab_out]
157 : :
158 : 0 : call cwtime(cpu, wall, gflops, "start")
159 : 0 : call wrtout(units, " Solving isotropic Migdal-Eliashberg equations on the imaginary axis", pre_newlines=2)
160 : :
161 : 0 : cryst => gstore%cryst; ebands => gstore%ebands
162 : : !natom3 = 3 * cryst%natom; nsppol = ebands%nsppol
163 : :
164 : : ! Consistency check
165 : 0 : ierr = 0
166 [ # # ]: 0 : ABI_CHECK_NOSTOP(gstore%kzone == "bz", "gstore_kzone == 'bz' is required", ierr)
167 [ # # # # : 0 : ABI_CHECK_NOSTOP(any(gstore%qzone == ["bz ", "ibz"]), "gstore_qzone must be 'bz' or 'ibz'", ierr)
# # ]
168 [ # # ]: 0 : ABI_CHECK(ierr == 0, "Wrong gstore object for migdal_eliashberg_iso. See messages above")
169 : :
170 : : ! Compute electron DOS.
171 : 0 : call dtset%get_edos_params(edos_intmeth, edos_step, edos_broad)
172 : 0 : edos = ebands%get_edos(cryst, edos_intmeth, edos_step, edos_broad, gstore%comm)
173 : :
174 : : ! A disentangled Wannier Hamiltonian generally spans only a subspace of the
175 : : ! original bands. In this case ebands%nelect still describes the complete
176 : : ! ab-initio manifold, so locating eF by integrating the DOS can fail (e.g. a
177 : : ! four-band model with nelect = 8 appears completely filled). The electronic
178 : : ! delta functions used below are centered at ebands%fermie, copied from the
179 : : ! ab-initio bands, hence evaluate N(eF) at the same chemical potential.
180 [ # # # # ]: 0 : if (edos%ief == 0 .and. gstore%has_wannier) then
181 : 0 : iw = int((ebands%fermie - edos%mesh(1)) / edos%step) + 1
182 [ # # # # ]: 0 : ABI_CHECK(iw >= 1 .and. iw < edos%nw, "The ab-initio Fermi level lies outside the energy range of the Wannier-interpolated bands")
183 : 0 : alpha = (ebands%fermie - edos%mesh(iw)) / edos%step
184 [ # # ]: 0 : do spin=0,edos%nsppol
185 : 0 : edos%gef(spin) = (one - alpha) * edos%dos(iw,spin) + alpha * edos%dos(iw+1,spin)
186 : 0 : edos%ghf(spin) = edos%gef(spin)
187 : : end do
188 : 0 : edos%ief = iw
189 : 0 : edos%ihf = iw
190 : 0 : call wrtout(units, " Using the ab-initio Fermi level to evaluate the DOS of the Wannier band subspace.")
191 : : end if
192 : :
193 : : !! Store DOS per spin channel
194 : : !n0(:) = edos%gef(1:edos%nsppol)
195 [ # # ]: 0 : if (my_rank == master) then
196 : 0 : call edos%print(units)
197 : : !path = strcat(dtfil%filnam_ds(4), "_EDOS")
198 : : !call wrtout(ab_out, sjoin("- Writing electron DOS to file:", path, ch10))
199 : : !call edos%write(path)
200 : : end if
201 : :
202 : : ! Compute phonon frequency mesh.
203 : 0 : call gstore%ifc%get_phmesh(dtset%ph_wstep, phmesh_size, phmesh)
204 : :
205 : : ! Compute Eliashberg function a2F(w)
206 [ # # # # : 0 : ABI_MALLOC(a2fw, (phmesh_size))
# # # # #
# # # ]
207 : 0 : call get_a2fw(gstore, edos%gef(0), phmesh_size, phmesh, a2fw, phfreq_qibz, phlambda_qibz)
208 : :
209 : : ! Compute mode-resolved lambda on the phonon q-path when the matrix
210 : : ! elements can be evaluated at arbitrary q with Wannier interpolation.
211 : 0 : call get_lambda_qpath_wan(gstore, dtset, edos%gef(0), qpath, phfreq_qpath, phdispl_cart_qpath, phlambda_qpath)
212 : :
213 : : ! Save results.
214 : 0 : ncid = nctk_noid
215 [ # # ]: 0 : if (my_rank == master) then
216 : 0 : call alloc_copy(a2fw, a2fw_raw)
217 [ # # ]: 0 : ABI_CHECK(edos%gef(0) > zero, "The electronic DOS at the Fermi level must be positive")
218 [ # # ]: 0 : a2fw = a2fw / (edos%gef(0) / two)
219 : :
220 [ # # # # : 0 : ABI_MALLOC(a2f_1mom, (phmesh_size))
# # # # ]
221 [ # # # # : 0 : ABI_MALLOC(a2f_1mom_int, (phmesh_size))
# # # # ]
222 [ # # ]: 0 : a2f_1mom = zero
223 [ # # # # ]: 0 : where (phmesh > tol12) a2f_1mom = a2fw / phmesh
224 : 0 : call simpson_int(phmesh_size, dtset%ph_wstep, a2f_1mom, a2f_1mom_int)
225 : 0 : lambda_iso = two * a2f_1mom_int(phmesh_size)
226 : 0 : write(msg, "(a,es16.8)")" Isotropic lambda from a2F(w): ", lambda_iso
227 : 0 : call wrtout(units, msg)
228 : :
229 [ # # ]: 0 : ABI_CHECK(lambda_iso > zero, "Cannot compute omega_log because the isotropic lambda is not positive")
230 [ # # ]: 0 : a2f_1mom = zero
231 [ # # ]: 0 : do iw=1,phmesh_size
232 [ # # ]: 0 : if (phmesh(iw) > tol12) a2f_1mom(iw) = a2fw(iw) * log(phmesh(iw)) / phmesh(iw)
233 : : end do
234 : 0 : call simpson_int(phmesh_size, dtset%ph_wstep, a2f_1mom, a2f_1mom_int)
235 : 0 : omega_log = exp(two * a2f_1mom_int(phmesh_size) / lambda_iso)
236 : 0 : write(msg, "(a,es16.8,a,es16.8,a)")" Isotropic omega_log from a2F(w): ", omega_log, &
237 : 0 : " (Ha), ", omega_log * Ha_K, " (K)"
238 : 0 : call wrtout(units, msg)
239 : :
240 : : ! Allen-Dynes square-root second moment:
241 : : ! omega_2^2 = (2 / lambda) integral dw w a2F(w).
242 [ # # # # : 0 : a2f_1mom = phmesh * a2fw
# # # # ]
243 : 0 : call simpson_int(phmesh_size, dtset%ph_wstep, a2f_1mom, a2f_1mom_int)
244 : 0 : omega_2 = sqrt(two * a2f_1mom_int(phmesh_size) / lambda_iso)
245 : 0 : write(msg, "(a,es16.8,a,es16.8,a)")" Isotropic omega_2 from a2F(w): ", omega_2, &
246 : 0 : " (Ha), ", omega_2 * Ha_K, " (K)"
247 : 0 : call wrtout(units, msg)
248 [ # # ]: 0 : ABI_FREE(a2f_1mom)
249 : 0 : ABI_FREE(a2f_1mom_int)
250 : :
251 [ # # ]: 0 : NCF_CHECK(nctk_open_create(ncid, strcat(dtfil%filnam_ds(4), "_ISOME.nc") , xmpi_comm_self))
252 [ # # ]: 0 : NCF_CHECK(cryst%ncwrite(ncid))
253 [ # # ]: 0 : NCF_CHECK(ebands%ncwrite(ncid))
254 [ # # ]: 0 : NCF_CHECK(edos%ncwrite(ncid))
255 : 0 : call isome_ncwrite_spectral(ncid, dtset, gstore, phmesh_size, phmesh, a2fw_raw, a2fw, edos%gef(0), omega_2)
256 : 0 : call isome_ncwrite_qibz(ncid, gstore, phfreq_qibz, phlambda_qibz)
257 [ # # ]: 0 : if (allocated(qpath)) then
258 : 0 : call isome_ncwrite_qpath(ncid, qpath, phfreq_qpath, phdispl_cart_qpath, phlambda_qpath)
259 : : end if
260 [ # # ]: 0 : ABI_FREE(a2fw_raw)
261 : : end if
262 : :
263 [ # # ]: 0 : ABI_SFREE(qpath)
264 [ # # ]: 0 : ABI_SFREE(phfreq_qpath)
265 [ # # ]: 0 : ABI_SFREE(phdispl_cart_qpath)
266 [ # # ]: 0 : ABI_SFREE(phlambda_qpath)
267 [ # # ]: 0 : ABI_FREE(phfreq_qibz)
268 [ # # ]: 0 : ABI_FREE(phlambda_qibz)
269 [ # # ]: 0 : ABI_FREE(a2fw)
270 [ # # ]: 0 : ABI_FREE(phmesh)
271 : 0 : call edos%free()
272 : :
273 : 0 : call dtset%get_ktmesh(ntemp, ktmesh)
274 : :
275 : : !NVHPC and LLVM don't like using this constructor because allocatable arrays aren't set.
276 : : #if defined FC_NVHPC || defined FC_LLVM
277 : : iso%ntemp=ntemp
278 : : iso%max_niter=10
279 : : iso%tolerance=tol10
280 : : iso%ncid=ncid
281 : : iso%comm=gstore%comm
282 : : #else
283 : 0 : iso = iso_solver_t(ntemp=ntemp, max_niter=10, tolerance=tol10, ncid=ncid, comm=gstore%comm)
284 : : #endif
285 : :
286 [ # # ]: 0 : do itemp=1,ntemp
287 : : ! Generate Matsubara mesh for this T with cutoff wmax.
288 : 0 : kt = ktmesh(itemp)
289 : 0 : wmax = one
290 [ # # ]: 0 : call matsubara_mesh("bosons", kt, wmax, niw, imag_w)
291 : :
292 : : ! Compute lambda(w_i - w_j)
293 [ # # # # : 0 : ABI_MALLOC(lambda_ij, (2 * niw))
# # # # #
# # # #
# ]
294 [ # # # # : 0 : ABI_MALLOC(imag_2w, (2 * niw))
# # # # ]
295 : :
296 : : !call wrtout(std_out, " Computing lambda_iso_iw...")
297 : : !call get_lambda_iso_iw(gstore, 2 * niw, imag_2w, lambda_ij)
298 [ # # ]: 0 : ABI_FREE(imag_2w)
299 : :
300 : : !call iso%solve(itemp, kt, niw, imag_w, lambda_ij)
301 [ # # ]: 0 : ABI_FREE(lambda_ij)
302 [ # # ]: 0 : ABI_FREE(imag_w)
303 : : end do ! itemp
304 : :
305 [ # # ]: 0 : if (my_rank == master) then
306 [ # # ]: 0 : NCF_CHECK(nf90_close(ncid))
307 : : end if
308 : :
309 [ # # ]: 0 : ABI_FREE(ktmesh)
310 : 0 : call iso%free()
311 : :
312 : 0 : call cwtime_report(" migdal_eliashberg_iso:", cpu, wall, gflops)
313 : :
314 [ # # # # : 0 : end subroutine migdal_eliashberg_iso
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
315 : : !!***
316 : :
317 : : !----------------------------------------------------------------------
318 : :
319 : : !!****f* m_migdal_eliashberg/isome_ncwrite_spectral
320 : : !! NAME
321 : : !! isome_ncwrite_spectral
322 : : !!
323 : : !! FUNCTION
324 : : !! Write the first revision of the spectral section of the ISOME.nc file.
325 : : !! The raw matrix-element spectral sum is stored together with the
326 : : !! provisionally DOS-normalized Eliashberg function so that the normalization
327 : : !! can be audited without recomputing the electron-phonon matrix elements.
328 : : !!
329 : : !! INPUTS
330 : : !! ncid=NetCDF file identifier, opened on xmpi_comm_self by the master rank.
331 : : !! dtset<dataset_type>=Input variables.
332 : : !! gstore<gstore_t>=Electron-phonon matrix-element container.
333 : : !! nomega=Number of points in the phonon-frequency mesh.
334 : : !! omega(nomega)=Phonon-frequency mesh in Hartree.
335 : : !! a2f_raw(nomega)=Raw matrix-element spectral sum.
336 : : !! a2f(nomega)=DOS-normalized Eliashberg function.
337 : : !! edos_fermie=Total electronic DOS at the Fermi level.
338 : : !! omega_2=Allen-Dynes square-root second moment in Hartree.
339 : : !!
340 : : !! SOURCE
341 : :
342 : 0 : subroutine isome_ncwrite_spectral(ncid, dtset, gstore, nomega, omega, a2f_raw, a2f, edos_fermie, omega_2)
343 : :
344 : : !Arguments ------------------------------------
345 : : !scalars
346 : : integer,intent(in) :: ncid, nomega
347 : : real(dp),intent(in) :: edos_fermie, omega_2
348 : : type(dataset_type),intent(in) :: dtset
349 : : type(gstore_t),intent(in) :: gstore
350 : : !arrays
351 : : real(dp),intent(in) :: omega(nomega), a2f_raw(nomega), a2f(nomega)
352 : :
353 : : !Local variables-------------------------------
354 : : !scalars
355 : : integer :: ncerr
356 : : !----------------------------------------------------------------------
357 : :
358 : 0 : ncerr = nctk_def_dims(ncid, nctkdim_t("a2f_nomega", nomega), defmode=.True.)
359 [ # # ]: 0 : NCF_CHECK(ncerr)
360 : :
361 : : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
362 [ # # ]: 0 : "isome_schema_version", "eph_intmeth", "ph_intmeth"])
363 [ # # ]: 0 : NCF_CHECK(ncerr)
364 : : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
365 [ # # ]: 0 : "eph_fsmear", "ph_smear", "ph_wstep", "a2f_edos_fermie", "a2f_dos_normalization", "omega_2"])
366 [ # # ]: 0 : NCF_CHECK(ncerr)
367 : :
368 : : ncerr = nctk_def_arrays(ncid, [ &
369 : : nctkarr_t("gstore_ngqpt", "int", "three"), &
370 : : nctkarr_t("eph_ngqpt_fine", "int", "three"), &
371 : : nctkarr_t("ddb_ngqpt", "int", "three"), &
372 : : nctkarr_t("a2f_mesh", "dp", "a2f_nomega"), &
373 : : nctkarr_t("a2f_values_raw", "dp", "a2f_nomega"), &
374 [ # # ]: 0 : nctkarr_t("a2f_values", "dp", "a2f_nomega")])
375 [ # # ]: 0 : NCF_CHECK(ncerr)
376 : :
377 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(ncid))
378 : : ncerr = nctk_write_iscalars(ncid, &
379 : : [character(len=nctk_slen) :: "isome_schema_version", "eph_intmeth", "ph_intmeth"], &
380 [ # # # # ]: 0 : [3, dtset%eph_intmeth, dtset%ph_intmeth])
381 [ # # ]: 0 : NCF_CHECK(ncerr)
382 : : ncerr = nctk_write_dpscalars(ncid, &
383 : : [character(len=nctk_slen) :: &
384 : : "eph_fsmear", "ph_smear", "ph_wstep", "a2f_edos_fermie", "a2f_dos_normalization", "omega_2"], &
385 [ # # # # ]: 0 : [dtset%eph_fsmear, dtset%ph_smear, dtset%ph_wstep, edos_fermie, edos_fermie / two, omega_2])
386 [ # # ]: 0 : NCF_CHECK(ncerr)
387 : :
388 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "gstore_ngqpt"), gstore%ngqpt))
389 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "eph_ngqpt_fine"), dtset%eph_ngqpt_fine))
390 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ddb_ngqpt"), dtset%ddb_ngqpt))
391 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "a2f_mesh"), omega))
392 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "a2f_values_raw"), a2f_raw))
393 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "a2f_values"), a2f))
394 : :
395 : 0 : end subroutine isome_ncwrite_spectral
396 : : !!***
397 : :
398 : : !----------------------------------------------------------------------
399 : :
400 : : !!****f* m_migdal_eliashberg/isome_ncwrite_qibz
401 : : !! NAME
402 : : !! isome_ncwrite_qibz
403 : : !!
404 : : !! FUNCTION
405 : : !! Write phonon frequencies and the normalized mode-resolved lambda(q,nu) on
406 : : !! the phonon IBZ. No averaging is applied inside degenerate subspaces;
407 : : !! their gauge-invariant contribution enters a2F through the mode sum.
408 : : !!
409 : : !! SOURCE
410 : :
411 [ # # # # ]: 0 : subroutine isome_ncwrite_qibz(ncid, gstore, phfreq, phlambda)
412 : :
413 : : !Arguments ------------------------------------
414 : : integer,intent(in) :: ncid
415 : : type(gstore_t),intent(in) :: gstore
416 : : real(dp),intent(in) :: phfreq(:,:), phlambda(:,:,:)
417 : :
418 : : !Local variables-------------------------------
419 : : integer :: ncerr, natom3
420 : : !----------------------------------------------------------------------
421 : :
422 : 0 : natom3 = size(phfreq, dim=1)
423 [ # # ]: 0 : ABI_CHECK_IEQ(size(phfreq, dim=2), gstore%nqibz, "Invalid phfreq q-IBZ dimension")
424 [ # # ]: 0 : ABI_CHECK_IEQ(size(phlambda, dim=1), natom3, "Invalid phlambda mode dimension")
425 [ # # ]: 0 : ABI_CHECK_IEQ(size(phlambda, dim=2), gstore%nqibz, "Invalid phlambda q-IBZ dimension")
426 [ # # ]: 0 : ABI_CHECK_IEQ(size(phlambda, dim=3), gstore%nsppol, "Invalid phlambda spin dimension")
427 : :
428 : : ncerr = nctk_def_dims(ncid, [nctkdim_t("isome_nqibz", gstore%nqibz), &
429 [ # # ]: 0 : nctkdim_t("isome_natom3", natom3)], defmode=.True.)
430 [ # # ]: 0 : NCF_CHECK(ncerr)
431 : : ncerr = nctk_def_arrays(ncid, [ &
432 : : nctkarr_t("qibz", "dp", "number_of_reduced_dimensions, isome_nqibz"), &
433 : : nctkarr_t("wtq", "dp", "isome_nqibz"), &
434 : : nctkarr_t("phfreq_qibz", "dp", "isome_natom3, isome_nqibz"), &
435 [ # # ]: 0 : nctkarr_t("phlambda_qibz", "dp", "isome_natom3, isome_nqibz, number_of_spins")])
436 [ # # ]: 0 : NCF_CHECK(ncerr)
437 : :
438 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(ncid))
439 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qibz"), gstore%qibz))
440 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "wtq"), gstore%wtq))
441 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phfreq_qibz"), phfreq))
442 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phlambda_qibz"), phlambda))
443 : :
444 : 0 : end subroutine isome_ncwrite_qibz
445 : : !!***
446 : :
447 : : !----------------------------------------------------------------------
448 : :
449 : : !!****f* m_migdal_eliashberg/isome_ncwrite_qpath
450 : : !! NAME
451 : : !! isome_ncwrite_qpath
452 : : !!
453 : : !! FUNCTION
454 : : !! Write phonon frequencies, displacements, and mode-resolved
455 : : !! electron-phonon coupling lambda(q,nu) along the input phonon path.
456 : : !!
457 : : !! SOURCE
458 : :
459 [ # # # # : 0 : subroutine isome_ncwrite_qpath(ncid, qpath, phfreq, phdispl_cart, phlambda)
# # # # ]
460 : :
461 : : !Arguments ------------------------------------
462 : : !scalars
463 : : integer,intent(in) :: ncid
464 : : !arrays
465 : : real(dp),intent(in) :: qpath(:,:), phfreq(:,:), phdispl_cart(:,:,:,:), phlambda(:,:,:)
466 : :
467 : : !Local variables-------------------------------
468 : : !scalars
469 : : integer :: ncerr, nqpath, natom3, nsppol
470 : : !----------------------------------------------------------------------
471 : :
472 : 0 : nqpath = size(qpath, dim=2)
473 : 0 : natom3 = size(phfreq, dim=1)
474 : 0 : nsppol = size(phlambda, dim=3)
475 : :
476 : : ncerr = nctk_def_dims(ncid, [ &
477 : : nctkdim_t("isome_nqpath", nqpath), &
478 : : nctkdim_t("number_of_phonon_modes", natom3), &
479 [ # # ]: 0 : nctkdim_t("isome_nsppol", nsppol)], defmode=.True.)
480 [ # # ]: 0 : NCF_CHECK(ncerr)
481 : :
482 [ # # ]: 0 : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "phlambda_qpath_average_degenerate"])
483 [ # # ]: 0 : NCF_CHECK(ncerr)
484 [ # # ]: 0 : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: "phlambda_qpath_degen_tol"])
485 [ # # ]: 0 : NCF_CHECK(ncerr)
486 : :
487 : : ncerr = nctk_def_arrays(ncid, [ &
488 : : nctkarr_t("qpath", "dp", "number_of_reduced_dimensions, isome_nqpath"), &
489 : : nctkarr_t("phfreq_qpath", "dp", "number_of_phonon_modes, isome_nqpath"), &
490 : : nctkarr_t("phdispl_cart_qpath", "dp", "two, number_of_phonon_modes, number_of_phonon_modes, isome_nqpath"), &
491 [ # # ]: 0 : nctkarr_t("phlambda_qpath", "dp", "number_of_phonon_modes, isome_nqpath, isome_nsppol")])
492 [ # # ]: 0 : NCF_CHECK(ncerr)
493 : :
494 [ # # ]: 0 : NCF_CHECK(nctk_set_datamode(ncid))
495 : : ncerr = nctk_write_iscalars(ncid, &
496 : : [character(len=nctk_slen) :: "phlambda_qpath_average_degenerate"], &
497 [ # # ]: 0 : [merge(1, 0, average_lambda_qpath_degenerate)])
498 [ # # ]: 0 : NCF_CHECK(ncerr)
499 [ # # ]: 0 : ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: "phlambda_qpath_degen_tol"], [lambda_qpath_degen_tol])
500 [ # # ]: 0 : NCF_CHECK(ncerr)
501 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpath"), qpath))
502 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phfreq_qpath"), phfreq))
503 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phdispl_cart_qpath"), phdispl_cart))
504 [ # # ]: 0 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phlambda_qpath"), phlambda))
505 : :
506 : 0 : end subroutine isome_ncwrite_qpath
507 : : !!***
508 : :
509 : : !----------------------------------------------------------------------
510 : :
511 : : !!****f* m_migdal_eliashberg/get_lambda_qpath_wan
512 : : !! NAME
513 : : !! get_lambda_qpath_wan
514 : : !!
515 : : !! FUNCTION
516 : : !! Compute lambda(q,nu) on the path defined by ph_qpath and ph_ndivsm.
517 : : !! The path construction is the same as in ifc_mkphbs. Arbitrary-q
518 : : !! electronic energies and matrix elements are obtained from the Wannier
519 : : !! Hamiltonian and GWAN interpolation, respectively.
520 : : !!
521 : : !! SOURCE
522 : :
523 : 0 : subroutine get_lambda_qpath_wan(gstore, dtset, edos_fermie, qpoints, phfreq, phdispl_cart, phlambda)
524 : :
525 : : !Arguments ------------------------------------
526 : : !scalars
527 : : class(gstore_t),intent(inout) :: gstore
528 : : type(dataset_type),intent(in) :: dtset
529 : : real(dp),intent(in) :: edos_fermie
530 : : !arrays
531 : : real(dp),allocatable,intent(out) :: qpoints(:,:), phfreq(:,:), phdispl_cart(:,:,:,:), phlambda(:,:,:)
532 : :
533 : : !Local variables-------------------------------
534 : : !scalars
535 : : integer,parameter :: master = 0
536 : : integer :: my_is, my_ik, my_ip, iq, ipc, nu, in_k, im_kq, ierr, my_rank
537 : : integer :: natom, natom3, nwan, nqpath, spin, ik_start, ik_stop, ikb, nkb, nk_batch
538 : : real(dp) :: weight_k, g2, fs_weight, spin_factor, cpu, wall, gflops
539 : : logical :: has_gwan
540 : 0 : type(kpath_t) :: qpath
541 : : character(len=500) :: msg
542 : : !arrays
543 : : integer :: units(2)
544 : 0 : real(dp),allocatable :: displ_cart4(:,:,:,:), displ_red4(:,:,:,:), displ_red(:,:,:)
545 : 0 : real(dp),allocatable :: gatm_real(:,:,:,:,:), gnu_real(:,:,:,:,:)
546 : 0 : real(dp),allocatable :: eig_k(:,:), eig_kq(:,:)
547 : 0 : complex(dp),allocatable :: intp_gatm(:,:,:,:), gatm_full(:,:,:,:), g_req(:,:,:,:)
548 : : !----------------------------------------------------------------------
549 : :
550 [ # # ]: 0 : units = [std_out, ab_out]
551 : :
552 [ # # # # ]: 0 : if (dtset%ph_nqpath <= 0 .or. dtset%ph_ndivsm <= 0) return
553 : :
554 : 0 : has_gwan = gstore%my_nspins > 0
555 [ # # ]: 0 : if (has_gwan) has_gwan = allocated(gstore%gqk(1)%wan%grpe_wwp)
556 [ # # ]: 0 : if (.not. has_gwan) then
557 [ # # ]: 0 : call wrtout([std_out, ab_out], " Skipping lambda(q,nu): GWAN interpolation is not available for this GSTORE.")
558 : 0 : return
559 : : end if
560 : :
561 [ # # ]: 0 : ABI_CHECK(dtset%eph_fsmear > zero, "lambda(q,nu) along a path requires a positive eph_fsmear for Gaussian Fermi-surface integration")
562 [ # # ]: 0 : ABI_CHECK(edos_fermie > zero, "The electronic DOS at the Fermi level must be positive")
563 [ # # ]: 0 : ABI_CHECK(gstore%kzone == "bz", "get_lambda_qpath_wan requires gstore_kzone = 'bz'")
564 : 0 : call cwtime(cpu, wall, gflops, "start")
565 : :
566 : 0 : natom = gstore%cryst%natom; natom3 = 3 * natom
567 : 0 : call qpath%init(dtset%ph_qpath(:,1:dtset%ph_nqpath), gstore%cryst%gprimd, dtset%ph_ndivsm)
568 : 0 : nqpath = qpath%npts
569 : :
570 [ # # # # : 0 : ABI_MALLOC(qpoints, (3, nqpath))
# # # # #
# # # #
# ]
571 [ # # # # : 0 : ABI_MALLOC(phfreq, (natom3, nqpath))
# # # # #
# # # # #
# # # # ]
572 [ # # # # : 0 : ABI_MALLOC(phdispl_cart, (2, natom3, natom3, nqpath))
# # # # #
# # # # #
# # # # #
# # # ]
573 [ # # # # : 0 : ABI_CALLOC(phlambda, (natom3, nqpath, gstore%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
574 [ # # # # : 0 : ABI_MALLOC(displ_cart4, (2, 3, natom, natom3))
# # # # #
# # # # #
# # ]
575 [ # # # # : 0 : ABI_MALLOC(displ_red4, (2, 3, natom, natom3))
# # # # #
# # # ]
576 [ # # # # : 0 : ABI_MALLOC(displ_red, (2, natom3, natom3))
# # # # #
# # # # #
# # ]
577 : :
578 [ # # # # : 0 : qpoints = qpath%points
# # # # #
# # # # #
# # ]
579 [ # # ]: 0 : do iq=1,nqpath
580 : 0 : call gstore%ifc%fourq(gstore%cryst, qpoints(:,iq), phfreq(:,iq), displ_cart4, out_displ_red=displ_red4)
581 [ # # ]: 0 : phdispl_cart(:,:,:,iq) = reshape(displ_cart4, [2, natom3, natom3])
582 : : end do
583 : :
584 : 0 : write(msg, "(a,i0,a,es12.4,a)")" Computing lambda(q,nu) at ", nqpath, &
585 : 0 : " path points with eph_fsmear: ", dtset%eph_fsmear * Ha_meV, " meV"
586 : 0 : call wrtout(units, msg, pre_newlines=1)
587 : :
588 [ # # ]: 0 : do my_is=1,gstore%my_nspins
589 : 0 : associate (gqk => gstore%gqk(my_is))
590 : 0 : spin = gqk%spin; nwan = gqk%wan%nwan
591 : 0 : ABI_CHECK_IEQ(nwan, gqk%nb_k, "Wannier and GSTORE band dimensions differ")
592 [ # # ]: 0 : ABI_CHECK_IEQ(nwan, gqk%nb_kq, "Wannier and GSTORE band dimensions differ")
593 : :
594 : 0 : nk_batch = gqk%wan%eph_kbatch_size(gqk%my_nk, natom3)
595 [ # # # # : 0 : ABI_MALLOC(intp_gatm, (nwan, nwan, gqk%my_npert, nk_batch))
# # # # #
# # # # #
# # # # #
# # # #
# ]
596 [ # # # # : 0 : ABI_MALLOC(gatm_full, (nwan, nwan, natom3, nk_batch))
# # # # #
# # # # #
# # # # #
# # # #
# ]
597 [ # # # # : 0 : ABI_MALLOC(g_req, (gqk%wan%nr_e, nwan, nwan, gqk%my_npert))
# # # # #
# # # # #
# # # # #
# # # #
# ]
598 [ # # # # : 0 : ABI_MALLOC(gatm_real, (2, nwan, nwan, 1, natom3))
# # # # #
# # # # #
# # # # #
# ]
599 [ # # # # : 0 : ABI_MALLOC(gnu_real, (2, nwan, nwan, 1, natom3))
# # # # #
# # # # #
# # ]
600 [ # # # # : 0 : ABI_MALLOC(eig_k, (nwan, nk_batch))
# # # # #
# # # # #
# # ]
601 [ # # # # : 0 : ABI_MALLOC(eig_kq, (nwan, nk_batch))
# # # # #
# # # ]
602 : :
603 [ # # ]: 0 : do iq=1,nqpath
604 [ # # ]: 0 : if (gqk%qpt_comm%skip(iq)) cycle
605 : 0 : call gstore%ifc%fourq(gstore%cryst, qpoints(:,iq), phfreq(:,iq), displ_cart4, out_displ_red=displ_red4)
606 [ # # ]: 0 : displ_red = reshape(displ_red4, [2, natom3, natom3])
607 : 0 : call gqk%wan%prepare_eph_q(qpoints(:,iq), g_req)
608 : :
609 [ # # # # : 0 : do ik_start=1,gqk%my_nk,nk_batch
# # # # ]
610 : 0 : ik_stop = min(gqk%my_nk, ik_start + nk_batch - 1); nkb = ik_stop - ik_start + 1
611 : :
612 : : ! Interpolate one bounded k block and reuse the returned electronic
613 : : ! energies in the Fermi-surface weights.
614 : : call gqk%wan%interp_eph_manyk_from_q(gstore%cryst, nkb, gqk%my_kpts(:,ik_start:ik_stop), &
615 : : qpoints(:,iq), g_req, intp_gatm(:,:,:,1:nkb), &
616 : 0 : out_eigens_k=eig_k(:,1:nkb), out_eigens_kq=eig_kq(:,1:nkb))
617 : :
618 [ # # # # : 0 : gatm_full(:,:,:,1:nkb) = czero
# # # # ]
619 [ # # ]: 0 : do ikb=1,nkb
620 [ # # ]: 0 : do ipc=1,gqk%my_npert
621 [ # # # # ]: 0 : gatm_full(:,:,gqk%my_pertcases(ipc),ikb) = intp_gatm(:,:,ipc,ikb)
622 : : end do
623 : : end do
624 [ # # ]: 0 : if (gqk%pert_comm%nproc > 1) call xmpi_sum(gatm_full(:,:,:,1:nkb), gqk%pert_comm%value, ierr)
625 : :
626 [ # # ]: 0 : do ikb=1,nkb
627 : 0 : my_ik = ik_start + ikb - 1
628 : 0 : weight_k = gqk%my_wtk(my_ik)
629 [ # # # # : 0 : gatm_real(1,:,:,1,:) = real(gatm_full(:,:,:,ikb), kind=dp)
# # ]
630 [ # # # # : 0 : gatm_real(2,:,:,1,:) = aimag(gatm_full(:,:,:,ikb))
# # ]
631 : 0 : call ephtk_gkknu_from_atm(nwan, nwan, 1, natom, gatm_real, phfreq(:,iq), displ_red, gnu_real)
632 : :
633 [ # # ]: 0 : do my_ip=1,gqk%my_npert
634 : 0 : nu = gqk%my_pertcases(my_ip)
635 [ # # ]: 0 : if (phfreq(nu,iq) < EPHTK_WTOL) cycle
636 [ # # ]: 0 : do in_k=1,nwan
637 [ # # ]: 0 : do im_kq=1,nwan
638 : 0 : g2 = gnu_real(1,im_kq,in_k,1,nu)**2 + gnu_real(2,im_kq,in_k,1,nu)**2
639 : : fs_weight = gaussian(eig_k(in_k,ikb) - gstore%ebands%fermie, dtset%eph_fsmear) * &
640 : 0 : gaussian(eig_kq(im_kq,ikb) - gstore%ebands%fermie, dtset%eph_fsmear)
641 : 0 : phlambda(nu,iq,spin) = phlambda(nu,iq,spin) + two * g2 * weight_k * fs_weight / phfreq(nu,iq)
642 : : end do
643 : : end do
644 : : end do
645 : : end do ! ikb
646 : : end do ! ik_start
647 : : end do
648 : :
649 [ # # ]: 0 : ABI_FREE(intp_gatm)
650 [ # # ]: 0 : ABI_FREE(gatm_full)
651 [ # # ]: 0 : ABI_FREE(g_req)
652 [ # # ]: 0 : ABI_FREE(gatm_real)
653 [ # # ]: 0 : ABI_FREE(gnu_real)
654 [ # # ]: 0 : ABI_FREE(eig_k)
655 [ # # # # ]: 0 : ABI_FREE(eig_kq)
656 : : end associate
657 : : end do
658 : :
659 : 0 : spin_factor = two / (gstore%nsppol * dtset%nspinor)
660 [ # # # # : 0 : phlambda = phlambda * spin_factor / edos_fermie
# # ]
661 : 0 : call xmpi_sum(phlambda, gstore%comm, ierr)
662 : 0 : if (average_lambda_qpath_degenerate) call average_lambda_degenerate_modes(nqpath, natom3, gstore%nsppol, phfreq, phlambda)
663 : :
664 : 0 : my_rank = xmpi_comm_rank(gstore%comm)
665 [ # # ]: 0 : if (my_rank == master) then
666 : 0 : call wrtout(ab_out, " Phonon frequencies and lambda(q,nu) along the q-path:", pre_newlines=1)
667 [ # # ]: 0 : do iq=1,nqpath
668 : 0 : write(msg, "(a,i0,a,3es16.8)")" q-path point ", iq, ": ", qpoints(:,iq)
669 : 0 : call wrtout(ab_out, msg)
670 : 0 : select case (gstore%nsppol)
671 : : case (1)
672 : 0 : call wrtout(ab_out, " nu omega (meV) lambda")
673 [ # # ]: 0 : do nu=1,natom3
674 : 0 : write(msg, "(i5,2x,es16.8,2x,es16.8)")nu, phfreq(nu,iq) * Ha_meV, phlambda(nu,iq,1)
675 : 0 : call wrtout(ab_out, msg)
676 : : end do
677 : : case (2)
678 : 0 : call wrtout(ab_out, " nu omega (meV) lambda_spin1 lambda_spin2")
679 [ # # ]: 0 : do nu=1,natom3
680 : 0 : write(msg, "(i5,2x,es16.8,2x,es16.8,2x,es16.8)")nu, phfreq(nu,iq) * Ha_meV, phlambda(nu,iq,1:2)
681 : 0 : call wrtout(ab_out, msg)
682 : : end do
683 : : case default
684 [ # # # ]: 0 : ABI_ERROR("Printing lambda(q,nu) supports only nsppol = 1 or 2")
685 : : end select
686 : : end do
687 : : end if
688 : :
689 [ # # ]: 0 : ABI_FREE(displ_cart4)
690 [ # # ]: 0 : ABI_FREE(displ_red4)
691 [ # # ]: 0 : ABI_FREE(displ_red)
692 : 0 : call qpath%free()
693 : 0 : call cwtime_report(" Wannier interpolation of lambda(q,nu) along q-path", cpu, wall, gflops)
694 : :
695 [ # # # # : 0 : end subroutine get_lambda_qpath_wan
# # # # #
# # # #
# ]
696 : : !!***
697 : :
698 : : !----------------------------------------------------------------------
699 : :
700 : : !!****f* m_migdal_eliashberg/average_lambda_degenerate_modes
701 : : !! NAME
702 : : !! average_lambda_degenerate_modes
703 : : !!
704 : : !! FUNCTION
705 : : !! Replace lambda(q,nu) inside each degenerate phonon subspace with its
706 : : !! arithmetic average. Frequencies are assumed to be ordered by branch,
707 : : !! as returned by ifc%fourq. The sum over every subspace is preserved.
708 : : !!
709 : : !! SOURCE
710 : :
711 : 0 : subroutine average_lambda_degenerate_modes(nqpath, nmode, nsppol, phfreq, phlambda)
712 : :
713 : : !Arguments ------------------------------------
714 : : !scalars
715 : : integer,intent(in) :: nqpath, nmode, nsppol
716 : : !arrays
717 : : real(dp),intent(in) :: phfreq(nmode,nqpath)
718 : : real(dp),intent(inout) :: phlambda(nmode,nqpath,nsppol)
719 : :
720 : : !Local variables-------------------------------
721 : : !scalars
722 : : integer :: iq, spin, first_mode, last_mode, ndeg
723 : : real(dp) :: lambda_avg
724 : : !----------------------------------------------------------------------
725 : :
726 [ # # ]: 0 : do iq=1,nqpath
727 : : first_mode = 1
728 [ # # ]: 0 : do while (first_mode <= nmode)
729 : : last_mode = first_mode
730 [ # # ]: 0 : do while (last_mode < nmode)
731 [ # # ]: 0 : if (abs(phfreq(last_mode + 1,iq) - phfreq(first_mode,iq)) > lambda_qpath_degen_tol) exit
732 : 0 : last_mode = last_mode + 1
733 : : end do
734 : :
735 : 0 : ndeg = last_mode - first_mode + 1
736 [ # # ]: 0 : if (ndeg > 1) then
737 [ # # ]: 0 : do spin=1,nsppol
738 [ # # ]: 0 : lambda_avg = sum(phlambda(first_mode:last_mode,iq,spin)) / ndeg
739 [ # # ]: 0 : phlambda(first_mode:last_mode,iq,spin) = lambda_avg
740 : : end do
741 : : end if
742 : 0 : first_mode = last_mode + 1
743 : : end do
744 : : end do
745 : :
746 : 0 : end subroutine average_lambda_degenerate_modes
747 : : !!***
748 : :
749 : : !----------------------------------------------------------------------
750 : :
751 : : !!****f* m_migdal_eliashberg/get_a2fw
752 : : !! NAME
753 : : !! get_a2fw
754 : : !!
755 : : !! FUNCTION
756 : : !! Compute the raw, mode-resolved lambda(q,nu) on the phonon IBZ and
757 : : !! construct a^2F(omega) from its weighted sum. Phonon modes are not
758 : : !! averaged when they are degenerate.
759 : : !!
760 : : !! INPUTS
761 : : !! gstore: Electron-phonon matrix elements. Electronic k-points must cover
762 : : !! the full BZ; phonon q-points may cover either the BZ or the IBZ.
763 : : !! edos_fermie: Electronic DOS at the Fermi level.
764 : : !! nw: Number of frequencies.
765 : : !! wmesh: Frequency mesh.
766 : : !!
767 : : !! OUTPUT
768 : : !! a2fw(nw): Eliashberg function in the historical raw normalization.
769 : : !! phfreq_qibz: Phonon frequencies on the q-point IBZ.
770 : : !! phlambda_qibz: DOS-normalized mode- and spin-resolved lambda(q,nu).
771 : : !!
772 : : !! SOURCE
773 : :
774 : 0 : subroutine get_a2fw(gstore, edos_fermie, nw, wmesh, a2fw, phfreq_qibz, phlambda_qibz)
775 : :
776 : : !Arguments ------------------------------------
777 : : class(gstore_t),intent(inout) :: gstore
778 : : integer,intent(in) :: nw
779 : : real(dp),intent(in) :: edos_fermie
780 : : real(dp),intent(in) :: wmesh(nw)
781 : : real(dp),intent(out) :: a2fw(nw)
782 : : real(dp),allocatable,intent(out) :: phfreq_qibz(:,:), phlambda_qibz(:,:,:)
783 : :
784 : : !Local variables-------------------------------
785 : : integer :: my_is, my_ik, my_iq, my_ip, in_k, im_kq, ierr, iq_ibz, isym_q, trev_q, nb_k, nb_kq
786 : : integer :: natom, natom3, g0_q(3), nk_batch, ik_start, ik_stop, ikb, nkb, ipc, nwan
787 : : real(dp) :: g2_qnu, wqnu, weight_k, weight_q, cpu, wall, gflops, spin_factor
788 : : logical :: isirr_q
789 : : !arrays
790 : : integer :: units(2)
791 : : real(dp) :: qpt(3)
792 : 0 : real(dp),allocatable :: dbl_delta_q(:,:,:), g2_mnkp(:,:,:,:), deltaw_nuq(:), displ_cart_dum(:,:,:,:)
793 : 0 : real(dp),allocatable :: displ_red_local(:,:,:)
794 : 0 : complex(dp),allocatable :: intp_gatm(:,:,:,:), gatm_full(:,:,:,:), g_req(:,:,:,:), gnu(:,:)
795 : : !----------------------------------------------------------------------
796 : :
797 [ # # ]: 0 : units = [std_out, ab_out]
798 : :
799 : 0 : call cwtime(cpu, wall, gflops, "start")
800 : 0 : call wrtout(units, sjoin(" Computing a^2F(w) with ph_smear:", ftoa(gstore%dtset%ph_smear * Ha_meV), "(meV)"), pre_newlines=1)
801 : :
802 [ # # ]: 0 : ABI_CHECK(gstore%kzone == "bz", "get_a2fw requires kzone == `bz`")
803 [ # # # # : 0 : ABI_CHECK(any(gstore%qzone == ["bz ", "ibz"]), "get_a2fw requires qzone == `bz` or `ibz`")
# # ]
804 [ # # ]: 0 : ABI_CHECK(any(gstore%with_cplex == [0, 1]), "get_a2fw requires with_cplex=0 or 1")
805 [ # # ]: 0 : if (gstore%with_cplex == 0) then
806 [ # # ]: 0 : ABI_CHECK(gstore%has_wannier, "get_a2fw with_cplex=0 requires a Wannier interpolator")
807 : : end if
808 [ # # ]: 0 : ABI_CHECK(edos_fermie > zero, "The electronic DOS at the Fermi level must be positive")
809 : :
810 [ # # ]: 0 : ABI_CHECK(allocated(gstore%gqk), "gstore%gqk is not allocated")
811 [ # # ]: 0 : ABI_CHECK(size(gstore%gqk) == gstore%my_nspins, "gstore%gqk is inconsistent with my_nspins")
812 : :
813 [ # # # # : 0 : ABI_MALLOC(deltaw_nuq, (nw))
# # # # #
# # # ]
814 : 0 : natom = gstore%cryst%natom
815 : 0 : natom3 = 3 * natom
816 [ # # # # : 0 : ABI_MALLOC(phfreq_qibz, (natom3, gstore%nqibz))
# # # # #
# # # # #
# # # # ]
817 [ # # # # : 0 : ABI_CALLOC(phlambda_qibz, (natom3, gstore%nqibz, gstore%nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
818 [ # # # # : 0 : ABI_MALLOC(displ_cart_dum, (2, 3, gstore%cryst%natom, natom3))
# # # # #
# # # # #
# # ]
819 [ # # ]: 0 : do iq_ibz=1,gstore%nqibz
820 : 0 : call gstore%ifc%fourq(gstore%cryst, gstore%qibz(:,iq_ibz), phfreq_qibz(:,iq_ibz), displ_cart_dum)
821 : : end do
822 [ # # ]: 0 : ABI_FREE(displ_cart_dum)
823 [ # # ]: 0 : a2fw = zero
824 : :
825 : : ! Loop over collinear spins.
826 [ # # ]: 0 : do my_is=1,gstore%my_nspins
827 : 0 : associate (gqk => gstore%gqk(my_is), cryst => gstore%cryst)
828 : 0 : if (gstore%with_cplex == 1) then
829 [ # # ]: 0 : ABI_CHECK(allocated(gqk%my_g2), "my_g2 is not allocated")
830 : : end if
831 [ # # ]: 0 : ABI_CHECK(allocated(gqk%my_wnuq), "my_wnuq is not allocated")
832 : :
833 : 0 : nb_k = gqk%nb_k; nb_kq = gqk%nb_kq
834 [ # # ]: 0 : ABI_CHECK_IEQ(nb_k, nb_kq, "gqk_dbldelta_qpt does not support nb_k != nb_kq")
835 [ # # ]: 0 : do ipc=1,gqk%my_npert
836 [ # # ]: 0 : ABI_CHECK(gqk%my_pertcases(ipc) == gqk%my_pert_start + ipc - 1, "gqk%my_pertcases is inconsistent with my_pert_start")
837 : : end do
838 : :
839 : : ! Weights for delta(e_{m k+q}) delta(e_{n k}) for my list of k-points.
840 [ # # # # : 0 : ABI_MALLOC(dbl_delta_q, (nb_kq, nb_k, gqk%my_nk))
# # # # #
# # # # #
# # # # #
# ]
841 [ # # # # : 0 : ABI_MALLOC(g2_mnkp, (nb_kq, nb_k, gqk%my_nk, gqk%my_npert))
# # # # #
# # # # #
# # # # #
# # # #
# ]
842 : :
843 [ # # ]: 0 : if (gstore%with_cplex == 0) then
844 : 0 : nwan = gqk%wan%nwan
845 : :
846 : 0 : nk_batch = gqk%wan%eph_kbatch_size(gqk%my_nk, natom3)
847 [ # # # # ]: 0 : ABI_CHECK(nk_batch >= 1 .and. nk_batch <= gqk%my_nk, "Invalid Wannier e-ph k-batch size")
848 : :
849 [ # # # # : 0 : ABI_MALLOC(intp_gatm, (nwan, nwan, gqk%my_npert, nk_batch))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
850 [ # # # # : 0 : ABI_MALLOC(gatm_full, (nwan, nwan, natom3, nk_batch))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
851 [ # # # # : 0 : ABI_MALLOC(g_req, (gqk%wan%nr_e, nwan, nwan, gqk%my_npert))
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
852 [ # # # # : 0 : ABI_MALLOC(gnu, (nwan, nwan))
# # # # #
# # # # #
# # # # ]
853 [ # # # # : 0 : ABI_MALLOC(displ_red_local, (2, natom3, gqk%my_npert))
# # # # #
# # # # #
# # # # ]
854 : : end if
855 : :
856 : : ! Loop over my q-points.
857 [ # # ]: 0 : do my_iq=1,gqk%my_nq
858 : 0 : iq_ibz = gqk%my_q2ibz(1,my_iq)
859 : 0 : isym_q = gqk%my_q2ibz(2,my_iq)
860 : 0 : trev_q = gqk%my_q2ibz(6,my_iq)
861 [ # # ]: 0 : g0_q = gqk%my_q2ibz(3:5,my_iq)
862 [ # # # # : 0 : isirr_q = isym_q == 1 .and. trev_q == 0 .and. all(g0_q == 0)
# # # # ]
863 [ # # # # ]: 0 : if (gstore%qzone == "bz" .and. .not. isirr_q) cycle
864 : :
865 : : ! Compute all integration weights for the double delta.
866 : 0 : call gqk%dbldelta_qpt(my_iq, gstore, gstore%dtset%eph_intmeth, gstore%dtset%eph_fsmear, qpt, weight_q, dbl_delta_q)
867 : :
868 [ # # ]: 0 : if (gstore%with_cplex == 1) then
869 : : ! Copy data to improve memory access in the loops below.
870 [ # # ]: 0 : do my_ip=1,gqk%my_npert
871 [ # # # # : 0 : g2_mnkp(:,:,:,my_ip) = gqk%my_g2(my_ip,:,my_iq,:,:)
# # ]
872 : : end do
873 : : else
874 : : ! Convert the symmetry-consistent phonon eigenvectors already stored
875 : : ! in gstore to reduced coordinates for the locally owned modes.
876 [ # # ]: 0 : do my_ip=1,gqk%my_npert
877 : : call phdispl_cart2red_nmodes(natom, 1, cryst%gprimd, &
878 : : gqk%my_displ_cart(:,:,:,my_ip,my_iq), &
879 : 0 : displ_red_local(:,:,my_ip:my_ip))
880 : : end do
881 : :
882 : : ! Interpolate bounded k blocks and immediately form |g_mnnu(k,q)|^2.
883 : 0 : call gqk%wan%prepare_eph_q(qpt, g_req)
884 [ # # # # : 0 : do ik_start=1,gqk%my_nk,nk_batch
# # # # ]
885 : 0 : ik_stop = min(gqk%my_nk, ik_start + nk_batch - 1)
886 : 0 : nkb = ik_stop - ik_start + 1
887 : : call gqk%wan%interp_eph_manyk_from_q(cryst, nkb, gqk%my_kpts(:,ik_start:ik_stop), qpt, &
888 : 0 : g_req, intp_gatm(:,:,:,1:nkb))
889 : :
890 [ # # # # : 0 : gatm_full(:,:,:,1:nkb) = czero
# # # # ]
891 [ # # ]: 0 : do ikb=1,nkb
892 [ # # ]: 0 : do ipc=1,gqk%my_npert
893 [ # # # # ]: 0 : gatm_full(:,:,gqk%my_pertcases(ipc),ikb) = intp_gatm(:,:,ipc,ikb)
894 : : end do
895 : : end do
896 [ # # ]: 0 : if (gqk%pert_comm%nproc > 1) call xmpi_sum(gatm_full(:,:,:,1:nkb), gqk%pert_comm%value, ierr)
897 : :
898 [ # # ]: 0 : do ikb=1,nkb
899 : 0 : my_ik = ik_start + ikb - 1
900 [ # # ]: 0 : do my_ip=1,gqk%my_npert
901 : 0 : wqnu = gqk%my_wnuq(my_ip,my_iq)
902 [ # # ]: 0 : if (wqnu < EPHTK_WTOL) then
903 [ # # # # ]: 0 : g2_mnkp(:,:,my_ik,my_ip) = zero; cycle
904 : : end if
905 [ # # # # ]: 0 : gnu = czero
906 [ # # ]: 0 : do ipc=1,natom3
907 : : gnu = gnu + gatm_full(:,:,ipc,ikb) * &
908 [ # # # # : 0 : (displ_red_local(1,ipc,my_ip) + j_dpc * displ_red_local(2,ipc,my_ip))
# # ]
909 : : end do
910 [ # # # # ]: 0 : gnu = gnu / sqrt(two * wqnu)
911 [ # # # # ]: 0 : g2_mnkp(:,:,my_ik,my_ip) = real(gnu * conjg(gnu), kind=dp)
912 : : end do
913 : : end do
914 : : end do
915 : : end if
916 : :
917 : : ! Loop over my phonon modes.
918 [ # # ]: 0 : do my_ip=1,gqk%my_npert
919 : 0 : wqnu = gqk%my_wnuq(my_ip, my_iq)
920 [ # # ]: 0 : if (wqnu < EPHTK_WTOL) cycle
921 : : ! Loop over my k-points.
922 [ # # ]: 0 : do my_ik=1,gqk%my_nk
923 : 0 : weight_k = gqk%my_wtk(my_ik)
924 : :
925 : : ! Sum over m_kq and n_k and accumulate.
926 [ # # ]: 0 : do in_k=1,nb_k
927 [ # # ]: 0 : do im_kq=1,nb_kq
928 : 0 : g2_qnu = g2_mnkp(im_kq, in_k, my_ik, my_ip)
929 : : phlambda_qibz(gqk%my_pertcases(my_ip),iq_ibz,gqk%spin) = &
930 : : phlambda_qibz(gqk%my_pertcases(my_ip),iq_ibz,gqk%spin) + two * g2_qnu * weight_k * &
931 : 0 : dbl_delta_q(im_kq, in_k, my_ik) / wqnu
932 : : end do
933 : : end do
934 : : end do
935 : : end do
936 : : end do ! my_iq
937 : :
938 [ # # ]: 0 : ABI_FREE(dbl_delta_q)
939 [ # # ]: 0 : ABI_FREE(g2_mnkp)
940 [ # # # # ]: 0 : if (gstore%with_cplex == 0) then
941 [ # # ]: 0 : ABI_FREE(intp_gatm)
942 [ # # ]: 0 : ABI_FREE(gatm_full)
943 [ # # ]: 0 : ABI_FREE(g_req)
944 [ # # ]: 0 : ABI_FREE(gnu)
945 [ # # ]: 0 : ABI_FREE(displ_red_local)
946 : : end if
947 : : end associate
948 : : end do ! my_is
949 : :
950 [ # # ]: 0 : ABI_FREE(deltaw_nuq)
951 : :
952 : : ! Normalize lambda(q,nu), then construct the normalized Eliashberg function
953 : : ! with the phonon-IBZ weights. edos_fermie is the total DOS, including spin
954 : : ! degeneracy. The factor two already present in the mode-resolved accumulator
955 : : ! is the conventional prefactor in lambda(q,nu), so do not divide the DOS by
956 : : ! two here.
957 : 0 : spin_factor = two / (gstore%nsppol * gstore%dtset%nspinor)
958 [ # # # # : 0 : phlambda_qibz = phlambda_qibz * spin_factor / edos_fermie
# # ]
959 : 0 : call xmpi_sum(phlambda_qibz, gstore%comm, ierr)
960 [ # # ]: 0 : a2fw = zero
961 [ # # ]: 0 : do iq_ibz=1,gstore%nqibz
962 [ # # ]: 0 : do my_ip=1,natom3
963 : 0 : wqnu = phfreq_qibz(my_ip,iq_ibz)
964 [ # # ]: 0 : if (wqnu < EPHTK_WTOL) cycle
965 [ # # # # ]: 0 : deltaw_nuq = gaussian(wmesh - wqnu, gstore%dtset%ph_smear)
966 [ # # # # ]: 0 : a2fw = a2fw + half * gstore%wtq(iq_ibz) * wqnu * sum(phlambda_qibz(my_ip,iq_ibz,:)) * deltaw_nuq
967 : : end do
968 : : end do
969 [ # # ]: 0 : a2fw = a2fw * (edos_fermie / two)
970 : :
971 : 0 : call cwtime_report(" get_a2fw", cpu, wall, gflops)
972 : :
973 [ # # # # : 0 : end subroutine get_a2fw
# # # # #
# # # ]
974 : : !!***
975 : :
976 : : !----------------------------------------------------------------------
977 : :
978 : : !!****f* m_migdal_eliashberg/iso_solver_free
979 : : !! NAME
980 : : !! iso_solver_free
981 : : !!
982 : : !! FUNCTION
983 : : !! Free dynamic memory
984 : : !!
985 : : !! SOURCE
986 : :
987 : 0 : subroutine iso_solver_free(iso)
988 : :
989 : : !Arguments ------------------------------------
990 : : class(iso_solver_t),intent(inout) :: iso
991 : : !----------------------------------------------------------------------
992 : :
993 [ # # ]: 0 : ABI_SFREE(iso%delta_iw)
994 [ # # ]: 0 : ABI_SFREE(iso%zeta_iw)
995 [ # # ]: 0 : ABI_SFREE(iso%prev_delta_iw)
996 [ # # ]: 0 : ABI_SFREE(iso%prev_zeta_iw)
997 [ # # ]: 0 : ABI_SFREE(iso%delta_iw_mix)
998 : :
999 : 0 : end subroutine iso_solver_free
1000 : : !!***
1001 : :
1002 : : !----------------------------------------------------------------------
1003 : :
1004 : : !!****f* m_migdal_eliashberg/iso_solver_solve
1005 : : !! NAME
1006 : : !! iso_solver_solve
1007 : : !!
1008 : : !! FUNCTION
1009 : : !!
1010 : : !! INPUTS
1011 : : !!
1012 : : !! OUTPUT
1013 : : !!
1014 : : !! SOURCE
1015 : :
1016 : 0 : subroutine iso_solver_solve(iso, itemp, kt, niw, imag_w, lambda_ij)
1017 : :
1018 : : !Arguments ------------------------------------
1019 : : !scalars
1020 : : class(iso_solver_t),intent(inout) :: iso
1021 : : integer,intent(in) :: itemp, niw
1022 : : real(dp),intent(in) :: kt
1023 : : !arrays
1024 : : real(dp),intent(in) :: imag_w(niw), lambda_ij(2 * niw)
1025 : :
1026 : : !Local variables-------------------------------
1027 : : !scalars
1028 : : integer,parameter :: master = 0
1029 : : integer :: nproc, my_rank, iter, ii, jj, converged
1030 : : real(dp) :: rr
1031 : : !arrays
1032 : 0 : real(dp),allocatable :: prev_vals(:)
1033 : :
1034 : : !----------------------------------------------------------------------
1035 : :
1036 : : ABI_UNUSED(lambda_ij)
1037 : :
1038 : 0 : nproc = xmpi_comm_size(iso%comm); my_rank = xmpi_comm_rank(iso%comm)
1039 : :
1040 [ # # # # : 0 : ABI_REMALLOC(iso%delta_iw_mix, (niw, iso%max_nmix))
# # # # #
# # # # #
# # # # #
# ]
1041 : :
1042 [ # # ]: 0 : if (itemp == 1) then
1043 : : ! Init values from scratch
1044 [ # # # # : 0 : ABI_CALLOC(iso%zeta_iw, (niw))
# # # # #
# # # # #
# # ]
1045 [ # # # # : 0 : ABI_CALLOC(iso%prev_zeta_iw, (niw))
# # # # #
# # # ]
1046 [ # # # # : 0 : ABI_CALLOC(iso%delta_iw, (niw))
# # # # #
# # # ]
1047 [ # # # # : 0 : ABI_CALLOC(iso%prev_delta_iw, (niw))
# # # # #
# # # ]
1048 : : else
1049 : : ! Init values from previous temperature. TODO: May use spline
1050 : 0 : call alloc_copy(iso%zeta_iw, prev_vals)
1051 [ # # # # : 0 : ABI_RECALLOC(iso%zeta_iw, (niw))
# # # # #
# # # # #
# # # # ]
1052 [ # # ]: 0 : ABI_MOVE_ALLOC(prev_vals, iso%prev_zeta_iw)
1053 : 0 : call alloc_copy(iso%delta_iw, prev_vals)
1054 [ # # # # : 0 : ABI_RECALLOC(iso%delta_iw, (niw))
# # # # #
# # # #
# ]
1055 [ # # ]: 0 : ABI_MOVE_ALLOC(prev_vals, iso%prev_delta_iw)
1056 : : end if
1057 : :
1058 : 0 : converged = 0
1059 [ # # ]: 0 : iter_loop: do iter=1,iso%max_niter
1060 : :
1061 [ # # ]: 0 : do ii=1,niw
1062 : : !if (mod(ii, nproc) /= my_rank) cycle ! MPI parallelism inside comm
1063 [ # # ]: 0 : do jj=1,niw
1064 : 0 : rr = one / sqrt(imag_w(jj) ** 2 + iso%prev_delta_iw(jj) ** 2)
1065 : 0 : iso%zeta_iw(ii) = iso%zeta_iw(ii) + imag_w(jj) * rr !* lambda(ii - jj)
1066 : 0 : iso%delta_iw(ii) = iso%delta_iw(ii) + rr * iso%prev_delta_iw(jj) !* (lambda(ii - jj) - mustar)
1067 : : end do
1068 : 0 : iso%zeta_iw(ii) = one + pi * kt / imag_w(ii) * iso%zeta_iw(ii)
1069 : 0 : iso%delta_iw(ii) = pi * kt * iso%delta_iw(ii) / iso%zeta_iw(ii)
1070 : : end do ! ii
1071 : :
1072 : : if (my_rank == master) then
1073 : : ! Write SCF cycle to stdout.
1074 : : ! Check for convergence.
1075 : : converged = 0
1076 : : end if
1077 : :
1078 : : if (converged == 2) exit iter_loop
1079 : :
1080 : : ! TODO: Mixing
1081 [ # # # # : 0 : iso%prev_zeta_iw = iso%zeta_iw
# # # # #
# ]
1082 [ # # # # : 0 : iso%prev_delta_iw = iso%delta_iw
# # # # #
# ]
1083 : :
1084 : : end do iter_loop
1085 : :
1086 : : ! Pade' to go to real axis
1087 : : ! Compute Delta F
1088 : : ! Compute QP DOS
1089 : :
1090 : : ! Write results to netcdf file
1091 : : if (my_rank == master) then
1092 : : end if
1093 : :
1094 [ # # ]: 0 : end subroutine iso_solver_solve
1095 : : !!***
1096 : :
1097 : : !----------------------------------------------------------------------
1098 : :
1099 : : !!****f* m_migdal_eliashberg/matsubara_mesh
1100 : : !! NAME
1101 : : !! mastubara_mesh
1102 : : !!
1103 : : !! FUNCTION
1104 : : !!
1105 : : !! INPUTS
1106 : : !!
1107 : : !! OUTPUT
1108 : : !!
1109 : : !! SOURCE
1110 : :
1111 : 0 : subroutine matsubara_mesh(bosons_or_fermions, kt, wmax, niw, imag_w)
1112 : :
1113 : : !Arguments ------------------------------------
1114 : : !scalars
1115 : : character(len=*),intent(in) :: bosons_or_fermions
1116 : : real(dp),intent(in) :: kt, wmax
1117 : : integer,intent(out) :: niw
1118 : : real(dp),allocatable,intent(out) :: imag_w(:)
1119 : :
1120 : : !Local variables-------------------------------
1121 : : integer :: nn
1122 : : !----------------------------------------------------------------------
1123 : :
1124 : 0 : select case (bosons_or_fermions)
1125 : : case ("bosons")
1126 : : ! 2 n pi kT
1127 : 0 : niw = nint(wmax / (two * pi * kt)) + 1
1128 [ # # # # : 0 : ABI_MALLOC(imag_w, (niw))
# # # # #
# # # #
# ]
1129 [ # # ]: 0 : do nn=0,niw-1
1130 : 0 : imag_w(nn + 1) = two * nn * pi * kt
1131 : : end do
1132 : :
1133 : : case ("fermions")
1134 : : ! 2 (n + 1) pi kT
1135 : 0 : niw = nint(wmax / (two * pi * kt))
1136 [ # # # # : 0 : ABI_MALLOC(imag_w, (niw))
# # # # #
# # # #
# ]
1137 [ # # ]: 0 : do nn=0,niw-1
1138 : 0 : imag_w(nn + 1) = two * (nn + 1) * pi * kt
1139 : : end do
1140 : :
1141 : : case default
1142 [ # # # ]: 0 : ABI_ERROR(sjoin("Wrong values for bosons_or_fermions:", bosons_or_fermions))
1143 : : end select
1144 : :
1145 : 0 : end subroutine matsubara_mesh
1146 : : !!***
1147 : :
1148 : : !----------------------------------------------------------------------
1149 : :
1150 : : !!****f* m_migdal_eliashberg/get_lambda_iso_iw
1151 : : !! NAME
1152 : : !! get_lambda_iso_iw
1153 : : !!
1154 : : !! FUNCTION
1155 : : !! Compute isotropic lambda along the imaginary axis
1156 : : !!
1157 : : !! NOTES
1158 : : !! This routine currently requires with_cplex=1, i.e. squared e-ph matrix
1159 : : !! elements precomputed and stored in gqk%my_g2. The with_cplex=0 on-demand
1160 : : !! Wannier backend implemented in get_a2fw is not yet supported here.
1161 : : !!
1162 : : !! INPUTS
1163 : : !!
1164 : : !! OUTPUT
1165 : : !!
1166 : : !! SOURCE
1167 : :
1168 : : subroutine get_lambda_iso_iw(gstore, nw, imag_w, lambda)
1169 : :
1170 : : !Arguments ------------------------------------
1171 : : class(gstore_t),intent(inout) :: gstore
1172 : : integer,intent(in) :: nw
1173 : : real(dp),intent(in) :: imag_w(nw)
1174 : : real(dp),intent(out) :: lambda(nw)
1175 : :
1176 : : !Local variables-------------------------------
1177 : : integer :: my_is, my_ik, my_iq, my_ip, in_k, im_kq, ierr, nb_k, nb_kq
1178 : : real(dp) :: g2, wqnu, weight_k, weight_q
1179 : : !arrays
1180 : : real(dp) :: qpt(3)
1181 : : real(dp),allocatable :: dbl_delta_q(:,:,:), g2_pmnk(:,:,:,:)
1182 : : !----------------------------------------------------------------------
1183 : :
1184 : : ABI_CHECK(gstore%qzone == "bz", "get_lambda_iso_iw assumes qzone == `bz`")
1185 : : ABI_CHECK(gstore%with_cplex == 1, "get_lambda_iso_iw requires squared e-ph matrix elements in memory (with_cplex=1)")
1186 : : !if (gstore%check_cplex_qkzone_gmode(cplex1, "bz", kzone, gmode, kfilter) result(ierr)
1187 : :
1188 : : lambda = zero
1189 : : do my_is=1,gstore%my_nspins
1190 : : associate (gqk => gstore%gqk(my_is))
1191 : : ABI_CHECK(allocated(gqk%my_g2), "my_g2 is not allocated")
1192 : : ABI_CHECK(allocated(gqk%my_wnuq), "my_wnuq is not allocated")
1193 : :
1194 : : nb_k = gqk%nb_k; nb_kq = gqk%nb_kq
1195 : : ABI_CHECK_IEQ(nb_k, nb_kq, "gqk_dbldelta_qpt does not support nb_k != nb_kq")
1196 : :
1197 : : ! Weights for delta(e_{m k+q}) delta(e_{n k}) for my list of k-points.
1198 : : ABI_MALLOC(dbl_delta_q, (nb_kq, nb_k, gqk%my_nk))
1199 : : ABI_MALLOC(g2_pmnk, (gqk%my_npert, nb_kq, nb_k, gqk%my_nk))
1200 : :
1201 : : do my_iq=1,gqk%my_nq
1202 : : ! Compute integration weights for the double delta.
1203 : : call gqk%dbldelta_qpt(my_iq, gstore, gstore%dtset%eph_intmeth, gstore%dtset%eph_fsmear, qpt, weight_q, dbl_delta_q)
1204 : :
1205 : : ! Copy data to improve memory access in the loops below.
1206 : : g2_pmnk = gqk%my_g2(:,:,my_iq,:,:)
1207 : :
1208 : : do my_ik=1,gqk%my_nk
1209 : : weight_k = gqk%my_wtk(my_ik)
1210 : : do in_k=1,nb_k
1211 : : do im_kq=1,nb_kq
1212 : : do my_ip=1,gqk%my_npert
1213 : : g2 = g2_pmnk(my_ip, im_kq, in_k, my_ik)
1214 : : ! TODO: handle wqnu ~ 0
1215 : : wqnu = gqk%my_wnuq(my_ip, my_iq)
1216 : : lambda(:) = lambda(:) + &
1217 : : two * wqnu / (imag_w(:) ** 2 + wqnu ** 2) * g2 * weight_k * weight_q * dbl_delta_q(im_kq, in_k, my_ik)
1218 : : end do
1219 : : end do
1220 : : end do
1221 : : end do
1222 : : end do ! my_iq
1223 : :
1224 : : ABI_FREE(dbl_delta_q)
1225 : : ABI_FREE(g2_pmnk)
1226 : : end associate
1227 : : end do ! my_is
1228 : :
1229 : : ! Take into account collinear spin
1230 : : lambda = lambda * (two / (gstore%nsppol * gstore%dtset%nspinor))
1231 : : call xmpi_sum(lambda, gstore%comm, ierr)
1232 : :
1233 : : end subroutine get_lambda_iso_iw
1234 : : !!***
1235 : :
1236 [ # # # # : 0 : end module m_migdal_eliashberg
# # # # #
# # # # #
# # # # #
# # # ]
1237 : : !!***
|