LCOV - code coverage report
Current view: top level - src/78_eph - m_cumulant.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.5 % 668 591
Test Date: 2026-09-19 15:24:51 Functions: 72.7 % 11 8

            Line data    Source code
       1              : !!****m* ABINIT/m_cumulant
       2              : !! NAME
       3              : !!  m_cumulant
       4              : !!
       5              : !! FUNCTION
       6              : !!  Module to compute the e-ph spectral functions within the cumulant formalism
       7              : !!  and, optionally, transport properties within the Kubo formalism.
       8              : !!
       9              : !! COPYRIGHT
      10              : !!  Copyright (C) 2008-2026 ABINIT group (JCA, MG)
      11              : !!  This file is distributed under the terms of the
      12              : !!  GNU General Public License, see ~abinit/COPYING
      13              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14              : !!
      15              : !! SOURCE
      16              : 
      17              : #if defined HAVE_CONFIG_H
      18              : #include "config.h"
      19              : #endif
      20              : 
      21              : #include "abi_common.h"
      22              : 
      23              : module m_cumulant
      24              : 
      25              :  use defs_basis
      26              :  use m_abicore
      27              :  use m_xmpi
      28              :  use m_errors
      29              :  use m_ebands
      30              :  use m_sigmaph
      31              :  use m_dtset
      32              :  use m_dtfil
      33              :  use netcdf
      34              :  use m_nctk
      35              : 
      36              :  !use m_ebands,   only : ebands_t
      37              :  use defs_abitypes,    only : MPI_type
      38              :  use m_io_tools,       only : open_file, file_exists, is_open
      39              :  use m_time,           only : cwtime, cwtime_report
      40              :  use m_crystal,        only : crystal_t
      41              :  use m_numeric_tools,  only : simpson_cplx, arth, c2r, simpson, safe_div, simpson_int, ctrap, linfit, linspace
      42              :  use m_fstrings,       only : strcat, sjoin, itoa, ltoa, stoa, ftoa
      43              :  !use m_kpts,           only : kpts_timrev_from_kptopt
      44              :  use m_mpinfo,         only : destroy_mpi_enreg, initmpi_seq
      45              :  use m_fft,            only : fourdp
      46              :  use m_fftcore,        only : ngfft_seq,fftalg_isavailable
      47              :  use m_occ,            only : occ_fd, occ_dfde
      48              : 
      49              :  implicit none
      50              : 
      51              :  private
      52              : !!****
      53              : 
      54              :  public :: cumulant_driver                 ! Main entry point for cumulant computations
      55              : !!****
      56              : 
      57              : !----------------------------------------------------------------------
      58              : 
      59              : !!****t* m_cumulant/cumulant_t
      60              : !! NAME
      61              : !! cumulant_t
      62              : !!
      63              : !! FUNCTION
      64              : !! Container for cumulant and transport quantities
      65              : !!
      66              : !! SOURCE
      67              : 
      68              :  type,public :: cumulant_t
      69              : 
      70              :   integer :: my_nspins
      71              :    ! Number of spins treated by this MPI rank
      72              : 
      73              :   integer :: nkcalc
      74              :    ! Total number of k-points computed. global variable
      75              : 
      76              :   integer :: my_nkcalc
      77              :    ! Number of k-points treated by this MPI rank i.e. local variable.
      78              : 
      79              :   integer :: max_nbcalc
      80              :    ! Maximum number of bands computed (max over nkcalc and spin). global variable
      81              : 
      82              :   integer :: nsppol
      83              :    ! Number of independent spin polarizations.
      84              : 
      85              :   integer :: nspinor
      86              :    ! Number of spinor components.
      87              : 
      88              :   integer :: nqbz
      89              :    ! Number of q-points in the (dense) BZ for sigma integration
      90              : 
      91              :   integer :: nqibz
      92              :    ! Number of q-points in the (dense) IBZ for sigma integration
      93              : 
      94              :   integer :: nbsum
      95              :    ! Total number of bands used in sum over states without taking into account MPI distribution.
      96              : 
      97              :   integer :: natom3
      98              :    ! 3 * natom.
      99              : 
     100              :   integer :: nwr
     101              :    ! Number of frequency points along the real axis for Sigma(w) and spectral function A(w)
     102              :    ! Read from SIGEPH.nc
     103              :    ! Odd number so that the mesh is centered on the KS energy.
     104              :    ! The spectral function is computed only if nwr > 0 (taken from dtset%nfreqsp)
     105              : 
     106              :   integer :: nwr_ce
     107              :    ! Number of frequency points along the real axis for Sigma(w) and spectral function A(w)
     108              :    ! Read from SIGEPH.nc
     109              :    ! Odd number so that the mesh is centered on the KS energy.
     110              :    ! The spectral function is computed only if nwr > 0 (taken from dtset%nfreqsp)
     111              : 
     112              :   integer :: ntemp
     113              :    ! Number of temperatures.
     114              : 
     115              :   integer :: comm
     116              :    ! MPI communicator
     117              : 
     118              :   !type(xcomm_t) :: all_comm
     119              : 
     120              :   type(xcomm_t) :: spin_comm
     121              :    ! MPI communicator for parallelism over spins (high-level)
     122              : 
     123              :   type(xcomm_t) :: kcalc_comm
     124              :    ! MPI communicator for parallelism over k-points
     125              : 
     126              :   type(xcomm_t) :: wt_comm
     127              :     ! MPI communicator for time/frequency domain (low-level)
     128              :     ! NB: memory is not distributed
     129              : 
     130              :   type(xcomm_t) :: ncwrite_comm
     131              :    ! MPI communicator for parallel netcdf IO used to write results for the different k-points/spins
     132              : 
     133              :   !integer :: coords(5)
     134              :    ! Cartesian coordinates of this processor in the Cartesian grid.
     135              : 
     136              :   ! real(dp) :: wr_step
     137              :    ! Step of the linear mesh along the real axis (Ha units).
     138              : 
     139              :   integer :: ngqpt(3)
     140              :    ! Number of divisions in the Q mesh in the BZ.
     141              : 
     142              :   integer,allocatable :: kcalc2ebands(:,:)
     143              :    ! Mapping ikcalc --> ebands IBZ
     144              :    ! Note that this array is not necessarily equation to kcalc2ibz computed in sigmaph
     145              :    ! because we may have used sigma_nkpt to downsample the initial nkpt mesh.
     146              :    ! This array is computed in get_ebands and is equal to kcalc2ibz if sigma_nkpt == ngkpt
     147              : 
     148              :    real(dp),allocatable :: linewidths(:,:,:,:,:)
     149              :    ! (ntemp, bmin:bmax, nkpt, nsppol, nrta)
     150              :    ! Linewidth in the IBZ computed in the SERTA/MRTA.
     151              :    ! Non-zero only for the kcalc k-points.
     152              : 
     153              :    real(dp),allocatable :: vbks(:,:,:,:)
     154              :    ! (3, bmin:bmax, nkpt, nsppol))
     155              :    ! band velocity in Cartesian coordinates in the IBZ
     156              :    ! Non-zero only for the kcalc k-points.
     157              : 
     158              :    integer :: bmin, bmax, bsize
     159              :    ! Only bands between bmin and bmax are considered in the integrals
     160              :    ! as we don't compute linewidths for all states.
     161              :    ! bmin = minval(%bstart_ks); bmax = maxval(%bstop_ks)
     162              :    ! bisze = bmax - bmin + 1
     163              : 
     164              :    type(ebands_t) :: ebands
     165              :    ! bandstructure object used to compute the transport properties
     166              :    ! Allocate using only the relevant bands for transport
     167              :    ! including valence states to allow to compute different doping
     168              : 
     169              :   complex(dp) :: ieta
     170              :    ! Used to shift the poles in the complex plane (Ha units)
     171              :    ! Corresponds to `i eta` term in equations.
     172              : 
     173              :   real(dp) :: tolcum
     174              : 
     175              :   integer :: debug
     176              : 
     177              :   integer,allocatable :: bstart_ks(:,:)
     178              :    ! bstart_ks(nkcalc, nsppol)
     179              :    ! Initial KS band index included in self-energy matrix elements for each k-point in kcalc.
     180              :    ! Depends on spin because all denerate states should be included when symmetries are used.
     181              : 
     182              :   !integer,allocatable :: bstop_ks(:,:)
     183              :    ! bstop_ks(nkcalc, nsppol)
     184              : 
     185              :   integer,allocatable :: nbcalc_ks(:,:)
     186              :    ! nbcalc_ks(nkcalc, nsppol)
     187              :    ! Number of bands included in self-energy matrix elements for each k-point in kcalc.
     188              :    ! Depends on spin because all denerate states should be included when symmetries are used.
     189              : 
     190              :   integer,allocatable :: coords_kws(:,:)
     191              :    ! (2, self%nsppol))
     192              :    ! Cartesian coordinates of this processor in the Cartesian grid.
     193              : 
     194              :   integer,allocatable :: my_spins(:)
     195              :    ! my_spins(my_nspins)
     196              :    ! Indirect table giving the spin indices treated by this rank.
     197              :    ! Used only the collinear case with nspinor == 1
     198              : 
     199              :   integer,allocatable :: my_ikcalc(:)
     200              :    ! my_ikcalc(my_nkcalc)
     201              :    ! List of ikcalc indices treated by this pool if k-point parallelism is activated.
     202              : 
     203              :   real(dp),allocatable :: time_mesh(:,:,:,:,:)
     204              :   ! time_mesh(nwr, max_nbcalc, my_nkcalc, nsppol)
     205              :   ! Time mesh in atomic units
     206              : 
     207              :   real(dp),allocatable :: kcalc(:,:)
     208              :    ! kcalc(3, nkcalc)
     209              :    ! List of k-points where the self-energy is computed.
     210              :    ! This array is not MPI-distributed.
     211              : 
     212              :   real(dp),allocatable :: kTmesh(:)
     213              :    ! kTmesh(ntemp)
     214              :    ! List of temperatures (kT units).
     215              : 
     216              :   real(dp),allocatable :: mu_e(:)
     217              :    ! mu_e(ntemp)
     218              :    ! chemical potential of electrons for the different temperatures.
     219              : 
     220              :    real(dp),allocatable :: l0(:,:,:,:,:), l1(:,:,:,:,:), l2(:,:,:,:,:)
     221              :    real(dp),allocatable :: l0_dm(:,:,:,:,:), l1_dm(:,:,:,:,:), l2_dm(:,:,:,:,:)
     222              :    ! (3, 3, 2, nsppol, ntemp)
     223              :    ! Onsager coeficients in Cartesian coordinates
     224              :    ! _dm is version with Dyson Migdal
     225              : 
     226              :   integer,allocatable :: kcalc2ibz(:,:)
     227              :    !kcalc2ibz(nkcalc, 6))
     228              :    ! Mapping ikcalc --> IBZ as reported by listkk.
     229              : 
     230              :   real(dp),allocatable :: dw_vals(:,:,:,:)
     231              :    !  dw_vals(ntemp, max_nbcalc, my_nkcalc, nsppol)
     232              :    !  Debye-Waller term (static).
     233              : 
     234              :   real(dp),allocatable :: e0vals(:,:,:)
     235              :    ! (max_nbcalc, my_nkcalc, nsppol)
     236              :    ! KS energies at the calculated states retrieved from EPH output file
     237              : 
     238              :   real(dp),allocatable :: wrmesh_b(:,:,:,:)
     239              :   real(dp),allocatable :: wrmesh_ce(:,:,:,:)
     240              :   ! wrmesh_b(nwr, max_nbcalc, my_nkcalc, nsppol))
     241              :   ! Frequency mesh along the real axis (Ha units) used for the different bands
     242              :   ! Each mesh is **centered** on the corresponding KS energy.
     243              : 
     244              :   complex(dp),allocatable :: vals_e0ks(:,:,:,:)
     245              :    ! vals_e0ks(ntemp, max_nbcalc, my_nkcalc, nsppol))
     246              :    ! Sigma_eph(omega=eKS, kT, band, ikcalc, spin).
     247              :    ! Fan-Migdal + Debye-Waller
     248              : 
     249              :   complex(dp),allocatable :: vals_wr(:,:,:,:,:)
     250              :    ! vals_wr(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     251              :    ! Sigma_eph(omega, kT, band, ikcalc, spin).
     252              :    ! enk_KS corresponds to nwr/2 + 1.
     253              : 
     254              :      complex(dp),allocatable :: ct_vals(:,:,:,:,:)
     255              :    ! ct_vals(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     256              :    ! Cumulant function (time, kT, band, ikcalc, spin).
     257              : 
     258              :      complex(dp),allocatable :: c1(:,:,:,:,:)
     259              :    ! FIXME ct_vals(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     260              :    ! Cumulant function (time, kT, band, ikcalc, spin).
     261              : 
     262              :      complex(dp),allocatable :: c2(:,:,:,:,:)
     263              :    ! FIXME ct_vals(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     264              :    ! Cumulant function (time, kT, band, ikcalc, spin).
     265              : 
     266              :      complex(dp),allocatable :: c3(:,:,:,:,:)
     267              :    ! FIXME ct_vals(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     268              :    ! Cumulant function (time, kT, band, ikcalc, spin).
     269              : 
     270              :      complex(dp),allocatable :: gt_vals(:,:,:,:,:)
     271              :    ! FIXME vals_wr(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     272              :    ! Green's function in time domain (time, kT, band, ikcalc, spin).
     273              : 
     274              :      complex(dp),allocatable :: gw_vals(:,:,:,:,:)
     275              :    ! gw_vals(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     276              :    ! Green's function in frequency domain(omega, kT, band) for given (ikcalc, spin).
     277              : 
     278              :      real(dp),allocatable :: spfunc_dm_wr(:,:,:,:,:)
     279              :      real(dp),allocatable :: spfunc_wr(:,:,:,:,:)
     280              :    ! ce_spfunc_wr(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     281              :    ! spectral function for dyson migdal case (omega, kT, band, ikcalc, spin).
     282              : 
     283              :    ! real(dp),allocatable :: ce_spfunc_wr(:,:,:,:,:)
     284              :    ! ce_spfunc_wr(nwr, ntemp, max_nbcalc, my_nkcalc, nsppol)
     285              :    ! Absorption spectrum (omega, kT, band, ikcalc, spin).
     286              : 
     287              :    ! for Cumulant and for Dyson Migdal (_dm)
     288              :    real(dp),allocatable :: seebeck(:,:,:,:,:)
     289              :    real(dp),allocatable :: seebeck_dm(:,:,:,:,:)
     290              :    real(dp),allocatable :: kappa(:,:,:,:,:)
     291              :    real(dp),allocatable :: kappa_dm(:,:,:,:,:)
     292              :    ! (3, 3, 2, nsppol, ntemp)
     293              :    ! Transport coefficients in Cartesian coordinates, for Cumulant and for Dyson Migdal (_dm)
     294              : 
     295              :    real(dp),allocatable :: conductivity_mu(:,:,:,:,:)
     296              :    real(dp),allocatable :: conductivity_mu_dm(:,:,:,:,:)
     297              :    ! (3, 3, 2, nsppol, ntemp)
     298              :    ! Conductivity in Siemens * cm-1
     299              :    ! computed by summing over k-points rather that by performing an energy integration).
     300              :    ! for Cumulant and for Dyson Migdal (_dm)
     301              : 
     302              :    real(dp),allocatable :: print_dfdw(:,:)
     303              : 
     304              :    real(dp),allocatable :: mobility_mu(:,:,:,:,:)
     305              :    real(dp),allocatable :: mobility_mu_dm(:,:,:,:,:)
     306              :    ! (3, 3, 2, nsppol, ntemp)
     307              :    ! mobility for electrons and holes (third dimension) at transport_mu_e(ntemp)
     308              :    ! Third dimension is for electron/hole
     309              :    ! for Cumulant and for Dyson Migdal (_dm)
     310              : 
     311              :    real(dp),allocatable :: transport_mu_e(:)
     312              :    ! (%ntemp)
     313              :    ! Chemical potential at this carrier concentration and temperature
     314              : 
     315              :    real(dp) :: transport_fermie
     316              :    ! Fermi level specified in the input file when computing the SIGEPH file.
     317              : 
     318              :    real(dp) :: transport_extrael
     319              :    ! Extra electrons per unit cell specified in the input file when computing the SIGEPH file.
     320              : 
     321              :    real(dp),allocatable :: n_ehst(:,:,:)
     322              :     ! (2, %nsppol, %ntemp)
     323              :     ! Number of electrons (e) and holes (h) per unit cell
     324              :     ! The first dimension is for electrons/holes.
     325              :     ! If nsppol == 2, the second dimension is the number of e/h for spin else the total number of e/h summed over spins.
     326              : 
     327              :    real(dp) :: eph_extrael
     328              :    ! Extra electrons per unit cell used to compute SERTA lifetimes in sigmaph.
     329              : 
     330              :    real(dp) :: eph_fermie
     331              :    ! Fermi level specified in the input file when computing the SIGEPH file.
     332              : 
     333              :    integer :: ce_ngfft(18)
     334              :    integer :: ce_ngfft_g(18)
     335              :    type(mpi_type) :: ce_mpi_enreg
     336              : 
     337              :  contains
     338              : 
     339              :     procedure :: init => cumulant_init
     340              :     procedure :: compute => cumulant_compute
     341              :     procedure :: kubo_transport => cumulant_kubo_transport
     342              :     procedure :: sigmaph_ncread => cumulant_sigmaph_ncread
     343              :     procedure :: ncwrite => cumulant_ncwrite
     344              :     !procedure :: print_txt_files => cumulant_print_txt_files
     345              :     procedure :: free => cumulant_free
     346              : 
     347              :  end type cumulant_t
     348              : !!***
     349              : 
     350              : !----------------------------------------------------------------------
     351              : 
     352              : contains  !=====================================================
     353              : !!***
     354              : 
     355              : !----------------------------------------------------------------------
     356              : 
     357              : !!****f* m_cumulant/cumulant_driver
     358              : !! NAME
     359              : !! cumulant_driver
     360              : !!
     361              : !! FUNCTION
     362              : !! General driver to compute transport properties
     363              : !!
     364              : !! INPUTS
     365              : !! dtfil<datafiles_type>=variables related to files.
     366              : !! dtset<dataset_type>=All input variables for this dataset.
     367              : !! ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
     368              : !! cryst<crystal_t>=Crystalline structure
     369              : !! comm=Initial MPI communicator with all procs provided by user.
     370              : !!
     371              : !! SOURCE
     372              : 
     373            2 : subroutine cumulant_driver(dtfil, dtset, ebands, cryst, comm)
     374              : 
     375              : !Arguments ------------------------------------
     376              : !scalars
     377              :  integer, intent(in) :: comm
     378              :  type(datafiles_type),intent(in) :: dtfil
     379              :  type(dataset_type),intent(in) :: dtset
     380              :  type(crystal_t),intent(in) :: cryst
     381              :  type(ebands_t),intent(in) :: ebands
     382              : 
     383              : !Local variables ------------------------------
     384              :  integer,parameter :: master = 0
     385              :  integer :: my_rank
     386              :  character(len=fnlen) :: path
     387            2 :  type(cumulant_t) :: cumulant
     388            2 :  type(sigmaph_t) :: sigmaph
     389              : !arrays
     390              :  integer :: unts(2)
     391              : 
     392              : ! *************************************************************************
     393              : 
     394            2 :  my_rank = xmpi_comm_rank(comm)
     395            6 :  unts = [std_out, ab_out]
     396              : 
     397              :  !sigeph_filepath = dtfil%filsigephin
     398            2 :  call wrtout(unts, ch10//' Entering cumulant expansion computation driver.')
     399              : 
     400              :  ! Initialize cumulant object
     401            2 :  call cumulant%init(dtset, dtfil, cryst, ebands, comm, sigmaph)
     402              :  !if (cumulant%all_comm%me == -1) goto 100
     403              : 
     404              :  ! Compute C(t), G(t), G(w) and A(w) using cumulant expansion
     405            2 :  call cumulant%compute()
     406              : 
     407              :  ! Compute transport properties within the Kubo formalism.
     408            3 :  if (any(abs(dtset%sigma_erange) > zero)) call cumulant%kubo_transport(dtset, cryst)!path, ncid)
     409              : 
     410              :  ! Output netcdf file with cumulant results e.g. A_nk(w).
     411              :  ! Use EPH prefix because we may also have EE and PHE cumulants.
     412            2 :  path = strcat(dtfil%filnam_ds(4), "_EPH_CUMULANT.nc")
     413              :  !call cumulant%ncwrite(path, cryst, ebands, dtset)
     414            2 :  call cumulant%ncwrite(path, cryst, dtset)
     415              : 
     416              :  !if (my_rank == master) then
     417              :  !  ! Print cumulant expansion results to stdout and other external txt files (for the test suite)
     418              :  !  !call cumulant%print_txt_files(cryst, dtset, dtfil)
     419              :  !end if
     420              : 
     421              :  ! Free memory
     422              : !100
     423            2 :  call cumulant%free()
     424            2 :  call sigmaph%free()
     425              : 
     426            2 : end subroutine cumulant_driver
     427              : !!***
     428              : 
     429              : !----------------------------------------------------------------------
     430              : 
     431              : !!****f* m_cumulant/cumulant_init
     432              : !! NAME
     433              : !! cumulant_init
     434              : !!
     435              : !! FUNCTION
     436              : !!   Initialization of the cumulant, ex: time mesh
     437              : !!
     438              : !! INPUTS
     439              : !! dtset<dataset_type>=All input variables for this dataset.
     440              : !! dtfil<datafiles_type>=variables related to files.
     441              : !! comm=Initial MPI communicator with all procs provided by user.
     442              : !!
     443              : !! SOURCE
     444              : 
     445            2 : subroutine cumulant_init(self, dtset, dtfil, cryst, ebands, comm, sigmaph )
     446              : 
     447              : !Arguments --------------------------------------
     448              :  integer,intent(in) :: comm
     449              :  type(dataset_type),intent(in) :: dtset
     450              :  type(datafiles_type),intent(in) :: dtfil
     451              :  type(crystal_t),intent(in) :: cryst
     452              :  type(ebands_t),intent(in) :: ebands
     453              :  type(sigmaph_t), intent(out) :: sigmaph
     454              :  class(cumulant_t),intent(inout) :: self
     455              : 
     456              : !Local variables --------------------------------
     457              :  integer, parameter :: master = 0
     458              :  integer :: ncerr, ncid, my_rank, nprocs, ierr, spin, ikcalc, ib,  color !my_spin, my_kcalc, cnt, nbands,
     459              :  integer :: fftalg, fftalga
     460              :  real(dp) :: cpu, wall, gflops, rsize
     461              :  logical :: is_prime
     462              :  character(len=500) :: msg
     463              :  character(len=fnlen) :: sigeph_filepath
     464              :  integer :: unts(2), facts(2)
     465            2 :  real(dp), allocatable :: rtmp_vals_wr(:,:,:,:,:,:), rtmp_vals_e0ks(:,:,:,:,:)
     466              :  !type(ebands_t) :: tmp_ebands
     467              :  real(dp) :: extrael_fermie(2),sigma_erange(2)
     468              :  integer :: sigma_ngkpt(3)
     469              : #ifdef HAVE_MPI
     470              :  integer :: ndims, comm_cart, me_cart
     471              :  logical :: reorder
     472            2 :  integer,allocatable :: dims(:)
     473            2 :  logical,allocatable :: periods(:), keepdim(:)
     474              : #endif
     475              : 
     476              : !************************************************************************
     477              : 
     478            2 :  call cwtime(cpu, wall, gflops, "start")
     479              : 
     480            2 :  self%comm = comm
     481            2 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
     482              : 
     483              : 
     484            6 :  unts = [std_out, ab_out]
     485              : 
     486              :  ! Read data from out_SIGEPH.out file
     487            2 :  sigeph_filepath = dtfil%filsigephin
     488            2 :  call wrtout(unts, sjoin("- Reading Sigma results from:", sigeph_filepath), newlines=1, do_flush=.True.)
     489            2 :  call self%sigmaph_ncread(sigeph_filepath, ncid, comm)
     490              :  sigmaph = sigmaph_read(sigeph_filepath, dtset, comm, msg, ierr, keep_open = .false., &
     491            2 :          extrael_fermie=extrael_fermie, sigma_ngkpt=sigma_ngkpt, sigma_erange=sigma_erange)
     492              : 
     493           30 :  self%bmin = minval(sigmaph%bstart_ks); self%bmax = maxval(sigmaph%bstop_ks)
     494              :  !ABI_CALLOC(self%vbks, (3, self%bmin:self%bmax, ebands%nkpt, sigmaph%nsppol))
     495              : 
     496              :  !if (any(abs(dtset%sigma_erange) > zero)) then
     497              :  self%ebands = sigmaph%get_ebands(cryst, ebands, [self%bmin, self%bmax], &
     498            6 :                                    self%kcalc2ebands, self%linewidths, self%vbks, xmpi_comm_self)
     499              :  !end if
     500              : 
     501            2 :  self%eph_extrael = extrael_fermie(1)
     502            2 :  self%eph_fermie = extrael_fermie(2)
     503              : 
     504            6 :  ABI_MALLOC(self%mu_e, (self%ntemp))
     505              :  ! Possibility to increase nwr in case of interpolation in cumulant to add extra points
     506              :  ! TODO: not working yet
     507            2 :  self%nwr_ce = self%nwr!*4 -1 ! Odd
     508              : 
     509            2 :  self%ieta = j_dpc * sigmaph%ieta
     510              :  !self%ebands = tmp_ebands
     511            6 :  self%mu_e = sigmaph%mu_e
     512              : 
     513              :  ! Setting variables to launch 1d FFT calculations later on
     514            8 :  call ngfft_seq(self%ce_ngfft, [self%nwr, 1, 1])
     515            8 :  self%ce_ngfft(4:6) = self%ce_ngfft(1:3)
     516              : 
     517            2 :  fftalg = self%ce_ngfft(7); fftalga = fftalg/100
     518            2 :  if (fftalga == FFT_SG) then
     519            0 :    self%ce_ngfft(7)= 102
     520            0 :    ABI_WARNING("Setting fftalg to 102. Please link with FFTW3 or DFTI for better performance!")
     521              :  end if
     522              :  !self%ce_ngfft(7)= 102
     523              : 
     524            2 :  call initmpi_seq(self%ce_mpi_enreg)
     525            2 :  call self%ce_mpi_enreg%distribfft%init_seq('c', self%ce_ngfft(2), self%ce_ngfft(3), 'all')
     526            2 :  call self%ce_mpi_enreg%distribfft%init_seq('f', self%ce_ngfft(2), self%ce_ngfft(3), 'all')
     527              : 
     528            8 :  call ngfft_seq(self%ce_ngfft_g, [self%nwr_ce, 1, 1])
     529            8 :  self%ce_ngfft_g(4:6) = self%ce_ngfft_g(1:3)
     530              : 
     531            2 :  fftalg = self%ce_ngfft_g(7); fftalga = fftalg/100
     532            2 :  if (fftalga == FFT_SG) then
     533            0 :    self%ce_ngfft_g(7)= 102
     534            0 :    ABI_WARNING("Setting fftalg to 102. Please link with FFTW3 or DFTI for better performance!")
     535              :  end if
     536              :  !self%ce_ngfft_g(7)= 102
     537              : 
     538              :  ! Setting debugging ( higher verbosity )
     539            2 :  self%tolcum = dtset%tolcum
     540            2 :  if (self%tolcum > zero) then
     541            2 :    self%debug = 0
     542              :  else
     543            0 :    self%debug = 1
     544              :  endif
     545            2 :  self%tolcum = abs(self%tolcum)
     546              : 
     547            2 :  call wrtout(unts, " Cumulant parameters:")
     548            2 :  call wrtout(unts, sjoin(" Number of spins:                   ", itoa(self%nsppol)))
     549            2 :  call wrtout(unts, sjoin(" Number of spinor components:       ", itoa(self%nspinor)))
     550            2 :  call wrtout(unts, sjoin(" Number of k-points computed:       ", itoa(self%nkcalc)))
     551            2 :  call wrtout(unts, sjoin(" Maximum number of bands computed:  ", itoa(self%max_nbcalc)))
     552            2 :  call wrtout(unts, sjoin(" Number of frequencies in Sigma(w): ", itoa(self%nwr)))
     553            2 :  call wrtout(unts, sjoin(" Number of frequencies in G(w): ", itoa(self%nwr_ce)))
     554            2 :  call wrtout(unts, sjoin(" Number of Temperatures:            ", itoa(self%ntemp)))
     555              : 
     556              :  ! ========================
     557              :  ! === MPI DISTRIBUTION ===
     558              :  ! ========================
     559              :  ! At present, there are two levels of MPI parallelism: kcalc and time/frequencies.
     560              :  ! Only the kcalc parallelism leads to memory distribution (my_nkcalc) whereas the secon level is only
     561              :  ! used to distribute the loop over frequencies/time points.
     562              :  ! Note the following:
     563              :  !
     564              :  ! 1) We distribute contigous blocks of kcalc k-points so that we can read/write data in mykcalc chuncks.
     565              : 
     566              :  ! TODO:
     567              :  !  *) Spin and nkcalc(nsppol)
     568              :  !  *) Decide whther it makes sense to create a new comm if nprocs > nkcalc  and mod(nprocs, nkcalc) /= 0
     569              :  !  *) No need anymore for parallelism in time/frequency
     570              : 
     571              : 
     572            2 :  self%kcalc_comm%nproc = nprocs
     573              : ! self%wt_comm%nproc = nprocs / self%kcalc_comm%nproc
     574              : 
     575            2 :  if (nprocs > self%nkcalc) then
     576            0 :    call ifact2(nprocs, facts, is_prime)
     577            0 :    if (is_prime) then
     578              :      ! TODO
     579            0 :      ABI_ERROR("prime numbers are evil!")
     580              :    end if
     581            0 :    if (facts(1) > self%nkcalc) then
     582              :       ! Avoid procs with no k-points.
     583            0 :       facts(1:2) = facts(2:1:-1)
     584              :    end if
     585            0 :    self%kcalc_comm%nproc = facts(1)
     586              :  !  self%wt_comm%nproc = facts(2)
     587              :    !do cnt=self%nkcalc,1,-1
     588              :    !  if (mod(nprocs, cnt) == 0 .and. mod(self%nkcalc, cnt) == 0) then
     589              :    !    self%kcalc_comm%nproc = cnt; self%my_nkcalc = self%nkcalc / cnt; exit
     590              :    !  end if
     591              :    !end do
     592              :  end if
     593              : 
     594           12 :  ABI_ICALLOC(self%coords_kws, (2, self%nsppol))
     595              : #ifdef HAVE_MPI
     596              :  ! Create 2d cartesian communicator: kpoints in Sigma_k, (time/frequency)
     597              :  ! FIXME: Fix spin
     598            2 :  spin = 1
     599            2 :  ndims = 1
     600            2 :  ABI_MALLOC(dims, (ndims))
     601            2 :  ABI_MALLOC(periods, (ndims))
     602            2 :  ABI_MALLOC(keepdim, (ndims))
     603            4 :  periods(:) = .False.; reorder = .False.
     604              : ! dims = [self%kcalc_comm%nproc, self%wt_comm%nproc]
     605            6 :  dims = [self%kcalc_comm%nproc]
     606              : 
     607            2 :  call MPI_CART_CREATE(comm, ndims, dims, periods, reorder, comm_cart, ierr)
     608              :  ! Find the index and coordinates of the current processor
     609            2 :  call MPI_COMM_RANK(comm_cart, me_cart, ierr)
     610            2 :  call MPI_CART_COORDS(comm_cart, me_cart, ndims, self%coords_kws(:, spin), ierr)
     611              : 
     612              :  ! Create communicator for kpoints.
     613            2 :  keepdim = .False.; keepdim(1) = .True.
     614            2 :  call MPI_CART_SUB(comm_cart, keepdim, self%kcalc_comm%value, ierr); self%kcalc_comm%me = xmpi_comm_rank(self%kcalc_comm%value)
     615              : 
     616              :  ! Create communicator for w/t.
     617              : ! keepdim = .False.; keepdim(2) = .True.
     618              : ! call MPI_CART_SUB(comm_cart, keepdim, self%wt_comm%value, ierr); self%wt_comm%me = xmpi_comm_rank(self%wt_comm%value)
     619              : 
     620              :  ! Create communicator for spins.
     621              :  !keepdim = .False.; keepdim(5) = .True.
     622              :  !call MPI_CART_SUB(comm_cart, keepdim, self%spin_comm%value, ierr); self%spin_comm%me = xmpi_comm_rank(self%spin_comm%value)
     623              : 
     624              :  ! Create communicator for parallel IO
     625              :  ! If parallelism over time/frequencies is ON, we select only a column of procs (kcalc dimension)
     626              :  ! to avoid writing the same data multiple times as omega/time are not MPI distributed
     627              :  ! Obviously I'm assuming HDF5 + MPI-IO
     628            2 :  color = xmpi_undefined; if (self%coords_kws(2, spin) == 0) color = 1
     629            2 :  call xmpi_comm_split(comm, color, my_rank, self%ncwrite_comm%value, ierr)
     630            2 :  if (color == 1) then
     631            2 :    self%ncwrite_comm%me = xmpi_comm_rank(self%ncwrite_comm%value)
     632            2 :    self%ncwrite_comm%nproc = xmpi_comm_size(self%ncwrite_comm%value)
     633              :  else
     634            0 :    call self%ncwrite_comm%set_to_null()
     635              :  end if
     636              : 
     637            2 :  ABI_FREE(dims)
     638            2 :  ABI_FREE(periods)
     639            2 :  ABI_FREE(keepdim)
     640            2 :  call xmpi_comm_free(comm_cart)
     641              : #endif
     642              : 
     643              :  call wrtout(unts, &
     644            2 :    sjoin("- Using: ", itoa(self%kcalc_comm%nproc), "MPI procs to distribute:", itoa(self%nkcalc), "k-points."))
     645              :  !call wrtout(unts, &
     646              : !   sjoin("- Using: ", itoa(self%wt_comm%nproc), "MPI procs to parallelize:", itoa(self%nwr_ce), "frequency/time loops."))
     647            2 :  call wrtout(std_out, sjoin("- Performing parallel IO with:", itoa(self%ncwrite_comm%nproc), "procs"))
     648              : 
     649            2 :  if (self%ncwrite_comm%nproc /= 1 .and. .not. nctk_has_mpiio) then
     650            0 :    ABI_WARNING("Cumulant requires netcdf with MPI-IO support! Continuing anyway but runtime error is expected!")
     651              :  end if
     652              : 
     653              :  ! Consistency check.
     654              :  !if (self%kcalc_comm%nproc * self%wt_comm%nproc /= nprocs) then
     655            2 :  if (self%kcalc_comm%nproc /= nprocs) then
     656              :    write(msg, "(a,i0,3a, 3(a,1x,i0))") &
     657            0 :      "Cannot create 2d Cartesian grid with total nprocs: ", nprocs, ch10, &
     658            0 :      "Idle processes are not supported. The product of comm%nproc should be equal to nprocs.", ch10, &
     659            0 :      "kcalc_nproc (", self%kcalc_comm%nproc, ") != ", & ! x wt_nproc (", self%wt_comm%nproc, ") != ", &
     660            0 :      self%kcalc_comm%nproc ! * self%wt_comm%nproc
     661            0 :    ABI_ERROR(msg)
     662              :  end if
     663              : 
     664              :  ! Here we distribute the k-points inside kcalc_comm.
     665            2 :  call xmpi_split_block(self%nkcalc, self%kcalc_comm%value, self%my_nkcalc, self%my_ikcalc)
     666            2 :  ABI_CHECK(self%my_nkcalc > 0, sjoin("nkcalc (", itoa(self%nkcalc), ") > nprocs (", itoa(nprocs), ")"))
     667              : 
     668            2 :  ib = mod(self%nkcalc, self%my_nkcalc)
     669            2 :  call xmpi_sum(ib, self%comm, ierr)
     670            2 :  if (ib /= 0) then
     671            0 :    ABI_COMMENT("The number of MPI procs should be divisible by nkcalc to distribute memory equally!")
     672              :  end if
     673              : 
     674              :  ! Distribute spins and create mapping to spin index.
     675            2 :  if (self%nsppol == 2) then
     676            0 :    ABI_ERROR("cumulant with nsppol 2 is not supported.")
     677            0 :    call xmpi_split_block(self%nsppol, comm, self%my_nspins, self%my_spins)
     678              :    !ABI_CHECK(self%my_nspins > 0, sjoin("nsppol (", itoa(self%nsppol), ") > spin_comm_nproc (", itoa(comm), ")"))
     679              :  else
     680              :    ! No nsppol parallelism DOH!
     681            2 :    self%my_nspins = 1
     682            2 :    ABI_MALLOC(self%my_spins, (self%my_nspins))
     683            4 :    self%my_spins = 1
     684              :  end if
     685              : 
     686              :  !ABI_CALLOC(self%ce_spfunc_wr, (self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     687         5508 :  ABI_CALLOC(self%spfunc_dm_wr, (self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     688         5508 :  ABI_CALLOC(self%spfunc_wr, (self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     689         5508 :  ABI_CALLOC(self%gw_vals, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     690              : 
     691            2 :  if (self%debug == 1) then
     692            0 :    ABI_CALLOC(self%time_mesh, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     693            0 :    ABI_CALLOC(self%ct_vals, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     694            0 :    ABI_CALLOC(self%c1, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     695            0 :    ABI_CALLOC(self%c2, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     696            0 :    ABI_CALLOC(self%c3, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     697            0 :    ABI_CALLOC(self%gt_vals, (self%nwr_ce, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     698              :  endif
     699              : 
     700           14 :  ABI_MALLOC(rtmp_vals_wr, (2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     701           12 :  ABI_MALLOC(rtmp_vals_e0ks, (2, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     702           14 :  ABI_MALLOC(self%vals_wr, (self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     703           12 :  ABI_MALLOC(self%vals_e0ks, (self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     704           12 :  ABI_MALLOC(self%wrmesh_b, (self%nwr, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     705           12 :  ABI_MALLOC(self%wrmesh_ce, (self%nwr_ce, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     706              : ! ABI_MALLOC(self%wrmesh_ce, (self%nwr_ce, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     707           10 :  ABI_MALLOC(self%e0vals, (self%max_nbcalc, self%my_nkcalc, self%nsppol))
     708           12 :  ABI_MALLOC(self%dw_vals, (self%ntemp, self%max_nbcalc, self%my_nkcalc, self%nsppol))
     709              : 
     710              :  ! Estimate memory (only nwr arrays)
     711            2 :  rsize = five; if (self%debug == 1) rsize = rsize + 3
     712            2 :  rsize = rsize * self%nwr_ce * self%ntemp * self%max_nbcalc * self%my_nkcalc * self%nsppol
     713            2 :  call xmpi_max(rsize, self%comm, ierr)
     714            2 :  write(msg,'(a,f8.1,a)')' Memory needed for cumulant arrays per MPI proc: ',dp * rsize * b2Mb, ' [Mb] <<< MEM'
     715            2 :  call wrtout(std_out, msg)
     716              : 
     717              :  ! Each MPI proc reads a chunk of my_nkcalc entries starting at (ikcalc, spin) from the SIGEPH.nc file.
     718              :  ! so that memory is MPI-distributed.
     719              :  ! On disk, we have the following netcdf arrays:
     720              :  !
     721              :  !         nctkarr_t("wrmesh_b", "dp", "nwr, max_nbcalc, nkcalc, nsppol"), &
     722              :  !         nctkarr_t("vals_wr", "dp", "two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
     723              :  !         nctkarr_t("vals_e0ks", "dp", "two, ntemp, max_nbcalc, nkcalc, nsppol"), &
     724              :  !         nctkarr_t("ks_enes", "dp", "max_nbcalc, nkcalc, nsppol"), &
     725              :  !
     726              :  ! Note the nkcalc global dimension instead of my_nkcalc.
     727              :  ! Results are in a.u.
     728              : 
     729              :  ! Offse of this proc
     730            2 :  spin = self%my_spins(1)
     731            2 :  ikcalc = self%my_ikcalc(1)
     732              : 
     733              :  ncerr = nf90_get_var(ncid, vid("vals_wr"), rtmp_vals_wr, start=[1,1,1,1,ikcalc,spin], &
     734           26 :                       count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
     735            2 :  NCF_CHECK(ncerr)
     736              : 
     737              :  ncerr = nf90_get_var(ncid, vid("wrmesh_b"), self%wrmesh_b, start=[1,1,ikcalc,spin], &
     738           18 :                       count=[self%nwr, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
     739            2 :  NCF_CHECK(ncerr)
     740              : 
     741              :  ncerr = nf90_get_var(ncid, vid("vals_e0ks"), rtmp_vals_e0ks, start=[1,1,1,ikcalc,spin],  &
     742           22 :                       count=[2, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
     743            2 :  NCF_CHECK(ncerr)
     744              : 
     745              :  ncerr = nf90_get_var(ncid, vid("ks_enes"), self%e0vals, start=[1,ikcalc,spin], &
     746           14 :                       count=[self%max_nbcalc, self%my_nkcalc, self%my_nspins])
     747            2 :  NCF_CHECK(ncerr)
     748              : 
     749              :  ncerr = nf90_get_var(ncid, vid("dw_vals"), self%dw_vals, start=[1,1,ikcalc,spin], &
     750           18 :                       count=[self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
     751            2 :  NCF_CHECK(ncerr)
     752              : 
     753              :  ! Close the file here but the Kubo equation needs to read v_nk from file.
     754              :  ! We will have to rationalize this part.
     755            2 :  NCF_CHECK(nf90_close(ncid))
     756              : 
     757              :  ! Convert from real arrays to Fortran complex
     758         5498 :  self%vals_wr =  (rtmp_vals_wr(1,:,:,:,:,:) + j_dpc * rtmp_vals_wr(2,:,:,:,:,:))!*Ha_eV
     759           98 :  self%vals_e0ks = (rtmp_vals_e0ks(1,:,:,:,:) + j_dpc * rtmp_vals_e0ks(2,:,:,:,:))!*Ha_eV
     760              : 
     761              : ! self%wrmesh_b = self%wrmesh_b*Ha_eV
     762              : ! self%e0vals = self%e0vals*Ha_eV
     763              : ! self%max_nbcalc=self%max_nbcalc*Ha_eV
     764              : 
     765              : ! self%e0vals = self%e0vals * Ha_eV
     766              : ! self%wrmesh_b = self%wrmesh_b * Ha_eV
     767              : 
     768            2 :  ABI_SFREE(rtmp_vals_wr)
     769            2 :  ABI_SFREE(rtmp_vals_e0ks)
     770              : 
     771           12 :  call cwtime_report(" cumulant init", cpu, wall, gflops)
     772              : 
     773              : contains
     774           10 :  integer function vid(vname)
     775              :    character(len=*),intent(in) :: vname
     776           10 :    vid = nctk_idname(ncid, vname)
     777              : end function vid
     778              : 
     779              : end subroutine cumulant_init
     780              : !!***
     781              : 
     782              : !----------------------------------------------------------------------
     783              : 
     784              : !!****f* m_cumulant/cumulant_compute
     785              : !! NAME
     786              : !! cumulant_compute
     787              : !!
     788              : !! FUNCTION
     789              : !!  Compute cumulant.
     790              : !!
     791              : !! INPUTS
     792              : !!
     793              : !! SOURCE
     794              : 
     795            2 : subroutine cumulant_compute(self)
     796              : 
     797              : !Arguments ------------------------------------
     798              :  class(cumulant_t),intent(inout) :: self
     799              : 
     800              : !Local variables ------------------------------
     801              :  integer,parameter :: master = 0
     802              :  integer :: nbands, ib, ikcalc, it, iw, spin, itemp, comm
     803              :  integer :: nwr, nwr_ce
     804              :  integer :: my_rank, nprocs, my_spin, my_ik
     805              :  real(dp) :: time, omega, init_t, time_step, time_step_init, time_max!, wmesh_step_init
     806              :  real(dp) :: cpu, wall, gflops, cpu_kloop, wall_kloop, gflops_kloop
     807              :  real(dp) :: wr_step, Ha_fs ! wr_step_ce
     808              :  character(len=500) :: msg
     809              : !arrays
     810            2 :  real(dp),allocatable :: temp_g(:,:,:), temp_r(:,:), temp_r_cplx(:,:), temp_g_ce(:,:,:)
     811            2 :  real(dp),allocatable :: betaoverw2(:) !, dfft(:)
     812              :  !complex(dp),allocatable :: temp_reflex(:) ! betaoverw2c(:),
     813            2 :  real(dp),allocatable :: wrmesh_shifted(:), wrmesh_shifted_ce(:), beta(:), c3(:)
     814            2 :  real(dp),allocatable :: time_mesh(:), time_mesh_temp(:)
     815              :  real(dp) :: output_c3!, output_test2r, output_test2i
     816              :  real(dp) :: m_fit_re, b_fit_re, m_fit_im, b_fit_im, res_re, res_im
     817            2 :  complex(dp),allocatable :: c1(:), ct_temp(:), c_temp(:)
     818            2 :  complex(dp),allocatable :: c2(:), ct(:), gt(:), gw(:), g1(:)
     819              :  integer :: fftalg, fftalga
     820              :  logical :: use_fft
     821              : 
     822              : !************************************************************************
     823              : 
     824              : ! Initialization of parallel variables
     825            2 :  comm = self%comm
     826            2 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
     827              : 
     828            2 :  call wrtout(std_out, " Computing cumulant. This may take some time depending on the dims of the problem...")
     829            2 :  call cwtime(cpu_kloop, wall_kloop, gflops_kloop, "start")
     830              : 
     831              :  ! Initialization of variables and allocation of arrays
     832            2 :  nwr = self%nwr
     833            2 :  nwr_ce = self%nwr_ce
     834          276 :  ABI_CALLOC(c1, (nwr))
     835          276 :  ABI_CALLOC(c_temp, (nwr_ce))
     836              :  !ABI_CALLOC(temp_reflex, (nwr/2))
     837          274 :  ABI_CALLOC(c2, (nwr))
     838          276 :  ABI_CALLOC(c3, (nwr))
     839          274 :  ABI_CALLOC(g1, (nwr_ce))
     840          274 :  ABI_CALLOC(gw, (nwr_ce))
     841              :  !ABI_CALLOC(dfft, (nwr_ce))
     842          276 :  ABI_CALLOC(time_mesh, (nwr_ce))
     843          274 :  ABI_CALLOC(time_mesh_temp, (nwr))
     844          274 :  ABI_CALLOC(ct, (nwr_ce))
     845          274 :  ABI_CALLOC(ct_temp, (nwr))
     846          274 :  ABI_CALLOC(gt, (nwr_ce))
     847          818 :  ABI_CALLOC(temp_g, (2,nwr,1))
     848          818 :  ABI_CALLOC(temp_g_ce, (2,nwr_ce,1))
     849              : 
     850          276 :  ABI_CALLOC(temp_r, (nwr,1))
     851          548 :  ABI_CALLOC(temp_r_cplx, (2*nwr_ce,1))
     852              :  !ABI_CALLOC(inv_wrmesh_shifted_sq, (nwr_ce))
     853          274 :  ABI_CALLOC(wrmesh_shifted, (nwr))
     854          274 :  ABI_CALLOC(wrmesh_shifted_ce, (nwr_ce))
     855          274 :  ABI_CALLOC(beta, (nwr))
     856          274 :  ABI_CALLOC(betaoverw2, (nwr))
     857              :  !ABI_CALLOC(betaoverw2c, (nwr))
     858            2 :  Ha_fs = 8.955433106
     859              : 
     860              :  ! Setting direct domain after fft
     861              :  ! 0 1 2 3 ... N/2    -(N-1)/2 ... -1    <= gc
     862              :  ! 1 2 3 4 ....N/2+1  N/2+2    ...  N    <= index ig
     863              : 
     864              :  !do iw=1,nwr_ce
     865              :  !  dfft(iw) = ig2gfft(iw,nwr)
     866              :  !end do
     867              :  !ABI_FREE(dfft)
     868              : 
     869            2 :  fftalg = self%ce_ngfft(7)
     870            2 :  fftalga = fftalg/100
     871              :  ! Loops are MPI-parallelized over k-points and spin.
     872            4 :  do my_spin=1,self%my_nspins
     873            2 :    spin = self%my_spins(my_spin)
     874           16 :    do my_ik=1,self%my_nkcalc
     875           12 :      ikcalc= self%my_ikcalc(my_ik)
     876              :      !if (ikcalc /= 1) cycle ! For debugging purpose
     877           12 :      nbands = self%nbcalc_ks(ikcalc, spin)
     878           12 :      call cwtime(cpu, wall, gflops, "start")
     879              : 
     880           32 :      do ib=1,nbands
     881              :        !if (ib > 1) cycle ! MG HACK To be able to run tests quickly.
     882              : 
     883              :        ! Shifting w-mesh to center at KS-energy and remove the value w=0.0 from integrations ( Principal Value )
     884           20 :        wr_step = self%wrmesh_b(2,ib,my_ik,spin) - self%wrmesh_b(1,ib,my_ik,spin)
     885              :        wrmesh_shifted(:) = self%wrmesh_b(:,ib,my_ik,spin) - self%e0vals(ib,my_ik,spin) &
     886         2720 :                - 0.5 * wr_step
     887              : 
     888              : 
     889           52 :        do itemp=1,self%ntemp
     890              :          ! if (itemp > 1) cycle ! MG HACK To be able to run tests quickly.
     891              : 
     892              :          ! Defining time mesh
     893              :          ! all variables with nwr_ce size are to use after interpolation of the
     894              :          ! cumulant function in case we want to add more points
     895           20 :          if (abs(aimag(self%vals_e0ks(itemp, ib, my_ik, spin))) >  1.0e-16) then
     896           20 :            time_max = log(self%tolcum) / (-abs(aimag(self%vals_e0ks(itemp, ib, my_ik, spin))))
     897              :          else
     898            0 :            time_max = log(self%tolcum) / (-1.0e-16)
     899            0 :            ABI_WARNING("Imaginary part of the self energy is 0 in cumulant calculation. Reset to 1.e-16")
     900              :          endif
     901           20 :          init_t = 0.0
     902           20 :          time_step_init = 1.0/(nwr - 1.0)
     903           20 :          time_mesh_temp(:) = arth(init_t, time_step_init, nwr)
     904         2720 :          time_mesh_temp = time_mesh_temp * 2*PI/wr_step
     905           20 :          time_step = time_mesh_temp(2) - time_mesh_temp(1)
     906              : 
     907         2720 :          time_mesh(:) = time_mesh_temp(:) !! arth(init_t, time_step_init, nwr_ce)
     908         2720 :          time_mesh = time_mesh * 2*PI/wr_step
     909              : 
     910              :          ! Defining frequency mesh for after interpolation
     911              : 
     912              :          !! TODO: Fix problems from when adding more points to time mesh by
     913              :          !interpolation
     914              : 
     915              :          !!wmesh_step_init = 1.0/(nwr_ce/2.0 -1 )
     916              :          !!init_w = -1.0
     917              :          !!end_w = 0.0
     918              :          !!wrmesh_shifted_ce(:nwr_ce/2+1) = linspace(init_w,end_w, nwr_ce/2+1)
     919              :          !!init_w = 0.0
     920              :          !!end_w = 1.0
     921              :          !!wrmesh_shifted_ce(nwr_ce/2+1:) = linspace(init_w,end_w, nwr_ce/2+1)
     922              : 
     923              :          !!wr_step_ce = wrmesh_shifted_ce(2) - wrmesh_shifted_ce(1)
     924              :          !!wrmesh_shifted_ce(:) = wrmesh_shifted_ce(:) * PI/time_step - 0.5 *wr_step_ce
     925              :          !!self%wrmesh_ce(:,ib,my_ik,spin) = wrmesh_shifted_ce(:) + self%e0vals(ib,my_ik,spin) + 0.5 *wr_step_ce
     926              :          !!wrmesh_shifted_ce = wrmesh_shifted
     927              : 
     928           20 :          if (self%debug == 1) self%time_mesh(:,itemp,ib,my_ik,spin) = time_mesh_temp(:)
     929              : 
     930           20 :          if (time_mesh_temp(nwr) < time_max) ABI_WARNING(sjoin("KBT",itoa(my_ik),itoa(ib),itoa(itemp)))
     931              :          msg = sjoin( &
     932              :                  "Time mesh smaller than needed to reach tolerance value. Actual value of", &
     933           20 :                  ftoa(time_mesh_temp(nwr)), ", desirable ",ftoa(time_max),". Increase nfreqsp.")
     934           20 :          if (time_mesh_temp(nwr) < time_max) ABI_WARNING(msg)
     935         2720 :          beta(:) = abs( aimag( self%vals_wr(:, itemp, ib, my_ik, spin ) ) ) / pi
     936              : 
     937              :          ! Calculation of the different terms of the cumulant ( c1, c2 and c3 ),
     938         2720 :          betaoverw2(:) = beta(:) / (wrmesh_shifted(:) ** 2)
     939              : 
     940         2720 :          c2(:) = -j_dpc * real( self%vals_e0ks( itemp, ib, my_ik, spin ) ) * time_mesh_temp(:)
     941              : 
     942           20 :          output_c3 = simpson(wr_step, betaoverw2)
     943         2720 :          c3(:) = -1.0 * output_c3
     944              : 
     945              : 
     946         2720 :          temp_r(:,1) = betaoverw2(:)
     947              : 
     948              :          !@Joao: I got different results when I set use_fft to .False.
     949              :          !Can you recheck this part, if use_fft = .False. still needed?
     950              : 
     951           20 :          use_fft = .True.
     952              :          !use_fft = .not. fftalga == FFT_SG
     953              :          if (use_fft) then
     954           20 :            call fourdp(1, temp_g, temp_r, -1, self%ce_mpi_enreg, nwr, 1, self%ce_ngfft , 0 )
     955         2720 :            c1(:) = temp_g(1, :, 1) + j_dpc* temp_g(2, :, 1)
     956         2720 :            c1 = c1 * wr_step * nwr
     957         1360 :            c1(2::2) = -1.0 * c1(2::2)
     958              :          else
     959              :            msg = sjoin("FFT not available, using DFT instead.",  &
     960              :                        " Slower but reliable.",  &
     961              :                        " Parallelism over frequency for integration of C(t)")
     962              :            ABI_COMMENT(msg)
     963              :            do it=1, nwr
     964              :              ! if (mod(it, self%wt_comm%nproc) /= self%wt_comm%me) cycle  ! MPI parallelism over time
     965              :              time = time_mesh_temp(it)
     966              : 
     967              :              ! Discrete Fourier Transform of C1 ( cumulant function without the +iwt and -1 parts
     968              :              c_temp(:) = betaoverw2(:) *  exp( - j_dpc * time * wrmesh_shifted(:) )
     969              :              c1(it) = simpson_cplx( nwr, wr_step, c_temp)
     970              :            enddo
     971              : 
     972              :          endif
     973              : 
     974              : 
     975              :          ! The cumulant function as sum of the different components
     976         2720 :          ct_temp(:) = c1 + c2 + c3
     977              :          ! Fitting the cumulant function
     978         2720 :          res_re = linfit(nwr,time_mesh_temp(:), real(ct_temp(:)), m_fit_re, b_fit_re)
     979         2720 :          res_im = linfit(nwr,time_mesh_temp(:), aimag(ct_temp(:)), m_fit_im, b_fit_im)
     980              :          !        call xmpi_sum(ct, self%wt_comm%value, ierr)
     981           20 :          if (self%debug == 1) then ! .and. self%wt_comm%nproc > 1) then
     982            0 :            self%ct_vals(:, itemp, ib, my_ik, spin) = ct(:)
     983            0 :            self%c1(:, itemp, ib, my_ik, spin) = c1(:)
     984            0 :            self%c2(:, itemp, ib, my_ik, spin) = c2(:)
     985            0 :            self%c3(:, itemp, ib, my_ik, spin) = c3(:)
     986              :          endif
     987              : 
     988              :          ! Adding extra interpolated points to the cumulant function
     989              :          !!ct(:nwr/2) = ct_temp(:nwr/2)
     990              :          !!ct(nwr/2:) = time_mesh(nwr/2:) * m_fit_re + b_fit_re + j_dpc * ( time_mesh(nwr/2:) * m_fit_im + b_fit_im )
     991              : 
     992              :          !!do iw=1, nwr/2
     993              :          !!    temp_reflex(nwr/2-iw) = - ct(iw) + time_mesh(iw) * m_fit_re + b_fit_re + j_dpc * ( time_mesh(iw) * m_fit_im + b_fit_im )
     994              :          !!enddo
     995              :          !!ct(nwr_ce - nwr/2:) =  ct(nwr_ce - nwr/2:) + temp_reflex(:)
     996         2720 :          ct(:) = ct_temp(:)
     997              :          ! Retarded Green's function in time domain
     998         2740 :          gt = - j_dpc * exp( ct )
     999              : 
    1000              :          ! Collect data if wt parallelism.
    1001              :          !call xmpi_sum(gt, self%wt_comm%value, ierr)
    1002              : 
    1003           20 :          if (self%debug == 1) then ! .and. self%wt_comm%nproc > 1) then
    1004            0 :            self%gt_vals(:, itemp, ib, my_ik, spin) = gt(:)
    1005              :          end if
    1006              : 
    1007           20 :          use_fft = .True.
    1008              :          !use_fft = .not. fftalga == FFT_SG
    1009           20 :          if (use_fft) then
    1010              : 
    1011              :            ! Fast Fourier Transform to obtain the Green's function in frequency
    1012              :            ! domain
    1013         2720 :            temp_g_ce(1,:,1) = real(gt(:))
    1014         2720 :            temp_g_ce(2,:,1) = aimag(gt(:))
    1015           20 :            call fourdp(2, temp_g_ce, temp_r_cplx, 1, self%ce_mpi_enreg, nwr_ce, 1, self%ce_ngfft_g , 0 )
    1016         2720 :            gw(:) = temp_r_cplx(1::2,1) + j_dpc* temp_r_cplx(2::2,1)
    1017              : 
    1018              : 
    1019              :            ! TODO use ig2gfft from 52_fft_mpi_noabirule/m_fftcore.F90 instead of the two following lines
    1020           20 :            if ( mod(nwr_ce,2) == 0 ) then
    1021            0 :              self%gw_vals(1:int(nwr_ce/2.0), itemp, ib, my_ik, spin) = gw(int(nwr_ce/2.0):nwr_ce)
    1022            0 :              self%gw_vals(int(nwr_ce/2.0)+1:nwr_ce, itemp, ib, my_ik, spin) = gw(1:int(nwr_ce/2.0)-1)
    1023              :            else
    1024         1380 :              self%gw_vals(1:int(nwr_ce/2.0)+1, itemp, ib, my_ik, spin) = gw(int(nwr_ce/2.0)+1:nwr_ce)
    1025         1360 :              self%gw_vals(int(nwr_ce/2.0)+2:nwr_ce, itemp, ib, my_ik, spin) = gw(1:int(nwr_ce/2.0))
    1026              :            endif
    1027              : 
    1028              : 
    1029         2720 :            self%gw_vals(:, itemp, ib, my_ik, spin) = self%gw_vals(:, itemp, ib, my_ik, spin) * time_step
    1030              : 
    1031              :            ! FFT is different from integration methods and the two extreme points
    1032              :            ! need to be compensated
    1033              :            self%gw_vals(:, itemp, ib, my_ik, spin) = self%gw_vals(:, itemp, ib, my_ik, spin)  &
    1034         2720 :              - 0.5* gt(1)*time_step - 0.5 * gt(nwr_ce)*exp(j_dpc*wrmesh_shifted_ce(:)*time_mesh(nwr_ce)) * time_step
    1035              : 
    1036              : 
    1037              :          else
    1038              :            msg = sjoin("FFT not available, using DFT instead.",  &
    1039              :                           " Slower but reliable.",  &
    1040              :                           " Parallelism over time for integration of G(t)")
    1041              :            ABI_COMMENT(msg)
    1042              : 
    1043              :            do iw=1, nwr_ce
    1044              :              ! if (mod(iw, self%wt_comm%nproc) /= self%wt_comm%me) cycle  ! MPI parallelism over freqs
    1045              :              omega = wrmesh_shifted_ce(iw)
    1046              : 
    1047              :              ! Discrete Fourier Transform of the Green's function
    1048              :              g1(:) = exp( j_dpc * omega * time_mesh(:) ) * gt(:)
    1049              : 
    1050              :              ! Retarded Green's function in frequency domain
    1051              :              self%gw_vals(iw, itemp, ib, my_ik, spin) = simpson_cplx(nwr_ce, time_step, g1)
    1052              : 
    1053              :              !if (my_rank == 0) write(ab_out, *)"gw_vals",  self%gw_vals(iw, itemp, ib, my_ik, spin)
    1054              :            end do ! iw
    1055              :          end if
    1056              : 
    1057              :          ! Collect data if wt parallelism.
    1058              :          ! call xmpi_sum(self%gw_vals(:, itemp, ib, my_ik, spin) , self%wt_comm%value, ierr)
    1059              : 
    1060              :        end do  ! itemp
    1061              :      end do ! ib
    1062              : 
    1063           12 :      write(msg,'(4(a,i0),a,f8.2)') " k-point [", ikcalc, "/", self%nkcalc, "]"
    1064           26 :      call cwtime_report(msg, cpu, wall, gflops)
    1065              :    end do ! my_ik
    1066              :  end do ! my_spin
    1067              : 
    1068            2 :  ABI_SFREE(c1)
    1069            2 :  ABI_FREE(ct_temp)
    1070            2 :  ABI_FREE(c_temp)
    1071            2 :  ABI_SFREE(c2)
    1072            2 :  ABI_SFREE(c3)
    1073            2 :  ABI_SFREE(ct)
    1074            2 :  ABI_SFREE(gt)
    1075            2 :  ABI_SFREE(g1)
    1076            2 :  ABI_SFREE(gw)
    1077            2 :  ABI_SFREE(beta)
    1078            2 :  ABI_SFREE(temp_g)
    1079            2 :  ABI_SFREE(temp_g_ce)
    1080            2 :  ABI_SFREE(temp_r)
    1081            2 :  ABI_SFREE(temp_r_cplx)
    1082            2 :  ABI_SFREE(time_mesh)
    1083            2 :  ABI_SFREE(wrmesh_shifted)
    1084            2 :  ABI_SFREE(wrmesh_shifted_ce)
    1085              :  !ABI_SFREE(inv_wrmesh_shifted_sq)
    1086            2 :  ABI_SFREE(betaoverw2)
    1087            2 :  ABI_FREE(time_mesh_temp)
    1088              : 
    1089            2 :  call cwtime_report(" cumulant_compute", cpu_kloop, wall_kloop, gflops_kloop)
    1090              : 
    1091              :  ! contains
    1092              : 
    1093              :  ! real function lreg(x,y, n, nsteps) result(m,b)
    1094              :  ! !
    1095              :  ! ! Determines a linear regression from x and y values
    1096              :  ! ! What are the best m and b values to produce y= m*x + b ?
    1097              :  ! !
    1098              :  ! !
    1099              :  ! ! Cost function ( Root Mean Squared Error ): J = 1/n sum_i^n (pred_i - y_i)^2
    1100              :  ! ! where pred is the predicted value and y the true value
    1101              :  ! !
    1102              :  ! ! Goal: minimize J
    1103              :  ! ! How? Using Gradient Descent
    1104              :  ! ! - Learning rate is the step that the new value will be ( too small, takes longer; too large, it can be instable )
    1105              :  ! ! - Initial m or b are chosen randomly
    1106              :  ! ! - n is the number of points
    1107              :  ! !
    1108              :  ! ! new b = old b - 2*(learning rate)/n sum_i^n (pred(x_i) - y) * x_i
    1109              :  ! ! new m = old m  - 2*(learning rate)/n sum_i^n (pred(x_i) - y)
    1110              :  ! !
    1111              :  !
    1112              :  ! integer, intent(in) :: n, nsteps
    1113              :  ! real(dp), intent(in) :: x(n), y(n)
    1114              :  ! !real(dp) :: m,b
    1115              :  ! integer :: istep, i
    1116              :  ! real(dp) :: lrate, cost, acc
    1117              :  ! real(dp) :: pred(n)
    1118              :  !
    1119              :  ! m = 0 ! Initial guesses
    1120              :  ! b = 0
    1121              :  ! do istep=1,nsteps
    1122              :  !
    1123              :  !  pred(:) = m * x(:) + b ! Prediction with the new coefficients m, b
    1124              :  !
    1125              :  !  ! Check accuracy comparing the linear regression and the data
    1126              :  !  do i=1, n
    1127              :  !    if (abs(y(i) ) < 1e-4 ) cycle
    1128              :  !    acc = acc + sum( abs(pred(i) - y(i))/y(i) )
    1129              :  !  end do i
    1130              :  !  acc = 1 - acc
    1131              :  !  print *, "Accuracy: ",istep, acc
    1132              :  !
    1133              :  !  cost = 1.0/n * sum(pred(:) - y(:))**2
    1134              :  !
    1135              :  !  print *, "Cost: ", istep, cost
    1136              :  !
    1137              :  !  ! Update coefficients
    1138              :  !
    1139              :  !  m = m - 2.0*lrate/n * sum(pred(:) - y(:))
    1140              :  !  b = b - 2.0*lrate/n * sum((pred(:) - y(:))*x(:))
    1141              :  ! enddo ! istep
    1142              :  !
    1143              :  ! end function lreg
    1144              : 
    1145              :  !  complex function trapz(f_size, f_step, f)
    1146              :  !
    1147              :  !   integer,intent(in) :: f_size
    1148              :  !   real(dp),intent(in) :: f_step
    1149              :  !   complex(dp),intent(in) :: f(f_size)
    1150              :  !
    1151              :  !   trapz = ( sum(f) - 0.5* f(1) - 0.5* f(f_size) )* f_step
    1152              :  !
    1153              :  !  end function trapz
    1154              : 
    1155            4 : end subroutine cumulant_compute
    1156              : !!***
    1157              : 
    1158              : !----------------------------------------------------------------------
    1159              : 
    1160              : !!****f* m_cumulant/cumulant_kubo_transport
    1161              : !! NAME
    1162              : !! cumulant_kubo_transport
    1163              : !!
    1164              : !! FUNCTION
    1165              : !!  Compute conductivity/mobility within Kubo Greenwood formula, using Cumulant self energy spectral function
    1166              : !!  NB: also modified to use Dyson Migdal for comparison
    1167              : !!
    1168              : !! INPUTS
    1169              : !!
    1170              : !! SOURCE
    1171              : 
    1172            2 : subroutine cumulant_kubo_transport(self, dtset, cryst)
    1173              : 
    1174              : !Arguments ------------------------------------
    1175              :  class(cumulant_t),intent(inout) :: self
    1176              :  type(dataset_type),intent(in) :: dtset
    1177              :  type(crystal_t),intent(in) :: cryst
    1178              : 
    1179              : !Local variables ------------------------------
    1180              :  integer,parameter :: master = 0
    1181              :  integer :: cnt
    1182              :  integer :: nbands, ib, ikcalc, iw, spin, itemp, comm, ik_ibz
    1183              :  integer :: ieh, ib_eph
    1184              :  integer :: ii, jj, time_opt, isym_k, trev_k
    1185              :  integer :: my_rank, nprocs, my_spin, my_ik
    1186              :  real(dp) :: omega!, time_step!, time_max
    1187              :  real(dp) :: cpu, wall, gflops, cpu_kloop, wall_kloop, gflops_kloop
    1188              :  real(dp) :: eig_nk, sp_func, wr_step
    1189              :  real(dp) :: sp_func_dm
    1190              :  real(dp) :: integration
    1191              :  real(dp) :: integration_dm
    1192              :  real(dp) :: mu_e, max_occ, fact0, fact
    1193              :  character(len=500) :: msg
    1194              : !arrays
    1195            2 :  real(dp),allocatable :: kernel(:), dfdw_acc(:),Aw(:),Aw_l0(:),dfdw_l0(:)!test_Aw(:), test_dfdw(:)
    1196            2 :  real(dp),allocatable :: kernel_dm(:), Aw_dm(:),Aw_l0_dm(:)
    1197            2 :  complex(dp),allocatable :: gdm_vals(:)
    1198              :  real(dp) :: int_Aw
    1199              :  real(dp) :: int_Aw_dm
    1200              :  real(dp) :: int_dfdw, dfdw
    1201              :  real(dp) :: vr(3), vv_tens(3,3), S(3,3), wtk!, spfunc
    1202              : ! real(dp), allocatable :: onsager_coeff(:,:)
    1203              :  real(dp) :: work_33(3,3)
    1204              :  real(dp) :: l0inv_33nw(3,3,2)
    1205              :  real(dp) :: l0inv_33nw_dm(3,3,2)
    1206              :  real(dp) :: Tkelv
    1207              : 
    1208              : !************************************************************************
    1209              : 
    1210            2 :  comm = self%comm
    1211            2 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
    1212              : 
    1213            2 :  call wrtout(std_out, " Computing conductivity using Kubo-Greenwood method.")
    1214            2 :  call cwtime(cpu_kloop, wall_kloop, gflops_kloop, "start")
    1215              : 
    1216              : 
    1217            6 :  ABI_MALLOC(kernel, (self%nwr))
    1218            4 :  ABI_MALLOC(kernel_dm, (self%nwr))
    1219              : ! ABI_MALLOC(test_Aw, (self%ntemp))
    1220              : ! ABI_MALLOC(test_dfdw, (self%ntemp))
    1221            4 :  ABI_MALLOC(Aw, (self%nwr))
    1222            4 :  ABI_MALLOC(Aw_dm, (self%nwr))
    1223            4 :  ABI_MALLOC(dfdw_acc, (self%nwr))
    1224            6 :  ABI_MALLOC(Aw_l0, (self%ntemp))
    1225            4 :  ABI_MALLOC(Aw_l0_dm, (self%ntemp))
    1226            4 :  ABI_MALLOC(dfdw_l0, (self%ntemp))
    1227              : 
    1228            6 :  ABI_MALLOC(gdm_vals, (self%nwr))
    1229              : 
    1230           64 :  ABI_CALLOC(self%l0, (3, 3, 2, self%nsppol, self%ntemp))
    1231           62 :  ABI_CALLOC(self%l1, (3, 3, 2, self%nsppol, self%ntemp))
    1232           62 :  ABI_CALLOC(self%l2, (3, 3, 2, self%nsppol, self%ntemp))
    1233           62 :  ABI_CALLOC(self%seebeck, (3, 3, 2, self%nsppol, self%ntemp))
    1234           62 :  ABI_CALLOC(self%kappa, (3, 3, 2, self%nsppol, self%ntemp))
    1235              : 
    1236           62 :  ABI_CALLOC(self%l0_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1237           62 :  ABI_CALLOC(self%l1_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1238           62 :  ABI_CALLOC(self%l2_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1239           62 :  ABI_CALLOC(self%seebeck_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1240           62 :  ABI_CALLOC(self%kappa_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1241              : 
    1242              : 
    1243           62 :  ABI_CALLOC(self%mobility_mu, (3, 3, 2, self%nsppol, self%ntemp))
    1244           62 :  ABI_CALLOC(self%conductivity_mu, (3, 3, 2, self%nsppol, self%ntemp))
    1245              : 
    1246           62 :  ABI_CALLOC(self%mobility_mu_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1247           62 :  ABI_CALLOC(self%conductivity_mu_dm, (3, 3, 2, self%nsppol, self%ntemp))
    1248              : 
    1249          280 :  ABI_CALLOC(self%print_dfdw, (self%nwr, self%ntemp))
    1250              : 
    1251            4 :  ABI_MALLOC(self%transport_mu_e, (self%ntemp))
    1252              : 
    1253           16 :  ABI_CALLOC(self%n_ehst, (2, self%nsppol, self%ntemp))
    1254              : 
    1255            2 :  self%transport_fermie = dtset%eph_fermie
    1256            2 :  self%transport_extrael = dtset%eph_extrael
    1257            6 :  self%transport_mu_e = self%mu_e
    1258            2 :  if (self%transport_fermie /= zero) self%transport_mu_e = self%transport_fermie
    1259              : 
    1260            2 :  if (self%transport_fermie == zero .and. self%transport_extrael /= self%eph_extrael) then
    1261              : 
    1262              :    if (self%transport_extrael /= self%eph_extrael) then
    1263              :      write(msg,'(2(a,e18.8),3a)') &
    1264            0 :        ' extrael from SIGEPH: ',self%transport_extrael, ' and input file: ',self%eph_extrael, "differ", ch10, &
    1265            0 :        ' Will recompute the chemical potential'
    1266            0 :      call wrtout(std_out, msg)
    1267              :    end if
    1268              : 
    1269              :    ! Compute Fermi level for different T values.
    1270            0 :    call self%ebands%get_muT_with_fd(self%ntemp, self%kTmesh, dtset%spinmagntarget, dtset%prtvol, self%transport_mu_e, comm)
    1271              :  end if
    1272              : 
    1273            2 :  call self%ebands%get_carriers(self%ntemp, self%kTmesh, self%transport_mu_e, self%n_ehst)
    1274              : 
    1275              : 
    1276            2 :  time_opt =0
    1277            2 :  cnt = 0
    1278            4 :  do my_spin=1,self%my_nspins
    1279            2 :    spin = self%my_spins(my_spin)
    1280           16 :    do my_ik=1,self%my_nkcalc
    1281           12 :      ikcalc= self%my_ikcalc(my_ik)
    1282              :      !if (ikcalc > 1) cycle
    1283           12 :      ik_ibz = self%kcalc2ibz(ikcalc, 1)
    1284           12 :      isym_k = self%kcalc2ibz(ikcalc, 2)
    1285           12 :      trev_k = self%kcalc2ibz(ikcalc, 6)
    1286              : 
    1287           12 :      wtk = self%ebands%wtk(ik_ibz)
    1288              :      ! TODO: this S is not used below - remove
    1289              :      S = transpose(cryst%symrel_cart(:,:,isym_k))
    1290              : 
    1291           12 :      nbands = self%nbcalc_ks(ikcalc, spin)
    1292           12 :      call cwtime(cpu, wall, gflops, "start")
    1293              :      !do ib=self%bmin,self%bmax
    1294           34 :      do ib=self%bstart_ks(ikcalc, spin),self%bstart_ks(ikcalc, spin)+self%nbcalc_ks(ikcalc, spin)-1
    1295              :        !if (ib > self%bmin) cycle ! MG HACK To be able to run tests quickly.
    1296              :        !ib_eph = ib - self%bmin + 1
    1297           20 :        ib_eph = ib - self%bstart_ks(ikcalc, spin) + 1
    1298           20 :        eig_nk = self%ebands%eig(ib, ik_ibz, spin)
    1299           20 :        wr_step = self%wrmesh_b(2,ib_eph,my_ik,spin) - self%wrmesh_b(1,ib_eph,my_ik,spin)
    1300           80 :        vr(:) = self%vbks(:, ib, ik_ibz, spin)
    1301              :        ! Store outer product (v_bks x v_bks) in vv_tens. This part does not depend on T and irta.
    1302           80 :        do ii=1,3
    1303          260 :          do jj=1,3
    1304          240 :            vv_tens(ii, jj) = vr(ii) * vr(jj)
    1305              :          end do
    1306              :        end do
    1307              :        ! Calculation of the velocity tensor
    1308          260 :        vv_tens = cryst%symmetrize_cart_tens33(vv_tens, time_opt)
    1309              : 
    1310              : ! temperature loop in Self Energy dependency
    1311           52 :        do itemp=1,self%ntemp
    1312              :      !if (itemp > 1) cycle
    1313              : 
    1314              : ! calculate Dyson Migdal Green's function as well, for comparison
    1315              :          gdm_vals(:) = one / (self%wrmesh_b(:,ib_eph,my_ik,spin) &
    1316              : &              - self%e0vals(ib_eph,my_ik,spin) - 0.5 * wr_step &
    1317         2720 : &              - self%vals_wr(:, itemp, ib_eph, my_ik, my_spin))
    1318              : 
    1319           20 :          Tkelv = self%kTmesh(itemp) / kb_HaK; if (Tkelv < one) Tkelv = one
    1320         2720 :          do iw=1, self%nwr
    1321              : !           if (mod(iw, self%wt_comm%nproc) /= self%wt_comm%me) cycle  ! MPI parallelism over freqs
    1322              : 
    1323              :               !  Preparing all elements needed for conductivity
    1324         2700 :               omega = self%wrmesh_b(iw,ib_eph,my_ik,my_spin)
    1325              : 
    1326              : ! this retrieves the Cumulant spectral function
    1327              : ! TODO: add the Dyson Migdal as well, to compare properly the transport with the same KG equation
    1328         2700 :               sp_func = -aimag (self%gw_vals(iw, itemp, ib_eph, my_ik, my_spin) ) / pi
    1329         2700 :               sp_func_dm = -aimag (gdm_vals(iw)) / pi
    1330              : 
    1331              : 
    1332         2700 :               self%spfunc_dm_wr(iw, itemp, ib_eph, my_ik, my_spin) = sp_func_dm
    1333              : 
    1334         2700 :               self%spfunc_wr(iw, itemp, ib_eph, my_ik, my_spin) = sp_func
    1335              : !              test_Aw(itemp) = test_Aw(itemp) + sp_func
    1336         2700 :               dfdw = occ_dfde(omega, self%kTmesh(itemp), self%mu_e(itemp))
    1337         2700 :               self%print_dfdw(iw,itemp) = dfdw
    1338              : !              test_dfdw(itemp) = test_dfdw(itemp) + dfdw
    1339         2700 :               kernel(iw) = - dfdw * sp_func**2
    1340         2700 :               kernel_dm(iw) = - dfdw * sp_func_dm**2
    1341         2700 :               Aw(iw) = sp_func**2
    1342         2700 :               Aw_dm(iw) = sp_func_dm**2
    1343         2720 :               dfdw_acc(iw) = dfdw
    1344              : 
    1345              :          end do !iw
    1346           20 :          mu_e = self%transport_mu_e(itemp)
    1347           20 :          ieh = 2; if (eig_nk >= mu_e) ieh = 1
    1348           20 :          integration = simpson( wr_step, kernel)
    1349           20 :          int_Aw = simpson(wr_step,Aw)
    1350           20 :          integration_dm = simpson( wr_step, kernel_dm)
    1351           20 :          int_Aw_dm = simpson(wr_step,Aw_dm)
    1352           20 :          int_dfdw = simpson(wr_step,dfdw_acc)
    1353              :          ! Calculation of the conductivity
    1354              :          self%l0( :, :, ieh, spin, itemp ) = self%l0( :, :, ieh, spin, itemp ) &
    1355          260 : &          + integration*vv_tens(:,:)*wtk
    1356              :          self%l0_dm( :, :, ieh, spin, itemp ) = self%l0_dm( :, :, ieh, spin, itemp ) &
    1357          260 : &          + integration_dm*vv_tens(:,:)*wtk
    1358              : 
    1359              : ! TODO: document this bit, why only use the xx component of vv_tens?? Aw_l0 is never used or output
    1360           20 :          Aw_l0(itemp) = Aw_l0(itemp) + int_Aw*wtk*vv_tens(1,1)
    1361           20 :          Aw_l0_dm(itemp) = Aw_l0_dm(itemp) + int_Aw_dm*wtk*vv_tens(1,1)
    1362           20 :          dfdw_l0(itemp) = dfdw_l0(itemp) + int_dfdw*wtk*vv_tens(1,1)
    1363              : ! END TODO
    1364              : 
    1365              : ! TODO : check these equations for l1 l2, they should not depend on the band indices, as we are inside the ib loop!!
    1366              :          self%l1( :, :, ieh, spin, itemp ) = self%l1( :, :, ieh, spin, itemp ) &
    1367          260 :              & + integration*vv_tens(:,:)*wtk*(eig_nk - self%mu_e(itemp))
    1368              :          self%l2( :, :, ieh, spin, itemp ) = self%l2( :, :, ieh, spin, itemp ) &
    1369          260 :              & + integration*vv_tens(:,:)*wtk*(eig_nk - self%mu_e(itemp))**2
    1370              :          self%l1_dm( :, :, ieh, spin, itemp ) = self%l1_dm( :, :, ieh, spin, itemp ) &
    1371          260 :              & + integration_dm*vv_tens(:,:)*wtk*(eig_nk - self%mu_e(itemp))
    1372              :          self%l2_dm( :, :, ieh, spin, itemp ) = self%l2_dm( :, :, ieh, spin, itemp ) &
    1373          280 :              & + integration_dm*vv_tens(:,:)*wtk*(eig_nk - self%mu_e(itemp))**2
    1374              : 
    1375              :        end do ! itemp
    1376              : 
    1377              :      end do !ib
    1378              : 
    1379              :    end do ! my_ik
    1380              : 
    1381              :  end do !my_spin
    1382              : 
    1383              :  ! Collect data if k-points parallelism. TODO: if this is reactivated, mpi_sum the l0 l1 l2 arrays instead
    1384              :  !call xmpi_sum(self%l0, self%kcalc_comm%value, ierr)
    1385              :  !call xmpi_sum(self%l1, self%kcalc_comm%value, ierr)
    1386              :  !call xmpi_sum(self%l2, self%kcalc_comm%value, ierr)
    1387              : 
    1388            4 :  do itemp = 1, self%ntemp
    1389            2 :    Tkelv = self%kTmesh(itemp) / kb_HaK; if (Tkelv < one) Tkelv = one
    1390            6 :    do my_spin=1,self%my_nspins
    1391            2 :      spin = self%my_spins(my_spin)
    1392            8 :      do ieh = 1, 2
    1393              :        ! calculate the transport coefficients from the l0 l1 l2
    1394            4 :        call inv33(self%l0(:, :, ieh, spin, itemp), l0inv_33nw(:,:,ieh))
    1395          580 :        self%seebeck(:,:,ieh,spin,itemp) = matmul(l0inv_33nw(:,:,ieh), self%l1(:,:,ieh,spin,itemp)) / Tkelv
    1396              : 
    1397            4 :        call inv33(self%l0_dm(:, :, ieh, spin, itemp), l0inv_33nw_dm(:,:,ieh))
    1398          580 :        self%seebeck_dm(:,:,ieh,spin,itemp) = matmul(l0inv_33nw_dm(:,:,ieh), self%l1_dm(:,:,ieh,spin,itemp)) / Tkelv
    1399              : 
    1400           52 :        work_33 = self%l1(:, :, ieh, spin, itemp)
    1401              :        ! TODO: check if one of the work_33 below is incorrect or needs a transpose
    1402          364 :        work_33 = self%l2(:, :, ieh, spin, itemp) - matmul(work_33, matmul(l0inv_33nw(:, :, ieh), work_33))
    1403           52 :        self%kappa(:,:,ieh,spin,itemp) = work_33 / Tkelv
    1404              : 
    1405           52 :        work_33 = self%l1_dm(:, :, ieh, spin, itemp)
    1406          364 :        work_33 = self%l2_dm(:, :, ieh, spin, itemp) - matmul(work_33, matmul(l0inv_33nw_dm(:, :, ieh), work_33))
    1407           54 :        self%kappa_dm(:,:,ieh,spin,itemp) = work_33 / Tkelv
    1408              : 
    1409              :        !TODO: leftover below - can this be removed?
    1410              :        !self%conductivity_mu( :, :, ieh, spin, itemp ) = self%conductivity_mu( :, :, ieh, spin, itemp ) + integration*vv_tens(:,:)*wtk
    1411              :      end do ! ieh
    1412              :    end do !my_spin
    1413              :  end do ! itemp
    1414              : 
    1415            2 :  max_occ = two / (self%nspinor * self%nsppol)
    1416            2 :  fact0 = max_occ * (siemens_SI / Bohr_meter / cryst%ucvol) / 100
    1417           60 :  self%conductivity_mu = fact0 * self%l0  ! siemens cm^-1
    1418           58 :  self%seebeck = - volt_SI  * max_occ * self%seebeck
    1419           58 :  self%kappa = + volt_SI**2 * fact0 * self%kappa
    1420              : 
    1421           60 :  self%conductivity_mu_dm = fact0 * self%l0_dm  ! siemens cm^-1
    1422           58 :  self%seebeck_dm = - volt_SI  * max_occ * self%seebeck_dm
    1423           58 :  self%kappa_dm = + volt_SI**2 * fact0 * self%kappa_dm
    1424              : 
    1425              :  ! Scale by the carrier concentration
    1426            2 :  fact = 100**3 / e_Cb
    1427            4 :  do my_spin=1,self%my_nspins
    1428            2 :    spin = self%my_spins(my_spin)
    1429            6 :      do itemp=1,self%ntemp
    1430            8 :        do ieh=1,2 ! e/h
    1431              :          call safe_div(fact * self%conductivity_mu(:,:,ieh,spin,itemp), &
    1432              :                        self%n_ehst(ieh, spin, itemp) / cryst%ucvol / Bohr_meter**3, zero, &
    1433           52 :                        self%mobility_mu(:,:,ieh,spin,itemp))
    1434              :          call safe_div(fact * self%conductivity_mu_dm(:,:,ieh,spin,itemp), &
    1435              :                        self%n_ehst(ieh, spin, itemp) / cryst%ucvol / Bohr_meter**3, zero, &
    1436           54 :                        self%mobility_mu_dm(:,:,ieh,spin,itemp))
    1437              :        end do
    1438              :      end do
    1439              :    end do
    1440              : 
    1441              : 
    1442            2 :  call cwtime_report(" cumulant_kubo_transport", cpu_kloop, wall_kloop, gflops_kloop)
    1443              : 
    1444            2 :  ABI_SFREE(kernel)
    1445            2 :  ABI_SFREE(kernel_dm)
    1446              : ! ABI_SFREE(test_Aw)
    1447              : ! ABI_SFREE(test_dfdw)
    1448            2 :  ABI_SFREE(Aw)
    1449            2 :  ABI_SFREE(Aw_dm)
    1450            2 :  ABI_SFREE(dfdw_acc)
    1451            2 :  ABI_SFREE(Aw_l0)
    1452            2 :  ABI_SFREE(Aw_l0_dm)
    1453            2 :  ABI_SFREE(dfdw_l0)
    1454            2 :  ABI_SFREE(gdm_vals)
    1455              : 
    1456            6 : end subroutine cumulant_kubo_transport
    1457              : 
    1458              : !!***
    1459              : 
    1460              : !----------------------------------------------------------------------
    1461              : 
    1462              : !!****f* m_cumulant/cumulant_sigmaph_ncread
    1463              : !! NAME
    1464              : !! cumulant_sigmaph_ncread
    1465              : !!
    1466              : !! FUNCTION
    1467              : !!   read out_SIGPH.nc file
    1468              : !!
    1469              : !! INPUTS
    1470              : !! cryst<crystal_t>=Crystalline structure
    1471              : !! dtset<dataset_type>=All input variables for this dataset.
    1472              : !! ncid=Netcdf file handle.
    1473              : !!
    1474              : !! SOURCE
    1475              : 
    1476            2 : subroutine cumulant_sigmaph_ncread(self, path, ncid, comm)
    1477              : 
    1478              : !Arguments --------------------------------------
    1479              :  class(cumulant_t),intent(inout) :: self
    1480              :  character(len=fnlen),intent(in) :: path
    1481              :  integer,intent(in) :: comm
    1482              :  integer,intent(out) :: ncid
    1483              : 
    1484              : !Local variables --------------------------------
    1485              :  integer :: ierr
    1486              :  real(dp) :: cpu, wall, gflops
    1487              :  character(len=1000) :: msg
    1488              :  !real(dp), allocatable :: vals_wr(:,:,:,:,:,:),vals_e0ks(:,:,:,:,:)
    1489              : 
    1490              : !************************************************************************
    1491              : 
    1492            2 :  call cwtime(cpu, wall, gflops, "start")
    1493              : 
    1494              :  ! Open netcdf file
    1495            2 :  ierr = 0
    1496              : 
    1497            2 :  if (.not. file_exists(path)) then
    1498            0 :    msg = sjoin("Cannot find file", path)
    1499            0 :    ierr = 1; return
    1500              :  end if
    1501              : 
    1502            2 :  call cwtime(cpu, wall, gflops, "start")
    1503            2 :  NCF_CHECK(nctk_open_read(ncid, path, comm))
    1504              : 
    1505            2 :  NCF_CHECK(nctk_get_dim(ncid, "nkcalc", self%nkcalc))
    1506            2 :  NCF_CHECK(nctk_get_dim(ncid, "max_nbcalc", self%max_nbcalc))
    1507            2 :  NCF_CHECK(nctk_get_dim(ncid, "nsppol", self%nsppol))
    1508            2 :  NCF_CHECK(nctk_get_dim(ncid, "number_of_spinor_components", self%nspinor))
    1509            2 :  NCF_CHECK(nctk_get_dim(ncid, "ntemp", self%ntemp))
    1510            2 :  NCF_CHECK(nctk_get_dim(ncid, "nwr", self%nwr))
    1511            2 :  NCF_CHECK(nctk_get_dim(ncid, "nqbz", self%nqbz))
    1512            2 :  NCF_CHECK(nctk_get_dim(ncid, "nqibz", self%nqibz))
    1513            2 :  NCF_CHECK(nctk_get_dim(ncid, "natom3", self%natom3))
    1514              : 
    1515            6 :  ABI_MALLOC(self%kcalc, (3, self%nkcalc))
    1516            8 :  ABI_MALLOC(self%nbcalc_ks, (self%nkcalc, self%nsppol))
    1517            6 :  ABI_MALLOC(self%bstart_ks, (self%nkcalc, self%nsppol))
    1518            6 :  ABI_MALLOC(self%kcalc2ibz, (self%nkcalc, 6))
    1519            6 :  ABI_MALLOC(self%kTmesh, (self%ntemp))
    1520              :  !ABI_MALLOC(self%wrmesh_b, (self%nwr, self%max_nbcalc, self%nkcalc, self%nsppol))
    1521              :  !ABI_MALLOC(self%vals_wr, ( self%nwr, self%ntemp, self%max_nbcalc, self%nkcalc, self%nsppol))
    1522              :  !ABI_MALLOC(self%vals_e0ks, ( self%ntemp, self%max_nbcalc, self%nkcalc, self%nsppol))
    1523              :  !ABI_MALLOC(self%e0vals, (self%max_nbcalc, self%nkcalc, self%nsppol))
    1524            2 :  NCF_CHECK(nf90_get_var(ncid, vid("ngqpt"), self%ngqpt))
    1525            2 :  NCF_CHECK(nf90_get_var(ncid, vid("kcalc"), self%kcalc))
    1526            2 :  NCF_CHECK(nf90_get_var(ncid, vid("kTmesh"), self%kTmesh))
    1527            2 :  NCF_CHECK(nf90_get_var(ncid, vid("nbcalc_ks"), self%nbcalc_ks))
    1528            2 :  NCF_CHECK(nf90_get_var(ncid, vid("bstart_ks"), self%bstart_ks))
    1529            2 :  NCF_CHECK(nf90_get_var(ncid, vid("kcalc2ibz"), self%kcalc2ibz))
    1530              : 
    1531            6 :  call cwtime_report(" sigmaph_ncread", cpu, wall, gflops)
    1532              : 
    1533              : contains
    1534           12 :  integer function vid(vname)
    1535              :    character(len=*),intent(in) :: vname
    1536           12 :    vid = nctk_idname(ncid, vname)
    1537              : end function vid
    1538              : 
    1539              : end subroutine cumulant_sigmaph_ncread
    1540              : !!***
    1541              : 
    1542              : !----------------------------------------------------------------------
    1543              : 
    1544              : !!****f* m_cumulant/cumulant_ncwrite
    1545              : !! NAME
    1546              : !! cumulant_ncwrite
    1547              : !!
    1548              : !! FUNCTION
    1549              : !!
    1550              : !! INPUTS
    1551              : !! path=Filenae of output netcdf file.
    1552              : !! cryst<crystal_t>=Crystalline structure
    1553              : !! dtset<dataset_type>=All input variables for this dataset.
    1554              : !! ncid=Netcdf file handle.
    1555              : !!
    1556              : !! SOURCE
    1557              : 
    1558              : !subroutine cumulant_ncwrite(self, path, cryst, ebands, dtset)
    1559            6 : subroutine cumulant_ncwrite(self, path, cryst, dtset)
    1560              : 
    1561              : !Arguments --------------------------------------
    1562              :  class(cumulant_t),intent(in) :: self
    1563              :  type(crystal_t),intent(in) :: cryst
    1564              : ! type(ebands_t),intent(in) :: ebands
    1565              :  type(dataset_type),intent(in) :: dtset
    1566              :  character(len=*),intent(in) :: path
    1567              : 
    1568              : !Local variables --------------------------------
    1569              :  integer,parameter :: master = 0
    1570              :  integer :: ncerr, ncid, ikcalc, spin, my_ik, ib, itemp, ntemp
    1571              :  integer :: ii, ieh
    1572              :  real(dp) :: cpu, wall, gflops
    1573              :  character(len=1000) :: msg
    1574              : 
    1575              : !************************************************************************
    1576              : 
    1577              :  !comm = self%comm my_rank =
    1578            6 :  call wrtout([std_out, ab_out], ch10//sjoin("- Writing cumulant results to:", path))
    1579            2 :  call cwtime(cpu, wall, gflops, "start")
    1580              : 
    1581              :  ! Only one proc create the file, write structure and define basic dimensions.
    1582              :  ! Then we reopen the file in MPI-IO mode.
    1583              : 
    1584            2 :  if (xmpi_comm_rank(self%comm) == master) then
    1585              : 
    1586            2 :    NCF_CHECK(nctk_open_create(ncid, path, xmpi_comm_self))
    1587              : 
    1588              :    ! Write to netcdf file
    1589            2 :    NCF_CHECK(cryst%ncwrite(ncid))
    1590              :    ! FIXME: Cannot write ebands because it crashes in
    1591              :    !   k_dependent = "no"; if (any(ebands%nband(1) /= ebands%nband)) k_dependent = "yes"
    1592              :    ! Should understand why!
    1593              :    !NCF_CHECK(ebands_ncwrite(ebands, ncid))
    1594              : 
    1595              :    ! Add cumulant dimensions.
    1596              :    ncerr = nctk_def_dims(ncid, [ &
    1597              :      nctkdim_t("nkcalc", self%nkcalc), nctkdim_t("max_nbcalc", self%max_nbcalc), &
    1598              :      nctkdim_t("nsppol", self%nsppol), nctkdim_t("ntemp", self%ntemp), &
    1599              :      nctkdim_t("nqbz", self%nsppol), nctkdim_t("nqibz", self%ntemp), &
    1600              :      nctkdim_t("nwr", self%nwr)], &
    1601           16 :      defmode=.True.)
    1602            2 :    NCF_CHECK(ncerr)
    1603              :    ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
    1604              :      "eph_task",  "nbsum", "bsum_start", "bsum_stop", "symdynmat", &
    1605              :      "ph_intmeth", "eph_intmeth", "qint_method", "eph_transport", &
    1606           30 :      "imag_only", "symv1scf", "dvdb_add_lr", "mrta", "ibte_prep"])
    1607            2 :    NCF_CHECK(ncerr)
    1608              :    ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
    1609           20 :      "eta", "wr_step", "eph_fsewin", "eph_fsmear", "eph_extrael", "eph_fermie", "ph_wstep", "ph_smear", "eph_phwinfact"])
    1610            2 :    NCF_CHECK(ncerr)
    1611              : 
    1612              : 
    1613              :    ! Define arrays. Note nkcalc instead of my_nkcalc
    1614              :    ncerr = nctk_def_arrays(ncid, [ &
    1615              :      nctkarr_t("bstart_ks", "int", "nkcalc, nsppol"), &
    1616              :      nctkarr_t("nbcalc_ks", "int", "nkcalc, nsppol"), &
    1617              :      nctkarr_t("ngqpt", "dp", "three"), &
    1618              :      nctkarr_t("kcalc", "dp", "three, nkcalc"), &
    1619              :      nctkarr_t("kcalc2ibz", "dp", " nkcalc, six"), &
    1620              :      nctkarr_t("kTmesh", "dp", "ntemp"), &
    1621              :      !nctkarr_t("mu_e", "dp", "ntemp"), &
    1622              :      nctkarr_t("wrmesh_b", "dp", "nwr, max_nbcalc, nkcalc, nsppol"), &
    1623              :      !nctkarr_t("vals_wr", "dp", "two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1624              :      nctkarr_t("gw_vals", "dp", "two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1625              :      nctkarr_t("ks_enes", "dp", "max_nbcalc, nkcalc, nsppol"), &
    1626              :      nctkarr_t("dw_vals", "dp", "ntemp, max_nbcalc, nkcalc, nsppol"), &
    1627              :      nctkarr_t("spfunc_dm_wr", "dp", "nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1628              :      nctkarr_t("spfunc_wr", "dp", "nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1629              :      nctkarr_t('dfdw',"dp", "nwr, ntemp"), &
    1630              :      nctkarr_t('conductivity_mu',"dp", "three, three, two, nsppol, ntemp"), &
    1631              :      nctkarr_t('conductivity_mu_dm',"dp", "three, three, two, nsppol, ntemp"), &
    1632              :      nctkarr_t('mobility_mu', "dp", "three, three, two, nsppol, ntemp"), &
    1633              :      nctkarr_t('mobility_mu_dm', "dp", "three, three, two, nsppol, ntemp"), &
    1634              :      nctkarr_t('seebeck',"dp", "three, three, two, nsppol, ntemp"), &
    1635              :      nctkarr_t('seebeck_dm',"dp", "three, three, two, nsppol, ntemp"), &
    1636              :      nctkarr_t('kappa',"dp", "three, three, two, nsppol, ntemp"), &
    1637              :      nctkarr_t('kappa_dm',"dp", "three, three, two, nsppol, ntemp") &
    1638           44 :    ])
    1639            2 :    NCF_CHECK(ncerr)
    1640              : 
    1641            2 :    if (self%debug == 1) then
    1642              :      ncerr = nctk_def_arrays(ncid, [ &
    1643              :      nctkarr_t("time_mesh", "dp", "nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1644              :      nctkarr_t("ct_vals", "dp","two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1645              :      nctkarr_t("c1", "dp","two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1646              :      nctkarr_t("c2", "dp","two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1647              :      nctkarr_t("c3", "dp","two, nwr, ntemp, max_nbcalc, nkcalc, nsppol"), &
    1648            0 :      nctkarr_t("gt_vals", "dp","two, nwr, ntemp, max_nbcalc, nkcalc, nsppol") ] )
    1649            0 :      NCF_CHECK(ncerr)
    1650              :    endif
    1651              : 
    1652              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "eta"), self%ieta))
    1653            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "nbsum"), self%nbsum))
    1654            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngqpt"), self%ngqpt))
    1655            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kcalc"), self%kcalc))
    1656            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kTmesh"), self%kTmesh))
    1657            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "nbcalc_ks"), self%nbcalc_ks))
    1658            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "bstart_ks"), self%bstart_ks))
    1659            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kcalc2ibz"), self%kcalc2ibz))
    1660            2 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "dfdw"), self%print_dfdw))
    1661              :    ! FIXME This part is wrong since these arrays are MPI distributed
    1662              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "conductivity_mu"), self%conductivity_mu))
    1663              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "mobility_mu"), self%mobility_mu))
    1664              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "seebeck"), self%seebeck))
    1665              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kappa"), self%kappa))
    1666              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "wrmesh_b"), self%wrmesh_b))
    1667              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vals_wr"), c2r(self%vals_wr)))
    1668              :    !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ks_enes"), self%e0vals))
    1669              : 
    1670            2 :    NCF_CHECK(nf90_close(ncid))
    1671              :  end if ! master
    1672              : 
    1673              :  ! Barrier to avoid race conditions.
    1674              :  !call wrtout(std_out, "before barrier")
    1675            2 :  call xmpi_barrier(self%comm)
    1676              : 
    1677              :  ! Only the procs in the ncwrite_comm communicator write to disk.
    1678            2 :  if (self%ncwrite_comm%value == xmpi_comm_null) goto 100
    1679              : 
    1680              :  ! open file for parallel-IO mode inside comm. All procs in ncwrite_comm enter this part.
    1681            2 :  call wrtout(std_out, sjoin(" Performing parallel IO with:", itoa(self%ncwrite_comm%nproc), "procs"))
    1682            2 :  NCF_CHECK(nctk_open_modify(ncid, path, self%ncwrite_comm%value))
    1683              : 
    1684            2 :  NCF_CHECK(nctk_set_datamode(ncid))
    1685              : 
    1686              :  ! Activate collectve IO.
    1687            2 :  ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "gw_vals"), nf90_collective)
    1688            2 :  NCF_CHECK(ncerr)
    1689              : 
    1690            2 :  ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "wrmesh_b"), nf90_collective)
    1691            2 :  NCF_CHECK(ncerr)
    1692              : 
    1693            2 :  ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "ks_enes"), nf90_collective)
    1694            2 :  NCF_CHECK(ncerr)
    1695              : 
    1696            2 :  ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "dw_vals"), nf90_collective)
    1697            2 :  NCF_CHECK(ncerr)
    1698              : 
    1699            2 :  ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "spfunc_dm_wr"), nf90_collective)
    1700            2 :  NCF_CHECK(ncerr)
    1701              : 
    1702            2 :  ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "spfunc_wr"), nf90_collective)
    1703            2 :  NCF_CHECK(ncerr)
    1704              : 
    1705            3 :  if (any(abs(dtset%sigma_erange) > zero)) then
    1706            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "dfdw"), nf90_collective)
    1707            2 :    NCF_CHECK(ncerr)
    1708              : 
    1709            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "conductivity_mu"), nf90_collective)
    1710            2 :    NCF_CHECK(ncerr)
    1711              : 
    1712            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "mobility_mu"), nf90_collective)
    1713            2 :    NCF_CHECK(ncerr)
    1714              : 
    1715            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "seebeck"), nf90_collective)
    1716            2 :    NCF_CHECK(ncerr)
    1717              : 
    1718            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "kappa"), nf90_collective)
    1719            2 :    NCF_CHECK(ncerr)
    1720              : 
    1721            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "conductivity_mu_dm"), nf90_collective)
    1722            2 :    NCF_CHECK(ncerr)
    1723              : 
    1724            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "mobility_mu_dm"), nf90_collective)
    1725            2 :    NCF_CHECK(ncerr)
    1726              : 
    1727            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "seebeck_dm"), nf90_collective)
    1728            2 :    NCF_CHECK(ncerr)
    1729              : 
    1730            2 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "kappa_dm"), nf90_collective)
    1731            2 :    NCF_CHECK(ncerr)
    1732              : 
    1733              : 
    1734              :  end if
    1735              : 
    1736            2 :  if (self%debug == 1) then
    1737            0 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "time_mesh"), nf90_collective)
    1738            0 :    NCF_CHECK(ncerr)
    1739              : 
    1740            0 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "ct_vals"), nf90_collective)
    1741            0 :    NCF_CHECK(ncerr)
    1742              : 
    1743            0 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "c1"), nf90_collective)
    1744            0 :    NCF_CHECK(ncerr)
    1745              : 
    1746            0 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "c2"), nf90_collective)
    1747            0 :    NCF_CHECK(ncerr)
    1748              : 
    1749            0 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "c3"), nf90_collective)
    1750            0 :    NCF_CHECK(ncerr)
    1751              : 
    1752            0 :    ncerr = nf90_var_par_access(ncid, nctk_idname(ncid, "gt_vals"), nf90_collective)
    1753            0 :    NCF_CHECK(ncerr)
    1754              :  endif
    1755            2 :  spin = self%my_spins(1)
    1756            2 :  ikcalc = self%my_ikcalc(1) ! index of the first kcalc treated by this rank.
    1757              : 
    1758              :  ! Start to write my **contiguous block** of kpoints from this **global** location
    1759              :  ! Each MPI proc writes my_nkcalc entries.
    1760              : 
    1761              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "gw_vals"), c2r(self%gw_vals), &
    1762              :                       start=[1,1,1,1,ikcalc,spin], &
    1763           26 :                       count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1764            2 :  NCF_CHECK(ncerr)
    1765              : 
    1766              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "wrmesh_b"), self%wrmesh_b, &
    1767              :                       start=[1,1,ikcalc,spin], &
    1768           18 :                       count=[self%nwr, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1769            2 :  NCF_CHECK(ncerr)
    1770              : 
    1771              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "ks_enes"), self%e0vals, &
    1772              :                       start=[1,ikcalc,spin], &
    1773           14 :                       count=[self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1774            2 :  NCF_CHECK(ncerr)
    1775              : 
    1776              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "dw_vals"), self%dw_vals, &
    1777              :                       start=[1,1,ikcalc,spin], &
    1778           18 :                       count=[self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1779            2 :  NCF_CHECK(ncerr)
    1780              : 
    1781              : !DEBUG STUFF MJV
    1782              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "spfunc_dm_wr"), self%spfunc_dm_wr, &
    1783              :                       start=[1,1,1,ikcalc,spin], &
    1784           22 :                       count=[self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1785            2 :  NCF_CHECK(ncerr)
    1786              : 
    1787              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "spfunc_wr"), self%spfunc_wr, &
    1788              :                       start=[1,1,1,ikcalc,spin], &
    1789           22 :                       count=[self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1790            2 :  NCF_CHECK(ncerr)
    1791              : 
    1792              : 
    1793            3 :  if (any(abs(dtset%sigma_erange) > zero)) then
    1794              : 
    1795              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "seebeck"), self%seebeck, &
    1796              :                       start=[1,1,1,spin,1], &
    1797           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1798            2 :  NCF_CHECK(ncerr)
    1799              : 
    1800              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "kappa"), self%kappa, &
    1801              :                       start=[1,1,1,spin,1], &
    1802           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1803            2 :  NCF_CHECK(ncerr)
    1804              : 
    1805              : 
    1806              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "mobility_mu"), self%mobility_mu, &
    1807              :                       start=[1,1,1,spin,1], &
    1808           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1809            2 :  NCF_CHECK(ncerr)
    1810              : 
    1811              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "conductivity_mu"), self%conductivity_mu, &
    1812              :                       start=[1,1,1,spin,1], &
    1813           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1814            2 :  NCF_CHECK(ncerr)
    1815              : 
    1816              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "seebeck_dm"), self%seebeck_dm, &
    1817              :                       start=[1,1,1,spin,1], &
    1818           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1819            2 :  NCF_CHECK(ncerr)
    1820              : 
    1821              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "kappa_dm"), self%kappa_dm, &
    1822              :                       start=[1,1,1,spin,1], &
    1823           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1824            2 :  NCF_CHECK(ncerr)
    1825              : 
    1826              : 
    1827              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "mobility_mu_dm"), self%mobility_mu_dm, &
    1828              :                       start=[1,1,1,spin,1], &
    1829           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1830            2 :  NCF_CHECK(ncerr)
    1831              : 
    1832              :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, "conductivity_mu_dm"), self%conductivity_mu_dm, &
    1833              :                       start=[1,1,1,spin,1], &
    1834           22 :                       count=[3, 3, 2, self%my_nspins , self%ntemp])
    1835            2 :  NCF_CHECK(ncerr)
    1836              : 
    1837              :  end if
    1838              : 
    1839              : 
    1840            2 :  if (self%debug == 1) then
    1841              : 
    1842              :    ncerr = nf90_put_var(ncid, nctk_idname(ncid, "time_mesh"), self%time_mesh, &
    1843              :                         start=[1,1,1,ikcalc,spin], &
    1844            0 :                         count=[self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1845            0 :    NCF_CHECK(ncerr)
    1846              : 
    1847              :    ncerr = nf90_put_var(ncid, nctk_idname(ncid, "ct_vals"), c2r(self%ct_vals), &
    1848              :                         start=[1,1,1,1,ikcalc,spin], &
    1849            0 :                         count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1850            0 :    NCF_CHECK(ncerr)
    1851              : 
    1852              :    ncerr = nf90_put_var(ncid, nctk_idname(ncid, "c1"), c2r(self%c1), &
    1853              :                         start=[1,1,1,1,ikcalc,spin], &
    1854            0 :                         count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1855            0 :    NCF_CHECK(ncerr)
    1856              : 
    1857              :    ncerr = nf90_put_var(ncid, nctk_idname(ncid, "c2"), c2r(self%c2), &
    1858              :                         start=[1,1,1,1,ikcalc,spin], &
    1859            0 :                         count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1860            0 :    NCF_CHECK(ncerr)
    1861              : 
    1862              :    ncerr = nf90_put_var(ncid, nctk_idname(ncid, "c3"), c2r(self%c3), &
    1863              :                         start=[1,1,1,1,ikcalc,spin], &
    1864            0 :                         count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1865            0 :    NCF_CHECK(ncerr)
    1866              : 
    1867              :    ncerr = nf90_put_var(ncid, nctk_idname(ncid, "gt_vals"), c2r(self%gt_vals), &
    1868              :                         start=[1,1,1,1,ikcalc,spin], &
    1869            0 :                         count=[2, self%nwr, self%ntemp, self%max_nbcalc, self%my_nkcalc, self%my_nspins])
    1870            0 :    NCF_CHECK(ncerr)
    1871              :  endif
    1872              : 
    1873            2 :  NCF_CHECK(nf90_close(ncid))
    1874              : 
    1875              :  ! Write to ab_out for automatic testing.
    1876            2 :  if (xmpi_comm_rank(self%comm) == master .and. is_open(ab_out)) then
    1877            2 :    write(ab_out, "(/,a)")" Print first 10 frequencies in gw_vals array (re-im) for testing purposes:"
    1878            2 :    write(ab_out, "(2(a, i0))")" spin: ", spin, ", ikcalc: ", ikcalc
    1879            2 :    my_ik = 1
    1880            7 :    do ib=1,self%nbcalc_ks(ikcalc, spin)
    1881           12 :      do itemp=1,self%ntemp
    1882            5 :        write(ab_out, "(2(a,i0))")" gw_vals for itemp:", itemp, "ib: ", ib
    1883           55 :        write(ab_out, "(*(es13.5))")dble(self%gw_vals(1:min(10, self%nwr), itemp, ib, my_ik, spin))
    1884           60 :        write(ab_out, "(*(es13.5))")aimag(self%gw_vals(1:min(10, self%nwr), itemp, ib, my_ik, spin))
    1885              :      end do
    1886              :   end do
    1887              :  end if
    1888            3 :  if (xmpi_comm_rank(self%comm) == master .and. is_open(ab_out) .and. any(abs(dtset%sigma_erange) > zero)) then
    1889              :    msg = sjoin(" Print first 5 temperatures of diagonal mobility_mu", &
    1890            2 :                " > 1e-6 (with ieh as electrons or holes) for testing purposes:")
    1891            2 :    write(ab_out, "(/,a)") trim(msg)
    1892            2 :    write(ab_out, "(2(a, i0))")" spin: ", spin
    1893            2 :    if (self%ntemp > 5) then
    1894              :      ntemp = 5
    1895              :    else
    1896              :      ntemp = self%ntemp
    1897              :    end if
    1898            6 :    do ieh=1,2
    1899           18 :      do ii=1,3
    1900           28 :        do itemp=1,ntemp
    1901           24 :          if (dble(self%mobility_mu(ii, ii, ieh, spin, itemp)) > 1e-6) then
    1902            6 :            write(ab_out, "(3(a,i0))")" mobility_mu for itemp:", itemp, " ieh: ", ieh, " xyz: ", ii
    1903            6 :            write(ab_out, "(*(es13.5))")dble(self%mobility_mu(ii, ii, ieh, spin, itemp))
    1904              :          end if
    1905              :        end do
    1906              :      end do
    1907              :    end do
    1908              :  end if
    1909              : 
    1910              : 
    1911            2 :  100 call cwtime_report(" cumulant_ncwrite", cpu, wall, gflops)
    1912              : 
    1913            2 : end subroutine cumulant_ncwrite
    1914              : !!***
    1915              : 
    1916              : !----------------------------------------------------------------------
    1917              : 
    1918              : !!****f* m_cumulant/cumulant_free
    1919              : !! NAME
    1920              : !! cumulant_free
    1921              : !!
    1922              : !! FUNCTION
    1923              : !!  Free dynamic memory.
    1924              : !!
    1925              : !! INPUTS
    1926              : !!
    1927              : !! SOURCE
    1928              : 
    1929            2 : subroutine cumulant_free(self)
    1930              : 
    1931              : !Arguments --------------------------------------
    1932              :  class(cumulant_t),intent(inout) :: self
    1933              : 
    1934              : !************************************************************************
    1935              : 
    1936            2 :  ABI_SFREE(self%kcalc2ebands)
    1937            2 :  ABI_SFREE(self%linewidths)
    1938            2 :  ABI_SFREE(self%vbks)
    1939            2 :  ABI_SFREE(self%nbcalc_ks)
    1940            2 :  ABI_SFREE(self%bstart_ks)
    1941              :  !ABI_SFREE(self%bstop_ks)
    1942            2 :  ABI_SFREE(self%kcalc2ibz)
    1943            2 :  ABI_SFREE(self%coords_kws)
    1944            2 :  ABI_SFREE(self%my_spins)
    1945            2 :  ABI_SFREE(self%my_ikcalc)
    1946            2 :  ABI_SFREE(self%e0vals)
    1947            2 :  ABI_SFREE(self%dw_vals)
    1948            2 :  ABI_SFREE(self%gw_vals)
    1949              :  !ABI_SFREE(self%ce_spfunc_wr)
    1950            2 :  ABI_SFREE(self%spfunc_dm_wr)
    1951            2 :  ABI_SFREE(self%spfunc_wr)
    1952            2 :  ABI_SFREE(self%conductivity_mu)
    1953            2 :  ABI_SFREE(self%conductivity_mu_dm)
    1954            2 :  ABI_SFREE(self%mobility_mu)
    1955            2 :  ABI_SFREE(self%mobility_mu_dm)
    1956            2 :  ABI_SFREE(self%transport_mu_e)
    1957            2 :  ABI_SFREE(self%print_dfdw)
    1958            2 :  ABI_SFREE(self%seebeck)
    1959            2 :  ABI_SFREE(self%seebeck_dm)
    1960            2 :  ABI_SFREE(self%kappa)
    1961            2 :  ABI_SFREE(self%kappa_dm)
    1962            2 :  ABI_SFREE(self%l0)
    1963            2 :  ABI_SFREE(self%l0_dm)
    1964            2 :  ABI_SFREE(self%l1)
    1965            2 :  ABI_SFREE(self%l1_dm)
    1966            2 :  ABI_SFREE(self%l2)
    1967            2 :  ABI_SFREE(self%l2_dm)
    1968            2 :  ABI_SFREE(self%time_mesh)
    1969            2 :  ABI_SFREE(self%ct_vals)
    1970            2 :  ABI_SFREE(self%c1)
    1971            2 :  ABI_SFREE(self%c2)
    1972            2 :  ABI_SFREE(self%c3)
    1973            2 :  ABI_SFREE(self%gt_vals)
    1974            2 :  ABI_SFREE(self%wrmesh_b)
    1975            2 :  ABI_SFREE(self%wrmesh_ce)
    1976            2 :  ABI_SFREE(self%vals_e0ks)
    1977            2 :  ABI_SFREE(self%vals_wr)
    1978            2 :  ABI_SFREE(self%kcalc)
    1979            2 :  ABI_SFREE(self%kTmesh)
    1980            2 :  ABI_SFREE(self%mu_e)
    1981            2 :  ABI_SFREE(self%n_ehst)
    1982              : 
    1983            2 :  call destroy_mpi_enreg(self%ce_mpi_enreg)
    1984            2 :  call self%ebands%free()
    1985            2 :  call self%spin_comm%free()
    1986            2 :  call self%kcalc_comm%free()
    1987            2 :  call self%wt_comm%free()
    1988            2 :  call self%ncwrite_comm%free()
    1989              : 
    1990            2 : end subroutine cumulant_free
    1991              : !!***
    1992              : 
    1993              : 
    1994              : integer function gcd(m, n) result(answer)
    1995              :  ! The greatest common divisor (GCD) of two nonzero integers
    1996              :  ! i.e. the largest positive integer that divides each of the integers.
    1997              :  ! gcd(a, 0) = gcd(0, a) = |a|
    1998              :  ! gcd(0, 0) is commonly defined as 0.
    1999              : 
    2000              :  integer,intent(in)  :: m, n
    2001              :  integer :: irest,ifirst
    2002              : 
    2003              :  ifirst = iabs(m)
    2004              :  answer = iabs(n)
    2005              :  if (answer ==  0) then
    2006              :     answer = ifirst
    2007              :  else
    2008              :     do
    2009              :        irest = mod(ifirst,answer)
    2010              :        if (irest == 0)  exit
    2011              :        ifirst = answer
    2012              :        answer = irest
    2013              :     end do
    2014              :     answer= iabs(answer)
    2015              :  end if
    2016              : 
    2017              : end function gcd
    2018              : 
    2019              : integer function lcm(a, b)
    2020              :  integer,intent(in) :: a, b
    2021              :  lcm = iabs(a * b) / gcd(a,b)
    2022              : end function lcm
    2023              : !
    2024              : !integer function gcd(a,b)
    2025              : ! integer :: a,b,t
    2026              : ! do while (b/=0)
    2027              : !     t = b
    2028              : !     b = mod(a,b)
    2029              : !     a = t
    2030              : ! end do
    2031              : ! gcd = abs(a)
    2032              : !end function gcd
    2033              : 
    2034              : ! Two Factor decomposotionns of positive integer
    2035              : ! The first entry in facts is the largest factor unless is_print is True.
    2036              : ! 1 facts (1, 1) is_prime: True
    2037              : ! 2 facts (2, 1) is_prime: False
    2038              : ! 12 facts (6, 2) is_prime: False
    2039              : ! 11 facts (1, 11) is_prime: True
    2040              : ! 17 facts (1, 17) is_prime: True
    2041              : ! 33 facts (11, 3) is_prime: False
    2042              : ! 35 facts (7, 5) is_prime: False
    2043              : 
    2044            0 : subroutine ifact2(nn, facts, is_prime)
    2045              : 
    2046              :  integer,intent(in) :: nn
    2047              :  integer,intent(out) :: facts(2)
    2048              :  logical,intent(out) :: is_prime
    2049              : 
    2050              : !Local variables ------------------------------
    2051              :  integer :: start, ii
    2052              : 
    2053              : ! *************************************************************************
    2054              : 
    2055            0 :  ABI_CHECK(nn > 0, sjoin("invalid nn:", itoa(nn)))
    2056              : 
    2057            0 :  start = nn / 2 + 1
    2058            0 :  do ii=start, 1, -1
    2059            0 :    if (mod(nn, ii) == 0) exit
    2060              :  end do
    2061              : 
    2062            0 :  facts = [ii, nn / ii]
    2063            0 :  is_prime = facts(1) == 1
    2064              : 
    2065            0 : end subroutine ifact2
    2066              : !!***
    2067              : 
    2068              : ! Invert 3x3 matrix, copied from matr3inv
    2069            8 : pure subroutine inv33(aa, ait)
    2070              : 
    2071              : !Arguments ------------------------------------
    2072              : !arrays
    2073              :  real(dp),intent(in) :: aa(3,3)
    2074              :  real(dp),intent(out) :: ait(3,3)
    2075              : 
    2076              : !Local variables-------------------------------
    2077              : !scalars
    2078              :  real(dp) :: dd,det,t1,t2,t3
    2079              : 
    2080              : ! *************************************************************************
    2081              : 
    2082            8 :  t1 = aa(2,2) * aa(3,3) - aa(3,2) * aa(2,3)
    2083            8 :  t2 = aa(3,2) * aa(1,3) - aa(1,2) * aa(3,3)
    2084            8 :  t3 = aa(1,2) * aa(2,3) - aa(2,2) * aa(1,3)
    2085            8 :  det = aa(1,1) * t1 + aa(2,1) * t2 + aa(3,1) * t3
    2086              : 
    2087              :  ! Make sure matrix is not singular
    2088            8 :  if (abs(det) > 100 * tiny(one)) then
    2089            6 :    dd = one / det
    2090            6 :    ait(1,1) = t1 * dd
    2091            6 :    ait(2,1) = t2 * dd
    2092            6 :    ait(3,1) = t3 * dd
    2093            6 :    ait(1,2) = (aa(3,1)*aa(2,3)-aa(2,1)*aa(3,3)) * dd
    2094            6 :    ait(2,2) = (aa(1,1)*aa(3,3)-aa(3,1)*aa(1,3)) * dd
    2095            6 :    ait(3,2) = (aa(2,1)*aa(1,3)-aa(1,1)*aa(2,3)) * dd
    2096            6 :    ait(1,3) = (aa(2,1)*aa(3,2)-aa(3,1)*aa(2,2)) * dd
    2097            6 :    ait(2,3) = (aa(3,1)*aa(1,2)-aa(1,1)*aa(3,2)) * dd
    2098            6 :    ait(3,3) = (aa(1,1)*aa(2,2)-aa(2,1)*aa(1,2)) * dd
    2099          156 :    ait = transpose(ait)
    2100              :  else
    2101            2 :    ait = zero
    2102              :  end if
    2103              : 
    2104            8 :  end subroutine inv33
    2105              : 
    2106              : 
    2107            0 : end module m_cumulant
    2108              : !!***
        

Generated by: LCOV version 2.3-1