Branch data Line data Source code
1 : : !!****m* ABINIT/m_phgamma
2 : : !! NAME
3 : : !!
4 : : !! FUNCTION
5 : : !! Computation of phonon linewidths, isotropic superconducting properties,
6 : : !! and transport properties in metals within the LOVA approximation
7 : : !! to the linearized Boltzmann equation.
8 : : !!
9 : : !! COPYRIGHT
10 : : !! Copyright (C) 2008-2026 ABINIT group (MG)
11 : : !! This file is distributed under the terms of the
12 : : !! GNU General Public License, see ~abinit/COPYING
13 : : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : : !!
15 : : !! TODO
16 : : !! 1) Implement restart capabilities (eph_restart).
17 : : !! 2) Sum over the IBZ(q) on the FS instead of full BZ.
18 : : !! 3) Gaussian adaptive smearing for double delta (tetra version from libtetrabz really slow!).
19 : : !! 4) Automatic detections of energy window, improve filtering techniques.
20 : : !! 5) Interface with KERANGE trick
21 : : !! 6) More examples and tutorials (using precomputed Netcdf files).
22 : : !! 7) Implement SKW interpolation for ph linewidths and/or linear interpolation (I don't trust plain Fourier interpolation).
23 : : !! 8) Perform more benchmarks with dense meshes to detect hotspots and memory bottlenecks.
24 : : !! 9) Test spin and SOC.
25 : : !!
26 : : !! SOURCE
27 : :
28 : : #if defined HAVE_CONFIG_H
29 : : #include "config.h"
30 : : #endif
31 : :
32 : : #include "abi_common.h"
33 : :
34 : : module m_phgamma
35 : :
36 : : use, intrinsic :: iso_c_binding
37 : : use defs_basis
38 : : use m_abicore
39 : : use m_xmpi
40 : : use m_errors
41 : : use m_krank
42 : : use m_htetra
43 : : use m_tetrahedron
44 : : use libtetrabz
45 : : use m_ifc
46 : : use m_ebands
47 : : use m_fstab
48 : : use m_nctk
49 : : use netcdf
50 : : use m_wfk
51 : : use m_ddb
52 : : use m_ddk
53 : : use m_dvdb
54 : : use m_crystal
55 : : use m_fft
56 : : use m_hamiltonian
57 : : use m_pawcprj
58 : : use m_dtset
59 : : use m_dtfil
60 : : use m_ephtk
61 : : use m_mkffnl
62 : :
63 : : use defs_abitypes, only : mpi_type
64 : : use defs_datatypes, only : pseudopotential_type
65 : : use m_time, only : cwtime, cwtime_report
66 : : use m_fstrings, only : toupper, itoa, sjoin, ktoa, ltoa, strcat
67 : : use m_numeric_tools, only : arth, wrap2_pmhalf, simpson_int, simpson, mkherm, get_diag, isdiagmat
68 : : use m_io_tools, only : open_file, iomode_from_fname
69 : : use m_symtk, only : littlegroup_q
70 : : use m_geometry, only : normv
71 : : use m_special_funcs, only : gaussian
72 : : use m_fftcore, only : ngfft_seq, get_kg
73 : : use m_cgtools, only : cg_zdotc
74 : : use m_kg, only : getph, mkkpg
75 : : use m_dynmat, only : symdyma, ftgam_init, ftgam, asrif9
76 : : use m_bz_mesh, only : kpath_t
77 : : use m_special_funcs, only : fermi_dirac
78 : : use m_kpts, only : kpts_ibz_from_kptrlatt, tetra_from_kptrlatt, kpts_timrev_from_kptopt, kpts_map
79 : : use defs_elphon, only : complete_gamma !, complete_gamma_tr
80 : : use m_getgh1c, only : getgh1c, rf_transgrid_and_pack
81 : : use m_pawang, only : pawang_type
82 : : use m_pawrad, only : pawrad_type
83 : : use m_pawtab, only : pawtab_type
84 : : use m_pawfgr, only : pawfgr_type
85 : : use m_wfd, only : wfd_t
86 : : use m_pstat, only : pstat_proc
87 : : use m_lgroup, only : lgroup_t
88 : : use m_abi_linalg, only : abi_gpu_xgemm_d
89 : :
90 : : implicit none
91 : :
92 : : private
93 : : !!***
94 : :
95 : : public :: eph_phgamma
96 : : public :: find_ewin
97 : :
98 : : !----------------------------------------------------------------------
99 : :
100 : : !!****t* m_phgamma/phgamma_t
101 : : !! NAME
102 : : !! phgamma_t
103 : : !!
104 : : !! FUNCTION
105 : : !! Provides methods for computing phonon linewidths, interpolating the results
106 : : !! in q-space and evaluate superconducting properties within the isotropic formalism.
107 : : !!
108 : : !! SOURCE
109 : :
110 : : type,public :: phgamma_t
111 : :
112 : : integer :: natom = -1
113 : : ! Number of atoms per unit cell.
114 : :
115 : : integer :: natom3 = -1
116 : : ! Number of phonon branches i.e. 3*natom.
117 : :
118 : : integer :: nsppol = -1
119 : : ! Number of independent spin polarizations.
120 : :
121 : : integer :: nspinor = -1
122 : : ! Number of spinorial components.
123 : :
124 : : integer :: nqibz = -1
125 : : ! Number of q-points in the IBZ.
126 : :
127 : : integer :: my_nqibz = -1
128 : : ! Number of q-points in the IBZ treated by the current MPI processor
129 : :
130 : : integer :: nqbz = -1
131 : : ! Number of q-points in the BZ.
132 : :
133 : : integer :: eph_scalprod = 0
134 : : ! This to call anaddb routines. Note that eph_scalprod 1 is not supported in eph.
135 : :
136 : : integer :: bcorr = 0
137 : : ! 1 to include Blochl correction in the tetrahedron method else 0.
138 : :
139 : : integer :: prteliash = 0
140 : : ! This flag activates the computation of the Eliashberg function.
141 : :
142 : : integer :: nrpt = -1
143 : : ! Number of R-points in the real space representation of the gamma matrices.
144 : :
145 : : integer :: symgamma
146 : : ! 1 if gamma matrices should be symmetrized by symdyma when using Fourier interpolation
147 : :
148 : : integer :: asr
149 : : ! If the "Acoustic rule" at Gamma should be enforced.
150 : :
151 : : integer :: ndir_transp = 0
152 : : ! 0 if no transport, otherwise 3.
153 : :
154 : : integer :: ngqpt(3)
155 : : ! Number of divisions in the q-mesh.
156 : :
157 : : integer :: nene = -1
158 : : ! Number of chemical potential values used for inelastic integration
159 : :
160 : : !integer :: my_nqpt
161 : : !integer,allocatable :: my_iqpt(:)
162 : :
163 : : integer :: my_nfsk_q = -1
164 : : ! Number of k-points in the FS treated by this MPI processor for a given q.
165 : : ! Computed in phgamma_setup_qpoint.
166 : :
167 : : integer,allocatable :: my_ifsk_q(:)
168 : : ! Index of the FS k-points treated by this processor for a given q
169 : : ! Computed in phgamma_setup_qpoint.
170 : :
171 : : integer :: my_nspins = -1
172 : : ! Number of spins treated by the MPI rank.
173 : :
174 : : integer,allocatable :: my_spins(:)
175 : : ! my_spins(my_nspins)
176 : : ! Indirect table giving the spin indices treated by this rank.
177 : : ! Used only the collinear case with nspinor == 1
178 : :
179 : : !integer :: my_npert
180 : : ! Number of atomic perturbations or phonon modes treated by this MPI rank.
181 : :
182 : : !integer(i1b),allocatable :: itreat_qibz(:)
183 : : ! itreat_qibz(nqibz)
184 : : ! Table used to distribute potentials over q-points in the IBZ.
185 : : ! The loop over qpts in the IBZ(k) is MPI distributed inside qpt_comm accordinging to this table.
186 : : ! 0 if this IBZ point is not treated by this proc.
187 : : ! 1 if this IBZ is treated.
188 : :
189 : : !integer,allocatable :: my_pinfo(:,:)
190 : : ! my_pinfo(3, my_npert)
191 : : ! my_pinfo(1, ip) gives the `idir` index of the ip-th perturbation.
192 : : ! my_pinfo(2, ip) gives the `ipert` index of the ip-th perturbation.
193 : : ! my_pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3
194 : :
195 : : !integer,allocatable :: pert_table(:,:)
196 : : ! pert_table(2, natom3)
197 : : ! pert_table(1, npert): rank of the processor treating this atomic perturbation.
198 : : ! pert_table(2, npert): my_ip index in my_pinfo table, -1 if this rank is not treating ipert.
199 : :
200 : : integer, allocatable :: my_iqibz(:)
201 : : ! indices of ibz iq in local array. -1 if iq does not belong to current proc
202 : :
203 : : integer, allocatable :: my_iqbz(:)
204 : : ! List of iq_ibz indices treated by current proc
205 : :
206 : : real(dp) :: enemin
207 : : ! Minimal chemical potential value used for inelastic integration Copied from fstab
208 : :
209 : : real(dp) :: deltaene
210 : : ! Chemical potential increment for inelastic integration Copied from fstab
211 : : ! for simplicity could be made equal to phonon frequency step
212 : :
213 : : real(dp) :: gprim(3,3)
214 : : ! Needed for Fourier interpolation.
215 : : ! NOTE: gprim (not gprimd) is used for all FT interpolations,
216 : : ! to be consistent with the dimensions of the rpt, which come from anaddb.
217 : :
218 : : real(dp),allocatable :: n0(:)
219 : : ! (%nsppol)
220 : : ! Density of states at the Fermi level per spin in a.u.
221 : :
222 : : real(dp),allocatable :: qibz(:,:)
223 : : ! qibz(3,nqibz)
224 : : ! Reduced coordinates of the q-points in the IBZ.
225 : :
226 : : real(dp),allocatable :: wtq(:)
227 : : ! wtq(nqibz)
228 : : ! Weights of the q-points in the IBZ (normalized to one)
229 : :
230 : : real(dp),allocatable :: qbz(:,:)
231 : : ! qbz(3,nqbz)
232 : : ! Reduced coordinates of the q-points in the BZ.
233 : :
234 : : real(dp),allocatable :: rpt(:,:)
235 : : ! rpt(3,nrpt)
236 : : ! Reduced coordinates ***in terms of rprim*** of the lattice points used
237 : : ! for the Fourier transform of the phonon linewidths.
238 : :
239 : : real(dp),allocatable :: wghatm(:,:,:)
240 : : ! wghatm(natom,natom,nrpt)
241 : : ! Weights used in the FT of the phonon linewidths.
242 : :
243 : : real(dp),allocatable :: vals_qibz(:,:,:,:,:)
244 : : ! vals_qibz(2,natom3,natom3,nqibz,nsppol)) in reduced coordinates for each q-point in the IBZ.
245 : : ! vals_qibz {\tau'\alpha',\tau\alpha} = sum over k, im_kq, in_k
246 : : ! <psi_{k+q,im_kq} | H(1)_{\tau'\alpha'} | psi_{k,in_k}>* \cdot
247 : : ! <psi_{k+q,im_kq} | H(1)_{\tau \alpha } | psi_{k,in_k}>
248 : :
249 : : !NOTE: choice to put nsppol before or after nqbz is a bit arbitrary
250 : : ! abinit uses nband,nkpt,nsppol, but here for convenience nkpt_phon,nsppol,nqbz interpolation is on qpt
251 : : !MG: I think that nsppol should be the last dimension set call to ftgam.
252 : :
253 : : real(dp),allocatable :: vals_rpt(:,:,:,:)
254 : : ! vals_rpt(2,natom3**2,nrpt,nsppol)
255 : : ! tgamma matrices in real space in reduced coordinates. Used for the Fourier interpolation.
256 : :
257 : : ! transport stuff with velocity factors
258 : : real(dp),allocatable :: vals_in_qibz(:,:,:,:,:,:)
259 : : real(dp),allocatable :: vals_out_qibz(:,:,:,:,:,:)
260 : : ! vals_XX_qibz(2,9,natom3,natom3,nqibz,nsppol)) in reduced coordinates for each q-point in the IBZ.
261 : :
262 : : real(dp),allocatable :: vals_in_rpt(:,:,:,:,:)
263 : : real(dp),allocatable :: vals_out_rpt(:,:,:,:,:)
264 : : ! vals_XX_rpt(2,9,natom3**2,nrpt,nsppol)
265 : : ! tgamma matrices in real space in reduced coordinates.
266 : :
267 : : ! gamma matrices keeping full electron energy dependency
268 : : real(dp),allocatable :: vals_ee(:,:,:,:,:,:,:)
269 : : ! vals_eew(2, nene, nene, natom3, natom3, nqibz, nsppol)
270 : :
271 : : contains
272 : :
273 : : procedure :: free => phgamma_free
274 : : ! Free memory.
275 : :
276 : : procedure :: interp => phgamma_interp
277 : : ! Interpolates the phonon linewidths.
278 : :
279 : : procedure :: eval_qibz => phgamma_eval_qibz
280 : : ! Evaluate phonon linewidths without Fourier interpolation.
281 : :
282 : : procedure :: interp_setup => phgamma_interp_setup
283 : : ! Compute the tables used for the interpolation in q-space.
284 : :
285 : : procedure :: linwid => phgamma_linwid
286 : : ! Interpolate linewidths along an arbitrary q-path.
287 : :
288 : : end type phgamma_t
289 : :
290 : : public :: phgamma_init ! Creation method.
291 : : !!***
292 : :
293 : : !----------------------------------------------------------------------
294 : :
295 : : !!****t* m_phgamma/a2fw_t
296 : : !! NAME
297 : : !! a2fw_t
298 : : !!
299 : : !! FUNCTION
300 : : !! Store the Eliashberg function a2F(w).
301 : : !!
302 : : !! SOURCE
303 : :
304 : : type,public :: a2fw_t
305 : :
306 : : integer :: nomega
307 : : ! Number of frequency points in a2f(w).
308 : :
309 : : integer :: nsppol
310 : : ! Number of independent spin polarizations.
311 : :
312 : : integer :: natom3
313 : : ! Number of phonon modes.
314 : :
315 : : integer :: nene
316 : : ! Number of chemical potential values used for inelastic integration
317 : :
318 : : real(dp) :: enemin
319 : : ! Minimal chemical potential value used for inelastic integration Copied from fstab
320 : :
321 : : real(dp) :: deltaene
322 : : ! Chemical potential increment for inelastic integration Copied from fstab
323 : : ! for simplicity could be made equal to phonon frequency step
324 : :
325 : : real(dp) :: omega_min, omega_max
326 : : ! min and Max frequency (Ha) in the linear mesh.
327 : :
328 : : real(dp) :: wstep
329 : : ! Step of the linear mesh
330 : :
331 : : real(dp) :: smear
332 : : ! Gaussian broadening used to approximated the Dirac distribution.
333 : :
334 : : integer :: nqshift
335 : : ! Number of shifts in the q-mesh
336 : :
337 : : integer :: ngqpt(3)
338 : : ! The q-mesh used for calculating vals(w).
339 : :
340 : : real(dp),allocatable :: qshift(:,:)
341 : : ! qshift(3,nqshift)
342 : : ! The shifts used to generate the q-mesh.
343 : :
344 : : real(dp),allocatable :: n0(:)
345 : : ! n0(nsppol)
346 : : ! Electronic DOS at the Fermi level.
347 : :
348 : : real(dp),allocatable :: omega(:)
349 : : ! omega(nomega)
350 : : ! Frequency mesh in Hartree (linear).
351 : :
352 : : real(dp),allocatable :: vals(:,:,:)
353 : : ! vals(nomega, 0:natom3, nsppol)
354 : : ! Eliashberg function
355 : : ! vals(w, 1:natom3, 1:nsppol): a2f(w) decomposed per phonon branch and spin
356 : : ! vals(w, 0 , 1:nsppol): a2f(w) summed over phonons modes, decomposed in spin
357 : :
358 : : real(dp),allocatable :: vals_ee(:,:,:,:)
359 : : ! vals_ee(nene,nene,nomega,nsppol)
360 : : ! Eliashberg function
361 : : ! vals(e,e',w,0,1:nsppol): a2f(e,e',w) summed over phonons modes, decomposed in spin
362 : :
363 : : real(dp),allocatable :: lambdaw(:,:,:)
364 : : ! lambda(nomega,0:natom3,nsppol)
365 : :
366 : : contains
367 : :
368 : : procedure :: init => a2fw_init !
369 : : ! Calculates the FS averaged alpha^2F(w) function.
370 : :
371 : : procedure :: free => a2fw_free
372 : : ! Free the memory allocated in the structure.
373 : :
374 : : procedure :: write => a2fw_write
375 : : ! Write alpha^2F(w) to an external file in text/netcdf format
376 : :
377 : : procedure :: get_moment => a2fw_get_moment
378 : : ! Compute moments of alpha^2F(w)/w .
379 : : end type a2fw_t
380 : : !!***
381 : :
382 : : !!****t* m_phgamma/a2fw_tr_t
383 : : !! NAME
384 : : !! a2fw_tr_t
385 : : !!
386 : : !! FUNCTION
387 : : !! Store the Eliashberg transport spectral functions:
388 : : !! a2F_trin(w, x, x')
389 : : !! a2F_trout(w, x, x')
390 : : !! a2F_tr(w, x, x') = in - out
391 : : !! a2F_tr_gen(e, e', w, x, x')
392 : : !!
393 : : !! SOURCE
394 : :
395 : : type,public :: a2fw_tr_t
396 : :
397 : : integer :: nomega
398 : : ! Number of frequency points in a2f_tr(w).
399 : :
400 : : integer :: nene
401 : : ! Number of chemical potential values used for inelastic integration
402 : : ! Number of electron points in a2f_tr_gen(e,e',w).
403 : :
404 : : integer :: nsppol
405 : : ! Number of independent spin polarizations.
406 : :
407 : : integer :: natom3
408 : : ! Number of phonon modes.
409 : :
410 : : real(dp) :: enemin
411 : : ! Minimal chemical potential value used for inelastic integration
412 : :
413 : : real(dp) :: deltaene
414 : : ! Chemical potential increment for inelastic integration
415 : :
416 : : real(dp) :: omega_min,omega_max
417 : : ! min and Max frequency (Ha) in the linear mesh.
418 : :
419 : : real(dp) :: wstep
420 : : ! Step of the linear mesh
421 : :
422 : : real(dp) :: smear
423 : : ! Gaussian broadening used to approximated the Dirac distribution.
424 : :
425 : : integer :: nqshift
426 : : ! Number of shifts in the q-mesh
427 : :
428 : : integer :: ngqpt(3)
429 : : ! The q-mesh used for calculating vals(w).
430 : :
431 : : real(dp),allocatable :: qshift(:,:)
432 : : ! qshift(3,nqshift)
433 : : ! The shifts used to generate the q-mesh.
434 : :
435 : : real(dp),allocatable :: n0(:)
436 : : ! n0(nsppol)
437 : : ! Electronic DOS at the Fermi level.
438 : :
439 : : real(dp),allocatable :: omega(:)
440 : : ! omega(nomega)
441 : : ! Frequency mesh in Hartree (linear).
442 : :
443 : : real(dp),allocatable :: vals_in(:,:,:,:,:)
444 : : real(dp),allocatable :: vals_out(:,:,:,:,:)
445 : : ! vals_in(nomega,3,3,0:natom3,nsppol)
446 : : ! Eliashberg transport functions for in and out scattering
447 : : ! vals_in(w,3,3,1:natom3,1:nsppol): a2f_tr(w) decomposed per phonon branch and spin
448 : : ! vals_in(w,3,3,0,1:nsppol): a2f_tr(w) summed over phonons modes, decomposed in spin
449 : :
450 : : real(dp),allocatable :: vals_tr(:,:,:,:,:)
451 : : ! vals_tr(nomega,3,3,0:natom3,nsppol)
452 : : ! transport spectral function = in-out
453 : :
454 : : real(dp),allocatable :: vals_tr_gen(:,:,:,:,:,:,:)
455 : : ! vals(nene,nene,nomega,3,3,nsppol)
456 : : ! generalized transport spectral function from PB Allen Phys. Rev. Lett. 59, 1460 (1987) [[cite:Allen1987]]
457 : :
458 : : real(dp),allocatable :: lambdaw_tr(:,:,:,:,:)
459 : : ! lambda(nomega,3,3,0:natom3,nsppol)
460 : :
461 : : contains
462 : :
463 : : procedure :: init => a2fw_tr_init
464 : : ! Calculates the FS averaged alpha^2F_tr,in,out(w, x, x') functions.
465 : :
466 : : procedure :: free => a2fw_tr_free
467 : : ! Free the memory allocated in the structure.
468 : :
469 : : procedure :: write => a2fw_tr_write
470 : : ! Write alpha^2F(w) to an external file in text/netcdf format
471 : :
472 : : end type a2fw_tr_t
473 : : !!***
474 : :
475 : : real(dp),private,parameter :: EPH_Q0TOL = 0.01_dp
476 : :
477 : : contains !=====================================================
478 : : !!***
479 : :
480 : : !----------------------------------------------------------------------
481 : :
482 : : !!****f* m_phgamma/phgamma_free
483 : : !! NAME
484 : : !! phgamma_free
485 : : !!
486 : : !! FUNCTION
487 : : !! Free the dynamic memory
488 : : !!
489 : : !! SOURCE
490 : :
491 : 5 : subroutine phgamma_free(gams)
492 : :
493 : : !Arguments ------------------------------------
494 : : class(phgamma_t),intent(inout) :: gams
495 : : ! *************************************************************************
496 : :
497 : : !real
498 [ + - ]: 5 : ABI_SFREE(gams%n0)
499 [ + - ]: 5 : ABI_SFREE(gams%qibz)
500 [ + - ]: 5 : ABI_SFREE(gams%wtq)
501 [ + - ]: 5 : ABI_SFREE(gams%qbz)
502 [ + - ]: 5 : ABI_SFREE(gams%rpt)
503 [ + - ]: 5 : ABI_SFREE(gams%wghatm)
504 [ + - ]: 5 : ABI_SFREE(gams%vals_qibz)
505 [ + - ]: 5 : ABI_SFREE(gams%vals_rpt)
506 [ + - ]: 5 : ABI_SFREE(gams%vals_in_qibz)
507 [ + - ]: 5 : ABI_SFREE(gams%vals_in_rpt)
508 [ + - ]: 5 : ABI_SFREE(gams%vals_out_qibz)
509 [ + - ]: 5 : ABI_SFREE(gams%vals_out_rpt)
510 [ - + ]: 5 : ABI_SFREE(gams%vals_ee)
511 [ + - ]: 5 : ABI_SFREE(gams%my_iqibz)
512 [ + - ]: 5 : ABI_SFREE(gams%my_ifsk_q)
513 [ + - ]: 5 : ABI_SFREE(gams%my_spins)
514 : :
515 : 5 : end subroutine phgamma_free
516 : : !!***
517 : :
518 : : !----------------------------------------------------------------------
519 : :
520 : : !!****f* m_phgamma/phgamma_init
521 : : !! NAME
522 : : !! phgamma_init
523 : : !!
524 : : !! FUNCTION
525 : : !! Creation method for the phgamma_t datatype.
526 : : !!
527 : : !! INPUTS
528 : : !! cryst<crystal_t>
529 : : !! ifc<ifc_type>=Interatomic force constants.
530 : : !! symdynmat=1 to activa symmetrization of gamma matrices.
531 : : !! ngqpt(3)=Q-mesh divisions
532 : : !! n0(dtset%nsppol)=Density of states at the Fermi level per spin.
533 : : !!
534 : : !! OUTPUT
535 : : !! gams<phgamma_t>
536 : : !!
537 : : !! SOURCE
538 : :
539 [ + - ]: 5 : subroutine phgamma_init(gams, cryst, ifc, ebands, fstab, dtset, eph_scalprod, ngqpt, n0, comm)
540 : :
541 : : !Arguments ------------------------------------
542 : : !scalars
543 : : class(phgamma_t),intent(out) :: gams
544 : : integer,intent(in) :: eph_scalprod, comm
545 : : type(crystal_t),intent(in) :: cryst
546 : : type(ifc_type),intent(in) :: ifc
547 : : type(ebands_t),intent(in) :: ebands
548 : : type(fstab_t), intent(in) :: fstab
549 : : type(dataset_type),intent(in) :: dtset
550 : : !arrays
551 : : integer,intent(in) :: ngqpt(3)
552 : : real(dp),intent(in) :: n0(dtset%nsppol)
553 : :
554 : : !Local variables-------------------------------
555 : : !scalars
556 : : integer :: my_rank, nproc, ierr, nsppol, natom3, qptopt, qtimrev
557 : : !arrays
558 : : integer :: qptrlatt(3,3)
559 : : ! *************************************************************************
560 : :
561 : 5 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
562 : :
563 : : ! Set basic dimensions.
564 : 5 : nsppol = dtset%nsppol; gams%nsppol = nsppol; gams%nspinor = dtset%nspinor
565 : :
566 : 5 : gams%natom = cryst%natom; gams%natom3 = 3*cryst%natom; natom3 = gams%natom3
567 : :
568 : 5 : gams%symgamma = dtset%symdynmat; gams%eph_scalprod = eph_scalprod
569 : : !gams%asr = ifc%asr
570 : 5 : gams%asr = 0
571 : 5 : gams%prteliash = dtset%prteliash
572 : :
573 [ + - ]: 5 : gams%ndir_transp = 0; if (dtset%eph_transport > 0) gams%ndir_transp = 3
574 : :
575 : : ! Copy DOS.
576 [ - + + - : 15 : ABI_MALLOC(gams%n0, (nsppol))
+ - + - -
+ - + -
+ ]
577 [ - + + + ]: 15 : gams%n0 = n0
578 : :
579 : 5 : gams%nene = fstab%nene
580 : 5 : gams%enemin = fstab%enemin
581 : 5 : gams%deltaene = fstab%deltaene
582 : :
583 : : ! Setup IBZ, weights and BZ. Always use q --> -q symmetry for phonons even in systems wo inversion
584 [ + + ]: 20 : gams%ngqpt = ngqpt
585 : 5 : qptrlatt = 0; qptrlatt(1,1) = ngqpt(1); qptrlatt(2,2) = ngqpt(2); qptrlatt(3,3) = ngqpt(3)
586 [ - + ]: 5 : qptopt = ebands%kptopt; if (dtset%qptopt /= 0) qptopt = dtset%qptopt
587 : : qtimrev = kpts_timrev_from_kptopt(qptopt)
588 : :
589 : : call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt, 1, [zero, zero, zero], &
590 [ - + - + : 5 : gams%nqibz, gams%qibz, gams%wtq, gams%nqbz, gams%qbz)
- + ]
591 : :
592 : : ! Allocate matrices in the IBZ.
593 [ - + + - : 30 : ABI_MALLOC_OR_DIE(gams%vals_qibz, (2, natom3, natom3, gams%nqibz, nsppol), ierr)
- + + - -
+ + - - +
+ - + - +
- + - + -
- + + - -
+ ]
594 [ + + + + : 1901 : gams%vals_qibz = zero
+ + + + +
+ ]
595 : :
596 [ + - ]: 5 : if (dtset%eph_transport > 0) then
597 [ - + + - : 30 : ABI_MALLOC_OR_DIE(gams%vals_in_qibz, (2, 9, natom3, natom3, gams%nqibz, nsppol), ierr)
- + + - -
+ + - - +
+ - + - +
- + - + -
- + + - -
+ ]
598 [ + + + + : 15626 : gams%vals_in_qibz = zero
+ + + + +
+ + + ]
599 [ - + + - : 30 : ABI_MALLOC_OR_DIE(gams%vals_out_qibz, (2, 9, natom3, natom3, gams%nqibz, nsppol), ierr)
- + + - -
+ + - - +
+ - + - +
- + - + -
- + + - -
+ ]
600 [ + + + + : 15626 : gams%vals_out_qibz = zero
+ + + + +
+ + + ]
601 : : end if
602 : :
603 [ - + ]: 5 : if (gams%prteliash == 3) then
604 [ # # # # : 0 : ABI_MALLOC_OR_DIE(gams%vals_ee, (2, gams%nene, gams%nene, natom3, natom3, gams%nqibz, nsppol), ierr)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
605 [ # # # # : 0 : gams%vals_ee = zero
# # # # #
# # # #
# ]
606 : : end if
607 : :
608 : : ! Prepare Fourier interpolation. gams%gprim actually holds Ifc%gprimd
609 : : ! (renamed to gprimd would ripple through this type's other uses; the
610 : : ! important invariant is that it stays paired with gams%rpt, which is
611 : : ! Ifc%rpt -- now cartesian, dual to gprimd, not the historical gprim).
612 [ + + + + ]: 65 : gams%gprim = ifc%gprimd
613 : 5 : gams%nrpt = ifc%nrpt
614 [ - + + - : 15 : ABI_MALLOC(gams%rpt, (3, gams%nrpt))
+ - + - -
+ - + -
+ ]
615 [ + - + - : 1870 : gams%rpt = ifc%rpt
- + - - -
- - - + +
+ + ]
616 [ - + + - : 25 : ABI_MALLOC(gams%wghatm, (gams%natom, gams%natom, gams%nrpt))
- + + - -
+ + - + -
+ - - + -
+ - + ]
617 [ + - + - : 1405 : gams%wghatm = ifc%wghatm
+ - - + -
- - - - -
- - + + +
+ + + ]
618 : :
619 : 5 : end subroutine phgamma_init
620 : : !!***
621 : :
622 : : !----------------------------------------------------------------------
623 : :
624 : : !!****f* m_phgamma/phgamma_ncwrite
625 : : !! NAME
626 : : !! phgamma_ncwrite
627 : : !!
628 : : !! FUNCTION
629 : : !! Write the results stored in the phgamma_t datatype to netcdf file.
630 : : !!
631 : : !! INPUTS
632 : : !! cryst<crystal_t>=Crystalline structure.
633 : : !! ifc<ifc_type>=Interatomic force constants.
634 : : !! ncid=Netcdf file handler (already open in the caller).
635 : : !!
636 : : !! SOURCE
637 : :
638 : 5 : subroutine phgamma_ncwrite(gams, cryst, ifc, ncid)
639 : :
640 : : !Arguments ------------------------------------
641 : : !scalars
642 : : class(phgamma_t),intent(inout) :: gams
643 : : type(crystal_t),intent(in) :: cryst
644 : : type(ifc_type),intent(in) :: ifc
645 : : integer,intent(in) :: ncid
646 : :
647 : : !Local variables-------------------------------
648 : : !scalars
649 : : integer :: max_nqpt = 50
650 : : integer :: iq_ibz,spin,mu, units(2)
651 : : real(dp) :: lambda_tot, cpu, wall, gflops
652 : : character(len=500) :: msg
653 : : !arrays
654 : 10 : real(dp) :: phfrq(3*cryst%natom), gamma_ph(3*cryst%natom), lambda_ph(3*cryst%natom)
655 : 10 : real(dp) :: displ_cart(2,3*cryst%natom,3*cryst%natom)
656 : : ! *************************************************************************
657 : :
658 [ + + ]: 15 : units = [std_out, ab_out]
659 : 5 : call cwtime(cpu, wall, gflops, "start")
660 : :
661 : : ! Write data to files for each q point, also compute total lambda.
662 : 5 : lambda_tot = zero
663 [ + + ]: 10 : do spin=1,gams%nsppol
664 [ + + ]: 66 : do iq_ibz=1,gams%nqibz
665 : :
666 : : ! Get phonon frequencies, gamma(q,nu) and lambda(q,nu).
667 : : ! Quantities are already summed over (collinear) spin channels if nsppol == 1.
668 : 61 : call gams%eval_qibz(cryst, ifc, iq_ibz, spin, phfrq, gamma_ph, lambda_ph, displ_cart)
669 : :
670 [ + + ]: 244 : do mu=1,gams%natom3
671 : 244 : lambda_tot = lambda_tot + lambda_ph(mu) * gams%wtq(iq_ibz)
672 : : end do
673 : :
674 : : ! Write data to netcdf file
675 [ + - ]: 61 : if (ncid /= nctk_noid) then
676 [ + - ]: 61 : if (spin == 1) then
677 [ + + - + : 183 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phfreq_qibz"), phfrq, start=[1, iq_ibz]))
- - ]
678 [ + + - + : 305 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'phdispl_cart_qibz'), displ_cart, start=[1, 1, 1, iq_ibz]))
- - ]
679 : : end if
680 [ + + - + : 244 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'phgamma_qibz'), gamma_ph, start=[1, iq_ibz, spin]))
- - ]
681 [ + + - + : 244 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'phlambda_qibz'), lambda_ph, start=[1, iq_ibz, spin]))
- - ]
682 : : end if
683 : :
684 : : ! Output to the main output file
685 [ + - ]: 66 : if (iq_ibz <= max_nqpt) then
686 [ - + ]: 61 : if (gams%nsppol == 2) then
687 : 0 : write(msg,'(2a,3es16.6,a,i1,a,a)')ch10,&
688 : 0 : ' q-point =',gams%qibz(:, iq_ibz),' spin = ',spin,ch10,&
689 : 0 : ' Mode number Frequency (Ha) Linewidth (Ha) Lambda(q,n)'
690 : : else
691 : 61 : write(msg,'(2a,3es16.6,a,a)')ch10,&
692 : 61 : ' q-point =',gams%qibz(:, iq_ibz),ch10,&
693 : 122 : ' Mode number Frequency (Ha) Linewidth (Ha) Lambda(q,n)'
694 : : end if
695 : 61 : call wrtout(units, msg)
696 [ + + ]: 244 : do mu=1,gams%natom3
697 : 183 : write(msg,'(i5,es20.6,2es16.6)')mu, phfrq(mu), gamma_ph(mu), lambda_ph(mu)
698 : 244 : call wrtout(units, msg)
699 : : end do
700 : : else
701 [ # # ]: 0 : if (iq_ibz == max_nqpt + 1) then
702 : 0 : call wrtout(units, sjoin(" No more that:", itoa(max_nqpt), " q-points are reported in the main output file"))
703 : 0 : call wrtout(units, " Use A2f.nc and AbiPy to analyze the results.")
704 : : end if
705 : : end if
706 : :
707 : : end do
708 : : ! Add blank lines to output files between spins
709 : 10 : call wrtout(units, "", do_flush=.True.)
710 : : end do
711 : :
712 : 5 : write(ab_out,"(a,f8.4)")" lambda= ",lambda_tot
713 : : !write(ab_out,"(a,f8.4)")" omega_log= ",omega_log
714 : :
715 : 5 : call cwtime_report(" phgamma_ncwrite:", cpu, wall, gflops)
716 : :
717 : 5 : end subroutine phgamma_ncwrite
718 : : !!***
719 : :
720 : : !----------------------------------------------------------------------
721 : :
722 : : !!****f* m_phgamma/tgamma_symm
723 : : !! NAME
724 : : !! tgamma_symm
725 : : !!
726 : : !! FUNCTION
727 : : !! Symmetrize the tgamma matrix
728 : : !!
729 : : !! INPUTS
730 : : !! qpt(3)=phonon wavevector in reduced coordinates.
731 : : !! cryst<crystal_t>=Crystalline structure.
732 : : !!
733 : : !! SOURCE
734 : :
735 : 14809 : subroutine tgamma_symm(cryst, qpt, tgamma)
736 : :
737 : : !Arguments ------------------------------------
738 : : !scalars
739 : : type(crystal_t),intent(in) :: cryst
740 : : !arrays
741 : : real(dp),intent(in) :: qpt(3)
742 : : real(dp),intent(inout) :: tgamma(2,3*cryst%natom,3*cryst%natom)
743 : :
744 : : !Local variables-------------------------------
745 : : !scalars
746 : : integer :: ii,natom3,k
747 : : !arrays
748 : 29618 : real(dp) :: tgcart(2,3*cryst%natom,3*cryst%natom)
749 : 14809 : real(dp) :: umat(2,3*cryst%natom,3*cryst%natom),tmp_mat(2,3*cryst%natom,3*cryst%natom)
750 : : ! *********************************************************************
751 : :
752 : : ! Build U matrix.
753 [ + + + + : 459079 : umat = zero; k = 1
+ + ]
754 [ + + ]: 29618 : do ii=1,cryst%natom
755 [ + + + + ]: 192517 : umat(1,k:k+2, k:k+2) = cryst%gprimd
756 : 29618 : k = k + 3
757 : : end do
758 : :
759 : 14809 : natom3 = 3 * cryst%natom
760 : :
761 : : ! Reduced --> Cartesian
762 : 14809 : call zgemm('N', 'N', natom3, natom3, natom3, cone, tgamma, natom3, umat, natom3, czero, tmp_mat, natom3)
763 : 14809 : call zgemm('T', 'N', natom3, natom3, natom3, cone, umat, natom3, tmp_mat, natom3, czero, tgcart, natom3)
764 : :
765 : : ! Make the matrix hermitian
766 : 14809 : call mkherm(tgcart, 3*cryst%natom)
767 : :
768 : : ! Symmetrize tgamma matrix.
769 : 14809 : call symdyma(tgcart, cryst%indsym, cryst%natom, cryst%nsym, qpt, cryst%rprimd, cryst%symrel, cryst%symafm)
770 : :
771 [ + + + + : 459079 : umat = zero; k = 1
+ + ]
772 [ + + ]: 29618 : do ii=0,cryst%natom-1
773 [ + + + + ]: 192517 : umat(1,k:k+2, k:k+2) = cryst%rprimd
774 : 29618 : k = k + 3
775 : : end do
776 : :
777 : : ! Cartesian --> Reduced
778 : 14809 : call zgemm('N', 'N', natom3, natom3, natom3, cone, tgcart, natom3, umat, natom3, czero, tmp_mat, natom3)
779 : 14809 : call zgemm('T', 'N', natom3, natom3, natom3, cone, umat, natom3, tmp_mat, natom3, czero, tgamma, natom3)
780 : :
781 : 14809 : end subroutine tgamma_symm
782 : : !!***
783 : :
784 : : !----------------------------------------------------------------------
785 : :
786 : : !!****f* m_phgamma/phgamma_eval_qibz
787 : : !! NAME
788 : : !! phgamma_eval_qibz
789 : : !!
790 : : !! FUNCTION
791 : : !! Compute the phonon linewidths for q-points in the IBZ without performing the interpolation.
792 : : !!
793 : : !! INPUTS
794 : : !! cryst<crystal_t>=Crystal structure.
795 : : !! ifc<ifc_type>=Interatomic force constants.
796 : : !! iq_ibz=Index of the q-point in the IBZ array.
797 : : !! spin=Spin index. See notes below.
798 : : !!
799 : : !! OUTPUT
800 : : !! phfrq(gams%natom3)=Phonon frequencies
801 : : !! gamma_ph(gams%natom3)=Phonon linewidths.
802 : : !! lambda_ph(gams%natom3)=coupling strength coefficients
803 : : !! displ_cart(2,3,cry%natom,3*cryst%natom)=Phonon displacement in cartesian coordinates.
804 : : !! [gamma_ph_ee]
805 : : !!
806 : : !! NOTES
807 : : !! If nsppol == 1 and nspinor == 1, lambda and gamma are already summed over the two equivalent spin channels.
808 : : !! If nsppol == 2, lambda and gamma are the particular contributions given by the input spin index.
809 : : !! Client code is responsible for assembling the final observables by summing over spins.
810 : : !!
811 : : !! SOURCE
812 : :
813 : 0 : subroutine phgamma_eval_qibz(gams, cryst, ifc, iq_ibz, spin, phfrq, gamma_ph, lambda_ph, displ_cart, gamma_ph_ee)
814 : :
815 : : !Arguments ------------------------------------
816 : : !scalars
817 : : class(phgamma_t),intent(inout) :: gams
818 : : integer,intent(in) :: iq_ibz,spin
819 : : type(crystal_t),intent(in) :: cryst
820 : : type(ifc_type),intent(in) :: ifc
821 : : !arrays
822 : : real(dp),intent(out) :: phfrq(gams%natom3),gamma_ph(gams%natom3),lambda_ph(gams%natom3)
823 : : real(dp),intent(out) :: displ_cart(2,3,cryst%natom,3*cryst%natom)
824 : : real(dp),intent(out),optional :: gamma_ph_ee(gams%nene,gams%nene,gams%natom3)
825 : :
826 : : !Local variables-------------------------------
827 : : !scalars
828 : : integer :: natom3, nu1, iene, jene
829 : : real(dp) :: spinfact
830 : : !character(len=500) :: msg
831 : : !arrays
832 : 244 : real(dp) :: displ_red(2,gams%natom3,gams%natom3), work_qnu(gams%natom3), gam_atm(2,gams%natom3,gams%natom3)
833 : : ! *************************************************************************
834 : :
835 : 122 : natom3 = gams%natom3
836 : :
837 : : ! Get phonon frequencies and eigenvectors.
838 : 122 : call ifc%fourq(cryst, gams%qibz(:,iq_ibz), phfrq, displ_cart, out_displ_red=displ_red)
839 : :
840 : : ! Scalar product with the displ_red vectors.
841 : : ! Note that the factor 1 / (2 * omega_qnu) coming from |g|^2 is absorbed in the expressions below.
842 [ + + ]: 488 : gam_atm = reshape(gams%vals_qibz(:,:,:,iq_ibz,spin), [2, natom3, natom3])
843 : 122 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, gamma_ph)
844 : :
845 [ - + - - ]: 122 : if (present(gamma_ph_ee) .and. gams%my_iqibz(iq_ibz) /= -1) then
846 [ # # ]: 0 : do iene = 1, gams%nene
847 [ # # ]: 0 : do jene = 1, gams%nene
848 [ # # ]: 0 : gam_atm = reshape(gams%vals_ee(:,jene,iene,:,:,iq_ibz,spin), [2, natom3, natom3])
849 : 0 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, work_qnu)
850 [ # # ]: 0 : gamma_ph_ee(jene, iene, :) = work_qnu
851 : : end do
852 : : end do
853 : : end if
854 : :
855 : : ! Compute lambda
856 : : ! TODO: check this - looks like a factor of 2 wrt the inline documentation!
857 : : ! NB: one factor of 2 comes from the phonon propagator and BE factor,
858 : : ! then you have to be careful with the convention for the Fermi level DOS
859 : : !
860 : : ! spinfact should be 1 for a normal non sppol calculation without spinorbit
861 : : ! for spinors it should also be 1 as bands are twice as numerous but n0 has been divided by 2
862 : : ! for nsppol 2 it should be 0.5 as we have 2 spin channels to sum
863 : 122 : spinfact = two / (gams%nsppol * gams%nspinor)
864 : :
865 [ + + ]: 488 : do nu1=1,gams%natom3
866 : 366 : gamma_ph(nu1) = gamma_ph(nu1) * pi * spinfact
867 : 366 : lambda_ph(nu1) = zero
868 [ + + ]: 366 : if (abs(phfrq(nu1)) > EPHTK_WTOL) lambda_ph(nu1) = gamma_ph(nu1) / (two * pi * gams%n0(spin) * phfrq(nu1)**2)
869 : : !if (abs(phfrq(nu1)) > EPHTK_WTOL) lambda_ph(nu1) = gamma_ph(nu1) / (two * pi * sum(gams%n0(:)) * phfrq(nu1)**2)
870 [ - + - - : 488 : if (present(gamma_ph_ee)) gamma_ph_ee(:,:,nu1) = gamma_ph_ee(:,:,nu1) * pi * spinfact
- - ]
871 : : end do
872 : :
873 : : ! This to avoid spurious results for the acoustic modes as gamma(q) --> 0 and lambda(q) --> 0 for q --> 0.
874 : : ! Here we set everything to zero when we are inside a sphere of radius EPH_Q0TOL as this acoustic rule
875 : : ! is not fulfilled due to numerical inaccuracies.
876 [ + + ]: 122 : if (normv(gams%qibz(:,iq_ibz), cryst%gmet, "G") < EPH_Q0TOL) then
877 [ + + ]: 40 : gamma_ph(1:3) = zero
878 [ + + ]: 40 : lambda_ph(1:3) = zero
879 : : end if
880 : :
881 [ - + ]: 122 : end subroutine phgamma_eval_qibz
882 : : !!***
883 : :
884 : : !----------------------------------------------------------------------
885 : :
886 : : !!****f* m_phgamma/phgamma_interp
887 : : !! NAME
888 : : !! phgamma_interp
889 : : !!
890 : : !! FUNCTION
891 : : !! Interpolate the phonon linewidths at a given q-point.
892 : : !!
893 : : !! INPUTS
894 : : !! cryst<crystal_t>=crystalline structure.
895 : : !! ifc<ifc_type>=Interatomic force constants.
896 : : !! spin=Spin index
897 : : !! qpt(3)=q-point in reduced coordinates
898 : : !! gamma_ph(3*natom)=Phonon linewidths
899 : : !!
900 : : !! OUTPUT
901 : : !! gamma_ph(gams%natom3)=Interpolated Phonon linewidths.
902 : : !! lamda_ph(3*natom)=Lambda coefficients for the different phonon modes.
903 : : !! phfrq(3*natom)=phonon frequencies at current q
904 : : !! displ_cart(2,3,natom,3*natom) = Phonon displacement in Cartesian coordinates
905 : : !!
906 : : !! SOURCE
907 : :
908 : 0 : subroutine phgamma_interp(gams, cryst, ifc, spin, qpt, phfrq, gamma_ph, lambda_ph, displ_cart, gamma_ph_ee)
909 : :
910 : : !Arguments ------------------------------------
911 : : !scalars
912 : : class(phgamma_t),intent(inout) :: gams
913 : : integer,intent(in) :: spin
914 : : type(crystal_t),intent(in) :: cryst
915 : : type(ifc_type),intent(in) :: ifc
916 : : !arrays
917 : : real(dp),intent(in) :: qpt(3)
918 : : real(dp),intent(out) :: phfrq(gams%natom3),gamma_ph(gams%natom3),lambda_ph(gams%natom3)
919 : : real(dp),intent(out) :: displ_cart(2,3,cryst%natom,3*cryst%natom)
920 : : real(dp),intent(out),optional :: gamma_ph_ee(gams%nene,gams%nene,gams%natom3)
921 : :
922 : : !Local variables-------------------------------
923 : : !scalars
924 : : integer,parameter :: qtor0 = 0
925 : : integer, save :: icall=0
926 : : integer :: natom3,nu1
927 : : real(dp) :: spinfact
928 : : character(len=500) :: msg
929 : : !arrays
930 : 1860 : real(dp) :: displ_red(2,gams%natom3,gams%natom3), gam_now(2,gams%natom3**2), gam_atm(2,gams%natom3,gams%natom3)
931 : 930 : real(dp),allocatable :: coskr(:,:),sinkr(:,:)
932 : : ! *************************************************************************
933 : :
934 : : ! Compute internal tables used for Fourier interpolation.
935 [ + + ]: 930 : if (.not. allocated(gams%vals_rpt)) call gams%interp_setup(cryst)
936 : :
937 [ - + - - ]: 930 : if (present(gamma_ph_ee) .and. icall == 0) then
938 [ # # # # : 0 : gamma_ph_ee = zero
# # ]
939 : : write (msg,'(3a)')&
940 : 0 : " For the moment gams_ee matrix elements are not FT interpolated wrt q,",ch10,&
941 : 0 : " only evaluated on the electron k grid. The resulting a2feew will be 0"
942 : 0 : ABI_WARNING(msg)
943 : 0 : icall = 1
944 : : end if
945 : :
946 : 930 : natom3 = gams%natom3
947 : :
948 : : ! Taken from mkph_linwid
949 : : ! This reduced version of ftgkk supposes the kpoints have been integrated
950 : : ! in integrate_gamma. Do FT from real-space gamma grid to 1 qpt.
951 [ - + + - : 2790 : ABI_MALLOC(coskr, (1, gams%nrpt))
+ - + - -
+ - + ]
952 [ - + + - : 1860 : ABI_MALLOC(sinkr, (1, gams%nrpt))
- + - + ]
953 : : ! TODO: This is not optimal
954 : 930 : call ftgam_init(gams%gprim, 1, gams%nrpt, qpt, gams%rpt, coskr, sinkr)
955 : :
956 : 930 : call ftgam(gams%wghatm, gam_now, gams%vals_rpt(:,:,:,spin), gams%natom, 1, gams%nrpt, qtor0, coskr, sinkr)
957 : :
958 : : ! This call is not executed in elphon!
959 [ + - ]: 930 : if (gams%symgamma == 1) call tgamma_symm(cryst, qpt, gam_now)
960 : :
961 [ - + ]: 930 : ABI_FREE(coskr)
962 [ - + ]: 930 : ABI_FREE(sinkr)
963 : :
964 : : ! Get phonon frequencies and eigenvectors.
965 : 930 : call ifc%fourq(cryst, qpt, phfrq, displ_cart, out_displ_red=displ_red)
966 : :
967 : : ! Scalar product with the displ_red
968 [ + + ]: 3720 : gam_atm = reshape(gam_now, [2, natom3, natom3])
969 : 930 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, gamma_ph)
970 : :
971 : : ! Compute lambda
972 : : ! spinfact should be 1 for a normal non sppol calculation without spinorbit
973 : : ! for spinors it should also be 1 as bands are twice as numerous but n0 has been divided by 2
974 : : ! for nsppol 2 it should be 0.5 as we have 2 spin channels to sum
975 : 930 : spinfact = two / (gams%nsppol * gams%nspinor)
976 : :
977 : : ! Compute lambda
978 [ + + ]: 3720 : do nu1=1,gams%natom3
979 : 2790 : gamma_ph(nu1) = gamma_ph(nu1) * pi * spinfact
980 : 2790 : lambda_ph(nu1) = zero
981 [ + + ]: 3720 : if (abs(phfrq(nu1)) > EPHTK_WTOL) lambda_ph(nu1) = gamma_ph(nu1) / (two * pi * gams%n0(spin) * phfrq(nu1)**2)
982 : : end do
983 : :
984 : : ! This to avoid spurious results for the acoustic modes.
985 : : ! In principle, gamma(q) --> 0 and lambda(q) --> 0 for q --> 0
986 : : ! but the Fourier interpolated gammas do not fulfill this property so we set everything
987 : : ! to zero when we are inside a sphere or radius
988 [ + + ]: 930 : if (normv(qpt, cryst%gmet, "G") < EPH_Q0TOL) then
989 : : !write(std_out,*)"Setting values to zero."
990 [ + + ]: 40 : gamma_ph(1:3) = zero
991 [ + + ]: 40 : lambda_ph(1:3) = zero
992 : : end if
993 : :
994 [ - + ]: 930 : end subroutine phgamma_interp
995 : : !!***
996 : :
997 : : !----------------------------------------------------------------------
998 : :
999 : : !!****f* m_phgamma/phgamma_interp_setup
1000 : : !! NAME
1001 : : !! phgamma_interp_setup
1002 : : !!
1003 : : !! FUNCTION
1004 : : !! This routines prepares the internal tables used to interpolate the linewidths in q-space
1005 : : !!
1006 : : !! INPUTS
1007 : : !!
1008 : : !! SOURCE
1009 : :
1010 : 5 : subroutine phgamma_interp_setup(gams, cryst)
1011 : :
1012 : : !Arguments ------------------------------------
1013 : : !scalars
1014 : : class(phgamma_t),intent(inout) :: gams
1015 : : type(crystal_t),intent(in) :: cryst
1016 : :
1017 : : !Local variables-------------------------------
1018 : : !scalars
1019 : : integer,parameter :: qtor1 = 1
1020 : : integer :: iq_bz,iq_ibz,spin,ierr,ii
1021 : : !character(len=500) :: msg
1022 : : !arrays
1023 : 5 : integer,allocatable :: qirredtofull(:),qpttoqpt(:,:,:)
1024 : 5 : real(dp),allocatable :: coskr(:,:),sinkr(:,:), gamma_qpt(:,:,:,:),atmfrc(:,:), vals_bz(:,:,:,:)
1025 : : ! *************************************************************************
1026 : :
1027 [ - + + - : 25 : ABI_MALLOC_OR_DIE(vals_bz, (2, gams%natom3**2, gams%nqbz, gams%nsppol), ierr)
- + + - -
+ + - + -
+ - + - -
+ - + ]
1028 [ + + + + : 21514 : vals_bz = zero
+ + + + ]
1029 : :
1030 : : ! Build tables needed by complete_gamma.
1031 : 5 : call ephtk_mkqtabs(cryst, gams%nqibz, gams%qibz, gams%nqbz, gams%qbz, qirredtofull, qpttoqpt)
1032 : :
1033 : : ! Fill BZ array with IBZ data.
1034 [ + + ]: 10 : do spin=1,gams%nsppol
1035 [ + + ]: 71 : do iq_ibz=1,gams%nqibz
1036 : 61 : iq_bz = qirredtofull(iq_ibz)
1037 [ + + ]: 188 : vals_bz(:,:,iq_bz,spin) = reshape(gams%vals_qibz(:,:,:,iq_ibz,spin), [2, gams%natom3**2])
1038 : : end do
1039 : : end do
1040 : :
1041 : : ! Complete vals_bz in the full BZ.
1042 : : ! FIXME: Change complete_gamma API to pass (..., nsppol)
1043 [ - + + - : 25 : ABI_MALLOC(gamma_qpt, (2, gams%natom3**2, gams%nsppol, gams%nqbz))
- + + - -
+ + - + -
+ - - + -
+ ]
1044 [ + + ]: 10 : do spin=1,gams%nsppol
1045 [ + + + + : 21514 : gamma_qpt(:, :, spin, :) = vals_bz(:, :, :, spin)
+ + ]
1046 : : end do
1047 : :
1048 : : call complete_gamma(cryst, gams%natom3, gams%nsppol, gams%nqibz, gams%nqbz, &
1049 : 5 : gams%eph_scalprod, qirredtofull, qpttoqpt, gamma_qpt)
1050 : :
1051 [ + + ]: 10 : do spin=1,gams%nsppol
1052 [ + + + + : 21514 : vals_bz(:, :, :, spin) = gamma_qpt(:, :, spin, :)
+ + ]
1053 : : end do
1054 : :
1055 [ - + ]: 5 : ABI_FREE(gamma_qpt)
1056 [ - + ]: 5 : ABI_FREE(qirredtofull)
1057 [ - + ]: 5 : ABI_FREE(qpttoqpt)
1058 : :
1059 : : ! This call is not executed in elphon!
1060 [ + - ]: 5 : if (gams%symgamma == 1) then
1061 [ + + ]: 10 : do spin=1,gams%nsppol
1062 [ + + ]: 778 : do iq_bz=1,gams%nqbz
1063 : 773 : call tgamma_symm(cryst, gams%qbz(:,iq_bz), vals_bz(:,:,iq_bz,spin))
1064 : : end do
1065 : : end do
1066 : : end if
1067 : :
1068 : : ! Now FT to real space too
1069 : : ! NOTE: gprim (not gprimd) is used for all FT interpolations,
1070 : : ! to be consistent with the dimensions of the rpt, which come from anaddb.
1071 [ - + + - : 25 : ABI_MALLOC_OR_DIE(gams%vals_rpt, (2, gams%natom3**2, gams%nrpt, gams%nsppol), ierr)
- + + - -
+ + - + -
+ - + - +
- - + + -
- + ]
1072 [ + + + + : 13030 : gams%vals_rpt = zero
+ + + + ]
1073 : :
1074 : : ! q --> r
1075 [ - + + - : 20 : ABI_MALLOC(coskr, (gams%nqbz, gams%nrpt))
- + + - +
- + - - +
- + ]
1076 [ - + + - : 15 : ABI_MALLOC(sinkr, (gams%nqbz, gams%nrpt))
- + + - -
+ - + ]
1077 : 5 : call ftgam_init(gams%gprim, gams%nqbz, gams%nrpt, gams%qbz, gams%rpt, coskr, sinkr)
1078 : :
1079 [ + + ]: 10 : do spin=1,gams%nsppol
1080 : : call ftgam(gams%wghatm, vals_bz(:,:,:,spin), gams%vals_rpt(:,:,:,spin), gams%natom, gams%nqbz,&
1081 : 5 : gams%nrpt, qtor1, coskr, sinkr)
1082 : :
1083 : : ! Enforce "acoustic" rule on vals_rpt. NB: This call is not executed in elphon!
1084 [ - + ]: 10 : if (gams%asr /= 0) then
1085 [ # # # # : 0 : ABI_MALLOC(atmfrc, (3*gams%natom*3*gams%natom, gams%nrpt))
# # # # #
# # # # #
# # # # ]
1086 [ # # ]: 0 : do ii=1,2
1087 [ # # # # : 0 : atmfrc = gams%vals_rpt(ii,:,:,spin)
# # # # #
# # # ]
1088 : : !gals%vals_rpt(2,:,,spin) = zero
1089 : 0 : call asrif9(gams%asr, atmfrc, gams%natom, gams%nrpt, gams%rpt, gams%wghatm)
1090 [ # # # # ]: 0 : gams%vals_rpt(ii,:,:,spin) = atmfrc
1091 : : end do
1092 [ # # ]: 0 : ABI_FREE(atmfrc)
1093 : : end if
1094 : : end do
1095 : :
1096 [ - + ]: 5 : ABI_FREE(vals_bz)
1097 [ - + ]: 5 : ABI_FREE(coskr)
1098 [ - + ]: 5 : ABI_FREE(sinkr)
1099 : :
1100 : 5 : end subroutine phgamma_interp_setup
1101 : : !!***
1102 : :
1103 : : !----------------------------------------------------------------------
1104 : :
1105 : : !!****f* m_phgamma/phgamma_vv_eval_qibz
1106 : : !! NAME
1107 : : !! phgamma_vv_eval_qibz
1108 : : !!
1109 : : !! FUNCTION
1110 : : !! Compute the phonon linewidths times velocity squared, for q-points in the IBZ without performing interpolation.
1111 : : !!
1112 : : !! INPUTS
1113 : : !! gams<phgamma_t>
1114 : : !! cryst<crystal_t>=Crystal structure.
1115 : : !! ifc<ifc_type>=Interatomic force constants.
1116 : : !! iq_ibz=Index of the q-point in the IBZ array.
1117 : : !! spin=Spin index
1118 : : !!
1119 : : !! OUTPUT
1120 : : !! phfrq(gams%natom3)=Phonon frequencies
1121 : : !! gamma_in_ph(gams%natom3)=Phonon linewidths.
1122 : : !! gamma_out_ph(gams%natom3)=Phonon linewidths.
1123 : : !! lambda_in_ph(gams%natom3)=Phonon linewidths.
1124 : : !! lambda_out_ph(gams%natom3)=Phonon linewidths.
1125 : : !!
1126 : : !! SOURCE
1127 : :
1128 : 61 : subroutine phgamma_vv_eval_qibz(gams, cryst, ifc, iq_ibz, spin, phfrq, gamma_in_ph, gamma_out_ph, lambda_in_ph, lambda_out_ph)
1129 : :
1130 : : !Arguments ------------------------------------
1131 : : !scalars
1132 : : class(phgamma_t),intent(inout) :: gams
1133 : : integer,intent(in) :: iq_ibz,spin
1134 : : type(crystal_t),intent(in) :: cryst
1135 : : type(ifc_type),intent(in) :: ifc
1136 : : !arrays
1137 : : real(dp),intent(out) :: phfrq(gams%natom3)
1138 : : real(dp),intent(out) :: gamma_in_ph(3,3,gams%natom3),lambda_in_ph(3,3,gams%natom3)
1139 : : real(dp),intent(out) :: gamma_out_ph(3,3,gams%natom3),lambda_out_ph(3,3,gams%natom3)
1140 : :
1141 : : !Local variables-------------------------------
1142 : : !scalars
1143 : : integer,parameter :: qtor0 = 0
1144 : : integer :: natom3, nu1, idir, jdir, ii
1145 : : real(dp) :: spinfact
1146 : : !character(len=500) :: msg
1147 : : !arrays
1148 : 122 : real(dp) :: displ_cart(2,3,cryst%natom,3*cryst%natom), displ_red(2,gams%natom3,gams%natom3)
1149 : 122 : real(dp) :: work_qnu(gams%natom3), gam_atm(2,gams%natom3,gams%natom3)
1150 : : ! *************************************************************************
1151 : :
1152 : 61 : natom3 = gams%natom3
1153 : :
1154 : : ! Get phonon frequencies and eigenvectors.
1155 : 61 : call ifc%fourq(cryst, gams%qibz(:,iq_ibz), phfrq, displ_cart, out_displ_red=displ_red)
1156 : :
1157 [ + + ]: 244 : do jdir=1,3
1158 [ + + ]: 793 : do idir=1,3
1159 : 549 : ii = idir + gams%ndir_transp * (jdir - 1)
1160 : :
1161 : : ! Scalar product with the displ_red vectors.
1162 [ + + ]: 2196 : gam_atm = reshape(gams%vals_in_qibz(:,ii,:,:,iq_ibz,spin), [2, natom3, natom3])
1163 : 549 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, work_qnu)
1164 [ + + ]: 2196 : gamma_in_ph(idir,jdir,:) = work_qnu
1165 : :
1166 [ + + ]: 2196 : gam_atm = reshape(gams%vals_out_qibz(:,ii,:,:,iq_ibz,spin), [2, natom3, natom3])
1167 : 549 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, work_qnu)
1168 [ + + ]: 2379 : gamma_out_ph(idir,jdir,:) = work_qnu
1169 : : end do ! idir
1170 : : end do ! jdir
1171 : :
1172 : : ! TODO : check this - looks like a factor of 2 wrt the inline documentation!
1173 : : !spinfact should be 1 for a normal non sppol calculation without spinorbit
1174 : : !for spinors it should also be 1 as bands are twice as numerous but n0 has been divided by 2
1175 : : !for sppol 2 it should be 0.5 as we have 2 spin channels to sum
1176 : 61 : spinfact = two / (gams%nsppol*gams%nspinor)
1177 : :
1178 : : ! Compute lambda transport.
1179 [ + + ]: 244 : do jdir =1,3
1180 [ + + ]: 793 : do idir =1,3
1181 [ + + ]: 2379 : do nu1=1,gams%natom3
1182 : 1647 : gamma_in_ph(idir,jdir,nu1) = gamma_in_ph(idir,jdir,nu1) * pi * spinfact
1183 : 1647 : gamma_out_ph(idir,jdir,nu1) = gamma_out_ph(idir,jdir,nu1) * pi * spinfact
1184 : 1647 : lambda_in_ph(idir,jdir,nu1) = zero
1185 : 1647 : lambda_out_ph(idir,jdir,nu1) = zero
1186 [ + + ]: 2196 : if (abs(phfrq(nu1)) > EPHTK_WTOL) then
1187 : 1512 : lambda_in_ph(idir,jdir,nu1) = gamma_in_ph(idir,jdir,nu1) / (two * pi * gams%n0(spin) * phfrq(nu1)**2)
1188 : 1512 : lambda_out_ph(idir,jdir,nu1) = gamma_out_ph(idir,jdir,nu1) / (two * pi * gams%n0(spin) * phfrq(nu1)**2)
1189 : : end if
1190 : : end do
1191 : : end do ! idir
1192 : : end do ! jdir
1193 : :
1194 : 61 : end subroutine phgamma_vv_eval_qibz
1195 : : !!***
1196 : :
1197 : : !----------------------------------------------------------------------
1198 : :
1199 : : !!****f* m_phgamma/phgamma_vv_interp
1200 : : !! NAME
1201 : : !! phgamma_vv_interp
1202 : : !!
1203 : : !! FUNCTION
1204 : : !! Interpolate the linewidths at a given q-point.
1205 : : !!
1206 : : !! INPUTS
1207 : : !! cryst<crystal_t>=crystalline structure.
1208 : : !! ifc<ifc_type>=Interatomic force constants.
1209 : : !! spin=Spin index
1210 : : !! qpt(3)=q-point in reduced coordinates
1211 : : !! gamma_ph(3*natom)=Phonon linewidths
1212 : : !! displ_cart(2,3,cryst%natom,3*cryst%natom)=Phonon displacement in cartesian coordinates.
1213 : : !!
1214 : : !! OUTPUT
1215 : : !! phfrq(3*natom)=phonon frequencies at current q
1216 : : !! gamma_out_ph(gams%natom3)=Interpolated Phonon linewidths.
1217 : : !! lambda_in_ph(3*natom)=Lambda coefficients for the different phonon modes.
1218 : : !! lambda_out_ph(3*natom)=Lambda coefficients for the different phonon modes.
1219 : : !!
1220 : : !! SOURCE
1221 : :
1222 : 725 : subroutine phgamma_vv_interp(gams, cryst, ifc, spin, qpt, phfrq, gamma_in_ph, gamma_out_ph, lambda_in_ph, lambda_out_ph)
1223 : :
1224 : : !Arguments ------------------------------------
1225 : : !scalars
1226 : : class(phgamma_t),intent(inout) :: gams
1227 : : type(crystal_t),intent(in) :: cryst
1228 : : type(ifc_type),intent(in) :: ifc
1229 : : integer,intent(in) :: spin
1230 : : !arrays
1231 : : real(dp),intent(in) :: qpt(3)
1232 : : real(dp),intent(out) :: phfrq(gams%natom3)
1233 : : real(dp),intent(out) :: gamma_in_ph(3,3,gams%natom3),lambda_in_ph(3,3,gams%natom3)
1234 : : real(dp),intent(out) :: gamma_out_ph(3,3,gams%natom3),lambda_out_ph(3,3,gams%natom3)
1235 : :
1236 : : !Local variables-------------------------------
1237 : : !scalars
1238 : : integer,parameter :: qtor0 = 0
1239 : : integer :: natom3, nu1, idir,jdir,ii
1240 : : real(dp) :: spinfact
1241 : : !character(len=500) :: msg
1242 : : !arrays
1243 : 1450 : real(dp) :: displ_cart(2,3,cryst%natom,3*cryst%natom), displ_red(2,gams%natom3,gams%natom3),work_qnu(gams%natom3)
1244 : 1450 : real(dp) :: gam_in_now(2,3,3,gams%natom3**2), gam_out_now(2,3,3,gams%natom3**2), gam_atm(2,gams%natom3,gams%natom3)
1245 : 725 : real(dp),allocatable :: coskr(:,:),sinkr(:,:)
1246 : : ! *************************************************************************
1247 : :
1248 : : ! Compute internal tables used for Fourier interpolation.
1249 [ + + ]: 725 : if (.not.allocated(gams%vals_in_rpt)) call phgamma_vv_interp_setup(gams, cryst)
1250 : :
1251 : 725 : natom3 = gams%natom3
1252 : :
1253 : : ! Get phonon frequencies and eigenvectors.
1254 : 725 : call ifc%fourq(cryst, qpt, phfrq, displ_cart, out_displ_red=displ_red)
1255 : :
1256 : : ! Taken from mkph_linwid
1257 : : ! This reduced version of ftgkk supposes the kpoints have been integrated
1258 : : ! in integrate_gamma. Do FT from real-space gamma grid to 1 qpt.
1259 [ - + + - : 2175 : ABI_MALLOC(coskr, (1,gams%nrpt))
+ - + - -
+ - + ]
1260 [ - + + - : 1450 : ABI_MALLOC(sinkr, (1,gams%nrpt))
- + - + ]
1261 : : ! TODO: This is not optimal
1262 : 725 : call ftgam_init(gams%gprim, 1, gams%nrpt, qpt, gams%rpt, coskr, sinkr)
1263 : :
1264 [ + + ]: 2900 : do idir=1,3
1265 [ + + ]: 9425 : do jdir=1,3
1266 : 6525 : ii = idir+gams%ndir_transp*(jdir-1)
1267 : :
1268 [ + - + - : 33988725 : call ftgam(gams%wghatm, gam_in_now, gams%vals_in_rpt(:,ii,:,:,spin), gams%natom, 1, gams%nrpt, qtor0, coskr, sinkr)
+ + + + +
+ + - + +
+ + + + ]
1269 [ + - + - : 33988725 : call ftgam(gams%wghatm, gam_out_now, gams%vals_out_rpt(:,ii,:,:,spin), gams%natom, 1, gams%nrpt, qtor0, coskr, sinkr)
+ + + + +
+ + - + +
+ + + + ]
1270 : :
1271 : : ! This call is not executed in elphon!
1272 : : ! TODO: needs to take into account the matrix nature of _in_ and _out_ gammas
1273 [ + - ]: 6525 : if (gams%symgamma == 1) then
1274 : 6525 : call tgamma_symm(cryst, qpt, gam_in_now)
1275 : 6525 : call tgamma_symm(cryst, qpt, gam_out_now)
1276 : : end if
1277 : :
1278 : : ! Scalar product with the displ_red
1279 [ + + ]: 26100 : gam_atm = reshape(gam_in_now, [2, natom3, natom3])
1280 : 6525 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, work_qnu)
1281 [ + + ]: 26100 : gamma_in_ph(idir,jdir,:) = work_qnu
1282 : :
1283 [ + + ]: 26100 : gam_atm = reshape(gam_out_now, [2, natom3, natom3])
1284 : 6525 : call ephtk_gam_atm2qnu(natom3, displ_red, gam_atm, work_qnu)
1285 [ + + ]: 28275 : gamma_out_ph(idir,jdir,:) = work_qnu
1286 : : end do
1287 : : end do
1288 : :
1289 [ - + ]: 725 : ABI_FREE(coskr)
1290 [ - + ]: 725 : ABI_FREE(sinkr)
1291 : :
1292 : : ! Compute lambda
1293 : : ! spinfact should be 1 for a normal non sppol calculation without spinorbit
1294 : : ! for spinors it should also be 1 as bands are twice as numerous but n0 has been divided by 2
1295 : : ! for sppol 2 it should be 0.5 as we have 2 spin channels to sum
1296 : 725 : spinfact = two / (gams%nsppol * gams%nspinor)
1297 : :
1298 : : ! Compute lambda
1299 [ + + ]: 2900 : do nu1=1,gams%natom3
1300 [ + + ]: 9425 : do idir=1,3
1301 [ + + ]: 28275 : do jdir=1,3
1302 : 19575 : gamma_in_ph(idir,jdir,nu1) = gamma_in_ph(idir,jdir,nu1) * pi * spinfact
1303 : 19575 : gamma_out_ph(idir,jdir,nu1) = gamma_out_ph(idir,jdir,nu1) * pi * spinfact
1304 : 19575 : lambda_in_ph(idir,jdir,nu1) = zero
1305 : 19575 : lambda_out_ph(idir,jdir,nu1) = zero
1306 [ + + ]: 26100 : if (abs(phfrq(nu1)) > EPHTK_WTOL) then
1307 : 19440 : lambda_in_ph(idir,jdir,nu1) = gamma_in_ph(idir,jdir,nu1) / (two * pi * gams%n0(spin) * phfrq(nu1)**2)
1308 : 19440 : lambda_out_ph(idir,jdir,nu1) = gamma_out_ph(idir,jdir,nu1) / (two * pi * gams%n0(spin) * phfrq(nu1)**2)
1309 : : end if
1310 : : end do
1311 : : end do
1312 : : end do
1313 : :
1314 : 725 : end subroutine phgamma_vv_interp
1315 : : !!***
1316 : :
1317 : : !----------------------------------------------------------------------
1318 : :
1319 : : !!****f* m_phgamma/phgamma_vv_interp_setup
1320 : : !! NAME
1321 : : !! phgamma_vv_interp_setup
1322 : : !!
1323 : : !! FUNCTION
1324 : : !! This routines prepare the internal tables used to interpolate the vv_linewidths in q-space
1325 : : !!
1326 : : !! INPUTS
1327 : : !! action =
1328 : : !! "INIT" to allocate and compute the internal tables (default)
1329 : : !! "FREE" to deallocate the internal tables.
1330 : : !!
1331 : : !! SOURCE
1332 : :
1333 : 5 : subroutine phgamma_vv_interp_setup(gams, cryst)
1334 : :
1335 : : !Arguments ------------------------------------
1336 : : class(phgamma_t),intent(inout) :: gams
1337 : : type(crystal_t),intent(in) :: cryst
1338 : :
1339 : : !Local variables-------------------------------
1340 : : !scalars
1341 : : integer,parameter :: qtor1 = 1
1342 : : integer :: iq_bz,iq_ibz,spin,ierr, ii, idir, jdir
1343 : : !character(len=500) :: msg
1344 : : !arrays
1345 : 5 : integer,allocatable :: qirredtofull(:),qpttoqpt(:,:,:)
1346 : 5 : real(dp),allocatable :: coskr(:,:),sinkr(:,:), vals_in_bz(:,:,:,:,:), vals_out_bz(:,:,:,:,:)
1347 : : ! *************************************************************************
1348 : :
1349 [ - + + - : 25 : ABI_MALLOC_OR_DIE(vals_in_bz,(2, 9, gams%natom3**2, gams%nqbz, gams%nsppol), ierr)
- + + - -
+ + - + -
+ - + - -
+ - + ]
1350 [ - + + - : 25 : ABI_MALLOC_OR_DIE(vals_out_bz,(2, 9, gams%natom3**2, gams%nqbz, gams%nsppol), ierr)
- + + - -
+ + - + -
+ - + - -
+ - + ]
1351 [ + + + + : 194314 : vals_in_bz = zero
+ + + + +
+ ]
1352 [ + + + + : 194314 : vals_out_bz = zero
+ + + + +
+ ]
1353 : :
1354 : : ! Build tables needed by complete_gamma.
1355 : 5 : call ephtk_mkqtabs(cryst, gams%nqibz, gams%qibz, gams%nqbz, gams%qbz, qirredtofull, qpttoqpt)
1356 : :
1357 : : ! Fill BZ array with IBZ data.
1358 [ + + ]: 10 : do spin=1,gams%nsppol
1359 [ + + ]: 71 : do iq_ibz=1,gams%nqibz
1360 : 61 : iq_bz = qirredtofull(iq_ibz)
1361 [ + + ]: 244 : vals_in_bz(:,:,:,iq_bz,spin) = reshape(gams%vals_in_qibz(:,:,:,:,iq_ibz,spin), [2, 9, gams%natom3**2])
1362 [ + + ]: 249 : vals_out_bz(:,:,:,iq_bz,spin) = reshape(gams%vals_out_qibz(:,:,:,:,iq_ibz,spin), [2, 9, gams%natom3**2])
1363 : : end do
1364 : : end do
1365 : :
1366 : : ! Complete vals_bz in the full BZ.
1367 : : !TODO!!! rotate the vv in and out matrices, according to the symmetry operation, instead of just copying them
1368 : : !call complete_gamma_vv(cryst, gams%natom3, gams%nsppol, gams%nqibz, gams%nqbz,&
1369 : : ! gams%eph_scalprod, qirredtofull, qpttoqpt, vals_in_bz(:,:,:,:,spin))
1370 : : !call complete_gamma_vv(cryst, gams%natom3, gams%nsppol, gams%nqibz, gams%nqbz,&
1371 : : ! gams%eph_scalprod, qirredtofull, qpttoqpt, vals_out_bz(:,:,:,:,spin))
1372 : :
1373 : : ! TODO: replace the above with these calls from anaddb
1374 : : !call complete_gamma_tr(cryst,elph_ds%ep_scalprod,elph_ds%nbranch,elph_ds%nqptirred,&
1375 : : !& elph_ds%nqpt_full,elph_ds%nsppol,elph_tr_ds%gamma_qpt_trout,elph_ds%qirredtofull,qpttoqpt)
1376 : :
1377 : : ! TODO: idem for vv_vals 3x3 matrices
1378 : :
1379 [ - + ]: 5 : ABI_FREE(qirredtofull)
1380 [ - + ]: 5 : ABI_FREE(qpttoqpt)
1381 : :
1382 : : !! This call is not executed in elphon!
1383 : : !if (gams%symgamma == 1) then
1384 : : ! do spin=1,gams%nsppol
1385 : : ! do iq_bz=1,gams%nqbz
1386 : : ! call tgamma_symm_vv(cryst, gams%qbz(:,iq_bz), vals_in_bz(:,:,:,iq_bz,spin))
1387 : : ! call tgamma_symm_vv(cryst, gams%qbz(:,iq_bz), vals_out_bz(:,:,:,iq_bz,spin))
1388 : : ! end do
1389 : : ! end do
1390 : : !end if
1391 : :
1392 : : ! Now FT to real space
1393 : : ! NOTE: gprim (not gprimd) is used for all FT interpolations,
1394 : : ! to be consistent with the dimensions of the rpt, which come from anaddb.
1395 : : ! TODO: this is needed only if FT is used, not when the linear interpolation is employed.
1396 : : !if (.not. allocated(gams%vals_in_rpt)) then
1397 [ - + + - : 25 : ABI_MALLOC_OR_DIE(gams%vals_in_rpt, (2, 9, gams%natom3**2, gams%nrpt, gams%nsppol), ierr)
- + + - -
+ + - + -
+ - + - +
- - + + -
- + ]
1398 [ - + + - : 25 : ABI_MALLOC_OR_DIE(gams%vals_out_rpt, (2, 9, gams%natom3**2, gams%nrpt, gams%nsppol), ierr)
- + + - -
+ + - + -
+ - + - +
- - + + -
- + ]
1399 [ + + + + : 117655 : gams%vals_in_rpt = zero
+ + + + +
+ ]
1400 [ + + + + : 117655 : gams%vals_out_rpt = zero
+ + + + +
+ ]
1401 : :
1402 : : ! q --> r
1403 [ - + + - : 20 : ABI_MALLOC(coskr, (gams%nqbz,gams%nrpt))
- + + - +
- + - - +
- + ]
1404 [ - + + - : 15 : ABI_MALLOC(sinkr, (gams%nqbz,gams%nrpt))
- + + - -
+ - + ]
1405 : 5 : call ftgam_init(gams%gprim, gams%nqbz, gams%nrpt, gams%qbz, gams%rpt, coskr, sinkr)
1406 : :
1407 [ + + ]: 10 : do spin=1,gams%nsppol
1408 [ + + ]: 25 : do idir=1,3
1409 [ + + ]: 65 : do jdir=1,3
1410 : 45 : ii = idir+gams%ndir_transp*(jdir-1)
1411 : : ! TODO: this is no contiguous in memory and will be slow. Make adapted ftgam?
1412 : : call ftgam(gams%wghatm, vals_in_bz(:,ii,:,:,spin), gams%vals_in_rpt(:,ii,:,:,spin), gams%natom, gams%nqbz,&
1413 [ + - + + : 621477 : gams%nrpt, qtor1, coskr, sinkr)
+ + + + +
- + - + +
+ + + + +
+ + + + +
+ - + + +
+ + + ]
1414 : : call ftgam(gams%wghatm, vals_out_bz(:,ii,:,:,spin), gams%vals_out_rpt(:,ii,:,:,spin), gams%natom, gams%nqbz,&
1415 [ + - + + : 621492 : gams%nrpt, qtor1, coskr, sinkr)
+ + + + +
- + - + +
+ + + + +
+ + + + +
+ - + + +
+ + + ]
1416 : : end do
1417 : : end do
1418 : : end do
1419 : :
1420 [ - + ]: 5 : ABI_FREE(vals_in_bz)
1421 [ - + ]: 5 : ABI_FREE(vals_out_bz)
1422 [ - + ]: 5 : ABI_FREE(coskr)
1423 [ - + ]: 5 : ABI_FREE(sinkr)
1424 : :
1425 : 5 : end subroutine phgamma_vv_interp_setup
1426 : : !!***
1427 : : !----------------------------------------------------------------------
1428 : :
1429 : : !!****f* m_phgamma/phgamma_linwid
1430 : : !! NAME
1431 : : !! phgamma_linwid
1432 : : !!
1433 : : !! FUNCTION
1434 : : !! Interpolate the phonon linewidths along an arbitrary q-path (use Fourier interpolation).
1435 : : !!
1436 : : !! INPUTS
1437 : : !! cryst<crystal_t>=Info on the unit cell and symmetries.
1438 : : !! ifc<ifc_type>=Interatomic force constants.
1439 : : !! ndivsm=Number of points used to sample the smallest segment
1440 : : !! nvert = Number of extrema in qverts
1441 : : !! qverts(3,nvert) = vertices of reciprocal space trajectory
1442 : : !! basename=name used to create the different output files (text format).
1443 : : !! ncid=Netcdf file handler (already open in the caller).
1444 : : !! comm=MPI communicator
1445 : : !!
1446 : : !! OUTPUT
1447 : : !! wminmax=Minimum and max phonon frequency obtained on the path (Hartree units)
1448 : : !!
1449 : : !! SOURCE
1450 : :
1451 : 5 : subroutine phgamma_linwid(gams, cryst, ifc, ndivsm, nvert, qverts, basename, ncid, wminmax, comm)
1452 : :
1453 : : !Arguments ------------------------------------
1454 : : !scalars
1455 : : class(phgamma_t),intent(inout) :: gams
1456 : : integer,intent(in) :: nvert,ndivsm,comm,ncid
1457 : : type(crystal_t),intent(in) :: cryst
1458 : : type(ifc_type),intent(in) :: ifc
1459 : : character(len=*),intent(in) :: basename
1460 : : !arrays
1461 : : real(dp),intent(in) :: qverts(3,nvert)
1462 : : real(dp),intent(out) :: wminmax(2)
1463 : :
1464 : : !Local variables-------------------------------
1465 : : !scalars
1466 : : integer,parameter :: master = 0
1467 : : integer :: natom,ii,mu,iqpt,natom3,nsppol,ierr, spin,unt,nqpt,nrpt,cnt,nproc,my_rank, ncerr
1468 : : real(dp) :: omega_min,omega_max,wtmp,omega
1469 : : character(len=500) :: msg
1470 : 5 : type(kpath_t) :: qpath
1471 : : !arrays
1472 : 10 : real(dp) :: gamma_spin(gams%nsppol),lambda_spin(gams%nsppol)
1473 : 10 : real(dp) :: displ_cart(2,3*cryst%natom,3*cryst%natom)
1474 : 10 : real(dp) :: phfrq(3*cryst%natom),gamma_ph(3*cryst%natom),lambda_ph(3*cryst%natom), qpt(3),shift(3)
1475 : 5 : real(dp),allocatable :: all_phfreq(:,:),all_gammaq(:,:,:),all_lambdaq(:,:,:),all_displ_cart(:,:,:,:)
1476 : : ! *********************************************************************
1477 : :
1478 : 5 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1479 : 5 : natom = cryst%natom; natom3 = gams%natom3; nsppol = gams%nsppol; nrpt = gams%nrpt
1480 : :
1481 : : ! Define the q-path along which phonon linwid will be interpolated.
1482 : 5 : call qpath%init(qverts, cryst%gprimd, ndivsm)
1483 : 5 : nqpt = qpath%npts
1484 : :
1485 : : ! Allocate workspace arrays for MPI.
1486 [ - + + - : 840 : ABI_CALLOC(all_phfreq, (natom3, nqpt))
- + + - +
- + - - +
- + + + +
+ ]
1487 [ - + + - : 850 : ABI_CALLOC(all_gammaq, (natom3, nqpt, nsppol))
- + + - -
+ + - + -
+ - - + -
+ + + + +
+ + ]
1488 [ - + + - : 845 : ABI_CALLOC(all_lambdaq, (natom3, nqpt, nsppol))
- + + - -
+ + - - +
- + + + +
+ + + ]
1489 [ - + + - : 6380 : ABI_CALLOC(all_displ_cart, (2, natom3, natom3, nqpt))
- + + - -
+ + - + -
+ - - + -
+ + + + +
+ + + + ]
1490 : :
1491 : : ! initialize the minimum and maximum phonon frequency
1492 : 5 : omega_min = huge(one); omega_max = -huge(one)
1493 : :
1494 : : ! Interpolation along specified path in q space (keep spin dep.)
1495 : 5 : cnt = 0
1496 [ + + ]: 10 : do spin=1,nsppol
1497 [ + + ]: 215 : do iqpt=1,nqpt
1498 [ - + ]: 205 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle
1499 [ + + ]: 820 : call wrap2_pmhalf(qpath%points(:,iqpt), qpt, shift)
1500 : :
1501 : : ! Get phgamma
1502 : 205 : call gams%interp(cryst, ifc, spin, qpt, phfrq, gamma_ph, lambda_ph, displ_cart)
1503 [ + + ]: 820 : all_gammaq(:, iqpt, spin) = gamma_ph
1504 [ + + ]: 820 : all_lambdaq(:, iqpt, spin) = lambda_ph
1505 [ + - ]: 205 : if (spin == 1) then
1506 [ + + ]: 820 : all_phfreq(:, iqpt) = phfrq
1507 [ + + + + : 6355 : all_displ_cart(:, :, :, iqpt) = displ_cart
+ + ]
1508 : : end if
1509 : :
1510 : : ! Find max/min phonon frequency along path chosen
1511 : : ! presumed to be representative of full BZ to within 10 percent
1512 : 205 : omega_min = min(omega_min, phfrq(1))
1513 : 210 : omega_max = max(omega_max, phfrq(natom3))
1514 : : end do ! end iqpt do
1515 : : end do ! spin
1516 : :
1517 : : ! Collect results
1518 [ - + ]: 5 : if (omega_min > tol12) omega_min = zero
1519 : 5 : wtmp = omega_min; call xmpi_min(wtmp, omega_min, comm, ierr)
1520 : 5 : wtmp = omega_max; call xmpi_max(wtmp, omega_max, comm, ierr)
1521 [ + + ]: 15 : wminmax = [omega_min, omega_max]
1522 : :
1523 : 5 : call xmpi_sum_master(all_gammaq, master, comm, ierr)
1524 : 5 : call xmpi_sum_master(all_lambdaq, master, comm, ierr)
1525 : 5 : call xmpi_sum_master(all_phfreq, master, comm, ierr)
1526 : 5 : call xmpi_sum_master(all_displ_cart, master, comm, ierr)
1527 : :
1528 : : ! Master writes text file with final results.
1529 : : ! 3 * natom blocks, one block for each phonon mode.
1530 : : ! Each block contains:
1531 : : ! iqpt omega_(q) gamma(q) lambda(q) nesting(q) ....
1532 : :
1533 [ + - ]: 5 : if (xmpi_comm_rank(comm) == master) then
1534 [ - + ]: 5 : if (open_file(strcat(basename, '_PHGAMMA'), msg, newunit=unt, action="write", form="formatted", status="unknown") /= 0) then
1535 : 5 : ABI_ERROR(msg)
1536 : : end if
1537 : :
1538 : 5 : write(unt,'(a)') '#'
1539 : 5 : write(unt,'(a)') '# ABINIT package: E-PH band structure file. Hartree units'
1540 : 5 : write(unt,'(a)') '#'
1541 : 5 : write(unt,'(a,i0,a)')'# Phonon frequencies, ph linewidths and lambda calculated on ',nqpt,' q-points'
1542 [ + + ]: 10 : call qpath%print([unt], header="Description of the q-path:", pre="#")
1543 [ + + ]: 15 : do ii=1,2; write(unt,'(a)') "# "; end do
1544 : :
1545 [ + + ]: 10 : write(unt,'(a,e16.6)')"# Total DOS at Fermi level ",sum(gams%n0)
1546 [ + + ]: 10 : do spin=1,nsppol
1547 : 10 : write(unt,"(a,i0,a,e16.6)")"# The DOS at Fermi level for spin ",spin," is ",gams%n0(spin)
1548 : : end do
1549 : :
1550 [ + + ]: 20 : do mu=1,natom3
1551 : 15 : write(unt,'(a)')"#"
1552 [ + - ]: 15 : if (nsppol == 1) write(unt,'(a,i0,a)')"# phonon mode [",mu,"] q-index omega gamma lambda"
1553 [ - + ]: 15 : if (nsppol == 2) write(unt,'(a,i0,a)')&
1554 : 0 : "# phonon mode [",mu,"] q-index omega gamma_tot lambda_tot gamma[spin=1] lambda[spin=1] gamma[2] lambda[2]"
1555 : 15 : write(unt,'(a)')"#"
1556 [ + + ]: 635 : do iqpt=1,nqpt
1557 : 615 : omega = all_phfreq(mu, iqpt)
1558 [ + + ]: 1230 : gamma_spin = all_gammaq(mu, iqpt, :)
1559 [ + + ]: 1230 : lambda_spin = all_lambdaq(mu, iqpt, :)
1560 [ + - ]: 630 : if (nsppol == 1) then
1561 : 615 : write(unt,'(i8,3es16.6)' )iqpt,omega,gamma_spin(1),lambda_spin(1)
1562 : : else
1563 : 0 : write(unt,'(i8,es20.6,6es16.6)' )iqpt,omega,&
1564 [ # # # # ]: 0 : sum(gamma_spin),sum(lambda_spin),gamma_spin(1),lambda_spin(1),gamma_spin(2),lambda_spin(2)
1565 : : end if
1566 : : end do
1567 : : end do
1568 : :
1569 : 5 : close(unt)
1570 : :
1571 : : ! Write data to netcdf file
1572 [ + - ]: 5 : if (ncid /= nctk_noid) then
1573 : : ncerr = nctk_def_dims(ncid, [&
1574 : : nctkdim_t("natom3", 3*natom), nctkdim_t("nqpath", nqpt), nctkdim_t("number_of_spins", nsppol) &
1575 [ + + ]: 20 : ], defmode=.True.)
1576 [ - + ]: 5 : NCF_CHECK(ncerr)
1577 : :
1578 : : ncerr = nctk_def_arrays(ncid, [&
1579 : : nctkarr_t('qpath', "dp", "number_of_reduced_dimensions, nqpath"), &
1580 : : nctkarr_t('phfreq_qpath', "dp", "natom3, nqpath"), &
1581 : : nctkarr_t('phdispl_cart_qpath', "dp", "two, natom3, natom3, nqpath"), &
1582 : : nctkarr_t('phgamma_qpath', "dp", "natom3, nqpath, number_of_spins"), &
1583 [ + + ]: 30 : nctkarr_t('phlambda_qpath', "dp", "natom3, nqpath, number_of_spins")])
1584 [ - + ]: 5 : NCF_CHECK(ncerr)
1585 : :
1586 [ - + ]: 5 : NCF_CHECK(nctk_set_datamode(ncid))
1587 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpath"), qpath%points))
1588 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phfreq_qpath"), all_phfreq))
1589 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phdispl_cart_qpath"), all_displ_cart))
1590 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phgamma_qpath"), all_gammaq))
1591 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "phlambda_qpath"), all_lambdaq))
1592 : : end if
1593 : : end if ! master
1594 : :
1595 [ - + ]: 5 : ABI_FREE(all_phfreq)
1596 [ - + ]: 5 : ABI_FREE(all_gammaq)
1597 [ - + ]: 5 : ABI_FREE(all_lambdaq)
1598 [ - + ]: 5 : ABI_FREE(all_displ_cart)
1599 : :
1600 : 5 : call qpath%free()
1601 : :
1602 [ - + - + : 10 : end subroutine phgamma_linwid
- + - + -
+ ]
1603 : : !!***
1604 : :
1605 : : !----------------------------------------------------------------------
1606 : :
1607 : : !!****f* m_phgamma/a2fw_free
1608 : : !! NAME
1609 : : !! a2fw_free
1610 : : !!
1611 : : !! FUNCTION
1612 : : !! Free the memory allocated in a2f
1613 : : !!
1614 : : !! SOURCE
1615 : :
1616 : 10 : subroutine a2fw_free(a2f)
1617 : :
1618 : : !Arguments ------------------------------------
1619 : : class(a2fw_t),intent(inout) :: a2f
1620 : : ! *********************************************************************
1621 : :
1622 : : ! integer
1623 [ + - ]: 10 : ABI_SFREE(a2f%qshift)
1624 : :
1625 : : ! real
1626 [ + - ]: 10 : ABI_SFREE(a2f%n0)
1627 [ + - ]: 10 : ABI_SFREE(a2f%omega)
1628 [ + - ]: 10 : ABI_SFREE(a2f%vals)
1629 [ - + ]: 10 : ABI_SFREE(a2f%vals_ee)
1630 [ + - ]: 10 : ABI_SFREE(a2f%lambdaw)
1631 : :
1632 : 10 : end subroutine a2fw_free
1633 : : !!***
1634 : :
1635 : : !----------------------------------------------------------------------
1636 : :
1637 : : !!****f* m_phgamma/a2fw_init
1638 : : !! NAME
1639 : : !! a2fw_init
1640 : : !!
1641 : : !! FUNCTION
1642 : : !! Calculates the FS averaged alpha^2F(w) function
1643 : : !!
1644 : : !! INPUTS
1645 : : !! cryst<crystal_t>=Info on the unit cell.
1646 : : !! ifc<ifc_type>=Interatomic force constants.
1647 : : !! gams<phgamma_t>=Structure storing the phonon linewidths.
1648 : : !! wstep=Step for linear frequency mesh in Ha.
1649 : : !! wminmax(2)=Minimum and maximum phonon frequency. Used to construct the linear mesh for A2F(w).
1650 : : !! ph_intmeth=Integration method for phonons: 1 for gaussian, 2 for tetrahedra
1651 : : !! smear=Gaussian broadening used to approximate the Dirac delta.
1652 : : !! ngqpt(3)=Divisions of the Q-mesh used for interpolating the phonon linewidths (see also nqshift and qshift).
1653 : : !! nqshift=Number of shifts used to generated the Q-mesh.
1654 : : !! qshift(3,nqshift)=The shifts.
1655 : : !! comm=MPI communicator
1656 : : !! [qintp]=If set to False, ngqgpt, nqshift, qshift and qptop are ignored and
1657 : : !! A2F(w) is computed from the IBZ values stored in gams. Default: True i.e use Fourier interpolation.
1658 : : !! [qptopt]=Controls the generation of the q-points. If not specified, the routine takes fully into account
1659 : : !! the symmetries of the system to generate the q points in the IBZone i.e. qptopt=1
1660 : : !! Other values of qptopt can be used for debugging purpose.
1661 : : !!
1662 : : !! OUTPUT
1663 : : !! a2f<a2fw_t>=Structure storing the Eliashberg function a2F(w).
1664 : : !!
1665 : : !! SOURCE
1666 : :
1667 : 10 : subroutine a2fw_init(a2f, gams, cryst, ifc, ph_intmeth, wstep, wminmax, smear, ngqpt, nqshift, qshift, comm, &
1668 : : qintp, qptopt) ! optional
1669 : :
1670 : : !Arguments ------------------------------------
1671 : : !scalars
1672 : : class(a2fw_t),target,intent(out) :: a2f
1673 : : integer,intent(in) :: ph_intmeth,nqshift,comm
1674 : : integer,intent(in),optional :: qptopt
1675 : : real(dp),intent(in) :: wstep,smear
1676 : : logical,optional,intent(in) :: qintp
1677 : : type(phgamma_t),intent(inout) :: gams
1678 : : type(ifc_type),intent(in) :: ifc
1679 : : type(crystal_t),intent(in) :: cryst
1680 : : !arrays
1681 : : integer,intent(in) :: ngqpt(3)
1682 : : real(dp),intent(in) :: wminmax(2),qshift(3,nqshift)
1683 : :
1684 : : !Local variables -------------------------
1685 : : !scalars
1686 : : integer,parameter :: master = 0
1687 : : integer :: my_qptopt,iq_ibz,nqibz,ount,my_rank,nproc,cnt
1688 : : integer :: mu,iw,natom3,nsppol,spin,ierr,nomega,nqbz
1689 : : integer :: iene, jene, itemp, ntemp, jene_jump, spinfactor
1690 : : real(dp) :: cpu,wall,gflops
1691 : : real(dp) :: lambda_iso,omega,omega_log,xx,omega_min,omega_max,ww,mustar,tc_macmill
1692 : : real(dp) :: temp_el, min_temp, delta_temp, chempot, ene1, ene2, G0
1693 : : logical :: do_qintp
1694 : : character(len=500) :: msg
1695 : 10 : type(htetra_t) :: tetra_q
1696 : : !arrays
1697 : : integer :: qptrlatt(3,3),new_qptrlatt(3,3)
1698 : 20 : real(dp) :: displ_cart(2,3,cryst%natom,3*cryst%natom)
1699 : 40 : real(dp) :: phfrq(gams%natom3),gamma_ph(gams%natom3),lambda_ph(gams%natom3), invphfrq(gams%natom3)
1700 : 10 : real(dp),allocatable :: my_qshift(:,:), gamma_ph_ee(:,:,:,:), tmp_a2f(:)
1701 : 10 : real(dp),contiguous, pointer :: a2f_1d(:)
1702 : 10 : real(dp),allocatable :: qibz(:,:),wtq(:),qbz(:,:), a2f_1mom(:),a2flogmom(:),a2flogmom_int(:),wdt(:,:)
1703 : 10 : real(dp),allocatable :: lambda_tetra(:,:,:),phfreq_tetra(:,:), tmp_gaussian(:,:)
1704 : 10 : real(dp),allocatable :: a2feew_partial(:), a2feew_partial_int(:), a2feew_w(:), a2feew_w_int(:)
1705 : : ! *********************************************************************
1706 : :
1707 : 10 : call cwtime(cpu, wall, gflops, "start")
1708 : 10 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
1709 : :
1710 [ + - ]: 10 : my_qptopt = 1; if (present(qptopt)) my_qptopt = qptopt
1711 [ + + ]: 10 : do_qintp = .True.; if (present(qintp)) do_qintp = qintp
1712 : 10 : nsppol = gams%nsppol; natom3 = gams%natom3
1713 : :
1714 [ - + ]: 10 : if (gams%prteliash == 3) then
1715 [ # # # # : 0 : ABI_MALLOC(gamma_ph_ee, (gams%nene, gams%nene, gams%natom3, gams%nsppol))
# # # # #
# # # # #
# # # # #
# # # #
# ]
1716 : : end if
1717 : :
1718 [ + + ]: 10 : if (do_qintp) then
1719 : : ! Generate fine q-mesh, find the IBZ and the corresponding weights.
1720 : 5 : qptrlatt = 0; qptrlatt(1,1) = ngqpt(1); qptrlatt(2,2) = ngqpt(2); qptrlatt(3,3) = ngqpt(3)
1721 : :
1722 : : call kpts_ibz_from_kptrlatt(cryst, qptrlatt, my_qptopt, nqshift, qshift, nqibz, qibz, wtq, nqbz, qbz, &
1723 : 5 : new_kptrlatt=new_qptrlatt, new_shiftk=my_qshift)
1724 [ - + ]: 5 : ABI_FREE(qbz)
1725 : :
1726 : : ! Store quantities that cannot be easily (and safely) calculated if we only know the IBZ.
1727 [ + + ]: 20 : a2f%ngqpt = ngqpt; a2f%nqshift = size(my_qshift, dim=2)
1728 [ - + + - : 15 : ABI_MALLOC(a2f%qshift, (3, a2f%nqshift))
+ - + - -
+ - + -
+ ]
1729 [ + - + - : 30 : a2f%qshift = my_qshift
- + - - -
- - - + +
+ + ]
1730 [ - + ]: 5 : ABI_FREE(my_qshift)
1731 : :
1732 : : else
1733 : : ! No interpolation. Use q-mesh parameters from gams%
1734 [ + + ]: 20 : a2f%ngqpt = gams%ngqpt; a2f%nqshift = 1
1735 : 5 : nqibz = gams%nqibz
1736 [ - + + - : 15 : ABI_MALLOC(qibz, (3, nqibz))
+ - + - -
+ - + ]
1737 [ - + + - : 15 : ABI_MALLOC(wtq, (nqibz))
+ - + - -
+ - + ]
1738 [ - + - + ]: 5 : ABI_MALLOC(a2f%qshift, (3, a2f%nqshift))
1739 [ + - + - : 320 : qibz = gams%qibz; wtq = gams%wtq
- + - - -
- - - + +
+ + + - -
+ - - - -
+ + ]
1740 [ + + + + ]: 25 : a2f%qshift = zero ! Note: assuming q-mesh centered on Gamma.
1741 : : end if
1742 : :
1743 : 10 : call cwtime_report(" a2fw_init, q-setup:", cpu, wall, gflops)
1744 : :
1745 : : ! Define Min and max frequency for the mesh (enlarge it a bit)
1746 : 10 : omega_min = wminmax(1); omega_max = wminmax(2)
1747 : 10 : omega_min = omega_min - 0.1*abs(omega_min)
1748 [ - + ]: 10 : if (omega_min >= zero) omega_min = one/Ha_meV
1749 : 10 : omega_max = omega_max + 0.1*abs(omega_max)
1750 : :
1751 : 10 : a2f%nsppol = nsppol; a2f%natom3 = gams%natom3; a2f%smear = smear
1752 : 10 : a2f%omega_min = omega_min; a2f%omega_max = omega_max
1753 : 10 : nomega = int((omega_max - omega_min) / wstep); a2f%nomega = nomega; a2f%wstep = wstep
1754 : 10 : a2f%nene = gams%nene
1755 : 10 : a2f%enemin = gams%enemin
1756 : 10 : a2f%deltaene = gams%deltaene
1757 : :
1758 [ - + + - : 30 : ABI_MALLOC(a2f%n0, (nsppol))
+ - + - -
+ - + -
+ ]
1759 [ + - - + : 30 : a2f%n0 = gams%n0
- - - - -
- + + ]
1760 : : ! Build linear mesh.
1761 [ - + + - : 30 : ABI_MALLOC(a2f%omega, (nomega))
+ - + - -
+ - + -
+ ]
1762 [ + - + - : 4750 : a2f%omega = arth(omega_min, wstep, nomega)
- + - - +
+ ]
1763 : :
1764 [ - + + - : 19020 : ABI_CALLOC(a2f%vals, (nomega,0:natom3, nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + + +
+ + + + ]
1765 [ - + + - : 19010 : ABI_CALLOC(a2f%lambdaw, (nomega,0:natom3, nsppol))
- + + - -
+ + - - +
- + - + +
+ + + +
+ ]
1766 : :
1767 [ - + ]: 10 : if (gams%prteliash == 3) then
1768 [ # # # # : 0 : ABI_CALLOC(a2f%vals_ee, (gams%nene, gams%nene, nomega, nsppol))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
1769 : : end if
1770 : :
1771 [ - + + - : 20 : ABI_MALLOC(tmp_a2f, (nomega))
- + - + ]
1772 : :
1773 [ + + ]: 10 : if (ph_intmeth == 2) then
1774 : : ! Prepare tetrahedron integration.
1775 : 8 : call cwtime(cpu, wall, gflops, "start")
1776 : :
1777 : 8 : qptrlatt = 0; qptrlatt(1, 1) = a2f%ngqpt(1); qptrlatt(2, 2) = a2f%ngqpt(2); qptrlatt(3, 3) = a2f%ngqpt(3)
1778 : 8 : tetra_q = tetra_from_kptrlatt(cryst, my_qptopt, qptrlatt, a2f%nqshift, a2f%qshift, nqibz, qibz, comm, msg, ierr)
1779 [ - + ]: 8 : if (ierr /= 0) ABI_ERROR(msg)
1780 : :
1781 [ - + + - : 1971 : ABI_CALLOC(lambda_tetra, (nqibz, natom3, nsppol))
- + + - -
+ + - + -
+ - - + -
+ + + + +
+ + ]
1782 [ - + + - : 1955 : ABI_CALLOC(phfreq_tetra, (nqibz, natom3))
- + + - +
- + - - +
- + + + +
+ ]
1783 : 8 : cnt = 0
1784 [ + + ]: 641 : do iq_ibz = 1, nqibz
1785 [ + - ]: 633 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
1786 : 633 : call ifc%fourq(cryst, qibz(:,iq_ibz), phfrq, displ_cart)
1787 : : ! save for tetrahedron interpolation
1788 [ + + ]: 2540 : phfreq_tetra(iq_ibz,:) = phfrq(:)
1789 : : end do
1790 : 8 : call xmpi_sum(phfreq_tetra, comm, ierr)
1791 : 16 : call cwtime_report(" a2fw_init%tetra", cpu, wall, gflops)
1792 : : end if
1793 : :
1794 : 10 : call cwtime(cpu, wall, gflops, "start")
1795 : :
1796 : : ! DEV_MJV
1797 : : !open(unit=900, file="a2fvals_ee.dat"); write (900,*) '# do_qintp ', do_qintp
1798 : :
1799 : : ! Loop over spins and q-points in the IBZ. For the moment parallelize over iq_ibz
1800 [ + + ]: 20 : do spin=1,nsppol
1801 : 10 : cnt = 0
1802 [ + + ]: 806 : do iq_ibz=1,nqibz
1803 : : ! TODO: for the moment the memory is not distributed, only the calculation exception is vals_ee
1804 [ - + ]: 786 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
1805 : :
1806 : : ! Interpolate or evaluate gamma directly.
1807 [ + + ]: 786 : if (do_qintp) then
1808 [ - + ]: 725 : if (gams%prteliash == 3) then
1809 : 0 : call gams%interp(cryst,ifc,spin,qibz(:,iq_ibz),phfrq,gamma_ph,lambda_ph,displ_cart,gamma_ph_ee=gamma_ph_ee(:,:,:,spin))
1810 : : else
1811 : 725 : call gams%interp(cryst,ifc,spin,qibz(:,iq_ibz),phfrq,gamma_ph,lambda_ph,displ_cart)
1812 : : end if
1813 : : else
1814 [ - + ]: 61 : if (gams%prteliash == 3) then
1815 : 0 : call gams%eval_qibz(cryst,ifc,iq_ibz,spin,phfrq,gamma_ph,lambda_ph,displ_cart,gamma_ph_ee=gamma_ph_ee(:,:,:,spin))
1816 : : else
1817 : 61 : call gams%eval_qibz(cryst,ifc,iq_ibz,spin,phfrq,gamma_ph,lambda_ph, displ_cart)
1818 : : end if
1819 : : end if
1820 : :
1821 : 10 : select case (ph_intmeth)
1822 : : case (1)
1823 : : ! Gaussian: Add all contributions from the phonon modes at this qpoint to a2f
1824 : : ! (note that unstable modes are included).
1825 [ - + + - : 612 : ABI_MALLOC(tmp_gaussian, (nomega, natom3))
- + + - +
- + - - +
- + ]
1826 [ + + ]: 612 : do mu=1,natom3
1827 [ + + ]: 217566 : tmp_a2f = zero
1828 [ + + ]: 217566 : do iw=1,nomega
1829 : 217107 : xx = a2f%omega(iw) - phfrq(mu)
1830 : 217107 : tmp_gaussian(iw, mu) = gaussian(xx, smear)
1831 : 217566 : tmp_a2f(iw) = tmp_a2f(iw) + tmp_gaussian(iw,mu) * lambda_ph(mu) * abs(phfrq(mu))
1832 : : end do
1833 [ + + ]: 217719 : a2f%vals(:,mu,spin) = a2f%vals(:,mu,spin) + tmp_a2f * wtq(iq_ibz)
1834 : : end do
1835 : :
1836 [ - + ]: 153 : if (gams%prteliash == 3) then
1837 : : ! reset phfrq for low freq modes
1838 [ # # ]: 0 : invphfrq = zero
1839 [ # # ]: 0 : do mu=1,natom3
1840 [ # # ]: 0 : if (abs(phfrq(mu)) > EPHTK_WTOL) invphfrq(mu) = one / abs(phfrq(mu))
1841 : : end do
1842 : :
1843 [ # # ]: 0 : do iene= 1, gams%nene
1844 [ # # ]: 0 : do jene= 1, gams%nene
1845 [ # # ]: 0 : tmp_a2f = zero
1846 : : ! TODO: following block is just a GEMM
1847 [ # # ]: 0 : do mu=1,natom3
1848 [ # # ]: 0 : do iw=1,nomega
1849 : 0 : tmp_a2f(iw) = tmp_a2f(iw) + tmp_gaussian(iw,mu) * gamma_ph_ee(jene,iene,mu,spin) * invphfrq(mu)
1850 : : end do
1851 : : end do
1852 : :
1853 [ # # ]: 0 : a2f%vals_ee(jene, iene, :, spin) = a2f%vals_ee(jene, iene, :, spin) + tmp_a2f(:) * wtq(iq_ibz)
1854 : : !if (iene == gams%nene/2 .and. jene == gams%nene/2) then
1855 : : ! write (900, '(a,E20.10,2x,2x,I6,3E20.10)') '#', wtq(iq_ibz), iq_ibz, invphfrq(1:3)
1856 : : ! do iw=1,nomega
1857 : : ! write (900, '(i6,2x,E20.10,2x,3E20.10,2x,3E20.10)') iw, a2f%vals_ee(jene, iene, iw, spin), &
1858 : : ! gamma_ph_ee(jene,iene,:,spin), tmp_gaussian(iw,1:3)
1859 : : ! end do
1860 : : ! write (900,*)
1861 : : !end if
1862 : : end do
1863 : : end do
1864 : : end if
1865 : :
1866 [ - + ]: 153 : ABI_FREE(tmp_gaussian)
1867 : :
1868 : : case (2)
1869 : : ! Tetra: store data.
1870 [ + + ]: 2532 : do mu=1,natom3
1871 : 2532 : lambda_tetra(iq_ibz, mu, spin) = lambda_ph(mu) * abs(phfrq(mu))
1872 : : end do
1873 : :
1874 [ - + ]: 633 : if (gams%prteliash == 3) then
1875 : 0 : ABI_ERROR("Eliashberg function with tetra not coded")
1876 : : end if
1877 : :
1878 : : case default
1879 [ + + - ]: 786 : ABI_ERROR(sjoin("Wrong ph_intmeth:", itoa(ph_intmeth)))
1880 : : end select
1881 : :
1882 : : end do ! iq_ibz
1883 : : end do ! spin
1884 : :
1885 : : !DEV_MJV
1886 : : !close(900)
1887 : :
1888 [ + + ]: 10 : if (ph_intmeth == 2) then
1889 : : ! workspace for tetra.
1890 [ - + + - : 24 : ABI_MALLOC(wdt, (nomega, 2))
+ - + - -
+ - + ]
1891 : :
1892 : : ! For each mode get its contribution
1893 [ + + ]: 16 : do spin=1,nsppol
1894 [ + + ]: 40 : do mu=1,natom3
1895 : 24 : cnt = 0
1896 [ + + ]: 1931 : do iq_ibz=1,nqibz
1897 : : ! NB: if we are interpolating the gamma, nqibz > gams%nqibz
1898 [ + - ]: 1899 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
1899 : :
1900 : 1899 : call tetra_q%get_onewk(iq_ibz, gams%bcorr, nomega, nqibz, phfreq_tetra(:,mu), omega_min, omega_max, one, wdt)
1901 [ + + + + ]: 1802151 : wdt = wdt * wtq(iq_ibz)
1902 : :
1903 : : ! Accumulate (Integral of a2F is computed afterwards)
1904 [ + + ]: 900150 : a2f%vals(:,mu,spin) = a2f%vals(:,mu,spin) + wdt(:,1) * lambda_tetra(iq_ibz,mu,spin)
1905 : : !a2f%lambdaw(:,mu,spin) = a2f%lambdaw(:,mu,spin) + wdt(:,2) * lambda_tetra(iq_ibz, mu, spin)
1906 : : end do
1907 : : end do
1908 : : end do
1909 : :
1910 : : ! Free memory allocated for tetra.
1911 [ - + ]: 8 : ABI_FREE(wdt)
1912 [ - + ]: 8 : ABI_FREE(lambda_tetra)
1913 [ - + ]: 8 : ABI_FREE(phfreq_tetra)
1914 : 8 : call tetra_q%free()
1915 : : end if
1916 : :
1917 : : ! Collect final results on each node
1918 : 10 : call xmpi_sum(a2f%vals, comm, ierr)
1919 [ + + ]: 20 : do spin=1,nsppol
1920 [ + + + + ]: 18940 : a2f%vals(:,0,spin) = sum(a2f%vals(:,1:natom3,spin), dim=2)
1921 : : ! previously would divide by g(eF, spin)
1922 : : !a2f%vals(:,:,spin) = a2f%vals(:,:,spin) / (two_pi*a2f%n0(spin))
1923 : : end do
1924 : :
1925 [ - + ]: 10 : if (gams%prteliash == 3) then
1926 : : ! For the moment vals_ee only works with gaussians
1927 : 0 : call xmpi_sum(a2f%vals_ee, comm, ierr)
1928 [ # # ]: 0 : do spin=1,nsppol
1929 [ # # # # : 0 : a2f%vals_ee(:,:,:,spin) = a2f%vals_ee(:,:,:,spin) / (two * pi * gams%n0(spin))
# # ]
1930 : : end do
1931 : : end if
1932 : :
1933 : 10 : call cwtime_report(" a2fw_init, a2f_eval:", cpu, wall, gflops)
1934 : :
1935 [ - + + - : 20 : ABI_MALLOC(a2f_1mom, (nomega))
- + - + ]
1936 [ - + + - : 20 : ABI_MALLOC(a2flogmom, (nomega))
- + - + ]
1937 [ - + + - : 20 : ABI_MALLOC(a2flogmom_int, (nomega))
- + - + ]
1938 : :
1939 : : !call a2fw_print_info()
1940 : :
1941 : : ! Compute lambda(w) resolved in spin and phonon mode.
1942 : : ! lambda(w) = int a2F(w')/w' dw'
1943 [ + + ]: 20 : do spin=1,nsppol
1944 [ + + ]: 60 : do mu=0,natom3
1945 : :
1946 [ + + ]: 18960 : do iw=1,nomega
1947 : 18920 : ww = a2f%omega(iw)
1948 [ + - ]: 18960 : if (abs(ww) > EPHTK_WTOL) then
1949 : 18920 : a2f_1mom(iw) = a2f%vals(iw, mu, spin) / abs(ww)
1950 : : else
1951 : 0 : a2f_1mom(iw) = zero
1952 : : end if
1953 : : end do
1954 : :
1955 : 50 : call simpson_int(nomega, wstep, a2f_1mom, a2f%lambdaw(:, mu, spin))
1956 : : end do
1957 : : end do
1958 : :
1959 : : ! print log moments of the alpha^2 F function (for each spin, note degeneracy factor).
1960 : 10 : spinfactor = int(2 / nsppol / gams%nspinor)
1961 [ + + ]: 20 : do spin=1,nsppol
1962 : 10 : a2f_1d => a2f%vals(:,0,spin)
1963 : :
1964 : 10 : lambda_iso = a2f%get_moment(0, spin)
1965 : :
1966 : : ! Get log moment of alpha^2F.
1967 [ + + ]: 4740 : a2flogmom = zero
1968 [ + + ]: 4740 : do iw=1,nomega
1969 : 4730 : omega = a2f%omega(iw)
1970 [ + - ]: 4740 : if (abs(omega) > EPHTK_WTOL) then
1971 : : !a2flogmom(iw) = (two / lambda_iso) * a2f_1d(iw) * log(abs(omega)) / abs(omega)
1972 : : ! I (WHO??? GMATTEO?) think this is the correct expression.
1973 : 4730 : a2flogmom(iw) = (spinfactor / lambda_iso) * a2f_1d(iw) * log(abs(omega)) / abs(omega)
1974 : : end if
1975 : : end do
1976 : 10 : call simpson_int(nomega, wstep, a2flogmom, a2flogmom_int)
1977 : 10 : omega_log = exp(a2flogmom_int(nomega))
1978 : :
1979 : 10 : mustar = 0.12
1980 : 10 : tc_macmill = omega_log/1.2_dp * exp((-1.04_dp*(one+lambda_iso)) / (lambda_iso-mustar*(one+0.62_dp*lambda_iso)))
1981 : :
1982 [ + - ]: 20 : if (my_rank == master) then
1983 : 10 : ount = std_out
1984 [ - + ]: 10 : if (nsppol > 1) then
1985 : 0 : write(msg,'(3a)') ch10,' Warning: some of the following quantities should be integrated over spin', ch10
1986 : 0 : call wrtout(ount, msg)
1987 : : end if
1988 : :
1989 [ + + ]: 10 : if (do_qintp) then
1990 : 5 : write(ount,'(a,i3)') ' Superconductivity: isotropic evaluation of parameters from electron-phonon coupling (interpolated) for spin ', spin
1991 : : else
1992 : 5 : write(ount,'(a,i3)') ' Superconductivity: isotropic evaluation of parameters from electron-phonon coupling (coarse grid) for spin ', spin
1993 : : endif
1994 : 10 : write(ount,'(a,es16.6)') ' isotropic lambda = ',lambda_iso
1995 : 10 : write(ount,'(a,es16.6,a,es16.6,a)' )' omegalog = ',omega_log,' (Ha) ', omega_log * Ha_K, ' (Kelvin) '
1996 : 10 : write(ount,'(a,es16.6,a,es16.6,a)') ' MacMillan Tc = ',tc_macmill,' (Ha) ', tc_macmill * Ha_K, ' (Kelvin) '
1997 : 10 : write(ount,"(a)") ' Positive moments of alpha2F:'
1998 : 10 : write(ount,'(a,es16.6)' ) ' lambda <omega^2> = ',a2f%get_moment(2, spin)
1999 : 10 : write(ount,'(a,es16.6)' ) ' lambda <omega^3> = ',a2f%get_moment(3, spin)
2000 : 10 : write(ount,'(a,es16.6)' ) ' lambda <omega^4> = ',a2f%get_moment(4, spin)
2001 : 10 : write(ount,'(a,es16.6)' ) ' lambda <omega^5> = ',a2f%get_moment(5, spin)
2002 : : end if
2003 : : end do
2004 : :
2005 : : ! Calculate the temperature dependence of the a2f(e,e',w) integrals (G_0(T_e)
2006 : : ! as in PRL 110 016405 (2013) [[cite:Arnaud2013]])
2007 [ - + - - ]: 10 : if (gams%prteliash == 3 .and. my_rank == master) then
2008 : 0 : ntemp = 100
2009 : 0 : min_temp = zero
2010 : 0 : delta_temp = 40._dp ! Kelvin
2011 [ # # # # : 0 : ABI_MALLOC(a2feew_partial, (a2f%nene))
# # # # #
# # # ]
2012 [ # # # # : 0 : ABI_MALLOC(a2feew_partial_int, (a2f%nene))
# # # # ]
2013 [ # # # # : 0 : ABI_MALLOC(a2feew_w, (nomega))
# # # # ]
2014 [ # # # # : 0 : ABI_MALLOC(a2feew_w_int, (nomega))
# # # # ]
2015 : :
2016 [ # # ]: 0 : if (open_file("EPC_strength_aafo_T.dat", msg, newunit=ount, form="formatted", action="write", status="unknown") /= 0) then
2017 : 0 : ABI_ERROR(msg)
2018 : : end if
2019 : :
2020 : 0 : write(ount, "(a)")"# temp_el, G_0(T_e) in W/m^3/K, spin"
2021 [ # # ]: 0 : do spin=1,nsppol
2022 [ # # ]: 0 : do itemp = 1, ntemp
2023 : 0 : temp_el = min_temp + (itemp-1)*delta_temp
2024 : :
2025 : : ! TODO: need to evolve the chemical potential with T, but I do not have access to the full DOS here!!
2026 : : ! possible fix using local information on DOS variation near E_F...
2027 : 0 : chempot = a2f%enemin + half * a2f%nene * a2f%deltaene
2028 : :
2029 [ # # ]: 0 : do iw=1,nomega
2030 : 0 : omega = a2f%omega(iw)
2031 : 0 : jene_jump = nint(omega/a2f%deltaene)
2032 [ # # ]: 0 : a2feew_partial = zero
2033 [ # # ]: 0 : do iene=1,a2f%nene
2034 : 0 : ene1 = a2f%enemin + (iene-1)*a2f%deltaene
2035 : 0 : ene2 = ene1 + omega
2036 : : a2feew_partial(iene) = a2f%vals_ee(min(a2f%nene,iene+jene_jump), iene, iw, spin) * &
2037 : 0 : (fermi_dirac(ene1, chempot, temp_el/Ha_K) - fermi_dirac(ene2, chempot, temp_el/Ha_K))
2038 : : end do
2039 : 0 : call simpson_int(a2f%nene, a2f%deltaene, a2feew_partial, a2feew_partial_int)
2040 : 0 : a2feew_w(iw) = a2feew_partial_int(a2f%nene)
2041 : : end do
2042 : 0 : call simpson_int(nomega, wstep, a2feew_w, a2feew_w_int)
2043 : 0 : G0 = a2feew_w_int(nomega) * two_pi * a2f%n0(spin) / cryst%ucvol
2044 : : ! conversion factor for G0 to SI units = Ha_J / Time_Sec / (Bohr_meter)**3 ~ 1.2163049915755545e+30
2045 : 0 : write(ount, "(2(e20.10,2x),i5)") temp_el, G0 * kb_HaK / Time_Sec / (Bohr_meter)**3, spin !* Ha_J???
2046 : : end do
2047 : : end do
2048 : 0 : close(ount)
2049 : :
2050 [ # # ]: 0 : ABI_FREE(a2feew_partial)
2051 [ # # ]: 0 : ABI_FREE(a2feew_partial_int)
2052 [ # # ]: 0 : ABI_FREE(a2feew_w)
2053 [ # # ]: 0 : ABI_FREE(a2feew_w_int)
2054 [ # # ]: 0 : ABI_FREE(gamma_ph_ee)
2055 : : end if
2056 : :
2057 [ - + ]: 10 : ABI_FREE(tmp_a2f)
2058 [ - + ]: 10 : ABI_FREE(a2f_1mom)
2059 [ - + ]: 10 : ABI_FREE(a2flogmom)
2060 [ - + ]: 10 : ABI_FREE(a2flogmom_int)
2061 [ - + ]: 10 : ABI_FREE(qibz)
2062 [ - + ]: 10 : ABI_FREE(wtq)
2063 : :
2064 [ + - - + : 70 : end subroutine a2fw_init
- + - + -
+ - - - -
- + - - -
- - + - +
- + - + -
+ ]
2065 : : !!***
2066 : :
2067 : : !----------------------------------------------------------------------
2068 : :
2069 : : !!****f* m_phgamma/a2fw_get_moment
2070 : : !! NAME
2071 : : !! a2fw_get_moment
2072 : : !!
2073 : : !! FUNCTION
2074 : : !! Compute \int dw [a2F(w)/w] w^n. From Allen PRL 59 1460 [[cite:Allen1987]].
2075 : : !! See also [[cite:Grimvall1981]], Eq 6.72 page 175)
2076 : : !!
2077 : : !! INPUTS
2078 : : !! nn=Value of n
2079 : : !! spin=The spin component. 0 to sum over spins.
2080 : : !!
2081 : : !! OUTPUT
2082 : : !! a2fw_get_moment = \int dw [a2F(w)/w] w^n
2083 : : !! [out_int(x)] = \int^{x} dw [a2F(w)/w] w^n
2084 : : !!
2085 : : !! SOURCE
2086 : :
2087 : 50 : real(dp) function a2fw_get_moment(a2f, nn, spin, out_int)
2088 : :
2089 : : !Arguments ------------------------------------
2090 : : class(a2fw_t),intent(in) :: a2f
2091 : : integer,intent(in) :: spin,nn
2092 : : !arrays
2093 : : real(dp),intent(out),optional :: out_int(a2f%nomega)
2094 : :
2095 : : !Local variables -------------------------
2096 : : !scalars
2097 : : integer :: iw
2098 : : real(dp) :: omg, omg_nm1
2099 : : !arrays
2100 : 50 : real(dp) :: ff(a2f%nomega), int_ff(a2f%nomega), values(a2f%nomega)
2101 : : ! *********************************************************************
2102 : :
2103 : : ! Construct the integrand function. [a2F(w)/w] w^n
2104 [ + + + + ]: 47350 : ff = zero; int_ff = zero
2105 : :
2106 [ - + ]: 50 : if (spin == 0) then
2107 [ # # ]: 0 : if (a2f%nsppol == 1) then
2108 [ # # ]: 0 : values = a2f%vals(:, 0, 1)
2109 : : !if (a2f%nspinor == 1) values = two * values
2110 [ # # ]: 0 : else if (a2f%nsppol == 2) then
2111 [ # # # # ]: 0 : values = sum(a2f%vals(:, 0, :), dim=2)
2112 : : end if
2113 : :
2114 : : else
2115 [ + + ]: 23700 : values = a2f%vals(:, 0, spin)
2116 : : end if
2117 : :
2118 [ + + ]: 50 : if (nn - 1 >= 0) then
2119 [ + + ]: 18960 : do iw=1,a2f%nomega
2120 : 18920 : omg = a2f%omega(iw)
2121 : 18920 : omg_nm1 = omg ** (nn - 1)
2122 : 18960 : ff(iw) = values(iw) * omg_nm1
2123 : : end do
2124 : : else
2125 [ + + ]: 4740 : do iw=1,a2f%nomega
2126 : 4730 : omg = a2f%omega(iw)
2127 [ + - ]: 4730 : omg_nm1 = zero; if (abs(omg) > EPHTK_WTOL) omg_nm1 = omg**(nn-1)
2128 : 4740 : ff(iw) = values(iw) * omg_nm1
2129 : : end do
2130 : : end if
2131 : :
2132 : : ! Integration with simpson rule on a linear mesh.
2133 : 50 : call simpson_int(a2f%nomega, a2f%wstep, ff, int_ff)
2134 : :
2135 : 50 : a2fw_get_moment = int_ff(a2f%nomega)
2136 [ - + - - ]: 50 : if (present(out_int)) out_int = int_ff
2137 : :
2138 : 50 : end function a2fw_get_moment
2139 : : !!***
2140 : :
2141 : : !----------------------------------------------------------------------
2142 : :
2143 : : !!****f* m_phgamma/a2fw_tr_moment
2144 : : !! NAME
2145 : : !! a2fw_tr_moment
2146 : : !!
2147 : : !! FUNCTION
2148 : : !! Compute \int dw [a2F_tr(w)/w] w^n
2149 : : !! From Allen PRL 59 1460 [[cite:Allen1987]] and later PRB papers.
2150 : : !! See also [[cite:Grimvall1981]] book.
2151 : : !!
2152 : : !! INPUTS
2153 : : !! nn=Value of n
2154 : : !! spin=The spin component
2155 : : !!
2156 : : !! OUTPUT
2157 : : !! a2fw_tr_moment = \int dw [a2F_tr(w)/w] w^n
2158 : : !! [out_int(x)] = \int^{x} dw [a2F_tr(w)/w] w^n
2159 : : !!
2160 : : !! SOURCE
2161 : :
2162 [ - + ]: 50 : function a2fw_tr_moment(a2f_tr, nn, spin, out_int)
2163 : :
2164 : : !Arguments ------------------------------------
2165 : : !scalars
2166 : : class(a2fw_tr_t),intent(in) :: a2f_tr
2167 : : integer,intent(in) :: spin,nn
2168 : : !arrays
2169 : : real(dp),intent(out),optional :: out_int(a2f_tr%nomega,3,3)
2170 : : real(dp) :: a2fw_tr_moment(3,3)
2171 : :
2172 : : !Local variables -------------------------
2173 : : !scalars
2174 : : integer :: iw, idir, jdir
2175 : : real(dp) :: omg,omg_nm1
2176 : : !arrays
2177 [ - + ]: 50 : real(dp) :: ff(a2f_tr%nomega),int_ff(a2f_tr%nomega)
2178 : : ! *********************************************************************
2179 : :
2180 [ + + ]: 200 : do jdir = 1, 3
2181 [ + + ]: 650 : do idir = 1, 3
2182 : : ! Construct the integrand function. [a2F_tr(w)/w] w^n
2183 [ + + + + ]: 426150 : ff = zero; int_ff = zero
2184 : :
2185 [ + + ]: 450 : if (nn-1 >= 0) then
2186 [ + + ]: 170640 : do iw=1,a2f_tr%nomega
2187 : 170280 : omg = a2f_tr%omega(iw)
2188 : 170280 : omg_nm1 = omg ** (nn-1)
2189 : 170640 : ff(iw) = a2f_tr%vals_tr(iw,idir,jdir,0,spin) * omg_nm1
2190 : : end do
2191 : : else
2192 [ + + ]: 42660 : do iw=1,a2f_tr%nomega
2193 : 42570 : omg = a2f_tr%omega(iw)
2194 [ + - ]: 42570 : omg_nm1 = zero; if (abs(omg) > EPHTK_WTOL) omg_nm1 = omg**(nn-1)
2195 : 42660 : ff(iw) = a2f_tr%vals_tr(iw,idir,jdir,0,spin) * omg_nm1
2196 : : end do
2197 : : end if
2198 : :
2199 : : ! Integration with simpson rule on a linear mesh.
2200 : 450 : call simpson_int(a2f_tr%nomega, a2f_tr%wstep, ff, int_ff)
2201 : :
2202 : 450 : a2fw_tr_moment(idir, jdir) = int_ff(a2f_tr%nomega)
2203 [ - + - - ]: 600 : if (present(out_int)) out_int(:,idir,jdir) = int_ff(:)
2204 : : end do
2205 : : end do
2206 : :
2207 : : end function a2fw_tr_moment
2208 : : !!***
2209 : :
2210 : : !----------------------------------------------------------------------
2211 : :
2212 : : !!****f* m_phgamma/a2fw_write
2213 : : !! NAME
2214 : : !! a2fw_write
2215 : : !!
2216 : : !! FUNCTION
2217 : : !! Write alpha^2F(w) to an external file in text form
2218 : : !!
2219 : : !! INPUTS
2220 : : !! basename=Filename for output.
2221 : : !! post=String appended to netcdf variables e.g. _qcoarse, _qintp
2222 : : !! ncid=Netcdf file handler. Set it to nctk_noid to disable output.
2223 : : !!
2224 : : !! OUTPUT
2225 : : !! Output is written to file. This routine should be called by one MPI proc.
2226 : : !!
2227 : : !! SOURCE
2228 : :
2229 : 10 : subroutine a2fw_write(a2f, basename, post, ncid)
2230 : :
2231 : : !Arguments ------------------------------------
2232 : : !scalars
2233 : : class(a2fw_t),intent(in) :: a2f
2234 : : character(len=*),intent(in) :: basename, post
2235 : : integer,intent(in) :: ncid
2236 : :
2237 : : !Local variables -------------------------
2238 : : !scalars
2239 : : integer :: iw,spin,unt,ii,mu, ncerr
2240 : : character(len=500) :: dim1_name, msg
2241 : : character(len=fnlen) :: path
2242 : : ! *********************************************************************
2243 : :
2244 : : ! Write spin-resolved a2F(w)
2245 [ + - ]: 10 : path = strcat(basename, "_A2FW")
2246 [ - + ]: 10 : if (open_file(path, msg, newunit=unt, form="formatted", action="write", status="unknown") /= 0) then
2247 : 0 : ABI_ERROR(msg)
2248 : : end if
2249 : :
2250 : 10 : call write_a2fw_header()
2251 : :
2252 [ + - ]: 10 : if (a2f%nsppol == 1) then
2253 : 10 : write(unt,'(a)')"# Frequency, a2F(w), lambda(w)"
2254 [ + + ]: 4740 : do iw=1,a2f%nomega
2255 : 4740 : write(unt,*) a2f%omega(iw), a2f%vals(iw,0,1), a2f%lambdaw(iw,0,1)
2256 : : end do
2257 : :
2258 : : else
2259 : 0 : write(unt,'(a)')"# Frequency, a2F_tot(w), lambda_tot(w)dw, a2F_spin1(w), lambda_spin1(w) ..."
2260 [ # # ]: 0 : do iw=1,a2f%nomega
2261 : 0 : write(unt,'(E20.10,3x,3(2E20.10, 2x))') a2f%omega(iw), &
2262 [ # # # # ]: 0 : sum(a2f%vals(iw,0,:)) , sum(a2f%lambdaw(iw,0,:)), & ! TOT
2263 : 0 : a2f%vals(iw,0,1) , a2f%lambdaw(iw,0,1), & ! UP
2264 : 0 : a2f%vals(iw,0,2) , a2f%lambdaw(iw,0,2) ! DOWN
2265 : : end do
2266 : : end if
2267 : :
2268 : 10 : close(unt)
2269 : :
2270 : : ! Write phonon contributions to a2F(w)
2271 [ + - ]: 10 : path = strcat(basename, "_PH_A2FW")
2272 [ - + ]: 10 : if (open_file(path, msg, newunit=unt, form="formatted", action="write", status="unknown") /= 0) then
2273 : 0 : ABI_ERROR(msg)
2274 : : end if
2275 : 10 : call write_a2fw_header()
2276 : :
2277 [ + - ]: 10 : if (a2f%nsppol == 1) then
2278 [ + + ]: 50 : do mu=0,a2f%natom3
2279 : 40 : write(unt,'(a,i0)')"# Phonon mode ",mu
2280 : 40 : write(unt,'(a)')"# Frequency, a2F(w), lambda(w)"
2281 [ + + ]: 18960 : do iw=1,a2f%nomega
2282 : 18960 : write(unt,*) a2f%omega(iw), a2f%vals(iw,mu,1), a2f%lambdaw(iw,mu,1)
2283 : : end do
2284 [ + + ]: 130 : do ii=1,2; write(unt,'(a)')""; end do
2285 : : end do
2286 : :
2287 : : else
2288 [ # # ]: 0 : do mu=0,a2f%natom3
2289 : 0 : write(unt,'(a,i0)')"# Phonon mode ",mu
2290 : 0 : write(unt,'(a)')"# Frequency, a2F_tot(w), lambda_tot(w)dw, a2F_spin1(w), lambda_spin1(w) ..."
2291 [ # # ]: 0 : do iw=1,a2f%nomega
2292 : 0 : write(unt,'(E20.10,3x,3(2E20.10, 2x))') a2f%omega(iw), &
2293 [ # # # # ]: 0 : sum(a2f%vals(iw,mu,:)), sum(a2f%lambdaw(iw,mu,:)), & ! TOT
2294 : 0 : a2f%vals(iw,mu,1) , a2f%lambdaw(iw,mu,1), & ! UP
2295 : 0 : a2f%vals(iw,mu,2) , a2f%lambdaw(iw,mu,2) ! DOWN
2296 : : end do
2297 : : end do
2298 : : end if
2299 : :
2300 : 10 : close(unt)
2301 : :
2302 [ + - ]: 10 : if (ncid /= nctk_noid) then
2303 : : ! Define dimensions.
2304 [ + - ]: 10 : dim1_name = strcat("a2f_nomega", post)
2305 : : ncerr = nctk_def_dims(ncid, [ &
2306 : : nctkdim_t(dim1_name, a2f%nomega), &
2307 : : nctkdim_t("natom3p1", a2f%natom3 + 1), nctkdim_t("number_of_spins", a2f%nsppol) &
2308 [ + + ]: 40 : ], defmode=.True.)
2309 [ - + ]: 10 : NCF_CHECK(ncerr)
2310 : :
2311 : : ncerr = nctk_def_arrays(ncid, [ &
2312 : : nctkarr_t(strcat('a2f_mesh', post), "dp", dim1_name), &
2313 : : nctkarr_t(strcat('a2f_values', post), "dp", strcat(dim1_name, ", natom3p1, number_of_spins")), &
2314 : : nctkarr_t(strcat('a2f_lambdaw', post), "dp", strcat(dim1_name, ", natom3p1, number_of_spins")) &
2315 [ + - + - : 40 : ])
+ - + - +
- + + ]
2316 [ - + ]: 10 : NCF_CHECK(ncerr)
2317 : :
2318 [ - + ]: 10 : NCF_CHECK(nctk_set_datamode(ncid))
2319 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, strcat("a2f_mesh", post)), a2f%omega))
2320 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, strcat("a2f_values", post)), a2f%vals))
2321 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, strcat("a2f_lambdaw", post)), a2f%lambdaw))
2322 : : end if
2323 : :
2324 : : contains
2325 : :
2326 : 20 : subroutine write_a2fw_header()
2327 : :
2328 : : ! Output the header.
2329 : 20 : write(unt,'(a)') '#'
2330 : 20 : write(unt,'(a)') '# ABINIT package: a2F(w) file'
2331 : 20 : write(unt,'(a)') '#'
2332 : 20 : write(unt,'(a)') '# a2F(w) function integrated over the FS. omega in a.u.'
2333 [ + - ]: 20 : write(unt,'(2a)') '# ngqpt: ',trim(ltoa(a2f%ngqpt))
2334 : 20 : write(unt,'(a,i0,3(a,e16.6))')'# number of frequencies: ',a2f%nomega," between omega_min: ",a2f%omega_min,&
2335 : 40 : ' Ha and omega_max: ',a2f%omega_max,' Ha with step:',a2f%wstep
2336 : 20 : write(unt,'(a,e16.6)') '# the smearing width for gaussians is ',a2f%smear
2337 [ + + ]: 40 : write(unt,'(a,e16.6)')"# Total DOS at Fermi level ",sum(a2f%n0)
2338 [ + + ]: 40 : do spin=1,a2f%nsppol
2339 : 40 : write(unt,"(a,i0,a,e16.6)")"# The DOS at Fermi level for spin ",spin," is ",a2f%n0(spin)
2340 : : end do
2341 [ + + ]: 60 : do ii=1,2; write(unt,'(a)') "# "; end do
2342 : :
2343 : 20 : end subroutine write_a2fw_header
2344 : :
2345 : : end subroutine a2fw_write
2346 : : !!***
2347 : :
2348 : : !----------------------------------------------------------------------
2349 : : !!****f* m_phgamma/a2fw_ee_write
2350 : : !! NAME
2351 : : !! a2fw_ee_write
2352 : : !!
2353 : : !! FUNCTION
2354 : : !! Write alpha^2F(e,e',w) to an external file in text form
2355 : : !!
2356 : : !! INPUTS
2357 : : !! basename=Filename for output.
2358 : : !!
2359 : : !! OUTPUT
2360 : : !! Output is written to file. This routine should be called by one MPI proc.
2361 : : !!
2362 : : !! SOURCE
2363 : :
2364 : 0 : subroutine a2fw_ee_write(a2f, basename)
2365 : :
2366 : : !Arguments ------------------------------------
2367 : : class(a2fw_t),intent(in) :: a2f
2368 : : character(len=*),intent(in) :: basename
2369 : :
2370 : : !Local variables -------------------------
2371 : : !scalars
2372 : : integer :: iw, spin, unt, ii, iene, jene
2373 : : real(dp) :: ene1, ene2
2374 : : character(len=500) :: msg
2375 : : character(len=fnlen) :: path
2376 : : ! *********************************************************************
2377 : :
2378 : : ! Write spin-resolved a2F(e,e',w)
2379 [ # # ]: 0 : path = strcat(basename, "_A2FEEW")
2380 [ # # ]: 0 : if (open_file(path, msg, newunit=unt, form="formatted", action="write", status="unknown") /= 0) then
2381 : 0 : ABI_ERROR(msg)
2382 : : end if
2383 : :
2384 : 0 : call write_a2fw_header()
2385 : :
2386 : 0 : write(unt,'(a)')"# en2, en1, Frequency, a2F_tot(w) (presently summed over spin)"
2387 [ # # ]: 0 : do iw=1,a2f%nomega
2388 [ # # ]: 0 : do iene=1,a2f%nene
2389 : 0 : ene1 = a2f%enemin + (iene-1)*a2f%deltaene
2390 [ # # ]: 0 : do jene=1,a2f%nene
2391 : 0 : ene2 = a2f%enemin + (jene-1)*a2f%deltaene
2392 [ # # ]: 0 : write(unt,'(3E20.10,2x,E20.10)') ene2, ene1, a2f%omega(iw), sum(a2f%vals_ee(jene,iene,iw,:)) ! TOT
2393 : : end do
2394 : : end do
2395 : : end do
2396 : :
2397 : 0 : close(unt)
2398 : :
2399 : : ! Write spin-resolved a2F(ef, ef, w)
2400 [ # # ]: 0 : path = strcat(basename, "_A2FW_reference")
2401 [ # # ]: 0 : if (open_file(path, msg, newunit=unt, form="formatted", status="unknown") /= 0) then
2402 : 0 : ABI_ERROR(msg)
2403 : : end if
2404 : :
2405 : 0 : call write_a2fw_header()
2406 : :
2407 : 0 : write(unt,'(a)')"# Frequency, a2F_tot(ef,ef,w) for comparison with normal a2F(w) (presently summed over spin)"
2408 : 0 : iene = int(a2f%nene/2)
2409 : 0 : jene = int(a2f%nene/2)
2410 [ # # ]: 0 : do iw=1,a2f%nomega
2411 [ # # ]: 0 : write(unt,'(E20.10,2x,E20.10)') a2f%omega(iw), sum(a2f%vals_ee(jene,iene,iw,:)) ! TOT
2412 : : end do
2413 : :
2414 : 0 : close(unt)
2415 : :
2416 : : contains
2417 : :
2418 : 0 : subroutine write_a2fw_header()
2419 : :
2420 : : ! Output the header.
2421 : 0 : write(unt,'(a)') '#'
2422 : 0 : write(unt,'(a)') '# ABINIT package: a2F(e,eprime,w) file'
2423 : 0 : write(unt,'(a)') '#'
2424 : 0 : write(unt,'(a)') '# a2F(e,eprime,w) function integrated over the FS. omega in a.u.'
2425 [ # # ]: 0 : write(unt,'(2a)') '# ngqpt: ',trim(ltoa(a2f%ngqpt))
2426 : 0 : write(unt,'(a,i0,2(a,e16.6))')'# number of energies: ',a2f%nene," from enemin: ",a2f%enemin,' Ha with step ', a2f%deltaene
2427 : 0 : write(unt,'(a,i0,3(a,e16.6))')'# number of frequencies: ',a2f%nomega," between omega_min: ",a2f%omega_min, &
2428 : 0 : ' Ha and omega_max: ',a2f%omega_max,' Ha with step:',a2f%wstep
2429 : 0 : write(unt,'(a,e16.6)') '# the smearing width for gaussians is ',a2f%smear
2430 [ # # ]: 0 : write(unt,'(a,e16.6)')"# Total DOS at Fermi level ",sum(a2f%n0)
2431 [ # # ]: 0 : do spin=1,a2f%nsppol
2432 : 0 : write(unt,"(a,i0,a,e16.6)")"# The DOS at Fermi level for spin ",spin," is ",a2f%n0(spin)
2433 : : end do
2434 [ # # ]: 0 : do ii=1,2
2435 : 0 : write(unt,'(a)') "# "
2436 : : end do
2437 : :
2438 : 0 : end subroutine write_a2fw_header
2439 : :
2440 : : end subroutine a2fw_ee_write
2441 : : !!***
2442 : :
2443 : : !----------------------------------------------------------------------
2444 : :
2445 : : !!****f* m_phgamma/a2fw_tr_free
2446 : : !! NAME
2447 : : !! a2fw_tr_free
2448 : : !!
2449 : : !! FUNCTION
2450 : : !! Free the memory allocated in a2fw_tr_t
2451 : : !!
2452 : : !! SOURCE
2453 : :
2454 : 10 : subroutine a2fw_tr_free(a2f_tr)
2455 : :
2456 : : !Arguments ------------------------------------
2457 : : class(a2fw_tr_t),intent(inout) :: a2f_tr
2458 : : ! *********************************************************************
2459 : :
2460 : : ! integer
2461 [ + - ]: 10 : ABI_SFREE(a2f_tr%qshift)
2462 : :
2463 : : ! real
2464 [ + - ]: 10 : ABI_SFREE(a2f_tr%n0)
2465 [ + - ]: 10 : ABI_SFREE(a2f_tr%omega)
2466 [ + - ]: 10 : ABI_SFREE(a2f_tr%vals_in)
2467 [ + - ]: 10 : ABI_SFREE(a2f_tr%vals_out)
2468 [ + - ]: 10 : ABI_SFREE(a2f_tr%vals_tr)
2469 [ - + ]: 10 : ABI_SFREE(a2f_tr%vals_tr_gen)
2470 [ + - ]: 10 : ABI_SFREE(a2f_tr%lambdaw_tr)
2471 : :
2472 : 10 : end subroutine a2fw_tr_free
2473 : : !!***
2474 : :
2475 : : !----------------------------------------------------------------------
2476 : :
2477 : : !!****f* m_phgamma/a2fw_tr_init
2478 : : !! NAME
2479 : : !! a2fw_tr_init
2480 : : !!
2481 : : !! FUNCTION
2482 : : !! Calculates the FS averaged alpha^2F_tr,in,out(w) functions
2483 : : !!
2484 : : !! INPUTS
2485 : : !! cryst<crystal_t>=Info on the unit cell.
2486 : : !! ifc<ifc_type>=Interatomic force constants.
2487 : : !! gams<phgamma_t>=Structure storing the phonon linewidths.
2488 : : !! wstep=Step for linear frequency mesh in Ha.
2489 : : !! wminmax(2)=Minimum and maximum phonon frequency. Used to construct the linear mesh for A2F(w).
2490 : : !! ph_intmeth=Integration method for phonons: 1 for gaussian, 2 for tetrahedra
2491 : : !! smear=Gaussian broadening used to approximate the Dirac delta.
2492 : : !! ngqpt(3)=Divisions of the Q-mesh used for interpolating the phonon linewidths (see also nqshift and qshift).
2493 : : !! nqshift=Number of shifts used to generated the Q-mesh.
2494 : : !! qshift(3,nqshift)=The shifts.
2495 : : !! comm=MPI communicator
2496 : : !! [qintp]=If set to False, ngqgpt, nqshift, qshift and qptop are ignored and
2497 : : !! A2F(w) is computed from the IBZ values stored in gams. Default: True i.e use Fourier interpolation.
2498 : : !! [qptopt]=Controls the generation of the q-points. If not specified, the routine takes fully into account
2499 : : !! the symmetries of the system to generate the q points in the IBZone i.e. qptopt=1
2500 : : !! Other values of qptopt can be used for debugging purpose.
2501 : : !!
2502 : : !! OUTPUT
2503 : : !! a2f_tr<a2fw_tr_t>=Structure storing the Eliashberg transport function a2F_tr(w).
2504 : : !!
2505 : : !! SOURCE
2506 : :
2507 : 10 : subroutine a2fw_tr_init(a2f_tr, gams, cryst, ifc, ph_intmeth, wstep, wminmax, smear, ngqpt, nqshift, qshift, comm,&
2508 : : qintp, qptopt) ! optional
2509 : :
2510 : : !Arguments ------------------------------------
2511 : : !scalars
2512 : : class(a2fw_tr_t),target,intent(out) :: a2f_tr
2513 : : integer,intent(in) :: ph_intmeth,nqshift,comm
2514 : : integer,intent(in),optional :: qptopt
2515 : : real(dp),intent(in) :: wstep,smear
2516 : : logical,optional,intent(in) :: qintp
2517 : : type(phgamma_t),intent(inout) :: gams
2518 : : type(ifc_type),intent(in) :: ifc
2519 : : type(crystal_t),intent(in) :: cryst
2520 : : !arrays
2521 : : integer,intent(in) :: ngqpt(3)
2522 : : real(dp),intent(in) :: wminmax(2),qshift(3,nqshift)
2523 : :
2524 : : !Local variables -------------------------
2525 : : !scalars
2526 : : integer,parameter :: master = 0
2527 : : integer :: my_qptopt,iq_ibz,nqibz,ount,my_rank,nproc,cnt
2528 : : integer :: mu,iw,natom3,nsppol,spin,ierr,nomega,nqbz, idir, jdir
2529 : : real(dp) :: omega,xx,omega_min,omega_max,ww, cpu, wall, gflops
2530 : : logical :: do_qintp
2531 : : character(len=500) :: msg
2532 : 10 : type(htetra_t) :: tetra_q
2533 : : !arrays
2534 : : integer :: qptrlatt(3,3),new_qptrlatt(3,3)
2535 : 20 : real(dp) :: lambda_iso(3,3), omega_log(3,3), phfrq(gams%natom3)
2536 : 20 : real(dp) :: gamma_in_ph(3,3,gams%natom3), gamma_out_ph(3,3,gams%natom3)
2537 : 30 : real(dp) :: lambda_in_ph(3,3,gams%natom3), lambda_out_ph(3,3,gams%natom3)
2538 : 10 : real(dp),allocatable :: tmp_a2f_in(:,:,:), tmp_a2f_out(:,:,:), my_qshift(:,:)
2539 : 10 : real(dp), contiguous, pointer :: a2f_tr_1d(:)
2540 : 10 : real(dp),allocatable :: qibz(:,:),wtq(:),qbz(:,:)
2541 : 10 : real(dp),allocatable :: a2f_tr_1mom(:),a2f_tr_logmom(:),a2f_tr_logmom_int(:),wdt(:,:)
2542 : 10 : real(dp),allocatable :: lambda_in_tetra(:,:,:,:,:),phfreq_tetra(:,:,:), lambda_out_tetra(:,:,:,:,:)
2543 : : ! *********************************************************************
2544 : :
2545 [ + - ]: 10 : my_qptopt = 1; if (present(qptopt)) my_qptopt = qptopt
2546 [ + + ]: 10 : do_qintp = .True.; if (present(qintp)) do_qintp = qintp
2547 : :
2548 : 10 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
2549 : 10 : nsppol = gams%nsppol; natom3 = gams%natom3
2550 : :
2551 : 10 : call cwtime(cpu, wall, gflops, "start")
2552 : :
2553 [ + + ]: 10 : if (do_qintp) then
2554 : : ! Generate the q-mesh by finding the IBZ and the corresponding weights.
2555 : 5 : qptrlatt = 0; qptrlatt(1,1) = ngqpt(1); qptrlatt(2,2) = ngqpt(2); qptrlatt(3,3) = ngqpt(3)
2556 : :
2557 : : call kpts_ibz_from_kptrlatt(cryst, qptrlatt, my_qptopt, nqshift, qshift, nqibz, qibz, wtq, nqbz, qbz, &
2558 : 5 : new_kptrlatt=new_qptrlatt, new_shiftk=my_qshift)
2559 [ - + ]: 5 : ABI_FREE(qbz)
2560 : :
2561 : : ! Store quantities that cannot be easily (and safely) calculated if we only know the IBZ.
2562 [ + + ]: 20 : a2f_tr%ngqpt = ngqpt; a2f_tr%nqshift = size(my_qshift, dim=2)
2563 [ - + + - : 15 : ABI_MALLOC(a2f_tr%qshift, (3, a2f_tr%nqshift))
+ - + - -
+ - + -
+ ]
2564 [ + - + - : 30 : a2f_tr%qshift = my_qshift
- + - - -
- - - + +
+ + ]
2565 [ - + ]: 5 : ABI_FREE(my_qshift)
2566 : :
2567 : : else
2568 : : ! No interpolation. Use q-mesh parameters from gams%
2569 [ + + ]: 20 : a2f_tr%ngqpt = gams%ngqpt; a2f_tr%nqshift = 1
2570 : 5 : nqibz = gams%nqibz
2571 [ - + + - : 15 : ABI_MALLOC(qibz, (3,nqibz))
+ - + - -
+ - + ]
2572 [ - + + - : 15 : ABI_MALLOC(wtq, (nqibz))
+ - + - -
+ - + ]
2573 [ - + - + ]: 5 : ABI_MALLOC(a2f_tr%qshift, (3, a2f_tr%nqshift))
2574 [ + - + - : 320 : qibz = gams%qibz; wtq = gams%wtq
- + - - -
- - - + +
+ + + - -
+ - - - -
+ + ]
2575 [ + + + + ]: 25 : a2f_tr%qshift = zero ! Note: assuming q-mesh centered on Gamma.
2576 : : end if
2577 : :
2578 : 10 : call cwtime_report(" a2fw_tr_init, q-setup", cpu, wall, gflops)
2579 : :
2580 : : ! Define Min and max frequency for the mesh (enlarge it a bit)
2581 : 10 : omega_min = wminmax(1); omega_max = wminmax(2)
2582 : 10 : omega_min = omega_min - 0.1*abs(omega_min)
2583 [ - + ]: 10 : if (omega_min >= zero) omega_min = one/Ha_meV
2584 : 10 : omega_max = omega_max + 0.1*abs(omega_max)
2585 : :
2586 : 10 : a2f_tr%nsppol = nsppol; a2f_tr%natom3 = gams%natom3; a2f_tr%smear = smear
2587 : 10 : a2f_tr%omega_min = omega_min; a2f_tr%omega_max = omega_max
2588 : 10 : nomega = int((omega_max - omega_min) / wstep); a2f_tr%nomega = nomega; a2f_tr%wstep = wstep
2589 : :
2590 [ - + + - : 30 : ABI_MALLOC(a2f_tr%n0, (nsppol))
+ - + - -
+ - + -
+ ]
2591 [ + - - + : 30 : a2f_tr%n0 = gams%n0
- - - - -
- + + ]
2592 : : ! Build linear mesh.
2593 [ - + + - : 30 : ABI_MALLOC(a2f_tr%omega, (nomega))
+ - + - -
+ - + -
+ ]
2594 [ + - + - : 4750 : a2f_tr%omega = arth(omega_min, wstep, nomega)
- + - - +
+ ]
2595 : :
2596 [ - + + - : 170870 : ABI_CALLOC(a2f_tr%vals_in, (nomega, 3, 3, 0:natom3, nsppol))
+ - - + +
- - + + -
+ - + - -
+ - + - +
+ + + + +
+ + + +
+ ]
2597 [ - + + - : 170850 : ABI_CALLOC(a2f_tr%vals_out, (nomega,3, 3, 0:natom3, nsppol))
- + + - -
+ + - - +
- + - + +
+ + + + +
+ + + + ]
2598 [ - + + - : 170850 : ABI_CALLOC(a2f_tr%vals_tr, (nomega,3, 3, 0:natom3, nsppol))
- + + - -
+ + - - +
- + - + +
+ + + + +
+ + + + ]
2599 [ - + + - : 170850 : ABI_CALLOC(a2f_tr%lambdaw_tr, (nomega, 3, 3, 0:natom3, nsppol))
- + + - -
+ + - - +
- + - + +
+ + + + +
+ + + + ]
2600 [ - + + - : 30 : ABI_MALLOC(tmp_a2f_in, (nomega, 3, 3))
+ - + - -
+ - + ]
2601 [ - + + - : 20 : ABI_MALLOC(tmp_a2f_out, (nomega, 3, 3))
- + - + ]
2602 : :
2603 [ + + ]: 10 : if (ph_intmeth == 2) then
2604 : 8 : call cwtime(cpu, wall, gflops, "start")
2605 : :
2606 : : ! Prepare tetrahedron integration.
2607 : 8 : qptrlatt = 0; qptrlatt(1, 1) = a2f_tr%ngqpt(1); qptrlatt(2, 2) = a2f_tr%ngqpt(2); qptrlatt(3, 3) = a2f_tr%ngqpt(3)
2608 : 8 : tetra_q = tetra_from_kptrlatt(cryst, my_qptopt, qptrlatt, a2f_tr%nqshift, a2f_tr%qshift, nqibz, qibz, comm, msg, ierr)
2609 [ - + ]: 8 : if (ierr/=0) ABI_ERROR(msg)
2610 : :
2611 [ - + + - : 48 : ABI_MALLOC_OR_DIE(lambda_in_tetra, (nqibz, 3, 3, natom3, nsppol), ierr)
+ - - + +
- - + + -
+ - + - +
- - + -
+ ]
2612 [ - + + - : 32 : ABI_MALLOC_OR_DIE(lambda_out_tetra, (nqibz, 3, 3, natom3, nsppol), ierr)
- + + - -
+ + - + -
- + - + ]
2613 [ + + + + : 17419 : lambda_in_tetra = zero
+ + + + +
+ ]
2614 [ + + + + : 17419 : lambda_out_tetra = zero
+ + + + +
+ ]
2615 : :
2616 [ - + + - : 40 : ABI_MALLOC_OR_DIE(phfreq_tetra, (nqibz, natom3, nsppol), ierr)
- + + - -
+ + - + -
+ - + - -
+ - + ]
2617 [ + + + + : 1939 : phfreq_tetra = zero
+ + ]
2618 : :
2619 : 16 : call cwtime_report(" a2fw_tr_init%tetra,", cpu, wall, gflops)
2620 : : end if
2621 : :
2622 : 10 : call cwtime(cpu, wall, gflops, "start")
2623 : :
2624 : : ! Loop over spins and qpoints in the IBZ
2625 : 10 : cnt = 0
2626 [ + + ]: 20 : do spin=1,nsppol
2627 [ + + ]: 806 : do iq_ibz=1,nqibz
2628 [ + - ]: 786 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle
2629 : :
2630 : : ! Interpolate or evaluate lambda transport coefficients.
2631 [ + + ]: 786 : if (do_qintp) then
2632 : 725 : call phgamma_vv_interp(gams,cryst,ifc,spin,qibz(:,iq_ibz),phfrq,gamma_in_ph,gamma_out_ph,lambda_in_ph,lambda_out_ph)
2633 : : else
2634 : 61 : call phgamma_vv_eval_qibz(gams,cryst,ifc,iq_ibz,spin,phfrq,gamma_in_ph,gamma_out_ph,lambda_in_ph,lambda_out_ph)
2635 : : end if
2636 : :
2637 : 10 : select case (ph_intmeth)
2638 : : case (1)
2639 : : ! Gaussian: Add all contributions from the phonon modes at this qpoint to a2f_tr
2640 : : ! (note that unstable modes are included).
2641 [ + + ]: 612 : do mu=1,natom3
2642 [ + + + + : 1959930 : tmp_a2f_in = zero
+ + ]
2643 [ + + + + : 1959930 : tmp_a2f_out = zero
+ + ]
2644 [ + + ]: 217566 : do iw=1,nomega
2645 : 217107 : xx = a2f_tr%omega(iw) - phfrq(mu)
2646 [ + + + + ]: 2822391 : tmp_a2f_in(iw,:,:) = tmp_a2f_in(iw,:,:) + gaussian(xx, smear) * lambda_in_ph(:,:,mu) * abs(phfrq(mu))
2647 [ + + + + ]: 2822850 : tmp_a2f_out(iw,:,:) = tmp_a2f_out(iw,:,:) + gaussian(xx, smear) * lambda_out_ph(:,:,mu) * abs(phfrq(mu))
2648 : : end do
2649 [ + + + + : 1959930 : a2f_tr%vals_in(:,:,:,mu,spin) = a2f_tr%vals_in(:,:,:,mu,spin) + tmp_a2f_in(:,:,:) * wtq(iq_ibz)
+ + ]
2650 [ + + + + : 1960083 : a2f_tr%vals_out(:,:,:,mu,spin) = a2f_tr%vals_out(:,:,:,mu,spin) + tmp_a2f_out(:,:,:) * wtq(iq_ibz)
+ + ]
2651 : : end do
2652 : :
2653 : : case (2)
2654 : : ! Tetra: store data.
2655 [ + + - + : 2685 : do mu=1,natom3
+ ]
2656 [ + + + + ]: 24687 : lambda_in_tetra(iq_ibz, :,:, mu, spin) = lambda_in_ph(:,:,mu) * abs(phfrq(mu))
2657 [ + + + + ]: 24687 : lambda_out_tetra(iq_ibz, :,:, mu, spin) = lambda_out_ph(:,:,mu) * abs(phfrq(mu))
2658 : 2532 : phfreq_tetra(iq_ibz, mu, spin) = phfrq(mu)
2659 : : end do
2660 : : end select
2661 : :
2662 : : end do ! iq_ibz
2663 : : end do ! spin
2664 : :
2665 [ + + ]: 10 : if (ph_intmeth == 2) then
2666 : : ! Collect results on each node.
2667 : 8 : call xmpi_sum(lambda_in_tetra, comm, ierr)
2668 : 8 : call xmpi_sum(lambda_out_tetra, comm, ierr)
2669 : 8 : call xmpi_sum(phfreq_tetra, comm, ierr)
2670 : :
2671 : : ! workspace for tetra.
2672 [ - + + - : 24 : ABI_MALLOC(wdt, (nomega, 2))
+ - + - -
+ - + ]
2673 : :
2674 : : ! TODO: with the tetra_get_onewk call we can integrate this above
2675 : : ! and avoid allocating all of lambda_in_tetra and phfreq_tetra!!!
2676 : : ! For each mode get its contribution
2677 : 8 : cnt = 0
2678 [ + + ]: 16 : do spin=1,nsppol
2679 [ + + ]: 40 : do mu=1,natom3
2680 [ + + ]: 1931 : do iq_ibz=1,nqibz
2681 [ + - ]: 1899 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! mpi-parallelism
2682 : :
2683 : 1899 : call tetra_q%get_onewk(iq_ibz, gams%bcorr, nomega, nqibz, phfreq_tetra(:,mu,spin), omega_min, omega_max, one, wdt)
2684 [ + + + + ]: 1802151 : wdt = wdt * wtq(iq_ibz)
2685 : :
2686 : : ! Accumulate (Integral of a2F_tr is computed afterwards)
2687 [ + + ]: 7620 : do idir=1,3
2688 [ + + ]: 24687 : do jdir=1,3
2689 : : a2f_tr%vals_in(:,idir,jdir,mu,spin) = a2f_tr%vals_in(:,idir,jdir,mu,spin) &
2690 [ + + ]: 8101134 : + wdt(:,1) * lambda_in_tetra(iq_ibz,idir,jdir,mu,spin)
2691 : : a2f_tr%vals_out(:,idir,jdir,mu,spin) = a2f_tr%vals_out(:,idir,jdir,mu,spin) &
2692 [ + + ]: 8106831 : + wdt(:,1) * lambda_out_tetra(iq_ibz,idir,jdir,mu,spin)
2693 : : !a2f_tr%lambdaw(:,mu,spin) = a2f_tr%lambdaw(:,mu,spin) + wdt(:,2) * lambda_XX_tetra(iq_ibz, mu, spin)
2694 : : end do
2695 : : end do
2696 : : end do
2697 : : end do
2698 : : end do
2699 : :
2700 [ - + ]: 8 : ABI_FREE(wdt)
2701 [ - + ]: 8 : ABI_FREE(lambda_in_tetra)
2702 [ - + ]: 8 : ABI_FREE(lambda_out_tetra)
2703 [ - + ]: 8 : ABI_FREE(phfreq_tetra)
2704 : 16 : call tetra_q%free()
2705 : : end if
2706 : :
2707 : : ! Collect final results on each node
2708 : 10 : call xmpi_sum(a2f_tr%vals_in, comm, ierr)
2709 : 10 : call xmpi_sum(a2f_tr%vals_out, comm, ierr)
2710 : :
2711 : : ! TODO: divide by g(eF, spin)
2712 : : ! check normalization with N(0) and <v^2> from Savrasov eq 20
2713 [ + + ]: 20 : do spin=1,nsppol
2714 [ + + + + : 170410 : a2f_tr%vals_in(:,:,:,0,spin) = sum(a2f_tr%vals_in(:,:,:,1:natom3,spin), dim=4)
+ + + + ]
2715 [ + + + + : 170420 : a2f_tr%vals_out(:,:,:,0,spin) = sum(a2f_tr%vals_out(:,:,:,1:natom3,spin), dim=4)
+ + + + ]
2716 : : !a2f_tr%vals(:,:,spin) = a2f_tr%vals(:,:,spin) / (two_pi * a2f_tr%n0(spin))
2717 : : end do
2718 : :
2719 [ + - + - : 170830 : a2f_tr%vals_tr = a2f_tr%vals_out - a2f_tr%vals_in
+ - + - +
- - + - -
+ + + + +
+ + + +
+ ]
2720 : :
2721 : 10 : call cwtime_report(" a2fw_tr_init, a2f_eval", cpu, wall, gflops)
2722 : :
2723 : : ! NOTE: for the moment calculate the log moms etc on just the trace of the a2f functions
2724 [ - + + - : 20 : ABI_MALLOC(a2f_tr_1mom, (nomega))
- + - + ]
2725 [ - + + - : 20 : ABI_MALLOC(a2f_tr_logmom, (nomega))
- + - + ]
2726 [ - + + - : 20 : ABI_MALLOC(a2f_tr_logmom_int, (nomega))
- + - + ]
2727 : :
2728 : : !call a2fw_tr_print_info()
2729 : :
2730 : : ! Compute lambda_tr(w) (resolved in spin mode and directions)
2731 [ + + ]: 20 : do spin=1,nsppol
2732 [ + + ]: 60 : do mu=0,natom3
2733 [ + + ]: 170 : do idir=1,3
2734 [ + + ]: 520 : do jdir=1,3
2735 : :
2736 [ + + ]: 170640 : do iw=1,nomega
2737 : 170280 : ww = a2f_tr%omega(iw)
2738 [ + - ]: 170640 : if (abs(ww) > EPHTK_WTOL) then
2739 : 170280 : a2f_tr_1mom(iw) = a2f_tr%vals_tr(iw,idir,jdir,mu,spin) / abs(ww)
2740 : : else
2741 : 0 : a2f_tr_1mom(iw) = zero
2742 : : end if
2743 : : ! TODO: Strange that the first value of int(f) is not set to zero!
2744 : : ! FIXME: The frequency integration overestimates lambda if there are negative phonon frequencies!
2745 : : end do
2746 : :
2747 : 480 : call simpson_int(nomega, wstep, a2f_tr_1mom, a2f_tr%lambdaw_tr(:,idir,jdir,mu,spin))
2748 : : end do ! jdir
2749 : : end do ! idir
2750 : : end do ! mu
2751 : : end do ! spin
2752 : :
2753 [ + - ]: 10 : if (my_rank == master) then
2754 : 10 : ount = std_out
2755 [ - + ]: 10 : if (nsppol > 1) then
2756 : 0 : write(msg,'(3a)') ch10,'Comment: some of the following quantities should be integrated over spin', ch10
2757 : 0 : call wrtout(ount, msg)
2758 : : end if
2759 : : end if
2760 : :
2761 [ + + ]: 20 : do spin=1,nsppol
2762 : 10 : lambda_iso = a2fw_tr_moment(a2f_tr, 0, spin)
2763 : :
2764 [ + + ]: 40 : do idir=1,3
2765 [ + + ]: 130 : do jdir=1,3
2766 : 90 : a2f_tr_1d => a2f_tr%vals_tr(:,idir,jdir,0,spin)
2767 : :
2768 : : ! Get log moment of alpha^2F.
2769 [ + + ]: 42660 : a2f_tr_logmom = zero
2770 [ + + ]: 42660 : do iw=1,nomega
2771 : 42570 : omega = a2f_tr%omega(iw)
2772 [ + - + - ]: 42660 : if (abs(omega) > EPHTK_WTOL .and. abs(lambda_iso(idir,jdir)) > EPHTK_WTOL) then
2773 : 42570 : a2f_tr_logmom(iw) = (two/lambda_iso(idir,jdir)) * a2f_tr_1d(iw)*log(abs(omega))/abs(omega)
2774 : : end if
2775 : : end do
2776 : 90 : call simpson_int(nomega, wstep, a2f_tr_logmom, a2f_tr_logmom_int)
2777 : : !write(std_out,*)' iw,nomega,greatest_real,a2f_tr_logmom_int(nomega)=',& iw,nomega,greatest_real,a2f_tr_logmom_int(nomega)
2778 [ + - ]: 120 : if(abs(a2f_tr_logmom_int(nomega)) < log(greatest_real*tol6)) then
2779 : 90 : omega_log(idir,jdir) = exp(a2f_tr_logmom_int(nomega))
2780 : : else
2781 : 0 : omega_log(idir,jdir)=greatest_real*tol6
2782 : : endif
2783 : : end do
2784 : : end do
2785 : :
2786 : : ! TODO: make output only for irred values xx yy zz and top half of matrix
2787 [ + - ]: 20 : if (my_rank == master) then
2788 [ + + ]: 10 : if (do_qintp) then
2789 : 5 : write(ount,'(a)')' Evaluation of parameters analogous to electron-phonon coupling for 3x3 directions (interpolated) '
2790 : : else
2791 : 5 : write(ount,'(a)')' Evaluation of parameters analogous to electron-phonon coupling for 3x3 directions (coarse grid) '
2792 : : endif
2793 : 10 : write(ount,'(a,3(3es10.3,2x))') ' lambda = ',lambda_iso
2794 : 10 : write(ount,'(a,3(3es10.3,2x),a)' )' omegalog = ',omega_log,' (Ha) '
2795 [ + + + + ]: 130 : write(ount,'(a,3(3es10.3,2x),a)' )' ',omega_log*Ha_K, ' (Kelvin) '
2796 : 10 : write(ount,"(a)")' positive moments of alpha2Ftr:'
2797 [ + + + + ]: 130 : write(ount,'(a,9(es10.3,2x))' )' lambda <omega^2> = ',a2fw_tr_moment(a2f_tr, 2, spin)
2798 [ + + + + ]: 130 : write(ount,'(a,9(es10.3,2x))' )' lambda <omega^3> = ',a2fw_tr_moment(a2f_tr, 3, spin)
2799 [ + + + + ]: 130 : write(ount,'(a,9(es10.3,2x))' )' lambda <omega^4> = ',a2fw_tr_moment(a2f_tr, 4, spin)
2800 [ + + + + ]: 130 : write(ount,'(a,9(es10.3,2x))' )' lambda <omega^5> = ',a2fw_tr_moment(a2f_tr, 5, spin)
2801 : : end if
2802 : : end do
2803 : :
2804 [ - + ]: 10 : ABI_FREE(tmp_a2f_in)
2805 [ - + ]: 10 : ABI_FREE(tmp_a2f_out)
2806 [ - + ]: 10 : ABI_FREE(a2f_tr_1mom)
2807 [ - + ]: 10 : ABI_FREE(a2f_tr_logmom)
2808 [ - + ]: 10 : ABI_FREE(a2f_tr_logmom_int)
2809 [ - + ]: 10 : ABI_FREE(qibz)
2810 [ - + ]: 10 : ABI_FREE(wtq)
2811 : :
2812 [ + - - + : 70 : end subroutine a2fw_tr_init
- + - + -
+ - - - -
- + - - -
- - + - +
- + - + -
+ ]
2813 : : !!***
2814 : :
2815 : : !----------------------------------------------------------------------
2816 : :
2817 : : !!****f* m_phgamma/a2fw_tr_write
2818 : : !! NAME
2819 : : !! a2fw_tr_write
2820 : : !!
2821 : : !! FUNCTION
2822 : : !! Write alpha^2F_tr(w) to an external file in text form
2823 : : !!
2824 : : !! INPUTS
2825 : : !! basename=Filename for output.
2826 : : !! post=String appended to netcdf variables e.g. _qcoarse, _qintp
2827 : : !! ncid=Netcdf file handler. Set it to nctk_noid to disable output.
2828 : : !!
2829 : : !! OUTPUT
2830 : : !! Output is written to file. This routine should be called by one MPI proc.
2831 : : !!
2832 : : !! SOURCE
2833 : :
2834 : 10 : subroutine a2fw_tr_write(a2f_tr, basename, post, ncid)
2835 : :
2836 : : !Arguments ------------------------------------
2837 : : !scalars
2838 : : class(a2fw_tr_t),intent(in) :: a2f_tr
2839 : : integer,intent(in) :: ncid
2840 : : character(len=*),intent(in) :: basename, post
2841 : :
2842 : : !Local variables -------------------------
2843 : : !scalars
2844 : : integer :: iw,spin,unt,ii,mu,idir, jdir, ncerr
2845 : : character(len=500) :: dim1_name, msg
2846 : : character(len=fnlen) :: path
2847 : : ! *********************************************************************
2848 : :
2849 : : ! Write spin-resolved a2F_tr(w)
2850 [ + - ]: 10 : path = strcat(basename, "_A2FW_tr")
2851 [ - + ]: 10 : if (open_file(path, msg, newunit=unt, form="formatted", action="write", status="unknown") /= 0) then
2852 : 0 : ABI_ERROR(msg)
2853 : : end if
2854 : :
2855 : 10 : call write_a2fw_tr_header()
2856 : :
2857 : : ! Reminder: vals_tr(nomega,3,3,0:natom3,nsppol)
2858 : :
2859 [ + - ]: 10 : if (a2f_tr%nsppol == 1) then
2860 : 10 : write(unt,'(a)')"# Frequency, a2F_tr(w,i,j)"
2861 [ + + ]: 4740 : do iw=1,a2f_tr%nomega
2862 : 4740 : write(unt,'(e16.6, 2x, 3(3e16.6,1x))') a2f_tr%omega(iw), a2f_tr%vals_tr(iw,:,:,0,1)
2863 : : end do
2864 : 10 : write(unt,'(3a)')ch10, ch10, "# Frequency, lambda(w,i,j)"
2865 [ + + ]: 4740 : do iw=1,a2f_tr%nomega
2866 : 4740 : write(unt,'(e16.6, 2x, 3(3e16.6,1x))') a2f_tr%omega(iw), a2f_tr%lambdaw_tr(iw,:,:,0,1)
2867 : : end do
2868 : :
2869 : : else
2870 : 0 : write(unt,'(a)')"# Frequency, a2F_tr_tot(w,i,j), a2F_tr_spin1(w,i,j) ..."
2871 [ # # ]: 0 : do iw=1,a2f_tr%nomega
2872 : 0 : write(unt,'(e16.6, 2x, 3(3e16.6,1x), 2x, 3(3e16.6,1x), 2x, 3(3e16.6,1x))') a2f_tr%omega(iw), &
2873 [ # # # # : 0 : ((sum(a2f_tr%vals_tr(iw,idir,jdir,0,:)), idir=1,3), jdir=1,3) , &
# # ]
2874 : 0 : a2f_tr%vals_tr(iw,:,:,0,1), & ! UP
2875 [ # # # # ]: 0 : a2f_tr%vals_tr(iw,:,:,0,2) ! DOWN
2876 : : end do
2877 : 0 : write(unt,'(3a)') ch10, ch10, "# Frequency, lambda_tr_tot(w,i,j)dw, lambda_tr_spin1(w,i,j) ..."
2878 [ # # ]: 0 : do iw=1,a2f_tr%nomega
2879 : 0 : write(unt,'(e16.6, 2x, 3(3e16.6,1x), 2x, 3(3e16.6,1x), 2x, 3(3e16.6,1x), 2x, 3(3e16.6,1x))') a2f_tr%omega(iw), &
2880 [ # # # # : 0 : ((sum(a2f_tr%lambdaw_tr(iw,idir,jdir,0,:)), idir=1,3), jdir=1,3) , & ! TOT
# # ]
2881 : 0 : a2f_tr%lambdaw_tr(iw,:,:,0,1), & ! UP
2882 [ # # # # ]: 0 : a2f_tr%lambdaw_tr(iw,:,:,0,2) ! DOWN
2883 : : end do
2884 : : end if
2885 : :
2886 : 10 : close(unt)
2887 : :
2888 : : ! Write phonon mode contributions to a2F_tr(w,i,j)
2889 [ + - ]: 10 : path = strcat(basename, "_PH_A2FW_tr")
2890 [ - + ]: 10 : if (open_file(path, msg, newunit=unt, form="formatted", action="write", status="unknown") /= 0) then
2891 : 0 : ABI_ERROR(msg)
2892 : : end if
2893 : 10 : call write_a2fw_tr_header()
2894 : :
2895 : : ! Reminder: vals_tr(nomega,3,3,0:natom3,nsppol)
2896 [ + - ]: 10 : if (a2f_tr%nsppol == 1) then
2897 [ + + ]: 50 : do mu=0,a2f_tr%natom3
2898 : 40 : write(unt,'(a,i0)')"# Phonon mode ",mu
2899 : 40 : write(unt,'(a)')"# Frequency, a2F_tr(w)"
2900 [ + + ]: 18960 : do iw=1,a2f_tr%nomega
2901 : 18960 : write(unt,'(e16.6,2x,3(3e16.6,1x))') a2f_tr%omega(iw), a2f_tr%vals_tr(iw,:,:,mu,1)
2902 : : end do
2903 [ + + ]: 120 : do ii=1,2; write(unt,'(a)')""; end do
2904 : 40 : write(unt,'(a)')"# Frequency, lambda_tr(w)"
2905 [ + + ]: 18960 : do iw=1,a2f_tr%nomega
2906 : 18960 : write(unt,'(e16.6,2x,3(3e16.6,1x))') a2f_tr%omega(iw), a2f_tr%lambdaw_tr(iw,:,:,mu,1)
2907 : : end do
2908 [ + + ]: 130 : do ii=1,2; write(unt,'(a)')""; end do
2909 : : end do
2910 : :
2911 : : else
2912 [ # # ]: 0 : do mu=0,a2f_tr%natom3
2913 : 0 : write(unt,'(a,i0)')"# Phonon mode ",mu
2914 : 0 : write(unt,'(a)')"# Frequency, a2F_tot(w), a2F_spin1(w) ..."
2915 [ # # ]: 0 : do iw=1,a2f_tr%nomega
2916 : 0 : write(unt,*) a2f_tr%omega(iw), &
2917 [ # # # # : 0 : sum(a2f_tr%vals_tr(iw,:,:,mu,:)), & ! TOT
# # ]
2918 : 0 : a2f_tr%vals_tr(iw,:,:,mu,1) , & ! UP
2919 : 0 : a2f_tr%vals_tr(iw,:,:,mu,2) ! DOWN
2920 : : end do
2921 : 0 : write(unt,'(3a)')ch10,ch10,"# Frequency, lambda_tot(w)dw, lambda_spin1(w) ..."
2922 [ # # ]: 0 : do iw=1,a2f_tr%nomega
2923 : 0 : write(unt,*) a2f_tr%omega(iw), &
2924 [ # # # # : 0 : sum(a2f_tr%lambdaw_tr(iw,:,:,mu,:)), & ! TOT
# # ]
2925 : 0 : a2f_tr%lambdaw_tr(iw,:,:,mu,1), & ! UP
2926 : 0 : a2f_tr%lambdaw_tr(iw,:,:,mu,2) ! DOWN
2927 : : end do
2928 : : end do
2929 : : end if
2930 : :
2931 : 10 : close(unt)
2932 : :
2933 [ + - ]: 10 : if (ncid /= nctk_noid) then
2934 : : ! Define dimensions.
2935 [ + - ]: 10 : dim1_name = strcat("a2ftr_nomega", post)
2936 : : ncerr = nctk_def_dims(ncid, [ &
2937 : : nctkdim_t(dim1_name, a2f_tr%nomega), &
2938 : : nctkdim_t("natom3p1", a2f_tr%natom3 + 1), nctkdim_t("number_of_spins", a2f_tr%nsppol) &
2939 [ + + ]: 40 : ], defmode=.True.)
2940 [ - + ]: 10 : NCF_CHECK(ncerr)
2941 : :
2942 : : ncerr = nctk_def_arrays(ncid, [ &
2943 : : nctkarr_t(strcat('a2ftr_mesh', post), "dp", dim1_name), &
2944 : : nctkarr_t(strcat('a2ftr_values', post), "dp", strcat(dim1_name, ", three, three, natom3p1, number_of_spins")), &
2945 : : nctkarr_t(strcat('a2ftr_lambdaw', post), "dp", strcat(dim1_name, ", three, three, natom3p1, number_of_spins")) &
2946 [ + - + - : 40 : ])
+ - + - +
- + + ]
2947 [ - + ]: 10 : NCF_CHECK(ncerr)
2948 : :
2949 [ - + ]: 10 : NCF_CHECK(nctk_set_datamode(ncid))
2950 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, strcat("a2ftr_mesh", post)), a2f_tr%omega))
2951 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, strcat("a2ftr_values", post)), a2f_tr%vals_tr))
2952 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, strcat("a2ftr_lambdaw", post)), a2f_tr%lambdaw_tr))
2953 : : end if
2954 : :
2955 : : contains
2956 : :
2957 : 20 : subroutine write_a2fw_tr_header()
2958 : :
2959 : : ! Output the header.
2960 : 20 : write(unt,'(a)') '#'
2961 : 20 : write(unt,'(a)') '# ABINIT package: a2F_tr(w) file'
2962 : 20 : write(unt,'(a)') '#'
2963 : 20 : write(unt,'(a)') '# a2F_tr(w) function integrated over the FS. omega in a.u.'
2964 [ + - ]: 20 : write(unt,'(2a)') '# ngqpt: ',trim(ltoa(a2f_tr%ngqpt))
2965 : 20 : write(unt,'(a,i0,3(a,e16.6))')'# number of frequencies: ',a2f_tr%nomega," between omega_min: ",a2f_tr%omega_min,&
2966 : 40 : ' Ha and omega_max: ',a2f_tr%omega_max,' Ha with step:',a2f_tr%wstep
2967 : 20 : write(unt,'(a,e16.6)') '# the smearing width for gaussians is ',a2f_tr%smear
2968 [ - + ]: 20 : if (a2f_tr%nsppol == 2) then
2969 [ # # ]: 0 : write(unt,'(a,e16.6)')"# Total DOS at Fermi level ",sum(a2f_tr%n0)
2970 : : end if
2971 [ + + ]: 40 : do spin=1,a2f_tr%nsppol
2972 : 40 : write(unt,"(a,i0,a,e16.6)")"# The DOS at Fermi level for spin ",spin," is ",a2f_tr%n0(spin)
2973 : : end do
2974 [ + + ]: 60 : do ii=1,2; write(unt,'(a)') "# "; end do
2975 : :
2976 : 20 : end subroutine write_a2fw_tr_header
2977 : :
2978 : : end subroutine a2fw_tr_write
2979 : : !!***
2980 : :
2981 : : !----------------------------------------------------------------------
2982 : :
2983 : : !!****f* m_phgamma/eph_phgamma
2984 : : !! NAME
2985 : : !! eph_phgamma
2986 : : !!
2987 : : !! FUNCTION
2988 : : !! Compute phonon linewidths in metals.
2989 : : !!
2990 : : !! INPUTS
2991 : : !! wk0_path=String with the path to the GS unperturbed WFK file.
2992 : : !! ngfft(18),ngfftf(18)=Coarse and Fine FFT meshes.
2993 : : !! dtset<dataset_type>=All input variables for this dataset.
2994 : : !! ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
2995 : : !! dvdb<dbdb_type>=Database with the DFPT SCF potentials.
2996 : : !! ifc<ifc_type>=interatomic force constants and corresponding real space grid info.
2997 : : !! pawfgr <type(pawfgr_type)>=fine grid parameters and related data
2998 : : !! pawang<pawang_type)>=PAW angular mesh and related data.
2999 : : !! pawrad(ntypat*usepaw)<pawrad_type>=Paw radial mesh and related data.
3000 : : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
3001 : : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
3002 : : !! comm=MPI communicator.
3003 : : !!
3004 : : !! OUTPUT
3005 : : !!
3006 : : !! SOURCE
3007 : :
3008 : 5 : subroutine eph_phgamma(wfk0_path, dtfil, ngfft, ngfftf, dtset, cryst, ebands, dvdb, ifc, &
3009 : 5 : pawfgr, pawang, pawrad, pawtab, psps, mpi_enreg, comm)
3010 : :
3011 : : !Arguments ------------------------------------
3012 : : !scalars
3013 : : character(len=*),intent(in) :: wfk0_path
3014 : : integer,intent(in) :: comm
3015 : : type(datafiles_type),intent(in) :: dtfil
3016 : : type(dataset_type),intent(in) :: dtset
3017 : : type(crystal_t),intent(in) :: cryst
3018 : : type(ebands_t),intent(in) :: ebands
3019 : : type(dvdb_t),intent(inout) :: dvdb
3020 : : type(pawang_type),intent(in) :: pawang
3021 : : type(pseudopotential_type),intent(in) :: psps
3022 : : type(pawfgr_type),intent(in) :: pawfgr
3023 : : type(ifc_type),intent(in) :: ifc
3024 : : type(mpi_type),intent(in) :: mpi_enreg
3025 : : !arrays
3026 : : integer,intent(in) :: ngfft(18),ngfftf(18)
3027 : : type(pawrad_type),intent(in) :: pawrad(psps%ntypat*psps%usepaw)
3028 : : type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
3029 : :
3030 : : !Local variables ------------------------------
3031 : : !scalars
3032 : : integer,parameter :: tim_getgh1c = 1, berryopt0 = 0, qptopt1 = 1, master = 0, ndat1 = 1, eph_scalprod0 = 0
3033 : : integer :: my_rank,nproc,mband,nsppol,nkibz,idir,ipert,iq_ibz
3034 : : integer :: cplex,db_iqpt,natom,natom3,ipc,ipc1,ipc2,nspinor,onpw
3035 : : integer :: bstart_k,bstart_kq,nb_k,nb_kq,band_k, band_kq, in_k, im_kq
3036 : : integer :: ik_ibz,ik_bz,ikq_bz,ikq_ibz,isym_k,isym_kq,trev_k,trev_kq !,timrev_q
3037 : : integer :: ik_fs, my_ik, my_is, spin, istwf_k, istwf_kq, npw_k, npw_kq
3038 : : integer :: ii,jj,ipw,mpw,my_mpw,mnb,ierr,cnt,ncid
3039 : : integer :: n1, n2, n3, n4, n5, n6, nspden, ltetra
3040 : : integer :: sij_opt, usecprj, usevnl, optlocal, optnl, opt_gvnlx1
3041 : : integer :: nfft,nfftf,mgfft,mgfftf,nkpg
3042 : : integer :: jene, iene, comm_rpt, nesting, my_npert, my_ip, my_iq, ncerr, edos_intmeth
3043 : : real(dp) :: cpu, wall, gflops, cpu_q, wall_q, gflops_q, cpu_k, wall_k, gflops_k, cpu_all, wall_all, gflops_all
3044 : : real(dp) :: edos_step, edos_broad, sigma, ecut, eig0nk ! eshift,
3045 : : logical :: gen_eigenpb, need_velocities, isirr_k, isirr_kq, print_time_k, need_ftinterp
3046 : 5 : type(wfd_t) :: wfd
3047 : : type(fstab_t),pointer :: fs
3048 : 5 : type(gs_hamiltonian_type) :: gs_hamkq
3049 : 5 : type(rf_hamiltonian_type) :: rf_hamkq
3050 : 5 : type(edos_t) :: edos
3051 : 5 : type(phgamma_t) :: gams
3052 : 5 : type(a2fw_t) :: a2fw
3053 : 5 : type(a2fw_tr_t) :: a2fw_tr
3054 [ + + - + : 50 : type(ddkop_t) :: ddkop
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ + + - +
- + + + -
+ - + - +
- + - + -
+ - + -
+ ]
3055 : : type(xcomm_t) :: pert_comm, qs_comm, qpt_comm, bsum_comm, kpt_comm, spin_comm, pkb_comm !, ncwrite_comm
3056 : 5 : type(krank_t) :: krank
3057 : 5 : type(htetra_t) :: tetra
3058 : : !type(lgroup_t) :: lg_q
3059 : : character(len=500) :: msg
3060 : : character(len=fnlen) :: path
3061 : : !arrays
3062 : : integer :: g0_k(3),g0bz_kq(3),g0_kq(3),units(2)
3063 : : integer :: indkk_kq(6,1), work_ngfft(18),gmax(3),my_gmax(3),gamma_ngqpt(3) !g0ibz_kq(3),
3064 : 5 : integer,allocatable :: kg_k(:,:),kg_kq(:,:),gtmp(:,:),nband(:,:),wfd_istwfk(:), my_pinfo(:,:), pert_table(:,:) !, qibz_done(:)
3065 : 10 : real(dp) :: kk(3),kq(3),kk_ibz(3),kq_ibz(3),qpt(3), lf(2),rg(2),res(2), vk(3), vkq(3), wminmax(2), n0(ebands%nsppol)
3066 : 10 : real(dp) :: resvv_in(2,9), resvv_out(2,9), phfrq(3*cryst%natom), abc(3)
3067 : 5 : real(dp),allocatable :: kinpw_k(:), kinpw_kq(:), displ_cart(:,:,:,:), displ_red(:,:,:,:)
3068 : 5 : real(dp),allocatable :: grad_berry(:,:), kpg_kq(:,:), kpg_k(:,:)
3069 : 5 : real(dp),allocatable :: ffnl_k(:,:,:,:), ffnl_kq(:,:,:,:), ph3d_k(:,:,:), ph3d_kq(:,:,:)
3070 : 5 : real(dp),allocatable :: v1scf(:,:,:,:), tgam(:,:,:), gkq_atm(:,:,:,:), gkq_atm_ipc(:,:,:), lambda(:)
3071 : 10 : real(dp),allocatable :: bras_kq(:,:,:), kets_k(:,:,:), h1_kets_kq(:,:,:), cg_work(:,:)
3072 : 5 : real(dp),allocatable :: ph1d(:,:), vlocal(:,:,:,:), vlocal1(:,:,:,:,:)
3073 : 5 : real(dp),allocatable :: dummy_vtrial(:,:), gvnlx1(:,:,:), work(:,:,:,:)
3074 : 5 : real(dp),allocatable :: gs1c_kq(:,:), v1_work(:,:,:,:), vcart_ibz(:,:,:,:)
3075 : 10 : real(dp),allocatable :: wt_ek(:,:), wt_ekq(:,:), dbldelta_wts(:,:)
3076 : 5 : real(dp),allocatable :: tgamvv_in(:,:,:,:), vv_kk(:,:,:), tgamvv_out(:,:,:,:), vv_kkq(:,:,:), tmp_vals_ee(:,:,:,:,:), emesh(:)
3077 : 10 : logical,allocatable :: bks_mask(:,:,:),keep_ur(:,:,:)
3078 : 5 : type(fstab_t),target,allocatable :: fstab(:)
3079 : 5 : type(pawcprj_type),allocatable :: cwaveprj0(:,:)
3080 : : #ifdef HAVE_MPI
3081 : : integer :: ndims, comm_cart, me_cart, coords(5)
3082 : : logical :: reorder
3083 : 5 : integer,allocatable :: dims(:)
3084 : 5 : logical,allocatable :: periods(:), keepdim(:)
3085 : : #endif
3086 : : !************************************************************************
3087 : :
3088 : 5 : if (psps%usepaw == 1) then
3089 : 0 : ABI_ERROR("PAW not implemented")
3090 : : ABI_UNUSED((/pawang%nsym, pawrad(1)%mesh_size/))
3091 : : end if
3092 : :
3093 : 5 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
3094 [ + + ]: 15 : units = [std_out, ab_out]
3095 : 5 : call wrtout(std_out, " Computing ph linewidths in metals.")
3096 : 5 : call cwtime(cpu_all, wall_all, gflops_all, "start")
3097 : 5 : call pstat_proc%print(_PSTAT_ARGS_)
3098 : :
3099 : : ! Copy important dimensions
3100 : 5 : natom = cryst%natom; natom3 = 3 * natom; nsppol = ebands%nsppol; nspinor = ebands%nspinor; nspden = dtset%nspden
3101 : 5 : nkibz = ebands%nkpt; mband = ebands%mband
3102 : :
3103 : : ! FFT meshes
3104 [ + + ]: 20 : nfftf = product(ngfftf(1:3)); mgfftf = maxval(ngfftf(1:3))
3105 [ + + + + ]: 35 : nfft = product(ngfft(1:3)) ; mgfft = maxval(ngfft(1:3))
3106 : 5 : n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
3107 : 5 : n4 = ngfft(4); n5 = ngfft(5); n6 = ngfft(6)
3108 : :
3109 : : ! Compute electron DOS.
3110 : : !call dtset%get_edos_params(edos_intmeth, edos_step, edos_broad)
3111 [ - + ]: 5 : edos_intmeth = 2; if (dtset%prtdos /= 0) edos_intmeth = dtset%prtdos
3112 : : edos_step = dtset%dosdeltae; edos_broad = dtset%tsmear
3113 : 5 : edos_step = 0.01 * eV_Ha; edos_broad = 0.3 * eV_Ha
3114 [ - + - + : 5 : edos = ebands%get_edos(cryst, edos_intmeth, edos_step, edos_broad, comm)
- + - + -
+ ]
3115 : :
3116 : : ! Store DOS per spin channel.
3117 [ + + ]: 10 : n0(:) = edos%gef(1:edos%nsppol)
3118 [ + - ]: 5 : if (my_rank == master) then
3119 : 5 : call edos%print(units)
3120 : 5 : call edos%write(strcat(dtfil%filnam_ds(4), "_EDOS"))
3121 : : end if
3122 : :
3123 : : ! Find Fermi surface k-points
3124 : : ! TODO: support kptopt, change setup of k-points if tetra: fist tetra weights then k-points on the Fermi surface!
3125 [ - + + - : 20 : ABI_MALLOC(fstab, (nsppol))
+ - + - -
+ - + + +
+ - - + -
+ - + - +
- + - + -
+ - + - +
- + - + ]
3126 : 5 : call fstab_init(fstab, ebands, cryst, dtset, tetra, comm)
3127 : 5 : call tetra%free()
3128 : :
3129 : : ! Define q-mesh. eph_ngqpt_fine activates the Fourier interpolation of the DFPT potentials.
3130 [ + + + + : 16 : gamma_ngqpt = get_diag(ifc%qptrlatt); if (all(dtset%eph_ngqpt_fine /= 0)) gamma_ngqpt = dtset%eph_ngqpt_fine
+ + + + ]
3131 : :
3132 : 5 : call phgamma_init(gams, cryst, ifc, ebands, fstab(1), dtset, eph_scalprod0, gamma_ngqpt, n0, comm)
3133 : :
3134 : 5 : call wrtout(std_out, sjoin(" q-mesh for phonon linewidths:", ltoa(gamma_ngqpt)))
3135 : 5 : call wrtout(std_out, sjoin(" Will compute:", itoa(gams%nqibz), "q-points in the IBZ"))
3136 : 5 : call pstat_proc%print(_PSTAT_ARGS_)
3137 : :
3138 : : ! Select option for double delta with tetra.
3139 : : ! 2 for the optimized tetrahedron method.
3140 : : ! -2 for the linear tetrahedron method.
3141 : 5 : ltetra = 0
3142 [ + + ]: 5 : if (dtset%eph_intmeth == 2) ltetra = 2
3143 [ - + ]: 5 : if (dtset%eph_intmeth == -2) ltetra = 1
3144 : :
3145 : : ! Compute optimal energy window for tetra.
3146 : : !call find_ewin(gams%nqibz, gams%qibz, cryst, ebands, ltetra, sigma, comm)
3147 : :
3148 : : ! ========================
3149 : : ! === MPI DISTRIBUTION ===
3150 : : ! ========================
3151 : : ! Init for sequential execution.
3152 : 5 : my_npert = natom3
3153 : :
3154 [ + + + - : 30 : if (any(dtset%eph_np_pqbks /= 0)) then
- + ]
3155 : : ! Use parameters from input file.
3156 : 0 : pert_comm%nproc = dtset%eph_np_pqbks(1)
3157 : 0 : qpt_comm%nproc = dtset%eph_np_pqbks(2)
3158 : 0 : bsum_comm%nproc = dtset%eph_np_pqbks(3)
3159 : 0 : kpt_comm%nproc = dtset%eph_np_pqbks(4)
3160 : 0 : spin_comm%nproc = dtset%eph_np_pqbks(5)
3161 : 0 : my_npert = natom3 / pert_comm%nproc
3162 [ # # ]: 0 : ABI_CHECK(my_npert > 0, "pert_comm_nproc cannot be greater than 3 * natom.")
3163 [ # # ]: 0 : ABI_CHECK(mod(natom3, pert_comm%nproc) == 0, "pert_comm_nproc must divide 3 * natom.")
3164 : : else
3165 : : ! Automatic grid generation
3166 : : ! Not the most efficient distribution if large number of MPI procs.
3167 : : ! TODO: Add parallelism over perturbations although it's less efficient than the parallelism over k
3168 : : ! It starts to be interesting if we implement symmetries in the k-integration though.
3169 : :
3170 : : ! TODO: Spin
3171 : : ! Automatic grid generation over q-points and spins.
3172 : : !if (new%nsppol == 2 .and. mod(nprocs, 2) == 0) then
3173 : : ! spin_comm%nproc = 2
3174 : : ! new%qpt_comm%nproc = nprocs / 2
3175 : : !else
3176 : : ! new%qpt_comm%nproc = nprocs
3177 : : !end if
3178 : :
3179 : : ! Handle parallelism over perturbations first.
3180 : : ! Use MPI communicator to distribute the 3 * natom perturbations to reduce memory requirements for DFPT potentials.
3181 : : ! Ideally, perturbations are equally distributed --> total number of CPUs should be divisible by 3 * natom.
3182 : : ! or at least, divisible by one integer i for i in [2, 3 * natom - 1].
3183 : :
3184 [ - + - - ]: 5 : if (nsppol == 2 .and. mod(nproc, 2) == 0) then
3185 : 0 : spin_comm%nproc = 2
3186 : 0 : kpt_comm%nproc = nproc / 2
3187 : : else
3188 : : ! Try to have 3 perts per proc first because the q-point parallelism is more efficient.
3189 : : ! The memory for W(R,r,ipert) will increase though.
3190 : : !do cnt=natom,2,-1
3191 : : ! if (mod(nprocs, cnt) == 0 .and. mod(natom3, cnt) == 0) then
3192 : : ! pert_comm%nproc = cnt; new%my_npert = natom3 / cnt; exit
3193 : : ! end if
3194 : : !end do
3195 : :
3196 : : !if (pert_comm%nproc == 1) then
3197 : : ! ! Try again with more procs.
3198 : : ! do cnt=natom3,2,-1
3199 : : ! if (mod(nprocs, cnt) == 0 .and. mod(natom3, cnt) == 0) then
3200 : : ! pert_comm%nproc = cnt; new%my_npert = natom3 / cnt; exit
3201 : : ! end if
3202 : : ! end do
3203 : : !end if
3204 : :
3205 : : !if (new%my_npert == natom3 .and. nprocs > 1) then
3206 : : ! ABI_WARNING("The number of MPI procs should be divisible by 3*natom to reduce memory requirements!")
3207 : : !end if
3208 : :
3209 : 5 : kpt_comm%nproc = nproc
3210 : : end if
3211 : : end if
3212 : :
3213 : : ! Consistency check.
3214 [ - + ]: 5 : if (pert_comm%nproc * qpt_comm%nproc * bsum_comm%nproc * kpt_comm%nproc * spin_comm%nproc /= nproc) then
3215 : : write(msg, "(a,i0,3a, 6(a,1x,i0))") &
3216 : 0 : "Cannot create 5d Cartesian grid with total nproc: ", nproc, ch10, &
3217 : 0 : "Idle processes are not supported. The product of the `nproc_*` vars should be equal to nproc.", ch10, &
3218 : 0 : "pert_nproc (", pert_comm%nproc, ") x qpt_nproc (", qpt_comm%nproc, ") x bsum_nproc (", bsum_comm%nproc, &
3219 : 0 : ") x kcalc_nproc (", kpt_comm%nproc, ") x spin_nproc (", spin_comm%nproc, ") != ", &
3220 : 0 : pert_comm%nproc * qpt_comm%nproc * bsum_comm%nproc * kpt_comm%nproc * spin_comm%nproc
3221 : 0 : ABI_ERROR(msg)
3222 : : end if
3223 : :
3224 [ - + ]: 5 : ABI_CHECK(bsum_comm%nproc == 1, "Band parallelism not implemented in m_phgamma")
3225 : :
3226 : : #ifdef HAVE_MPI
3227 : : ! Create 5d cartesian communicator: 3*natom perturbations, q-points in IBZ, bands in FS, kpoints in FS, spins
3228 : 5 : ndims = 5
3229 [ - + ]: 5 : ABI_MALLOC(dims, (ndims))
3230 [ - + ]: 5 : ABI_MALLOC(periods, (ndims))
3231 [ - + ]: 5 : ABI_MALLOC(keepdim, (ndims))
3232 [ + + ]: 30 : periods(:) = .False.; reorder = .False.
3233 [ - + + + ]: 35 : dims = [pert_comm%nproc, qpt_comm%nproc, bsum_comm%nproc, kpt_comm%nproc, spin_comm%nproc]
3234 : :
3235 : 5 : call MPI_CART_CREATE(comm, ndims, dims, periods, reorder, comm_cart, ierr)
3236 : : ! Find the index and coordinates of the current processor
3237 : 5 : call MPI_COMM_RANK(comm_cart, me_cart, ierr)
3238 : 5 : call MPI_CART_COORDS(comm_cart, me_cart, ndims, coords, ierr)
3239 : :
3240 : : ! Create communicator to distribute natom3 perturbations.
3241 [ + + ]: 30 : keepdim = .False.; keepdim(1) = .True.
3242 : 5 : call MPI_CART_SUB(comm_cart, keepdim, pert_comm%value, ierr); pert_comm%me = xmpi_comm_rank(pert_comm%value)
3243 : : ! Create communicator for qpoints in self-energy integration.
3244 [ + + ]: 30 : keepdim = .False.; keepdim(2) = .True.
3245 : 5 : call MPI_CART_SUB(comm_cart, keepdim, qpt_comm%value, ierr); qpt_comm%me = xmpi_comm_rank(qpt_comm%value)
3246 : : ! Create communicator for bands for band summation
3247 [ + + ]: 30 : keepdim = .False.; keepdim(3) = .True.
3248 : 5 : call MPI_CART_SUB(comm_cart, keepdim, bsum_comm%value, ierr); bsum_comm%me = xmpi_comm_rank(bsum_comm%value)
3249 : : ! Create communicator for kpoints.
3250 [ + + ]: 30 : keepdim = .False.; keepdim(4) = .True.
3251 : 5 : call MPI_CART_SUB(comm_cart, keepdim, kpt_comm%value, ierr); kpt_comm%me = xmpi_comm_rank(kpt_comm%value)
3252 : : ! Create communicator for spins.
3253 [ + + ]: 30 : keepdim = .False.; keepdim(5) = .True.
3254 : 5 : call MPI_CART_SUB(comm_cart, keepdim, spin_comm%value, ierr); spin_comm%me = xmpi_comm_rank(spin_comm%value)
3255 : : ! Create communicator for the (qpoint, spin) loops
3256 [ + + ]: 30 : keepdim = .False.; keepdim(2) = .True.; keepdim(5) = .True.
3257 : 5 : call MPI_CART_SUB(comm_cart, keepdim, qs_comm%value, ierr); qs_comm%me = xmpi_comm_rank(qs_comm%value)
3258 : : ! Create communicator for the (perturbation, k-point, band_sum)
3259 [ + + + + ]: 40 : keepdim = .False.; keepdim(1) = .True.; keepdim(3:4) = .True.
3260 : 5 : call MPI_CART_SUB(comm_cart, keepdim, pkb_comm%value, ierr); pkb_comm%me = xmpi_comm_rank(pkb_comm%value)
3261 : :
3262 [ - + ]: 5 : ABI_FREE(dims)
3263 [ - + ]: 5 : ABI_FREE(periods)
3264 : 5 : ABI_FREE(keepdim)
3265 : 5 : call xmpi_comm_free(comm_cart)
3266 : : #endif
3267 : :
3268 : : ! Distribute spins and q-points in IBZ.
3269 [ - + ]: 5 : call xmpi_split_cyclic(nsppol, spin_comm%value, gams%my_nspins, gams%my_spins)
3270 [ - + ]: 5 : ABI_CHECK(gams%my_nspins > 0, sjoin("nsppol (", itoa(nsppol), ") < spin_comm_nproc (", itoa(spin_comm%nproc), ")"))
3271 : :
3272 [ - + ]: 5 : call xmpi_split_cyclic(gams%nqibz, qpt_comm%value, gams%my_nqibz, gams%my_iqibz)
3273 [ - + ]: 5 : ABI_CHECK(gams%my_nqibz > 0, sjoin("nqibz (", itoa(gams%nqibz), ") < qpt_comm_nproc (", itoa(qpt_comm%nproc), ")"))
3274 : :
3275 : : !ABI_CALLOC(qibz_done, (gams%nqibz))
3276 [ + - ]: 5 : path = strcat(dtfil%filnam_ds(4), "_A2F.nc")
3277 : 5 : ncid = nctk_noid
3278 : :
3279 [ + - ]: 5 : if (my_rank == master) then
3280 : 5 : call cwtime(cpu, wall, gflops, "start")
3281 : :
3282 : 5 : write(std_out, "(/,a)")" === MPI parallelism ==="
3283 : : !write(std_out, "(2(a,i0))")"P Allocating and summing bands from my_bsum_start: ", self%my_bsum_start, &
3284 : : ! " up to my_bsum_stop: ", self%my_bsum_stop
3285 : 5 : write(std_out, "(a,i0)")"P Number of CPUs for parallelism over perturbations: ", pert_comm%nproc
3286 : 5 : write(std_out, "(a,i0)")"P Number of perturbations treated by this CPU: ", my_npert
3287 : 5 : write(std_out, "(a,i0)")"P Number of CPUs for parallelism over q-points: ", qpt_comm%nproc
3288 : : !write(std_out, "(2(a,i0))")"P Number of q-points in the IBZ treated by this proc: " , &
3289 : : ! count(self%itreat_qibz == 1), " of ", self%nqibz
3290 : 5 : write(std_out, "(a,i0)")"P Number of CPUs for parallelism over bands: ", bsum_comm%nproc
3291 : 5 : write(std_out, "(a,i0)")"P Number of CPUs for parallelism over spins: ", spin_comm%nproc
3292 : 5 : write(std_out, "(a,i0)")"P Number of CPUs for parallelism over k-points: ", kpt_comm%nproc
3293 : : !write(std_out, "(2(a,i0),/)")"P Number of k-point in Sigma_nk treated by this proc: ", self%my_nkcalc, " of ", self%nkcalc
3294 : :
3295 : : ! Master creates the netcdf file used to store the results of the calculation.
3296 [ - + ]: 5 : NCF_CHECK(nctk_open_create(ncid, path, xmpi_comm_self))
3297 [ - + ]: 5 : NCF_CHECK(cryst%ncwrite(ncid))
3298 [ - + ]: 5 : NCF_CHECK(ebands%ncwrite(ncid))
3299 [ - + ]: 5 : NCF_CHECK(edos%ncwrite(ncid))
3300 : :
3301 : : ! Add dimensions.
3302 [ + + ]: 15 : ncerr = nctk_def_dims(ncid, [nctkdim_t("nqibz", gams%nqibz), nctkdim_t("natom3", natom3)], defmode=.True.)
3303 [ - + ]: 5 : NCF_CHECK(ncerr)
3304 [ + + ]: 20 : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "eph_intmeth", "eph_transport", "symdynmat"])
3305 [ - + ]: 5 : NCF_CHECK(ncerr)
3306 [ + + ]: 10 : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "ph_intmeth"])
3307 [ - + ]: 5 : NCF_CHECK(ncerr)
3308 [ + + ]: 25 : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: "eph_fsewin", "eph_fsmear", "eph_extrael", "eph_fermie"])
3309 [ - + ]: 5 : NCF_CHECK(ncerr)
3310 [ + + ]: 15 : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: "ph_wstep", "ph_smear"])
3311 [ - + ]: 5 : NCF_CHECK(ncerr)
3312 : :
3313 : : ! Define arrays for results.
3314 : : ncerr = nctk_def_arrays(ncid, [ &
3315 : : nctkarr_t("ngqpt", "int", "three"), &
3316 : : nctkarr_t("eph_ngqpt_fine", "int", "three"), &
3317 : : nctkarr_t("ddb_ngqpt", "int", "three"), &
3318 : : nctkarr_t("ph_ngqpt", "int", "three"), &
3319 : : nctkarr_t('qibz', "dp", "number_of_reduced_dimensions, nqibz"), &
3320 : : nctkarr_t('wtq', "dp", "nqibz"), &
3321 : : !nctkarr_t('qibz_done', "int", "nqibz"), &
3322 : : nctkarr_t('phfreq_qibz', "dp", "natom3, nqibz"), &
3323 : : nctkarr_t('phdispl_cart_qibz', "dp", "two, natom3, natom3, nqibz"), &
3324 : : nctkarr_t('phgamma_qibz', "dp", "natom3, nqibz, number_of_spins"), &
3325 : : nctkarr_t('phlambda_qibz', "dp", "natom3, nqibz, number_of_spins") &
3326 [ + + ]: 55 : ])
3327 [ - + ]: 5 : NCF_CHECK(ncerr)
3328 : :
3329 : : ! ======================================================
3330 : : ! Write data that do not depend on the (kpt, spin) loop.
3331 : : ! ======================================================
3332 [ - + ]: 5 : NCF_CHECK(nctk_set_datamode(ncid))
3333 : :
3334 : : ncerr = nctk_write_iscalars(ncid, &
3335 : : [character(len=nctk_slen) :: "eph_intmeth", "eph_transport", "symdynmat", "ph_intmeth"], &
3336 [ + + + + ]: 45 : [dtset%eph_intmeth, dtset%eph_transport, dtset%symdynmat, dtset%ph_intmeth])
3337 [ - + ]: 5 : NCF_CHECK(ncerr)
3338 : : ncerr = nctk_write_dpscalars(ncid, &
3339 : : [character(len=nctk_slen) :: "eph_fsewin", "eph_fsmear", "eph_extrael", "eph_fermie", "ph_wstep", "ph_smear"], &
3340 [ + + + + ]: 65 : [dtset%eph_fsewin, dtset%eph_fsmear, dtset%eph_extrael, dtset%eph_fermie, dtset%ph_wstep, dtset%ph_smear])
3341 [ - + ]: 5 : NCF_CHECK(ncerr)
3342 : :
3343 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'qibz'), gams%qibz))
3344 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'wtq'), gams%wtq))
3345 : : !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'qibz_done'), qibz_done))
3346 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngqpt"), gamma_ngqpt))
3347 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "eph_ngqpt_fine"), dtset%eph_ngqpt_fine))
3348 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ph_ngqpt"), dtset%ph_ngqpt))
3349 [ - + ]: 5 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ddb_ngqpt"), dtset%ddb_ngqpt))
3350 : : !NCF_CHECK(nf90_close(ncid))
3351 : 5 : call cwtime_report(" Creation of A2F.nc", cpu, wall, gflops, end_str=ch10)
3352 : : end if
3353 : : !call xmpi_barrier(comm)
3354 : :
3355 : : ! Now reopen the file inside ncwrite_comm to perform parallel-IO (required for q-point parallelism).
3356 : : !if (self%ncwrite_comm%value /= xmpi_comm_null) then
3357 : : ! NCF_CHECK(nctk_open_modify(self%ncid, path, self%ncwrite_comm%value))
3358 : : ! NCF_CHECK(nctk_set_datamode(self%ncid))
3359 : : !end if
3360 : 5 : call edos%free()
3361 : :
3362 : : ! Open the DVDB file
3363 : 5 : call dvdb%open_read(ngfftf, xmpi_comm_self)
3364 [ - + ]: 5 : ABI_CHECK(dvdb%has_fields("pot1", msg), msg)
3365 : :
3366 [ - + ]: 5 : if (pert_comm%nproc > 1) then
3367 : : ! Activate parallelism over perturbations
3368 : : ! Build table with list of perturbations treated by this CPU inside pert_comm
3369 [ # # # # ]: 0 : call ephtk_set_pertables(cryst%natom, my_npert, pert_table, my_pinfo, pert_comm%value)
3370 : 0 : call dvdb%set_pert_distrib(my_npert, natom3, my_pinfo, pert_table, pert_comm%value)
3371 [ # # ]: 0 : ABI_FREE(my_pinfo)
3372 [ # # ]: 0 : ABI_FREE(pert_table)
3373 : : end if
3374 : :
3375 : : ! Check whether all q-points are available in the input DVDB file.
3376 : 5 : need_ftinterp = .False.
3377 [ + + ]: 66 : do iq_ibz=1,gams%nqibz
3378 [ - + ]: 66 : if (dvdb%findq(gams%qibz(:,iq_ibz) ) == -1) then
3379 : 0 : need_ftinterp = .True.; exit
3380 : : end if
3381 : : end do
3382 : 5 : call wrtout(std_out, " ", do_flush=.True.)
3383 : :
3384 : : ! Find correspondence IBZ --> set of q-points in DVDB.
3385 : : ! Activate FT interpolation automatically if required q-points in the IBZ are not found in the DVDB.
3386 : : !need_ftinterp = .False.
3387 : : !ABI_MALLOC(qibz2dvdb, (sigma%nqibz))
3388 : : !if (dvdb%find_qpts(sigma%nqibz, sigma%qibz, qibz2dvdb, comm) /= 0) then
3389 : : ! call wrtout(units, " Cannot find eph_ngqpt_fine q-points in DVDB --> Activating Fourier interpolation.")
3390 : : ! need_ftinterp = .True.
3391 : : !else
3392 : : ! call wrtout(units, " DVDB file contains all q-points in the IBZ --> Reading DFPT potentials from file.")
3393 : : ! need_ftinterp = .False.
3394 : : !end if
3395 : :
3396 : : !if (.not. need_ftinterp .and. dtset%eph_use_ftinterp /= 0) then
3397 : : ! ABI_WARNING("Enforcing FT interpolation for q-points even if it's not strictly needed.")
3398 : : ! need_ftinterp = .True.
3399 : : !end if
3400 : :
3401 [ - + ]: 5 : if (need_ftinterp) then
3402 : 0 : call wrtout(units, " Cannot find eph_ngqpt_fine q-points in DVDB --> Activating Fourier interpolation.")
3403 : : ! Prepare Fourier interpolation of DFPT potentials.
3404 : 0 : comm_rpt = xmpi_comm_self
3405 : : !comm_rpt = bqs_comm%value
3406 : 0 : call dvdb%ftinterp_setup(dtset%ddb_ngqpt, qptopt1, 1, dtset%ddb_shiftq, nfftf, ngfftf, comm_rpt)
3407 : : end if
3408 : :
3409 : : ! Initialize the wave function descriptor.
3410 : : ! Only wavefunctions on the FS are stored in wfd.
3411 : : ! Need all k-points on the FS because of k+q, spin is not distributed for the time being.
3412 : : ! It would be possible to reduce the memory allocated per MPI-rank via OpenMP.
3413 : :
3414 [ - + + - : 20 : ABI_MALLOC(nband, (nkibz, nsppol))
- + + - +
- + - - +
- + ]
3415 [ - + + - : 25 : ABI_MALLOC(bks_mask, (mband, nkibz, nsppol))
- + + - -
+ + - + -
+ - - + -
+ ]
3416 [ - + + - : 20 : ABI_MALLOC(keep_ur, (mband, nkibz ,nsppol))
- + + - -
+ + - - +
- + ]
3417 [ + + + + : 1905 : nband = mband; bks_mask = .False.; keep_ur = .False.
+ + + + +
+ + + + +
+ + ]
3418 : :
3419 [ + + ]: 10 : do my_is=1,gams%my_nspins
3420 : 5 : spin = gams%my_spins(my_is); fs => fstab(spin)
3421 [ + + ]: 700 : do ik_bz=1,fs%nkfs
3422 : 690 : ik_ibz = fs%indkk_fs(1, ik_bz)
3423 : 690 : bstart_k = fs%bstart_cnt_ibz(1, ik_ibz); nb_k = fs%bstart_cnt_ibz(2, ik_ibz)
3424 [ + + ]: 1385 : bks_mask(bstart_k:bstart_k+nb_k-1, ik_ibz, spin) = .True.
3425 : : end do
3426 : : end do
3427 : : !bks_mask(1:mband,:,:) = .True. ! no memory distribution, each node has the full set of states.
3428 : :
3429 : : ! Impose istwfk = 1 for all k-points. This is also done in respfn (see inkpts)
3430 : : ! wfd_read_wfk will handle a possible conversion if WFK contains istwfk /= 1.
3431 [ - + + - : 15 : ABI_MALLOC(wfd_istwfk, (nkibz))
+ - + - -
+ - + ]
3432 [ + + ]: 150 : wfd_istwfk = 1
3433 : :
3434 : 5 : ecut = dtset%ecut ! dtset%dilatmx
3435 : : call wfd%init(cryst, pawtab, psps, keep_ur, mband, nband, nkibz, nsppol, bks_mask,&
3436 : : nspden, nspinor, ecut, dtset%ecutsm, dtset%dilatmx, wfd_istwfk, ebands%kptns, ngfft,&
3437 : 5 : dtset%nloalg, dtset%prtvol, dtset%pawprtvol, comm)
3438 : :
3439 [ + + ]: 10 : call wfd%print([std_out], header="Wavefunctions on the Fermi surface")
3440 : :
3441 [ - + ]: 5 : ABI_FREE(nband)
3442 [ - + ]: 5 : ABI_FREE(keep_ur)
3443 [ - + ]: 5 : ABI_FREE(wfd_istwfk)
3444 : :
3445 : : ! Read wavefunctions.
3446 : 5 : call wfd%read_wfk(wfk0_path, iomode_from_fname(wfk0_path))
3447 : :
3448 : : ! one-dimensional structure factor information on the coarse grid.
3449 [ + - - + : 15 : ABI_MALLOC(ph1d, (2, 3*(2*mgfft+1)*natom))
+ - + - +
- - + - +
- + ]
3450 : 5 : call getph(cryst%atindx, natom, n1, n2, n3, ph1d, cryst%xred)
3451 : :
3452 : : ! mpw is the maximum number of plane-waves over k and k+q where k and k+q are in the BZ.
3453 : : ! we also need the max components of the G-spheres (k, k+q) in order to allocate the workspace array work
3454 : : ! that will be used to symmetrize the wavefunctions in G-space.
3455 : 5 : call cwtime(cpu, wall, gflops, "start")
3456 : 5 : call wrtout(std_out, " Computing mpw. This may take some time for dense k/q meshes...")
3457 : : !call fstab_get_mpw_gmax(nsppol, fstab, mpw, gmax, comm)
3458 : 5 : mpw = 0; gmax = 0; cnt = 0
3459 : :
3460 : : ! FIXME: This is an hotspot due to the loop over nkfs.
3461 : : ! Should use a geometric approach to compute mpw gmax.
3462 [ + + ]: 10 : do spin=1,nsppol
3463 : 5 : fs => fstab(spin)
3464 [ + + ]: 700 : do ik_bz=1,fs%nkfs
3465 [ + - ]: 690 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism inside comm
3466 [ + + ]: 2760 : kk = fs%kpts(:, ik_bz)
3467 : : ! Compute G sphere, returning npw. Note istwfk == 1.
3468 [ - + ]: 690 : call get_kg(kk, 1, ecut, cryst%gmet, onpw, gtmp)
3469 : 690 : mpw = max(mpw, onpw)
3470 [ + + ]: 52350 : do ipw=1,onpw
3471 [ + + ]: 207330 : do ii=1,3
3472 : 206640 : gmax(ii) = max(gmax(ii), abs(gtmp(ii,ipw)))
3473 : : end do
3474 : : end do
3475 [ - + ]: 690 : ABI_FREE(gtmp)
3476 : :
3477 [ + + ]: 9113 : do iq_ibz=1,gams%nqibz
3478 [ + + ]: 33672 : qpt = gams%qibz(:,iq_ibz)
3479 : : ! TODO: g0 umklapp here can enter into play!
3480 : : ! fstab should contains the max of the umlapp G-vectors.
3481 : : ! gmax could not be large enough!
3482 [ + + ]: 33672 : kq = kk + qpt
3483 [ - + ]: 8418 : call get_kg(kq, 1, ecut, cryst%gmet, onpw, gtmp)
3484 : 8418 : mpw = max(mpw, onpw)
3485 [ + + ]: 633595 : do ipw=1,onpw
3486 [ + + ]: 2509126 : do ii=1,3
3487 : 2500708 : gmax(ii) = max(gmax(ii), abs(gtmp(ii,ipw)))
3488 : : end do
3489 : : end do
3490 [ - + ]: 9108 : ABI_FREE(gtmp)
3491 : : end do
3492 : :
3493 : : end do ! ik_bz
3494 : : end do ! spin
3495 : :
3496 : 5 : my_mpw = mpw; call xmpi_max(my_mpw, mpw, comm, ierr)
3497 : 5 : my_gmax = gmax; call xmpi_max(my_gmax, gmax, comm, ierr)
3498 : 5 : call wrtout(std_out, sjoin(' Optimal value of mpw: ', itoa(mpw)))
3499 : 5 : call cwtime_report(" Computation of gmax and mpw:", cpu, wall, gflops)
3500 : :
3501 : : ! Init work_ngfft
3502 [ + + ]: 20 : gmax = gmax + 4 ! FIXME: this is to account for umklapp
3503 [ + + ]: 20 : gmax = 2*gmax + 1
3504 : 5 : call ngfft_seq(work_ngfft, gmax)
3505 : : !write(std_out,*)"work_ngfft(1:3): ",work_ngfft(1:3)
3506 [ - + + - : 25 : ABI_MALLOC(work, (2, work_ngfft(4), work_ngfft(5), work_ngfft(6)))
- + + - -
+ + - + -
+ - - + -
+ ]
3507 : :
3508 : : ! Allow PW-arrays dimensioned with mpw
3509 [ - + + - : 15 : ABI_MALLOC(kg_k, (3, mpw))
+ - + - -
+ - + -
+ ]
3510 [ - + + - : 10 : ABI_MALLOC(kg_kq, (3, mpw))
- + - + -
+ ]
3511 : :
3512 : : ! TODO FOR PAW
3513 : 5 : usecprj = 0
3514 [ - + + - : 10 : ABI_MALLOC(cwaveprj0, (natom, nspinor*usecprj))
- + - + -
+ ]
3515 : :
3516 : : ! Prepare call to getgh1c
3517 : 5 : usevnl = 0
3518 : 5 : optlocal = 1 ! local part of H^(1) is computed in gh1c=<G|H^(1)|C>
3519 : 5 : optnl = 2 ! non-local part of H^(1) is totally computed in gh1c=<G|H^(1)|C>
3520 : 5 : opt_gvnlx1 = 0 ! gvnlx1 is output
3521 : :
3522 [ - + - + ]: 5 : ABI_MALLOC(grad_berry, (2, nspinor*(berryopt0/4)))
3523 : :
3524 : : ! This part is taken from dfpt_vtorho
3525 : : !==== Initialize most of the Hamiltonian (and derivative) ====
3526 : : !1) Allocate all arrays and initialize quantities that do not depend on k and spin.
3527 : : !2) Perform the setup needed for the non-local factors:
3528 : : ! Norm-conserving: Constant kleimann-Bylander energies are copied from psps to gs_hamk.
3529 : : ! PAW: Initialize the overlap coefficients and allocate the Dij coefficients.
3530 : :
3531 : : call gs_hamkq%init(psps, pawtab, nspinor, nsppol, nspden, natom, &
3532 : : dtset%typat, cryst%xred, nfft, mgfft, ngfft, cryst%rprimd, dtset%nloalg, &
3533 : : comm_atom=mpi_enreg%comm_atom, mpi_atmtab=mpi_enreg%my_atmtab, mpi_spintab=mpi_enreg%my_isppoltab, &
3534 : 5 : usecprj=usecprj, ph1d=ph1d, nucdipmom=dtset%nucdipmom, gpu_option=dtset%gpu_option)
3535 : :
3536 : : ! Allocate vlocal. Note nvloc
3537 : : ! I set vlocal to huge to trigger possible bugs (DFPT routines should not access the data)
3538 [ - + + - : 30 : ABI_MALLOC(vlocal, (n4, n5, n6, gs_hamkq%nvloc))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
3539 [ + + + + : 10990 : vlocal = huge(one)
+ + + + ]
3540 : :
3541 : : ! Allocate work space arrays.
3542 [ - + + - : 20 : ABI_MALLOC(tgam, (2, natom3, natom3))
- + + - +
- + - - +
- + - + ]
3543 [ - + + - : 20 : ABI_MALLOC(displ_cart, (2, 3, cryst%natom, natom3))
- + + - +
- + - - +
- + ]
3544 [ - + + - : 15 : ABI_MALLOC(displ_red, (2, 3, cryst%natom, natom3))
- + + - -
+ - + ]
3545 [ - + + - : 8665 : ABI_CALLOC(dummy_vtrial, (nfftf, nspden))
- + + - +
- + - - +
- + + + +
+ ]
3546 : :
3547 : : ! TODO: Save data to netcdf file for each q in IBZ and then read data to build a2Fw once all big
3548 : : ! datastructures (wfd, dvdb) have been deallocated.
3549 : : ! As a side effect, one can also implement restart over q-points
3550 : :
3551 : : ! Create ddkop object to compute group velocities if needed.
3552 : : !
3553 : : ! 1) precompute group velocities in the IBZ and the ihave_ikibz_spin file (common to all procs)
3554 : : ! 2) Use symmetries to reconstruct v_kq from vcart_ibz
3555 : : !
3556 : : ! NB: All procs store in memory the same set of Bloch states inside the energy window.
3557 : :
3558 : 5 : call ddkop%init(dtset, cryst, pawtab, psps, wfd%mpi_enreg, mpw, wfd%ngfft)
3559 : :
3560 : 5 : call cwtime(cpu, wall, gflops, "start", msg=" Computing v_nk matrix elements for all states on the FS...")
3561 : 5 : ii = huge(1); jj = -1
3562 [ + + ]: 10 : do spin=1,nsppol
3563 : 5 : ii = min(ii, fstab(spin)%bmin)
3564 : 10 : jj = max(jj, fstab(spin)%bmax)
3565 : : end do
3566 [ - + + - : 1335 : ABI_CALLOC(vcart_ibz, (3, ii:jj, nkibz, nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + + +
+ + + + +
+ ]
3567 [ - + + - : 15 : ABI_MALLOC(cg_work, (2, mpw * wfd%nspinor))
+ - + - -
+ - + ]
3568 : :
3569 : 5 : cnt = 0
3570 [ + + ]: 10 : do spin=1,nsppol
3571 : 5 : fs => fstab(spin)
3572 [ + + ]: 155 : do ik_ibz=1,ebands%nkpt
3573 [ + + ]: 580 : kk = ebands%kptns(:, ik_ibz); npw_k = wfd%npwarr(ik_ibz); istwf_k = wfd%istwfk(ik_ibz)
3574 : : ! NB: The two checks below are global --> all procs will cycle.
3575 [ + + + + : 760 : if (all(bks_mask(:, ik_ibz, spin) .eqv. .False.)) cycle
+ + ]
3576 [ - + ]: 30 : if (npw_k == 1) cycle
3577 [ - + ]: 30 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
3578 : :
3579 : 30 : call ddkop%setup_spin_kpoint(dtset, cryst, psps, spin, kk, istwf_k, npw_k, wfd%kdata(ik_ibz)%kg_k)
3580 : :
3581 [ + + ]: 95 : do band_k=fs%bmin,fs%bmax
3582 [ + + ]: 60 : if (.not. bks_mask(band_k, ik_ibz, spin)) cycle
3583 : 30 : call wfd%copy_cg(band_k, ik_ibz, spin, cg_work)
3584 : 30 : eig0nk = ebands%eig(band_k, ik_ibz, spin)
3585 : 30 : vk = ddkop%get_vdiag(eig0nk, istwf_k, npw_k, wfd%nspinor, cg_work, cwaveprj0)
3586 [ + + ]: 265 : vcart_ibz(:, band_k, ik_ibz, spin) = vk
3587 : :
3588 : : ! TODO: Use ebands_get_edos_matrix_elements
3589 : : ! reald(dp) :: vv_fs(3,3,nsppol)
3590 : : !vv_fs = zero
3591 : : !sigma = fs%eph_fsmear
3592 : : !if (fs%eph_fsmear < zero) then
3593 : : ! sigma = max(maxval([(abs(dot_product(fs%vk(:, ib2), fs%kmesh_cartvec(:,ii))), ii=1,3)]), fs%min_smear)
3594 : : !end if
3595 : : !fs_wtk = gaussian(emesh - ebands%eig(band_k, ik_ibz, spin), sigma) / (one * fs%nktot)
3596 : : !do ii=1,3
3597 : : ! do jj=1,3
3598 : : ! vv_fs(ii,jj,spin) = vv_fs(ii,jj,spin) + vk(ii) * vk(jj) * fs_wtk
3599 : : ! end do
3600 : : !end do
3601 : : !call xmpi_sum(vv_fs, comm, ierr)
3602 : : end do
3603 : : end do
3604 : : end do ! spin
3605 : :
3606 : 5 : call xmpi_sum(vcart_ibz, comm, ierr)
3607 [ - + ]: 5 : ABI_FREE(cg_work)
3608 : 5 : call cwtime_report(" Computation of group velocities", cpu, wall, gflops)
3609 : :
3610 [ - + ]: 5 : ABI_FREE(bks_mask)
3611 : :
3612 : : !Write v_nk to disk.
3613 : : !if (my_rank == master) then
3614 : : ! NCF_CHECK(nf90_put_var(sigma%ncid, nctk_idname(sigma%ncid, "vcart_ibz"), vcart_ibz))
3615 : : !end if
3616 : :
3617 [ + - ]: 5 : if (dtset%eph_transport > 0) then
3618 [ - + + - : 20 : ABI_MALLOC(tgamvv_in, (2, 9, natom3, natom3))
- + + - +
- + - - +
- + - + ]
3619 [ - + + - : 15 : ABI_MALLOC(tgamvv_out, (2, 9, natom3, natom3))
- + + - -
+ - + -
+ ]
3620 : : end if
3621 : :
3622 : : ! Build krank object to find k-points
3623 : 5 : call krank%from_kptrlatt(ebands%nkpt, ebands%kptns, ebands%kptrlatt, compute_invrank=.False.)
3624 : 5 : call pstat_proc%print(_PSTAT_ARGS_)
3625 : :
3626 : : ! Loop over my q-points in the IBZ.
3627 [ + + ]: 66 : do my_iq=1,gams%my_nqibz
3628 : 61 : iq_ibz = gams%my_iqibz(my_iq)
3629 : :
3630 : : ! TODO: Restart capabilities
3631 : : ! Check if this (kpoint, spin) was already calculated
3632 : : !if (all(qibz_done(iq_ibz, :) == 1)) cycle
3633 : :
3634 : 61 : call cwtime(cpu_q, wall_q, gflops_q, "start")
3635 : :
3636 [ + + ]: 244 : qpt = gams%qibz(:, iq_ibz)
3637 [ + - ]: 61 : msg = sjoin("[", itoa(iq_ibz), "/", itoa(gams%nqibz), "]")
3638 : 61 : call wrtout(std_out, sjoin(" Computing ph linewidths for IBZ q-point:", ktoa(qpt), msg))
3639 : :
3640 [ + + + + : 1891 : tgam = zero
+ + ]
3641 [ + - ]: 61 : if (dtset%eph_transport > 0) then
3642 [ + + + + : 31171 : tgamvv_in = zero; tgamvv_out = zero
+ + + + +
+ + + + +
+ + ]
3643 : : end if
3644 : :
3645 [ + - ]: 61 : if (.not. need_ftinterp) then
3646 : : ! No interpolation --> find the index of the q-point in the DVDB.
3647 : 61 : db_iqpt = dvdb%findq(qpt)
3648 : :
3649 [ + - ]: 61 : if (db_iqpt /= -1) then
3650 : : ! Read and reconstruct the dvscf potentials for all 3*natom perturbations.
3651 : : ! This call allocates v1scf(cplex, nfftf, nspden, 3*natom))
3652 [ - + ]: 61 : call dvdb%readsym_allv1(db_iqpt, cplex, nfftf, ngfftf, v1scf, pkb_comm%value)
3653 : :
3654 [ - + ]: 61 : if (dvdb%my_npert /= natom3) then
3655 : : ! Extract my npert from v1scf
3656 [ # # # # : 0 : ABI_MALLOC(v1_work, (cplex, nfftf, nspden, dvdb%my_npert))
# # # # #
# # # # #
# # # # #
# # # #
# ]
3657 [ # # ]: 0 : do my_ip=1,dvdb%my_npert
3658 [ # # # # : 0 : v1_work(:,:,:,my_ip) = v1scf(:,:,:,dvdb%my_pinfo(3, my_ip))
# # ]
3659 : : end do
3660 [ # # ]: 0 : ABI_MOVE_ALLOC(v1_work, v1scf)
3661 : : end if
3662 : :
3663 : : else
3664 : 0 : ABI_ERROR(sjoin("Cannot find q-point:", ktoa(qpt), "in the DVDB file."))
3665 : : end if
3666 : :
3667 : : else
3668 : : ! Use Fourier interpolation of DFPT potentials to get my_npert potentials.
3669 : 0 : cplex = 2
3670 [ # # # # : 0 : ABI_MALLOC(v1scf, (cplex, nfft, nspden, dvdb%my_npert))
# # # # #
# # # # #
# # # # #
# # # ]
3671 : 0 : call dvdb%ftinterp_qpt(qpt, nfftf, ngfftf, v1scf, dvdb%comm_rpt)
3672 : : end if
3673 : :
3674 : : ! Compute the little group of the q-point so that we can compute g(k,q) only for k in the IBZ_q
3675 : : !if (dtset%symsigma /= 0) then
3676 : : ! timrev_q = kpts_timrev_from_kptopt(my_qptopt)
3677 : : ! call lg_q%init(cryst, qpt, timrev_q, gstore%nkbz, gstore%kbz, gstore%nkibz, gstore%kibz, xmpi_comm_self)
3678 : : !end if
3679 : :
3680 : : !if (dtset%symsigma /= 0) then
3681 : : ! ii = lg_q%findq_ibzk(kk)
3682 : : ! if (ii == -1) then
3683 : : ! call wrtout(std_out, sjoin(" my_ik:", itoa(my_ik), kk_string, " not in IBZ_q --> skipping iteration"))
3684 : : ! cycle
3685 : : ! ! TODO: Check fillvalue (should be zero)
3686 : : ! end if
3687 : : ! weight_k = lg_q%weights(ii)
3688 : : !end if
3689 : : !call lg_q%free()
3690 : :
3691 : : ! Get phonon frequencies and eigenvectors for this q-point.
3692 : 61 : call ifc%fourq(cryst, qpt, phfrq, displ_cart, out_displ_red=displ_red)
3693 : 61 : wminmax(1) = min(wminmax(1), phfrq(1))
3694 : 61 : wminmax(2) = max(wminmax(2), phfrq(3*cryst%natom))
3695 : :
3696 : : ! Allocate vlocal1 with correct cplex. Note nvloc and my_npert.
3697 [ - + + - : 427 : ABI_MALLOC(vlocal1, (cplex*n4, n5, n6, gs_hamkq%nvloc, my_npert))
- + + - -
+ + - - +
+ - - + +
- + - + -
- + - + ]
3698 : :
3699 : : ! Loop over my spins.
3700 [ + + ]: 122 : do my_is=1,gams%my_nspins
3701 : 61 : spin = gams%my_spins(my_is); fs => fstab(spin)
3702 : :
3703 [ - + ]: 61 : if (dtset%prteliash == 3) then
3704 [ # # # # : 0 : ABI_CALLOC_OR_DIE(tmp_vals_ee, (2, gams%nene, gams%nene, natom3, natom3), ierr)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
3705 : : ! Energy mesh for electrons in a2F(e,e',w) NB: It depends on the spin through enemin
3706 [ # # # # : 0 : ABI_MALLOC(emesh, (gams%nene))
# # # # #
# # # #
# ]
3707 [ # # ]: 0 : emesh = arth(fs%enemin, fs%deltaene, gams%nene)
3708 : : end if
3709 : :
3710 : : ! Set up local potential vlocal1 with proper dimensioning from vtrial1 taking into account the spin.
3711 [ + + ]: 244 : do my_ip=1,my_npert
3712 : : call rf_transgrid_and_pack(spin, nspden, psps%usepaw, cplex, nfftf, nfft, ngfft, gs_hamkq%nvloc,&
3713 : 244 : pawfgr, mpi_enreg, dummy_vtrial, v1scf(:,:,:,my_ip), vlocal, vlocal1(:,:,:,:,my_ip))
3714 : : end do
3715 : :
3716 : : ! Continue to initialize the GS Hamiltonian
3717 : 61 : call gs_hamkq%load_spin(spin, vlocal=vlocal, with_nonlocal=.true.)
3718 : :
3719 : : ! Allocate workspace for wavefunctions. Make npw larger than expected.
3720 : : ! maxnb is the maximum number of bands crossing the FS, used to dimension arrays.
3721 : 61 : mnb = fs%maxnb
3722 : : ! The weights for the integration of the double-delta.
3723 [ - + + - : 244 : ABI_MALLOC(dbldelta_wts, (mnb, mnb))
- + + - +
- + - - +
- + - + ]
3724 : :
3725 [ + - ]: 61 : if (dtset%eph_transport > 0) then
3726 [ - + + - : 244 : ABI_MALLOC(vv_kk, (9, mnb, mnb))
- + + - +
- + - - +
- + - + ]
3727 [ - + + - : 183 : ABI_MALLOC(vv_kkq, (9, mnb, mnb))
- + + - -
+ - + -
+ ]
3728 : : end if
3729 : :
3730 [ - + ]: 61 : if (dtset%prteliash == 3) then
3731 [ # # # # : 0 : ABI_MALLOC(wt_ek, (gams%nene, mnb))
# # # # #
# # # # #
# # # # ]
3732 [ # # # # : 0 : ABI_MALLOC(wt_ekq, (gams%nene, mnb))
# # # # #
# # # #
# ]
3733 : : end if
3734 : :
3735 : : ! =====================================
3736 : : ! Integration over the FS for this spin
3737 : : ! =====================================
3738 : : ! Compute integration weights and distribute k-points (gams%my_nfsk_q) inside kpt_comm
3739 : 61 : call phgamma_setup_qpoint(gams, fs, cryst, ebands, spin, ltetra, qpt, nesting, kpt_comm%value)
3740 : :
3741 [ + + ]: 6265 : do my_ik=1,gams%my_nfsk_q
3742 [ + + + - : 6204 : print_time_k = (my_ik <= 2 .or. (fs%nkfs > 100 .and. mod(my_ik, 200) == 0))
- + ]
3743 : 122 : if (print_time_k) call cwtime(cpu_k, wall_k, gflops_k, "start")
3744 : :
3745 : : ! The k-point and the symmetries relating the BZ k-point to the IBZ.
3746 : 6204 : ik_fs = gams%my_ifsk_q(my_ik)
3747 [ + + ]: 24816 : kk = fs%kpts(:, ik_fs)
3748 : 6204 : ik_ibz = fs%indkk_fs(1, ik_fs); isym_k = fs%indkk_fs(2, ik_fs)
3749 [ + + ]: 24816 : trev_k = fs%indkk_fs(6, ik_fs); g0_k = fs%indkk_fs(3:5,ik_fs)
3750 [ + + + + : 19906 : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
+ + - + ]
3751 [ + + ]: 24816 : kk_ibz = ebands%kptns(:,ik_ibz)
3752 : :
3753 : : ! Number of bands crossing the Fermi level at k.
3754 : 6204 : bstart_k = fs%bstart_cnt_ibz(1, ik_ibz); nb_k = fs%bstart_cnt_ibz(2, ik_ibz)
3755 : :
3756 : : ! Find k+q in the extended zone and extract symmetry info. cycle if k+q not in FS.
3757 : : ! Be careful here because there are two umklapp vectors to be considered:
3758 : : !
3759 : : ! k + q = k_bz + g0_bz = IS(k_ibz) + g0_ibz + g0_bz
3760 : : !
3761 [ + + ]: 24816 : kq = kk + qpt; ikq_bz = fs%findkg0(kq, g0bz_kq)
3762 : :
3763 : : ! Skip this point if kq does not belong to the FS window.
3764 [ + + ]: 6204 : if (ikq_bz == -1) cycle
3765 : :
3766 [ - + ]: 2864 : if (kpts_map("symrel", ebands%kptopt, cryst, krank, 1, kq, indkk_kq) /= 0) then
3767 : : write(msg, '(9a)' ) &
3768 : 0 : "The WFK file cannot be used to compute phonon linewidths.",ch10, &
3769 : 0 : "At least one of the k-points on the FS could not be generated from a symmetrical one.", ch10, &
3770 [ # # # # ]: 0 : "q-mesh: ", trim(ltoa(gamma_ngqpt)), ", k-mesh (from kptrlatt) ", trim(ltoa(get_diag(ebands%kptrlatt))), &
3771 : 0 : 'Action: check your WFK file and the (k, q) point input variables.'
3772 : 0 : ABI_ERROR(msg)
3773 : : end if
3774 : :
3775 : : ! The k+q point and the symmetries relating it to the IBZ.
3776 : 2864 : ikq_ibz = indkk_kq(1, 1); isym_kq = indkk_kq(2, 1)
3777 [ + + ]: 11456 : trev_kq = indkk_kq(6, 1); g0_kq = indkk_kq(3:5, 1)
3778 [ + + + + : 6934 : isirr_kq = (isym_kq == 1 .and. trev_kq == 0 .and. all(g0_kq == 0))
+ + + + ]
3779 [ + + ]: 11456 : kq_ibz = ebands%kptns(:, ikq_ibz)
3780 : :
3781 : : ! If we have used the KERANGE trick, we may have k or k+q points with just one G component set to zero
3782 : : ! so we skip this transition immediately. This should happen only if fsewin > sigma_erange.
3783 [ + - + - ]: 2864 : if (wfd%npwarr(ik_ibz) == 1 .or. wfd%npwarr(ikq_ibz) == 1) cycle
3784 : :
3785 : : ! Number of bands crossing the Fermi level at k+q.
3786 : 2864 : bstart_kq = fs%bstart_cnt_ibz(1, ikq_ibz); nb_kq = fs%bstart_cnt_ibz(2, ikq_ibz)
3787 [ - + ]: 2864 : ABI_CHECK(nb_k <= mnb .and. nb_kq <= mnb, "wrong nband")
3788 : :
3789 : : ! Get npw_k, kg_k and symmetrize wavefunctions from IBZ (if needed).
3790 : : call wfd%sym_ug_kg_npw(ecut, kk, kk_ibz, bstart_k, nb_k, spin, fs%indkk_fs(:,ik_fs), cryst, &
3791 [ - + ]: 2864 : work_ngfft, work, istwf_k, npw_k, kg_k, kets_k)
3792 : :
3793 : : ! Get npw_kq, kg_kq and symmetrize wavefunctions from IBZ (if needed).
3794 : : call wfd%sym_ug_kg_npw(ecut, kq, kq_ibz, bstart_kq, nb_kq, spin, indkk_kq(:,1), cryst, &
3795 [ - + ]: 2864 : work_ngfft, work, istwf_kq, npw_kq, kg_kq, bras_kq)
3796 : :
3797 : : call gs_hamkq%eph_setup_k("k" , kk, istwf_k, npw_k, kg_k, dtset, cryst, psps, & ! in
3798 [ - + - + : 2864 : nkpg, kpg_k, ffnl_k, kinpw_k, ph3d_k, pert_comm%value) ! out
- + - + ]
3799 : :
3800 : : call gs_hamkq%eph_setup_k("kq", kq, istwf_k, npw_kq, kg_kq, dtset, cryst, psps, & ! in
3801 [ - + - + : 2864 : nkpg, kpg_kq, ffnl_kq, kinpw_kq, ph3d_kq, pert_comm%value) ! out
- + - + ]
3802 : :
3803 : : ! If PAW, one has to solve a generalized eigenproblem
3804 [ - + ]: 2864 : gen_eigenpb = psps%usepaw == 1; sij_opt = 0; if (gen_eigenpb) sij_opt = 1
3805 : :
3806 [ - + + - : 8592 : ABI_MALLOC(lambda, (nb_k))
+ - + - -
+ - + -
+ ]
3807 [ - + + - : 14320 : ABI_MALLOC(gkq_atm, (2, nb_kq, nb_k, natom3))
- + + - -
+ + - + -
+ - - + -
+ - + ]
3808 [ - + + - : 11456 : ABI_MALLOC(h1_kets_kq, (2, npw_kq*nspinor, nb_k))
- + + - +
- + - - +
- + - + ]
3809 [ - + + - : 8592 : ABI_MALLOC(gvnlx1, (2, npw_kq*nspinor, nb_k))
- + + - -
+ - + -
+ ]
3810 [ + - - - : 8592 : ABI_MALLOC(gs1c_kq, (2, npw_kq*nspinor*nb_k*((sij_opt+1)/2)))
+ - - + -
+ - + -
+ ]
3811 [ - + + - : 11456 : ABI_MALLOC(gkq_atm_ipc, (2, nb_kq, nb_k))
- + + - +
- + - - +
- + - + ]
3812 : : #ifdef HAVE_OPENMP_OFFLOAD
3813 : : !$OMP TARGET ENTER DATA MAP(alloc:gkq_atm_ipc) IF (dtset%gpu_option == ABI_GPU_OPENMP)
3814 : : !$OMP TARGET ENTER DATA MAP(to:kets_k, bras_kq) IF (dtset%gpu_option == ABI_GPU_OPENMP)
3815 : : !$OMP TARGET ENTER DATA MAP(alloc:h1_kets_kq, gvnlx1, kets_k, bras_kq) IF (dtset%gpu_option == ABI_GPU_OPENMP)
3816 : : !$OMP TARGET ENTER DATA MAP(alloc:gs1c_kq) IF (dtset%gpu_option == ABI_GPU_OPENMP .and. sij_opt /= 0)
3817 : : #endif
3818 : :
3819 : : ! Loop over all my atomic perturbations and compute gkq_atm.
3820 [ + + ]: 11456 : do my_ip=1,my_npert
3821 : 8592 : idir = dvdb%my_pinfo(1, my_ip); ipert = dvdb%my_pinfo(2, my_ip); ipc = dvdb%my_pinfo(3, my_ip)
3822 : :
3823 : : ! Prepare application of the NL part.
3824 : 8592 : call rf_hamkq%init(cplex, gs_hamkq, ipert, has_e1kbsc=.true.)
3825 : 8592 : call rf_hamkq%load_spin(spin, vlocal1=vlocal1(:,:,:,:,my_ip), with_nonlocal=.true.)
3826 : :
3827 : : #if 1
3828 : : ! Calculate dvscf * psi_k, results stored in h1_kets_kq on the k+q sphere.
3829 : : ! Compute H(1) applied to GS wavefunction Psi(0)
3830 [ + + ]: 17184 : do in_k=1,nb_k
3831 : : ! Use scissor shift on 0-order eigenvalue
3832 : 8592 : band_k = in_k + bstart_k - 1
3833 : 17184 : lambda(in_k) = ebands%eig(band_k, ik_ibz, spin) - dtset%dfpt_sciss
3834 : : end do
3835 : : !call ebands%get_dfpt_eshifted(gqk%bstart_k, nb_k, ik_ibz, spin, dtset%dfpt_sciss, lambda)
3836 : :
3837 : : call getgh1c(berryopt0, kets_k, cwaveprj0, h1_kets_kq, &
3838 : : grad_berry, gs1c_kq, gs_hamkq, gvnlx1, idir, ipert, lambda, mpi_enreg, nb_k, optlocal, &
3839 : 8592 : optnl, opt_gvnlx1, rf_hamkq, sij_opt, tim_getgh1c, usevnl)
3840 : :
3841 : : #else
3842 : : do in_k=1,nb_k
3843 : : ! Use scissor shift on 0-order eigenvalue
3844 : : band_k = in_k + bstart_k - 1
3845 : : eshift = ebands%eig(band_k, ik_ibz, spin) - dtset%dfpt_sciss
3846 : :
3847 : : call getgh1c(berryopt0, kets_k(:,:,in_k), cwaveprj0, h1_kets_kq(:,:,in_k), &
3848 : : grad_berry, gs1c_kq, gs_hamkq, gvnlx1, idir, ipert, [eshift], mpi_enreg, ndat1, optlocal, &
3849 : : optnl, opt_gvnlx1, rf_hamkq, sij_opt, tim_getgh1c, usevnl)
3850 : : end do ! in_k
3851 : : #endif
3852 : :
3853 : 8592 : call rf_hamkq%free()
3854 : :
3855 : : ! Calculate <psi_{k+q,m}|dvscf_q|psi_{k,n}> for this perturbation.
3856 : : ! No need to handle istwf_kq because it's always 1.
3857 [ - + ]: 8592 : if (dtset%gpu_option == ABI_GPU_OPENMP) then
3858 : : call abi_gpu_xgemm_d(2, 'C', 'N', nb_kq, nb_k, npw_kq*nspinor, cone, bras_kq, npw_kq*nspinor, &
3859 : 0 : h1_kets_kq, npw_kq*nspinor, czero, gkq_atm_ipc, nb_kq)
3860 : : #ifdef HAVE_OPENMP_OFFLOAD
3861 : : !$OMP TARGET UPDATE FROM(gkq_atm_ipc)
3862 : : #endif
3863 : :
3864 : : else
3865 : : call ZGEMM('C', 'N', nb_kq, nb_k, npw_kq*nspinor, cone, bras_kq, npw_kq*nspinor, &
3866 : 8592 : h1_kets_kq, npw_kq*nspinor, czero, gkq_atm_ipc, nb_kq)
3867 : : end if
3868 : :
3869 : : ! Transfer data
3870 [ + + + + : 45824 : gkq_atm(:,:,:,ipc) = gkq_atm_ipc
+ + ]
3871 : : end do ! my_ip (loop over my_npert atomic perturbations)
3872 : :
3873 : : ! Collect gkq_atm inside pert_comm so that all procs can operate on the data.
3874 [ - + ]: 2864 : if (pert_comm%nproc > 1) call xmpi_sum(gkq_atm, pert_comm%value, ierr)
3875 : :
3876 [ - + ]: 2864 : ABI_FREE(ffnl_k)
3877 [ - + ]: 2864 : ABI_FREE(ffnl_kq)
3878 [ - + ]: 2864 : ABI_FREE(kpg_kq)
3879 [ - + ]: 2864 : ABI_FREE(kpg_k)
3880 [ - + ]: 2864 : ABI_FREE(kinpw_k)
3881 [ - + ]: 2864 : ABI_FREE(kinpw_kq)
3882 [ - + ]: 2864 : ABI_FREE(ph3d_k)
3883 [ - + ]: 2864 : ABI_FREE(ph3d_kq)
3884 : :
3885 : : #ifdef HAVE_OPENMP_OFFLOAD
3886 : : !$OMP TARGET EXIT DATA MAP(delete:h1_kets_kq, gvnlx1, kets_k, bras_kq) IF (dtset%gpu_option == ABI_GPU_OPENMP)
3887 : : !$OMP TARGET EXIT DATA MAP(delete:gs1c_kq) IF (dtset%gpu_option == ABI_GPU_OPENMP .and. sij_opt /= 0)
3888 : : #endif
3889 [ - + ]: 2864 : ABI_FREE(kets_k)
3890 [ - + ]: 2864 : ABI_FREE(bras_kq)
3891 [ - + ]: 2864 : ABI_FREE(h1_kets_kq)
3892 [ - + ]: 2864 : ABI_FREE(gs1c_kq)
3893 [ - + ]: 2864 : ABI_FREE(gvnlx1)
3894 : :
3895 : : ! Compute group velocities if we are in transport mode or adaptive gaussian or
3896 : : ! tetrahedron with libtetrabz returning nesting condition.
3897 [ - + - - : 2864 : need_velocities = dtset%eph_transport > 0 .or. fs%eph_fsmear < zero .or. nesting /= 0
- - ]
3898 : :
3899 : : if (need_velocities) then
3900 : : ! Compute diagonal matrix elements of velocity operator with DFPT routines
3901 : : ! Velocities are in Cartesian coordinates.
3902 : : !
3903 : : ! If k+q is not in the IBZ, we need to recostruct the value by symmetry using v(Sq) = S v(q).
3904 : : ! Use transpose(R) because we are using the tables for the wavefunctions
3905 : : ! In this case listkk has been called with symrec and use_symrec=False
3906 : : ! so q_bz = S^T q_ibz where S is the isym_kq symmetry
3907 : :
3908 : : !call ddkop%setup_spin_kpoint(dtset, cryst, psps, spin, kk, istwf_k, npw_k, kg_k)
3909 [ + + ]: 5728 : do in_k=1,nb_k
3910 : 2864 : band_k = in_k + bstart_k - 1
3911 [ + + ]: 11456 : vk = vcart_ibz(:, band_k, ik_ibz, spin)
3912 [ + + ]: 2864 : if (.not. isirr_k) then
3913 : 2754 : vk = matmul(transpose(cryst%symrel_cart(:,:,isym_k)), vk)
3914 [ - + - - ]: 2754 : if (trev_k /= 0) vk = -vk
3915 : : end if
3916 : : !vk = ddkop%get_vdiag(ebands%eig(band_k, ik_ibz, spin), &
3917 : : ! istwf_k, npw_k, wfd%nspinor, kets_k(:,:,in_k), cwaveprj0)
3918 [ + + ]: 14320 : fs%vk(:,in_k) = vk
3919 : : end do
3920 : :
3921 : : !call ddkop%setup_spin_kpoint(dtset, cryst, psps, spin, kq, istwf_kq, npw_kq, kg_kq)
3922 [ + + ]: 5728 : do im_kq=1,nb_kq
3923 : 2864 : band_kq = im_kq + bstart_kq - 1
3924 [ + + ]: 11456 : vkq = vcart_ibz(:, band_kq, ikq_ibz, spin)
3925 [ + + ]: 2864 : if (.not. isirr_kq) then
3926 : 2833 : vkq = matmul(transpose(cryst%symrel_cart(:,:,isym_kq)), vkq)
3927 [ - + - - ]: 2833 : if (trev_kq /= 0) vkq = -vkq
3928 : : end if
3929 : : !vkq = ddkop%get_vdiag(ebands%eig(band_kq, ikq_ibz, spin), &
3930 : : ! istwf_kq, npw_kq, wfd%nspinor, bras_kq(:,:,im_kq), cwaveprj0)
3931 [ + + ]: 14320 : fs%vkq(:,im_kq) = vkq
3932 : : end do
3933 : : end if
3934 : :
3935 : : ! Compute weights for double delta integration at the Fermi level.
3936 : : ! Note that we have to call the routine here after the initialization of fs%vk and fs%vkq
3937 : : ! TODO: Could precompute weights before entering the loop, apply filter and compute MPI-distribution
3938 : 2864 : call fs%get_dbldelta_weights(ebands, ik_fs, ik_ibz, ikq_ibz, spin, nesting, dbldelta_wts)
3939 : : ! Multiply by the weight of the q-point if we are summing over the IBZ(q).
3940 : : !dbldelta_wts = dbldelta_wts * wtk_lgq
3941 : :
3942 : : ! Accumulate results in tgam (sum over FS k-points and bands for this spin).
3943 [ + + ]: 11456 : do ipc2=1,natom3
3944 [ + + ]: 37232 : do ipc1=1,natom3
3945 [ + + ]: 60144 : do in_k=1,nb_k
3946 [ + + ]: 77328 : do im_kq=1,nb_kq
3947 [ + + ]: 77328 : lf = gkq_atm(:, im_kq, in_k, ipc1)
3948 [ + + ]: 77328 : rg = gkq_atm(:, im_kq, in_k, ipc2)
3949 : 25776 : res(1) = lf(1) * rg(1) + lf(2) * rg(2)
3950 : 25776 : res(2) = lf(1) * rg(2) - lf(2) * rg(1)
3951 [ + + ]: 103104 : tgam(:,ipc1,ipc2) = tgam(:,ipc1,ipc2) + res(:) * dbldelta_wts(im_kq, in_k)
3952 : : end do
3953 : : end do
3954 : : end do
3955 : : end do
3956 : :
3957 [ + - ]: 2864 : if (dtset%eph_transport > 0) then
3958 : : ! TODO: could almost make this a BLAS call plus a reshape...
3959 [ + + ]: 5728 : do in_k = 1,nb_k
3960 [ + + ]: 8592 : do im_kq = 1,nb_kq
3961 [ + + ]: 14320 : do ipc2 = 1,3
3962 [ + + ]: 37232 : do ipc1 = 1,3
3963 : : ! vk x vk
3964 : 25776 : vv_kk(ipc1 + (ipc2-1)*3, im_kq, in_k) = fs%vk(ipc1, im_kq) * fs%vk(ipc2, in_k)
3965 : : ! vk x vk+q
3966 : 34368 : vv_kkq(ipc1 + (ipc2-1)*3, im_kq, in_k) = fs%vkq(ipc1, im_kq) * fs%vk(ipc2, in_k)
3967 : : end do
3968 : : end do
3969 : : end do
3970 : : end do
3971 : :
3972 : : ! Accumulate results (sum over FS and bands).
3973 [ + + ]: 11456 : do ipc2=1,natom3
3974 [ + + ]: 37232 : do ipc1=1,natom3
3975 [ + + ]: 60144 : do in_k=1,nb_k
3976 [ + + ]: 77328 : do im_kq=1,nb_kq
3977 [ + + ]: 77328 : lf = gkq_atm(:, im_kq, in_k, ipc1)
3978 [ + + ]: 77328 : rg = gkq_atm(:, im_kq, in_k, ipc2)
3979 : : ! res was missing in MJV version!
3980 : 25776 : res(1) = lf(1) * rg(1) + lf(2) * rg(2)
3981 : 25776 : res(2) = lf(1) * rg(2) - lf(2) * rg(1)
3982 [ + + ]: 257760 : resvv_in(1,:) = res(1) * vv_kkq(:,im_kq, in_k)
3983 [ + + ]: 257760 : resvv_in(2,:) = res(2) * vv_kkq(:,im_kq, in_k)
3984 [ + + ]: 257760 : resvv_out(1,:) = res(1) * vv_kk(:,im_kq, in_k)
3985 [ + + ]: 257760 : resvv_out(2,:) = res(2) * vv_kk(:,im_kq, in_k)
3986 [ + + + + ]: 721728 : tgamvv_in(:,:,ipc1, ipc2) = tgamvv_in(:,:,ipc1,ipc2) + resvv_in * dbldelta_wts(im_kq, in_k)
3987 [ + + + + ]: 747504 : tgamvv_out(:,:,ipc1, ipc2) = tgamvv_out(:,:,ipc1,ipc2) + resvv_out * dbldelta_wts(im_kq, in_k)
3988 : : end do
3989 : : end do
3990 : : end do
3991 : : end do
3992 : : end if ! add transport things
3993 : :
3994 [ - + ]: 2864 : if (dtset%prteliash == 3) then
3995 : : ! Precompute deltas with gaussian (tetra is not supported here
3996 : : ! also because one should allocate (nene, nene, mband, mband)
3997 : : !call get_dbldelta_weights_emesh()
3998 [ # # ]: 0 : do in_k=1,nb_k
3999 : 0 : band_k = in_k + bstart_k - 1
4000 : 0 : sigma = fs%eph_fsmear
4001 [ # # ]: 0 : if (fs%eph_fsmear < zero) then
4002 [ # # ]: 0 : do ii=1,3
4003 [ # # ]: 0 : abc(ii) = abs(dot_product(fs%vk(:, in_k), fs%kmesh_cartvec(:,ii)))
4004 : : end do
4005 [ # # # # : 0 : sigma = max(maxval(abc), fs%min_smear)
# # ]
4006 : : end if
4007 [ # # ]: 0 : wt_ek(:, in_k) = gaussian(emesh - ebands%eig(band_k, ik_ibz, spin), sigma) / sqrt(one * fs%nktot)
4008 : : end do
4009 : :
4010 [ # # ]: 0 : do im_kq=1,nb_kq
4011 : 0 : band_kq = im_kq + bstart_kq - 1
4012 : 0 : sigma = fs%eph_fsmear
4013 [ # # ]: 0 : if (fs%eph_fsmear < zero) then
4014 [ # # ]: 0 : do ii=1,3
4015 [ # # ]: 0 : abc(ii) = abs(dot_product(fs%vkq(:, im_kq), fs%kmesh_cartvec(:,ii)))
4016 : : end do
4017 [ # # # # : 0 : sigma = max(maxval(abc), fs%min_smear)
# # ]
4018 : : end if
4019 [ # # ]: 0 : wt_ekq(:, im_kq) = gaussian(emesh - ebands%eig(band_kq, ikq_ibz, spin), sigma) / sqrt(one * fs%nktot)
4020 : : end do
4021 : :
4022 [ # # ]: 0 : do in_k=1,nb_k
4023 [ # # ]: 0 : do im_kq=1,nb_kq
4024 [ # # ]: 0 : do ipc2=1,natom3
4025 [ # # ]: 0 : do ipc1=1,natom3
4026 [ # # ]: 0 : lf = gkq_atm(:, im_kq, in_k, ipc1)
4027 [ # # ]: 0 : rg = gkq_atm(:, im_kq, in_k, ipc2)
4028 : 0 : res(1) = lf(1) * rg(1) + lf(2) * rg(2)
4029 : 0 : res(2) = lf(1) * rg(2) - lf(2) * rg(1)
4030 [ # # ]: 0 : do jene = 1, gams%nene
4031 [ # # ]: 0 : do iene = 1, gams%nene
4032 : : ! TODO: distribute this in procs over q. Make a temp array here for 1 q
4033 : : ! then mpi sync it and save it only on 1 processor below after mpisum over k
4034 : : tmp_vals_ee(:,iene,jene,ipc1,ipc2) = tmp_vals_ee(:,iene,jene,ipc1,ipc2) + &
4035 [ # # ]: 0 : res(:) * wt_ekq(iene, im_kq) * wt_ek(jene, in_k)
4036 : : end do
4037 : : end do
4038 : : end do
4039 : : end do
4040 : : end do
4041 : : end do
4042 : : end if ! prteliash == 3
4043 : :
4044 [ - + ]: 2864 : ABI_FREE(lambda)
4045 [ - + ]: 2864 : ABI_FREE(gkq_atm)
4046 : : #ifdef HAVE_OPENMP_OFFLOAD
4047 : : !$OMP TARGET EXIT DATA MAP(delete:gkq_atm_ipc) IF (dtset%gpu_option == ABI_GPU_OPENMP)
4048 : : #endif
4049 [ - + ]: 2864 : ABI_FREE(gkq_atm_ipc)
4050 : :
4051 [ + + ]: 2925 : if (print_time_k) then
4052 : 66 : write(msg,'(5x,2(a,i0),a)')"k-point [", my_ik, "/", gams%my_nfsk_q, "]"
4053 : 66 : call cwtime_report(msg, cpu_k, wall_k, gflops_k)
4054 : : end if
4055 : : end do ! imyk: sum over k-points on the BZ FS for this spin.
4056 : :
4057 [ - + ]: 61 : ABI_FREE(dbldelta_wts)
4058 [ - + ]: 61 : ABI_SFREE(wt_ek)
4059 [ - + ]: 61 : ABI_SFREE(wt_ekq)
4060 : :
4061 : : ! Collect tgam values inside kpt comm and divide by the total number of k-points in the full mesh.
4062 : 61 : call xmpi_sum(tgam, kpt_comm%value, ierr)
4063 : :
4064 : : ! Symmetrize gamma matrices (default). Note that this call is not executed in elphon!
4065 [ + - ]: 61 : if (gams%symgamma == 1) call tgamma_symm(cryst, gams%qibz(:,iq_ibz), tgam)
4066 : :
4067 : : ! Save results in gams.
4068 [ + + + + : 1891 : gams%vals_qibz(:,:,:,iq_ibz, spin) = tgam
+ + ]
4069 : :
4070 [ + - ]: 61 : if (dtset%eph_transport > 0) then
4071 [ - + ]: 61 : ABI_FREE(vv_kk)
4072 [ - + ]: 61 : ABI_FREE(vv_kkq)
4073 : 61 : call xmpi_sum(tgamvv_in, kpt_comm%value, ierr)
4074 : 61 : call xmpi_sum(tgamvv_out, kpt_comm%value, ierr)
4075 [ + + + + : 15616 : gams%vals_in_qibz(:,:,:,:,iq_ibz,spin) = tgamvv_in
+ + + + ]
4076 [ + + + + : 15616 : gams%vals_out_qibz(:,:,:,:,iq_ibz,spin) = tgamvv_out
+ + + + ]
4077 : : end if
4078 : :
4079 [ - + ]: 183 : if (dtset%prteliash == 3) then
4080 : 0 : call xmpi_sum(tmp_vals_ee, kpt_comm%value, ierr)
4081 : : !TODO: write arrays to ncfile.
4082 [ # # # # : 0 : gams%vals_ee(:,:,:,:,:, iq_ibz, spin) = tmp_vals_ee
# # # # #
# ]
4083 [ # # ]: 0 : ABI_FREE(tmp_vals_ee)
4084 [ # # ]: 0 : ABI_FREE(emesh)
4085 : : end if
4086 : : end do ! spin
4087 : :
4088 [ - + ]: 61 : ABI_FREE(v1scf)
4089 [ - + ]: 61 : ABI_FREE(vlocal1)
4090 : :
4091 : 61 : write(msg,'(2(a,i0),a)')" Computation of q-point [", iq_ibz, "/", gams%nqibz, "]"
4092 : 127 : call cwtime_report(msg, cpu_q, wall_q, gflops_q, end_str=ch10)
4093 : : end do ! iq_ibz
4094 : :
4095 : 5 : call cwtime_report(" phonon linewidths q-loop", cpu_all, wall_all, gflops_all, end_str=ch10)
4096 : :
4097 : : ! Free memory
4098 [ - + ]: 5 : ABI_FREE(grad_berry)
4099 [ - + ]: 5 : ABI_FREE(dummy_vtrial)
4100 [ - + ]: 5 : ABI_FREE(work)
4101 [ - + ]: 5 : ABI_FREE(ph1d)
4102 [ - + ]: 5 : ABI_FREE(vlocal)
4103 [ - + ]: 5 : ABI_FREE(kg_k)
4104 [ - + ]: 5 : ABI_FREE(kg_kq)
4105 [ - + ]: 5 : ABI_FREE(tgam)
4106 [ - + ]: 5 : ABI_FREE(displ_cart)
4107 [ - + ]: 5 : ABI_FREE(displ_red)
4108 : : !ABI_FREE(qibz_done)
4109 [ + - ]: 5 : ABI_SFREE(vcart_ibz)
4110 : 5 : call krank%free()
4111 : :
4112 [ + - ]: 5 : ABI_SFREE(tgamvv_in)
4113 [ + - ]: 5 : ABI_SFREE(tgamvv_out)
4114 : 5 : call ddkop%free(); call gs_hamkq%free(); call wfd%free()
4115 [ + + ]: 10 : do spin=1,ebands%nsppol
4116 : 10 : call fstab(spin)%free()
4117 : : end do
4118 [ + - + + : 10 : ABI_FREE(fstab)
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + ]
4119 : 5 : call pawcprj_free(cwaveprj0)
4120 [ + - - + : 5 : ABI_FREE(cwaveprj0)
- - - - -
+ ]
4121 : :
4122 : : ! Collect results on each node
4123 : 5 : call cwtime(cpu_all, wall_all, gflops_all, "start")
4124 : 5 : call xmpi_sum(gams%vals_qibz, qs_comm%value, ierr)
4125 [ + - ]: 5 : if (dtset%eph_transport > 0) then
4126 : 5 : call xmpi_sum(gams%vals_in_qibz, qs_comm%value, ierr)
4127 : 5 : call xmpi_sum(gams%vals_out_qibz, qs_comm%value, ierr)
4128 : : end if
4129 [ - + ]: 5 : if (dtset%prteliash == 3) call xmpi_sum(gams%vals_ee, qs_comm%value, ierr)
4130 : 5 : call cwtime_report(" xmpi_sum", cpu_all, wall_all, gflops_all)
4131 : :
4132 : : ! Deallocate MPI communicators.
4133 : 5 : call pert_comm%free(); call qpt_comm%free(); call bsum_comm%free(); call qs_comm%free()
4134 : 5 : call kpt_comm%free(); call spin_comm%free(); call pkb_comm%free()
4135 : : !call ncwrite_comm%free()
4136 : :
4137 : : ! Print gamma(IBZ) to ab_out and ncid.
4138 [ + - ]: 5 : if (my_rank == master) call phgamma_ncwrite(gams, cryst, ifc, ncid)
4139 : :
4140 : : ! Interpolate linewidths along the q-path.
4141 [ - + ]: 5 : if (dtset%ph_nqpath <= 0) then
4142 : : write(msg, '(7a,es16.6,4a)' ) &
4143 : 0 : 'You have not specified a path for the linewidth calculation - no interpolation or output will be done ',ch10,&
4144 : 0 : 'Action: check your input variables ph_nqpath and ph_qpath'
4145 : 0 : ABI_WARNING(msg)
4146 : : else
4147 : 5 : call gams%linwid(cryst, ifc, dtset%ph_ndivsm, dtset%ph_nqpath, dtset%ph_qpath, dtfil%filnam_ds(4), ncid, wminmax, comm)
4148 : : end if
4149 : :
4150 : : ! Compute a2Fw using the ab-initio q-points (no interpolation here)
4151 : : call a2fw%init(gams, cryst, ifc, dtset%ph_intmeth, dtset%ph_wstep, wminmax, dtset%ph_smear, &
4152 : 5 : dtset%ph_ngqpt, dtset%ph_nqshift, dtset%ph_qshift, comm, qintp=.False., qptopt=1)
4153 : :
4154 [ + - ]: 5 : if (my_rank == master) then
4155 : 5 : call a2fw%write(strcat(dtfil%filnam_ds(4), "_NOINTP"), "_qcoarse", ncid)
4156 [ - + ]: 5 : if (dtset%prteliash == 3) call a2fw_ee_write(a2fw, strcat(dtfil%filnam_ds(4), "_NOINTP"))
4157 : : end if
4158 : 5 : call a2fw%free()
4159 : :
4160 : : ! Compute a2Fw using Fourier interpolation (R -> q) and ph_ngqpt grid.
4161 : : call a2fw%init(gams, cryst, ifc, dtset%ph_intmeth, dtset%ph_wstep, wminmax, dtset%ph_smear, &
4162 : 5 : dtset%ph_ngqpt, dtset%ph_nqshift, dtset%ph_qshift, comm, qptopt=1)
4163 : :
4164 [ + - ]: 5 : if (my_rank == master) then
4165 : 5 : call a2fw%write(dtfil%filnam_ds(4), "_qintp", ncid)
4166 [ - + ]: 5 : if (dtset%prteliash == 3) call a2fw_ee_write(a2fw, dtfil%filnam_ds(4))
4167 : : end if
4168 : :
4169 : 5 : call a2fw%free()
4170 : :
4171 : : ! Compute A2fw using Fourier interpolation and full BZ for debugging purposes.
4172 : : !call a2fw%init(gams, cryst, ifc, dtset%ph_intmeth, dtset%ph_wstep, wminmax, dtset%ph_smear,&
4173 : : ! dtset%ph_ngqpt, dtset%ph_nqshift, dtset%ph_qshift, comm, qptopt=3)
4174 : : !if (my_rank == master) call a2fw%write(strcat(dtfil%filnam_ds(4), "_A2FW_QPTOPT3"), "fake", nctk_noid)
4175 : : !call a2fw%free()
4176 : :
4177 [ + - ]: 5 : if (dtset%eph_transport == 1) then
4178 : : ! Calculate and output transport quantities
4179 : :
4180 : : ! Compute a2Fw_tr using ab-initio q-points (no interpolation)
4181 : : call a2fw_tr%init(gams, cryst, ifc, dtset%ph_intmeth, dtset%ph_wstep, wminmax, dtset%ph_smear,&
4182 : 5 : dtset%ph_ngqpt, dtset%ph_nqshift, dtset%ph_qshift, comm, qintp=.False., qptopt=1)
4183 : :
4184 [ + - ]: 5 : if (my_rank == master) call a2fw_tr%write(strcat(dtfil%filnam_ds(4), "_NOINTP"), "_qcoarse", ncid)
4185 : 5 : call a2fw_tr%free()
4186 : :
4187 : : ! Compute a2Fw_tr using Fourier interpolation (R --> q) and ph_ngqpt grid
4188 : : call a2fw_tr%init(gams, cryst, ifc, dtset%ph_intmeth, dtset%ph_wstep, wminmax, dtset%ph_smear,&
4189 : 5 : dtset%ph_ngqpt, dtset%ph_nqshift, dtset%ph_qshift, comm, qptopt=1)
4190 : :
4191 [ + - ]: 5 : if (my_rank == master) call a2fw_tr%write(dtfil%filnam_ds(4), "_qintp", ncid)
4192 : 5 : call a2fw_tr%free()
4193 : :
4194 : : ! Compute A2fw_tr using Fourier interpolation and full BZ for debugging purposes.
4195 : : !call a2fw_tr%init(gams, cryst, ifc, dtset%ph_intmeth, dtset%ph_wstep, wminmax, dtset%ph_smear,&
4196 : : ! dtset%ph_ngqpt, dtset%ph_nqshift, dtset%ph_qshift, comm, qptopt=3)
4197 : : !if (my_rank == master) call a2fw_tr%write(strcat(dtfil%filnam_ds(4), "_A2FWTR_QPTOPT3"), "fake", nctk_noid)
4198 : : !call a2fw_tr%free()
4199 : : end if
4200 : :
4201 [ + - ]: 5 : if (my_rank == master) then
4202 [ - + ]: 5 : NCF_CHECK(nf90_close(ncid))
4203 : : end if
4204 : :
4205 : 5 : call gams%free()
4206 : :
4207 [ - + - + : 115 : end subroutine eph_phgamma
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - -
- - - - -
- - - - -
- - - + -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
- - - - +
- - - - -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + + + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + + + -
+ - + + +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - - -
- - - - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + ]
4208 : : !!***
4209 : :
4210 : : !----------------------------------------------------------------------
4211 : :
4212 : : !!****f* m_phgamma/phgamma_setup_qpoint
4213 : : !! NAME
4214 : : !! phgamma_setup_qpoint
4215 : : !!
4216 : : !! FUNCTION
4217 : : !!
4218 : : !! SOURCE
4219 : :
4220 : 61 : subroutine phgamma_setup_qpoint(gams, fs, cryst, ebands, spin, ltetra, qpt, nesting, comm)
4221 : :
4222 : : !Arguments ------------------------------------
4223 : : class(phgamma_t),intent(inout) :: gams
4224 : : type(fstab_t),intent(inout) :: fs
4225 : : type(crystal_t),intent(in) :: cryst
4226 : : type(ebands_t),intent(in) :: ebands
4227 : : integer,intent(in) :: spin, ltetra, comm
4228 : : integer,intent(out) :: nesting
4229 : : !arrays
4230 : : real(dp),intent(in) :: qpt(3)
4231 : :
4232 : : !Local variables-------------------------------
4233 : : !scalars
4234 : : integer,parameter :: enough = 5
4235 : : integer :: nkbz, ierr, nb, ik_bz, ik_ibz, ikq_ibz, ikq_fs, ik_fs, i1, i2, i3, nkfs_q, nene, ib1, ib2 ! band_k, band_kq
4236 : : real(dp),parameter :: max_occ1 = one
4237 : : real(dp) :: cpu, wall, gflops, enemin, enemax
4238 : : character(len=500) :: msg
4239 : 61 : type(krank_t) :: ibz_krank
4240 : 61 : type(t_tetrahedron) :: tetra
4241 : : character(len=80) :: errorstring
4242 : : !arrays
4243 : : integer :: nge(3), ngw(3), g0bz_kq(3)
4244 : 61 : integer,allocatable :: select_ikfs(:), indkpt(:), kbz2fs(:) !, symrecfm(:,:,:)
4245 : : real(dp) :: kk(3), kq(3)
4246 : 61 : real(dp),allocatable :: eig_k(:,:), eig_kq(:,:), wght_bz(:,:,:), kbz(:,:)
4247 : 61 : real(dp),allocatable :: work_k(:), work_kq(:), dtweightde(:,:,:), tweight(:,:,:)
4248 : : ! *************************************************************************
4249 : :
4250 : 61 : call cwtime(cpu, wall, gflops, "start")
4251 : :
4252 : : ! The double delta with tetra is ill-defined for q == 0. Set nesting to 1 and return
4253 : 61 : nesting = 0
4254 [ + + + + : 76 : if (abs(fs%eph_intmeth) == 2 .and. all(abs(qpt) < tol12)) then
+ + + + ]
4255 : 2 : ABI_COMMENT("Tetrahedron for double grid with q = 0 is ill-defined. Using adaptive gaussian.")
4256 : 2 : nesting = 1
4257 : : end if
4258 : :
4259 [ + + + + ]: 61 : if (fs%eph_intmeth == 1 .or. nesting == 1) then
4260 : : ! Gaussian method:
4261 : : ! Distribute k-points within the FS window inside comm.
4262 : : ! 1) Select k-points such that k+q is still inside the FS window
4263 : : ! 2) Distribute effective k-points assuming all procs in comm have all FS k-points (no filtering).
4264 [ - + + - : 78 : ABI_MALLOC(select_ikfs, (fs%nkfs))
+ - + - -
+ - + ]
4265 : 26 : nkfs_q = 0
4266 [ + + ]: 3614 : do ik_fs=1,fs%nkfs
4267 [ + + ]: 14352 : kq = fs%kpts(:, ik_fs) + qpt
4268 [ + + ]: 3588 : ikq_fs = fs%findkg0(kq, g0bz_kq); if (ikq_fs == -1) cycle
4269 : 1536 : nkfs_q = nkfs_q + 1
4270 : 3614 : select_ikfs(nkfs_q) = ik_fs
4271 : : end do
4272 [ + + ]: 26 : ABI_SFREE(gams%my_ifsk_q)
4273 [ - + ]: 26 : call xmpi_split_list(nkfs_q, select_ikfs, comm, gams%my_nfsk_q, gams%my_ifsk_q)
4274 [ - + ]: 26 : ABI_FREE(select_ikfs)
4275 : 26 : call cwtime_report(" phgamma_setup_qpoint", cpu, wall, gflops)
4276 : 26 : return
4277 : : end if
4278 : :
4279 : : ! Tetrahedron method:
4280 : : ! 1) Compute weights for double delta integration.
4281 : : ! 2) Filter k-points according to the weights (k must be in FS window with non-zero weight)
4282 : : ! 3) Distribute effective k-points assuming all procs have all FS k-points.
4283 : :
4284 [ + + + + : 33845 : fs%dbldelta_tetra_weights_kfs = zero
+ + ]
4285 : :
4286 [ - + ]: 35 : ABI_CHECK(isdiagmat(ebands%kptrlatt), "kptrlatt must be diagonal when tetra is used.")
4287 [ - + ]: 35 : ABI_CHECK(ebands%nshiftk == 1, "nshiftk must be 1 when tetra is used")
4288 : 35 : nge = get_diag(ebands%kptrlatt); ngw = nge
4289 [ + + ]: 140 : nkbz = product(nge(1:3))
4290 : :
4291 : : ! TODO: Handle symmetries in a cleaner way. Change API of krank_new to pass symafm and kptopt
4292 : : call ibz_krank%init(ebands%nkpt, ebands%kptns, nsym=cryst%nsym, symrec=cryst%symrec, &
4293 : 35 : time_reversal=kpts_timrev_from_kptopt(ebands%kptopt) == 1)
4294 : :
4295 : : ! Compute eig_k and eig_kq in full BZ for the relevant bands around Ef.
4296 : 35 : nb = fs%maxnb
4297 [ - + + - : 105 : ABI_MALLOC(kbz, (3, nkbz))
+ - + - -
+ - + ]
4298 [ - + + - : 105 : ABI_MALLOC(indkpt, (nkbz))
+ - + - -
+ - + ]
4299 [ - + + - : 140 : ABI_MALLOC(eig_k, (nb, nkbz))
- + + - +
- + - - +
- + ]
4300 [ - + + - : 105 : ABI_MALLOC(eig_kq, (nb, nkbz))
- + + - -
+ - + ]
4301 [ - + + - : 70 : ABI_MALLOC(kbz2fs, (nkbz))
- + - + ]
4302 : :
4303 [ + + ]: 17955 : kbz2fs = -1; ierr = 0; ik_bz = 0
4304 [ + + ]: 315 : do i3=0,nge(3) - 1
4305 [ + + ]: 2555 : do i2=0,nge(2) - 1
4306 [ + + ]: 20440 : do i1=0,nge(1) - 1
4307 : 17920 : ik_bz = ik_bz + 1
4308 : 17920 : indkpt(ik_bz) = ik_bz
4309 : :
4310 : : ! Find correspondence between libtetra mesh and the IBZ.
4311 [ + + ]: 71680 : kk = ([i1, i2, i3] + ebands%shiftk(:, 1)) / nge(:)
4312 [ + + ]: 71680 : kbz(:, ik_bz) = kk
4313 : :
4314 : 17920 : ik_fs = fs%krank%get_index(kk)
4315 [ + + ]: 17920 : if (ik_fs /= -1) then
4316 : 4830 : kbz2fs(ik_bz) = ik_fs
4317 : : else
4318 : : !ABI_ERROR(sjoin('kpt:', trim(ktoa(kk)), 'is not in FS!!'))
4319 : : end if
4320 : :
4321 : 17920 : ik_ibz = ibz_krank%get_index(kk)
4322 [ - + ]: 17920 : if (ik_ibz < 1) then
4323 [ # # ]: 0 : if (ierr <= enough) then
4324 [ # # ]: 0 : ABI_WARNING(sjoin('kpt:', trim(ktoa(kk)), 'has no symmetric among the k-points!'))
4325 : : end if
4326 : 0 : ierr = ierr + 1; cycle
4327 : : end if
4328 : :
4329 [ + + ]: 53760 : eig_k(:, ik_bz) = ebands%eig(fs%bmin:fs%bmax, ik_ibz, spin)
4330 : :
4331 : : ! Find correspondence between k+q in the BZ and the IBZ image.
4332 [ + + ]: 71680 : kq = kk + qpt
4333 : 17920 : ikq_ibz = ibz_krank%get_index(kq)
4334 : :
4335 [ - + ]: 17920 : if (ikq_ibz < 1) then
4336 [ # # ]: 0 : if (ierr <= enough) then
4337 [ # # ]: 0 : ABI_WARNING(sjoin('kpt + qpt:', trim(ktoa(kq)), 'has no symmetric among the k-points!'))
4338 : : end if
4339 : 0 : ierr = ierr + 1; cycle
4340 : : end if
4341 : :
4342 [ + + ]: 56000 : eig_kq(:, ik_bz) = ebands%eig(fs%bmin:fs%bmax, ikq_ibz, spin)
4343 : : end do
4344 : : end do
4345 : : end do
4346 : :
4347 [ - + ]: 35 : ABI_CHECK(ierr == 0, "See above warnings")
4348 : 35 : call ibz_krank%free()
4349 : :
4350 : 70 : select case (ltetra)
4351 : : case (1, 2)
4352 : : ! Use libtetra routines.
4353 : : ! Compute weights for double delta integration. Note that libtetra assumes Ef set to zero.
4354 : : ! TODO: Average weights over degenerate states?
4355 [ - + ]: 35 : if (ltetra == 1) call wrtout(std_out, " Using linear tetrahedron method from libtetrabz (ltetra: 1)")
4356 [ + - ]: 35 : if (ltetra == 2) call wrtout(std_out, " Using optimized tetrahedron method from libtetrabz (ltetra: 2)")
4357 [ + + + + : 107555 : eig_k = eig_k - ebands%fermie; eig_kq = eig_kq - ebands%fermie
+ + + + ]
4358 [ - + + - : 175 : ABI_MALLOC(wght_bz, (nb, nb, nkbz))
- + + - -
+ + - + -
+ - - + -
+ ]
4359 : 35 : call libtetrabz_dbldelta(ltetra, cryst%gprimd, nb, nge, eig_k, eig_kq, ngw, wght_bz, comm=comm)
4360 : : ! Revert changes to eig arrays
4361 [ + + + + ]: 53795 : eig_k = eig_k + ebands%fermie !; eig_kq = eig_kq + ebands%fermie
4362 : :
4363 : : ! Reindex from full BZ to fs% kpoints.
4364 [ + + ]: 17955 : do ik_bz=1,nkbz
4365 : 17920 : ik_fs = kbz2fs(ik_bz)
4366 [ + + ]: 17955 : if (ik_fs /= -1) then
4367 [ + + + + ]: 33810 : fs%dbldelta_tetra_weights_kfs(:,:,ik_fs) = wght_bz(:,:,ik_bz)
4368 : : else
4369 : : !write(std_out,*)"should be zero :", wght_bz(:,:,ik_bz)
4370 : : end if
4371 : : end do
4372 [ - + ]: 35 : ABI_FREE(wght_bz)
4373 : :
4374 : : case (3)
4375 : : ! Tetrahedron method with Allen's approach for double delta.
4376 : : ! WARNING: wrong results maybe bug somewhere.
4377 : 0 : call wrtout(std_out, " Calling Allen's version for q-point")
4378 : 0 : nene = 3
4379 : 0 : enemin = ebands%fermie - tol6
4380 : 0 : enemax = ebands%fermie + tol6
4381 : :
4382 [ # # # # : 0 : ABI_MALLOC(dtweightde, (nkbz, nene, nene))
# # # # #
# # # # #
# # ]
4383 [ # # # # : 0 : ABI_MALLOC(tweight, (nkbz, nene, nene))
# # # # #
# # # ]
4384 [ # # # # : 0 : ABI_MALLOC(work_k, (nkbz))
# # # # #
# # # ]
4385 [ # # # # : 0 : ABI_MALLOC(work_kq, (nkbz))
# # # # ]
4386 : :
4387 : 0 : call init_tetra(indkpt, cryst%gprimd, fs%klatt, kbz, nkbz, tetra, ierr, errorstring, comm)
4388 [ # # ]: 0 : ABI_CHECK(ierr == 0, "init_tetra returned ierr /= 0")
4389 : :
4390 [ # # # # : 0 : fs%dbldelta_tetra_weights_kfs = zero
# # ]
4391 [ # # ]: 0 : do ib2=1,nb
4392 [ # # # # ]: 0 : work_k = eig_k(ib2, :)
4393 [ # # ]: 0 : do ib1=1,nb
4394 [ # # # # ]: 0 : work_kq = eig_kq(ib1, :)
4395 : : ! TODO: Average weights over degenerate states?
4396 : : call get_dbl_tetra_weight(work_k, work_kq, enemin, enemax, enemin, enemax, &
4397 : 0 : max_occ1, nene, nene, nkbz, tetra, tweight, dtweightde, ierr)
4398 [ # # ]: 0 : ABI_CHECK(ierr == 0, "get_dbldelta_weights returned ierr /= 0")
4399 : :
4400 : : ! Reindex from full BZ to fs% kpoints.
4401 [ # # ]: 0 : do ik_bz=1,nkbz
4402 : 0 : ik_fs = kbz2fs(ik_bz)
4403 [ # # ]: 0 : if (ik_fs /= -1) then
4404 : 0 : fs%dbldelta_tetra_weights_kfs(ib1,ib2,ik_fs) = dtweightde(ik_bz, 2, 2) ! / nkbz
4405 : : else
4406 : : !write(std_out,*)"should be zero :", wght_bz(:,:,ik_bz)
4407 : : end if
4408 : : end do
4409 : : end do
4410 : : end do
4411 : :
4412 : 0 : call destroy_tetra(tetra)
4413 [ # # ]: 0 : ABI_FREE(work_k)
4414 [ # # ]: 0 : ABI_FREE(work_kq)
4415 [ # # ]: 0 : ABI_FREE(dtweightde)
4416 [ # # ]: 0 : ABI_FREE(tweight)
4417 : :
4418 : : case default
4419 [ + - - ]: 35 : ABI_ERROR(sjoin("Invalid value of ltetra:", itoa(ltetra)))
4420 : : end select
4421 : :
4422 : : ! Now we can filter the k-points according to the tetra weights and distribute them inside comm.
4423 : : ! Assuming all procs in comm have all k-points in the IBZ.
4424 : : ! nkfs_q is the total number of BZ k-points on the FS contributing for this q-point.
4425 [ - + + - : 105 : ABI_MALLOC(select_ikfs, (fs%nkfs))
+ - + - -
+ - + ]
4426 : 35 : nkfs_q = 0
4427 [ + + ]: 4865 : do ik_fs=1,fs%nkfs
4428 [ + + + + : 6079 : if (any(abs(fs%dbldelta_tetra_weights_kfs(:,:,ik_fs)) > zero)) then
+ + + + ]
4429 : 4668 : nkfs_q = nkfs_q + 1; select_ikfs(nkfs_q) = ik_fs
4430 : : end if
4431 : : end do
4432 : :
4433 : : ! Here we compute my_ifsk_q.
4434 [ + - ]: 35 : ABI_SFREE(gams%my_ifsk_q)
4435 [ - + ]: 35 : call xmpi_split_list(nkfs_q, select_ikfs, comm, gams%my_nfsk_q, gams%my_ifsk_q)
4436 [ - + ]: 35 : ABI_FREE(select_ikfs)
4437 : :
4438 : : !write(std_out,"(2(a,i0),/)")" Treating ", gams%my_nfsk_q, " my k-points in the FS window over total nkfs: ", fs%nkfs
4439 : :
4440 : : write(msg, "(2(a,i0),a)") &
4441 : 35 : " Number of k-points in the FS window treated by me: ", gams%my_nfsk_q, " over: ", nkfs_q, ch10
4442 : : !" Number of MPI procs in kpt_comm: ", gams%kpt_comm%nproc
4443 : 35 : call wrtout(std_out, msg)
4444 : :
4445 [ - + ]: 35 : ABI_FREE(kbz2fs)
4446 [ - + ]: 35 : ABI_FREE(indkpt)
4447 [ - + ]: 35 : ABI_FREE(kbz)
4448 [ - + ]: 35 : ABI_FREE(eig_k)
4449 [ - + ]: 35 : ABI_FREE(eig_kq)
4450 : :
4451 : 35 : call cwtime_report(sjoin(" phgamma_setup_qpoint for spin:", itoa(spin)), cpu, wall, gflops)
4452 : :
4453 [ - + - + : 122 : end subroutine phgamma_setup_qpoint
- + - + -
+ - + - +
- + ]
4454 : : !!***
4455 : :
4456 : : !----------------------------------------------------------------------
4457 : :
4458 : : !!****f* m_phgamma/find_ewin
4459 : : !! NAME
4460 : : !! find_ewin
4461 : : !!
4462 : : !! FUNCTION
4463 : : !! Use bisection to find the optimal energy window around the Fermi level
4464 : : !!
4465 : : !! SOURCE
4466 : :
4467 : 0 : subroutine find_ewin(nqibz, qibz, cryst, ebands, ltetra, fs_ewin, comm)
4468 : :
4469 : : !Arguments ------------------------------------
4470 : : integer,intent(in) :: nqibz
4471 : : type(crystal_t),intent(in) :: cryst
4472 : : type(ebands_t),intent(in) :: ebands
4473 : : integer,intent(in) :: ltetra, comm
4474 : : real(dp),intent(out) :: fs_ewin
4475 : : !arrays
4476 : : real(dp),intent(in) :: qibz(3, nqibz)
4477 : :
4478 : : !Local variables-------------------------------
4479 : : !scalars
4480 : : integer,parameter :: master = 0
4481 : : integer :: my_rank, iq_ibz, spin, ii, unt
4482 : : real(dp) :: cpu, wall, gflops
4483 : : character(len=500) :: msg
4484 : : !arrays
4485 : : integer :: bstarts(3), bstops(3)
4486 : : real(dp) :: elows(3), ehighs(3), ewins(3), qsums(3)
4487 : 0 : real(dp), allocatable :: wtqs(:,:,:)
4488 : : ! *************************************************************************
4489 : :
4490 : 0 : call cwtime(cpu, wall, gflops, "start")
4491 : 0 : my_rank = xmpi_comm_rank(comm)
4492 : :
4493 : 0 : unt = -1
4494 [ # # ]: 0 : if (xmpi_comm_rank(comm) == master) then
4495 [ # # ]: 0 : if (open_file("tetra.dat", msg, newunit=unt, action="write", form="formatted", status="unknown") /= 0) then
4496 : 0 : ABI_ERROR(msg)
4497 : : end if
4498 : : end if
4499 : :
4500 : : ! 1 is low, 2 is high, 3 is for the workspace
4501 [ # # # # : 0 : ABI_MALLOC(wtqs, (nqibz, ebands%nsppol, 3))
# # # # #
# # # # #
# # # # ]
4502 : 0 : ewins(1) = half * eV_Ha; elows(1) = ebands%fermie - ewins(1); ehighs(1) = ebands%fermie + ewins(1)
4503 : 0 : call ebands%get_bands_from_erange(elows(1), ehighs(1), bstarts(1), bstops(1))
4504 : 0 : call calc_dbldelta(cryst, ebands, ltetra, bstarts(1), bstops(1), nqibz, qibz, wtqs(:,:,1), comm)
4505 [ # # ]: 0 : if (unt /= -1) write(unt, *) wtqs(:,:,1)
4506 : :
4507 : : !ewins(2) = five * eV_Ha; elows(2) = ebands%fermie - ewins(2); ehighs(2) = ebands%fermie + ewins(2)
4508 : : ewins(2) = two * eV_Ha; elows(2) = ebands%fermie - ewins(2); ehighs(2) = ebands%fermie + ewins(2)
4509 : 0 : ewins(2) = one * eV_Ha; elows(2) = ebands%fermie - ewins(2); ehighs(2) = ebands%fermie + ewins(2)
4510 : 0 : call ebands%get_bands_from_erange(elows(2), ehighs(2), bstarts(2), bstops(2))
4511 : 0 : call calc_dbldelta(cryst, ebands, ltetra, bstarts(2), bstops(2), nqibz, qibz, wtqs(:,:,2), comm)
4512 [ # # ]: 0 : if (unt /= -1) write(unt, *) wtqs(:,:,2)
4513 : :
4514 [ # # # # : 0 : if (abs(sum(abs(wtqs(:,:,1)) - sum(abs(wtqs(:,:,2))))) / sum(abs(wtqs(:,:,2))) < tol2) then
# # # # #
# # # #
# ]
4515 : 0 : fs_ewin = ewins(1)
4516 : 0 : call print_weights_index(1); goto 100
4517 : : end if
4518 : :
4519 : : ! Bisection part.
4520 : 0 : do
4521 : 0 : ewins(3) = (ewins(1) + ewins(2)) / two; elows(3) = ebands%fermie - ewins(3); ehighs(3) = ebands%fermie + ewins(3)
4522 : 0 : call ebands%get_bands_from_erange(elows(3), ehighs(3), bstarts(3), bstops(3))
4523 : 0 : call calc_dbldelta(cryst, ebands, ltetra, bstarts(3), bstops(3), nqibz, qibz, wtqs(:,:,3), comm)
4524 [ # # ]: 0 : if (unt /= -1) write(unt, *) wtqs(:,:,3)
4525 : :
4526 [ # # ]: 0 : do ii=1,3
4527 [ # # # # ]: 0 : qsums(ii) = sum(abs(wtqs(:,:,ii))) / nqibz
4528 : : end do
4529 : :
4530 : 0 : write(std_out,*)qsums(1), ", for ewins(1)_eV", ewins(1) * Ha_eV, " bstart(1)", bstarts(1), " bstopt(1)", bstops(1)
4531 : 0 : write(std_out,*)qsums(2), ", for ewins(2)_eV", ewins(2) * Ha_eV, " bstart(1)", bstarts(2), " bstopt(1)", bstops(2)
4532 : 0 : write(std_out,*)qsums(3), ", for ewins(3)_eV", ewins(3) * Ha_eV, " bstart(1)", bstarts(3), " bstopt(1)", bstops(3)
4533 : :
4534 : : !if (abs(sum(abs(wtqs(:,:,3)) - sum(abs(wtqs(:,:,2))))) / sum(abs(wtqs(:,:,2))) < tol3) then
4535 : : ! ! If 3 is close to 2, try to reduce the window by moving towards 1
4536 : : ! ewins(2) = ewins(3); elows(2) = elows(3); ehighs(2) = ehighs(3)
4537 : :
4538 [ # # ]: 0 : if (abs(qsums(3) - qsums(2)) / qsums(2) < tol2) then
4539 : 0 : fs_ewin = ewins(3)
4540 : 0 : call print_weights_index(3)
4541 : 0 : exit
4542 : :
4543 : : else
4544 : 0 : ewins(1) = ewins(3); elows(1) = elows(3); ehighs(1) = ehighs(3)
4545 : : end if
4546 : :
4547 : : end do
4548 : :
4549 : : 100 continue
4550 [ # # ]: 0 : ABI_FREE(wtqs)
4551 [ # # ]: 0 : if (unt /= -1) close(unt)
4552 : :
4553 : 0 : call cwtime_report(" find_ewin", cpu, wall, gflops)
4554 : :
4555 : : contains
4556 : :
4557 : 0 : subroutine print_weights_index(ind)
4558 : :
4559 : : integer,intent(in) :: ind
4560 : :
4561 [ # # ]: 0 : if (my_rank == master) then
4562 : 0 : write(std_out, "(a, f8.3, a)")" Optimal FS energy window: ", fs_ewin * Ha_eV, " (eV)"
4563 [ # # ]: 0 : do iq_ibz=1,nqibz
4564 [ # # ]: 0 : write(std_out, "(2a)")" For q-point:", trim(ktoa(qibz(:, iq_ibz)))
4565 [ # # ]: 0 : do spin=1,ebands%nsppol
4566 : 0 : write(std_out, *) wtqs(iq_ibz, spin, ind)
4567 : : end do
4568 : : end do
4569 : : end if
4570 : :
4571 : 0 : end subroutine print_weights_index
4572 : :
4573 : : end subroutine find_ewin
4574 : : !!***
4575 : :
4576 : : !----------------------------------------------------------------------
4577 : :
4578 : : !!****f* m_phgamma/calc_dbldelta
4579 : : !! NAME
4580 : : !! calc_dbldelta
4581 : : !!
4582 : : !! FUNCTION
4583 : : !! Compute Tetrahedron weights for the double delta.
4584 : : !!
4585 : : !! SOURCE
4586 : :
4587 : 0 : subroutine calc_dbldelta(cryst, ebands, ltetra, bstart, bstop, nqibz, qibz, wtqs, comm)
4588 : :
4589 : : !Arguments ------------------------------------
4590 : : type(crystal_t),intent(in) :: cryst
4591 : : type(ebands_t),intent(in) :: ebands
4592 : : integer,intent(in) :: ltetra, bstart, bstop, nqibz, comm
4593 : : !arrays
4594 : : real(dp),intent(in) :: qibz(3,nqibz)
4595 : : real(dp),intent(out) :: wtqs(nqibz, ebands%nsppol)
4596 : :
4597 : : !Local variables-------------------------------
4598 : : !scalars
4599 : : integer,parameter :: enough = 50
4600 : : integer :: nkbz, ierr, nb, ik_bz, ik_ibz, ikq_ibz, i1, i2, i3, nene, spin, iq_ibz
4601 : : integer :: ib1, ib2, my_rank, nproc, cnt
4602 : : real(dp),parameter :: max_occ1 = one
4603 : : real(dp) :: enemin, enemax !cpu, wall, gflops,
4604 : : !character(len=500) :: msg
4605 : 0 : type(krank_t) :: ibz_krank
4606 : 0 : type(t_tetrahedron) :: tetra
4607 : : !character(len=80) :: errorstring
4608 : : !arrays
4609 : : integer :: nge(3), ngw(3)
4610 : 0 : integer,allocatable :: indkpt(:) !, symrecfm(:,:,:)
4611 : : real(dp) :: qpt(3), kk(3), kq(3)
4612 : 0 : real(dp),allocatable :: eig_k(:,:), eig_kq(:,:), wght_bz(:,:,:), kbz(:,:)
4613 : 0 : real(dp),allocatable :: work_k(:), work_kq(:), dtweightde(:,:,:), tweight(:,:,:)
4614 : : ! *************************************************************************
4615 : :
4616 : 0 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
4617 : : !call cwtime(cpu, wall, gflops, "start")
4618 : :
4619 [ # # ]: 0 : ABI_CHECK(nqibz > 1, "Need more that 1 q-point")
4620 [ # # ]: 0 : ABI_CHECK(isdiagmat(ebands%kptrlatt), "kptrlatt must be diagonal when tetra is used.")
4621 [ # # ]: 0 : ABI_CHECK(ebands%nshiftk == 1, "nshiftk must be 1 when tetra is used")
4622 : 0 : nge = get_diag(ebands%kptrlatt); ngw = nge
4623 [ # # ]: 0 : nkbz = product(nge(1:3))
4624 : :
4625 : : ! TODO: Handle symmetries in a cleaner way. Change API of krank_new to pass symafm and kptopt
4626 : : call ibz_krank%init(ebands%nkpt, ebands%kptns, nsym=cryst%nsym, symrec=cryst%symrec, &
4627 : 0 : time_reversal=kpts_timrev_from_kptopt(ebands%kptopt) == 1)
4628 : :
4629 : 0 : nb = bstop - bstart + 1
4630 [ # # # # : 0 : ABI_MALLOC(kbz, (3, nkbz))
# # # # #
# # # ]
4631 [ # # # # : 0 : ABI_MALLOC(indkpt, (nkbz))
# # # # #
# # # ]
4632 [ # # # # : 0 : ABI_MALLOC(eig_k, (nb, nkbz))
# # # # #
# # # # #
# # ]
4633 [ # # # # : 0 : ABI_MALLOC(eig_kq, (nb, nkbz))
# # # # #
# # # ]
4634 : :
4635 [ # # # # ]: 0 : wtqs = zero; cnt = 0
4636 [ # # ]: 0 : do spin=1,ebands%nsppol
4637 [ # # ]: 0 : do iq_ibz=1,nqibz
4638 [ # # ]: 0 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism.
4639 [ # # ]: 0 : qpt = qibz(:, iq_ibz)
4640 : :
4641 : : ! The double delta is ill-defined for q == 0
4642 [ # # # # : 0 : if (all(abs(qpt) < tol12)) cycle
# # ]
4643 : :
4644 : 0 : ierr = 0; ik_bz = 0
4645 [ # # ]: 0 : do i3=0,nge(3) - 1
4646 [ # # ]: 0 : do i2=0,nge(2) - 1
4647 [ # # ]: 0 : do i1=0,nge(1) - 1
4648 : 0 : ik_bz = ik_bz + 1
4649 : 0 : indkpt(ik_bz) = ik_bz
4650 : :
4651 : : ! Find correspondence between the grid and the IBZ
4652 [ # # ]: 0 : kk = ([i1, i2, i3] + ebands%shiftk(:, 1)) / nge(:)
4653 [ # # ]: 0 : kbz(:, ik_bz) = kk
4654 : :
4655 : 0 : ik_ibz = ibz_krank%get_index(kk)
4656 [ # # ]: 0 : if (ik_ibz < 1) then
4657 [ # # ]: 0 : if (ierr <= enough) then
4658 [ # # ]: 0 : ABI_WARNING(sjoin('kpt:', trim(ktoa(kk)), 'has no symmetric among the k-points!'))
4659 : : end if
4660 : 0 : ierr = ierr + 1; cycle
4661 : : end if
4662 : :
4663 [ # # ]: 0 : eig_k(:, ik_bz) = ebands%eig(bstart:bstop, ik_ibz, spin)
4664 : :
4665 : : ! Find correspondence between the BZ grid and the IBZ.
4666 [ # # ]: 0 : kq = kk + qpt
4667 : 0 : ikq_ibz = ibz_krank%get_index(kq)
4668 : :
4669 [ # # ]: 0 : if (ikq_ibz < 1) then
4670 [ # # ]: 0 : if (ierr <= enough) then
4671 [ # # ]: 0 : ABI_WARNING(sjoin('kpt + qpt:', trim(ktoa(kq)), 'has no symmetric among the k-points!'))
4672 : : end if
4673 : 0 : ierr = ierr + 1; cycle
4674 : : end if
4675 : :
4676 [ # # ]: 0 : eig_kq(:, ik_bz) = ebands%eig(bstart:bstop, ikq_ibz, spin)
4677 : : end do
4678 : : end do
4679 : : end do
4680 [ # # ]: 0 : ABI_CHECK(ierr == 0, "See above warnings")
4681 : :
4682 [ # # ]: 0 : if (any(ltetra == [1, 2])) then
4683 : : ! Compute weights for double delta integration. Note that libtetra assumes Ef set to zero.
4684 : : ! TODO: Average weights over degenerate states?
4685 : : !write(std_out,"(a,i0,2a)")" Calling libtetrabz_dbldelta with ltetra: ", ltetra, " for q-point:", trim(ktoa(qpt))
4686 [ # # # # : 0 : eig_k = eig_k - ebands%fermie; eig_kq = eig_kq - ebands%fermie
# # # # ]
4687 [ # # # # : 0 : ABI_MALLOC(wght_bz, (nb, nb, nkbz))
# # # # #
# # # # #
# # # # #
# ]
4688 : 0 : call libtetrabz_dbldelta(ltetra, cryst%gprimd, nb, nge, eig_k, eig_kq, ngw, wght_bz, comm=comm)
4689 [ # # # # ]: 0 : eig_k = eig_k + ebands%fermie !; eig_kq = eig_kq + ebands%fermie
4690 : :
4691 [ # # # # : 0 : wtqs(iq_ibz, spin) = sum(abs(wght_bz))
# # ]
4692 [ # # ]: 0 : ABI_FREE(wght_bz)
4693 : :
4694 [ # # ]: 0 : else if (ltetra == 3) then
4695 : : ! Tetrahedron method with Allen's approach for double delta.
4696 : : !write(std_out,"(2a)")" Calling Allen's version for q-point: ", trim(ktoa(qpt))
4697 : 0 : nene = 3
4698 : 0 : enemin = ebands%fermie - tol6
4699 : 0 : enemax = ebands%fermie + tol6
4700 : :
4701 [ # # # # : 0 : ABI_MALLOC(dtweightde, (nkbz, nene, nene))
# # # # #
# # # # #
# # ]
4702 [ # # # # : 0 : ABI_MALLOC(tweight, (nkbz, nene, nene))
# # # # #
# # # ]
4703 [ # # # # : 0 : ABI_MALLOC(work_k, (nkbz))
# # # # #
# # # ]
4704 [ # # # # : 0 : ABI_MALLOC(work_kq, (nkbz))
# # # # ]
4705 : :
4706 : : ! TODO
4707 : 0 : ABI_ERROR("Not Implemented")
4708 : : !call init_tetra(indkpt, cryst%gprimd, fs%klatt, kbz, nkbz, tetra, ierr, errorstring, comm)
4709 [ # # ]: 0 : ABI_CHECK(ierr == 0, "init_tetra returned ierr /= 0")
4710 : :
4711 : : !fs%dbldelta_tetra_weights_kfs = zero
4712 [ # # ]: 0 : do ib2=1,nb
4713 [ # # # # ]: 0 : work_k = eig_k(ib2, :)
4714 [ # # ]: 0 : do ib1=1,nb
4715 [ # # # # ]: 0 : work_kq = eig_kq(ib1, :)
4716 : : ! TODO: Average weights over degenerate states?
4717 : : call get_dbl_tetra_weight(work_k, work_kq, enemin, enemax, enemin, enemax, &
4718 : 0 : max_occ1, nene, nene, nkbz, tetra, tweight, dtweightde, ierr)
4719 [ # # ]: 0 : ABI_CHECK(ierr == 0, "get_dbldelta_weights returned ierr /= 0")
4720 : :
4721 [ # # ]: 0 : wtqs(iq_ibz, spin) = wtqs(iq_ibz, spin) + sum(abs(dtweightde(:, 2, 2)))
4722 : : end do
4723 : : end do
4724 : :
4725 : 0 : call destroy_tetra(tetra)
4726 [ # # ]: 0 : ABI_FREE(work_k)
4727 [ # # ]: 0 : ABI_FREE(work_kq)
4728 [ # # ]: 0 : ABI_FREE(dtweightde)
4729 [ # # ]: 0 : ABI_FREE(tweight)
4730 : : else
4731 : 0 : ABI_ERROR(sjoin("Invalid value of ltetra:", itoa(ltetra)))
4732 : : end if
4733 : : end do ! iq_ibz
4734 : : end do ! spin
4735 : :
4736 [ # # ]: 0 : ABI_FREE(indkpt)
4737 [ # # ]: 0 : ABI_FREE(kbz)
4738 [ # # ]: 0 : ABI_FREE(eig_k)
4739 [ # # ]: 0 : ABI_FREE(eig_kq)
4740 : :
4741 : 0 : call ibz_krank%free()
4742 : 0 : call xmpi_sum(wtqs, comm, ierr)
4743 : : !call cwtime_report(" calc_dbldelta", cpu, wall, gflops)
4744 : :
4745 [ # # # # : 0 : end subroutine calc_dbldelta
# # # # #
# # # # #
# # ]
4746 : : !!***
4747 : :
4748 [ - + - - : 75 : end module m_phgamma
+ + - + +
- - + - +
+ - - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + ]
4749 : : !!***
|