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