LCOV - code coverage report
Current view: top level - src/78_eph - m_rta.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 89.0 % 1004 894
Test Date: 2026-09-21 19:39:32 Functions: 100.0 % 16 16

            Line data    Source code
       1              : !!****m* ABINIT/m_rta
       2              : !! NAME
       3              : !!  m_rta
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides objects and procedures to compute transport properties by solving the
       7              : !!  linearized Boltzmann transport equation (BTE) in the relaxation-time approximation (RTA).
       8              : !!  or within the Iterative Bolztmann Equation (IBTE).
       9              : !!  The RTA has two different flavors: Self-energy Relaxation Time Approximation (SERTA)
      10              : !!  in which the back-scattering term is completely ignored and the Momentum-Relaxation Time Approximation (MRTA)
      11              : !!  in which backscattering is partly accounter for by multiplying the e-ph self-energy integrand function
      12              : !!  by the efficiency factor alpha that depends on the incoming/outgoing electron group velocity.
      13              : !!  The implementation assumes e-ph scattering although additional scattering mechanisms (e.g. ionized impurities)
      14              : !!  can be easily included once an appropriate model is added to the ab-initio e-ph scattering rates.
      15              : !!
      16              : !! COPYRIGHT
      17              : !!  Copyright (C) 2008-2026 ABINIT group (HM, MG)
      18              : !!  This file is distributed under the terms of the
      19              : !!  GNU General Public License, see ~abinit/COPYING
      20              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      21              : !!
      22              : !! NOTES
      23              : !!  Dimensional analysis for conductivity (sigma), mobility (mu).
      24              : !!
      25              : !!   [sigma] = Siemens/m  with S = Ampere/Volt = Ohm^-1
      26              : !!   [mu] = S L^2 Q
      27              : !!
      28              : !! SOURCE
      29              : 
      30              : #if defined HAVE_CONFIG_H
      31              : #include "config.h"
      32              : #endif
      33              : 
      34              : #include "abi_common.h"
      35              : 
      36              : module m_rta
      37              : 
      38              :  use defs_basis
      39              :  use m_abicore
      40              :  use m_xmpi
      41              :  use m_errors
      42              :  use m_copy
      43              :  use m_nctk
      44              :  use m_wfk
      45              :  use m_ephtk
      46              :  use m_sigmaph
      47              :  use m_dtset
      48              :  use m_dtfil
      49              :  use m_krank
      50              :  use netcdf
      51              : 
      52              :  use defs_datatypes,   only : pseudopotential_type
      53              :  use m_ebands,         only : ebands_t, gaps_t, edos_t, klinterp_t, klinterp_new
      54              :  use m_io_tools,       only : flush_unit, open_file
      55              :  use m_time,           only : cwtime, cwtime_report
      56              :  use m_crystal,        only : crystal_t
      57              :  use m_numeric_tools,  only : bisect, simpson_int, safe_div, arth
      58              :  use m_fstrings,       only : strcat, sjoin, itoa, ltoa, stoa, ftoa, yesno
      59              :  use m_kpts,           only : kpts_timrev_from_kptopt, kpts_map
      60              :  use m_occ,            only : occ_fd, occ_dfde
      61              :  use m_pawtab,         only : pawtab_type
      62              :  use m_ddk,            only : ddkstore_t
      63              : 
      64              :  implicit none
      65              : 
      66              :  private
      67              : !!****
      68              : 
      69              :  public :: rta_driver      ! Compute transport properties within the RTA (SERTA and MRTA)
      70              :  public :: ibte_driver     ! Compute transport properties within the IBTE.
      71              : !!****
      72              : 
      73              : !----------------------------------------------------------------------
      74              : 
      75              : !!****t* m_rta/rta_t
      76              : !! NAME
      77              : !! rta_t
      78              : !!
      79              : !! FUNCTION
      80              : !! Container for transport quantities in the RTA
      81              : !!
      82              : !! SOURCE
      83              : 
      84              : type,public :: rta_t
      85              : 
      86              :    integer :: nsppol
      87              :    ! Number of independent spin polarizations.
      88              : 
      89              :    integer :: nspinor
      90              :    ! Number of spinor components.
      91              : 
      92              :    integer :: nkcalc
      93              :    ! Number of computed k-points i.e. k-points inside the sigma_erange energy window.
      94              : 
      95              :    integer :: ntemp
      96              :    ! Number of temperatures.
      97              : 
      98              :    integer :: nw
      99              :    ! Number of energies (chemical potentials) at which transport quantities are computed
     100              :    ! Same number of energies used in DOS.
     101              : 
     102              :    integer :: bmin, bmax, bsize
     103              :    ! Only bands between bmin and bmax are considered in the integrals
     104              :    ! as we don't compute linewidths for all states.
     105              :    ! bmin = minval(%bstart_ks); bmax = maxval(%bstop_ks)
     106              :    ! bisze = bmax - bmin + 1
     107              : 
     108              :    integer :: nrta
     109              :    ! Number of relaxation-time approximations used (1 for SERTA, 2 for MRTA)
     110              : 
     111              :    real(dp) :: eph_extrael
     112              :    ! Extra electrons per unit cell used to compute SERTA lifetimes in sigmaph.
     113              : 
     114              :    real(dp) :: eph_fermie
     115              :    ! Fermi level specified in the input file when computing the SIGEPH file.
     116              : 
     117              :    real(dp) :: transport_extrael
     118              :    ! Extra electrons per unit cell specified in the input file when computing the SIGEPH file.
     119              : 
     120              :    real(dp) :: transport_fermie
     121              :    ! Fermi level specified in the input file when computing the SIGEPH file.
     122              : 
     123              :    logical :: assume_gap
     124              :    ! True if we are dealing with a semiconductor.
     125              :    ! This parameter is initialized from the value of sigma_erange provided by the user.
     126              : 
     127              :    integer,allocatable :: bstart_ks(:,:)
     128              :    ! bstart_ks(nkcalc, nsppol)
     129              :    ! Initial KS band index included in self-energy matrix elements for each k-point in kcalc.
     130              :    ! Depends on spin because all degenerate states should be included when symmetries are used.
     131              : 
     132              :    integer,allocatable :: bstop_ks(:,:)
     133              :    ! bstop_ks(nkcalc, nsppol)
     134              : 
     135              :    integer,allocatable :: nbcalc_ks(:,:)
     136              :    ! nbcalc_ks(nkcalc, nsppol)
     137              :    ! Number of bands included in self-energy matrix elements for each k-point in kcalc.
     138              :    ! Depends on spin because all degenerate states should be included when symmetries are used.
     139              : 
     140              :   integer,allocatable :: kcalc2ibz(:,:)
     141              :    !kcalc2ibz(nkcalc, 6))
     142              :    ! Mapping ikcalc --> IBZ as reported by listkk.
     143              : 
     144              :   integer,allocatable :: kcalc2ebands(:,:)
     145              :    ! (6, nkcalc)
     146              :    ! Mapping ikcalc --> ebands IBZ
     147              :    ! Note that this array is not necessarily equal to kcalc2ibz computed in sigmaph
     148              :    ! because we may have used sigma_ngkpt to downsample the initial nkpt mesh.
     149              :    ! This array is computed in get_ebands and is equal to kcalc2ibz if sigma_nkpt == ngkpt
     150              : 
     151              :    real(dp),allocatable :: kTmesh(:)
     152              :    ! (%ntemp)
     153              :    ! List of k * T temperatures at which to compute the transport
     154              : 
     155              :    real(dp),allocatable :: eph_mu_e(:)
     156              :    ! (%ntemp)
     157              :    ! Chemical potential at this carrier concentration and temperature from sigeph (lifetime)
     158              : 
     159              :    real(dp),allocatable :: transport_mu_e(:)
     160              :    ! (%ntemp)
     161              :    ! Chemical potential at this carrier concentration and temperature
     162              : 
     163              :    real(dp),allocatable :: eminmax_spin(:,:)
     164              :    ! (2, %nsppol))
     165              :    ! min/Max energy of the original ebands object
     166              : 
     167              :    real(dp),allocatable :: linewidths(:,:,:,:,:)
     168              :    ! (ntemp, bmin:bmax, nkpt, nsppol, nrta)
     169              :    ! Linewidth in the IBZ computed in the SERTA/MRTA.
     170              :    ! Non-zero only for the kcalc k-points.
     171              : 
     172              :    real(dp),allocatable :: vbks(:,:,:,:)
     173              :    ! (3, bmin:bmax, nkpt, nsppol))
     174              :    ! band velocity in Cartesian coordinates in the IBZ
     175              :    ! Non-zero only for the kcalc k-points.
     176              : 
     177              :    type(gaps_t) :: gaps
     178              :    ! gaps of original ebands object. Only if assume_gap
     179              : 
     180              :    type(ebands_t) :: ebands
     181              :    ! bandstructure object used to compute the transport properties
     182              :    ! Allocate using only the relevant bands for transport
     183              :    ! including valence states to allow to compute different doping
     184              : 
     185              :    type(edos_t) :: edos
     186              :    ! electronic density of states
     187              :    ! edos%mesh is the mesh used for vv_dos, vvtau_dos and tau_dos
     188              :    ! (%nw)
     189              : 
     190              :    real(dp),allocatable :: tau_dos(:,:,:,:)
     191              :    ! tau(e) (isotropic average for tau_nk for SERTA and MRTA.
     192              :    ! (nw, ntemp, nsppol, nrta)
     193              : 
     194              :    real(dp),allocatable :: vv_dos(:,:,:,:)
     195              :    ! (v x v)  DOS
     196              :    ! (nw, 3, 3, nsppol)
     197              : 
     198              :    real(dp),allocatable :: vvtau_dos(:,:,:,:,:,:)
     199              :    ! (v x v * tau) DOS
     200              :    ! (nw, 3, 3, ntemp, nsppol, nrta)
     201              : 
     202              :    real(dp),allocatable :: n_ehst(:,:,:)
     203              :     ! (2, %nsppol, %ntemp)
     204              :     ! Number of electrons (e) and holes (h) per unit cell
     205              :     ! The first dimension is for electrons/holes.
     206              :     ! If nsppol == 2, the second dimension is the number of e/h for spin else the total number of e/h summed over spins.
     207              : 
     208              :    real(dp),allocatable :: l0(:,:,:,:,:,:), l1(:,:,:,:,:,:), l2(:,:,:,:,:,:)
     209              :    ! (3, 3, nw, nsppol, ntemp, nrta)
     210              :    ! Onsager coefficients in Cartesian coordinates
     211              : 
     212              :    real(dp),allocatable :: l11_mu(:,:,:,:,:), l12_mu(:,:,:,:,:), l22_mu(:,:,:,:,:)
     213              :    ! (3, 3, nsppol, ntemp, nrta)
     214              :    ! Onsager coefficients in Cartesian coordinates, calculated at the correct mu (at the exact temperature)
     215              : 
     216              :    real(dp),allocatable :: sigma(:,:,:,:,:,:)
     217              :    real(dp),allocatable :: seebeck(:,:,:,:,:,:)
     218              :    real(dp),allocatable :: kappa(:,:,:,:,:,:)
     219              :    real(dp),allocatable :: pi(:,:,:,:,:,:)
     220              :    real(dp),allocatable :: zte(:,:,:,:,:,:)
     221              :    ! (3, 3, nw, nsppol, ntemp, nrta)
     222              :    ! Transport coefficients in Cartesian coordinates
     223              : 
     224              :    real(dp),allocatable :: mobility(:,:,:,:,:,:,:)
     225              :    ! Mobility
     226              :    ! (3, 3, nw, %ntemp, 2, %nsppol, nrta)
     227              :    ! 5-th index is for e-h
     228              : 
     229              :    real(dp),allocatable :: conductivity(:,:,:,:,:)
     230              :    ! Conductivity at the Fermi level
     231              :    ! (3, 3, %ntemp, %nsppol, nrta)
     232              : 
     233              :    real(dp),allocatable :: resistivity(:,:,:,:)
     234              :    ! (3, 3, %ntemp, nrta)
     235              : 
     236              :    real(dp),allocatable :: n(:,:,:)
     237              :    ! (nw, ntemp, 2) carrier density for e/h (n/cm^3)
     238              : 
     239              :    real(dp),allocatable :: mobility_mu(:,:,:,:,:,:)
     240              :    ! (3, 3, 2, nsppol, ntemp, nrta)
     241              :    ! mobility for electrons and holes (third dimension) at transport_mu_e(ntemp)
     242              :    ! Third dimension is for electron/hole
     243              : 
     244              :    real(dp),allocatable :: conductivity_mu(:,:,:,:,:,:)
     245              :    ! (3, 3, 2, nsppol, ntemp, nrta)
     246              :    ! Conductivity in Siemens * cm-1
     247              :    ! computed by summing over k-points rather that by performing an energy integration).
     248              : 
     249              :    real(dp),allocatable :: resistivity_mu(:,:,:,:)
     250              :    ! (3, 3, ntemp, nrta)
     251              :    ! Resistivity obtained by inverting conductivity after summing of e- and holes and spins
     252              :    ! computed by summing over k-points rather that by performing an energy integration).
     253              : 
     254              : 
     255              : 
     256              :  contains
     257              : 
     258              :    procedure :: compute_rta
     259              :    procedure :: compute_rta_mobility
     260              :    procedure :: print_rta_txt_files
     261              :    procedure :: write_tensor
     262              :    procedure :: free => rta_free
     263              :    procedure :: rta_ncwrite
     264              : 
     265              :  end type rta_t
     266              : !!***
     267              : 
     268              : !----------------------------------------------------------------------
     269              : 
     270              : contains  !=====================================================
     271              : !!***
     272              : 
     273              : !----------------------------------------------------------------------
     274              : 
     275              : !!****f* m_rta/rta_driver
     276              : !! NAME
     277              : !! rta_driver
     278              : !!
     279              : !! FUNCTION
     280              : !! Driver to compute transport properties within the RTA.
     281              : !!
     282              : !! INPUTS
     283              : !! dtfil<datafiles_type>=variables related to files.
     284              : !! ngfftc(18)=Coarse FFT mesh.
     285              : !! dtset<dataset_type>=All input variables for this dataset.
     286              : !! ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
     287              : !! cryst<crystal_t>=Crystalline structure
     288              : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
     289              : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
     290              : !! comm=MPI communicator.
     291              : !!
     292              : !! SOURCE
     293              : 
     294           12 : subroutine rta_driver(dtfil, ngfftc, dtset, ebands, cryst, pawtab, psps, comm)
     295              : 
     296              : !Arguments ------------------------------------
     297              : !scalars
     298              :  integer, intent(in) :: comm
     299              :  type(datafiles_type),intent(in) :: dtfil
     300              :  type(dataset_type),intent(in) :: dtset
     301              :  type(crystal_t),intent(in) :: cryst
     302              :  type(ebands_t),intent(in) :: ebands
     303              :  type(pseudopotential_type),intent(in) :: psps
     304              : !arrays
     305              :  integer,intent(in) :: ngfftc(18)
     306              :  type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
     307              : 
     308              : !Local variables ------------------------------
     309              :  type(rta_t) :: rta
     310              : !arrays
     311              :  integer :: units(2)
     312              : 
     313              : ! *************************************************************************
     314              : 
     315           36 :  units = [std_out, ab_out]
     316           12 :  call wrtout(units, ch10//' Entering transport RTA computation driver.')
     317           12 :  call wrtout(units, sjoin("- Reading carrier lifetimes from:", dtfil%filsigephin), newlines=1, do_flush=.True.)
     318              : 
     319              :  ! Initialize RTA object
     320           12 :  rta = rta_new(dtset, dtfil, ngfftc, cryst, ebands, pawtab, psps, comm)
     321              : 
     322              :  ! Compute RTA transport quantities
     323           12 :  call rta%compute_rta(cryst, dtset, dtfil, comm)
     324              : 
     325           12 :  call rta%free()
     326              : 
     327           12 : end subroutine rta_driver
     328              : !!***
     329              : 
     330              : !----------------------------------------------------------------------
     331              : 
     332              : !!****f* m_rta/rta_new
     333              : !! NAME
     334              : !! rta_new
     335              : !!
     336              : !! FUNCTION
     337              : !! Build object to compute RTA transport quantities.
     338              : !!
     339              : !! INPUTS
     340              : !!  dtset<dataset_type>=All input variables for this dataset.
     341              : !!  dtfil<datafiles_type>=variables related to files.
     342              : !!  cryst<crystal_t>=Crystalline structure
     343              : !!  ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
     344              : !!  comm=MPI communicator.
     345              : !!
     346              : !! SOURCE
     347              : 
     348           13 : type(rta_t) function rta_new(dtset, dtfil, ngfftc, cryst, ebands, pawtab, psps, comm) result (new)
     349              : 
     350              : !Arguments -------------------------------------
     351              :  integer, intent(in) :: comm
     352              :  type(dataset_type),intent(in) :: dtset
     353              :  type(datafiles_type),intent(in) :: dtfil
     354              :  type(crystal_t),intent(in) :: cryst
     355              :  type(ebands_t),intent(in) :: ebands
     356              :  type(pseudopotential_type),intent(in) :: psps
     357              : !arrays
     358              :  integer,intent(in) :: ngfftc(18)
     359              :  type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
     360              : 
     361              : !Local variables ------------------------------
     362              :  integer,parameter :: sppoldbl1 = 1, master = 0
     363              :  integer :: ierr, spin, nprocs, my_rank, ik_ibz, ib, irta, itemp, ndat, nsppol, idat, mband, ikpt
     364              :  real(dp) :: cpu, wall, gflops
     365              :  character(len=500) :: msg
     366              :  character(len=fnlen) :: wfk_fname_dense
     367           13 :  type(ebands_t) :: tmp_ebands, ebands_dense
     368           13 :  type(klinterp_t) :: klinterp
     369           13 :  type(ddkstore_t) :: ds
     370           13 :  type(sigmaph_t) :: sigmaph
     371           13 :  type(krank_t) :: krank
     372              : !arrays
     373              :  integer :: kptrlatt(3,3), units(2), sigma_ngkpt(3)
     374           13 :  integer,allocatable :: indkk(:,:)
     375              :  real(dp) :: extrael_fermie(2), sigma_erange(2)
     376           13 :  real(dp),allocatable :: values_bksd(:,:,:,:), vals_bsd(:,:,:), tmp_array4(:,:,:,:), tmp_array5(:,:,:,:,:)
     377              : !************************************************************************
     378              : 
     379           13 :  call cwtime(cpu, wall, gflops, "start")
     380           39 :  units = [std_out, ab_out]
     381              : 
     382           13 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
     383              : 
     384              :  ! Use sigma_erange to understand if we are dealing with a metal or a semiconductor.
     385           15 :  new%assume_gap = (.not. all(dtset%sigma_erange < zero) .or. dtset%gw_qprange /= 0)
     386              : 
     387              :  ! Read data from SIGEPH file.
     388              :  sigmaph = sigmaph_read(dtfil%filsigephin, dtset, xmpi_comm_self, msg, ierr, keep_open=.true., &
     389           13 :                         extrael_fermie=extrael_fermie, sigma_ngkpt=sigma_ngkpt, sigma_erange=sigma_erange)
     390           13 :  ABI_CHECK(ierr == 0, msg)
     391              : 
     392              :  !if (any(sigma_erange /= zero)) then
     393              :  !  ABI_CHECK(all(dtset%sigma_erange /= zero), "sigma_erange is required in input with a value compatible with SIGEPH.nc")
     394              :  !  ! Make sure that the two values are consistent
     395              :  !  ! Cannot switch to metallic case if SigmaPH file was produced assuming gapped-system
     396              :  !  if (.not. (all(dtset%sigma_erange < zero) .eqv. all(sigma_erange < zero))) then
     397              :  !    ABI_ERROR("The values of sigma_erange from input and SIGEPH are not compatible")
     398              :  !  end if
     399              :  !end if
     400              : 
     401              :  ! How many RTA approximations have we computed in sigmaph? (SERTA, MRTA ...?)
     402           13 :  new%nrta = 2; if (sigmaph%mrta == 0) new%nrta = 1
     403              : 
     404              :  ! Copy important arrays from sigmaph file.
     405              :  ! Allocate temperature arrays (use same values as the ones used in the SIGEPH calculation).
     406           13 :  new%ntemp = sigmaph%ntemp
     407           13 :  call alloc_copy(sigmaph%kTmesh, new%kTmesh)
     408              : 
     409           13 :  new%nkcalc = sigmaph%nkcalc
     410           13 :  call alloc_copy(sigmaph%bstart_ks, new%bstart_ks)
     411           13 :  call alloc_copy(sigmaph%bstop_ks, new%bstop_ks)
     412           13 :  call alloc_copy(sigmaph%nbcalc_ks, new%nbcalc_ks)
     413           13 :  call alloc_copy(sigmaph%kcalc2ibz, new%kcalc2ibz)
     414              : 
     415          141 :  new%bmin = minval(sigmaph%bstart_ks); new%bmax = maxval(sigmaph%bstop_ks)
     416              :  !new%bmin = 1; new%bmax = ebands%mband ! This for debugging purposes, results should not change
     417           13 :  new%bsize = new%bmax - new%bmin + 1
     418              : 
     419           13 :  new%nsppol = ebands%nsppol; new%nspinor = ebands%nspinor
     420           13 :  nsppol = new%nsppol
     421              : 
     422           39 :  ABI_MALLOC(new%eminmax_spin, (2, nsppol))
     423           65 :  new%eminmax_spin = ebands%get_minmax("eig")
     424              : 
     425           13 :  if (new%assume_gap) then
     426              :    ! Get gaps
     427           12 :    new%gaps = ebands%get_gaps(ierr)
     428           12 :    if (ierr /= 0) then
     429            0 :      do spin=1, nsppol
     430            0 :        ABI_WARNING(trim(new%gaps%errmsg_spin(spin)))
     431            0 :        new%gaps%vb_max(spin) = ebands%fermie - 1 * eV_Ha
     432            0 :        new%gaps%cb_min(spin) = ebands%fermie + 1 * eV_Ha
     433              :      end do
     434              :      !ABI_ERROR("ebands_get_gaps returned non-zero exit status. See above warning messages...")
     435            0 :      ABI_WARNING("ebands_get_gaps returned non-zero exit status. See above warning messages...")
     436              :    end if
     437           12 :    if (my_rank == master) call new%gaps%print(units)
     438              :  end if
     439              : 
     440              :  ! =================================================
     441              :  ! Read lifetimes and new%ebands from SIGEPH.nc file
     442              :  ! =================================================
     443              :  ! After this point we have:
     444              :  !
     445              :  !      vbks(3, bmin:bmax, nkpt, nsppol)
     446              :  !      linewidths(self%ntemp, bmin:bmax, nkpt, nsppol, 2)
     447              :  !
     448           46 :  if (any(dtset%sigma_ngkpt /= 0)) then
     449              :    ! If integrals are computed with the sigma_ngkpt k-mesh, we need to downsample ebands.
     450              :    !call wrtout(units, sjoin(" SIGMAPH file used sigma_ngkpt:", ltoa(sigma_ngkpt)))
     451            2 :    call wrtout(units, sjoin(" Computing integrals with downsampled sigma_ngkpt:", ltoa(dtset%sigma_ngkpt)))
     452            2 :    kptrlatt = 0
     453            2 :    kptrlatt(1,1) = dtset%sigma_ngkpt(1); kptrlatt(2,2) = dtset%sigma_ngkpt(2); kptrlatt(3,3) = dtset%sigma_ngkpt(3)
     454              : 
     455            2 :    tmp_ebands = ebands%downsample(cryst, kptrlatt, dtset%sigma_nshiftk, dtset%sigma_shiftk)
     456              :    new%ebands = sigmaph%get_ebands(cryst, tmp_ebands, [new%bmin, new%bmax], &
     457            6 :                                    new%kcalc2ebands, new%linewidths, new%vbks, xmpi_comm_self)
     458            2 :    call tmp_ebands%free()
     459              :  else
     460              :    !call wrtout(units, sjoin(" Computing integrals with SIGEPH k-mesh:", ebands_kmesh2str(ebands))
     461              :    new%ebands = sigmaph%get_ebands(cryst, ebands, [new%bmin, new%bmax], &
     462           33 :                                    new%kcalc2ebands, new%linewidths, new%vbks, xmpi_comm_self)
     463          143 :    kptrlatt = new%ebands%kptrlatt
     464              :  end if
     465              : 
     466              :  !print *, "linewidth_serta", maxval(abs(new%linewidths(:,:,:,:,1)))
     467              :  !print *, "linewidth_mrta", maxval(abs(new%linewidths(:,:,:,:,2)))
     468              :  !print *, "max velocities", maxval(abs(new%vbks))
     469              : 
     470              :  if ( &
     471           13 :      dtset%useria == 888 .and. &
     472              :      (dtset%getwfkfine /= 0 .or. dtset%irdwfkfine /= 0 .or. dtset%getwfkfine_filepath /= ABI_NOFILE)) then
     473              : 
     474              :    ! In principle only getwfkfine_filepath is used here
     475            0 :    wfk_fname_dense = trim(dtfil%fnameabi_wfkfine)
     476            0 :    ABI_CHECK(nctk_try_fort_or_ncfile(wfk_fname_dense, msg) == 0, msg)
     477              : 
     478            0 :    call wrtout(units, " EPH double grid interpolation: will read energies from: "//trim(wfk_fname_dense), newlines=1)
     479            0 :    mband = new%ebands%mband
     480              : 
     481              :    !ebands_dense = wfk_read_ebands(wfk_fname_dense, comm)
     482              : 
     483            0 :    tmp_ebands = wfk_read_ebands(wfk_fname_dense, comm)
     484            0 :    ebands_dense = tmp_ebands%chop(1, mband)
     485            0 :    call tmp_ebands%free()
     486            0 :    if (my_rank == master) then
     487            0 :      write(std_out, *)" Using kptrlatt: ", ebands_dense%kptrlatt
     488            0 :      write(std_out, *)"       shiftk: ", ebands_dense%shiftk
     489              :    end if
     490            0 :    ABI_CHECK_IEQ(mband, ebands_dense%mband, "Inconsistent number of bands for the fine and dense grid:")
     491              : 
     492              :    ! Compute v_{nk} on the dense grid in Cartesian coordinates.
     493              :    ! vdiago(3, bmin:bmax, nkpt, nsppol)
     494              :    ! NB: We select bands in [bmin:bmax] but all k-points in the IBZ are computed!
     495            0 :    ds%only_diago = .True.; ds%bmin = new%bmin; ds%bmax = new%bmax; ds%mode = "cart"
     496            0 :    call ds%compute_ddk(wfk_fname_dense, "", dtset, psps, pawtab, ngfftc, comm)
     497              : 
     498              :    ! Transfer data to new%vbks
     499            0 :    ABI_MOVE_ALLOC(ds%vdiago, new%vbks)
     500            0 :    call ds%free()
     501              :    !print *, "vbks:", new%vbks
     502              : 
     503              :    ! Linear interpolation in k-space of the linewidths from input SIGEPH to the dense IBZ provided by fine WFK file.
     504              :    ! First of all transfer linewidths to values_bksd to prepare call to klinterp_new.
     505            0 :    ndat = new%ntemp * new%nrta
     506            0 :    ABI_MALLOC(values_bksd, (new%bmin:new%bmax, new%ebands%nkpt, nsppol, ndat))
     507              : 
     508            0 :    do irta=1,new%nrta
     509            0 :      do spin=1,nsppol
     510            0 :        do ik_ibz=1,new%ebands%nkpt
     511            0 :          do ib=new%bmin,new%bmax
     512            0 :            do itemp=1,new%ntemp
     513            0 :              idat = itemp + new%ntemp * (irta - 1)
     514            0 :              values_bksd(ib, ik_ibz, spin, idat) = new%linewidths(itemp, ib, ik_ibz, spin, irta) ! - t(e)
     515              :            end do
     516              :          end do
     517              :        end do
     518              :      end do
     519              :    end do
     520              : 
     521              :    ! Build linear interpolator for linewidths (use only bsize bands)
     522              :    klinterp = klinterp_new(cryst, new%ebands%kptrlatt, new%ebands%nshiftk, new%ebands%shiftk, new%ebands%kptopt, &
     523            0 :                            new%ebands%kptns, new%bsize, new%ebands%nkpt, nsppol, ndat, values_bksd, comm)
     524            0 :    ABI_FREE(values_bksd)
     525              : 
     526              :    ! HERE we re-malloc new%ebands and %linewidths on the fine k-mesh.
     527              :    ! The call must be executed here, once klinterp has been built.
     528              :    ! After this point we can use new%ebands to allocate stuff.
     529            0 :    call ebands_dense%move_alloc(new%ebands)
     530              : 
     531              :    ! Unlinke the ebands stored in SIGEPH, the eigens read from WFK_FINE have not been
     532              :    ! shifted with the scissors operator or updated according to extrael_fermie so do it now.
     533            0 :    call ephtk_update_ebands(dtset, new%ebands, "GS energies read from WFK_FINE")
     534              : 
     535              :    ! And now interpolate linewidths on the fine k-mesh
     536              :    ! Note: k-points that close to the edge of the pocket may get zero linewidths
     537              :    ! One may fix the problem by using lw(e).
     538            0 :    ABI_REMALLOC(new%linewidths, (new%ntemp, new%bmin:new%bmax, new%ebands%nkpt, nsppol, new%nrta))
     539            0 :    ABI_MALLOC(vals_bsd, (new%bmin:new%bmax, nsppol, ndat))
     540              : 
     541            0 :    ierr = 0
     542            0 :    do ik_ibz=1,new%ebands%nkpt
     543              : 
     544            0 :      call klinterp%eval_bsd(new%ebands%kptns(:, ik_ibz), vals_bsd)
     545              :      !vals_bsd = vals_bsd + lw(e)
     546              : 
     547            0 :      if (any(vals_bsd < zero)) then
     548            0 :        ierr = ierr + 1
     549            0 :        where (vals_bsd < zero) vals_bsd = zero
     550              :      end if
     551              : 
     552              :      ! Transfer data.
     553            0 :      do spin=1,nsppol
     554            0 :        do irta=1,new%nrta
     555            0 :          do itemp=1,new%ntemp
     556            0 :            idat = itemp + new%ntemp * (irta - 1)
     557            0 :            do ib=new%bmin,new%bmax
     558            0 :              new%linewidths(itemp, ib, ik_ibz, spin, irta) = vals_bsd(ib, spin, idat)
     559              :            end do
     560              :          end do
     561              :        end do
     562              :      end do
     563              : 
     564              :    end do ! ik_ibz
     565              : 
     566            0 :    if (ierr /= 0) then
     567              :      ! This should never happen for linear interpolation.
     568            0 :      ABI_WARNING(sjoin("Linear interpolation produced:", itoa(ierr), " k-points with negative linewidths"))
     569              :    end if
     570              : 
     571            0 :    ABI_FREE(vals_bsd)
     572            0 :    call klinterp%free()
     573              :  end if
     574              : 
     575              :  ! FIXME: I think transport_ngkpt is buggy, wrong ne(T), weird zeros if MRTA ...
     576              :  ! Do we really need this option? Can't we replace it with sigma_ngkpt and eph_task 7?
     577              : 
     578           49 :  if (any(dtset%transport_ngkpt /= 0)) then
     579              :    ! Perform further downsampling (useful for debugging purposes)
     580            1 :    call wrtout(units, " Downsampling the k-mesh before computing transport:")
     581            1 :    call wrtout(units, sjoin(" Using transport_ngkpt: ", ltoa(dtset%transport_ngkpt)))
     582            1 :    kptrlatt = 0
     583            1 :    kptrlatt(1, 1) = dtset%transport_ngkpt(1)
     584            1 :    kptrlatt(2, 2) = dtset%transport_ngkpt(2)
     585            1 :    kptrlatt(3, 3) = dtset%transport_ngkpt(3)
     586            1 :    tmp_ebands = new%ebands%downsample(cryst, kptrlatt, 1, [zero, zero, zero])
     587              : 
     588              :    ! Map the points of the downsampled bands to dense ebands
     589            3 :    ABI_MALLOC(indkk, (6, tmp_ebands%nkpt))
     590              : 
     591            1 :    call krank%from_kptrlatt(new%ebands%nkpt, new%ebands%kptns, new%ebands%kptrlatt, compute_invrank=.False.)
     592              : 
     593            1 :    if (kpts_map("symrec", ebands%kptopt, cryst, krank, tmp_ebands%nkpt, tmp_ebands%kptns, indkk) /= 0) then
     594              :      write(msg, '(3a)' ) &
     595            0 :        "Error while downsampling ebands in the transport driver",ch10, &
     596            0 :        "The k-point could not be generated from a symmetrical one."
     597            0 :      ABI_ERROR(msg)
     598              :    end if
     599              : 
     600            1 :    call krank%free()
     601              : 
     602              :    ! Downsampling linewidths and velocities.
     603            1 :    ABI_MOVE_ALLOC(new%linewidths, tmp_array5)
     604            7 :    ABI_REMALLOC(new%linewidths, (new%ntemp, new%bmin:new%bmax, tmp_ebands%nkpt, nsppol, new%nrta))
     605           73 :    do ikpt=1,tmp_ebands%nkpt
     606         1369 :      new%linewidths(:,:,ikpt,:,:) = tmp_array5(:,:,indkk(1, ikpt),:,:)
     607              :    end do
     608            1 :    ABI_FREE(tmp_array5)
     609              : 
     610            1 :    ABI_MOVE_ALLOC(new%vbks, tmp_array4)
     611            5 :    ABI_REMALLOC(new%vbks, (3, new%bmin:new%bmax, tmp_ebands%nkpt, nsppol))
     612           73 :    do ikpt=1,tmp_ebands%nkpt
     613          433 :      new%vbks(:,:,ikpt,:) = tmp_array4(:,:,indkk(1, ikpt),:)
     614              :    end do
     615            1 :    ABI_FREE(tmp_array4)
     616              : 
     617              :    !print *, "after downsampling linewidths"
     618              :    !print *, "linewidth_serta", maxval(abs(new%linewidths(:,:,:,:,1)))
     619              :    !print *, "linewidth_mrta", maxval(abs(new%linewidths(:,:,:,:,2)))
     620              : 
     621            1 :    ABI_FREE(indkk)
     622            1 :    call tmp_ebands%move_alloc(new%ebands)
     623              :  end if
     624              : 
     625              :  ! Same doping case as in sigmaph file.
     626           39 :  ABI_MALLOC(new%eph_mu_e, (new%ntemp))
     627           26 :  ABI_MALLOC(new%transport_mu_e, (new%ntemp))
     628              : 
     629           13 :  new%eph_extrael = extrael_fermie(1)
     630           13 :  new%eph_fermie = extrael_fermie(2)
     631           13 :  new%transport_fermie = dtset%eph_fermie
     632           13 :  new%transport_extrael = dtset%eph_extrael
     633           88 :  new%eph_mu_e = sigmaph%mu_e
     634           88 :  new%transport_mu_e = sigmaph%mu_e
     635              : 
     636           13 :  if (new%transport_fermie /= zero) new%transport_mu_e = new%transport_fermie
     637              : 
     638           13 :  if (new%transport_fermie == zero .and. new%transport_extrael /= new%eph_extrael) then
     639              : 
     640              :    if (new%transport_extrael /= new%eph_extrael) then
     641              :      write(msg,'(2(a,e18.8),3a)') &
     642            0 :        ' extrael from SIGEPH: ',new%transport_extrael, ' and input file: ',new%eph_extrael, "differ", ch10, &
     643            0 :        ' Will recompute the chemical potential'
     644            0 :      call wrtout(std_out, msg)
     645              :    end if
     646              : 
     647              :    ! Compute Fermi level for different T values.
     648            0 :    call ebands%get_muT_with_fd(new%ntemp, new%kTmesh, dtset%spinmagntarget, dtset%prtvol, new%transport_mu_e, comm)
     649              :  end if
     650              : 
     651              :  ! TODO: Implement possible change of sigma_erange, useful for convergence studies
     652              :  !   1) Run sigmaph with relatively large sigma_erange.
     653              :  !   2) Decrease energy window in the transport part to analyze the behaviour of transport tensors.
     654              : 
     655              :  ! sigmaph is not needed anymore. Free it.
     656           13 :  sigmaph%ncid = nctk_noid
     657           13 :  call sigmaph%free()
     658              : 
     659           13 :  call cwtime_report(" rta_new", cpu, wall, gflops)
     660              : 
     661           26 : end function rta_new
     662              : !!***
     663              : 
     664              : !----------------------------------------------------------------------
     665              : 
     666              : !!****f* m_rta/compute_rta
     667              : !! NAME
     668              : !! compute_rta
     669              : !!
     670              : !! FUNCTION
     671              : !!
     672              : !! INPUTS
     673              : !! cryst<crystal_t>=Crystalline structure
     674              : !! dtset<dataset_type>=All input variables for this dataset.
     675              : !! dtfil<datafiles_type>=variables related to files.
     676              : !! comm=MPI communicator.
     677              : !!
     678              : !! SOURCE
     679              : 
     680           13 : subroutine compute_rta(self, cryst, dtset, dtfil, comm)
     681              : 
     682              : !Arguments ------------------------------------
     683              :  integer,intent(in) :: comm
     684              :  class(rta_t),intent(inout) :: self
     685              :  type(dataset_type),intent(in) :: dtset
     686              :  type(datafiles_type),intent(in) :: dtfil
     687              :  type(crystal_t),intent(in) :: cryst
     688              : 
     689              : !Local variables ------------------------------
     690              :  integer,parameter :: nvecs0 = 0, master = 0
     691              :  integer :: nsppol, nkibz, ib, ik_ibz, iw, spin, ii, jj, itemp, irta, itens_, iscal, cnt
     692              :  integer :: ntens, edos_intmeth, ifermi, iel, nvals, my_rank
     693              :  integer :: ncid
     694              :  !character(len=500) :: msg
     695              :  character(len=fnlen) :: path
     696              :  real(dp) :: emin, emax, edos_broad, edos_step, max_occ, kT, Tkelv, linewidth, fact0, cpu, wall, gflops
     697              : !arrays
     698              :  integer :: units(2)
     699              :  real(dp) :: vr(3), dummy_vecs(1,1,1,1,1), work_33(3,3), S_33(3,3), mat33(3,3)
     700           13 :  real(dp),allocatable :: vv_tens(:,:,:,:,:,:,:), out_valsdos(:,:,:,:), dummy_dosvecs(:,:,:,:,:)
     701           13 :  real(dp),allocatable :: out_tensdos(:,:,:,:,:,:), tau_vals(:,:,:,:,:), l0inv_33nw(:,:,:)
     702              : !************************************************************************
     703              : 
     704           13 :  call cwtime(cpu, wall, gflops, "start")
     705           13 :  my_rank = xmpi_comm_rank(comm)
     706           39 :  units = [std_out, ab_out]
     707              : 
     708              :  ! Basic dimensions
     709           13 :  nsppol = self%ebands%nsppol; nkibz = self%ebands%nkpt
     710              : 
     711              :  ! Allocate v x v tensors with and without the lifetimes. Eq 8 of [[cite:Madsen2018]]
     712              :  ! The total number of tensorial entries is ntens and accounts for nrta
     713              :  ! Remember that we haven't computed all the k-points in the IBZ hence we can have zero linewidths
     714              :  ! or very small values when the states are at the band edge so we use safe_dif to avoid SIGFPE.
     715              :  ! Also, note how we store only the states in the energy window.
     716              : 
     717           13 :  nvals = self%ntemp * self%nrta
     718        56295 :  ABI_CALLOC(tau_vals, (self%ntemp, self%nrta, self%bmin:self%bmax, nkibz, nsppol))
     719              : 
     720           13 :  ntens = (1 + self%ntemp) * self%nrta
     721       651318 :  ABI_CALLOC(vv_tens, (3, 3, 1 + self%ntemp, self%nrta, self%bmin:self%bmax, nkibz, nsppol))
     722              : 
     723              :  cnt = 0
     724           26 :  do spin=1,nsppol
     725         3582 :    do ik_ibz=1,nkibz
     726              :      !cnt = cnt + 1; if (mod(cnt, nprocs) /= my_rank) cycle ! MPI parallelism.
     727         7230 :      do ib=self%bmin,self%bmax
     728              : 
     729        14644 :        vr(:) = self%vbks(:, ib, ik_ibz, spin)
     730              :        ! Store outer product (v_bks x v_bks) in vv_tens. This part does not depend on T and irta.
     731        14644 :        do ii=1,3
     732        47593 :          do jj=1,3
     733       109830 :            vv_tens(ii, jj, 1, 1:self%nrta, ib, ik_ibz, spin) = vr(ii) * vr(jj)
     734              :          end do
     735              :        end do
     736              : 
     737              :        ! Multiply by the lifetime (SERTA and MRTA)
     738        14539 :        do irta=1,self%nrta
     739        52635 :          do itemp=1,self%ntemp
     740        41652 :            linewidth = self%linewidths(itemp, ib, ik_ibz, spin, irta)
     741              :            call safe_div(vv_tens(:,:, 1, irta, ib, ik_ibz, spin), two * linewidth, zero, &
     742       541476 :                          vv_tens(:,:, 1 + itemp, irta, ib, ik_ibz, spin))
     743        48974 :            call safe_div(one, two * linewidth, zero, tau_vals(itemp, irta, ib, ik_ibz, spin))
     744              :          end do
     745              :        end do
     746              : 
     747              :      end do
     748              :    end do
     749              :  end do
     750              : 
     751              :  !call xmpi_sum(vv_tens, comm, ierr)
     752              :  !call xmpi_sum(tau_vals, comm, ierr)
     753           13 :  call cwtime_report(" compute_rta_loop1", cpu, wall, gflops)
     754              : 
     755              :  ! Compute DOS and VV_DOS and VV_TAU_DOS
     756              :  ! Define integration method and mesh step.
     757           13 :  edos_intmeth = 2; if (dtset%prtdos /= 0) edos_intmeth = dtset%prtdos
     758           13 :  edos_step = dtset%dosdeltae
     759           13 :  if (edos_step == zero) edos_step = 0.001
     760              :  !if (edos_step == zero) edos_step = ten / Ha_meV
     761           13 :  edos_broad = dtset%tsmear
     762              : 
     763              :  ! Set default energy range for DOS
     764              :  ! If sigma_erange is set, get emin and emax from this variable
     765              :  ! MG: TODO This value should be read from SIGEPH
     766              :  ! Recheck metals
     767           13 :  if (self%assume_gap) then
     768           12 :    emin = huge(one); emax = -huge(one)
     769           24 :    do spin=1,self%ebands%nsppol
     770           12 :      if (dtset%sigma_erange(1) >= zero) emin = min(emin, self%gaps%vb_max(spin) + tol2 * eV_Ha - dtset%sigma_erange(1))
     771           24 :      if (dtset%sigma_erange(2) >= zero) emax = max(emax, self%gaps%cb_min(spin) - tol2 * eV_Ha + dtset%sigma_erange(2))
     772              :    end do
     773           12 :    ABI_CHECK(emin /=  huge(one), "Cannot initialize emin")
     774           12 :    ABI_CHECK(emax /= -huge(one), "Cannot initialize emax")
     775              :  else
     776            3 :    emin = minval(self%eminmax_spin(1, :)); emin = emin - tol1 * abs(emin)
     777            3 :    emax = maxval(self%eminmax_spin(2, :)); emax = emax + tol1 * abs(emax)
     778              :  end if
     779              : 
     780              :  ! Compute DOS, vv_dos and vvtau_DOS (v x v tau)
     781              :  !
     782              :  !    out_valsdos: (nw, 2, nvals, nsppol) array with DOS for scalar quantities if nvals > 0
     783              :  !    out_tensdos: (nw, 2, 3, 3, ntens,  nsppol) array with DOS weighted by tensorial terms if ntens > 0
     784              :  !
     785              :  !  Vectors and tensors are in Cartesian coordinates.
     786              :  !  Note how we compute the DOS only between [emin, emax] to save time and memory
     787              :  !  this implies that IDOS and edos%ifermi are ill-defined
     788              : 
     789              :  self%edos = self%ebands%get_edos_matrix_elements(cryst, self%bsize, &
     790              :                                              nvals, tau_vals, nvecs0, dummy_vecs, ntens, vv_tens, &
     791              :                                              edos_intmeth, edos_step, edos_broad, &
     792              :                                              out_valsdos, dummy_dosvecs, out_tensdos, comm, &
     793           65 :                                              brange=[self%bmin, self%bmax], erange=[emin, emax])
     794              : 
     795           13 :  if (my_rank == master) then
     796           39 :    call self%edos%print([std_out, ab_out], header="Computation of DOS, VV_DOS and VVTAU_DOS")
     797              :  end if
     798              : 
     799           13 :  call cwtime_report(" compute_rta_edos", cpu, wall, gflops)
     800              : 
     801              :  ! Unpack data stored in out_tensdos with shape (nw, 2, 3, 3, ntens, nsppol)
     802           13 :  self%nw = self%edos%nw
     803           78 :  ABI_MALLOC(self%tau_dos, (self%nw, self%ntemp, nsppol, self%nrta))
     804              :  ! TODO: Exchange dims?
     805           65 :  ABI_MALLOC(self%vv_dos, (self%nw, 3, 3, nsppol))
     806           91 :  ABI_MALLOC(self%vvtau_dos, (self%nw, 3, 3, self%ntemp, nsppol, self%nrta))
     807              : 
     808           39 :  do irta=1,self%nrta
     809           65 :    do spin=1,nsppol
     810          202 :      do itemp=1,self%ntemp+1
     811              : 
     812          150 :        itens_ = itemp + (irta - 1) * (self%ntemp + 1)
     813          176 :        if (itemp == 1) then
     814       100238 :          self%vv_dos(:,:,:,spin) = out_tensdos(:, 1, :, :, itens_, spin)
     815              :        else
     816       233092 :          self%vvtau_dos(:,:,:, itemp-1, spin, irta) = out_tensdos(:, 1, :, :, itens_, spin)
     817              :        end if
     818              : 
     819              :      end do
     820              :    end do
     821              :  end do
     822              : 
     823              :  ! Transfer data for tau(e)
     824           39 :  do irta=1,self%nrta
     825           65 :    do spin=1,nsppol
     826          176 :      do itemp=1,self%ntemp
     827          124 :        iscal = itemp + (irta - 1) * self%ntemp
     828        25870 :        self%tau_dos(:, itemp, spin, irta) = out_valsdos(:, 1, iscal, spin)
     829              :      end do
     830              :    end do
     831              :  end do
     832              : 
     833              :  ! Free memory
     834           13 :  ABI_SFREE(out_tensdos)
     835           13 :  ABI_SFREE(tau_vals)
     836           13 :  ABI_SFREE(out_valsdos)
     837           13 :  ABI_SFREE(dummy_dosvecs)
     838           13 :  ABI_SFREE(vv_tens)
     839              : 
     840              :  ! Compute Onsager coefficients. Eq 9 of [[cite:Madsen2018]]
     841              :  ! See also Eqs 41, page 11 of https://arxiv.org/pdf/1402.6979.pdf
     842              :  !
     843              :  !      L^\alpha(\mu, T) = \int de \sigma(e, T) (e - mu)^\alpha (-df/de)
     844              :  !
     845              :  ! with \sigma(e, T) stored in vvtau_dos
     846              : 
     847           78 :  ABI_MALLOC(self%l0, (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     848           78 :  ABI_MALLOC(self%l1, (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     849           78 :  ABI_MALLOC(self%l2, (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     850              : 
     851           13 :  call onsager(0, self%l0)
     852           13 :  call onsager(1, self%l1)
     853           13 :  call onsager(2, self%l2)
     854              : 
     855           13 :  call cwtime_report(" compute_rta_onsanger", cpu, wall, gflops)
     856              : 
     857              :  ! Compute transport tensors, Eqs 12-15 of [[cite:Madsen2018]] and convert to SI units.
     858       334712 :  ABI_CALLOC(self%sigma,   (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     859       334712 :  ABI_CALLOC(self%seebeck, (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     860       334712 :  ABI_CALLOC(self%kappa,   (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     861       334712 :  ABI_CALLOC(self%pi,      (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     862       334712 :  ABI_CALLOC(self%zte,     (3, 3, self%nw, self%nsppol, self%ntemp, self%nrta))
     863              : 
     864              :  ! Sigma = L0
     865              :  !TODO : missing maxocc??
     866           13 :  fact0 = (siemens_SI / Bohr_meter / cryst%ucvol)
     867       334660 :  self%sigma = fact0 * self%l0
     868              : 
     869              :  ! Used to stored L0^-1
     870           39 :  ABI_MALLOC(l0inv_33nw, (3, 3, self%nw))
     871              : 
     872           39 :  do irta=1,self%nrta
     873           65 :    do spin=1,nsppol
     874          176 :      do itemp=1,self%ntemp
     875              : 
     876          124 :        TKelv = self%kTmesh(itemp) / kb_HaK; if (TKelv < one) Tkelv = one
     877              : 
     878              :        ! S = -1/T L0^-1 L1 = -1/T sigma L1
     879        25844 :        do iw=1,self%nw
     880        25720 :          call inv33(self%l0(:, :, iw, spin, itemp, irta), work_33)
     881       334360 :          l0inv_33nw(:,:,iw) = work_33
     882      3729524 :          self%seebeck(:,:,iw,spin,itemp,irta) = - (volt_SI / TKelv) * matmul(work_33, self%l1(:,:,iw,spin,itemp,irta))
     883              :        end do
     884              : 
     885              :        ! kappa = 1/T [L2 - L1 L0^-1 L1]
     886              :        ! HM: Check why do we need minus sign here to get consistent results with Boltztrap!
     887              :        ! MG: Likely because of a different definition of kappa.
     888        25844 :        do iw=1,self%nw
     889       334360 :          work_33 = self%l1(:, :, iw, spin, itemp, irta)
     890      2957800 :          work_33 = self%l2(:, :, iw, spin, itemp, irta) - matmul(work_33, matmul(l0inv_33nw(:, :, iw), work_33))
     891              :          !self%kappa(:,:,iw,spin, itemp,spin,irta) = - (volt_SI**2 * fact0 / TKelv) * work_33
     892       334484 :          self%kappa(:,:,iw,spin,itemp,irta) = + (volt_SI**2 * fact0 / TKelv) * work_33
     893              :        end do
     894              : 
     895              :        ! Peltier pi = -L1 L0^-1
     896        25844 :        do iw=1,self%nw
     897       334360 :          work_33 = self%l1(:, :, iw, spin, itemp, irta)
     898      2340644 :          self%pi(:,:,iw,spin,itemp,irta) = - volt_SI * matmul(work_33, l0inv_33nw(:, :, iw))
     899              :        end do
     900              : 
     901              :        ! ZT: S^T sigma S k^-1 T (tensor form with k=k_electronic only):
     902        25870 :        do iw=1,self%nw
     903       334360 :          S_33 = self%seebeck(:,:,iw,spin,itemp,irta)
     904      3780840 :          S_33 = matmul(matmul(transpose(S_33), self%sigma(:,:,iw,spin,itemp,irta)), S_33)
     905        25720 :          call inv33(self%kappa(:,:,iw,spin,itemp,irta), work_33)
     906      2340644 :          self%zte(:,:,iw,spin,itemp,irta) = matmul(S_33, work_33) * TKelv
     907              :        end do
     908              : 
     909              :      end do
     910              :    end do
     911              :  end do
     912              : 
     913           13 :  ABI_FREE(l0inv_33nw)
     914              : 
     915              :  !Here are computed the transport tensors at exact mu (exact temperature and not based on a grid)
     916              : 
     917              : !  do irta=1,self%nrta
     918              : !   do spin=1,nsppol
     919              : !     do itemp=1,self%ntemp
     920              : !
     921              : !       TKelv = self%kTmesh(itemp) / kb_HaK; if (TKelv < one) Tkelv = one
     922              : !
     923              : !       ! S = -1/T L11^-1 L12 = -1/T sigma^-1 L12
     924              : !         call inv33(self%l11_mu(:, :, spin, itemp, irta), work_33)
     925              : !        ! l0inv_33nw(:,:) = work_33
     926              : !         self%seebeck_mu(:,:,spin,itemp,irta) = - (volt_SI / TKelv) * matmul(work_33, self%l12_mu(:,:,spin,itemp,irta))
     927              : !
     928              : !
     929              : !       ! kappa = 1/T [L22 - L21 L11^-1 L12] (in RTA L12=L21)
     930              : !         call inv33(self%l11_mu(:, :, spin, itemp, irta), work_33)
     931              : !         work_33 = matmul(work_33,self%l12_mu(:, :, spin, itemp, irta))
     932              : !         work_33 = self%l22_mu(:, :, spin, itemp, irta) - matmul(self%l12_mu(:, :, spin, itemp, irta), work_33)
     933              : !         self%kappa_mu(:,:,spin,itemp,irta) = + (volt_SI**2 * fact0 / TKelv) * work_33
     934              : !
     935              : !
     936              : !         ! Peltier pi = -L12 L11^-1 (in RTA and only in RTA, if TR sym. is not broken)
     937              : !
     938              : !         call inv33(self%l11_mu(:, :, spin, itemp, irta), work_33)
     939              : !         self%pi_mu(:,:,spin,itemp,irta) = - volt_SI * matmul(self%l12_mu(:, :, spin, itemp, irta), work_33)
     940              : !
     941              : !     end do ! itemp
     942              : !   end do !spin
     943              : ! end do  !irta
     944              : 
     945              : 
     946              : 
     947              :  ! Compute the index of the Fermi level and handle possible out of range condition.
     948           13 :  ifermi = bisect(self%edos%mesh, self%ebands%fermie)
     949           13 :  if (ifermi == 0 .or. ifermi == self%nw) then
     950            0 :    ABI_ERROR("Bisection could not find the index of the Fermi level in edos%mesh!")
     951              :  end if
     952              : 
     953           13 :  max_occ = two / (self%nspinor * self%nsppol)
     954              : 
     955              :  ! Conductivity
     956           65 :  ABI_MALLOC(self%conductivity, (3, 3, self%ntemp, self%nsppol, self%nrta))
     957           26 :  do spin=1,self%nsppol
     958           88 :    do itemp=1,self%ntemp
     959          199 :      do irta=1,self%nrta
     960          558 :        do jj=1,3
     961         1612 :          do ii=1,3
     962         1488 :            self%conductivity(ii,jj,itemp,spin,irta) = self%sigma(ii, jj, ifermi, spin, itemp, irta) * 0.01 !m^-1 to cm^-1
     963              :          end do
     964              :        end do
     965              :      end do
     966              :    end do ! itemp
     967              :  end do ! spin
     968              : 
     969           52 :  ABI_MALLOC(self%resistivity, (3, 3, self%ntemp, self%nrta))
     970           39 :  do irta=1,self%nrta
     971          163 :   do itemp=1,self%ntemp
     972         2728 :     work_33 = sum(self%conductivity(:,:,itemp,:,irta), dim=3)
     973         1612 :     call inv33(work_33, mat33); mat33 = 1e+6_dp * mat33
     974         1638 :     self%resistivity(:, :, itemp, irta) = mat33
     975              :   end do
     976              :  end do
     977              : 
     978              : 
     979              : 
     980              :  ! Mobility
     981           65 :  ABI_MALLOC(self%n, (self%nw, self%ntemp, 2))
     982           91 :  ABI_MALLOC(self%mobility, (3, 3, self%nw, self%ntemp, 2, self%nsppol, self%nrta))
     983              : 
     984           26 :  do spin=1,self%nsppol
     985           88 :    do itemp=1,self%ntemp
     986              :      ! Compute carrier density
     987           62 :      kT = self%kTmesh(itemp)
     988              : 
     989              :      ! MG TODO: I think that here we should use mu_e instead of ifermi.
     990              :      ! Compute carrier density of electrons (ifermi:self%nw)
     991        12922 :      do iw=1,self%nw ! doping
     992              :        self%n(iw,itemp,1) = carriers(self%edos%mesh, self%edos%dos(:,spin) * max_occ, ifermi, self%nw, &
     993     34127822 :                                      kT, self%edos%mesh(iw)) / cryst%ucvol / Bohr_meter**3
     994              :      end do
     995              : 
     996              :      ! Compute carrier density of holes (1:ifermi)
     997        12922 :      do iw=1,self%nw ! doping
     998              :        self%n(iw,itemp,2) = carriers(self%edos%mesh, self%edos%dos(:,spin) * max_occ, 1, ifermi, &
     999     34127822 :                                      kT, self%edos%mesh(iw)) / cryst%ucvol / Bohr_meter**3
    1000              :      end do
    1001              : 
    1002        12922 :      self%n(:,itemp,2) = self%n(self%nw,itemp,2) - self%n(:,itemp,2)
    1003              : 
    1004              :      ! Compute mobility
    1005          199 :      do irta=1,self%nrta
    1006          434 :        do iel=1,2
    1007        51812 :          do iw=1,self%nw
    1008       206008 :            do jj=1,3
    1009       668720 :              do ii=1,3
    1010              :                call safe_div(self%sigma(ii, jj, iw, spin, itemp, irta) * 100**2, &
    1011              :                              e_Cb * self%n(iw, itemp, iel), &
    1012       617280 :                              zero, self%mobility(ii, jj, iw, itemp, iel, spin, irta))
    1013              :              end do
    1014              :            end do
    1015              :          end do
    1016              :        end do
    1017              :      end do
    1018              :    end do ! itemp
    1019              :  end do ! spin
    1020              : 
    1021              :  ! Compute RTA mobility
    1022           13 :  call self%compute_rta_mobility(cryst, comm)
    1023              : 
    1024           13 :  if (my_rank == master) then
    1025              :    ! Print RTA results to stdout and other external txt files (for the test suite)
    1026           13 :    call self%print_rta_txt_files(cryst, dtset, dtfil)
    1027              : 
    1028              :    ! Creates the netcdf file used to store the results of the calculation.
    1029           13 :    path = strcat(dtfil%filnam_ds(4), "_RTA.nc")
    1030           13 :    call wrtout(units, ch10//sjoin("- Writing RTA transport results to:", path))
    1031           13 :    NCF_CHECK(nctk_open_create(ncid, path , xmpi_comm_self))
    1032           13 :    call self%rta_ncwrite(cryst, dtset, ncid)
    1033           13 :    NCF_CHECK(nf90_close(ncid))
    1034              :  end if
    1035              : 
    1036           65 :  call cwtime_report(" compute_rta", cpu, wall, gflops)
    1037              : 
    1038              : contains
    1039              : 
    1040        25720 :  real(dp) function carriers(wmesh, dos, istart, istop, kT, mu)
    1041              : 
    1042              :  !Arguments -------------------------------------------
    1043              :  real(dp),intent(in) :: kT, mu
    1044              :  real(dp),intent(in) :: wmesh(self%nw), dos(self%nw)
    1045              :  integer,intent(in) :: istart, istop
    1046              : 
    1047              :  !Local variables -------------------------------------
    1048              :  integer :: iw
    1049        25720 :  real(dp) :: kernel(self%nw), integral(self%nw)
    1050              : 
    1051     68255520 :  kernel = zero
    1052     34153480 :  do iw=istart,istop
    1053     34153480 :    kernel(iw) = dos(iw) * occ_fd(wmesh(iw), kT, mu)
    1054              :  end do
    1055        25720 :  call simpson_int(self%nw, edos_step, kernel, integral)
    1056        25720 :  carriers = integral(self%nw)
    1057              : 
    1058        25720 :  end function carriers
    1059              : 
    1060              :  ! Compute L^\alpha(\mu, T) = \int de \sigma(e, T) (e - mu)^\alpha (-df/de)
    1061           39 :  subroutine onsager(order, lorder)
    1062              : 
    1063              :  !Arguments -------------------------------------------
    1064              :  integer,intent(in) :: order
    1065              :  real(dp),intent(out) :: lorder(3, 3, self%nw, self%nsppol, self%ntemp, self%nrta)
    1066              : 
    1067              :  !Local variables -------------------------------------
    1068              :  integer :: spin, iw, imu, irta
    1069              :  real(dp) :: mu, ee, kT
    1070           78 :  real(dp) :: kernel(self%nw,3,3,self%nsppol), integral(self%nw)
    1071              : 
    1072              :  ! Get spin degeneracy
    1073           39 :  max_occ = two / (self%nspinor * self%nsppol)
    1074              : 
    1075          117 :  do irta=1,self%nrta
    1076          489 :    do itemp=1,self%ntemp
    1077          372 :      kT = self%kTmesh(itemp)
    1078              :      ! Loop over chemical potentials mu
    1079        77610 :      do imu=1,self%nw
    1080        77160 :        mu = self%edos%mesh(imu)
    1081              : 
    1082              :        ! Build integrand for given mu
    1083    204766560 :        do iw=1,self%nw
    1084    204689400 :          ee = self%edos%mesh(iw)
    1085    204766560 :          if (order > 0) then
    1086   1910434400 :            kernel(iw,:,:,:) = - max_occ * self%vvtau_dos(iw,:,:,itemp,:,irta) * (ee - mu)** order * occ_dfde(ee, kT, mu)
    1087              :          else
    1088    955217200 :            kernel(iw,:,:,:) = - max_occ * self%vvtau_dos(iw,:,:,itemp,:,irta) * occ_dfde(ee, kT, mu)
    1089              :          end if
    1090              :        end do
    1091              : 
    1092              :        ! Integrate with simpson_int
    1093       154692 :        do spin=1,self%nsppol
    1094       385800 :          do jj=1,3
    1095      1003080 :            do ii=1,3
    1096       694440 :              call simpson_int(self%nw, edos_step, kernel(:,ii,jj, spin), integral)
    1097       925920 :              lorder(ii, jj, imu, spin, itemp, irta) = integral(self%nw)
    1098              :            end do
    1099              :          end do
    1100              :        end do
    1101              : 
    1102              :      end do ! imu
    1103              :    end do ! itemp
    1104              :  end do ! irta
    1105              : 
    1106           39 :  end subroutine onsager
    1107              : 
    1108              : end subroutine compute_rta
    1109              : !!***
    1110              : 
    1111              : !----------------------------------------------------------------------
    1112              : 
    1113              : !!****f* m_rta/compute_rta_mobility
    1114              : !! NAME
    1115              : !! compute_rta_mobility
    1116              : !!
    1117              : !! FUNCTION
    1118              : !!
    1119              : !! INPUTS
    1120              : !! cryst<crystal_t>=Crystalline structure
    1121              : !! comm=MPI communicator.
    1122              : !!
    1123              : !! SOURCE
    1124              : 
    1125           13 : subroutine compute_rta_mobility(self, cryst, comm)
    1126              : 
    1127              : !Arguments ------------------------------------
    1128              :  class(rta_t),intent(inout) :: self
    1129              :  type(crystal_t),intent(in) :: cryst
    1130              :  integer,intent(in) :: comm
    1131              : 
    1132              : !Local variables ------------------------------
    1133              :  integer :: nsppol, nkibz, ib, ik_ibz, spin, ii, jj, itemp, ieh, cnt, nprocs, irta, time_opt
    1134              :  real(dp) :: eig_nk, mu_e, linewidth, fact, fact0, max_occ, kT, wtk, cpu, wall, gflops
    1135              :  real(dp) :: vr(3), vv_tens(3,3), vv_tenslw(3,3), work_33(3,3), mat33(3,3) !, tmp_tens(3,3)
    1136              : !************************************************************************
    1137              : 
    1138           13 :  call cwtime(cpu, wall, gflops, "start")
    1139              : 
    1140           13 :  nprocs = xmpi_comm_size(comm)
    1141           13 :  nkibz = self%ebands%nkpt; nsppol = self%ebands%nsppol
    1142              : 
    1143           13 :  time_opt = 0 ! This to preserve the previous behaviour in which TR was not used.
    1144              :  !time_opt = -1 ! This to preserve the previous behaviour in which TR was not used.
    1145              : 
    1146         3563 :  ABI_CALLOC(self%mobility_mu, (3, 3, 2, nsppol, self%ntemp, self%nrta))
    1147         3550 :  ABI_CALLOC(self%conductivity_mu, (3, 3, 2, nsppol, self%ntemp, self%nrta))
    1148         1827 :  ABI_CALLOC(self%l11_mu, (3, 3, nsppol, self%ntemp, self%nrta))
    1149         1814 :  ABI_CALLOC(self%l12_mu, (3, 3, nsppol, self%ntemp, self%nrta))
    1150         1814 :  ABI_CALLOC(self%l22_mu, (3, 3, nsppol, self%ntemp, self%nrta))
    1151         1690 :  ABI_CALLOC(self%resistivity_mu, (3, 3, self%ntemp, self%nrta))
    1152         3511 :  self%conductivity_mu=zero
    1153         1775 :  self%l11_mu=zero
    1154         1775 :  self%l12_mu=zero
    1155         1775 :  self%l22_mu=zero
    1156         1651 :  self%resistivity_mu=zero
    1157              : ! ABI_CALLOC(self%seebeck_mu, (3, 3, 2, nsppol, self%ntemp, self%nrta))
    1158              : ! ABI_CALLOC(self%kappa_mu, (3, 3, 2, nsppol, self%ntemp, self%nrta))
    1159              : ! ABI_CALLOC(self%peltier_mu, (3, 3, 2, nsppol, self%ntemp, self%nrta))
    1160              :  ! Compute (e/h) carriers per unit cell at the different temperatures.
    1161          300 :  ABI_CALLOC(self%n_ehst, (2, self%nsppol, self%ntemp))
    1162           13 :  call self%ebands%get_carriers(self%ntemp, self%kTmesh, self%transport_mu_e, self%n_ehst)
    1163              : 
    1164              :  ! Compute conductivity_mu i.e. results in which lifetimes have been computed in a consistent way
    1165              :  ! with the same the Fermi level. In all the other cases, indeed, we assume that tau does not depend on ef.
    1166              :  !
    1167              :  ! sigma_RTA = -S e^2 / (N_k Omega) sum_\nk (v_\nk \otimes v_\nk) \tau_\nk (df^0/de_\nk)
    1168              :  !
    1169              :  ! with S the spin degeneracy factor.
    1170              :  !
    1171              :  ! TODO: Implement other tensors. Compare these results with the ones obtained with spectral sigma
    1172              :  ! In principle, they should be the same, in practice the integration of sigma requires enough resolution
    1173              :  ! around the band edge.
    1174              :  !print *, "in RTA max velocities", maxval(abs(self%vbks))
    1175           13 :  cnt = 0
    1176           26 :  do spin=1,nsppol
    1177         3582 :    do ik_ibz=1,nkibz
    1178              :      !cnt = cnt + 1; if (mod(cnt, nprocs) /= my_rank) cycle ! MPI parallelism.
    1179         3556 :      wtk = self%ebands%wtk(ik_ibz)
    1180              : 
    1181         7230 :      do ib=self%bmin,self%bmax
    1182         3661 :        eig_nk = self%ebands%eig(ib, ik_ibz, spin)
    1183              : 
    1184              :        ! Store outer product in vv_tens
    1185        14644 :        vr(:) = self%vbks(:, ib, ik_ibz, spin)
    1186              :        ! Don't remove this if: it makes the loop a bit faster and, most importantly,
    1187              :        ! it prevents intel from miscompiling the code.
    1188        14472 :        if (all(abs(vr) == zero)) cycle
    1189              : 
    1190          232 :        do ii=1,3
    1191          754 :          do jj=1,3
    1192          696 :            vv_tens(ii, jj) = vr(ii) * vr(jj)
    1193              :          end do
    1194              :        end do
    1195              : 
    1196              :        ! Symmetrize tensor.
    1197              :        !print *, "intens", vv_tens
    1198          754 :        vv_tens = cryst%symmetrize_cart_tens33(vv_tens, time_opt)
    1199              :        !print *, "out_tens", vv_tens
    1200              : 
    1201              :        ! Multiply by the lifetime (SERTA or MRTA)
    1202         3730 :        do irta=1,self%nrta
    1203         4273 :          do itemp=1,self%ntemp
    1204          496 :            kT = self%kTmesh(itemp)
    1205          496 :            mu_e = self%transport_mu_e(itemp)
    1206          496 :            ieh = 2; if (eig_nk >= mu_e) ieh = 1
    1207          496 :            linewidth = self%linewidths(itemp, ib, ik_ibz, spin, irta)
    1208              :            !print *, linewidth, wtk, occ_dfde(eig_nk, kT, mu_e), "tens", vv_tens
    1209         6448 :            call safe_div( - wtk * vv_tens * occ_dfde(eig_nk, kT, mu_e), two * linewidth, zero, vv_tenslw)
    1210              :            self%conductivity_mu(:, :, ieh, spin, itemp, irta) = self%conductivity_mu(:, :, ieh, spin, itemp, irta) &
    1211         6448 :              + vv_tenslw(:, :)
    1212        15376 :            self%l11_mu(:, :, spin, itemp, irta) = sum(self%conductivity_mu(:,:,:, spin, itemp, irta), dim=3) !sum over ieh (holes and e-)
    1213              :         !Here I implement the other onsager coefficients at the correct mu
    1214         6448 :            call safe_div( - wtk * vv_tens * occ_dfde(eig_nk, kT, mu_e)*(eig_nk-mu_e), two * linewidth, zero, vv_tenslw)
    1215         6448 :            self%l12_mu(:, :, spin, itemp, irta)=self%l12_mu(:, :, spin, itemp, irta)+vv_tenslw(:, :)
    1216         6448 :            call safe_div( - wtk * vv_tens * occ_dfde(eig_nk, kT, mu_e)*(eig_nk-mu_e)**2, two * linewidth, zero, vv_tenslw)
    1217         6564 :            self%l22_mu(:, :, spin, itemp, irta)=self%l22_mu(:, :, spin, itemp, irta)+vv_tenslw(:, :)
    1218              :          end do
    1219              :        end do
    1220              :      end do
    1221              : 
    1222              :    end do ! ik_ibz
    1223              :  end do ! spin
    1224              : 
    1225              :  !call xmpi_sum(self%conductivity_mu, comm, ierr)
    1226              : 
    1227              :  ! Get units conversion factor including spin degeneracy.
    1228           13 :  max_occ = two / (self%nspinor * self%nsppol)
    1229           13 :  fact0 = max_occ * (siemens_SI / Bohr_meter / cryst%ucvol) / 100
    1230         3511 :  self%conductivity_mu = fact0 * self%conductivity_mu  ! siemens cm^-1
    1231         1775 :  self%l11_mu = max_occ * self%l11_mu
    1232         1775 :  self%l12_mu = max_occ * self%l12_mu
    1233         1775 :  self%l22_mu = max_occ * self%l22_mu
    1234              : 
    1235              : !Same for resistivity_mu (at correct mu)
    1236              : 
    1237              : ! ABI_MALLOC(self%resistivity_mu, (3, 3, self%ntemp, self%nrta))
    1238           39 :  do irta=1,self%nrta
    1239          163 :   do itemp=1,self%ntemp
    1240              : 
    1241         2728 :     work_33 = sum(self%l11_mu(:,:,:,itemp,irta), dim=3) !sum over spins
    1242         1612 :     work_33 = work_33*fact0
    1243         1612 :     call inv33(work_33, mat33); mat33 = 1e+6_dp * mat33
    1244         1638 :     self%resistivity_mu(:, :, itemp, irta) = mat33
    1245              :   end do
    1246              :  end do
    1247              : 
    1248              : 
    1249              :  !TODO: implement for mobility as well (verify)
    1250              :  ! Scale by the carrier concentration
    1251              :  fact = 100**3 / e_Cb
    1252           39 :  do irta=1,self%nrta
    1253           65 :    do spin=1,nsppol
    1254          176 :      do itemp=1,self%ntemp
    1255          398 :        do ieh=1,2 ! e/h
    1256              :          call safe_div(fact * self%conductivity_mu(:,:,ieh,spin,itemp, irta), &
    1257              :                        self%n_ehst(ieh, spin, itemp) / cryst%ucvol / Bohr_meter**3, zero, &
    1258         3348 :                        self%mobility_mu(:,:,ieh,spin,itemp,irta))
    1259              :        end do
    1260              :      end do
    1261              :    end do
    1262              :  end do
    1263              : 
    1264           13 :  call cwtime_report(" compute_rta_mobility", cpu, wall, gflops)
    1265              : 
    1266           26 : end subroutine compute_rta_mobility
    1267              : !!***
    1268              : 
    1269              : !----------------------------------------------------------------------
    1270              : 
    1271              : !!****f* m_rta/rta_ncwrite
    1272              : !! NAME
    1273              : !! rta_ncwrite
    1274              : !!
    1275              : !! FUNCTION
    1276              : !!
    1277              : !! INPUTS
    1278              : !! cryst<crystal_t>=Crystalline structure
    1279              : !! dtset<dataset_type>=All input variables for this dataset.
    1280              : !! ncid=Netcdf file handle.
    1281              : !!
    1282              : !! SOURCE
    1283              : 
    1284           13 : subroutine rta_ncwrite(self, cryst, dtset, ncid)
    1285              : 
    1286              : !Arguments --------------------------------------
    1287              :  class(rta_t),intent(in) :: self
    1288              :  type(crystal_t),intent(in) :: cryst
    1289              :  type(dataset_type),intent(in) :: dtset
    1290              :  integer,intent(in) :: ncid
    1291              : 
    1292              : !Local variables --------------------------------
    1293              :  integer :: ncerr, ii
    1294              :  real(dp) :: cpu, wall, gflops
    1295           26 :  real(dp) :: work(dtset%nsppol)
    1296              : !************************************************************************
    1297              : 
    1298           13 :  call cwtime(cpu, wall, gflops, "start")
    1299              : 
    1300              :  ! Write to netcdf file
    1301           13 :  NCF_CHECK(cryst%ncwrite(ncid))
    1302           13 :  NCF_CHECK(self%ebands%ncwrite(ncid))
    1303           13 :  NCF_CHECK(self%edos%ncwrite(ncid))
    1304              : 
    1305              :  !nctk_copy from sigeph?
    1306              :  !    nctkarr_t("eph_ngqpt_fine", "int", "three"), &
    1307              : 
    1308              :  ncerr = nctk_def_dims(ncid, [ &
    1309              :     nctkdim_t("ntemp", self%ntemp), nctkdim_t("nrta", self%nrta), nctkdim_t("nsppol", self%nsppol), &
    1310              :     nctkdim_t("nkcalc", self%nkcalc), nctkdim_t("nkibz", self%ebands%nkpt) &
    1311           78 :  ], defmode=.True.)
    1312           13 :  NCF_CHECK(ncerr)
    1313              : 
    1314              :  ncerr = nctk_def_arrays(ncid, [ &
    1315              :     nctkarr_t('transport_ngkpt', "int", "three"), &
    1316              :     nctkarr_t('sigma_erange', "dp", "two"), &
    1317              :     nctkarr_t("kcalc2ibz", "int", "nkcalc, six"), &
    1318              :     nctkarr_t("kcalc2ebands", "int", "six, nkcalc"), &
    1319              :     nctkarr_t("kibz", "dp", "three, nkibz"), &
    1320              :     nctkarr_t('kTmesh', "dp", "ntemp"), &
    1321              :     nctkarr_t('transport_mu_e', "dp", "ntemp"), &
    1322              :     nctkarr_t('n_ehst', "dp", "two, nsppol, ntemp"), &
    1323              :     nctkarr_t('eph_mu_e', "dp", "ntemp"), &
    1324              :     nctkarr_t('vb_max', "dp", "nsppol"), &
    1325              :     nctkarr_t('cb_min', "dp", "nsppol"), &
    1326              :     nctkarr_t('vv_dos', "dp", "edos_nw, three, three, nsppol"), &
    1327              :     nctkarr_t('vvtau_dos', "dp", "edos_nw, three, three, ntemp, nsppol, nrta"), &
    1328              :     nctkarr_t('tau_dos', "dp", "edos_nw, ntemp, nsppol, nrta"), &
    1329              :     nctkarr_t('L0', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1330              :     nctkarr_t('L1', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1331              :     nctkarr_t('L2', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1332              :     nctkarr_t('sigma', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1333              :     nctkarr_t('kappa', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1334              :     nctkarr_t('zte', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1335              :     nctkarr_t('seebeck', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1336              :     nctkarr_t('pi', "dp", "three, three, edos_nw, nsppol, ntemp, nrta"), &
    1337              :     nctkarr_t('mobility', "dp", "three, three, edos_nw, ntemp, two, nsppol, nrta"), &
    1338              :     nctkarr_t('conductivity', "dp", "three, three, ntemp, nsppol, nrta"), &
    1339              :     nctkarr_t('resistivity', "dp", "three, three, ntemp, nrta"), &
    1340              :     nctkarr_t('N', "dp", "edos_nw, ntemp, two"), &
    1341              :     !nctkarr_t('conductivity_mu',"dp", "three, three, two, nsppol, ntemp, nrta")], &
    1342              :     nctkarr_t('mobility_mu', "dp", "three, three, two, nsppol, ntemp, nrta")], &
    1343          364 :  defmode=.True.)
    1344           13 :  NCF_CHECK(ncerr)
    1345              : 
    1346           26 :  ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "assume_gap"])
    1347           13 :  NCF_CHECK(ncerr)
    1348              :  ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
    1349           65 :     "eph_extrael", "eph_fermie", "transport_extrael", "transport_fermie"])
    1350           13 :  NCF_CHECK(ncerr)
    1351              : 
    1352              :  ! Write data.
    1353           13 :  ii = 0; if (self%assume_gap) ii = 1
    1354           39 :  ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: "assume_gap"], [ii], datamode=.True.)
    1355              : 
    1356              :  ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: &
    1357              :    "eph_extrael", "eph_fermie", "transport_extrael", "transport_fermie"], &
    1358          117 :    [self%eph_extrael, self%eph_fermie, self%transport_extrael, self%transport_fermie])
    1359           13 :  NCF_CHECK(ncerr)
    1360              : 
    1361           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "transport_ngkpt"), dtset%transport_ngkpt))
    1362           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "sigma_erange"), dtset%sigma_erange))
    1363           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kcalc2ibz"), self%kcalc2ibz))
    1364           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kcalc2ebands"), self%kcalc2ebands))
    1365           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kibz"), self%ebands%kptns))
    1366           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kTmesh"), self%kTmesh))
    1367           13 :  if (self%assume_gap) then
    1368           12 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vb_max"), self%gaps%vb_max))
    1369           12 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "cb_min"), self%gaps%cb_min))
    1370              :  else
    1371              :    ! Set vbm and cbm to fermie if metal.
    1372            2 :    work(:) = self%ebands%fermie
    1373            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vb_max"), work))
    1374            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "cb_min"), work))
    1375              :  end if
    1376           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "eph_mu_e"), self%eph_mu_e))
    1377           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "transport_mu_e"), self%transport_mu_e))
    1378           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "n_ehst"), self%n_ehst))
    1379           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vv_dos"), self%vv_dos))
    1380           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vvtau_dos"),  self%vvtau_dos))
    1381           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "tau_dos"),  self%tau_dos))
    1382           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "L0"), self%l0))
    1383           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "L1"), self%l1))
    1384           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "L2"), self%l2))
    1385           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "sigma"),   self%sigma))
    1386           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kappa"),   self%kappa))
    1387           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "zte"),   self%zte))
    1388           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "seebeck"), self%seebeck))
    1389           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "pi"),      self%pi))
    1390           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "N"), self%n))
    1391           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "mobility"), self%mobility))
    1392           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "conductivity"), self%conductivity))
    1393           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "resistivity"), self%resistivity))
    1394           13 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "mobility_mu"), self%mobility_mu))
    1395              :  !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "conductivity_mu"), self%conductivity_mu))
    1396              :  !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "resistivity_mu"), self%resistivity_mu))
    1397              : 
    1398           13 :  call cwtime_report(" rta_ncwrite", cpu, wall, gflops)
    1399              : 
    1400           13 : end subroutine rta_ncwrite
    1401              : !!***
    1402              : 
    1403              : !----------------------------------------------------------------------
    1404              : 
    1405              : !!****f* m_rta/print_rta_txt_files
    1406              : !! NAME
    1407              : !! print_rta_txt_files
    1408              : !!
    1409              : !! FUNCTION
    1410              : !!
    1411              : !! INPUTS
    1412              : !! cryst<crystal_t>=Crystalline structure
    1413              : !! dtset<dataset_type>=All input variables for this dataset.
    1414              : !! dtfil<datafiles_type>=variables related to files.
    1415              : !!
    1416              : !! SOURCE
    1417              : 
    1418           13 : subroutine print_rta_txt_files(self, cryst, dtset, dtfil)
    1419              : 
    1420              : !Arguments --------------------------------------
    1421              :  class(rta_t),intent(in) :: self
    1422              :  type(crystal_t),intent(in) :: cryst
    1423              :  type(dataset_type),intent(in) :: dtset
    1424              :  type(datafiles_type),intent(in) :: dtfil
    1425              : 
    1426              : !Local variables --------------------------------
    1427              :  integer :: itemp, spin, irta, ii, nsp
    1428              :  real(dp) :: TKelv
    1429              :  character(len=500) :: msg, pre, rta_type
    1430              :  integer :: units(2)
    1431              :  character(len=2) :: components(3)
    1432              :  real(dp) :: mat33(3,3),  work33(3,3)
    1433              : !************************************************************************
    1434              : 
    1435           39 :  units = [std_out, ab_out]
    1436           13 :  call wrtout(units, ch10//' Transport (RTA) calculation results, chemical potential adjusted with T:', newlines=1)
    1437           52 :  components = ["xx", "yy", "zz"]
    1438              : 
    1439           39 :  do irta=1,self%nrta
    1440           26 :    if (irta == 1) rta_type = "SERTA"
    1441           26 :    if (irta == 2) rta_type = "MRTA"
    1442              : 
    1443           26 :    if (self%assume_gap) then
    1444              :      ! SemiConductor
    1445           96 :      do ii=1,3
    1446           72 :        call wrtout(units, sjoin(" Cartesian component of", rta_type, "mobility tensor:", components(ii)))
    1447           72 :        write(msg, "(a16,a32,a32)") 'Temperature [K]', 'e/h density [cm^-3]', 'e/h mobility [cm^2/Vs]'
    1448           72 :        call wrtout(units, msg)
    1449              : 
    1450          144 :        do spin=1,self%nsppol
    1451           72 :          if (self%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    1452              : 
    1453          504 :          do itemp=1,self%ntemp
    1454              :            write(msg,"(f16.2,2e16.2,2f16.2)") &
    1455          360 :              self%kTmesh(itemp) / kb_HaK, &
    1456          360 :              self%n_ehst(1, spin, itemp) / cryst%ucvol / Bohr_cm**3, &
    1457          360 :              self%n_ehst(2, spin, itemp) / cryst%ucvol / Bohr_cm**3, &
    1458          360 :              self%mobility_mu(ii, ii, 1, spin, itemp, irta), &
    1459          720 :              self%mobility_mu(ii, ii, 2, spin, itemp, irta)
    1460          432 :            call wrtout(units, msg)
    1461              :          end do ! itemp
    1462              :        end do ! spin
    1463           96 :        call wrtout(units, ch10)
    1464              :      end do ! ii
    1465              : 
    1466              :    else
    1467              :      ! Metals. Print conductivity (spin resolved) and resistivity (no spin resolved)
    1468              : !    do ii=1,2
    1469              : !      if (ii == 1) msg = sjoin(" Conductivity [Siemens cm^-1] using ", rta_type, "approximation")
    1470              : !      if (ii == 2) msg = sjoin(" Resistivity [micro-Ohm cm] using ", rta_type, "approximation")
    1471              : !      call wrtout(units, msg)
    1472              : !
    1473              : !      nsp = self%nsppol; if (ii == 2) nsp = 1
    1474              : !      do spin=1,nsp
    1475              : !        if (nsp == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    1476              : !        write(msg, "(4a16)") 'Temperature (K)', 'xx', 'yy', 'zz'
    1477              : !        call wrtout(units, msg)
    1478              : !        do itemp=1,self%ntemp
    1479              : !          if (ii == 1) then
    1480              : !            mat33 = self%conductivity(:,:,itemp,spin,irta)
    1481              : !          else
    1482              : !            mat33 = self%resistivity(:,:,itemp,irta)
    1483              : !          end if
    1484              : !          write(msg,"(f16.2,3e16.6)") self%kTmesh(itemp) / kb_HaK, mat33(1,1), mat33(2,2), mat33(3,3)
    1485              : !          call wrtout(units, msg)
    1486              : !        end do !itemp
    1487              : !      end do !spin
    1488              : !      call wrtout(units, ch10)
    1489              : !    end do
    1490              : 
    1491              :      !For coefficients calculated at exact mu (i.e for mu calculated at exact temp.):
    1492              :      !TODO: do the same for SM and thus mobility
    1493              : 
    1494            6 :      do ii=1,2
    1495            4 :        if (ii == 1) msg = sjoin(" Conductivity [Siemens cm^-1] using ", rta_type, "approximation")
    1496            4 :        if (ii == 2) msg = sjoin(" Resistivity [micro-Ohm cm] using ", rta_type, "approximation")
    1497            4 :        call wrtout(units, msg)
    1498              : 
    1499           12 :        do itemp=1, self%ntemp
    1500            8 :          nsp = self%nsppol; if (ii == 2) nsp = 1
    1501           20 :          do spin=1,nsp
    1502            8 :            if (nsp == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    1503            8 :            write(msg, "(4a16)") 'Temperature (K)', 'xx', 'yy', 'zz'
    1504            8 :            call wrtout(units, msg)
    1505              : 
    1506            8 :            if (ii == 1) then
    1507          124 :              mat33 = sum(self%conductivity_mu(:,:,:,spin, itemp, irta), dim=3)
    1508              :            else
    1509           52 :              mat33 = self%resistivity_mu(:,:,itemp,irta)
    1510              :            end if
    1511            8 :            write(msg,"(f16.2,3e16.6)") self%kTmesh(itemp) / kb_HaK, mat33(1,1), mat33(2,2), mat33(3,3)
    1512           16 :            call wrtout(units, msg)
    1513              :          end do !spin
    1514              :        end do !itemp
    1515            6 :        call wrtout(units, ch10)
    1516              :      end do
    1517              :    end if
    1518              : 
    1519           26 :    msg = sjoin(" Seebeck [Volts / Kelvin] using ", rta_type, "approximation")
    1520           26 :    call wrtout(units, msg)
    1521          150 :    do itemp=1, self%ntemp
    1522              :      !TODO : what is the following line? Resets 0 Kelvin to 1 Kelvin minimum T??? a bit arbitrary. Should handle T=0 more cleanly
    1523          124 :      TKelv = self%kTmesh(itemp) / kb_HaK; if (TKelv < one) Tkelv = one
    1524          124 :      nsp = self%nsppol;
    1525          274 :      do spin=1,nsp
    1526          124 :        if (nsp == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    1527          124 :        write(msg, "(4a16)") 'Temperature (K)', 'xx', 'yy', 'zz'
    1528          124 :        call wrtout(units, msg)
    1529          124 :        call inv33(self%l11_mu(:, :, spin, itemp, irta), work33)
    1530         9796 :        mat33 = - (volt_SI / TKelv) * matmul(work33, self%l12_mu(:,:,spin,itemp,irta))
    1531          124 :        write(msg,"(f16.2,3e16.6)") TKelv, mat33(1,1), mat33(2,2), mat33(3,3)
    1532          248 :        call wrtout(units, msg)
    1533              :      end do !spin
    1534              :    end do !itemp
    1535           26 :    call wrtout(units, ch10)
    1536              : 
    1537           26 :    msg = sjoin(" Kappa [W/m*K] using ", rta_type, "approximation")
    1538           26 :    call wrtout(units, msg)
    1539          150 :    do itemp=1, self%ntemp
    1540          124 :      TKelv = self%kTmesh(itemp) / kb_HaK; if (TKelv < one) Tkelv = one
    1541          124 :      nsp = self%nsppol;
    1542          274 :      do spin=1,nsp
    1543          124 :        if (nsp == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    1544          124 :        write(msg, "(4a16)") 'Temperature (K)', 'xx', 'yy', 'zz'
    1545          124 :        call wrtout(units, msg)
    1546          124 :          call inv33(self%l11_mu(:, :, spin, itemp, irta), work33)
    1547        26412 :          mat33 = + (volt_SI**2 * (siemens_SI / Bohr_meter / cryst%ucvol) / TKelv) * (self%l22_mu(:,:,spin,itemp,irta) - matmul(self%l12_mu(:,:,spin,itemp,irta),matmul(work33,self%l12_mu(:,:,spin,itemp,irta))))
    1548          124 :        write(msg,"(f16.2,3e16.6)") TKelv, mat33(1,1), mat33(2,2), mat33(3,3)
    1549          248 :        call wrtout(units, msg)
    1550              :      end do !spin
    1551              :    end do !itemp
    1552           26 :    call wrtout(units, ch10)
    1553              : 
    1554           26 :    msg = sjoin(" Peltier [Volts] using ", rta_type, "approximation")
    1555           26 :    call wrtout(units, msg)
    1556          150 :    do itemp=1, self%ntemp
    1557          124 :      TKelv = self%kTmesh(itemp) / kb_HaK; if (TKelv < one) Tkelv = one
    1558          124 :      nsp = self%nsppol;
    1559          274 :      do spin=1,nsp
    1560          124 :        if (nsp == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    1561          124 :        write(msg, "(4a16)") 'Temperature (K)', 'xx', 'yy', 'zz'
    1562          124 :        call wrtout(units, msg)
    1563          124 :          call inv33(self%l11_mu(:, :, spin, itemp, irta), work33)
    1564         9920 :          mat33 = - volt_SI * matmul(self%l12_mu(:,:,spin,itemp,irta), work33)
    1565          124 :        write(msg,"(f16.2,3e16.6)") TKelv, mat33(1,1), mat33(2,2), mat33(3,3)
    1566          248 :        call wrtout(units, msg)
    1567              :      end do !spin
    1568              :    end do !itemp
    1569           39 :    call wrtout(units, ch10)
    1570              : 
    1571              : 
    1572              : 
    1573              :  end do ! irta
    1574              : 
    1575           39 :  do irta=1,self%nrta
    1576           13 :    select case (irta)
    1577              :    case (1)
    1578           13 :      pre = "_SERTA"
    1579              :    case (2)
    1580           13 :      pre = "_MRTA"
    1581              :    case default
    1582           26 :      ABI_ERROR(sjoin("Don't know how to handle irta:", itoa(irta)))
    1583              :    end select
    1584           26 :    call self%write_tensor(dtset, irta, "sigma", self%sigma(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_SIGMA"))
    1585           26 :    call self%write_tensor(dtset, irta, "seebeck", self%seebeck(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_SBK"))
    1586           26 :    call self%write_tensor(dtset, irta, "kappa", self%kappa(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_KAPPA"))
    1587           26 :    call self%write_tensor(dtset, irta, "zte", self%zte(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_ZTE"))
    1588           39 :    call self%write_tensor(dtset, irta, "pi", self%pi(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_PI"))
    1589              :  end do
    1590              : 
    1591           13 : end subroutine print_rta_txt_files
    1592              : !!***
    1593              : 
    1594              : !----------------------------------------------------------------------
    1595              : 
    1596              : !!****f* m_rta/write_tensor
    1597              : !! NAME
    1598              : !!
    1599              : !! FUNCTION
    1600              : !!
    1601              : !! INPUTS
    1602              : !!
    1603              : !! SOURCE
    1604              : 
    1605          130 : subroutine write_tensor(self, dtset, irta, header, values, path)
    1606              : 
    1607              : !Arguments --------------------------------------
    1608              :  class(rta_t),intent(in) :: self
    1609              :  type(dataset_type),intent(in) :: dtset
    1610              :  integer,intent(in) :: irta
    1611              :  character(len=*),intent(in) :: header
    1612              :  real(dp),intent(in) :: values(:,:,:,:,:)
    1613              :  character(len=*),intent(in) :: path
    1614              : 
    1615              : !Local variables --------------------------------
    1616              :  integer :: itemp, iw, ount
    1617              :  character(len=500) :: msg, rta_type
    1618          130 :  real(dp),allocatable :: tmp_values(:,:,:,:,:)
    1619              : !************************************************************************
    1620              : 
    1621          130 :  if (open_file(trim(path), msg, newunit=ount, form="formatted", action="write", status='unknown') /= 0) then
    1622            0 :    ABI_ERROR(msg)
    1623              :  end if
    1624              : 
    1625          130 :  if (irta == 1) rta_type = "RTA type: Self-energy relaxation time approximation (SERTA)"
    1626          130 :  if (irta == 2) rta_type = "RTA type: Momentum relaxation time approximation (MRTA)"
    1627              : 
    1628              :  ! write header
    1629          130 :  write(ount, "(2a)")"# ", trim(header)
    1630          130 :  write(ount, "(2a)")"# ", trim(rta_type)
    1631              :  ! TODO: Units ?
    1632          130 :  write(ount, "(a, 3(i0, 1x))")"#", dtset%transport_ngkpt
    1633          130 :  write(ount, "(a)")"#"
    1634              : 
    1635              :  ! This to improve portability of the unit tests.
    1636          130 :  call alloc_copy(values, tmp_values)
    1637      1673170 :  where (abs(values) > tol30)
    1638              :    tmp_values = values
    1639              :  else where
    1640              :    tmp_values = zero
    1641              :  end where
    1642              : 
    1643              :  ! (nw, 3, 3, nsppol, ntemp)
    1644          130 :  if (self%nsppol == 1) then
    1645          750 :    do itemp=1, self%ntemp
    1646          620 :      write(ount, "(/, a, 1x, f16.2)")"# T = ", self%kTmesh(itemp) / kb_HaK
    1647          620 :      write(ount, "(a)")"# Energy [Ha], (xx, yx, zx, xy, yy, zy, xz, yz, zz) Cartesian components of tensor."
    1648       129350 :      do iw=1,self%nw
    1649       129220 :        write(ount, "(10(es16.6))")self%edos%mesh(iw), tmp_values(:, :, iw, 1, itemp)
    1650              :      end do
    1651              :    end do
    1652          130 :   write(ount, "(a)")""
    1653              :  else
    1654            0 :    do itemp=1, self%ntemp
    1655            0 :      write(ount, "(/, a, 1x, f16.2)")"# T = ", self%kTmesh(itemp) / kb_HaK
    1656              :      write(ount, "(a)") &
    1657            0 :        "# Energy [Ha], (xx, yx, zx, xy, yy, zy, xz, yz, zz) Cartesian components of tensor for spin up followed by spin down."
    1658            0 :      do iw=1,self%nw
    1659            0 :        write(ount, "(19(es16.6))")self%edos%mesh(iw), tmp_values(:, :, iw, 1, itemp), tmp_values(:, :, iw, 2, itemp)
    1660              :      end do
    1661              :    end do
    1662            0 :   write(ount, "(a)")""
    1663              :  end if
    1664              : 
    1665          130 :  close(ount)
    1666              : 
    1667          130 :  ABI_FREE(tmp_values)
    1668              : 
    1669          130 : end subroutine write_tensor
    1670              : !!***
    1671              : 
    1672              : !----------------------------------------------------------------------
    1673              : 
    1674              : !!****f* m_rta/rta_free
    1675              : !! NAME
    1676              : !! rta_free
    1677              : !!
    1678              : !! FUNCTION
    1679              : !!  Free dynamic memory.
    1680              : !!
    1681              : !! INPUTS
    1682              : !!
    1683              : !! SOURCE
    1684              : 
    1685           13 : subroutine rta_free(self)
    1686              : 
    1687              : !Arguments --------------------------------------
    1688              :  class(rta_t),intent(inout) :: self
    1689              : 
    1690           13 :  ABI_SFREE(self%n)
    1691           13 :  ABI_SFREE(self%vv_dos)
    1692           13 :  ABI_SFREE(self%vvtau_dos)
    1693           13 :  ABI_SFREE(self%tau_dos)
    1694           13 :  ABI_SFREE(self%bstart_ks)
    1695           13 :  ABI_SFREE(self%bstop_ks)
    1696           13 :  ABI_SFREE(self%nbcalc_ks)
    1697           13 :  ABI_SFREE(self%kcalc2ibz)
    1698           13 :  ABI_SFREE(self%kcalc2ebands)
    1699           13 :  ABI_SFREE(self%kTmesh)
    1700           13 :  ABI_SFREE(self%eminmax_spin)
    1701           13 :  ABI_SFREE(self%eph_mu_e)
    1702           13 :  ABI_SFREE(self%transport_mu_e)
    1703           13 :  ABI_SFREE(self%vbks)
    1704           13 :  ABI_SFREE(self%linewidths)
    1705           13 :  ABI_SFREE(self%l0)
    1706           13 :  ABI_SFREE(self%l1)
    1707           13 :  ABI_SFREE(self%l2)
    1708           13 :  ABI_SFREE(self%sigma)
    1709           13 :  ABI_SFREE(self%mobility)
    1710           13 :  ABI_SFREE(self%conductivity)
    1711           13 :  ABI_SFREE(self%resistivity)
    1712           13 :  ABI_SFREE(self%seebeck)
    1713           13 :  ABI_SFREE(self%kappa)
    1714           13 :  ABI_SFREE(self%zte)
    1715           13 :  ABI_SFREE(self%pi)
    1716           13 :  ABI_SFREE(self%mobility_mu)
    1717           13 :  ABI_SFREE(self%conductivity_mu)
    1718           13 :  ABI_SFREE(self%resistivity_mu)
    1719           13 :  ABI_SFREE(self%l11_mu)
    1720           13 :  ABI_SFREE(self%l12_mu)
    1721           13 :  ABI_SFREE(self%l22_mu)
    1722           13 :  ABI_SFREE(self%n_ehst)
    1723              : 
    1724           13 :  call self%ebands%free()
    1725           13 :  call self%gaps%free()
    1726           13 :  call self%edos%free()
    1727              : 
    1728           13 : end subroutine rta_free
    1729              : !!***
    1730              : 
    1731              : !----------------------------------------------------------------------
    1732              : 
    1733              : !!****f* m_rta/ibte_driver
    1734              : !! NAME
    1735              : !! ibte_driver
    1736              : !!
    1737              : !! FUNCTION
    1738              : !! Driver to compute transport properties within the IBTE.
    1739              : !!
    1740              : !! INPUTS
    1741              : !! dtfil<datafiles_type>=variables related to files.
    1742              : !! ngfftc(18)=Coarse FFT mesh
    1743              : !! dtset<dataset_type>=All input variables for this dataset.
    1744              : !! ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
    1745              : !! cryst<crystal_t>=Crystalline structure
    1746              : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
    1747              : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
    1748              : !! comm=MPI communicator.
    1749              : !!
    1750              : !! SOURCE
    1751              : 
    1752            1 : subroutine ibte_driver(dtfil, ngfftc, dtset, ebands, cryst, pawtab, psps, comm)
    1753              : 
    1754              : !Arguments ------------------------------------
    1755              : !scalars
    1756              :  integer, intent(in) :: comm
    1757              :  type(datafiles_type),intent(in) :: dtfil
    1758              :  type(dataset_type),intent(in) :: dtset
    1759              :  type(crystal_t),intent(in) :: cryst
    1760              :  type(ebands_t),intent(in) :: ebands
    1761              :  type(pseudopotential_type),intent(in) :: psps
    1762              : !arrays
    1763              :  integer,intent(in) :: ngfftc(18)
    1764              :  type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
    1765              : 
    1766              : !Local variables ------------------------------
    1767              :  integer,parameter :: master = 0
    1768              :  integer :: iet, max_et
    1769              :  integer :: spin, ikcalc, nkcalc, nbsum, nbcalc, itemp, iter, ierr, bsize
    1770              :  integer :: nkibz, nsppol, band_k, ik_ibz, bmin, bmax, band_sum, ntemp, ii, jj, iq_sum, nsp
    1771              :  integer :: ikq_ibz, isym_kq, trev_kq, cnt, tag, nprocs, receiver, my_rank, isym, itime, isym_lgk
    1772              :  integer :: ncid, grp_ncid, ncerr
    1773              :  real(dp) :: kT, mu_e, e_nk, dfde_nk, tau_nk, lw_nk, max_adiff, cpu, wall, gflops, abs_tol, rtmp
    1774              :  logical :: send_data
    1775              :  character(len=500) :: msg
    1776              :  character(len=fnlen) :: path
    1777            1 :  type(rta_t) :: ibte
    1778              : !arrays
    1779              :  integer :: units(2), dims(4)
    1780            1 :  logical,allocatable :: converged(:)
    1781              :  real(dp) :: vec3(3), sym_vec(3), mat33(3,3), f_kq(3), work33(3,3)
    1782              :  real(dp) :: inv_sig_p(3,3)
    1783            3 :  real(dp) :: fsum_eh(3,2,ebands%nsppol), max_adiff_spin(ebands%nsppol)
    1784            2 :  real(dp) :: onsager(3,3,3,ebands%nsppol)
    1785            1 :  real(dp),pointer :: sig_p(:,:,:,:), mob_p(:,:,:,:), sbk_p(:,:,:), kappa_p(:,:,:), pi_p(:,:,:)
    1786            1 :  real(dp),target,allocatable :: ibte_sigma(:,:,:,:,:), ibte_mob(:,:,:,:,:), ibte_rho(:,:,:)
    1787            1 :  real(dp),target,allocatable :: ibte_seebeck(:,:,:,:), ibte_kappa(:,:,:,:), ibte_pi(:,:,:,:)
    1788            1 :  real(dp),allocatable :: grp_srate(:,:,:,:), fkn_in(:,:,:,:), fkn_out(:,:,:,:), fkn_efield(:,:,:,:), fkn_serta(:,:,:,:), taukn_serta(:,:,:,:)
    1789              :  real(dp) :: fact_sbk
    1790              :  character(len=2) :: components(3)
    1791            1 :  real(dp), allocatable :: sig_gen(:,:,:,:), mob_gen(:,:,:,:), sig_l21(:,:,:,:), sig_l22(:,:,:,:), mob_21(:,:,:,:), mob_22(:,:,:,:)
    1792              :  type :: scatk_t
    1793              : 
    1794              :    integer :: rank = xmpi_undefined_rank
    1795              : 
    1796              :    integer :: nq_ibzk_eff
    1797              :    ! Number of effective q-points in the IBZ(k)
    1798              : 
    1799              :    integer :: lgk_nsym
    1800              :    ! Number of symmetry operations in the little group of k.
    1801              : 
    1802              :    integer,allocatable :: lgk_sym2glob(:,:)
    1803              :    ! lgk_sym2glob(2, lgk_nsym)
    1804              :    ! Mapping isym_lg --> [isym, itime]
    1805              :    ! where isym is the index of the operation in the global array **crystal%symrec**
    1806              :    ! and itim is 2 if time-reversal T must be included else 1. Depends on ikcalc
    1807              : 
    1808              :    integer,allocatable :: kq_symtab(:,:)
    1809              :    ! kq_symtab(6, nq_ibzk_eff)
    1810              : 
    1811              :    real(dp),allocatable :: vals(:,:,:,:)
    1812              :    ! (nq_ibzk_eff, nbsum, nbcalc, ntemp)
    1813              :  end type scatk_t
    1814              : 
    1815            1 :  type(scatk_t),target,allocatable :: sr(:,:)
    1816              :  type(scatk_t),pointer :: sr_p
    1817              : 
    1818              : ! *************************************************************************
    1819              : 
    1820            1 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
    1821            3 :  units = [std_out, ab_out]
    1822              : 
    1823            1 :  call wrtout(units, ch10//' Entering IBTE driver.')
    1824              :  call wrtout(units, sjoin("- Reading SERTA lifetimes and e-ph scattering operator from:", &
    1825            1 :              dtfil%filsigephin), newlines=1, do_flush=.True.)
    1826              : 
    1827              :  ! Initialize IBTE object
    1828            1 :  ibte = rta_new(dtset, dtfil, ngfftc, cryst, ebands, pawtab, psps, comm)
    1829              : 
    1830              :  ! Compute RTA transport quantities
    1831            1 :  call ibte%compute_rta(cryst, dtset, dtfil, comm)
    1832              : 
    1833            1 :  nkcalc = ibte%nkcalc
    1834            1 :  nkibz = ibte%ebands%nkpt; nsppol = ibte%nsppol; ntemp = ibte%ntemp
    1835            1 :  bmin = ibte%bmin; bmax = ibte%bmax
    1836              :  !call wrtout(std_out, sjoin(" nkcalc", itoa(nkcalc), "bmin:", itoa(bmin), "bmax:", itoa(bmax)))
    1837              : 
    1838              :  ! Get units conversion factor including spin degeneracy.
    1839              : !max_occ = two / (self%nspinor * self%nsppol)
    1840              : !fact_sigma = max_occ * (siemens_SI / Bohr_meter) / 100.  ! Siemens / cm
    1841              : ! fact_mob   = fact_sigma * 100.**3 / e_Cb * Bohr_meter**3 ! cm^2 / V / s
    1842            1 :  fact_sbk   = -volt_SI * kb_HaK                           ! Volt / Kelvin
    1843              : !call wrtout(std_out,"factors: ")
    1844              : ! write (std_out,*) fact_sigma,  fact_sbk
    1845              : 
    1846              :  !call ibte%read_scattering()
    1847              :  ! Loops and memory are distributed over k-points and collinear spins
    1848           11 :  ABI_MALLOC(sr, (nkcalc, nsppol))
    1849            1 :  cnt = 0
    1850            2 :  do spin=1,nsppol
    1851            8 :    do ikcalc=1,nkcalc
    1852            6 :      cnt = cnt + 1
    1853            7 :      sr(ikcalc, spin)%rank = mod(cnt, nprocs)
    1854              :    end do
    1855              :  end do
    1856              : 
    1857            1 :  call cwtime(cpu, wall, gflops, "start")
    1858              :  ! Master reads and sends data to the rank treating (ikcalc, spin).
    1859            1 :  if (my_rank == master) then
    1860            1 :    NCF_CHECK(nctk_open_read(ncid, dtfil%filsigephin, xmpi_comm_self))
    1861              :  end if
    1862              : 
    1863            2 :  do spin=1,nsppol
    1864            8 :    do ikcalc=1,nkcalc
    1865            6 :      sr_p => sr(ikcalc, spin)
    1866            6 :      receiver = sr_p%rank
    1867            6 :      send_data = master /= receiver
    1868            6 :      if (.not. any(my_rank == [master, receiver])) cycle
    1869              :      !call wrtout(std_out, sjoin(" Sending data from my_rank:", itoa(my_rank), " to:", itoa(receiver)))
    1870              : 
    1871            6 :      if (my_rank == master) then
    1872              :        ! Get ncid of group used to store scattering rate for this k-point.
    1873            6 :        ncerr = nf90_inq_ncid(ncid, strcat("srate_k", itoa(ikcalc), "_s", itoa(spin)), grp_ncid)
    1874            6 :        if (ncerr /= NF90_NOERR) then
    1875            0 :          ABI_ERROR("Cannot find collision terms in SIGEPH file. Rerun eph_task -4 step with ibte_prep 1.")
    1876              :        end if
    1877            6 :        NCF_CHECK(nctk_get_dim(grp_ncid, "nq_ibzk_eff", sr_p%nq_ibzk_eff))
    1878            6 :        NCF_CHECK(nctk_get_dim(grp_ncid, "nbsum", nbsum))
    1879            6 :        NCF_CHECK(nctk_get_dim(grp_ncid, "nbcalc", nbcalc))
    1880            6 :        NCF_CHECK(nctk_get_dim(grp_ncid, "lgk_nsym", sr_p%lgk_nsym))
    1881           30 :        dims = [sr_p%nq_ibzk_eff, nbsum, nbcalc, sr_p%lgk_nsym]
    1882              :      end if
    1883              : 
    1884            6 :      if (send_data) then
    1885            0 :        tag = size(dims)
    1886            0 :        if (my_rank == master) call xmpi_send(dims, receiver, tag, comm, ierr)
    1887            0 :        if (my_rank == receiver) then
    1888            0 :          call xmpi_recv(dims, master, tag, comm, ierr)
    1889            0 :          sr_p%nq_ibzk_eff = dims(1); nbsum = dims(2); nbcalc = dims(3); sr_p%lgk_nsym = dims(4)
    1890              :        end if
    1891              :      end if
    1892              : 
    1893              :      ! Note that the size along the (n, m) axis does not depend on the kcalc index.
    1894        18434 :      ABI_CALLOC(sr_p%vals, (sr_p%nq_ibzk_eff, bmin:bmax, bmin:bmax, ntemp))
    1895           18 :      ABI_MALLOC(sr_p%kq_symtab, (6, sr_p%nq_ibzk_eff))
    1896           18 :      ABI_MALLOC(sr_p%lgk_sym2glob, (2, sr_p%lgk_nsym))
    1897              : 
    1898            6 :      if (my_rank == master) then
    1899            6 :        NCF_CHECK(nf90_get_var(grp_ncid, nctk_idname(grp_ncid, "kq_symtab"), sr_p%kq_symtab))
    1900            6 :        NCF_CHECK(nf90_get_var(grp_ncid, nctk_idname(grp_ncid, "lgk_sym2glob"), sr_p%lgk_sym2glob))
    1901              : 
    1902              :        ! Note that on file, we have:
    1903              :        !
    1904              :        !      nctkarr_t("srate", "dp", "nq_ibzk_eff, nbsum, nbcalc, ntemp")
    1905              :        !
    1906              :        ! but in terms of n, m indices we have that the:
    1907              :        !
    1908              :        !   n index: bstart_ks bstop_ks
    1909              :        !   m index: bsum_start up to bsum_stop to account for phonon emission/absorption.
    1910              :        !
    1911              :        ! so we have to insert the values in bmin:bmax slice.
    1912              :        ! TODO: Recheck this part.
    1913           36 :        ABI_MALLOC(grp_srate, (sr_p%nq_ibzk_eff, nbsum, nbcalc, ntemp))
    1914            6 :        NCF_CHECK(nf90_get_var(grp_ncid, nctk_idname(grp_ncid, "srate"), grp_srate))
    1915            6 :        ii = ibte%bstart_ks(ikcalc, spin)
    1916            6 :        jj = ibte%bstop_ks(ikcalc, spin)
    1917        18404 :        sr_p%vals(:, bmin:bmax, ii:jj, :) = grp_srate(:, 1:bmax-bmin+1, 1:nbcalc, :)
    1918            6 :        ABI_SFREE(grp_srate)
    1919              :      end if
    1920              : 
    1921            6 :      if (send_data) then
    1922            0 :        tag = size(sr_p%vals)
    1923            0 :        if (my_rank == master) then
    1924            0 :          tag = tag + 1; call xmpi_send(sr_p%vals, receiver, tag, comm, ierr)
    1925            0 :          tag = tag + 1; call xmpi_send(sr_p%kq_symtab, receiver, tag, comm, ierr)
    1926            0 :          tag = tag + 1; call xmpi_send(sr_p%lgk_sym2glob, receiver, tag, comm, ierr)
    1927              :        end if
    1928            0 :        if (my_rank == receiver) then
    1929            0 :          tag = tag + 1; call xmpi_recv(sr_p%vals, master, tag, comm, ierr)
    1930            0 :          tag = tag + 1; call xmpi_recv(sr_p%kq_symtab, master, tag, comm, ierr)
    1931            0 :          tag = tag + 1; call xmpi_recv(sr_p%lgk_sym2glob, master, tag, comm, ierr)
    1932              :        end if
    1933              :      end if
    1934              : 
    1935            1 :      if (send_data .and. my_rank /= receiver) call free_sr_ks(ikcalc, spin)
    1936              : 
    1937              :    end do ! spin
    1938              :  end do ! ikcalc
    1939              : 
    1940            1 :  if (my_rank == master) then
    1941            1 :    NCF_CHECK(nf90_close(ncid))
    1942              :  end if
    1943              : 
    1944            1 :  call cwtime_report(" sigeph IO", cpu, wall, gflops)
    1945              : 
    1946              :  ! Solve the linearized BTE with B = 0.
    1947              :  !
    1948              :  !   F_\nk = e df/de_\nk v_\nk \tau^0 + \tau^0 \sum_{mq} Srate_{nk,mq} F_{m,k+q}
    1949              :  !
    1950              :  ! where F is a vector in Cartesian coordinates and tau^0 is the SERTA relaxation time.
    1951              :  !
    1952              :  ! Take advantage of the following symmetry properties:
    1953              :  !
    1954              :  ! 1. F_k = F_Sk.
    1955              :  ! 2. F_{-k} = -F_k if TR symmetry.
    1956              :  ! 3. The q-space integration is reduced to the IBZ(k) using the symmetries of the little group of k.
    1957              : 
    1958              :  !call ibte%solve_ibte(solver_type=1)
    1959              : 
    1960            1 :  bsize = bmax - bmin + 1
    1961          587 :  ABI_CALLOC(fkn_in, (3, nkibz, bmin:bmax, nsppol))
    1962          586 :  ABI_CALLOC(fkn_out, (3, nkibz, bmin:bmax, nsppol))
    1963          586 :  ABI_CALLOC(fkn_serta, (3, nkibz, bmin:bmax, nsppol))
    1964          586 :  ABI_CALLOC(taukn_serta, (3, nkibz, bmin:bmax, nsppol))
    1965            4 :  ABI_MALLOC(ibte_sigma, (3, 3, 2, nsppol, ntemp))
    1966            4 :  ABI_MALLOC(ibte_seebeck, (3, 3, nsppol, ntemp))
    1967            3 :  ABI_MALLOC(ibte_pi, (3, 3, nsppol, ntemp))
    1968            3 :  ABI_MALLOC(ibte_mob, (3, 3, 2, nsppol, ntemp))
    1969            3 :  ABI_MALLOC(converged, (ntemp))
    1970            3 :  ABI_MALLOC(sig_gen, (3, 3, 2, nsppol))
    1971            2 :  ABI_MALLOC(sig_l21, (3, 3, 2, nsppol))
    1972            2 :  ABI_MALLOC(sig_l22, (3, 3, 2, nsppol))
    1973            2 :  ABI_MALLOC(mob_gen, (3, 3, 2, nsppol))
    1974            2 :  ABI_MALLOC(mob_21, (3, 3, 2, nsppol))
    1975            2 :  ABI_MALLOC(mob_22, (3, 3, 2, nsppol))
    1976            3 :  ABI_MALLOC(ibte_kappa, (3, 3, nsppol, ntemp))
    1977            1 :  abs_tol = dtset%ibte_abs_tol
    1978              : 
    1979              :  ! If the fermi level is inside the gap, F_k is gonna be very small
    1980              :  ! hence once should use a much smaller tolerance to converge.
    1981              :  ! According to numerical tests, a reasonable value of abs_tol can be estimated from the free carrier density using:
    1982              :  !
    1983              :  !  1e-20 * e_density (in cm**-3)
    1984              :  !
    1985              :  ! These are the numerical values used to derive the fit:
    1986              : 
    1987              :  !  max_adiff = np.array([9e-12, 5.6e-6, 2.7e-6, 8.2e-60, 2.9e-46, 6.9e-6, 2.9e-8, 9.5E+00, 7.3E-04, 9.2E-04, 8.4E-04])
    1988              :  !  e_density = np.array([0.97e8, 0.86e13, 0.26e14, 0.1e-40, 0.89e-26, 0.45e14, 0.28e12, 0.10E+19, 0.12E+16, 0.10E+15, 0.90E+14])
    1989              : 
    1990            1 :  if (abs_tol <= zero) then
    1991            0 :    rtmp = minval(ibte%n_ehst, mask=ibte%n_ehst > zero) * ibte%nsppol
    1992            0 :    abs_tol = 1e-20 * rtmp / cryst%ucvol / Bohr_cm**3
    1993            0 :    call wrtout(std_out, " Input ibte_abs_tol <= zero ==> computing abs tolerance from minimal carrier density over all T")
    1994            0 :    call wrtout(std_out, " using: abs_tol = 1e-20 * e_density (in cm**-3)")
    1995            0 :    call wrtout(std_out, sjoin(" abs_tol:", ftoa(abs_tol), " from carrier_density:", ftoa(rtmp / cryst%ucvol / Bohr_cm**3)))
    1996              :  end if
    1997              : 
    1998            1 :  if (my_rank == master) then
    1999            1 :    path = strcat(dtfil%filnam_ds(4), "_RTA.nc")
    2000            1 :    call wrtout(units, ch10//sjoin("- Writing IBTE transport results to:", path))
    2001            1 :    NCF_CHECK(nctk_open_modify(ncid, path , xmpi_comm_self))
    2002              : 
    2003              :    ncerr = nctk_def_dims(ncid, [ &
    2004              :       nctkdim_t("nkibz", nkibz), nctkdim_t("bsize", bsize), nctkdim_t("nkcalc", ibte%nkcalc) &
    2005            4 :    ], defmode=.True.)
    2006            1 :    NCF_CHECK(ncerr)
    2007              : 
    2008              :    ncerr = nctk_def_arrays(ncid, [ &
    2009              :      nctkarr_t('fkn_out_sigma', "dp", "three, nkibz, bsize, nsppol, ntemp"), &
    2010              :      nctkarr_t('ibte_sigma', "dp", "three, three, two, nsppol, ntemp"), &
    2011              :      nctkarr_t('ibte_mob', "dp", "three, three, two, nsppol, ntemp"), &
    2012              :      nctkarr_t("kcalc2ibz", "int", "nkcalc, six"), &
    2013              :      nctkarr_t("kcalc2ebands", "int", "six, nkcalc"), &
    2014              :      nctkarr_t("kibz", "dp", "three, nkibz"), &
    2015              :      nctkarr_t('ibte_rho', "dp", "three, three, ntemp") &
    2016            8 :    ], defmode=.True.)
    2017            1 :    NCF_CHECK(ncerr)
    2018              : 
    2019            1 :    NCF_CHECK(nctk_set_datamode(ncid))
    2020              :  end if
    2021              : 
    2022            1 :  cnt = 0
    2023            3 :  do itemp=1,ntemp
    2024              :  !do itemp=ntemp, 1, -1
    2025            2 :    cnt = cnt + 1
    2026            2 :    kT = max(ibte%kTmesh(itemp), one * kb_HaK)
    2027            2 :    mu_e = ibte%eph_mu_e(itemp)
    2028            2 :    sig_p => ibte_sigma(:,:,:,:,itemp)
    2029            2 :    mob_p => ibte_mob(:,:,:,:,itemp)
    2030            2 :    sbk_p => ibte_seebeck(:,:,:,itemp)
    2031            2 :    kappa_p => ibte_kappa(:,:,:,itemp)
    2032            2 :    pi_p => ibte_pi(:,:,:,itemp)
    2033              : 
    2034            2 :    call wrtout(std_out," Value of kT: ", pre_newlines=1, newlines=1)
    2035            2 :         write (std_out,*) kT
    2036              : 
    2037              : 
    2038              :    ! Precompute tau_serta and fkn_serta for this T: f^'_nk v_\nk * \tau^0
    2039            4 :    do spin=1,nsppol
    2040           16 :      do ikcalc=1,nkcalc
    2041              :        !ik_ibz = ibte%kcalc2ibz(ikcalc, 1)
    2042           12 :        ik_ibz = ibte%kcalc2ebands(1, ikcalc)
    2043           26 :        do band_k=ibte%bstart_ks(ikcalc, spin), ibte%bstop_ks(ikcalc, spin)
    2044           12 :          lw_nk = ibte%linewidths(itemp, band_k, ik_ibz, spin, 1)  ! 1 --> SERTA linewidths.
    2045           12 :          call safe_div(one, two * lw_nk, zero, tau_nk)
    2046           48 :          taukn_serta(:, ik_ibz, band_k, spin) = tau_nk
    2047           12 :          e_nk = ebands%eig(band_k, ik_ibz, spin)
    2048           12 :          dfde_nk = occ_dfde(e_nk, kT, mu_e)
    2049           60 :          fkn_serta(:, ik_ibz, band_k, spin) = tau_nk * dfde_nk * ibte%vbks(:, band_k, ik_ibz, spin)
    2050              :        end do
    2051              :      end do
    2052              :    end do
    2053              : 
    2054              :    call wrtout(std_out, sjoin(" Begin IBTE loop for itemp:", itoa(itemp), ", KT:", ftoa(kT / kb_HaK), "[K]"), &
    2055            2 :                pre_newlines=1, newlines=1)
    2056              : 
    2057              :    ! iter = 0 --> Compute SERTA transport tensors just for initial reference.
    2058            2 :    call ibte_calc_tensors(ibte, cryst, itemp, kT, mu_e, fkn_serta, onsager, sig_p, mob_p, fsum_eh, comm, iet)
    2059              : 
    2060              :    !TODO fix dtset here ans use maxocc, CAREFUL, it has to be included in all L coeff. I think
    2061              : !max_occ = two / (self%nspinor * self%nsppol)
    2062              : ! fact_sigma = max_occ * (siemens_SI / Bohr_meter) / 100.  ! Siemens / cm
    2063              : ! fact_mob   = fact_sigma * 100.**3 / e_Cb * Bohr_meter**3 ! cm^2 / V / s
    2064              :  !fact_sbk   = volt_SI * kb_HaK                           ! Volt / Kelvin
    2065              :   ! sig_p = fact_sigma * sig_p  ! siemens cm^-1
    2066              :  !  mob_p = fact_mob   * mob_p  !
    2067              : 
    2068              :    ! Print mobility for semiconductors, conductivity for metals.
    2069            2 :    if (ibte%assume_gap) then
    2070            0 :      do spin=1,nsppol
    2071            0 :        mat33 = sum(mob_p(:,:,:,spin), dim=3)
    2072              :        write(msg, "(i5,1x,es9.1, *(1x, f16.2))") &
    2073            0 :          0, zero, mat33(1,1), mat33(2,2), mat33(3,3), sum(fsum_eh(:,:,spin))
    2074              :      end do
    2075              :    else
    2076            4 :      do spin=1,nsppol
    2077           62 :        mat33 = sum(sig_p(:,:,:,spin), dim=3)
    2078              :        write(msg, "(i5,1x,es9.1, *(1x, es16.6))") &
    2079           20 :          0, zero, mat33(1,1), mat33(2,2), mat33(3,3), sum(fsum_eh(:,:,spin))
    2080              :      end do
    2081              :    end if
    2082            2 :    call wrtout(std_out, msg)
    2083              : 
    2084         1168 :    fkn_in = fkn_serta
    2085              :    ! TODO: B-field
    2086              :    ! Initialize fkn_in either from SERTA or from previous T.
    2087              :    !if (cnt == 1) fkn_in = fkn_serta
    2088              :    !if (cnt > 1 ) fkn_in = fkn_out
    2089         1166 :    fkn_out = zero
    2090              : 
    2091            2 :    max_et=2 !max_et =1 pour F^E et max_et=2 pour F^E et F^T, iet = 3 pour calculer kappa
    2092              : 
    2093              : ! start here with loop over E and T perturbations: once F^Eps is done, init F^T and converge it as well
    2094            6 :    electherm_loop: do iet = 1, max_et
    2095              : 
    2096            4 :      if (iet == 2) then
    2097              :      ! initialize F^T from F^E
    2098            4 :        do spin=1,nsppol
    2099           16 :           do ikcalc=1,nkcalc
    2100           12 :             ik_ibz = ibte%kcalc2ebands(1, ikcalc)
    2101           26 :             do band_k=ibte%bstart_ks(ikcalc, spin), ibte%bstop_ks(ikcalc, spin)
    2102           12 :                e_nk = ebands%eig(band_k, ik_ibz, spin)
    2103              :               !Which one of the following is correct ?
    2104              :               ! fkn_in(:, ik_ibz, band_k, spin)  = fkn_serta(:, ik_ibz, band_k, spin) * (e_nk-mu_e)/kT
    2105              :                !fkn_in(:, ik_ibz, band_k, spin)  = fkn_efield(:, ik_ibz, band_k, spin) * (e_nk-mu_e)/kT
    2106           48 :                fkn_in(:, ik_ibz, band_k, spin)  = fkn_efield(:, ik_ibz, band_k, spin) * (e_nk-mu_e)
    2107           60 :                fkn_serta(:, ik_ibz, band_k, spin)  = fkn_serta(:, ik_ibz, band_k, spin) * (e_nk-mu_e)
    2108              :             end do !band_k
    2109              :           end do !ikcalc
    2110              :         end do !spin
    2111            2 :        ABI_CHECK(converged(itemp), "Warning: E field BTE not converged, I will not try to converge the T gradient")
    2112            2 :        if (.not. converged(itemp)) exit electherm_loop
    2113              :      end if ! iet == 2  ?????
    2114              : 
    2115              : 
    2116              :      ! Begin iterative solver.
    2117           25 :      iter_loop: do iter=1,dtset%ibte_niter
    2118              : 
    2119              :        ! call wrtout(std_out," check beginning loop, iter, iet:", pre_newlines=1, newlines=1)
    2120              :        ! write (std_out,*) iter, iet
    2121              : 
    2122              :         ! Loop over the nk index in F_nk.
    2123           50 :        do spin=1,nsppol
    2124          200 :           do ikcalc=1,nkcalc
    2125          150 :             sr_p => sr(ikcalc, spin)
    2126          150 :             if (sr_p%rank /= my_rank) cycle ! MPI parallelism
    2127          150 :             ik_ibz = ibte%kcalc2ebands(1, ikcalc)
    2128          325 :             do band_k=ibte%bstart_ks(ikcalc, spin), ibte%bstop_ks(ikcalc, spin)
    2129              : 
    2130              :               ! Summing over the q-points in the effective IBZ(k) and the m band index.
    2131              :               ! Results stored in vec3. Integration weights are already included.
    2132          150 :               vec3 = zero
    2133          300 :               do band_sum=ibte%bmin, ibte%bmax
    2134       229825 :                 do iq_sum=1, sr_p%nq_ibzk_eff
    2135       229525 :                   ikq_ibz = sr_p%kq_symtab(1, iq_sum); isym_kq = sr_p%kq_symtab(2, iq_sum)
    2136       229525 :                   trev_kq = sr_p%kq_symtab(6, iq_sum) !; g0_kq = sr_p%kq_symtab(3:5, iq_sum)
    2137              :                   ! Build F_{m,k+q} in the effective IBZ(k) from fkn_in using symmetries (need k+q --> IBZ map)
    2138              :                   ! Use transpose(R) because we are using the tables for the wavefunctions
    2139              :                   ! In this case listkk has been called with symrec and use_symrec=False
    2140              :                   ! so q_bz = S^T q_ibz where S is the isym_kq symmetry
    2141              :                   ! vkq = matmul(transpose(cryst%symrel_cart(:,:,isym_kq)), vkq)
    2142      2983825 :                   mat33 = transpose(cryst%symrel_cart(:,:,isym_kq))
    2143      2983825 :                   f_kq = matmul(mat33, fkn_in(:, ikq_ibz, band_sum, spin))
    2144       229525 :                   if (trev_kq == 1) f_kq = -f_kq
    2145       918250 :                   vec3 = vec3 + sr_p%vals(iq_sum, band_sum, band_k, itemp) * f_kq(:)
    2146              :                 end do ! iq_sum
    2147              :               end do ! band_k
    2148              : 
    2149              :               ! Symmetrize intermediate results using the operations of the little group of k.
    2150          150 :               sym_vec = zero
    2151          800 :               do isym_lgk=1,sr_p%lgk_nsym
    2152          650 :                 isym = sr_p%lgk_sym2glob(1, isym_lgk)
    2153          650 :                 itime = sr_p%lgk_sym2glob(2, isym_lgk)
    2154         8450 :                 mat33 = transpose(cryst%symrel_cart(:,:,isym))
    2155              :                 !if(itime == 1) mat33 = -mat33 ! FIXME: here there's a different convention for TR used in m_lgroup
    2156         4550 :                 if (itime == 2) mat33 = -mat33
    2157        10550 :                 sym_vec = sym_vec + matmul(mat33, vec3)
    2158              :               end do
    2159          600 :               sym_vec = taukn_serta(:, ik_ibz, band_k, spin) * sym_vec / sr_p%lgk_nsym
    2160              :               ! if iet 2 serta and fkn_in have been multiplied by e-mu / T
    2161          750 :               fkn_out(:, ik_ibz, band_k, spin) = fkn_serta(:, ik_ibz, band_k, spin) + sym_vec
    2162              :             end do ! band_k
    2163              :           end do ! ikcalc
    2164              :        end do ! spin
    2165              : 
    2166              : 
    2167           25 :        call xmpi_sum(fkn_out, comm, ierr)
    2168              : 
    2169              :        ! Write fkn_out_sigma to disk.
    2170           25 :        if (my_rank == master) then
    2171          150 :            NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "fkn_out_sigma"), fkn_out, start=[1,1,1,1,itemp]))
    2172              :        end if
    2173              : 
    2174           50 :        do spin=1,nsppol
    2175        14575 :          max_adiff_spin(spin) = maxval(abs(fkn_out(:,:,:,spin) - fkn_in(:,:,:,spin)))
    2176              :        end do
    2177           75 :        max_adiff = maxval(max_adiff_spin)
    2178              : 
    2179              : 
    2180          725 :        mob_gen=sig_gen
    2181          725 :        mob_21=sig_gen
    2182          725 :        mob_22=sig_gen
    2183              : 
    2184              : !Here I test if F^T=(eps-mu)F^E
    2185              : !        if (iet==2) then
    2186              : !         do spin=1,nsppol
    2187              : !          do ikcalc=1,nkcalc
    2188              : !            ik_ibz = ibte%kcalc2ebands(1, ikcalc)
    2189              : !            do band_k=ibte%bstart_ks(ikcalc, spin), ibte%bstop_ks(ikcalc, spin)
    2190              : !               e_nk = ebands%eig(band_k, ik_ibz, spin)
    2191              :               !Which one of the following is correct ?
    2192              :               ! fkn_in(:, ik_ibz, band_k, spin)  = fkn_serta(:, ik_ibz, band_k, spin) * (e_nk-mu_e)/kT
    2193              :                !fkn_in(:, ik_ibz, band_k, spin)  = fkn_efield(:, ik_ibz, band_k, spin) * (e_nk-mu_e)/kT
    2194              : !               fkn_out(:, ik_ibz, band_k, spin)  = fkn_efield(:, ik_ibz, band_k, spin) * (e_nk-mu_e)
    2195              :                !fkn_serta(:, ik_ibz, band_k, spin)  = fkn_serta(:, ik_ibz, band_k, spin) * (e_nk-mu_e)
    2196              : !            end do
    2197              : !          end do
    2198              : !        end do
    2199              : !       end if
    2200              : 
    2201              : 
    2202              :        ! Compute transport tensors from fkn_out (= F_eps or F_T)
    2203           25 :        if(iet==1) call ibte_calc_tensors(ibte, cryst, itemp, kT, mu_e, fkn_out, onsager, sig_p, mob_p, fsum_eh, comm, iet)
    2204              : ! call flush_unit(std_out)
    2205              : 
    2206              :       !For seebeck, use another array(sig_gen) because sig_p points towards ibte_sigma
    2207           25 :       if(iet==2) call ibte_calc_tensors(ibte, cryst, itemp, kT, mu_e, fkn_out, onsager, sig_gen, mob_gen, fsum_eh, comm, iet)
    2208              : 
    2209              :        !check to find the bug
    2210              : ! call wrtout(std_out," check 3", pre_newlines=1, newlines=1)
    2211              : ! call flush_unit(std_out)
    2212              : 
    2213              :        ! Print mobility for semiconductors or conductivity for metals.
    2214           25 :        if (iet==1) then! for F_eps and charge transport
    2215              :          !sig_p = fact_sigma * sig_gen  ! siemens cm^-1
    2216              :          !mob_p = fact_mob   * mob_gen  ! cm2/V/s
    2217              : 
    2218              : !call wrtout(std_out, "check 3bis: sig_gen, fact_sigma, sig_p")
    2219              :  !               write(std_out,*) , sig_gen, fact_sigma, sig_p
    2220              :           !check to find the bug
    2221              : ! call wrtout(std_out," check 4", pre_newlines=1, newlines=1)
    2222              : 
    2223           23 :          if (ibte%assume_gap) then
    2224            0 :            do spin=1,nsppol
    2225            0 :              mat33 = sum(mob_p(:,:,:,spin), dim=3)
    2226              :              write(msg, "(i5,1x,es9.1,*(1x, f16.2))") &
    2227            0 :                iter, max_adiff_spin(spin), mat33(1,1), mat33(2,2), mat33(3,3), sum(fsum_eh(:,:,spin))
    2228              :            end do
    2229              :          else
    2230           46 :            do spin=1,nsppol
    2231          713 :              mat33 = sum(sig_p(:,:,:,spin), dim=3)
    2232              :              write(msg, "(i5,1x,es9.1,*(1x, es16.6))") &
    2233          230 :                iter, max_adiff_spin(spin), mat33(1,1), mat33(2,2), mat33(3,3), sum(fsum_eh(:,:,spin))
    2234              :            end do
    2235              :          end if
    2236           23 :          call wrtout(std_out, msg)
    2237              : 
    2238            2 :        else if (iet == 2) then! for Seebeck, Seebeck=1/T sig_p^-1 * sig_gen
    2239              :          ! output sig_p^-1 * sig_gen
    2240              :          !pay attention when implementing if sigma=zero, bug ! impossible to get S.
    2241              :          ! use matr3inv to inverse the matrix sigma but verify also that the det is not equal to zero !
    2242              :          ! maybe type the command use "..." to be able to use the functions, check in the code
    2243              : 
    2244              :          !call wrtout(std_out, "check : sig_gen, sig_p")
    2245              :          !write(std_out,*) sig_gen, sig_p
    2246              : 
    2247              :          !TODO: implement for inv_sig_p with two spins
    2248            4 :          do spin=1,nsppol
    2249           62 :            call inv33(sum(sig_p(:,:,:,spin),dim=3), inv_sig_p)
    2250              :            !We divide by 100 because sig_p is in Siemens cm^-1 and we want to retrieve meters
    2251              :           ! work33 = matmul (inv_sig_p, sum(sig_gen(:,:,:,spin),dim=4))
    2252          164 :            mat33 = matmul (inv_sig_p, sum(sig_gen(:,:,:,spin),dim=3)) / (kT)
    2253              :           ! mat33 = (volt_SI / (ibte%kTmesh(itemp) / kb_HaK)) * matmul (inv_sig_p, sum(sig_gen(:,:,:,spin),dim=3))
    2254              :            write(msg, "(i5,1x,es9.1,*(1x, es16.6))") &
    2255           18 :                iter, max_adiff_spin(spin), mat33(1,1), mat33(2,2), mat33(3,3), sum(fsum_eh(:,:,spin))
    2256           28 :            sbk_p (:,:,spin) = mat33
    2257              :          end do
    2258            2 :          call wrtout(std_out, msg)
    2259              :        end if ! iet == 1, 2
    2260              : 
    2261           25 :        if (ibte%assume_gap) then
    2262            0 :          write(msg, "(a5,1x,a9,*(1x, a16))")" ITER", "max_adiff", "mobility_e+h", "sum_k(df_k)"
    2263              :        else
    2264           25 :          write(msg, "(a5,1x,a9,*(1x, a16))")" ITER", "max_adiff", "conductivity", "sum_k(df_k)"
    2265              :        end if
    2266           25 :        call wrtout(std_out, msg)
    2267              : 
    2268              : 
    2269              :        ! Check for convergence by testing max_k |F_k^i - F_k^{i-1}|.
    2270           25 :        call wrtout (std_out, "Print check convergence: max_adiff, abs_tol")
    2271           25 :        write(std_out,*) max_adiff, abs_tol
    2272           25 :        converged(itemp) = max_adiff < abs_tol
    2273           50 :        if (converged(itemp)) then
    2274              :          call wrtout(std_out, sjoin(" IBTE solver converged after:", itoa(iter), &
    2275            4 :                      "iterations within ibte_abs_tol:", ftoa(abs_tol)), pre_newlines=1)
    2276              : 
    2277            4 :          exit iter_loop
    2278              :        else
    2279              :          ! Linear mixing of fkn_in and fkn_out.
    2280        12264 :          fkn_in = (one - dtset%ibte_alpha_mix) * fkn_in + dtset%ibte_alpha_mix * fkn_out
    2281        12243 :          fkn_out = zero
    2282              :        end if
    2283              :         !check where is the problem with iter loop
    2284              : 
    2285              :         !call wrtout(std_out," check iet:", pre_newlines=1, newlines=1)
    2286              :         !write (std_out,*) iet
    2287              : 
    2288              :      end do iter_loop
    2289              : 
    2290            4 :      if (.not. converged(itemp)) then
    2291            0 :        msg = sjoin("Not converged after:", itoa(dtset%ibte_niter), "max iterations")
    2292            0 :        call wrtout(ab_out, msg, pre_newlines=1, newlines=1)
    2293            0 :        ABI_WARNING(msg)
    2294              :      end if
    2295              : 
    2296              :      !Change of unit here because sig_p is used in to calculate sbk in SI units
    2297         1174 :         if (iet == 1) fkn_efield = fkn_out
    2298            6 :         if (iet==2) then
    2299              :                 !iet =3
    2300            2 :                 call ibte_calc_tensors(ibte, cryst, itemp, kT, mu_e, fkn_efield, onsager, sig_l21, mob_21, fsum_eh, comm, 3)
    2301            2 :                 call ibte_calc_tensors(ibte, cryst, itemp, kT, mu_e, fkn_out, onsager, sig_l22, mob_22, fsum_eh, comm, 3)
    2302            4 :                 do spin=1, nsppol
    2303           62 :                 call inv33(sum(sig_p(:,:,:,spin),dim=3), inv_sig_p)
    2304          252 :                 kappa_p(:,:,spin)=(1/kT)*(sum(sig_l22(:,:,:,spin), dim=3)-matmul(sum(sig_l21(:,:,:,spin),dim=3),sbk_p(:,:,spin)*kT))
    2305          166 :                 pi_p(:,:,spin)= matmul (sum(sig_l21(:,:,:,spin),dim=3), inv_sig_p) ! PI=L21/L11 in IBTE
    2306              :                 end do
    2307              :         end if
    2308              :    end do electherm_loop
    2309              : ! end E/T loop
    2310              : 
    2311              : !Units conversion for sigma, at this step in order to keep atomic units for the calculation of S
    2312              : !Truncated in purpose for nspinor=2 and nsppol=1 compared to how its done in the calc_tensor routine because dont have access to self in this routine
    2313           57 : sig_p=sig_p*(siemens_SI / Bohr_meter / cryst%ucvol) / 100
    2314              : !check if sig_p and sbk_p are empty
    2315              : !call wrtout(std_out, "sig_p, sbk_p")
    2316              : !write(std_out,*)  sig_p, sbk_p
    2317              : 
    2318              :  end do ! itemp
    2319              : 
    2320              :  !TODO: do it for spins as well
    2321            3 :  ABI_MALLOC(ibte_rho, (3, 3, ntemp))
    2322            3 :  do itemp=1,ntemp
    2323           62 :    work33 = sum(ibte_sigma(:,:,:,1,itemp), dim=3)
    2324            2 :    if (ibte%nsppol == 2) work33 = work33 + sum(ibte_sigma(:,:,:,2,itemp), dim=3)
    2325            2 :    call inv33(work33, mat33)
    2326           27 :    ibte_rho(:, :, itemp) = 1e+6_dp * mat33
    2327              :  end do
    2328              : 
    2329              : !ibte_sigma rho and seebeck seem empty, let's check
    2330              : 
    2331              : 
    2332              : !write(*,*) "sigma: ", ibte_sigma
    2333              : !write(*,*) "rho: ", ibte_rho
    2334              : !write(*,*) "seebeck: ", ibte_seebeck
    2335              : 
    2336              : 
    2337            1 :  if (my_rank == master) then
    2338              :    ! Write final results to main output.
    2339            4 :    components = ["xx", "yy", "zz"]
    2340            1 :    if (ibte%assume_gap) then
    2341              :      ! SemiConductor
    2342            0 :      do ii=1,3
    2343            0 :        call wrtout(units, sjoin(" Cartesian component of IBTE mobility tensor:", components(ii)))
    2344            0 :        write(msg, "(a16,2(a32),a16)") 'Temperature [K]', 'e/h density [cm^-3]', 'e/h mobility [cm^2/Vs]', "Converged"
    2345            0 :        call wrtout(units, msg)
    2346              : 
    2347            0 :        do spin=1,ibte%nsppol
    2348            0 :          if (ibte%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    2349              : 
    2350            0 :          do itemp=1,ibte%ntemp
    2351              :            write(msg,"(f16.2,2e16.2,2f16.2,a16)") &
    2352            0 :              ibte%kTmesh(itemp) / kb_HaK, &
    2353            0 :              ibte%n_ehst(1, spin, itemp) / cryst%ucvol / Bohr_cm **3, &
    2354            0 :              ibte%n_ehst(2, spin, itemp) / cryst%ucvol / Bohr_cm **3, &
    2355            0 :              ibte_mob(ii, ii, 1, spin, itemp), ibte_mob(ii, ii, 2, spin, itemp), &
    2356            0 :              yesno(converged(itemp))
    2357            0 :            call wrtout(units, msg)
    2358              :          end do ! itemp
    2359              :        end do ! spin
    2360              :        ! TODO:HERE look into adding seebeck output for semiconductors as well, check what happens with e and h components in tensors
    2361              :        ! routine
    2362            0 :        call wrtout(units, ch10)
    2363              :      end do ! ii
    2364              : 
    2365              :    else
    2366              :      ! Metals. Print conductivity (spin resolved) and resistivity (no spin resolved)
    2367            3 :      do ii=1,2
    2368            2 :        if (ii == 1) msg = " Conductivity [Siemens cm^-1] using IBTE"
    2369            2 :        if (ii == 2) msg = " Resistivity [micro-Ohm cm] using IBTE"
    2370            2 :        call wrtout(units, msg)
    2371              : 
    2372            2 :        nsp = ibte%nsppol; if (ii == 2) nsp = 1
    2373            4 :        do spin=1,nsp
    2374            2 :          if (ibte%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    2375            2 :          write(msg, "(5a16)") 'Temperature (K)', 'xx', 'yy', 'zz', "Converged"
    2376            2 :          call wrtout(units, msg)
    2377            8 :          do itemp=1,ibte%ntemp
    2378            4 :            if (ii == 1) then
    2379           62 :              mat33 = sum(ibte_sigma(:,:,:,spin,itemp), dim=3)
    2380              :            else
    2381           26 :              mat33 = ibte_rho(:,:,itemp)
    2382              :            end if
    2383              :            write(msg,"(f16.2,3e16.6,a16)") &
    2384            4 :              ibte%kTmesh(itemp) / kb_HaK, mat33(1,1), mat33(2,2), mat33(3,3), yesno(converged(itemp))
    2385            6 :            call wrtout(units, msg)
    2386              :          end do ! itemp
    2387              :        end do ! spin
    2388            3 :        call wrtout(units, ch10)
    2389              :      end do ! ii
    2390              : 
    2391              :      ! HERE add output of Seebeck and kappa_el coefficients
    2392              :      ! TODO: add off diagonal Seebeck and sigma coefficients
    2393            1 :      msg = " Seebeck [Volts / Kelvin] using IBTE"
    2394            1 :      call wrtout(units, msg)
    2395            2 :      do spin=1,ibte%nsppol
    2396            1 :        if (ibte%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    2397            1 :        write(msg, "(5a16)") 'Temperature (K)', 'xx', 'yy', 'zz', "Converged"
    2398            1 :        call wrtout(units, msg)
    2399            4 :        do itemp=1,ibte%ntemp
    2400           26 :          mat33 = fact_sbk * ibte_seebeck(:,:,spin,itemp)
    2401              :          write(msg,"(f16.2,3e16.6,a16)") &
    2402            2 :            ibte%kTmesh(itemp) / kb_HaK, mat33(1,1), mat33(2,2), mat33(3,3), yesno(converged(itemp))
    2403            3 :          call wrtout(units, msg)
    2404              :        end do ! itemp
    2405              :      end do ! spin
    2406            1 :      call wrtout(units, ch10)
    2407              : 
    2408              : 
    2409            1 :      msg = " Kappa [W/m*K] using IBTE"
    2410            1 :      call wrtout(units, msg)
    2411            2 :      do spin=1,ibte%nsppol
    2412            1 :        if (ibte%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    2413            1 :        write(msg, "(5a16)") 'Temperature (K)', 'xx', 'yy', 'zz', "Converged"
    2414            1 :        call wrtout(units, msg)
    2415            4 :        do itemp=1,ibte%ntemp
    2416           26 :          mat33 = volt_SI**2 * kb_HaK * (siemens_SI / Bohr_meter / cryst%ucvol)* ibte_kappa(:,:,spin,itemp)
    2417              :          write(msg,"(f16.2,3e16.6,a16)") &
    2418            2 :            ibte%kTmesh(itemp) / kb_HaK, mat33(1,1), mat33(2,2), mat33(3,3), yesno(converged(itemp))
    2419            3 :          call wrtout(units, msg)
    2420              :        end do ! itemp
    2421              :      end do ! spin
    2422            1 :      call wrtout(units, ch10)
    2423              : 
    2424            1 :      msg = " Peltier [Volts] using IBTE"
    2425            1 :      call wrtout(units, msg)
    2426            2 :      do spin=1,ibte%nsppol
    2427            1 :        if (ibte%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    2428            1 :        write(msg, "(5a16)") 'Temperature (K)', 'xx', 'yy', 'zz', "Converged"
    2429            1 :        call wrtout(units, msg)
    2430            4 :        do itemp=1,ibte%ntemp
    2431           26 :          mat33 = -volt_SI * ibte_pi(:,:,spin,itemp)
    2432              :          write(msg,"(f16.2,3e16.6,a16)") &
    2433            2 :            ibte%kTmesh(itemp) / kb_HaK, mat33(1,1), mat33(2,2), mat33(3,3), yesno(converged(itemp))
    2434            3 :          call wrtout(units, msg)
    2435              :        end do ! itemp
    2436              :      end do ! spin
    2437            1 :      call wrtout(units, ch10)
    2438              : 
    2439            1 :      msg = "Carrier density: "
    2440            1 :      call wrtout(units, msg)
    2441            1 :        write(msg, "(a16,a16,a32)") 'Temperature [K]', ' chem pot [eV]  ', 'e/h density [cm^-3]'
    2442            1 :        call wrtout(units, msg)
    2443              : 
    2444            2 :        do spin=1,ibte%nsppol
    2445            1 :          if (ibte%nsppol == 2) call wrtout(units, sjoin(" For spin:", stoa(spin)), newlines=1)
    2446              : 
    2447            4 :          do itemp=1,ibte%ntemp
    2448              :            write(msg,"(f16.2,3e16.2)") &
    2449            2 :              ibte%kTmesh(itemp) / kb_HaK, &
    2450            2 :              ibte%eph_mu_e(itemp) * eV_Ha, &
    2451            2 :              ibte%n_ehst(1, spin, itemp) / cryst%ucvol / Bohr_cm **3, &
    2452            4 :              ibte%n_ehst(2, spin, itemp) / cryst%ucvol / Bohr_cm **3
    2453            3 :            call wrtout(units, msg)
    2454              :          end do ! itemp
    2455              :        end do ! spin
    2456            1 :        call wrtout(units, ch10)
    2457              : 
    2458              : 
    2459              : 
    2460              : 
    2461              :    end if
    2462              : 
    2463              :    !pre = "_IBTE"
    2464              :    !call ibte%write_tensor(dtset, irta, "sigma", ibte%sigma(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_SIGMA"))
    2465              :    !call ibte%write_tensor(dtset, irta, "seebeck", ibte%seebeck(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_SBK"))
    2466              :    !call ibte%write_tensor(dtset, irta, "kappa", ibte%kappa(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_KAPPA"))
    2467              :    !call ibte%write_tensor(dtset, irta, "zte", ibte%zte(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_ZTE"))
    2468              :    !call ibte%write_tensor(dtset, irta, "pi", ibte%pi(:,:,:,:,:,irta), strcat(dtfil%filnam_ds(4), pre, "_PI"))
    2469              : 
    2470              :    ! Print IBTE results to stdout and other external txt files (for the test suite)
    2471              :    !call ibte%print_rta_txt_files(cryst, dtset, dtfil)
    2472              :    ! Creates the netcdf file used to store the results of the calculation.
    2473            1 :    path = strcat(dtfil%filnam_ds(4), "_RTA.nc")
    2474            1 :    call wrtout(units, ch10//sjoin("- Writing IBTE transport results to:", path))
    2475              :    !NCF_CHECK(nctk_open_modify(ncid, path , xmpi_comm_self))
    2476              : 
    2477              :    ncerr = nctk_def_arrays(ncid, [ &
    2478              :      nctkarr_t('ibte_sigma', "dp", "three, three, two, nsppol, ntemp"), &
    2479              :      nctkarr_t('ibte_mob', "dp", "three, three, two, nsppol, ntemp"), &
    2480              :      nctkarr_t('ibte_rho', "dp", "three, three, ntemp"), &
    2481              :      nctkarr_t('ibte_kappa', "dp", "three, three, nsppol, ntemp"), &
    2482              :      nctkarr_t('ibte_seebeck', "dp", "three, three, nsppol, ntemp"), &
    2483              :      nctkarr_t('ibte_pi', "dp", "three, three, nsppol, ntemp") &
    2484            7 :    ], defmode=.True.)
    2485            1 :    NCF_CHECK(ncerr)
    2486              : 
    2487              :    ! Write data.
    2488            1 :    NCF_CHECK(nctk_set_datamode(ncid))
    2489            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ibte_sigma"), ibte_sigma))
    2490            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ibte_mob"), ibte_mob))
    2491            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ibte_rho"), ibte_rho))
    2492            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ibte_seebeck"), ibte_seebeck))
    2493            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ibte_pi"), ibte_pi))
    2494            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ibte_kappa"), ibte_kappa))
    2495            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kcalc2ibz"), ibte%kcalc2ibz))
    2496            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kcalc2ebands"), ibte%kcalc2ebands))
    2497            1 :    NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kibz"), ibte%ebands%kptns))
    2498            1 :    NCF_CHECK(nf90_close(ncid))
    2499              :  end if ! master
    2500              : 
    2501              :  ! Free memory
    2502            1 :  ABI_FREE(fkn_serta)
    2503            1 :  ABI_FREE(taukn_serta)
    2504            1 :  ABI_FREE(fkn_in)
    2505            1 :  ABI_FREE(fkn_out)
    2506            1 :  ABI_FREE(ibte_sigma)
    2507            1 :  ABI_FREE(ibte_seebeck)
    2508            1 :  ABI_FREE(ibte_pi)
    2509            1 :  ABI_FREE(ibte_mob)
    2510            1 :  ABI_FREE(ibte_rho)
    2511            1 :  ABI_FREE(ibte_kappa)
    2512            1 :  ABI_FREE(converged)
    2513            1 :  ABI_FREE(sig_gen)
    2514            1 :  ABI_FREE(sig_l21)
    2515            1 :  ABI_FREE(sig_l22)
    2516            1 :  ABI_FREE(mob_gen)
    2517            1 :  ABI_FREE(mob_21)
    2518            1 :  ABI_FREE(mob_22)
    2519              : 
    2520            2 :  do spin=1,nsppol
    2521            8 :    do ikcalc=1,nkcalc
    2522            7 :      call free_sr_ks(ikcalc, spin)
    2523              :    end do
    2524              :  end do
    2525            7 :  ABI_FREE(sr)
    2526              : 
    2527            4 :  call ibte%free()
    2528              : 
    2529              : contains
    2530              : 
    2531            6 : subroutine free_sr_ks(ikc, isp)
    2532              :   integer,intent(in) :: ikc, isp
    2533            6 :   ABI_SFREE(sr(ikc, isp)%vals)
    2534            6 :   ABI_SFREE(sr(ikc, isp)%lgk_sym2glob)
    2535            6 :   ABI_SFREE(sr(ikc, isp)%kq_symtab)
    2536            6 : end subroutine free_sr_ks
    2537              : 
    2538              : end subroutine ibte_driver
    2539              : !!***
    2540              : 
    2541              : !----------------------------------------------------------------------
    2542              : 
    2543              : !!****f* m_rta/ibte_calc_tensors
    2544              : !! NAME
    2545              : !! ibte_calc_tensors
    2546              : !!
    2547              : !! FUNCTION
    2548              : !!   calculate transport tensors within iBTE method, from v x F expressions for current and sigma etc
    2549              : !!   this routine now stays in atomic units to accommodate calculation of sigma and seebeck
    2550              : !!
    2551              : !! INPUTS
    2552              : !! cryst<crystal_t>=Crystalline structure
    2553              : !! comm=MPI communicator.
    2554              : !!
    2555              : !! SOURCE
    2556              : 
    2557           31 : subroutine ibte_calc_tensors(self, cryst, itemp, kT, mu_e, fk, onsager, sigma_eh, mob_eh, fsum_eh, comm, iet)
    2558              : 
    2559              : !Arguments ------------------------------------
    2560              :  class(rta_t),intent(inout) :: self
    2561              :  type(crystal_t),intent(in) :: cryst
    2562              :  integer,intent(in) :: itemp
    2563              :  real(dp),intent(in) :: kT, mu_e
    2564              :  real(dp),intent(in) :: fk(3, self%ebands%nkpt, self%bmin:self%bmax, self%nsppol)
    2565              :  real(dp),intent(out) :: sigma_eh(3,3,2,self%nsppol), mob_eh(3,3,2,self%nsppol)
    2566              :  real(dp),intent(out) :: fsum_eh(3,2,self%nsppol), onsager(3,3,3,self%nsppol)
    2567              :  integer,intent(in) :: comm, iet !iet to know which tensor we calculate, 1 for L11, 2 for L12 and 3 for L21 and L22
    2568              : 
    2569              : !Local variables ------------------------------
    2570              : !scalars
    2571              :  integer :: nsppol, nkibz, ib, ik_ibz, spin, ii, jj, ieh, cnt, nprocs, ia, time_opt
    2572              :  real(dp) :: eig_nk, max_occ, wtk, emu_alpha, fact, fact0
    2573              :  !real(dp) :: fact_sigma, fact_mob
    2574              :  !arrays
    2575              :  real(dp) :: vr(3), vv_tens(3,3)
    2576              : !************************************************************************
    2577              : 
    2578              :  ABI_UNUSED(kt)
    2579              : 
    2580           31 :  nprocs = xmpi_comm_size(comm)
    2581              : 
    2582              :  ! Copy important dimensions
    2583           31 :  nkibz = self%ebands%nkpt; nsppol = self%ebands%nsppol
    2584           31 :  time_opt = 0 ! This to preserve the previous behaviour in which TR was not used.
    2585              : 
    2586              :  ! sigma_IBTE = (-S e^ / omega sum_\nk) (v_\nk \otimes F_\nk)
    2587              :  ! with S the spin degeneracy factor.
    2588         2387 :  sigma_eh = zero; fsum_eh = zero; onsager = zero
    2589              : 
    2590              :  ! Compute mobility_mu i.e. results in which lifetimes have been computed in a consistent way
    2591              :  ! with the same the Fermi level. In all the other cases, indeed, we assume that tau does not depend on ef.
    2592              :  !
    2593              : 
    2594              :  !TODO: rewrite this because every L (onsager coeff) is given with a minus sign and it's just the case for L11 and L22 normally
    2595              :  ! Fortunately these minus signs compensate each other in the code or are suppressed by putting a -1 factor in front of sbk and PI
    2596              :  ! It is not because of the sign of e !
    2597              :  cnt = 0
    2598           62 :  do spin=1,nsppol
    2599         4557 :    do ik_ibz=1,nkibz
    2600              :      !cnt = cnt + 1; if (mod(cnt, nprocs) /= my_rank) cycle ! MPI parallelism.
    2601         4495 :      wtk = self%ebands%wtk(ik_ibz)
    2602              : 
    2603         9021 :      do ib=self%bmin,self%bmax
    2604         4495 :        eig_nk = self%ebands%eig(ib, ik_ibz, spin)
    2605              : 
    2606              :        ! Compute outer product in vv_tens and symmetrize tensor.
    2607        17980 :        vr(:) = self%vbks(:, ib, ik_ibz, spin)
    2608        22475 :        do ia=1,3
    2609        13485 :          if (ia == 1) then
    2610              :            emu_alpha = one
    2611              :          else
    2612         8990 :            emu_alpha = (eig_nk - mu_e) ** (ia - 1)
    2613              :          end if
    2614              : 
    2615        53940 :          do ii=1,3
    2616       175305 :            do jj=1,3
    2617       161820 :              vv_tens(ii, jj) = vr(ii) * fk(jj, ik_ibz, ib, spin)
    2618              :            end do
    2619              :          end do
    2620       175305 :          vv_tens = vv_tens * emu_alpha
    2621       175305 :          vv_tens = cryst%symmetrize_cart_tens33(vv_tens, time_opt)
    2622              :         ! TODO: write the expression below in another way, without the useless sigma_eh - and without the sign - (adapt the
    2623              :         ! calculations of coefficients in the main routine then)
    2624        13485 :          if (ia == 1 .and. iet /= 3) then
    2625         3770 :            ieh = 2; if (eig_nk >= mu_e) ieh = 1
    2626        49010 :            sigma_eh(:,:,ieh,spin) = sigma_eh(:,:,ieh,spin) - wtk * vv_tens
    2627        15080 :            fsum_eh(:,ieh,spin) = fsum_eh(:,ieh,spin) + wtk * cryst%symmetrize_cart_vec3(fk(:, ik_ibz, ib, spin), time_opt)
    2628              : 
    2629              :          !Here the tensorial product in order to get L21 and L22 to calculate kappa
    2630         9715 :          else if (ia==2 .and. iet==3) then
    2631          725 :                  ieh = 2; if (eig_nk >= mu_e) ieh = 1
    2632         9425 :                  sigma_eh(:,:,ieh,spin) = sigma_eh(:,:,ieh,spin) - wtk * vv_tens
    2633         2900 :            fsum_eh(:,ieh,spin) = fsum_eh(:,ieh,spin) + wtk * cryst%symmetrize_cart_vec3(fk(:, ik_ibz, ib, spin), time_opt)
    2634              :          end if
    2635              : 
    2636              : 
    2637              : 
    2638       179800 :          onsager(:,:,ia,spin) = onsager(:,:,ia,spin) - wtk * vv_tens
    2639              :        end do ! ia
    2640              : 
    2641              :      end do ! ib
    2642              :    end do ! ik_ibz
    2643              :  end do ! spin
    2644              : 
    2645           31 :  if (iet==1) then ! In order to output the mobility (only for L11, the conductivity, thus iet==1)
    2646           23 :    max_occ = two / (self%nspinor * self%nsppol)
    2647           23 :    fact0 = max_occ * (siemens_SI / Bohr_meter / cryst%ucvol) / 100
    2648           23 :    fact = 100**3 / e_Cb
    2649              : 
    2650          644 :    sigma_eh = fact0 * sigma_eh  ! siemens cm^-1
    2651          230 :    fsum_eh = fsum_eh / cryst%ucvol
    2652              : 
    2653              :  ! Scale by the carrier concentration.
    2654           46 :    do spin=1,nsppol
    2655           92 :      do ieh=1,2
    2656              :        call safe_div(sigma_eh(:,:,ieh,spin) * fact, &
    2657          621 :                      self%n_ehst(ieh, spin, itemp) / cryst%ucvol / Bohr_meter**3, zero, mob_eh(:,:,ieh,spin))
    2658              :      end do
    2659              :    end do
    2660              : 
    2661              :    !Here I rescale sigma_eh to output correctly the Onsager coeff L11
    2662          644 :    sigma_eh = sigma_eh / fact0
    2663              :    end if
    2664              :  !call xmpi_sum(sigma_eh, comm, ierr)
    2665              :  !call xmpi_sum(onsager, comm, ierr)
    2666              : 
    2667              : ! max_occ = two / (self%nspinor * self%nsppol)
    2668              : ! sigma_eh = max_occ * sigma_eh / cryst%ucvol
    2669              :  !fsum_eh = fsum_eh / cryst%ucvol
    2670              : 
    2671           31 :  max_occ = two / (self%nspinor * self%nsppol)
    2672              :  !Take into account spin degeneracy for all Onsager coefficient:
    2673          868 :  sigma_eh= max_occ * sigma_eh
    2674              : 
    2675              : 
    2676              : 
    2677              : ! fact0 = max_occ * (siemens_SI / Bohr_meter / cryst%ucvol) / 100
    2678              : ! fact = 100**3 / e_Cb
    2679              : ! sigma_eh = fact0 * sigma_eh
    2680              : 
    2681              : 
    2682              : 
    2683              :  ! Scale by the carrier concentration.
    2684              : ! do spin=1,nsppol
    2685              : !   do ieh=1,2
    2686              : !     call safe_div(sigma_eh(:,:,ieh,spin) * fact, &
    2687              : !                   self%n_ehst(ieh, spin, itemp) / cryst%ucvol / Bohr_meter**3, zero, mob_eh(:,:,ieh,spin))
    2688              : 
    2689              : !check to find the bug
    2690              : !call wrtout(std_out, " ieh, shape(sigma_eh) vol shape(mob_eh) ", pre_newlines=1, newlines=1)
    2691              : !write (std_out,*)  ieh, shape(sigma_eh), cryst%ucvol, shape(mob_eh)
    2692              : !call wrtout(std_out," check safe_div, in order: sigma_eh, self%n_ehst, cryst%ucvol, zero", pre_newlines=1, newlines=1)
    2693              : !        write (std_out,*) sigma_eh(:,:,ieh,spin), self%n_ehst(ieh, spin, itemp), cryst%ucvol, zero
    2694              : ! call flush_unit(std_out)
    2695              : 
    2696              : !        call safe_div(sigma_eh(:,:,ieh,spin), &
    2697              : !                   self%n_ehst(ieh, spin, itemp) / cryst%ucvol, zero, mob_eh(:,:,ieh,spin))
    2698              : !mob_eh(:,:,ieh,spin) = sigma_eh(:,:,ieh,spin)   / (self%n_ehst(ieh, spin, itemp) / cryst%ucvol)
    2699              :            !check to find the bug
    2700              : !           call wrtout(std_out," check safe_div, mob_eh: ", pre_newlines=1, newlines=1)
    2701              : !        write (std_out,*) mob_eh(:,:,ieh,spin)
    2702              : ! call flush_unit(std_out)
    2703              : 
    2704              : !   end do
    2705              : ! end do
    2706              : !In order to be able to compile, to have a value for the dummy argument mob_eh
    2707              : 
    2708              : !call wrtout(std_out, "shape(sigma_eh), sigma_eh,  shape(mob_eh), mob_eh ", pre_newlines=1, newlines=1)
    2709              : !write (std_out,*) shape(sigma_eh),sigma_eh, shape(mob_eh), mob_eh
    2710              : 
    2711              : !mob_eh=zero
    2712              : 
    2713              : !mob_eh=sigma_eh
    2714              : 
    2715              : 
    2716              : !max_occ = two / (self%nspinor * self%nsppol)
    2717              : ! fact_sigma = max_occ * (siemens_SI / Bohr_meter) / 100.  ! Siemens / cm
    2718              : ! fact_mob   = fact_sigma * 100.**3 / e_Cb * Bohr_meter**3 ! cm^2 / V / s
    2719              : ! fact_sbk   = volt_SI * kb_HaK                           ! Volt / Kelvin
    2720              : !   sigma_eh = fact_sigma * sigma_eh  ! siemens cm^-1
    2721              :  !  mob_eh = fact_mob   * mob_eh  !
    2722              : !call wrtout(std_out, "factors: fact_sigma, fact_mob", pre_newlines=1, newlines=1)
    2723              : !   write (std_out,*) fact_sigma, fact_mob
    2724              : 
    2725           31 : end subroutine ibte_calc_tensors
    2726              : !!***
    2727              : 
    2728              : ! Invert 3x3 matrix, copied from matr3inv
    2729        52066 : pure subroutine inv33(aa, ait)
    2730              : 
    2731              : !Arguments ------------------------------------
    2732              : !arrays
    2733              :  real(dp),intent(in) :: aa(3,3)
    2734              :  real(dp),intent(out) :: ait(3,3)
    2735              : 
    2736              : !Local variables-------------------------------
    2737              : !scalars
    2738              :  real(dp) :: dd,det,t1,t2,t3
    2739              : 
    2740              : ! *************************************************************************
    2741              : 
    2742        52066 :  t1 = aa(2,2) * aa(3,3) - aa(3,2) * aa(2,3)
    2743        52066 :  t2 = aa(3,2) * aa(1,3) - aa(1,2) * aa(3,3)
    2744        52066 :  t3 = aa(1,2) * aa(2,3) - aa(2,2) * aa(1,3)
    2745        52066 :  det = aa(1,1) * t1 + aa(2,1) * t2 + aa(3,1) * t3
    2746              : 
    2747              :  ! Make sure matrix is not singular
    2748        52066 :  if (abs(det) > 100 * tiny(one)) then
    2749        15779 :    dd = one / det
    2750        15779 :    ait(1,1) = t1 * dd
    2751        15779 :    ait(2,1) = t2 * dd
    2752        15779 :    ait(3,1) = t3 * dd
    2753        15779 :    ait(1,2) = (aa(3,1)*aa(2,3)-aa(2,1)*aa(3,3)) * dd
    2754        15779 :    ait(2,2) = (aa(1,1)*aa(3,3)-aa(3,1)*aa(1,3)) * dd
    2755        15779 :    ait(3,2) = (aa(2,1)*aa(1,3)-aa(1,1)*aa(2,3)) * dd
    2756        15779 :    ait(1,3) = (aa(2,1)*aa(3,2)-aa(3,1)*aa(2,2)) * dd
    2757        15779 :    ait(2,3) = (aa(3,1)*aa(1,2)-aa(1,1)*aa(3,2)) * dd
    2758        15779 :    ait(3,3) = (aa(1,1)*aa(2,2)-aa(2,1)*aa(1,2)) * dd
    2759       410254 :    ait = transpose(ait)
    2760              :  else
    2761        36287 :    ait = zero
    2762              :  end if
    2763              : 
    2764        52066 :  end subroutine inv33
    2765              : 
    2766        51566 : end module m_rta
    2767              : !!***
        

Generated by: LCOV version 2.3-1