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