LCOV - code coverage report
Current view: top level - src/78_eph - m_phgamma.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.5 % 1765 1351
Test Date: 2026-09-21 19:39:32 Functions: 76.5 % 34 26

            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              : !!***
        

Generated by: LCOV version 2.3-1