LCOV - code coverage report
Current view: top level - src/78_eph - m_migdal_eliashberg.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 435 0
Test Date: 2026-11-06 01:31:13 Functions: 0.0 % 12 0
Branches: 0.0 % 1352 0

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

Generated by: LCOV version 2.3-1