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