Branch data Line data Source code
1 : : !! NAME
2 : : !! m_varpeq
3 : : !!
4 : : !! FUNCTION
5 : : !! Description
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 2023-2026 ABINIT group (VV, MG)
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !!
13 : : !! SOURCE
14 : :
15 : : #if defined HAVE_CONFIG_H
16 : : #include "config.h"
17 : : #endif
18 : :
19 : : #include "abi_common.h"
20 : :
21 : : module m_varpeq
22 : :
23 : : use, intrinsic :: iso_c_binding
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_dtset
27 : : use m_dtfil
28 : : use m_crystal
29 : : use m_ebands
30 : : use m_errors
31 : : use m_krank
32 : : use netcdf
33 : : use m_nctk
34 : : use m_xmpi
35 : : use m_ifc
36 : : use m_wfd
37 : : use m_sigtk
38 : :
39 : : use defs_datatypes, only : pseudopotential_type
40 : : use m_numeric_tools, only : interpolate_ur
41 : : use m_fstrings, only : sjoin, ktoa, ftoa, strcat, ltoa, itoa, yesno
42 : : use m_time, only : cwtime_report, cwtime
43 : : use m_io_tools, only : file_exists, iomode_from_fname, open_file
44 : : use m_pptools, only : write_xsf
45 : : use m_geometry, only : xcart2xred, phdispl_cart2red_nmodes
46 : : use m_kpts, only : kpts_map, kpts_timrev_from_kptopt, bzlint_t, kptrlatt_from_ngkpt
47 : : use m_fft_mesh, only : calc_ceikr
48 : : use m_pawtab, only : pawtab_type
49 : : use m_gstore, only : gstore_t, gqk_t
50 : : use m_supercell, only : supercell_type
51 : : use m_paw_sphharm, only : ylm_angular_mesh
52 : : use m_fftcore, only : ngfft_seq
53 : : use m_ephtk, only : ephtk_get_mpw_gmax, EPHTK_WTOL
54 : : use m_dynmat, only : phdispl_from_eigvec
55 : : use m_phonons, only : pheigvec_rotate
56 : : use m_splines, only : spline_complex, splint_complex
57 : : use m_occ, only : occ_be, occ_fd
58 : :
59 : :
60 : : implicit none
61 : :
62 : : private
63 : : !!***
64 : :
65 : : !----------------------------------------------------------------------
66 : :
67 : : !!****t* m_varpeq/polstate_t
68 : : !! NAME
69 : : !! polstate_t
70 : : !!
71 : : !! FUNCTION
72 : : !! Datatype defining MPI-distributed parameters of polaronic states for a
73 : : !! given spin index (if collinear magnetism i.e. nsppol 2). Local variables and
74 : : !! arrays start with `my_`, global have `*glob*` in their names. The MPI grid is
75 : : !! inherited from a gstore%gqk object at initialization.
76 : : !!
77 : : !! SOURCE
78 : :
79 : : type, public :: polstate_t
80 : :
81 : : character(len=abi_slen) :: aseed = " "
82 : : ! Specifies the type of initial seed for charge localization A_nk
83 : : ! Possible values: "gau_energy", "gau_length", "random", "even", "localize"
84 : :
85 : : logical :: translate = .false.
86 : : ! Flag controlling treatment of polaronic solution invariant by primitive
87 : : ! translations inside supercell
88 : : ! if .true. and np > 1, the next solution is found to be orthogonal to all
89 : : ! previous states + their translated replicas
90 : :
91 : : integer :: spin = -1
92 : : ! Spin index
93 : :
94 : : integer :: ip = -1
95 : : ! Current polaronic state
96 : :
97 : : integer :: np = -1
98 : : ! Number of polaronic states
99 : :
100 : : integer :: nkbz = -1
101 : : ! Number of k-points in full BZ
102 : :
103 : : integer :: nqbz = -1
104 : : ! Number of q-points in full BZ
105 : :
106 : : integer :: psign = 1
107 : : ! Sign of the charge carrier
108 : : ! +1 -- electron addition (electron polaron)
109 : : ! -1 -- electron removal (hole polaron)
110 : :
111 : : real(dp) :: e_frohl
112 : : ! Long-range divergence correction of polaron binding energy due to g(0) avg
113 : :
114 : : real(dp) :: efilter
115 : : ! Energy filter
116 : :
117 : : integer :: ngkpt(3)
118 : : ! Number of points in the uniform k-grid defining the electronic subspace
119 : :
120 : : real(dp) :: gpr_energy(2)
121 : : ! Gaussian parameters for energy-based initialization
122 : :
123 : : real(dp) :: gpr_length(3)
124 : : ! Gaussian parameters for localization length-based initialization
125 : :
126 : : logical, allocatable :: has_prev_grad(:)
127 : : ! (np)
128 : : ! Flag indicating if an electronic gradient has been computed at previous step
129 : :
130 : : real(dp), allocatable :: gradres(:)
131 : : ! (np)
132 : : ! L^2-norm of the electronic gradient for each state
133 : :
134 : : real(dp), allocatable :: enterms(:,:)
135 : : ! (4, np)
136 : : ! Polaronic energy terms for each state
137 : : ! 1 -> electronic term
138 : : ! 2 -> vibrational term
139 : : ! 3 -> electron-phonon term
140 : : ! 4 -> polaron energy level
141 : :
142 : : real(dp), allocatable :: eig(:,:)
143 : : ! (gqk%nb_k, gstore%ebands%nkpt)
144 : : ! Electronic eigenstates participating in the polaron formation
145 : : ! Correspond either to valence or conduction manifold, not both
146 : : ! Band edge is set to 0; valence states are also inverted
147 : :
148 : : real(dp), allocatable :: my_g0(:)
149 : : ! (gqk%my_npert)
150 : : ! Long-range correction for electron-phonon matrix elements at q=\Gamma
151 : :
152 : : real(dp), allocatable :: my_qpts(:,:)
153 : : ! (3, gqk%my_nq)
154 : : ! q-points treated by this MPI proc
155 : :
156 : : real(dp), allocatable :: displ(:,:,:)
157 : : ! (3, self%scell%natom, np)
158 : : ! Atomic displacements \Delta \tau_{\alpha \kappa*p} for each state
159 : :
160 : : real(dp), pointer :: my_kpts(:,:) => null()
161 : : ! (3, gqk%my_nk)
162 : : ! k-points treated by this MPI proc, points to gqk%my_kpts(:,:)
163 : :
164 : : complex(dp), allocatable :: my_a(:,:,:)
165 : : ! (gqk%nb_k, gqk%my_nk, np)
166 : : ! Electronic coefficients A_nk for each state treated by this MPI proc
167 : :
168 : : complex(dp), allocatable :: a_glob(:,:,:)
169 : : ! (gqk%nb_k, gqk%glob_nk, np)
170 : : ! Global array of electronic coefficients A_nk at each state
171 : :
172 : : complex(dp), allocatable :: my_b(:,:,:)
173 : : ! (gqk%my_npert, gqk%my_nq, np)
174 : : ! Vibrational coefficients B_q\nu for each state treated by this MPI proc
175 : :
176 : : complex(dp), allocatable :: my_prev_b(:,:)
177 : : ! (gqk%my_npert, gqk%my_nq)
178 : : ! Previous vibrational coefficients B_q\nu for each state treated by this MPI proc
179 : :
180 : : complex(dp), allocatable :: my_prev_b_hop(:,:,:)
181 : : ! (gqk%my_npert, gqk%my_nq)
182 : : ! Previous vibrational coefficients B_q\nu for each state (hopping optimization)
183 : :
184 : : complex(dp), allocatable :: my_pc(:,:)
185 : : ! (gqk%nb_k, gqk%my_nk)
186 : : ! Preconditioner at current state treated by this MPI proc
187 : :
188 : : complex(dp), allocatable :: my_grad(:,:)
189 : : ! (gqk%nb_k, gqk%my_nk)
190 : : ! Electronic gradient D_nk at current state treated by this MPI proc
191 : : ! orthogonal to states
192 : :
193 : : complex(dp), allocatable :: my_prev_grad(:,:)
194 : : ! (gqk%nb_k, gqk%my_nk)
195 : : ! Previous electronic gradient D_nk at current state, orthogonal to states
196 : :
197 : : complex(dp), allocatable :: my_pcgrad(:,:)
198 : : ! (gqk%nb_k, gqk%my_nk)
199 : : ! Preconditioned gradient at current state, orthogonal to states
200 : :
201 : : complex(dp), allocatable :: my_prev_pcgrad(:,:)
202 : : ! (gqk%nb_k, gqk%my_nk)
203 : : ! Previous preconditioned gradient at current state, orthogonal to states
204 : :
205 : : complex(dp), allocatable :: my_pcjgrad(:,:)
206 : : ! (gqk%nb_k, gqk%my_nk)
207 : : ! Preconditioned conjugate gradient at current state treated by this MPI proc
208 : : ! orthogonal to current state & normalized
209 : :
210 : : complex(dp), allocatable :: my_prev_pcjgrad(:,:)
211 : : ! (gqk%nb_k, gqk%my_nk)
212 : : ! Previous preconditioned conjugate gradient at current state
213 : :
214 : : complex(dp), allocatable :: pcjgrad_glob(:,:)
215 : : ! (gqk%nb_k, gqk%glob_nk)
216 : : ! Global preconditioned conjugate gradient at current state
217 : : ! orthogonal to current state & normalized
218 : :
219 : : complex(dp), allocatable :: my_phgrad(:,:,:)
220 : : ! (gqk%my_npert, gqk%my_nq, np)
221 : : ! Phonon gradient \nabla E_{B_q\nu} for each state treated by this MPI proc
222 : :
223 : : complex(dp), allocatable :: my_eff_phforce(:,:,:)
224 : : ! (gqk%my_npert, gqk%my_nq, np)
225 : : ! Effective phonon force F_q\nu at current state treated by this MPI proc
226 : :
227 : : real(dp), allocatable :: hop_ts(:)
228 : : ! (np)
229 : : ! Line minimization timestep for hopping optimization for each state
230 : :
231 : : class(gqk_t), pointer :: gqk => null()
232 : : ! Datastructure storing e-ph matrix elements treated by this MPI proc
233 : :
234 : : type(krank_t) :: krank_kpts
235 : : ! Object used to find k-points in BZ
236 : :
237 : : type(krank_t) :: krank_qpts
238 : : ! Object used to find q-points in BZ
239 : :
240 : : type(crystal_t) :: cryst
241 : : ! Object storing information on crystal structure & symmetries
242 : :
243 : : contains
244 : :
245 : : procedure :: setup => polstate_setup
246 : : ! Set up optimization process by specifying initial electronic vector A_nk
247 : :
248 : : procedure :: localize => polstate_localize
249 : : ! Localize polaron at current state. From A_nk calculate:
250 : : ! vibrational coefficients B_q\nu, energy terms, polaron level
251 : :
252 : : procedure :: get_enel => polstate_get_enel
253 : : ! Calculate and return electronic energy term
254 : :
255 : : procedure :: get_enph => polstate_get_enph
256 : : ! Calculate and return vibrational energy term
257 : :
258 : : procedure :: get_enelph => polstate_get_enelph
259 : : ! Calculate and return electron-phonon energy term
260 : :
261 : : procedure :: get_lm_theta => polstate_get_lm_theta
262 : : ! Calculate and return line minimization parameter \theta
263 : :
264 : : procedure :: calc_grad => polstate_calc_grad
265 : : ! Calculate steepest descent vector (electronic gradient)
266 : :
267 : : procedure :: calc_pcjgrad => polstate_calc_pcjgrad
268 : : ! Calculate preconditioned conjugate gradient direction
269 : :
270 : : procedure :: update_pc => polstate_update_pc
271 : : ! Update preconditioner
272 : :
273 : : procedure :: update_a => polstate_update_a
274 : : ! Update array of electronic coefficients
275 : :
276 : : procedure :: ort_to_states => polstate_ort_to_states
277 : : ! Orthogonalize a given vector to a set of polaronic states
278 : :
279 : : procedure :: calc_b_from_a => polstate_calc_b_from_a
280 : : ! Calculate vibrational coefficients B_q\nu from a known set of electronic
281 : : ! coefficients A_nk
282 : :
283 : : procedure :: calc_b_from_displ => polstate_calc_b_from_displ
284 : : ! Calculate vibrational coefficients B_q\nu from a known set of displacements
285 : : ! \Delta \tau_{\alpha \kappa p}
286 : :
287 : : procedure :: calc_displ_from_b => polstate_calc_displ_from_b
288 : : ! Calculate polaron-induced displacements \Delta \tau_{\alpha \kappa p} from
289 : : ! a known set of vibrational coefficients B_q\nu
290 : :
291 : : procedure :: calc_clb_displ => polstate_calc_clb_displ
292 : : ! Calculate displacements induced by the Coulomb forces for a unit charge
293 : : ! localized on a supercell atom
294 : :
295 : : procedure :: calc_phgrad => polstate_calc_phgrad
296 : : ! Calculate steepest descent vector (phonon gradient)
297 : :
298 : : procedure :: calc_hpol => polstate_calc_hpol
299 : : ! Construct and calculate the polaron Hamiltonian, <A_bra|H(B)|A_ket>
300 : :
301 : : procedure :: seed_a => polstate_seed_a
302 : : ! Seed an initial vector of electronic coefficients A_nk
303 : :
304 : : procedure :: load_a => polstate_load_a
305 : : ! Initialize A_nk from an existing vector of electronic coefficients
306 : :
307 : : procedure :: load_b => polstate_load_b
308 : : ! Initialize B_q\nu from an existing vector of electronic coefficients
309 : :
310 : : procedure :: linterp_b => polstate_linterp_b
311 : : ! Linear interpolation of B_\qnu coefficients between initial and final state
312 : :
313 : : procedure :: redistr_b => polstate_redistr_b
314 : : ! Redistribute B_\qnu coefficients with spline interpolation
315 : :
316 : : procedure :: calc_eff_phforce => polstate_calc_eff_phforce
317 : : ! Calculate effective phonon force for hopping optimization
318 : :
319 : : procedure :: calc_hop_timestep => polstate_calc_hop_timestep
320 : : ! Calculate timestep from effective phonon force for this state
321 : :
322 : : procedure :: get_sqnorm => polstate_get_sqnorm
323 : : ! Helper function to compute squared L^2-norm of MPI-distributed array
324 : :
325 : : procedure :: gather => polstate_gather
326 : : ! Helper function to gather MPI-distributed array into a global one
327 : :
328 : : procedure :: filter => polstate_filter
329 : : ! Helper function to filter MPI-distributed array
330 : :
331 : : procedure :: get_krank_glob => polstate_get_krank_glob
332 : : ! Helper function to calculate global krank objects
333 : :
334 : : procedure :: free => polstate_free
335 : : ! Free memory
336 : :
337 : : end type polstate_t
338 : : !!***
339 : :
340 : : !----------------------------------------------------------------------
341 : :
342 : : !!****t* m_varpeq/varpeq_t
343 : : !! NAME
344 : : !! varpeq_t
345 : : !!
346 : : !! FUNCTION
347 : : !! Variational Polaron Equations datatype. Stores variational optimization
348 : : !! parameters, polaronic states and provides higher-level procedures required
349 : : !! for variational optimization and related input and output.
350 : : !!
351 : : !! SOURCE
352 : :
353 : : type, public :: varpeq_t
354 : :
355 : : character(len=abi_slen) :: mode = " "
356 : : ! Specifies the calculation mode
357 : : ! Possible values: "polaron", "hopping"
358 : :
359 : : character(len=abi_slen) :: pkind = " "
360 : : ! Specifies the kind of polaron
361 : : ! Possible values: "hole", "electron"
362 : :
363 : : character(len=abi_slen) :: aseed = " "
364 : : ! Specifies the type of initial seed for charge localization A_nk
365 : : ! Possible values: "gau_energy", "gau_length", "random", "even", "localize"
366 : :
367 : : logical :: fix_displ = .false.
368 : : ! Flag indicating if vibrational coefficients need to be fixed between steps.
369 : : ! True for hopping calculations.
370 : :
371 : : logical :: use_filter = .false.
372 : : ! Flag indicating if the energy filtering for electronic states was used
373 : :
374 : : logical :: is_complete = .false.
375 : : ! Flag indicating if the datatype is completely or partially initialized
376 : : ! Required to distinguish between newly created and loaded-from-disk datatype
377 : :
378 : : logical :: restart = .false.
379 : : ! Flag to check if a restart from a *VPQ.nc file is needed
380 : :
381 : : logical :: interp = .false.
382 : : ! Flag to check if an interpolation from a *VPQ.nc file is needed
383 : :
384 : : logical :: ld_flag = .false.
385 : : ! Flag indicating if internal variables have been loaded from source
386 : :
387 : : logical :: g0_flag = .true.
388 : : ! Flag indicating if the average of el-ph matrix elements at Gamma is computed
389 : :
390 : : logical :: translate = .false.
391 : : ! Flag controlling the translational invariance of polaronic solutions
392 : :
393 : : integer :: ncid = nctk_noid
394 : : ! Netcdf file handle used to save results
395 : :
396 : : integer :: atloc = -1
397 : : ! At which atom the polaron is localized
398 : : ! from 1 to cryst%natom if aseed = "localize"
399 : :
400 : : integer :: hop_nstep = -1
401 : : ! Maximum number of iterations for hopping transport optimization
402 : :
403 : : integer :: nstep = -1
404 : : ! Maximum number of iterations for optimization of a single polaronic state
405 : :
406 : : integer :: nstep_ort = -1
407 : : ! Maximum number of iterations for which orthogonalization to all previous
408 : : ! states is performed
409 : :
410 : : integer :: nsppol = -1
411 : : ! Number of independent spin polarizations
412 : :
413 : : integer :: nstates = -1
414 : : ! Number of polaronic states to be optimized for each spin polarization
415 : :
416 : : integer :: natom3 = -1
417 : : ! 3*gstore%cryst%natom
418 : : ! Number of atomic perturbations, mainly used to dimensionalize arrays
419 : :
420 : : integer :: max_nk = -1
421 : : ! Maximum number of k-points among between independent spin polarizations
422 : :
423 : : integer :: max_nq = -1
424 : : ! Maximum number of q-points among between independent spin polarizations
425 : :
426 : : integer :: max_nb = -1
427 : : ! Maximum number of bands among between independent spin polarizations
428 : :
429 : : integer :: frohl_ntheta = -1
430 : : ! Number of angular mesh division for spherical integration of long-range
431 : : ! divergence of electron-phonon matrix elements
432 : :
433 : : real(dp) :: e_frohl
434 : : ! Long-range divergence correction of polaron binding energy
435 : :
436 : : real(dp) :: mixing_factor
437 : : ! Mixing factor to be used in the solver for vibrational coefficients
438 : :
439 : : real(dp) :: tolgrs
440 : : ! L^2 gradient norm tolerance
441 : :
442 : : real(dp) :: hop_tolgrs
443 : : ! L^2 force norm tolerance for hopping optimization
444 : :
445 : : real(dp) :: hop_ts
446 : : ! Timestep for hopping
447 : :
448 : : integer :: ngkpt(3)
449 : : ! Number of points in the uniform k-grid defining the electronic subspace
450 : :
451 : : integer, allocatable :: nk_spin(:)
452 : : ! (nsppol)
453 : : ! Number of k-points for each spin polarization
454 : :
455 : : integer, allocatable :: nq_spin(:)
456 : : ! (nsppol)
457 : : ! Number of q-points for each spin polarization
458 : :
459 : : integer, allocatable :: nb_spin(:)
460 : : ! (nsppol)
461 : : ! Number of bands for each spin polarization
462 : :
463 : : integer, allocatable :: brange_spin(:,:)
464 : : ! (2, nsppol)
465 : : ! Number of bands for each spin polarization
466 : :
467 : : integer, allocatable :: cvflag_spin(:,:,:)
468 : : ! (nstates, hop_nstep, nsppol)
469 : : ! Convergence flags at each state for each spin:
470 : : ! 0 --> calculation is not converged
471 : : ! 1 --> calculation is converged
472 : :
473 : : integer, allocatable :: hop_nstep2cv_spin(:)
474 : : ! (nsppol)
475 : : ! number of steps to convergence the hopping optimization for each spin
476 : :
477 : : integer, allocatable :: nstep2cv_spin(:,:,:)
478 : : ! (nstates, hop_nstep, nsppol)
479 : : ! number of steps to convergence at each state for each spin
480 : :
481 : : real(dp), allocatable :: erange_spin(:)
482 : : ! (nsppol)
483 : : ! energy window wrt to vbm/cbm for hole/electron polaron for each spin
484 : :
485 : : integer, allocatable :: k2ibz_spin(:,:)
486 : : ! (max_nk, nsppol)
487 : : ! bz->ibz index table for kpoints (related to sell%gstore%kibz)
488 : :
489 : : integer, allocatable :: q2ibz_spin(:,:)
490 : : ! (max_nq, nsppol)
491 : : ! bz->ibz index table for qpoints (related to sell%gstore%qibz)
492 : :
493 : : real(dp), allocatable :: chrgat(:)
494 : : ! (natom)
495 : : ! charge of the cations
496 : :
497 : : real(dp), allocatable :: hop_hist_spin(:,:,:,:)
498 : : ! (5, nstates, hop_nstep, nsppol)
499 : : ! hopping optimization history at each state (image) for each spin
500 : : ! 1 - bare phonon force norms, i.e. |dE_pol/dB| at each image
501 : : ! 2 - string forces, i.e. |B^n - B^(n-1)|/timestep for step n
502 : : ! 3 - diabatic energy curve for initial state: <A_in|B_i|A_in>
503 : : ! 4 - diabatic energy curve for final state: <A_end|B_i|A_end>
504 : : ! 5 - overlap integral <A_in|B_i|A_end>
505 : :
506 : : real(dp), allocatable :: scf_hist_spin(:,:,:,:,:)
507 : : ! (6, nstep, nstates, hop_nstep, nsppol)
508 : : ! scf optimization history at each state for each spin
509 : : ! 1 - binding energy, 2 - electronic energy, 3 - phonon energy
510 : : ! 4 - electron-phonon energy, 5 - localization energy
511 : : ! 6 - gradient norm
512 : :
513 : : real(dp), allocatable :: kpts_spin(:,:,:)
514 : : ! (3, max_nk, nsppol)
515 : : ! k-points for each spin
516 : :
517 : : real(dp), allocatable :: qpts_spin(:,:,:)
518 : : ! (3, max_nq, nsppol)
519 : : ! q-points for each spin
520 : :
521 : : complex(dp), allocatable :: a_spin(:,:,:,:)
522 : : ! (max_nb, max_nk, nstates, nsppol)
523 : : ! optimized electronic coefficients a_nk at each state for each spin
524 : :
525 : : complex(dp), allocatable :: b_spin(:,:,:,:)
526 : : ! (natom3, max_nq, nstates, nsppol)
527 : : ! optimized vibrational coefficients b_q\nu at each state for each spin
528 : :
529 : : class(gstore_t), pointer :: gstore => null()
530 : : ! object storing el-ph matrix elements and other related quantities
531 : :
532 : : type(crystal_t) :: cryst
533 : : ! Object storing information on crystal structure & symmetries
534 : :
535 : : type(gaps_t) :: gaps
536 : : ! Object used to get information on bandgap
537 : :
538 : : type(supercell_type) :: scell
539 : : ! Object used to get information on supercell
540 : :
541 : : type(polstate_t), allocatable :: polstate(:)
542 : : ! (nsppol)
543 : : ! Datatype providing data and lower-level methods for polaronic states
544 : : ! at each spin polarization
545 : :
546 : : contains
547 : :
548 : : procedure :: init => varpeq_init
549 : : ! Initialize object
550 : :
551 : : procedure :: load => varpeq_load
552 : : ! Load the initial electronic vector from a *VPQ.nc netcdf file
553 : :
554 : : procedure :: solve => varpeq_solve
555 : : ! Solve variational polaron equations at each polaronic state for each spin
556 : :
557 : : procedure :: record => varpeq_record
558 : : ! Record the current SCF optimization data
559 : :
560 : : procedure :: collect => varpeq_collect
561 : : ! Collect SCF optimization results from each spin
562 : :
563 : : procedure :: print_scf_results => varpeq_print_scf_results
564 : : ! Output SCF optimization final results
565 : :
566 : : procedure :: print_hop_results => varpeq_print_hop_results
567 : : ! Output hopping optimization final results
568 : :
569 : : procedure :: print_metadata => varpeq_print_metadata
570 : : ! Output parameters defining varpeq calculation
571 : :
572 : : procedure :: ncwrite => varpeq_ncwrite
573 : : ! Save results to a *VPQ.nc netcdf file
574 : :
575 : : procedure :: ncread => varpeq_ncread
576 : : ! Initialize an incomplete object from a *VPQ.nc netcdf file
577 : :
578 : : procedure :: compare => varpeq_compare
579 : : ! Compare basic dimensions with another instance of varpeq_t datatype
580 : :
581 : : procedure :: calc_fravg => varpeq_calc_fravg
582 : : ! Calculate average Fr\"ohlich (long-range) contribution to the polaron
583 : : ! binding energy & average of electron-phonon matrix elements at q=\Gamma
584 : :
585 : : procedure :: hop_setup => varpeq_hop_setup
586 : : ! Set up the data structure for hopping transport calculations
587 : :
588 : : procedure :: hop => varpeq_hop
589 : : ! Polaron hopping optimization for self%nstates images
590 : :
591 : : procedure :: free => varpeq_free
592 : : ! Free memory
593 : :
594 : : end type varpeq_t
595 : : !!***
596 : :
597 : : public :: varpeq_run
598 : : ! Main entry point
599 : :
600 : : public :: varpeq_plot
601 : : ! Compute polaron wavefunctions and atomic displacements in the supercell and write results to XSF files
602 : :
603 : : contains !=====================================================================
604 : :
605 : :
606 : : !!****f* m_varpeq/varpeq_run
607 : : !! NAME
608 : : !! varpeq_run
609 : : !!
610 : : !! FUNCTION
611 : : !! Higher-level subroutine that solves variational polaron equations, produces
612 : : !! necessary output and writes results to a *VPQ.nc file.
613 : : !!
614 : : !! INPUTS
615 : : !! gstore<gstore_t>=Electron-phonon matrix elements and related quantities.
616 : : !! dtset<dataset_type>=All input variables for this dataset.
617 : : !! dtfil<datafiles_types>=Variables related to files.
618 : : !!
619 : : !! OUTPUT
620 : : !!
621 : : !! SOURCE
622 : :
623 : 9 : subroutine varpeq_run(gstore, dtset, dtfil)
624 : :
625 : : !Arguments ------------------------------------
626 : : class(gstore_t), intent(in) :: gstore
627 : : type(dataset_type), intent(in) :: dtset
628 : : type(datafiles_type), intent(in) :: dtfil
629 : : !arrays
630 : : integer :: units(2)
631 : :
632 : : !Local variables-------------------------------
633 [ + + + + : 468 : type(varpeq_t) :: vpq
+ + + + +
+ + + + +
+ + + + ]
634 : : !----------------------------------------------------------------------
635 : :
636 [ + + ]: 27 : units = [std_out, ab_out]
637 : 9 : call wrtout(units, sjoin(ch10, " === Variational Polaron Equations ==="))
638 : :
639 : 9 : call vpq%init(gstore, dtset)
640 [ + - ]: 9 : if (vpq%frohl_ntheta > 0) call vpq%calc_fravg(avg_g0=vpq%g0_flag)
641 [ + - - + ]: 9 : if (vpq%interp .or. vpq%restart) call vpq%load(dtfil, dtset%vpq_select)
642 : :
643 : 9 : call vpq%print_metadata()
644 : :
645 : 8 : select case(vpq%mode)
646 : : case ("polaron")
647 : 8 : call vpq%solve(verbose=.true.)
648 : :
649 : : case ("hopping")
650 [ - + ]: 1 : ABI_CHECK(vpq%nstates > 1, "varpeq_run: vpq_nstates must be > 1 for hopping")
651 : 1 : call vpq%hop_setup(dtset)
652 : 1 : call vpq%hop()
653 : :
654 : : case default
655 [ + + - ]: 9 : ABI_ERROR(sjoin("varpeq_run, unsupported varpeq mode: ", vpq%mode))
656 : : end select
657 : :
658 : 9 : call vpq%collect()
659 : :
660 : 8 : select case(vpq%mode)
661 : : case ("polaron")
662 : 8 : call vpq%print_scf_results(ihop=1)
663 : : case ("hopping")
664 [ + + - ]: 9 : call vpq%print_hop_results()
665 : : end select
666 : :
667 : 9 : call vpq%ncwrite(dtset, dtfil)
668 : 9 : call vpq%free()
669 : :
670 [ - + - + : 9 : end subroutine varpeq_run
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - ]
671 : : !!***
672 : :
673 : : !----------------------------------------------------------------------
674 : :
675 : : !!****f* m_varpeq/varpeq_free
676 : : !! NAME
677 : : !! varpeq_free
678 : : !!
679 : : !! FUNCTION
680 : : !! Free dynamic memory
681 : : !!
682 : : !! SOURCE
683 : :
684 : 13 : subroutine varpeq_free(self)
685 : :
686 : : !Arguments ------------------------------------
687 : : class(varpeq_t), target, intent(inout) :: self
688 : :
689 : : !Local variables-------------------------------
690 : : integer :: my_is
691 : : !----------------------------------------------------------------------
692 : :
693 : : ! Free allocatable arrays
694 : : ! integer
695 [ + - ]: 13 : ABI_SFREE(self%nk_spin)
696 [ + - ]: 13 : ABI_SFREE(self%nq_spin)
697 [ + - ]: 13 : ABI_SFREE(self%nb_spin)
698 [ + - ]: 13 : ABI_SFREE(self%brange_spin)
699 [ + + ]: 13 : ABI_SFREE(self%cvflag_spin)
700 [ + + ]: 13 : ABI_SFREE(self%hop_nstep2cv_spin)
701 [ + + ]: 13 : ABI_SFREE(self%nstep2cv_spin)
702 : : ! real
703 [ + + ]: 13 : ABI_SFREE(self%chrgat)
704 [ + + ]: 13 : ABI_SFREE(self%erange_spin)
705 [ + + ]: 13 : ABI_SFREE(self%hop_hist_spin)
706 [ + + ]: 13 : ABI_SFREE(self%scf_hist_spin)
707 [ + + ]: 13 : ABI_SFREE(self%k2ibz_spin)
708 [ + + ]: 13 : ABI_SFREE(self%q2ibz_spin)
709 [ + - ]: 13 : ABI_SFREE(self%kpts_spin)
710 [ + - ]: 13 : ABI_SFREE(self%qpts_spin)
711 : :
712 : : ! complex
713 [ + - ]: 13 : ABI_SFREE(self%a_spin)
714 [ + - ]: 13 : ABI_SFREE(self%b_spin)
715 : :
716 : : ! Free local datatypes
717 : 13 : call self%cryst%free()
718 : :
719 : : ! Close netcdf file
720 [ + + ]: 13 : if (self%ncid /= nctk_noid) then
721 [ - + ]: 9 : NCF_CHECK(nf90_close(self%ncid))
722 : 9 : self%ncid = nctk_noid
723 : : end if
724 : :
725 : : ! If entry is completely initialized (e.g. from self%init call), free remaining
726 : : ! datatypes and nullify pointers
727 [ + + ]: 13 : if (self%is_complete) then
728 : 9 : call self%gaps%free()
729 [ + + ]: 18 : do my_is=1,self%gstore%my_nspins
730 : 18 : call self%polstate(my_is)%free()
731 : : enddo
732 : 9 : call self%scell%free()
733 [ + - + + : 18 : ABI_SFREE(self%polstate)
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ ]
734 : 9 : self%gstore => null()
735 : : endif
736 : :
737 : 13 : end subroutine varpeq_free
738 : : !!***
739 : :
740 : : !----------------------------------------------------------------------
741 : :
742 : : !!****f* m_varpeq/varpeq_compare
743 : : !! NAME
744 : : !! varpeq_compare
745 : : !!
746 : : !! FUNCTION
747 : : !! Compares the current instance of varpeq datatype with another one (possibly
748 : : !! incomplete).
749 : : !!
750 : : !! INPUTS
751 : : !! other<varpeq_t>=Varpeq datatype to compare with.
752 : : !! bz_mismatch [optional]=if .true. mismatch between BZ sampling is allowed
753 : : !! (required for comparison prior to an interpolation)
754 : : !!
755 : : !! OUTPUT
756 : : !!
757 : : !! SOURCE
758 : :
759 : 4 : subroutine varpeq_compare(self, other, bz_mismatch)
760 : :
761 : : !Arguments ------------------------------------
762 : : class(varpeq_t), target, intent(in) :: self, other
763 : : logical, optional, intent(in) :: bz_mismatch
764 : :
765 : : !Local variables-------------------------------
766 : : integer :: ierr
767 : : real(dp) :: cpu, wall, gflops
768 : : !----------------------------------------------------------------------
769 : :
770 : : ! TODO: provide more flexibility for nstates
771 : :
772 : 2 : call cwtime(cpu, wall, gflops, "start")
773 : :
774 : 2 : ierr = 0
775 : :
776 : : ! Compare basic dimensions
777 : 2 : call check_(self%pkind == other%pkind, "Difference found in pkind.")
778 : 2 : call check_(self%nsppol == other%nsppol, "Difference found in nsppol.")
779 : : !call check_(self%nstates == other%nstates, "Difference found in nstates.")
780 : : call check_(self%cryst%compare(other%cryst) == 0, &
781 : 2 : "Difference found in cryst.")
782 : : call check_(all(self%brange_spin == other%brange_spin), &
783 [ + + + + : 8 : "Difference found in brange_spin.")
+ - ]
784 : :
785 : : ! If bz_mismatch is not allowed, also compare k/q-grids
786 [ + - ]: 2 : if (present(bz_mismatch)) then
787 [ + - ]: 2 : if (.not. bz_mismatch) then
788 : : call check_(all(abs(self%kpts_spin - other%kpts_spin) < tol6), &
789 [ + + + + : 1004 : "Difference found in kpts_spin.")
+ + + - ]
790 : : call check_(all(abs(self%qpts_spin - other%qpts_spin) < tol6), &
791 [ + + + + : 1004 : "Difference found in nq_spin.")
+ + + - ]
792 : : end if
793 : : endif
794 : :
795 [ - + ]: 2 : ABI_CHECK(ierr == 0, "Error in varpeq_compare, see previous messages!")
796 : :
797 : 2 : call cwtime_report(" varpeq_compare", cpu, wall, gflops)
798 : :
799 : : contains
800 : 12 : subroutine check_(cond, msg)
801 : : logical, intent(in) :: cond
802 : : character(len=*), intent(in) :: msg
803 [ - + ]: 12 : ABI_CHECK_NOSTOP(cond, msg, ierr)
804 : 12 : end subroutine check_
805 : :
806 : : end subroutine varpeq_compare
807 : : !!***
808 : :
809 : : !----------------------------------------------------------------------
810 : :
811 : : !!****f* m_varpeq/varpeq_ncread
812 : : !! NAME
813 : : !! varpeq_ncread
814 : : !!
815 : : !! FUNCTION
816 : : !! Reads basic dimensions of varpeq_t datatype from a *VPQ.nc netcdf file.
817 : : !!
818 : : !! INPUTS
819 : : !! path=Path a *VPQ.nc file to be read.
820 : : !! comm=MPI communicator.
821 : : !! keep_open [optional]=if .true. keep the nc file handle open for further
822 : : !! reading. Default: .false.
823 : : !!
824 : : !! OUTPUT
825 : : !!
826 : : !! SOURCE
827 : :
828 : 4 : subroutine varpeq_ncread(self, path, comm, keep_open)
829 : :
830 : : !Arguments ------------------------------------
831 : : class(varpeq_t), target, intent(inout) :: self
832 : : character(len=fnlen), intent(in) :: path
833 : : integer, intent(in) :: comm
834 : : logical, optional, intent(in) :: keep_open
835 : :
836 : : !Local variables-------------------------------
837 : : integer :: ncid, nsppol, natom3, nstates
838 : : real(dp) :: cpu, wall, gflops
839 : 4 : real(dp), contiguous, pointer :: rpt_d5(:,:,:,:,:)
840 : : !----------------------------------------------------------------------
841 : :
842 : 4 : call cwtime(cpu, wall, gflops, "start")
843 : :
844 [ - + ]: 4 : ABI_CHECK(file_exists(path), sjoin(" varpeq_ncread: cannot find *VPQ.nc file", path))
845 : :
846 [ - + ]: 4 : NCF_CHECK(nctk_open_read(ncid, path, comm))
847 : :
848 : : ! Read crystal structure
849 : 4 : call self%cryst%ncread(ncid)
850 : :
851 : : ! Read varpeq dimensions
852 [ - + ]: 4 : NCF_CHECK(nctk_get_dim(ncid, "nsppol", self%nsppol))
853 [ - + ]: 4 : NCF_CHECK(nctk_get_dim(ncid, "nstates", self%nstates))
854 [ - + ]: 4 : NCF_CHECK(nctk_get_dim(ncid, "natom3", self%natom3))
855 [ - + ]: 4 : NCF_CHECK(nctk_get_dim(ncid, "max_nk", self%max_nk))
856 [ - + ]: 4 : NCF_CHECK(nctk_get_dim(ncid, "max_nq", self%max_nq))
857 [ - + ]: 4 : NCF_CHECK(nctk_get_dim(ncid, "max_nb", self%max_nb))
858 : 4 : nsppol = self%nsppol
859 : 4 : nstates = self%nstates
860 : 4 : natom3 = self%natom3
861 : :
862 : : ! Read data
863 : : ! Static arrays
864 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("vpq_pkind"), self%pkind))
865 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("ngkpt"), self%ngkpt))
866 : :
867 : : ! Allocatable arrays
868 [ - + + - : 12 : ABI_MALLOC(self%nk_spin, (nsppol))
+ - + - -
+ - + -
+ ]
869 [ - + + - : 8 : ABI_MALLOC(self%nq_spin, (nsppol))
- + - + -
+ ]
870 [ - + + - : 8 : ABI_MALLOC(self%nb_spin, (nsppol))
- + - + -
+ ]
871 [ - + + - : 12 : ABI_MALLOC(self%brange_spin, (2, nsppol))
+ - + - -
+ - + -
+ ]
872 [ - + + - : 16 : ABI_MALLOC(self%kpts_spin, (3, self%max_nk, nsppol))
- + + - +
- + - - +
- + - + ]
873 [ - + + - : 16 : ABI_MALLOC(self%qpts_spin, (3, self%max_nq, nsppol))
- + + - +
- + - - +
- + - + ]
874 [ - + + - : 24 : ABI_MALLOC(self%a_spin, (self%max_nb, self%max_nk, nstates, nsppol))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
875 [ - + + - : 24 : ABI_MALLOC(self%b_spin, (natom3, self%max_nq, nstates, nsppol))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
876 : :
877 : : ! integer
878 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("nk_spin"), self%nk_spin))
879 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("nq_spin"), self%nq_spin))
880 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("nb_spin"), self%nb_spin))
881 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("brange_spin"), self%brange_spin))
882 : : ! real
883 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("kpts_spin"), self%kpts_spin))
884 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("qpts_spin"), self%qpts_spin))
885 : : ! complex
886 : : ! TODO: is it possible to encapsulate this trick as some abstraction?
887 : : call c_f_pointer(c_loc(self%a_spin), rpt_d5, &
888 [ + + ]: 24 : [2, self%max_nb, self%max_nk, nstates, nsppol])
889 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("a_spin"), rpt_d5))
890 : :
891 : : call c_f_pointer(c_loc(self%b_spin), rpt_d5, &
892 [ + + ]: 24 : [2, natom3, self%max_nq, nstates, nsppol])
893 [ - + ]: 4 : NCF_CHECK(nf90_get_var(ncid, vid("b_spin"), rpt_d5))
894 : :
895 [ + + ]: 4 : if (present(keep_open)) then
896 [ - + ]: 2 : if (keep_open) self%ncid = ncid
897 : : else
898 [ - + ]: 2 : NCF_CHECK(nf90_close(ncid))
899 : 2 : self%ncid = nctk_noid
900 : : end if
901 : :
902 : 4 : self%is_complete = .false.
903 : :
904 : 8 : call cwtime_report(" varpeq_ncread", cpu, wall, gflops)
905 : :
906 : : !----------------------------------------------------------------------
907 : :
908 : : contains
909 : 40 : integer function vid(var_name)
910 : : character(len=*),intent(in) :: var_name
911 : 40 : vid = nctk_idname(ncid, var_name)
912 : : end function vid
913 : :
914 : : end subroutine varpeq_ncread
915 : : !!***
916 : :
917 : : !----------------------------------------------------------------------
918 : :
919 : : !!****f* m_varpeq/varpeq_ncwrite
920 : : !! NAME
921 : : !! varpeq_ncwrite
922 : : !!
923 : : !! FUNCTION
924 : : !! Dump varpeq variables in a newly created *VPQ.nc netcdf file.
925 : : !!
926 : : !! INPUTS
927 : : !! dtset<dataset_type>=All input variables for this dataset.
928 : : !! dtfil<datafiles_types>=Variables related to files.
929 : : !!
930 : : !! OUTPUT
931 : : !!
932 : : !! SOURCE
933 : :
934 : 27 : subroutine varpeq_ncwrite(self, dtset, dtfil)
935 : :
936 : : !Arguments ------------------------------------
937 : : class(varpeq_t), target, intent(inout) :: self
938 : : type(dataset_type), intent(in) :: dtset
939 : : type(datafiles_type),intent(in) :: dtfil
940 : :
941 : : !Local variables-------------------------------
942 : : character(len=fnlen) :: path
943 : : integer, parameter :: master = 0
944 : : integer :: my_rank, ncid, ncerr
945 : : real(dp) :: cpu, wall, gflops
946 : 9 : real(dp), contiguous, pointer :: rpt_d5(:,:,:,:,:)
947 : : integer :: units(2)
948 : : !----------------------------------------------------------------------
949 : :
950 [ + + ]: 27 : units = [std_out, ab_out]
951 : :
952 : 9 : call cwtime(cpu, wall, gflops, "start")
953 : :
954 : 9 : my_rank = xmpi_comm_rank(self%gstore%comm)
955 : :
956 : : ! Create netcdf file (only master works, HDF5 + MPI-IO can be handled after
957 : : ! by reopening the file inside ncwrite_comm)
958 [ + - ]: 9 : path = strcat(dtfil%filnam_ds(4), "_VPQ.nc")
959 [ + - ]: 9 : if (my_rank == master) then
960 : :
961 : 9 : call wrtout(units, sjoin(ch10, sjoin("Saving results to:", path)))
962 : :
963 : : ! Master creates the netcdf file used to store the data.
964 [ - + ]: 9 : NCF_CHECK(nctk_open_create(self%ncid, path, xmpi_comm_self))
965 : 9 : ncid = self%ncid
966 : :
967 : : ! Write the crystal (TR & invsersion symmetry only) & ebands dataset_type
968 [ - + ]: 9 : NCF_CHECK(self%cryst%ncwrite(ncid))
969 [ - + ]: 9 : NCF_CHECK(self%gstore%ebands%ncwrite(ncid))
970 : :
971 : : ! Add varpeq dimensions.
972 : : ncerr = nctk_def_dims(ncid, [ &
973 : : nctkdim_t("hop_nstep", self%hop_nstep), &
974 : : nctkdim_t("nstep", self%nstep), nctkdim_t("nsppol", self%nsppol), &
975 : : nctkdim_t("nstates", self%nstates), nctkdim_t("natom3", self%natom3), &
976 : : nctkdim_t("max_nk", self%max_nk), nctkdim_t("max_nq", self%max_nq), &
977 : : nctkdim_t("max_nb", self%max_nb), nctkdim_t("nkibz", self%gstore%nkibz), &
978 : : nctkdim_t("nqibz", self%gstore%nqibz)], &
979 [ + + ]: 99 : defmode=.true.)
980 [ - + ]: 9 : NCF_CHECK(ncerr)
981 : :
982 : : ! Define scalars
983 : : ! integers
984 : : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
985 : : "eph_task", "nkbz", "nqbz", "frohl_ntheta", "vpq_avg_g", "vpq_translate", &
986 : : "vpq_interp", "vpq_nstates", "vpq_nstep_ort", "vpq_select", "vpq_mesh_fact", &
987 [ + + ]: 117 : "vpq_hop_nstep"])
988 [ - + ]: 9 : NCF_CHECK(ncerr)
989 : : ! real
990 : : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
991 [ + + ]: 36 : "vpq_tolgrs", "e_frohl", "vpq_mix_fact"])
992 [ - + ]: 9 : NCF_CHECK(ncerr)
993 : :
994 : : ! Define arrays with results
995 : : ncerr = nctk_def_arrays(ncid, [ &
996 : : nctkarr_t("vpq_mode", "c", "character_string_length"), &
997 : : nctkarr_t("vpq_pkind", "c", "character_string_length"), &
998 : : nctkarr_t("vpq_aseed", "c", "character_string_length"), &
999 : : nctkarr_t("ngkpt", "int", "three"), &
1000 : : nctkarr_t("gstore_ngqpt", "int", "three"), &
1001 : : nctkarr_t("nk_spin", "int", "nsppol"), &
1002 : : nctkarr_t("nq_spin", "int", "nsppol"), &
1003 : : nctkarr_t("nb_spin", "int", "nsppol"), &
1004 : : nctkarr_t("brange_spin", "int", "two, nsppol"), &
1005 : : nctkarr_t("cvflag_spin", "int", "nstates, hop_nstep, nsppol"), &
1006 : : nctkarr_t("hop_nstep2cv_spin", "int", "nsppol"), &
1007 : : nctkarr_t("nstep2cv_spin", "int", "nstates, hop_nstep, nsppol"), &
1008 : : nctkarr_t("vpq_trvec", "int", "three"), &
1009 : : nctkarr_t("k2ibz_spin", "int", "max_nk, nsppol"), &
1010 : : nctkarr_t("q2ibz_spin", "int", "max_nq, nsppol"), &
1011 : : nctkarr_t("erange_spin", "dp", "nsppol"), &
1012 : : nctkarr_t("hop_hist_spin", "dp", "five, nstates, hop_nstep, nsppol"), &
1013 : : nctkarr_t("scf_hist_spin", "dp", "six, nstep, nstates, hop_nstep, nsppol"), &
1014 : : nctkarr_t("kibz", "dp", "three, nkibz"), &
1015 : : nctkarr_t("qibz", "dp", "three, nqibz"), &
1016 : : nctkarr_t("kpts_spin", "dp", "three, max_nk, nsppol"), &
1017 : : nctkarr_t("qpts_spin", "dp", "three, max_nq, nsppol"), &
1018 : : nctkarr_t("cb_min_spin", "dp", "nsppol"), &
1019 : : nctkarr_t("vb_max_spin", "dp", "nsppol"), &
1020 : : nctkarr_t("vpq_gpr_energy", "dp", "two"), &
1021 : : nctkarr_t("vpq_gpr_length", "dp", "three"), &
1022 : : nctkarr_t("a_spin", "dp", "two, max_nb, max_nk, nstates, nsppol"), &
1023 : : nctkarr_t("b_spin", "dp", "two, natom3, max_nq, nstates, nsppol") &
1024 [ + + ]: 261 : ])
1025 [ - + ]: 9 : NCF_CHECK(ncerr)
1026 : :
1027 : : ! Write data
1028 [ - + ]: 9 : NCF_CHECK(nctk_set_datamode(ncid))
1029 : : ! Scalars
1030 : : ! integer
1031 : : ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
1032 : : "eph_task", "nkbz", "nqbz", "frohl_ntheta", "vpq_avg_g", "vpq_translate", &
1033 : : "vpq_interp", "vpq_nstates", "vpq_nstep_ort", "vpq_select", "vpq_mesh_fact", &
1034 : : "vpq_hop_nstep"], &
1035 : : [dtset%eph_task, self%gstore%nkbz, self%gstore%nqbz, self%frohl_ntheta, &
1036 : : dtset%vpq_avg_g, dtset%vpq_translate, dtset%vpq_interp, dtset%vpq_nstates, &
1037 [ + + + + ]: 225 : dtset%vpq_nstep_ort, dtset%vpq_select, dtset%vpq_mesh_fact, dtset%vpq_hop_nstep])
1038 [ - + ]: 9 : NCF_CHECK(ncerr)
1039 : : ! real
1040 : : ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: &
1041 : : "vpq_tolgrs", "e_frohl", "vpq_mix_fact"], &
1042 [ + + + + ]: 63 : [self%tolgrs, self%e_frohl, dtset%vpq_mix_fact])
1043 [ - + ]: 9 : NCF_CHECK(ncerr)
1044 : :
1045 : : ! Arrays
1046 : : ! character
1047 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vpq_mode"), self%mode))
1048 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vpq_pkind"), self%pkind))
1049 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vpq_aseed"), self%aseed))
1050 : : ! integer
1051 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngkpt"), self%ngkpt))
1052 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "gstore_ngqpt"), self%gstore%ngqpt))
1053 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "nk_spin"), self%nk_spin))
1054 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "nq_spin"), self%nq_spin))
1055 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "nb_spin"), self%nb_spin))
1056 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "brange_spin"), self%brange_spin))
1057 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "cvflag_spin"), self%cvflag_spin))
1058 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "hop_nstep2cv_spin"), self%hop_nstep2cv_spin))
1059 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "nstep2cv_spin"), self%nstep2cv_spin))
1060 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vpq_trvec"), dtset%vpq_trvec))
1061 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "k2ibz_spin"), self%k2ibz_spin))
1062 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "q2ibz_spin"), self%q2ibz_spin))
1063 : : ! real
1064 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "hop_hist_spin"), self%hop_hist_spin))
1065 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "scf_hist_spin"), self%scf_hist_spin))
1066 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kibz"), self%gstore%kibz))
1067 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qibz"), self%gstore%qibz))
1068 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "kpts_spin"), self%kpts_spin))
1069 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpts_spin"), self%qpts_spin))
1070 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "cb_min_spin"), self%gaps%cb_min))
1071 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vb_max_spin"), self%gaps%vb_max))
1072 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vpq_gpr_energy"), dtset%vpq_gpr_energy))
1073 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "vpq_gpr_length"), dtset%vpq_gpr_length))
1074 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "erange_spin"), self%erange_spin))
1075 : : ! complex
1076 : : call c_f_pointer(c_loc(self%a_spin), rpt_d5, &
1077 [ + + ]: 54 : [2, self%max_nb, self%max_nk, self%nstates, self%nsppol])
1078 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "a_spin"), rpt_d5))
1079 : :
1080 : : call c_f_pointer(c_loc(self%b_spin), rpt_d5, &
1081 [ + + ]: 54 : [2, self%natom3, self%max_nq, self%nstates, self%nsppol])
1082 [ - + ]: 9 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "b_spin"), rpt_d5))
1083 : : end if ! master
1084 : :
1085 : 9 : call xmpi_barrier(self%gstore%comm)
1086 : 9 : call cwtime_report(" varpeq: ncwrite", cpu, wall, gflops)
1087 : :
1088 : 9 : end subroutine varpeq_ncwrite
1089 : : !!***
1090 : :
1091 : : !!----------------------------------------------------------------------
1092 : :
1093 : : !!****f* m_varpeq/varpeq_print_metadata
1094 : : !! NAME
1095 : : !! varpeq_print_metadata
1096 : : !!
1097 : : !! FUNCTION
1098 : : !! Output parameters defining varpeq calculation
1099 : : !!
1100 : : !! INPUTS
1101 : : !!
1102 : : !! OUTPUT
1103 : : !!
1104 : : !! SOURCE
1105 : :
1106 : : !subroutine varpeq_print_metadata(self, dtset)
1107 : 9 : subroutine varpeq_print_metadata(self)
1108 : :
1109 : : !Arguments ------------------------------------
1110 : : class(varpeq_t), target, intent(inout) :: self
1111 : : !type(dataset_type), intent(in) :: dtset
1112 : :
1113 : : !Local variables-------------------------------
1114 : : !scalars
1115 : : character(len=abi_slen) :: msg
1116 : : !character(len=abi_slen) :: use_frohl = "no"
1117 : : integer :: spin, my_rank
1118 : : integer, parameter :: master = 0
1119 : : !arrays
1120 : : integer :: units(2)
1121 : :
1122 : : !----------------------------------------------------------------------
1123 : :
1124 : 9 : my_rank = xmpi_comm_rank(self%gstore%comm)
1125 : :
1126 [ + + ]: 27 : units = [std_out, ab_out]
1127 [ + - ]: 9 : if (my_rank == master) then
1128 : :
1129 : 9 : call title_("Polaron:")
1130 : :
1131 : 9 : call entry_("Polaron kind", self%pkind)
1132 : 9 : write(msg, '(i0,a,i0,a,i0)') self%ngkpt(1), "x", self%ngkpt(2), "x", self%ngkpt(3)
1133 : 9 : call entry_("BvK supercell", msg)
1134 : 9 : call entry_("Number of independent spin polarizations", itoa(self%nsppol))
1135 : 9 : call entry_("Number of polaronic states", itoa(self%nstates))
1136 : 9 : call entry_("Filtering of electronic states", yesno(self%use_filter))
1137 [ + + ]: 9 : if (self%use_filter) then
1138 [ + + ]: 2 : do spin=1,self%nsppol
1139 : 1 : write(msg, '(a,i0,a,i0)') "Energy filter wrt band edge for spin ", &
1140 : 2 : spin, "/", self%nsppol
1141 : 2 : call entry_(msg, sjoin(ftoa(self%erange_spin(spin)*Ha_eV, "es8.2"), "eV"))
1142 : : enddo
1143 : : endif
1144 : :
1145 : 9 : call title_("Long-range corrections:")
1146 : 9 : call entry_("Frohlich correction", yesno(self%frohl_ntheta > 0))
1147 [ + - ]: 9 : if (self%frohl_ntheta > 0) then
1148 : 9 : call entry_("Frohlich correction value", sjoin(ftoa(self%e_frohl*Ha_eV), "eV"))
1149 : 9 : call entry_("Frohlich correction included in matrix elements", yesno(self%g0_flag))
1150 : : endif
1151 : :
1152 : 9 : call title_("Optimization parameters:")
1153 : :
1154 : : ! TODO change this once a support for starting from B is added
1155 : 9 : call entry_("Initial seed", "charge localization A_nk")
1156 : 9 : call entry_("Initial seed type", strseed())
1157 : :
1158 : 9 : call entry_("Tolerance on the gradient norm", ftoa(self%tolgrs, "es8.2"))
1159 : 9 : call entry_("Maximum number of iterations per state", itoa(self%nstep))
1160 [ + + ]: 9 : if (self%nstates > 1) then
1161 : 2 : call wrtout(units, " (for pstate > 1)")
1162 : 2 : call entry_("Number of orthogonaliztion steps", itoa(self%nstep_ort))
1163 : 2 : call entry_("Translational invariance", yesno(self%translate))
1164 : : endif
1165 : :
1166 : : endif
1167 : :
1168 : : contains
1169 : 27 : subroutine title_(str)
1170 : : character(len=*), intent(in) :: str
1171 : 27 : call wrtout(units, sjoin(ch10, str))
1172 : 27 : end subroutine title_
1173 : :
1174 : 113 : subroutine entry_(name, val)
1175 : : character(len=*), intent(in) :: name
1176 : : character(len=*), intent(in) :: val
1177 : : character(len=abi_slen) :: output
1178 : 113 : write(output, '(a5,a,a2,a)') "* ", trim(name), ": ", trim(val)
1179 : 113 : call wrtout(units, output)
1180 : 113 : end subroutine entry_
1181 : :
1182 : 9 : character(len=abi_slen) function strseed()
1183 : 18 : select case(self%aseed)
1184 : : case ("gau_energy")
1185 : 9 : write(strseed, *) "Gaussian, based on the electroic energies"
1186 : : case ("gau_length")
1187 : 0 : write(strseed, *) "Gaussian, based on the localizaiton length"
1188 : : case ("random")
1189 : 0 : write(strseed, *) "random"
1190 : : case ("even")
1191 : 0 : write(strseed, *) "even"
1192 : : case ("localize")
1193 : 0 : write(strseed, *) "manual loclization"
1194 : : case default
1195 [ + - - - : 9 : write(strseed, *) "undefined"
- - ]
1196 : : end select
1197 : :
1198 [ + - - + ]: 9 : if (self%interp .or. self%restart) then
1199 : 0 : write(strseed, *) "loaded from file"
1200 : : endif
1201 : :
1202 : 9 : strseed = adjustl(strseed)
1203 : 9 : end function strseed
1204 : :
1205 : : end subroutine varpeq_print_metadata
1206 : : !!***
1207 : :
1208 : : !!----------------------------------------------------------------------
1209 : :
1210 : : !!****f* m_varpeq/varpeq_print_scf_results
1211 : : !! NAME
1212 : : !! varpeq_print_scf_results
1213 : : !!
1214 : : !! FUNCTION
1215 : : !! Output SCF optimization results
1216 : : !!
1217 : : !! INPUTS
1218 : : !! ineb [optional]=Hopping iteration. Relevant only if self%vpq_mode="hopping".
1219 : : !!
1220 : : !! OUTPUT
1221 : : !!
1222 : : !! SOURCE
1223 : :
1224 : 8 : subroutine varpeq_print_scf_results(self, ihop)
1225 : :
1226 : : !Arguments ------------------------------------
1227 : : class(varpeq_t), target, intent(inout) :: self
1228 : : integer, optional, intent(in) :: ihop
1229 : :
1230 : : !Local variables-------------------------------
1231 : : !scalars
1232 : : character(len=5000) :: msg
1233 : : integer, parameter :: master = 0
1234 : : integer :: my_rank, spin, ip, ii, ihop_
1235 : : !arrays
1236 : : integer :: units(2)
1237 : : !----------------------------------------------------------------------
1238 : :
1239 : 8 : my_rank = xmpi_comm_rank(self%gstore%comm)
1240 : :
1241 : 8 : ihop_ = 1
1242 [ + - ]: 8 : if (present(ihop)) ihop_ = ihop
1243 : :
1244 [ + + ]: 24 : units = [std_out, ab_out]
1245 [ + - ]: 8 : if (my_rank == master) then
1246 [ + + ]: 16 : do spin=1,self%gstore%nsppol
1247 [ + + ]: 26 : do ip=1,self%nstates
1248 : 10 : call header_(spin, ip)
1249 : :
1250 [ + + ]: 334 : do ii=1,self%nstep2cv_spin(ip, ihop_, spin)
1251 : 326 : call report_(spin, ip, ii, ihop_, self%nstep2cv_spin(ip, ihop_, spin))
1252 : :
1253 : : enddo
1254 : : enddo
1255 : : enddo
1256 : : endif
1257 : :
1258 : : contains
1259 : 10 : subroutine header_(spin, state)
1260 : : integer, intent(in) :: spin, state
1261 : : character(len=5000) :: sep
1262 : :
1263 : 10 : call wrtout(units, "")
1264 [ + + ]: 10 : if (state == 1) then
1265 : 8 : call wrtout(units, " Printing the optimization logs")
1266 : : endif
1267 : :
1268 : 10 : write(sep, "(a3,a)") "", repeat('-', 86)
1269 : : write(msg, '(a5,a,i0,a,i0,a,i0,a,i0)') &
1270 : 10 : "* ", "spin ", spin, "/", self%nsppol, ", pstate ", state, "/", self%nstates
1271 : :
1272 : 10 : call wrtout(units, sep)
1273 : 10 : call wrtout(units, msg)
1274 : 10 : write(msg, '(a3,a)') "", "* values in the optimization log are in (a.u.)"
1275 : 10 : call wrtout(units, msg)
1276 : :
1277 [ + + + - ]: 10 : if ((state > 1) .and. (self%nstep_ort > 1)) then
1278 : 2 : write(msg, "(a3,a,i0)") "", "(o) - orthogonal all pstates < ", state
1279 : 2 : call wrtout(units, msg)
1280 : : endif
1281 : :
1282 : 10 : call wrtout(units, sep)
1283 : : !write(msg, '(a3,a4,7a13,a5)') "", "Step", "E_pol", "E_el", "E_ph", "E_elph", "E2_elph", &
1284 : : ! "epsilon", "||grad||", ""
1285 : 10 : write(msg, '(a3,a4,6a13,a5)') "", "Step", "E_pol", "E_el", "E_ph", "E_elph", &
1286 : 20 : "epsilon", "||grad||", ""
1287 : 10 : call wrtout(units, msg)
1288 : 10 : end subroutine header_
1289 : :
1290 : 316 : subroutine report_(spin, state, step, hop_step, step2conv)
1291 : : integer, intent(in) :: spin, state, step, hop_step, step2conv
1292 : : character(len=5000) :: sep
1293 : : character(len=abi_slen) :: ort_flag
1294 : : logical :: is_conv
1295 : : real(dp) :: enpol, enel, enph, enelph, eps, grs
1296 : :
1297 : 316 : enpol = self%scf_hist_spin(1, step, state, hop_step, spin)
1298 : 316 : enel = self%scf_hist_spin(2, step, state, hop_step, spin)
1299 : 316 : enph = self%scf_hist_spin(3, step, state, hop_step, spin)
1300 : 316 : enelph = self%scf_hist_spin(4, step, state, hop_step, spin)
1301 : 316 : eps = self%scf_hist_spin(5, step, state, hop_step, spin)
1302 : 316 : grs = self%scf_hist_spin(6, step, state, hop_step, spin)
1303 : :
1304 : 316 : write(sep, "(a3,a)") "", repeat('-', 86)
1305 : :
1306 : : ! for states > 1 add flag if orthogonalization is used
1307 : 316 : write(ort_flag, '(a)') ""
1308 [ + + + + ]: 316 : if ((ip > 1) .and. (step <= self%nstep_ort)) then
1309 : 60 : write(ort_flag, '(a)') "(o)"
1310 : : endif
1311 : :
1312 : : write(msg,'(a3,i4,6es13.4,a5)') &
1313 : 316 : "", step, enpol, enel, enph, enelph, eps, grs, trim(ort_flag)
1314 : 316 : call wrtout(units, msg)
1315 : :
1316 [ + + ]: 316 : if (step == step2conv) then
1317 : :
1318 : 10 : is_conv = (self%cvflag_spin(state, hop_step, spin) == 1)
1319 [ + + ]: 10 : if (is_conv) then
1320 : 9 : write(msg, '(a3,a,es11.4,a,es11.4)') "", "Converged: ||grad||=", grs, &
1321 : 18 : " < vpq_tolgrs=", self%tolgrs
1322 : : else
1323 : 1 : write(msg, '(a3,a,es11.4,a,es11.4)') "", "Unconverged: ||grad||=", grs, &
1324 : 2 : " > vpq_tolgrs=", self%tolgrs
1325 : : endif
1326 : :
1327 : 10 : call wrtout(units, sep)
1328 : 10 : call wrtout(units, msg)
1329 : :
1330 : 10 : write(msg, '(a3,a,es17.8)') "", "E_pol (eV):", enpol*Ha_eV
1331 : 10 : call wrtout(units, msg)
1332 : 10 : write(msg, '(a3,a,es17.8)') "", " eps (eV):", eps*Ha_eV
1333 : 10 : call wrtout(units, msg)
1334 : :
1335 : 10 : call wrtout(units, sep)
1336 : :
1337 : : endif
1338 : 316 : end subroutine report_
1339 : :
1340 : : end subroutine varpeq_print_scf_results
1341 : : !!***
1342 : :
1343 : : !!----------------------------------------------------------------------
1344 : :
1345 : : !!****f* m_varpeq/varpeq_print_hop_results
1346 : : !! NAME
1347 : : !! varpeq_print_hop_results
1348 : : !!
1349 : : !! FUNCTION
1350 : : !! Output hopping optimization results
1351 : : !!
1352 : : !! INPUTS
1353 : : !!
1354 : : !! OUTPUT
1355 : : !!
1356 : : !! SOURCE
1357 : :
1358 : 1 : subroutine varpeq_print_hop_results(self)
1359 : :
1360 : : !Arguments ------------------------------------
1361 : : class(varpeq_t), target, intent(inout) :: self
1362 : :
1363 : : !Local variables-------------------------------
1364 : : !scalars
1365 : : character(len=5000) :: msg
1366 : : integer, parameter :: master = 0
1367 : : integer :: my_rank, spin, ip, ihop
1368 : : integer :: hop_nstep2cv, scf_nstep2cv
1369 : : !arrays
1370 : : integer :: units(2)
1371 : :
1372 : : !----------------------------------------------------------------------
1373 : :
1374 : 1 : my_rank = xmpi_comm_rank(self%gstore%comm)
1375 : :
1376 : :
1377 [ + + ]: 3 : units = [std_out, ab_out]
1378 : :
1379 [ + - ]: 1 : if (my_rank == master) then
1380 [ + + ]: 2 : do spin=1,self%gstore%nsppol
1381 : 1 : hop_nstep2cv = self%hop_nstep2cv_spin(spin)
1382 : :
1383 : 1 : call hop_header_(spin)
1384 [ + + ]: 16 : do ihop=1,self%hop_nstep2cv_spin(spin)
1385 : 16 : call hop_report_(spin, ihop)
1386 : : enddo
1387 : :
1388 : 1 : call header_(spin)
1389 [ + + ]: 11 : do ip=1,self%nstates
1390 : 9 : scf_nstep2cv = self%nstep2cv_spin(ip, hop_nstep2cv, spin)
1391 : 10 : call report_(spin, ip, scf_nstep2cv, hop_nstep2cv)
1392 : : enddo
1393 : :
1394 : : enddo
1395 : : endif
1396 : :
1397 : : contains
1398 : 1 : subroutine header_(spin)
1399 : : integer, intent(in) :: spin
1400 : : character(len=5000) :: sep
1401 : :
1402 : 1 : call wrtout(units, "")
1403 : 1 : call wrtout(units, " Printing the minimal energy path")
1404 : :
1405 : 1 : write(sep, "(a3,a)") "", repeat('-', 86)
1406 : : write(msg, '(a5,a,i0,a,i0)') &
1407 : 1 : "* ", "spin ", spin, "/", self%nsppol
1408 : :
1409 : 1 : call wrtout(units, sep)
1410 : 1 : call wrtout(units, msg)
1411 : 1 : write(msg, '(a3,a)') "", "* values are in (a.u.)"
1412 : 1 : call wrtout(units, msg)
1413 : :
1414 : 1 : call wrtout(units, sep)
1415 : 1 : write(msg, '(a3,a4,6a13)') "", "Image", "E_pol", "E_el", "E_ph", "E_elph", &
1416 : 2 : "epsilon", "||el_grad||"
1417 : 1 : call wrtout(units, msg)
1418 : 1 : end subroutine header_
1419 : :
1420 : 1 : subroutine hop_header_(spin)
1421 : : integer, intent(in) :: spin
1422 : : character(len=5000) :: sep
1423 : :
1424 : 1 : call wrtout(units, "")
1425 : 1 : call wrtout(units, " Printing the hopping optimization log")
1426 : :
1427 : 1 : write(sep, "(a3,a)") "", repeat('-', 43)
1428 : : write(msg, '(a5,a,i0,a,i0)') &
1429 : 1 : "* ", "spin ", spin, "/", self%nsppol
1430 : :
1431 : 1 : call wrtout(units, sep)
1432 : 1 : call wrtout(units, msg)
1433 : 1 : write(msg, '(a3,a)') "", "* values are in (a.u.)"
1434 : 1 : call wrtout(units, msg)
1435 : :
1436 : 1 : call wrtout(units, sep)
1437 : 1 : write(msg, '(a3,a4,a17,a18)') "", "Step", &
1438 : 2 : "max||ph_grad||", "max||hop_grad||"
1439 : 1 : call wrtout(units, msg)
1440 : 1 : end subroutine hop_header_
1441 : :
1442 : 9 : subroutine report_(spin, state, step, hop_step)
1443 : : integer, intent(in) :: spin, state, step, hop_step
1444 : : character(len=5000) :: sep
1445 : : real(dp) :: enpol, enel, enph, enelph, eps, grs
1446 : : !real(dp) :: min_epol, max_epol, ehop
1447 : :
1448 : 9 : enpol = self%scf_hist_spin(1, step, state, hop_step, spin)
1449 : 9 : enel = self%scf_hist_spin(2, step, state, hop_step, spin)
1450 : 9 : enph = self%scf_hist_spin(3, step, state, hop_step, spin)
1451 : 9 : enelph = self%scf_hist_spin(4, step, state, hop_step, spin)
1452 : 9 : eps = self%scf_hist_spin(5, step, state, hop_step, spin)
1453 : 9 : grs = self%scf_hist_spin(6, step, state, hop_step, spin)
1454 : :
1455 : 9 : write(sep, "(a3,a)") "", repeat('-', 86)
1456 : :
1457 : : write(msg,'(a3,i4,6es13.4)') &
1458 : 9 : "", state, enpol, enel, enph, enelph, eps, grs
1459 : 9 : call wrtout(units, msg)
1460 : :
1461 [ + + ]: 9 : if (state == self%nstates) then
1462 : 1 : call wrtout(units, sep)
1463 : : endif
1464 : :
1465 : 9 : end subroutine report_
1466 : :
1467 : 15 : subroutine hop_report_(spin, hop_step)
1468 : : integer, intent(in) :: spin, hop_step
1469 : : character(len=5000) :: sep
1470 : : real(dp) :: ph_max_grs, hop_max_grs
1471 : :
1472 [ + - - + : 165 : ph_max_grs = maxval(self%hop_hist_spin(1, :, hop_step, spin))
- - + + ]
1473 [ + - - + : 165 : hop_max_grs = maxval(self%hop_hist_spin(2, :, hop_step, spin))
- - + + ]
1474 : :
1475 : 15 : write(sep, "(a3,a)") "", repeat('-', 43)
1476 : :
1477 : : write(msg,'(a3,i4,es17.4,es18.4)') &
1478 : 15 : "", hop_step, ph_max_grs, hop_max_grs
1479 : 15 : call wrtout(units, msg)
1480 : :
1481 [ + + ]: 15 : if (hop_step == self%hop_nstep2cv_spin(spin)) then
1482 : 1 : call wrtout(units, sep)
1483 : : endif
1484 : :
1485 : 15 : end subroutine hop_report_
1486 : :
1487 : : end subroutine varpeq_print_hop_results
1488 : : !!***
1489 : :
1490 : : !!----------------------------------------------------------------------
1491 : :
1492 : : !!****f* m_varpeq/varpeq_collect
1493 : : !! NAME
1494 : : !! varpeq_collect
1495 : : !!
1496 : : !! FUNCTION
1497 : : !! Collect SCF optimization results for each spin
1498 : : !!
1499 : : !! INPUTS
1500 : : !!
1501 : : !! OUTPUT
1502 : : !!
1503 : : !! SOURCE
1504 : :
1505 : 198 : subroutine varpeq_collect(self)
1506 : :
1507 : : !Arguments ------------------------------------
1508 : : class(varpeq_t), target, intent(inout) :: self
1509 : :
1510 : : !Local variables-------------------------------
1511 : : class(gqk_t), pointer :: gqk
1512 : : class(polstate_t), pointer :: polstate
1513 : : integer :: ierr
1514 : : integer :: my_is, spin, my_ik, ik_glob, ik_ibz, ip
1515 : : integer :: my_iq, iq_glob, iq_ibz, my_pert, pert_glob
1516 : : integer :: oc_scf, oc_a, oc_b, oc_k, oc_q
1517 : : !----------------------------------------------------------------------
1518 : :
1519 : : ! Gather the SCF process evolution data
1520 : 18 : call xmpi_sum(self%cvflag_spin, self%gstore%comm, ierr)
1521 : 18 : call xmpi_sum(self%scf_hist_spin, self%gstore%comm, ierr)
1522 : 18 : call xmpi_sum(self%nstep2cv_spin, self%gstore%comm, ierr)
1523 : :
1524 : 18 : call xmpi_sum(self%hop_hist_spin, self%gstore%comm, ierr)
1525 : 18 : call xmpi_sum(self%hop_nstep2cv_spin, self%gstore%comm, ierr)
1526 : :
1527 : : ! Gather electron/phonon vectors and k/q points
1528 [ + + + + : 13534 : self%a_spin(:,:,:,:) = zero
+ + + + ]
1529 [ + + + + : 31364 : self%b_spin(:,:,:,:) = zero
+ + + + ]
1530 [ + + + + ]: 1382 : self%k2ibz_spin(:,:) = zero
1531 [ + + + + ]: 2398 : self%q2ibz_spin(:,:) = zero
1532 [ + + + + : 9484 : self%qpts_spin(:,:,:) = zero
+ + ]
1533 [ + + + + : 5420 : self%kpts_spin(:,:,:) = zero
+ + ]
1534 [ + + ]: 36 : do my_is=1,self%gstore%my_nspins
1535 : 18 : spin = self%gstore%my_spins(my_is)
1536 : 18 : gqk => self%gstore%gqk(my_is)
1537 : 18 : polstate => self%polstate(spin)
1538 : :
1539 [ + + ]: 56 : do ip=1,self%nstates
1540 : :
1541 : : ! electronic vector
1542 [ + + ]: 3492 : do my_ik=1,gqk%my_nk
1543 : 3454 : ik_glob = gqk%my_kstart + my_ik - 1
1544 [ + + ]: 13498 : self%a_spin(:, ik_glob, ip, spin) = polstate%my_a(:, my_ik, ip)
1545 : : enddo
1546 : :
1547 : : ! phonon vector
1548 [ + + ]: 4526 : do my_iq=1,gqk%my_nq
1549 : 4470 : iq_glob = gqk%my_qstart + my_iq - 1
1550 [ + + ]: 31328 : do my_pert=1,gqk%my_npert
1551 : 26820 : pert_glob = gqk%my_pert_start + my_pert - 1
1552 [ + + ]: 168054 : self%b_spin(pert_glob, iq_glob, :, spin) = polstate%my_b(my_pert, my_iq, :)
1553 : : enddo
1554 : : enddo
1555 : :
1556 : : enddo
1557 : :
1558 : : ! k-points
1559 [ + + ]: 1364 : do my_ik=1,gqk%my_nk
1560 : 1346 : ik_ibz = gqk%my_k2ibz(1, my_ik)
1561 : 1346 : ik_glob = gqk%my_kstart + my_ik - 1
1562 [ + + ]: 5384 : self%kpts_spin(:, ik_glob, spin) = polstate%my_kpts(:, my_ik)
1563 : 1364 : self%k2ibz_spin(ik_glob, spin) = ik_ibz
1564 : : enddo
1565 : :
1566 : : ! q-points
1567 [ + + ]: 2398 : do my_iq=1,gqk%my_nq
1568 : 2362 : iq_ibz = gqk%my_q2ibz(1, my_iq)
1569 : 2362 : iq_glob = gqk%my_qstart + my_iq - 1
1570 [ + + ]: 9448 : self%qpts_spin(:, iq_glob, spin) = polstate%my_qpts(:, my_iq)
1571 : 2380 : self%q2ibz_spin(iq_glob, spin) = iq_ibz
1572 : : enddo
1573 : :
1574 : : enddo
1575 : :
1576 : 18 : call xmpi_sum(self%a_spin, self%gstore%comm, ierr)
1577 : 18 : call xmpi_sum(self%b_spin, self%gstore%comm, ierr)
1578 : 18 : call xmpi_sum(self%k2ibz_spin, self%gstore%comm, ierr)
1579 : 18 : call xmpi_sum(self%q2ibz_spin, self%gstore%comm, ierr)
1580 : 18 : call xmpi_sum(self%kpts_spin, self%gstore%comm, ierr)
1581 : 18 : call xmpi_sum(self%qpts_spin, self%gstore%comm, ierr)
1582 : :
1583 : : ! Hack to mimic the summation over a non-existing spin communicator
1584 : : ! Divide by the number of times we overcount, as we use the global communicator
1585 [ + + ]: 36 : do my_is=1,self%gstore%my_nspins
1586 : 18 : spin = self%gstore%my_spins(my_is)
1587 : 18 : gqk => self%gstore%gqk(my_is)
1588 : 18 : polstate => self%polstate(spin)
1589 : :
1590 : 18 : oc_scf = gqk%comm%nproc
1591 : 18 : oc_a = gqk%qpt_pert_comm%nproc
1592 : 18 : oc_b = gqk%kpt_comm%nproc
1593 : 18 : oc_k = oc_a
1594 : 18 : oc_q = oc_b * gqk%pert_comm%nproc
1595 : :
1596 [ + + + + ]: 354 : self%cvflag_spin(:,:,spin) = self%cvflag_spin(:,:,spin) / oc_scf
1597 [ + + + + : 197264 : self%scf_hist_spin(:,:,:,:,spin) = self%scf_hist_spin(:,:,:,:,spin) / oc_scf
+ + + + ]
1598 [ + + + + ]: 354 : self%nstep2cv_spin(:,:,spin) = self%nstep2cv_spin(:,:,spin) / oc_scf
1599 [ + + + + : 1804 : self%hop_hist_spin(:,:,:,spin) = self%hop_hist_spin(:,:,:,spin) / oc_scf
+ + ]
1600 : 18 : self%hop_nstep2cv_spin(spin) = self%hop_nstep2cv_spin(spin) / oc_scf
1601 : :
1602 [ + + + + : 13516 : self%a_spin(:,:,:,spin) = self%a_spin(:,:,:,spin) / oc_a
+ + ]
1603 [ + + + + : 31346 : self%b_spin(:,:,:,spin) = self%b_spin(:,:,:,spin) / oc_b
+ + ]
1604 [ + + ]: 1364 : self%k2ibz_spin(:,spin) = self%k2ibz_spin(:,spin) / oc_k
1605 [ + + ]: 2380 : self%q2ibz_spin(:,spin) = self%q2ibz_spin(:,spin) / oc_q
1606 [ + + + + ]: 5402 : self%kpts_spin(:,:,spin) = self%kpts_spin(:,:,spin) / oc_k
1607 [ + + + + ]: 9484 : self%qpts_spin(:,:,spin) = self%qpts_spin(:,:,spin) / oc_q
1608 : : enddo
1609 : :
1610 : 18 : end subroutine varpeq_collect
1611 : : !!***
1612 : :
1613 : : !----------------------------------------------------------------------
1614 : :
1615 : : !!****f* m_varpeq/varpeq_load
1616 : : !! NAME
1617 : : !! varpeq_load
1618 : : !!
1619 : : !! FUNCTION
1620 : : !! Load and (optionally) interpolate the initial electronic vector A_nk from
1621 : : !! a *VPQ.nc netcdf file. Store result in the self%a_spin variable.
1622 : : !!
1623 : : !! INPUTS
1624 : : !! dtfil<datafiles_types>=Variables related to files.
1625 : : !! pselect=Which state to select for reload/interpolation. Non-positive value
1626 : : !! selects all states.
1627 : : !!
1628 : : !! OUTPUT
1629 : : !!
1630 : : !! SOURCE
1631 : :
1632 : 0 : subroutine varpeq_load(self, dtfil, pselect)
1633 : :
1634 : : !Arguments ------------------------------------
1635 : : class(varpeq_t), target, intent(inout) :: self
1636 : : type(datafiles_type), intent(in) :: dtfil
1637 : : integer,intent(in) :: pselect
1638 : :
1639 : : !Local variables-------------------------------
1640 : : !scalars
1641 [ # # # # : 0 : type(varpeq_t) :: vpq_ld
# # # # #
# # # # #
# # # # ]
1642 : 0 : type(bzlint_t) :: bzlint
1643 : : logical :: single_state
1644 : : integer, parameter :: master = 0
1645 : : integer :: my_rank, comm, ierr
1646 : : integer :: spin, ip, nk, nb, ik, ib
1647 : : real(dp) :: cpu, wall, gflops
1648 : : !arrays
1649 : : integer :: units(2)
1650 : : real(dp) :: kpt(3)
1651 : 0 : real(dp), allocatable :: ak(:), kpts_ld(:,:)
1652 : 0 : real(dp), contiguous, pointer :: rpt_d2(:,:)
1653 : 0 : complex(dp), allocatable, target :: a_ld(:,:)
1654 : : !----------------------------------------------------------------------
1655 : :
1656 : 0 : call cwtime(cpu, wall, gflops, "start")
1657 : :
1658 [ # # ]: 0 : units = [std_out, ab_out]
1659 : 0 : comm = self%gstore%comm; my_rank = xmpi_comm_rank(comm)
1660 : :
1661 : : ! Read A_nk from file. Only the master processor reads, then broadcasts the data
1662 [ # # ]: 0 : if (my_rank == master) then
1663 : 0 : call vpq_ld%ncread(dtfil%filvpqin, xmpi_comm_self, keep_open=.false.)
1664 : :
1665 : : ! Consitency check
1666 : 0 : call self%compare(vpq_ld, bz_mismatch=self%interp)
1667 [ # # ]: 0 : if (pselect > 0) then
1668 [ # # ]: 0 : ABI_CHECK(self%nstates == 1, "vpq_pstates must be 1 if vpq_select > 0.")
1669 [ # # ]: 0 : ABI_CHECK(pselect <= vpq_ld%nstates, "vpq_select must be <= loaded nstates.")
1670 : : single_state = .true.
1671 : : else
1672 [ # # ]: 0 : ABI_CHECK(self%nstates == vpq_ld%nstates, "Diefference found in nstates.")
1673 : : single_state = .false.
1674 : : endif
1675 : :
1676 [ # # # # : 0 : self%a_spin(:,:,:,:) = zero
# # # # ]
1677 : :
1678 [ # # ]: 0 : if (self%interp) then ! Interpolation
1679 : 0 : call wrtout(units, " - interpolating previous A_nk")
1680 [ # # ]: 0 : do spin=1,self%nsppol
1681 : : ! Setting basic dimensions & arrays
1682 : 0 : nk = vpq_ld%nk_spin(spin); nb = vpq_ld%nb_spin(spin)
1683 [ # # # # : 0 : ABI_MALLOC(kpts_ld, (3, nk))
# # # # #
# # # ]
1684 [ # # # # : 0 : ABI_MALLOC(a_ld, (nb, nk))
# # # # #
# # # # #
# # ]
1685 [ # # # # : 0 : ABI_MALLOC(ak, (2*nb))
# # # # #
# # # #
# ]
1686 [ # # # # ]: 0 : kpts_ld(:,:) = vpq_ld%kpts_spin(:, 1:nk, spin)
1687 : :
1688 : : ! Here, interpolation is performed
1689 [ # # ]: 0 : do ip=1,self%nstates
1690 : :
1691 [ # # ]: 0 : if (single_state) then
1692 [ # # # # ]: 0 : a_ld(:,:) = vpq_ld%a_spin(:, 1:nk, pselect, spin)
1693 : : else
1694 [ # # # # ]: 0 : a_ld(:,:) = vpq_ld%a_spin(:, 1:nk, ip, spin)
1695 : : endif
1696 : :
1697 : 0 : call c_f_pointer(c_loc(a_ld), rpt_d2, [2*nb, nk])
1698 : :
1699 : 0 : call bzlint%init(vpq_ld%ngkpt, 2*nb, nk, kpts_ld, rpt_d2)
1700 : :
1701 [ # # ]: 0 : do ik=1,self%nk_spin(spin)
1702 [ # # ]: 0 : kpt(:) = self%kpts_spin(:, ik, spin)
1703 : 0 : call bzlint%interp(kpt, ak)
1704 : :
1705 [ # # ]: 0 : do ib=1,nb
1706 : 0 : self%a_spin(ib, ik, ip, spin) = ak(2*ib-1) + j_dpc*ak(2*ib)
1707 : : enddo
1708 : : enddo
1709 : 0 : call bzlint%free()
1710 : :
1711 : : enddo
1712 [ # # ]: 0 : ABI_FREE(kpts_ld)
1713 [ # # ]: 0 : ABI_FREE(a_ld)
1714 [ # # ]: 0 : ABI_FREE(ak)
1715 : : enddo
1716 : :
1717 : : else ! Restart
1718 : 0 : call wrtout(units, " - restarting from previous A_nk")
1719 [ # # ]: 0 : if (single_state) then
1720 [ # # # # : 0 : self%a_spin(:,:,:,:) = vpq_ld%a_spin(:,:,pselect:pselect,:)
# # # # ]
1721 : : else
1722 [ # # # # : 0 : self%a_spin(:,:,:,:) = vpq_ld%a_spin(:,:,:,:)
# # # # ]
1723 : : endif
1724 : : endif
1725 : :
1726 : 0 : call vpq_ld%free()
1727 : : endif
1728 : :
1729 : 0 : call xmpi_bcast(self%a_spin, master, comm, ierr)
1730 : 0 : self%ld_flag = .true.
1731 : :
1732 : 0 : call cwtime_report(" varpeq: load", cpu, wall, gflops)
1733 : :
1734 [ # # # # : 0 : end subroutine varpeq_load
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1735 : : !!***
1736 : :
1737 : : !----------------------------------------------------------------------
1738 : :
1739 : : !!****f* m_varpeq/varpeq_hop
1740 : : !! NAME
1741 : : !! varpeq_hop
1742 : : !!
1743 : : !! FUNCTION
1744 : : !! Solve the Variational Polaron Equations for polaronic hopping between
1745 : : !! initial and final state.
1746 : : !! self%nstates act as number of polarnoc images, including the initial
1747 : : !! and final one.
1748 : : !! Optimization is performed via string method:
1749 : : !! [Weinan, J. Chem. Phys. 126, 164103 (2007)]
1750 : : !!
1751 : : !! INPUTS
1752 : : !!
1753 : : !! OUTPUT
1754 : : !!
1755 : : !! SOURCE
1756 : :
1757 : 1 : subroutine varpeq_hop(self)
1758 : :
1759 : : !Arguments ------------------------------------
1760 : : class(varpeq_t), target, intent(inout) :: self
1761 : :
1762 : : !Local variables-------------------------------
1763 : : !scalars
1764 : : class(polstate_t), pointer :: polstate
1765 : : character(len=5000) :: msg
1766 : : integer :: ierr
1767 : : integer :: my_is, spin, ip, ihop
1768 : : real(dp) :: cpu, wall, gflops
1769 : : real(dp) :: ts, dist2
1770 : : real(dp) :: phforce_grs, phforce_hop_grs
1771 : : !arrays
1772 : 2 : logical :: is_conv_spin(self%nsppol)
1773 : : integer :: units(2)
1774 : 2 : real(dp) :: b_mesh(self%nstates)
1775 : 2 : real(dp) :: even_mesh(self%nstates)
1776 : :
1777 : : !----------------------------------------------------------------------
1778 : :
1779 [ + + ]: 3 : units = [std_out, ab_out]
1780 : :
1781 : : call wrtout(units, &
1782 : 1 : sjoin(ch10, "Solving for the polaron hopping..."))
1783 : :
1784 : 1 : call cwtime(cpu, wall, gflops, "start")
1785 : :
1786 [ + + ]: 10 : do ip=1,self%nstates
1787 : 10 : even_mesh(ip) = (ip - one) / (self%nstates - one)
1788 : : enddo
1789 : :
1790 [ + + ]: 2 : is_conv_spin(:) = .false.
1791 [ + + ]: 16 : do ihop=1,self%hop_nstep
1792 : 15 : write(msg, '(a5,a,i0,a,i0)') "* ", "Hopping: step ", ihop, "/", self%hop_nstep
1793 : 15 : call wrtout(units, msg)
1794 : :
1795 : : ! Solve the variational polaron equations
1796 : 15 : call self%solve(verbose=.false., ihop=ihop)
1797 : :
1798 [ + + ]: 30 : do my_is=1,self%gstore%my_nspins
1799 : 15 : spin = self%gstore%my_spins(my_is)
1800 : 15 : polstate => self%polstate(my_is)
1801 : :
1802 [ + + + + : 7899 : if (ihop == 1) polstate%my_prev_b_hop(:,:,:) = zero
+ + + + ]
1803 : 15 : self%hop_nstep2cv_spin(spin) = ihop
1804 : :
1805 : : ! Calculate the forces
1806 [ + + ]: 150 : do ip=1,self%nstates
1807 : 135 : call polstate%calc_eff_phforce("fw_euler", ip)
1808 : :
1809 : : ! Record the bare phonon force norm
1810 : 135 : phforce_grs = sqrt(polstate%get_sqnorm("phgrad", ip))
1811 : 150 : self%hop_hist_spin(1, ip, ihop, spin) = phforce_grs
1812 : :
1813 : : enddo
1814 : :
1815 : : ! Calculate optimal timestep
1816 [ + + ]: 15 : if (ihop == 1) then
1817 [ + + ]: 8 : do ip=2,self%nstates-1
1818 : 8 : call polstate%calc_hop_timestep(ip)
1819 : : enddo
1820 [ + - - + : 9 : ts = minval(abs(polstate%hop_ts(2:self%nstates-1)))
- - + + ]
1821 : :
1822 [ + - ]: 1 : if (self%hop_ts > zero) ts = self%hop_ts
1823 : :
1824 : 1 : write(msg, '(a5,a,es8.2)') "", "line minimiation step t = ", ts
1825 : 1 : call wrtout(units, msg)
1826 : : endif
1827 : :
1828 : : ! Evolve B_\qnu coefficients
1829 : : polstate%my_b(:,:,:) = &
1830 [ + + + + : 118275 : polstate%my_b(:,:,:) + ts * polstate%my_eff_phforce(:,:,:)
+ + ]
1831 : :
1832 : : ! Reparametrize the string:
1833 : : ! Get current parametrization
1834 : 15 : b_mesh(1) = zero
1835 [ + + ]: 135 : do ip=2,self%nstates
1836 [ + + + + ]: 105120 : dist2 = sum(abs(polstate%my_b(:,:,ip) - polstate%my_b(:,:,ip-1))**2)
1837 : 120 : call xmpi_sum(dist2, polstate%gqk%qpt_pert_comm%value, ierr)
1838 : 135 : b_mesh(ip) = b_mesh(ip-1) + sqrt(dist2)
1839 : : enddo
1840 [ + + ]: 150 : b_mesh(:) = b_mesh(:) / b_mesh(self%nstates)
1841 : :
1842 : : ! Redistribute B_q\nu
1843 : 15 : call polstate%redistr_b(b_mesh, even_mesh, self%nstates)
1844 : :
1845 : : ! Record phonon force norm, computed from optimization
1846 : : ! F_q\nu = 1/ts * |B_q\nu^(n) - B_q\nu^(n-1)|
1847 [ + + ]: 150 : do ip=1,self%nstates
1848 : : phforce_hop_grs = &
1849 [ + + + + ]: 118260 : sum(abs(polstate%my_b(:,:,ip) - polstate%my_prev_b_hop(:,:,ip))**2)
1850 : 135 : call xmpi_sum(phforce_hop_grs, polstate%gqk%qpt_pert_comm%value, ierr)
1851 : :
1852 : 150 : self%hop_hist_spin(2, ip, ihop, spin) = sqrt(phforce_hop_grs) / ts
1853 : : enddo
1854 : :
1855 [ + - - + : 165 : if (maxval(self%hop_hist_spin(2, :, ihop, spin)) < self%hop_tolgrs) then
- - + + -
+ ]
1856 : 0 : is_conv_spin(spin) = .true.
1857 : : endif
1858 : :
1859 [ + + + + : 118290 : polstate%my_prev_b_hop(:,:,:) = polstate%my_b(:,:,:)
+ + ]
1860 : : enddo
1861 : :
1862 [ + - - + : 15 : if (all(is_conv_spin) .or. (ihop == self%hop_nstep)) then
+ - + + ]
1863 [ + + ]: 10 : do ip=1,self%nstates
1864 : : ! Compute the overlaps
1865 : : ! <A_in|B_i|A_in>
1866 : : self%hop_hist_spin(3, ip, ihop, spin) = &
1867 : : polstate%calc_hpol(polstate%my_a(:,:,1), polstate%a_glob(:,:,1), &
1868 : 9 : polstate%my_a(:,:,1), polstate%my_b(:,:,ip))
1869 : : ! <A_end|B_i|A_end>
1870 : : self%hop_hist_spin(4, ip, ihop, spin) = &
1871 : : polstate%calc_hpol(polstate%my_a(:,:,self%nstates), polstate%a_glob(:,:,self%nstates), &
1872 : 9 : polstate%my_a(:,:,self%nstates), polstate%my_b(:,:,ip))
1873 : : ! <A_in|B_i|A_end>
1874 : : self%hop_hist_spin(5, ip, ihop, spin) = &
1875 : : polstate%calc_hpol(polstate%my_a(:,:,1), polstate%a_glob(:,:,1), &
1876 : 24 : polstate%my_a(:,:,self%nstates), polstate%my_b(:,:,ip))
1877 : : enddo
1878 : : endif
1879 : :
1880 [ + - - + : 16 : if (all(is_conv_spin)) exit
+ - ]
1881 : :
1882 : : enddo
1883 : :
1884 : 1 : call cwtime_report(" varpeq: hop", cpu, wall, gflops)
1885 : :
1886 : 1 : end subroutine varpeq_hop
1887 : : !!***
1888 : :
1889 : : !----------------------------------------------------------------------
1890 : :
1891 : : !!****f* m_varpeq/varpeq_solve
1892 : : !! NAME
1893 : : !! varpeq_solve
1894 : : !!
1895 : : !! FUNCTION
1896 : : !! Solve the Variational Polaron Equations for each spin for self%nstates
1897 : : !! polaronic states.
1898 : : !!
1899 : : !! INPUTS
1900 : : !! ineb [optional]=Hopping iteration. Relevant only if self%vpq_mode="hopping".
1901 : : !!
1902 : : !! OUTPUT
1903 : : !!
1904 : : !! SOURCE
1905 : :
1906 : 69 : subroutine varpeq_solve(self, verbose, ihop)
1907 : :
1908 : : !Arguments ------------------------------------
1909 : : class(varpeq_t), target, intent(inout) :: self
1910 : : logical, intent(in) :: verbose
1911 : : integer, optional, intent(in) :: ihop
1912 : :
1913 : : !Local variables-------------------------------
1914 : : class(polstate_t), pointer :: polstate
1915 : : character(len=5000) :: msg
1916 : : integer :: my_is, spin, ip, ii, ihop_
1917 : : real(dp) :: grad_sqnorm
1918 : : real(dp) :: cpu, wall, gflops
1919 : : integer :: units(2)
1920 : : !----------------------------------------------------------------------
1921 : :
1922 [ + + ]: 69 : units = [std_out, ab_out]
1923 : :
1924 : 23 : ihop_ = 1
1925 [ + + ]: 23 : if (present(ihop)) ihop_ = ihop
1926 : :
1927 [ + + ]: 23 : if (verbose) then
1928 : : call wrtout(units, &
1929 : 8 : sjoin(ch10, "Solving the variational polaron equations for each state..."))
1930 : : endif
1931 : :
1932 : 23 : call cwtime(cpu, wall, gflops, "start")
1933 : :
1934 [ + + ]: 46 : do my_is=1,self%gstore%my_nspins
1935 : 23 : spin = self%gstore%my_spins(my_is)
1936 : 23 : polstate => self%polstate(my_is)
1937 : :
1938 [ + + ]: 191 : do ip=1,self%nstates
1939 : :
1940 [ + + ]: 145 : if (verbose) then
1941 : 10 : write(msg, '(a5,a,i0,a,i0,a,i0,a,i0,a)') "* ", "spin ", spin, "/", &
1942 : 20 : self%nsppol, ", pstate ", ip, "/", self%nstates, "..."
1943 : 10 : call wrtout(units, msg)
1944 : : endif
1945 : :
1946 : : ! initialize A_nk at this state, orthogonalize to the previous ones
1947 : : ! and normalize
1948 [ + + ]: 145 : if (ihop_ == 1) then
1949 : : call polstate%setup(ip, a_src=self%a_spin(:,:,ip,spin), load=self%ld_flag, &
1950 : : atloc=self%atloc, chrgat=self%chrgat, scell=self%scell, cryst=self%cryst, &
1951 : 19 : nstep_loc=self%nstep)
1952 : : endif
1953 : :
1954 [ + + ]: 2332 : do ii=1,self%nstep
1955 : : ! gather A, get B_qnu, get energies
1956 : 2331 : call polstate%localize(ip, self%mixing_factor, fix_displ=self%fix_displ)
1957 : :
1958 : : ! get bare gradient
1959 : 2331 : call polstate%calc_grad(ip)
1960 : :
1961 : : ! calculate and save the L^2 gradient norm
1962 : 2331 : grad_sqnorm = polstate%get_sqnorm("grad", ip)
1963 : 2331 : polstate%gradres(ip) = sqrt(grad_sqnorm)
1964 : :
1965 : : ! record the energies & gradient norm to varepq datatype
1966 : 2331 : call self%record(ii, ip, ihop_, my_is)
1967 : :
1968 : : ! check if gradient norm is lower than convergence threshold
1969 [ + + ]: 2331 : if (polstate%gradres(ip) < self%tolgrs) then
1970 : 144 : self%cvflag_spin(ip, ihop_, spin) = 1
1971 : 144 : exit
1972 : : endif
1973 : :
1974 : : ! calculate the preconditioner
1975 : 2187 : call polstate%update_pc(ip)
1976 : :
1977 : : ! get preconditioned conjugate gradient direction
1978 : 2187 : call polstate%calc_pcjgrad(ip, ii, self%nstep_ort)
1979 : :
1980 : : ! update a based on line minimization and pcj direction
1981 : 2188 : call polstate%update_a(ip)
1982 : :
1983 : : enddo
1984 : :
1985 [ + + ]: 168 : if (verbose) then
1986 : 10 : call wrtout(units, " Done")
1987 : : endif
1988 : :
1989 : : enddo
1990 : : enddo
1991 : :
1992 : 23 : call cwtime_report(" varpeq: solve", cpu, wall, gflops)
1993 : :
1994 : 23 : end subroutine varpeq_solve
1995 : : !!***
1996 : :
1997 : : !----------------------------------------------------------------------
1998 : :
1999 : : !!****f* m_varpeq/varpeq_record
2000 : : !! NAME
2001 : : !! varpeq_record
2002 : : !!
2003 : : !! FUNCTION
2004 : : !! Record variational polaron equations results for current iteration.
2005 : : !! Used to propagate the SCF cycle history from self%polstate to the
2006 : : !! varpeq datatype itself.
2007 : : !!
2008 : : !! INPUTS
2009 : : !! iter=Current iteration.
2010 : : !! ihop=Current iteration (hopping).
2011 : : !! ip=Index of a polaronic state.
2012 : : !! my_is=Spin polarization treated by this MPI proc.
2013 : : !!
2014 : : !! OUTPUT
2015 : : !!
2016 : : !! SOURCE
2017 : :
2018 : 2331 : subroutine varpeq_record(self, iter, ip, ihop, my_is)
2019 : :
2020 : : !Arguments ------------------------------------
2021 : : class(varpeq_t), target, intent(inout) :: self
2022 : : integer, intent(in) :: iter, ip, ihop, my_is
2023 : :
2024 : : !Local variables-------------------------------
2025 : : class(polstate_t), pointer :: polstate
2026 : : integer :: spin, psign
2027 : : real(dp) :: enel, enph, enelph, eps
2028 : : !----------------------------------------------------------------------
2029 : :
2030 : 2331 : spin = self%gstore%my_spins(my_is)
2031 : 2331 : polstate => self%polstate(my_is)
2032 : :
2033 : 2331 : psign = 1
2034 [ + + ]: 2331 : if (self%pkind == "hole") psign = -1
2035 : :
2036 : 2331 : enel = polstate%enterms(1, ip); enph = polstate%enterms(2, ip)
2037 : 2331 : enelph = polstate%enterms(3, ip); eps = polstate%enterms(4, ip)
2038 : :
2039 : 2331 : self%scf_hist_spin(1, iter, ip, ihop, spin) = (enel + enph + enelph)
2040 : 2331 : self%scf_hist_spin(2, iter, ip, ihop, spin) = enel
2041 : 2331 : self%scf_hist_spin(3, iter, ip, ihop, spin) = enph
2042 : 2331 : self%scf_hist_spin(4, iter, ip, ihop, spin) = enelph
2043 : 2331 : self%scf_hist_spin(5, iter, ip, ihop, spin) = psign*eps
2044 : 2331 : self%scf_hist_spin(6, iter, ip, ihop, spin) = polstate%gradres(ip)
2045 : 2331 : self%nstep2cv_spin(ip, ihop, spin) = iter
2046 : :
2047 : 2331 : end subroutine varpeq_record
2048 : : !!***
2049 : :
2050 : : !----------------------------------------------------------------------
2051 : :
2052 : : !!****f* m_varpeq/varpeq_hop_setup
2053 : : !! NAME
2054 : : !! varpeq_hop_setup
2055 : : !!
2056 : : !! FUNCTION
2057 : : !! Setup the hopping optimization.
2058 : : !! This routine specfifies the set of B_q\nu images via linear
2059 : : !! interpolation between an initial and final images.
2060 : : !!
2061 : : !! INPUTS
2062 : : !! dtset<dataset_type>=All input variables for this dataset.
2063 : : !!
2064 : : !! OUTPUT
2065 : : !!
2066 : : !! SOURCE
2067 : :
2068 : 1 : subroutine varpeq_hop_setup(self, dtset)
2069 : :
2070 : : !Arguments ------------------------------------
2071 : : class(varpeq_t), target, intent(inout) :: self
2072 : : type(dataset_type), intent(in) :: dtset
2073 : :
2074 : : !Local variables-------------------------------
2075 : : !scalars
2076 [ + + + + : 103 : type(varpeq_t) :: vpq_from, vpq_to
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + ]
2077 : : class(polstate_t), pointer :: polstate
2078 : : class(gqk_t), pointer :: gqk
2079 : : integer, parameter :: master = 0
2080 : : integer :: my_rank, comm, ierr
2081 : : integer :: my_is, spin
2082 : : real(dp) :: cpu, wall, gflops
2083 : : !arrays
2084 : : integer :: center(3)
2085 : 2 : complex(dp) :: b_spin_from(self%natom3, self%max_nq, self%nsppol)
2086 : 1 : complex(dp) :: b_spin_to(self%natom3, self%max_nq, self%nsppol)
2087 : :
2088 : : !----------------------------------------------------------------------
2089 : :
2090 : 1 : call cwtime(cpu, wall, gflops, "start")
2091 : :
2092 : 1 : comm = self%gstore%comm; my_rank = xmpi_comm_rank(comm)
2093 : :
2094 [ + - ]: 1 : if (my_rank == master) then
2095 : 1 : call vpq_from%ncread(dtset%vpq_hop_from_filepath, xmpi_comm_self)
2096 : :
2097 [ + - ]: 1 : if (dtset%vpq_hop_to_filepath /= ABI_NOFILE) then
2098 : 1 : call vpq_to%ncread(dtset%vpq_hop_to_filepath, xmpi_comm_self)
2099 : : else
2100 : 0 : call vpq_to%ncread(dtset%vpq_hop_from_filepath, xmpi_comm_self)
2101 : : endif
2102 : :
2103 : :
2104 : : ! TODO: allow BZ mismatch by adding a BZ interpolation step?
2105 : 1 : call self%compare(vpq_from, bz_mismatch=.false.)
2106 : 1 : call self%compare(vpq_to, bz_mismatch=.false.)
2107 : :
2108 [ + + + + : 877 : b_spin_from(:,:,:) = vpq_from%b_spin(:,:, dtset%vpq_hop_from_ip, :)
+ + ]
2109 [ + + + + : 877 : b_spin_to(:,:,:) = vpq_to%b_spin(:,:, dtset%vpq_hop_to_ip, :)
+ + ]
2110 : :
2111 : 1 : call vpq_from%free()
2112 : 1 : call vpq_to%free()
2113 : : endif
2114 : :
2115 : 1 : call xmpi_bcast(b_spin_from, master, comm, ierr)
2116 : 1 : call xmpi_bcast(b_spin_to, master, comm, ierr)
2117 : :
2118 [ + + ]: 4 : center(:) = self%ngkpt(:) / 2
2119 : :
2120 [ + + ]: 2 : do my_is=1,self%gstore%my_nspins
2121 : 1 : spin = self%gstore%my_spins(my_is)
2122 : 1 : gqk => self%gstore%gqk(my_is)
2123 : 1 : polstate => self%polstate(spin)
2124 : :
2125 : : call polstate%load_b(b_spin_from(:,:,spin), ip=1, &
2126 [ + + ]: 4 : trvec=(center(:) - dtset%vpq_hop_from_site(:)))
2127 : :
2128 [ + - ]: 1 : if (dtset%vpq_hop_to_filepath /= ABI_NOFILE) then
2129 : : call polstate%load_b(b_spin_to(:,:,spin), ip=self%nstates, &
2130 [ + + ]: 4 : trvec=(center(:) - dtset%vpq_hop_to_site(:) + dtset%vpq_hop_vec(:)))
2131 : : else
2132 : : call polstate%load_b(b_spin_to(:,:,spin), ip=self%nstates, &
2133 [ # # ]: 0 : trvec=(center(:) - dtset%vpq_hop_from_site(:) + dtset%vpq_hop_vec(:)))
2134 : : endif
2135 : :
2136 : 2 : call polstate%linterp_b()
2137 : : enddo
2138 : :
2139 : 1 : self%fix_displ = .true.
2140 : :
2141 : 1 : call cwtime_report(" varpeq: hop_setup", cpu, wall, gflops)
2142 : :
2143 [ - + - + : 1 : end subroutine varpeq_hop_setup
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - ]
2144 : : !!***
2145 : :
2146 : : !----------------------------------------------------------------------
2147 : :
2148 : : !!****f* m_varpeq/varpeq_init
2149 : : !! NAME
2150 : : !! varpeq_init
2151 : : !!
2152 : : !! FUNCTION
2153 : : !! Initialize the oboject by setting basic variables, allocate dynamic arrays.
2154 : : !!
2155 : : !! INPUTS
2156 : : !! gstore<gstore_t>=Electron-phonon matrix elements and related quantities.
2157 : : !! dtset<dataset_type>=All input variables for this dataset.
2158 : : !!
2159 : : !! OUTPUT
2160 : : !!
2161 : : !! SOURCE
2162 : :
2163 : 9 : subroutine varpeq_init(self, gstore, dtset)
2164 : :
2165 : : !Arguments ------------------------------------
2166 : : class(varpeq_t), target, intent(inout) :: self
2167 : : type(gstore_t), target, intent(in) :: gstore
2168 : : type(dataset_type), intent(in) :: dtset
2169 : :
2170 : : !Local variables-------------------------------
2171 : : !scalars
2172 : : character(len=5000) :: msg
2173 : : class(gqk_t), pointer :: gqk
2174 : : class(crystal_t), pointer :: cryst
2175 : : class(polstate_t), pointer :: polstate
2176 : : integer :: ierr, my_is, spin, bstart, bend, my_iq
2177 : : real(dp) :: wtq, cpu, wall, gflops
2178 : : !----------------------------------------------------------------------
2179 : :
2180 : 9 : call cwtime(cpu, wall, gflops, "start")
2181 : :
2182 : : ! Consistency check
2183 : 9 : ierr = 0
2184 [ - + ]: 9 : if (gstore%check_cplex_qkzone_gmode(2, "bz", "bz", "phonon") /= 0) then
2185 : 0 : ABI_ERROR_NOSTOP("The gstore object is inconsistent with varpeq. See messages above.", ierr)
2186 : : end if
2187 [ - + ]: 9 : if (gstore%has_used_lgk /= 0) then
2188 : 0 : ABI_ERROR_NOSTOP("The varpeq formalism does not support use_lgk /=0 .", ierr)
2189 : : end if
2190 [ - + ]: 9 : if (gstore%has_used_lgq /= 0) then
2191 : 0 : ABI_ERROR_NOSTOP("The varpeq formalism does not support use_lgq /=0 .", ierr)
2192 : : end if
2193 [ - + ]: 9 : if (ierr > 1) then
2194 : : write(msg,'(a,i0,5a)')&
2195 : 0 : 'Checking consistency of input data against itself gave ',ierr,' inconsistencies.',ch10,&
2196 : 0 : 'The details of the problems can be FOUND ABOVE (or in output or log file), in an earlier WARNING.',ch10,&
2197 : 0 : 'In parallel, the details might not even be printed there. Then, try running in sequential to see the details.'
2198 : 0 : ABI_ERROR(msg)
2199 : : end if
2200 : :
2201 : 9 : cryst => gstore%cryst
2202 : :
2203 : : ! Scalars
2204 : : ! character
2205 : 9 : self%mode = dtset%vpq_mode
2206 : 9 : self%pkind = dtset%vpq_pkind
2207 : 9 : self%aseed = dtset%vpq_aseed
2208 : : ! logical
2209 : 9 : self%restart = (dtset%eph_restart /= 0)
2210 : 9 : self%interp = (dtset%vpq_interp /= 0)
2211 : 9 : self%g0_flag = (dtset%vpq_avg_g /= 0)
2212 : 9 : self%translate = (dtset%vpq_translate /= 0)
2213 : : ! integer
2214 : 9 : self%atloc = dtset%vpq_atloc
2215 : 9 : self%hop_nstep = dtset%vpq_hop_nstep
2216 : 9 : self%nstep = dtset%vpq_nstep
2217 : 9 : self%nstep_ort = dtset%vpq_nstep_ort
2218 : 9 : self%nsppol = gstore%nsppol
2219 : 9 : self%nstates = dtset%vpq_nstates
2220 : 9 : self%natom3 = cryst%natom*3
2221 [ + + ]: 18 : self%max_nk = maxval(gstore%glob_nk_spin)
2222 [ + + ]: 18 : self%max_nq = maxval(gstore%glob_nq_spin)
2223 [ + + ]: 18 : self%max_nb = maxval(gstore%brange_k_spin(2,:) - gstore%brange_k_spin(1,:)) + 1
2224 : 9 : self%frohl_ntheta = dtset%eph_frohl_ntheta
2225 : : ! real
2226 : 9 : self%hop_tolgrs = dtset%vpq_hop_tolgrs
2227 : 9 : self%hop_ts = dtset%vpq_hop_ts
2228 : 9 : self%tolgrs = dtset%vpq_tolgrs
2229 : 9 : self%mixing_factor = dtset%vpq_mix_fact
2230 : :
2231 : : ! Static arrays
2232 : : ! integer
2233 [ + + ]: 36 : self%ngkpt(:) = dtset%ngkpt(:)
2234 : :
2235 : : ! Dynamic arrays
2236 : : ! integer
2237 [ - + + - : 27 : ABI_MALLOC(self%nk_spin, (gstore%nsppol))
+ - + - -
+ - + -
+ ]
2238 [ - + + - : 27 : ABI_MALLOC(self%nq_spin, (gstore%nsppol))
+ - + - -
+ - + -
+ ]
2239 [ - + + - : 27 : ABI_MALLOC(self%nb_spin, (gstore%nsppol))
+ - + - -
+ - + -
+ ]
2240 [ - + + - : 27 : ABI_MALLOC(self%brange_spin, (2, gstore%nsppol))
+ - + - -
+ - + -
+ ]
2241 [ + + ]: 18 : self%nk_spin(:) = gstore%glob_nk_spin(:)
2242 [ + + ]: 18 : self%nq_spin(:) = gstore%glob_nq_spin(:)
2243 [ + + ]: 18 : self%nb_spin(:) = gstore%brange_k_spin(2,:) - gstore%brange_k_spin(1,:) + 1
2244 [ + + + + ]: 36 : self%brange_spin(:,:) = gstore%brange_k_spin(:,:)
2245 : :
2246 [ - + + - : 45 : ABI_MALLOC(self%cvflag_spin, (self%nstates, self%hop_nstep, gstore%nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2247 [ - + + - : 45 : ABI_MALLOC(self%nstep2cv_spin, (self%nstates, self%hop_nstep, gstore%nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2248 [ - + + - : 27 : ABI_MALLOC(self%hop_nstep2cv_spin, (gstore%nsppol))
+ - + - -
+ - + -
+ ]
2249 [ + + + + : 186 : self%cvflag_spin(:,:,:) = zero
+ + ]
2250 [ + + + + : 186 : self%nstep2cv_spin(:,:,:) = zero
+ + ]
2251 [ + + ]: 18 : self%hop_nstep2cv_spin(:) = zero
2252 : :
2253 [ - + + - : 36 : ABI_MALLOC(self%k2ibz_spin, (self%max_nk, gstore%nsppol))
- + + - +
- + - - +
- + - + ]
2254 [ - + + - : 36 : ABI_MALLOC(self%q2ibz_spin, (self%max_nq, gstore%nsppol))
- + + - +
- + - - +
- + - + ]
2255 : :
2256 : : ! real
2257 [ - + + - : 27 : ABI_MALLOC(self%chrgat, (cryst%natom))
+ - + - -
+ - + -
+ ]
2258 [ - + + - : 45 : ABI_MALLOC(self%hop_hist_spin, (5, self%nstates, self%hop_nstep, gstore%nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2259 [ - + + - : 54 : ABI_MALLOC(self%scf_hist_spin, (6, self%nstep, self%nstates, self%hop_nstep, gstore%nsppol))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
2260 [ + + ]: 27 : self%chrgat(:) = dtset%chrgat(:)
2261 [ + + + + : 911 : self%hop_hist_spin(:,:,:,:) = zero
+ + + + ]
2262 [ + + + + : 98641 : self%scf_hist_spin(:,:,:,:,:) = zero
+ + + + +
+ ]
2263 : :
2264 [ - + + - : 36 : ABI_MALLOC(self%kpts_spin, (3, self%max_nk, gstore%nsppol))
- + + - +
- + - - +
- + - + ]
2265 [ - + + - : 36 : ABI_MALLOC(self%qpts_spin, (3, self%max_nq, gstore%nsppol))
- + + - +
- + - - +
- + - + ]
2266 [ - + + - : 27 : ABI_MALLOC(self%erange_spin, (gstore%nsppol))
+ - + - -
+ - + -
+ ]
2267 [ + + ]: 18 : self%erange_spin(:) = zero
2268 [ + + ]: 9 : if (gstore%kfilter == "erange") then
2269 : 1 : self%use_filter = .true.
2270 [ - + ]: 1 : if (dtset%vpq_pkind == "hole") then
2271 [ # # ]: 0 : self%erange_spin(:) = gstore%erange_spin(1,:)
2272 : : else
2273 [ + + ]: 2 : self%erange_spin(:) = gstore%erange_spin(2,:)
2274 : : endif
2275 : : endif
2276 : :
2277 : : ! complex
2278 [ - + + - : 54 : ABI_MALLOC(self%a_spin, (self%max_nb, self%max_nk, self%nstates, gstore%nsppol))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
2279 [ - + + - : 54 : ABI_MALLOC(self%b_spin, (self%natom3, self%max_nq, self%nstates, gstore%nsppol))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
2280 : :
2281 : : ! Datatypes and pointers
2282 : 9 : self%gstore => gstore
2283 : 9 : call cryst%copy(self%cryst)
2284 [ - + - + : 9 : self%gaps = gstore%ebands%get_gaps(ierr)
- + - + -
+ - + - +
- + ]
2285 : :
2286 : : call self%scell%init(cryst%natom, gstore%ebands%kptrlatt, cryst%rprimd, &
2287 : 9 : cryst%typat, cryst%xcart, cryst%znucl, xyz_order="xyz")
2288 [ - + ]: 9 : ABI_CHECK(gstore%same_nbands(msg), sjoin("VarPEq requires nb_k == nb_kq.", msg))
2289 : :
2290 : : ! Initialize polaronic states for each spin
2291 [ - + + - : 495 : ABI_MALLOC(self%polstate, (gstore%my_nspins))
+ - + - -
+ - + - +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ - - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ ]
2292 [ + + ]: 18 : do my_is=1,gstore%my_nspins
2293 : 9 : spin = gstore%my_spins(my_is)
2294 : 9 : gqk => gstore%gqk(my_is)
2295 : 9 : polstate => self%polstate(my_is)
2296 : :
2297 : : ! Scalars
2298 : : ! character
2299 : 9 : polstate%aseed = dtset%vpq_aseed
2300 : : ! logical
2301 : 9 : polstate%translate = (dtset%vpq_translate /= 0)
2302 : : ! integers
2303 : 9 : polstate%np = dtset%vpq_nstates
2304 : 9 : polstate%nkbz = gstore%nkbz
2305 : 9 : polstate%nqbz = gstore%nqbz
2306 : : ! real
2307 : 9 : polstate%e_frohl = zero
2308 : 9 : polstate%efilter = dtset%vpq_efilter
2309 : :
2310 : : ! Static arrays
2311 : : ! integer
2312 [ + + ]: 36 : polstate%ngkpt(:) = dtset%ngkpt(:)
2313 : : ! real
2314 [ + + ]: 27 : polstate%gpr_energy(:) = dtset%vpq_gpr_energy(:)
2315 [ + + ]: 36 : polstate%gpr_length(:) = dtset%vpq_gpr_length(:)
2316 : :
2317 : : ! Dynamic arrays
2318 : : ! logical
2319 [ - + + - : 27 : ABI_MALLOC(polstate%has_prev_grad, (dtset%vpq_nstates))
+ - + - -
+ - + -
+ ]
2320 [ + + ]: 28 : polstate%has_prev_grad(:) = .false.
2321 : : ! real
2322 [ - + + - : 27 : ABI_MALLOC(polstate%gradres, (dtset%vpq_nstates))
+ - + - -
+ - + -
+ ]
2323 [ - + + - : 27 : ABI_MALLOC(polstate%enterms, (4, dtset%vpq_nstates))
+ - + - -
+ - + -
+ ]
2324 : :
2325 [ - + + - : 36 : ABI_MALLOC(polstate%eig, (gqk%nb_k, gstore%ebands%nkpt))
- + + - +
- + - - +
- + - + ]
2326 : : msg = sjoin(self%gaps%errmsg_spin(spin), &
2327 [ + - ]: 9 : "VarPEq is incompatible with metals and requires band gap.")
2328 [ - + ]: 9 : ABI_CHECK(self%gaps%ierr(spin) == 0, msg)
2329 : :
2330 : 9 : bstart = gstore%brange_k_spin(1, spin)
2331 : 9 : bend = bstart + gqk%nb_k - 1
2332 : 1 : select case(dtset%vpq_pkind)
2333 : : case ("electron")
2334 : : polstate%eig = &
2335 [ + - + - : 170 : gstore%ebands%eig(bstart:bend, :, spin) - self%gaps%cb_min(spin)
- + - - +
+ + + ]
2336 : 1 : polstate%psign = 1
2337 : : case ("hole")
2338 : : polstate%eig = &
2339 [ + - + - : 248 : -(gstore%ebands%eig(bstart:bend, :, spin) - self%gaps%vb_max(spin))
- + - - +
+ + + ]
2340 [ + + - ]: 17 : polstate%psign = -1
2341 : : end select
2342 : :
2343 [ - + + - : 27 : ABI_MALLOC(polstate%my_g0, (gqk%my_npert))
+ - + - -
+ - + -
+ ]
2344 [ + + ]: 63 : polstate%my_g0(:) = zero
2345 : :
2346 [ - + + - : 27 : ABI_MALLOC(polstate%my_qpts, (3, gqk%my_nq))
+ - + - -
+ - + -
+ ]
2347 [ + + ]: 1190 : do my_iq=1,gqk%my_nq
2348 : 1190 : call gqk%myqpt(my_iq, gstore, wtq, polstate%my_qpts(:, my_iq))
2349 : : enddo
2350 : :
2351 [ - + + - : 36 : ABI_MALLOC(polstate%displ, (3, self%scell%natom, dtset%vpq_nstates))
- + + - +
- + - - +
- + - + ]
2352 : :
2353 : : ! complex
2354 [ - + + - : 45 : ABI_MALLOC(polstate%my_a, (gqk%nb_k, gqk%my_nk, dtset%vpq_nstates))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2355 [ - + + - : 45 : ABI_MALLOC(polstate%a_glob, (gqk%nb_k, gqk%glob_nk, dtset%vpq_nstates))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2356 [ - + + - : 45 : ABI_MALLOC(polstate%my_b, (gqk%my_npert, gqk%my_nq, dtset%vpq_nstates))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2357 [ - + + - : 36 : ABI_MALLOC(polstate%my_prev_b, (gqk%my_npert, gqk%my_nq))
- + + - +
- + - - +
- + - + ]
2358 [ - + + - : 45 : ABI_MALLOC(polstate%my_prev_b_hop, (gqk%my_npert, gqk%my_nq, dtset%vpq_nstates))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2359 [ - + + - : 36 : ABI_MALLOC(polstate%my_pc, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2360 [ - + + - : 36 : ABI_MALLOC(polstate%my_grad, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2361 [ - + + - : 36 : ABI_MALLOC(polstate%my_prev_grad, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2362 [ - + + - : 36 : ABI_MALLOC(polstate%my_pcgrad, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2363 [ - + + - : 36 : ABI_MALLOC(polstate%my_prev_pcgrad, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2364 [ - + + - : 36 : ABI_MALLOC(polstate%my_pcjgrad, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2365 [ - + + - : 36 : ABI_MALLOC(polstate%my_prev_pcjgrad, (gqk%nb_k, gqk%my_nk))
- + + - +
- + - - +
- + - + ]
2366 [ - + + - : 36 : ABI_MALLOC(polstate%pcjgrad_glob, (gqk%nb_k, gqk%glob_nk))
- + + - +
- + - - +
- + - + ]
2367 [ - + + - : 45 : ABI_MALLOC(polstate%my_phgrad, (gqk%my_npert, gqk%my_nq, dtset%vpq_nstates))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2368 [ - + + - : 45 : ABI_MALLOC(polstate%my_eff_phforce, (gqk%my_npert, gqk%my_nq, dtset%vpq_nstates))
- + + - -
+ + - + -
+ - - + -
+ - + ]
2369 [ - + + - : 27 : ABI_MALLOC(polstate%hop_ts, (dtset%vpq_nstates))
+ - + - -
+ - + -
+ ]
2370 : :
2371 : : ! Datatypes ans pointers
2372 : 9 : polstate%gqk => gqk
2373 : 9 : polstate%my_kpts => gqk%my_kpts(:,:)
2374 [ - + - + : 9 : polstate%krank_kpts = polstate%get_krank_glob("k", gstore%ebands%kptrlatt)
- + ]
2375 [ - + - + : 9 : polstate%krank_qpts = polstate%get_krank_glob("q", gstore%ebands%kptrlatt)
- + ]
2376 : :
2377 : 18 : call cryst%copy(polstate%cryst)
2378 : :
2379 : : enddo
2380 : :
2381 : : ! This is needed to fill kpts_spin/qpts_spin before the calculation, as they may
2382 : : ! be required by the varpeq_load subroutine
2383 : 9 : call xmpi_barrier(gstore%comm)
2384 : 9 : call self%collect()
2385 : :
2386 : 9 : self%is_complete = .true.
2387 : :
2388 : 9 : call cwtime_report(" varpeq: init", cpu, wall, gflops)
2389 : :
2390 : 18 : end subroutine varpeq_init
2391 : : !!***
2392 : :
2393 : : !----------------------------------------------------------------------
2394 : :
2395 : : !!****f* m_varpeq/varpeq_calc_fravg
2396 : : !! NAME
2397 : : !! varpeq_calc_fravg
2398 : : !!
2399 : : !! FUNCTION
2400 : : !! Calculate the average Fr\"ohlich long-range contribution to the polaron
2401 : : !! binding energy at Gamma using spherical integration in the spherical region
2402 : : !! arond Gamma-point.
2403 : : !!
2404 : : !! INPUTS
2405 : : !! avg_g0 [optional]=If .true., average electron-phonon matrix elements at
2406 : : !! Gamma-point. Default: .true.
2407 : : !!
2408 : : !! OUTPUT
2409 : : !!
2410 : : !! SOURCE
2411 : :
2412 : 9 : subroutine varpeq_calc_fravg(self, avg_g0)
2413 : :
2414 : : !Arguments ------------------------------------
2415 : : class(varpeq_t), target, intent(inout) :: self
2416 : : logical, optional, intent(in) :: avg_g0
2417 : :
2418 : : !Local variables-------------------------------
2419 : : !scalars
2420 : : type(ifc_type), pointer :: ifc
2421 : : class(polstate_t), pointer :: polstate
2422 : : class(gqk_t), pointer :: gqk
2423 : : integer :: comm, my_rank, nproc, ierr
2424 : : integer :: ntheta, nphi, angl_size
2425 : : integer :: iang, iatom
2426 : : integer :: nu, my_is, my_pert, pert_glob
2427 : : real(dp) :: inv_qepsq, wqnu, prefactor
2428 : : real(dp) :: cpu, wall, gflops
2429 : : complex(dp) :: cnum
2430 : : !arrays
2431 : : real(dp) :: qpt_cart(3)
2432 : 9 : real(dp), allocatable :: phfreq(:), displ_cart(:, :, :, :)
2433 : 9 : real(dp), allocatable :: qvers_cart(:, :)
2434 : 9 : real(dp), allocatable :: angweight(:)
2435 : : real(dp), allocatable :: e_frohl_mode(:)
2436 : : complex(dp) :: cp3(3)
2437 : : !----------------------------------------------------------------------
2438 : :
2439 : 9 : call cwtime(cpu, wall, gflops, "start")
2440 : :
2441 : 9 : comm = self%gstore%comm
2442 : 9 : nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
2443 : :
2444 : : ! Integrate electron-phonon energy in the spherical region around Gamma
2445 [ - + + - : 27 : ABI_MALLOC(phfreq, (self%natom3))
+ - + - -
+ - + ]
2446 [ - + + - : 18 : ABI_MALLOC(e_frohl_mode, (self%natom3))
- + - + ]
2447 [ - + + - : 36 : ABI_MALLOC(displ_cart, (2, 3, self%cryst%natom, self%natom3))
- + + - +
- + - - +
- + ]
2448 : :
2449 : 9 : ifc => self%gstore%ifc
2450 : :
2451 : : ! Create the mesh for spherical integrtion
2452 : 9 : ntheta = self%frohl_ntheta
2453 : 9 : nphi = 2*ntheta
2454 : 9 : call ylm_angular_mesh(ntheta, nphi, angl_size, qvers_cart, angweight)
2455 : :
2456 : : ! Integrate the contribution from each phonon mode
2457 : : ! This is similar to what is done in the src/78_eph/m_sigmaph.f90 module
2458 [ + + ]: 63 : e_frohl_mode(:) = zero
2459 [ + + ]: 18441 : do iang=1,angl_size
2460 [ + - ]: 18432 : if (mod(iang, nproc) /= my_rank) cycle
2461 : :
2462 [ + + ]: 73728 : qpt_cart = qvers_cart(:, iang)
2463 [ + + + + : 294912 : inv_qepsq = one / dot_product(qpt_cart, matmul(ifc%dielt, qpt_cart))
+ + ]
2464 : 18432 : call ifc%fourq(self%cryst, qpt_cart, phfreq, displ_cart, nanaqdir="cart")
2465 : :
2466 [ + + ]: 73737 : do nu=4,self%natom3
2467 : 55296 : wqnu = phfreq(nu)
2468 : :
2469 : 55296 : cp3(:) = zero
2470 [ + + ]: 165888 : do iatom=1,self%cryst%natom
2471 [ - + + - : 331776 : cp3(:) = cp3(:) + matmul(ifc%zeff(:, :, iatom), &
+ - + - -
+ - + ]
2472 [ + + + + : 4036608 : cmplx(displ_cart(1,:,iatom,nu), displ_cart(2,:,iatom,nu), kind=dp))
+ + + + +
+ + + + -
+ - + + +
- ]
2473 : : enddo
2474 [ + + ]: 221184 : cnum = dot_product(qpt_cart, cp3)
2475 [ + + ]: 55296 : if (abs(cnum) < tol12) cycle
2476 : :
2477 : : e_frohl_mode(nu) = e_frohl_mode(nu) + &
2478 : 73728 : angweight(iang)*(abs(cnum)*inv_qepsq/wqnu)**2
2479 : : enddo
2480 : : enddo
2481 : 9 : call xmpi_sum(e_frohl_mode, comm, ierr)
2482 : :
2483 : : prefactor = (eight * pi / self%cryst%ucvol) * &
2484 : 9 : (three / (four_pi * self%cryst%ucvol * self%gstore%nqbz))**third
2485 : :
2486 [ + + ]: 63 : e_frohl_mode(:) = prefactor*e_frohl_mode(:)
2487 [ + + ]: 63 : self%e_frohl = sum(e_frohl_mode)
2488 : : ! For an electron polaron, the correction has to be negative
2489 [ + + ]: 9 : if (self%pkind == "electron") self%e_frohl = -self%e_frohl
2490 : :
2491 : : ! If corresponding flag is provided, average the matrix elements at Gamma
2492 [ + - + + ]: 9 : if (present(avg_g0) .and. avg_g0) then
2493 [ + + ]: 12 : do my_is=1,self%gstore%my_nspins
2494 : 6 : polstate => self%polstate(my_is)
2495 : 6 : gqk => polstate%gqk
2496 : :
2497 : 6 : polstate%e_frohl = self%e_frohl
2498 [ + + ]: 48 : do my_pert=1,gqk%my_npert
2499 : 36 : pert_glob = gqk%my_pert_start + my_pert - 1
2500 : 36 : wqnu = phfreq(pert_glob)
2501 : : polstate%my_g0(my_pert) = &
2502 : 42 : sqrt(polstate%nqbz * wqnu * e_frohl_mode(pert_glob) / two)
2503 : :
2504 : : enddo
2505 : : enddo
2506 : : endif
2507 : :
2508 [ - + ]: 9 : ABI_FREE(phfreq)
2509 [ - + ]: 9 : ABI_FREE(e_frohl_mode)
2510 [ - + ]: 9 : ABI_FREE(displ_cart)
2511 [ - + ]: 9 : ABI_FREE(qvers_cart)
2512 [ - + ]: 9 : ABI_FREE(angweight)
2513 : :
2514 : 9 : call cwtime_report(" varpeq: calc_fravg", cpu, wall, gflops)
2515 : :
2516 : 27 : end subroutine varpeq_calc_fravg
2517 : : !!***
2518 : :
2519 : : !----------------------------------------------------------------------
2520 : :
2521 : : !!****f* m_varpeq/polstate_free
2522 : : !! NAME
2523 : : !! polstate_free
2524 : : !!
2525 : : !! FUNCTION
2526 : : !! Free dynamic memory
2527 : : !!
2528 : : !! OUTPUT
2529 : : !!
2530 : : !! SOURCE
2531 : :
2532 : 9 : subroutine polstate_free(self)
2533 : :
2534 : : !Arguments ------------------------------------
2535 : : class(polstate_t), intent(inout) :: self
2536 : : !----------------------------------------------------------------------
2537 : :
2538 : : ! Free allocatable arrays
2539 : :
2540 : : ! logical
2541 [ + - ]: 9 : ABI_SFREE(self%has_prev_grad)
2542 : : ! real
2543 [ + - ]: 9 : ABI_SFREE(self%gradres)
2544 [ + - ]: 9 : ABI_SFREE(self%enterms)
2545 [ + - ]: 9 : ABI_SFREE(self%eig)
2546 [ + - ]: 9 : ABI_SFREE(self%my_g0)
2547 [ + - ]: 9 : ABI_SFREE(self%my_qpts)
2548 [ + - ]: 9 : ABI_SFREE(self%displ)
2549 : :
2550 : : ! complex
2551 [ + - ]: 9 : ABI_SFREE(self%my_a)
2552 [ + - ]: 9 : ABI_SFREE(self%a_glob)
2553 [ + - ]: 9 : ABI_SFREE(self%my_b)
2554 [ + - ]: 9 : ABI_SFREE(self%my_prev_b)
2555 [ + - ]: 9 : ABI_SFREE(self%my_prev_b_hop)
2556 [ + - ]: 9 : ABI_SFREE(self%my_pc)
2557 [ + - ]: 9 : ABI_SFREE(self%my_grad)
2558 [ + - ]: 9 : ABI_SFREE(self%my_pcgrad)
2559 [ + - ]: 9 : ABI_SFREE(self%my_prev_pcgrad)
2560 [ + - ]: 9 : ABI_SFREE(self%my_prev_grad)
2561 [ + - ]: 9 : ABI_SFREE(self%my_pcjgrad)
2562 [ + - ]: 9 : ABI_SFREE(self%my_prev_pcjgrad)
2563 [ + - ]: 9 : ABI_SFREE(self%pcjgrad_glob)
2564 [ + - ]: 9 : ABI_SFREE(self%my_phgrad)
2565 [ + - ]: 9 : ABI_SFREE(self%my_eff_phforce)
2566 [ + - ]: 9 : ABI_SFREE(self%hop_ts)
2567 : :
2568 : : ! Free local datatypes & nullify pointers
2569 : 9 : self%my_kpts => null()
2570 : 9 : self%gqk => null()
2571 : :
2572 : 9 : call self%krank_kpts%free()
2573 : 9 : call self%krank_qpts%free()
2574 : :
2575 : 9 : call self%cryst%free()
2576 : :
2577 : 9 : end subroutine polstate_free
2578 : : !!***
2579 : :
2580 : : !----------------------------------------------------------------------
2581 : :
2582 : : !!****f* m_varpeq/polstate_setup
2583 : : !! NAME
2584 : : !! polstate_setup
2585 : : !!
2586 : : !! FUNCTION
2587 : : !! Setup optimization process at a given polaronic state.
2588 : : !! This routine specfifies an initial electronic vector A_nk, either by
2589 : : !! initializaing it by a pre-determined algorithm or loading from a
2590 : : !! *VPQ.nc netcdf file.
2591 : : !!
2592 : : !! INPUTS
2593 : : !! ip=Index of the polaronic state.
2594 : : !! a_src(self%gqk%nb_k, self%gqk%glob_nk) [optional]=Global A_nk coefficients at
2595 : : !! this state, which have to be provided if load_src=.true.
2596 : : !! load_src [optional]=.true. if A_nk is initialized from an external source,
2597 : : !! e.g. loaded from file. Default: .false.
2598 : : !! atloc [optional]=Index of an atom where charge is localized.
2599 : : !! chrgat(natom) [optional]=Charge of the atoms.
2600 : : !! scell<supercell_type> [optional]=Supercell data structure.
2601 : : !! cryst<crystal_t> [optional]=Crystal data structure.
2602 : : !! nstep_loc [optional]=Number of iterations for charge localization.
2603 : : !!
2604 : : !! OUTPUT
2605 : : !!
2606 : : !! SOURCE
2607 : :
2608 [ + - + - : 19 : subroutine polstate_setup(self, ip, a_src, load, atloc, chrgat, scell, cryst, nstep_loc)
- + ]
2609 : :
2610 : : !Arguments ------------------------------------
2611 : : class(polstate_t), target, intent(inout) :: self
2612 : : integer, intent(in) :: ip
2613 : : logical, optional, intent(in) :: load
2614 : : complex(dp), optional, intent(in) :: a_src(self%gqk%nb_k, self%gqk%glob_nk)
2615 : : integer, optional, intent(in) :: atloc
2616 : : class(supercell_type), optional, intent(in) :: scell
2617 : : class(crystal_t), optional, intent(in) :: cryst
2618 : : real(dp), optional, intent(in) :: chrgat(:)
2619 : : integer, optional, intent(in) :: nstep_loc
2620 : :
2621 : : !Local variables-------------------------------
2622 : : real(dp) :: a_sqnorm
2623 : : class(gqk_t), pointer :: gqk
2624 : : !----------------------------------------------------------------------
2625 : :
2626 : 19 : gqk => self%gqk
2627 : :
2628 [ + - - + ]: 19 : if (present(load) .and. load) then
2629 [ # # ]: 0 : ABI_CHECK(present(a_src), "polstate_setup: A_nk is expected but not provided")
2630 : : !print *, "load"
2631 : 0 : call self%load_a(a_src, ip)
2632 : : else
2633 [ - + ]: 19 : call self%seed_a(self%aseed, ip, atloc, chrgat, scell, cryst, nstep_loc)
2634 : : endif
2635 : :
2636 [ - + ]: 19 : if (self%efilter > zero) call self%filter("a", ip)
2637 : :
2638 : : ! Orthogonalize current states to the previous ones
2639 : 19 : call self%ort_to_states(self%my_a(:,:,ip), 1, ip-1, ip, tr_flag=self%translate)
2640 : :
2641 : : ! Normalize A_nk at current polaronic state
2642 : 19 : a_sqnorm = self%get_sqnorm("a", ip)
2643 [ + - ]: 19 : if (a_sqnorm > tol12) then
2644 [ + + + + ]: 6749 : self%my_a(:,:,ip) = sqrt(self%nkbz/a_sqnorm) * self%my_a(:,:,ip)
2645 : : endif
2646 : :
2647 : 19 : end subroutine polstate_setup
2648 : : !!***
2649 : :
2650 : : !----------------------------------------------------------------------
2651 : :
2652 : : !!****f* m_varpeq/polstate_update_a
2653 : : !! NAME
2654 : : !! polstate_update_a
2655 : : !!
2656 : : !! FUNCTION
2657 : : !! Update the vector of electronic coefficients A_nk by line minimization in
2658 : : !! the pcj direction for current polaronic state.
2659 : : !!
2660 : : !! INPUTS
2661 : : !! ip=Index of a polaronic state.
2662 : : !!
2663 : : !! OUTPUT
2664 : : !!
2665 : : !! SOURCE
2666 : :
2667 : 2187 : subroutine polstate_update_a(self, ip)
2668 : :
2669 : : !Arguments ------------------------------------
2670 : : class(polstate_t), intent(inout) :: self
2671 : : integer, intent(in) :: ip
2672 : :
2673 : : !Local variables-------------------------------
2674 : : real(dp) :: theta
2675 : : !----------------------------------------------------------------------
2676 : :
2677 : 2187 : theta = self%get_lm_theta(ip)
2678 : : self%my_a(:,:,ip) = &
2679 [ + + + + ]: 1002787 : cos(theta)*self%my_a(:,:,ip) + sin(theta)*self%my_pcjgrad(:,:)
2680 : :
2681 : 2187 : end subroutine polstate_update_a
2682 : : !!***
2683 : :
2684 : : !----------------------------------------------------------------------
2685 : :
2686 : : !!****f* m_varpeq/polstate_update_pc
2687 : : !! NAME
2688 : : !! polstate_update_pc
2689 : : !!
2690 : : !! FUNCTION
2691 : : !! Update the preconditioner for the present configuration. Changing this
2692 : : !! procedure may significantly improve (or worsen) the optimization process.
2693 : : !!
2694 : : !! INPUTS
2695 : : !! ip=Index of a polaronic state.
2696 : : !!
2697 : : !! OUTPUT
2698 : : !!
2699 : : !! SOURCE
2700 : :
2701 : 2187 : subroutine polstate_update_pc(self, ip)
2702 : :
2703 : : !Arguments ------------------------------------
2704 : : class(polstate_t), intent(inout) :: self
2705 : : integer, intent(in) :: ip
2706 : :
2707 : : !Local variables-------------------------------
2708 : : class(gqk_t), pointer :: gqk
2709 : : integer :: my_ik, ik_ibz, ib
2710 : : real(dp) :: eps
2711 : : !----------------------------------------------------------------------
2712 : :
2713 : 2187 : gqk => self%gqk
2714 : :
2715 : 2187 : eps = self%enterms(4, ip)
2716 [ + + ]: 253583 : do my_ik=1,gqk%my_nk
2717 : 251396 : ik_ibz = gqk%my_k2ibz(1, my_ik)
2718 [ + + ]: 1002787 : do ib=1,gqk%nb_k
2719 : : self%my_pc(ib, my_ik) = &
2720 : 1000600 : one/abs(self%eig(ib, ik_ibz) - two*abs(self%e_frohl) + abs(eps))
2721 : : !self%my_pc(ib, my_ik) = one
2722 : : enddo
2723 : : enddo
2724 : :
2725 : 2187 : end subroutine polstate_update_pc
2726 : : !!***
2727 : :
2728 : : !----------------------------------------------------------------------
2729 : :
2730 : : !!****f* m_varpeq/polstate_ort_to_states
2731 : : !! NAME
2732 : : !! polstate_ort_to_states
2733 : : !!
2734 : : !! FUNCTION
2735 : : !! Orthognongalize a vector wrt polaronic states using the Gram-Schmidt process.
2736 : : !! The orthogonalization is performed for a range of states, specified by arguments.
2737 : : !!
2738 : : !! INPUTS
2739 : : !! my_v(:,:)=Vetor to be orthogonalized
2740 : : !! istart=Index of starting polaronic state
2741 : : !! iend=Index of final polaronic state
2742 : : !! this_ip=Index of current polaronic state
2743 : : !! tr_flag=.true. if orthogonalization must include all states invariant by
2744 : : !! translations inside a supercell
2745 : : !!
2746 : : !! OUTPUT
2747 : : !!
2748 : : !! SOURCE
2749 : :
2750 : 6392 : subroutine polstate_ort_to_states(self, my_v, istart, iend, this_ip, tr_flag)
2751 : :
2752 : : !Arguments ------------------------------------
2753 : : class(polstate_t), intent(inout) :: self
2754 : : logical, intent(in) :: tr_flag
2755 : : integer, intent(in) :: istart, iend, this_ip
2756 : : complex(dp), intent(inout) :: my_v(self%gqk%nb_k, self%gqk%my_nk)
2757 : :
2758 : : !Local variables-------------------------------
2759 : : class(gqk_t), pointer :: gqk
2760 : : integer :: ip, my_ik, vx, vy, vz
2761 : : complex(dp) :: phase, proj
2762 : : integer :: tr_vec(3), ngkpt_tr(3)
2763 : : real(dp) :: kpt(3)
2764 : 12784 : complex(dp) :: a_tr(self%gqk%nb_k, self%gqk%my_nk)
2765 : : !----------------------------------------------------------------------
2766 : :
2767 : 6392 : gqk => self%gqk
2768 : :
2769 : : !! TODO: optimize
2770 : : !ngkpt_tr(:) = 1
2771 : : !if (tr_flag) ngkpt_tr(:) = self%ngkpt(:)
2772 : :
2773 [ + + ]: 28927 : do ip=istart,iend
2774 : :
2775 [ + + + + ]: 22535 : if ((tr_flag) .and. ip /= this_ip) then
2776 [ + + ]: 732 : ngkpt_tr(:) = self%ngkpt(:)
2777 : : else
2778 [ + + ]: 89408 : ngkpt_tr(:) = 1
2779 : : endif
2780 : :
2781 [ + + ]: 51828 : do vx=1,ngkpt_tr(1)
2782 : 22901 : tr_vec(1) = vx - 1
2783 [ + + ]: 69435 : do vy=1,ngkpt_tr(2)
2784 : 23999 : tr_vec(2) = vy - 1
2785 [ + + ]: 74193 : do vz=1,ngkpt_tr(3)
2786 : 27293 : tr_vec(3) = vz - 1
2787 : :
2788 [ + + ]: 2910742 : do my_ik=1,gqk%my_nk
2789 [ + + ]: 11533796 : kpt(:) = self%my_kpts(:, my_ik)
2790 [ + + ]: 11533796 : phase = exp(j_dpc*sum(kpt(:)*tr_vec(:))*two_pi)
2791 [ + + ]: 11551121 : a_tr(:, my_ik) = phase*self%my_a(:, my_ik, ip)
2792 : : enddo
2793 : :
2794 : 27293 : proj = get_proj_(a_tr)
2795 [ + + + + ]: 11575120 : my_v(:,:) = my_v(:,:) - proj * a_tr(:,:)
2796 : :
2797 : : enddo
2798 : : enddo
2799 : : enddo
2800 : :
2801 : : enddo
2802 : :
2803 : : !----------------------------------------------------------------------
2804 : : contains
2805 : :
2806 : 27293 : complex(dp) function get_proj_(my_u) result(proj)
2807 : :
2808 : : complex(dp), intent(in) :: my_u(gqk%nb_k, gqk%my_nk)
2809 : : integer :: ierr
2810 : : real(dp) :: u_sqnorm
2811 : : !----------------------------------------------------------------------
2812 [ + + + + ]: 11551121 : u_sqnorm = sum(abs(my_u(:,:))**2)
2813 : 27293 : call xmpi_sum(u_sqnorm, gqk%kpt_comm%value, ierr)
2814 : :
2815 : 27293 : proj = zero
2816 [ + - ]: 27293 : if (u_sqnorm > tol12) then
2817 [ + + + + ]: 11551121 : proj = sum(conjg(my_u(:,:))*my_v(:,:))
2818 : 27293 : call xmpi_sum(proj, gqk%kpt_comm%value, ierr)
2819 : 27293 : proj = proj/u_sqnorm
2820 : : endif
2821 : 27293 : end function get_proj_
2822 : :
2823 : : end subroutine polstate_ort_to_states
2824 : : !!***
2825 : :
2826 : : !----------------------------------------------------------------------
2827 : :
2828 : : !!****f* m_varpeq/polstate_get_lm_theta
2829 : : !! NAME
2830 : : !! polstate_get_lm_theta
2831 : : !!
2832 : : !! FUNCTION
2833 : : !! Calculate line minimization parameter theta that minimizes polaron binding
2834 : : !! energy at the next electronic configuration:
2835 : : !! A^n = A^(n-1)*cos(theta) + D^(n-1)*sin(theta), where
2836 : : !! A^(n-1) and D^(n-1) are current electronic configuration and gradient.
2837 : : !!
2838 : : !! INPUTS
2839 : : !! ip=Index of a polaronic state.
2840 : : !!
2841 : : !! OUTPUT
2842 : : !! theta=Line minimization parameter.
2843 : : !!
2844 : : !! SOURCE
2845 : :
2846 : 2187 : real(dp) function polstate_get_lm_theta(self, ip) result(theta)
2847 : :
2848 : : !Arguments ------------------------------------
2849 : : class(polstate_t), intent(inout) :: self
2850 : : integer, intent(in) :: ip
2851 : :
2852 : : !Local variables-------------------------------
2853 : : !scalars
2854 : : class(gqk_t), pointer :: gqk
2855 : : real(dp) :: sqnorm, e1, e2, eps
2856 : :
2857 : : !----------------------------------------------------------------------
2858 : :
2859 : 2187 : gqk => self%gqk
2860 : :
2861 : : ! Orthogonalize pcj direction to the current state and normalize
2862 : 2187 : call self%ort_to_states(self%my_pcjgrad, ip, ip, ip, tr_flag=.false.)
2863 : :
2864 : 2187 : sqnorm = self%get_sqnorm('pcjgrad', ip)
2865 [ + + + + ]: 1002787 : self%my_pcjgrad(:,:) = sqrt(self%nkbz/sqnorm)*self%my_pcjgrad(:,:)
2866 : :
2867 : : ! Calculation of theta requires globally available pcj direction
2868 : 2187 : call self%gather("pcjgrad", ip)
2869 : :
2870 : :
2871 : : ! Line-minimization theta
2872 : : ! E_pol(theta) = E_pol[A,B] - e1/2 + e1/2*cos(2*theta) + e2/2*sin(theta)
2873 : 2187 : eps = self%enterms(4, ip)
2874 : : e1 = eps - self%calc_hpol(self%my_pcjgrad, self%pcjgrad_glob, &
2875 : 2187 : self%my_pcjgrad, self%my_b(:,:,ip))
2876 : : e2 = &
2877 : : self%calc_hpol(self%my_a(:,:,ip), self%a_glob(:,:,ip), self%my_pcjgrad, self%my_b(:,:,ip)) + &
2878 : 2187 : self%calc_hpol(self%my_pcjgrad, self%pcjgrad_glob, self%my_a(:,:,ip), self%my_b(:,:,ip))
2879 : :
2880 : 2187 : theta = half*atan2(-e2, -e1)
2881 : : !if (theta < zero) then
2882 : : ! theta = theta + pi
2883 : : !end if
2884 : : !theta = half*theta
2885 : :
2886 : 2187 : end function polstate_get_lm_theta
2887 : : !!***
2888 : :
2889 : : !----------------------------------------------------------------------
2890 : :
2891 : : !!****f* m_varpeq/polstate_calc_pcjgrad
2892 : : !! NAME
2893 : : !! polstate_calc_pcjgrad
2894 : : !!
2895 : : !! FUNCTION
2896 : : !! Calculate preconditioned conjugate gradient direction, orthogonal to all
2897 : : !! already optimized polaronic states. The procedure is similar to the one
2898 : : !! described in [Payne et al, Rev. Mod. Phys, 64, 4, 1045-1097 (1992)].
2899 : : !!
2900 : : !! INPUTS
2901 : : !! ip=Index of a polaronic state.
2902 : : !! ii=Iteration number.
2903 : : !! nstep_ort=Iteration number, after which the orthogonality constraint
2904 : : !! on all PREVIOUS states is lifted.
2905 : : !!
2906 : : !! OUTPUT
2907 : : !!
2908 : : !! SOURCE
2909 : :
2910 : 2187 : subroutine polstate_calc_pcjgrad(self, ip, ii, nstep_ort)
2911 : :
2912 : : !Arguments ------------------------------------
2913 : : class(polstate_t), intent(inout) :: self
2914 : : integer, intent(in) :: ip, ii, nstep_ort
2915 : :
2916 : : !Local variables-------------------------------
2917 : : class(gqk_t), pointer :: gqk
2918 : : integer :: ierr
2919 : : !real(dp) :: eps
2920 : : complex(dp) :: beta, beta_num, beta_den
2921 : : !----------------------------------------------------------------------
2922 : :
2923 : 2187 : gqk => self%gqk
2924 : :
2925 [ - + ]: 2187 : if (self%efilter > zero) call self%filter("grad", ip)
2926 : :
2927 : : ! Orthogonalize current gradient to all previous bands
2928 [ + + ]: 2187 : if (ii <= nstep_ort) then
2929 : 1999 : call self%ort_to_states(self%my_grad, 1, ip-1, ip, tr_flag=self%translate)
2930 : : endif
2931 : :
2932 : : ! Precondtion vector
2933 [ + + + + ]: 1002787 : self%my_pcgrad(:,:) = self%my_pc(:,:)*self%my_grad(:,:)
2934 : : ! Orthogonalize to all bands
2935 [ + + ]: 2187 : if (ii <= nstep_ort) then
2936 : 1999 : call self%ort_to_states(self%my_pcgrad, 1, ip, ip, tr_flag=self%translate)
2937 : : else
2938 : 188 : call self%ort_to_states(self%my_pcgrad, ip, ip, ip, tr_flag=.false.)
2939 : : endif
2940 : :
2941 : : ! Conjugate gradient direction
2942 [ + + ]: 2187 : if (self%has_prev_grad(ip)) then
2943 : : ! Polak-Ribiere coefficient
2944 : : beta_num = &
2945 [ + + + + ]: 996038 : sum(conjg(self%my_pcgrad(:,:))*(self%my_grad(:,:) - self%my_prev_grad(:,:)))
2946 [ + + + + ]: 996038 : beta_den = sum(conjg(self%my_prev_pcgrad(:,:))*self%my_prev_grad(:,:))
2947 : 2168 : call xmpi_sum(beta_num, gqk%kpt_comm%value, ierr)
2948 : 2168 : call xmpi_sum(beta_den, gqk%kpt_comm%value, ierr)
2949 : 2168 : beta = beta_num / beta_den
2950 : : !if (abs(aimag(beta)) < tol12) beta = real(beta, dp)
2951 : :
2952 : :
2953 [ + + + + ]: 996038 : self%my_pcjgrad(:,:) = self%my_pcgrad(:,:) + beta*self%my_prev_pcjgrad(:,:)
2954 : : else
2955 [ + + + + ]: 6749 : self%my_pcjgrad(:,:) = self%my_pcgrad(:,:)
2956 : : endif
2957 : :
2958 : : ! Save previous gradients
2959 [ + + + + ]: 1002787 : self%my_prev_grad(:,:) = self%my_grad(:,:)
2960 [ + + + + ]: 1002787 : self%my_prev_pcgrad(:,:) = self%my_pcgrad(:,:)
2961 [ + + + + ]: 1002787 : self%my_prev_pcjgrad(:,:) = self%my_pcjgrad(:,:)
2962 : 2187 : self%has_prev_grad(ip) = .true.
2963 : :
2964 : 2187 : end subroutine polstate_calc_pcjgrad
2965 : : !!***
2966 : :
2967 : : !----------------------------------------------------------------------
2968 : :
2969 : : !!****f* m_varpeq/polstate_calc_grad
2970 : : !! NAME
2971 : : !! polstate_calc_grad
2972 : : !!
2973 : : !! FUNCTION
2974 : : !! Calculate the electronic gradient D_nk at the current configuration.
2975 : : !!
2976 : : !! INPUTS
2977 : : !! ip=Index of a polaronic state.
2978 : : !!
2979 : : !! OUTPUT
2980 : : !!
2981 : : !! SOURCE
2982 : :
2983 : 2331 : subroutine polstate_calc_grad(self, ip)
2984 : :
2985 : : !Arguments ------------------------------------
2986 : : class(polstate_t), intent(inout) :: self
2987 : : integer, intent(in) :: ip
2988 : :
2989 : : !Local variables-------------------------------
2990 : : !scalars
2991 : : class(gqk_t), pointer :: gqk
2992 : : logical :: q_gamma
2993 : : integer :: ierr
2994 : : integer :: my_iq, my_pert
2995 : : integer :: my_ik, ik_ibz, ik_forw, ik_back, ib, jb
2996 : : real(dp) :: eps, fact
2997 : : complex(dp) :: a_forw, a_back
2998 : : complex(dp) :: g_forw, g_back
2999 : : complex(dp) :: b, g0
3000 : : !arrays
3001 : : real(dp) :: kpt(3), qpt(3), kpq(3), kmq(3)
3002 : 4662 : complex(dp) :: ak(self%gqk%nb_k), akq(self%gqk%nb_kq), akmq(self%gqk%nb_kq), bq(self%gqk%my_npert)
3003 : 2331 : complex(dp), allocatable :: gq_gathered(:,:,:,:)
3004 : : !----------------------------------------------------------------------
3005 : :
3006 : 2331 : gqk => self%gqk
3007 : :
3008 : : !ABI_MALLOC(gq_gathered, (gqk%my_npert, gqk%nb_k, gqk%nb_k, gqk%glob_nk))
3009 : :
3010 : : ! Scattering-dependent part
3011 [ + + + + ]: 1072553 : self%my_grad(:, :) = zero
3012 : :
3013 : 2331 : fact = two * self%psign / real(self%nqbz, dp)
3014 : :
3015 [ + + ]: 285909 : do my_iq=1,gqk%my_nq
3016 [ + + ]: 1134312 : qpt(:) = self%my_qpts(:, my_iq)
3017 [ + + ]: 1985046 : bq(:) = self%my_b(:, my_iq, ip)
3018 : :
3019 : : ! Check if q=\Gamma
3020 : 353641 : q_gamma = .false.
3021 [ + + + + : 353641 : if (all(abs(qpt) < tol6)) q_gamma = .true.
+ + ]
3022 : :
3023 : : ! For this q, gather all the k-distributed matrix elements
3024 [ - + ]: 283578 : call gqk%gather("q", my_iq, gq_gathered)
3025 : :
3026 [ + + ]: 34403330 : do my_ik=1,gqk%my_nk
3027 [ + + ]: 133397294 : ak(:) = self%my_a(:,my_ik,ip)
3028 [ + + ]: 136479008 : kpt(:) = self%my_kpts(:, my_ik)
3029 : :
3030 : : ! Forward scattering
3031 : : ! Find k+q-->k' index in krank_kpts
3032 [ + + ]: 136479008 : kpq(:) = kpt(:) + qpt(:)
3033 : 34119752 : ik_forw = self%krank_kpts%get_index(kpq)
3034 : :
3035 : : ! If erange filter was used in gstore, some transitions are not valid
3036 [ + + ]: 34119752 : if (ik_forw /= -1) then
3037 [ + + ]: 130774998 : akq(:) = self%a_glob(:, ik_forw, ip)
3038 : :
3039 [ + + ]: 130774998 : do ib=1,gqk%nb_k
3040 : :
3041 [ + + ]: 424214762 : do jb=1,gqk%nb_kq
3042 : 293439764 : a_forw = akq(jb)
3043 : :
3044 [ + + ]: 2152044742 : do my_pert=1,gqk%my_npert
3045 : 1760638584 : b = bq(my_pert)
3046 : :
3047 : 1760638584 : g_forw = gqk%my_g(my_pert, jb, my_iq, ib, my_ik)
3048 : : ! Add long-range correction to matrix elements at Gamma
3049 : 1760638584 : g0 = self%my_g0(my_pert)
3050 [ + + ]: 1760638584 : if (q_gamma .and. (ib == jb)) then
3051 : 4808256 : g_forw = g_forw + g0
3052 : : endif
3053 : :
3054 : : self%my_grad(ib, my_ik) = &
3055 : 2054078348 : self%my_grad(ib, my_ik) + a_forw*b*conjg(g_forw)
3056 : :
3057 : : enddo
3058 : : enddo
3059 : : enddo
3060 : : endif ! Forward scattering
3061 : :
3062 : : ! Backward scattering
3063 : : ! Find k-q-->k' index in krank_kpts
3064 [ + + ]: 136479008 : kmq(:) = kpt(:) - qpt(:)
3065 : 34119752 : ik_back = self%krank_kpts%get_index(kmq)
3066 : :
3067 : : ! If erange filter was used in gstore, some transitions are not valid
3068 [ + + ]: 34403330 : if (ik_back /= -1) then
3069 [ + + ]: 130774998 : akmq(:) = self%a_glob(:, ik_back, ip)
3070 : :
3071 [ + + ]: 130774998 : do ib=1,gqk%nb_k
3072 : :
3073 [ + + ]: 424214762 : do jb=1,gqk%nb_kq
3074 : 293439764 : a_back = akmq(jb)
3075 : :
3076 [ + + ]: 2152044742 : do my_pert=1,gqk%my_npert
3077 : 1760638584 : b = bq(my_pert)
3078 : :
3079 : 1760638584 : g_back = gq_gathered(my_pert, ib, jb, ik_back)
3080 : : ! Add long-range correction to matrix elements at Gamma
3081 : 1760638584 : g0 = self%my_g0(my_pert)
3082 [ + + ]: 1760638584 : if (q_gamma .and. (ib == jb)) then
3083 : 4808256 : g_back = g_back + g0
3084 : : endif
3085 : :
3086 : : self%my_grad(ib, my_ik) = &
3087 : 2054078348 : self%my_grad(ib, my_ik) + a_back*conjg(b)*g_back
3088 : :
3089 : : enddo
3090 : : enddo
3091 : : enddo
3092 : : endif ! Backward scattering
3093 : :
3094 : : enddo
3095 : :
3096 [ - + ]: 285909 : ABI_FREE(gq_gathered)
3097 : : enddo
3098 : 2331 : call xmpi_sum(self%my_grad, gqk%qpt_pert_comm%value, ierr)
3099 : : self%my_grad(:, :) = &
3100 [ + + + + ]: 1072553 : -two/(real(self%nkbz, dp)*real(self%nqbz, dp)) * self%my_grad(:, :)
3101 : :
3102 : : ! Scattering-independent part
3103 : 2331 : eps = self%enterms(4, ip)
3104 [ + + ]: 271177 : do my_ik=1,gqk%my_nk
3105 : 268846 : ik_ibz = gqk%my_k2ibz(1, my_ik)
3106 [ + + ]: 1070222 : ak(:) = self%my_a(:, my_ik, ip)
3107 : :
3108 [ + + ]: 1072553 : do ib=1,gqk%nb_k
3109 : : self%my_grad(ib, my_ik) = self%my_grad(ib, my_ik) + &
3110 : 1070222 : two/self%nkbz * (self%eig(ib, ik_ibz) - eps) * self%my_a(ib, my_ik, ip)
3111 : :
3112 : : enddo
3113 : : enddo
3114 : :
3115 : : ! Here we're actually changing the gradient to the steepest descent direction
3116 : : ! A bit messy but i dont want to make another array called "forces" or something
3117 : : !self%my_grad(:,:) = -self%my_grad(:,:)
3118 : :
3119 : : !ABI_FREE(gq_gathered)
3120 : :
3121 [ - + ]: 2331 : if (self%efilter > zero) call self%filter("grad", ip)
3122 : :
3123 [ - + ]: 2331 : end subroutine polstate_calc_grad
3124 : : !!***
3125 : :
3126 : : !----------------------------------------------------------------------
3127 : :
3128 : : !!****f* m_varpeq/polstate_localize
3129 : : !! NAME
3130 : : !! polstate_localize
3131 : : !!
3132 : : !! FUNCTION
3133 : : !! Calculate vibrational coefficients, polaron energy terms and polaron energy
3134 : : !! level at a current state.
3135 : : !!
3136 : : !! INPUTS
3137 : : !! ip=Index of a polaronic state.
3138 : : !! alpha=Mixing factor.
3139 : : !! fix_displ [optional]=if .true., DO NOT update the phonon vector B_\qnu.
3140 : : !! Relevant for hopping calculations. Defaults to. False.
3141 : : !!
3142 : : !! OUTPUT
3143 : : !!
3144 : : !! SOURCE
3145 : :
3146 : 2331 : subroutine polstate_localize(self, ip, alpha, fix_displ)
3147 : :
3148 : : !Arguments ------------------------------------
3149 : : class(polstate_t), intent(inout) :: self
3150 : : integer, intent(in) :: ip
3151 : : real(dp), intent(in) :: alpha
3152 : : logical, optional, intent(in) :: fix_displ
3153 : : !----------------------------------------------------------------------
3154 : :
3155 : : ! Calculation of B_qnu requires globally available A_nk
3156 : 2331 : call self%gather("a", ip)
3157 : :
3158 : : ! We skip B calculation ONLY if the fix_displ is present and .true.
3159 [ + - + + ]: 2331 : if (.not. (present(fix_displ) .and. fix_displ)) then
3160 : 316 : call self%calc_b_from_a(ip)
3161 : : end if
3162 : :
3163 : : ! Mixing the previous & current vectors of vibrational coefficients
3164 [ + + ]: 2331 : if (self%has_prev_grad(ip)) then
3165 [ + + + + ]: 1971713 : self%my_b(:,:, ip) = (one - alpha)*self%my_b(:,:, ip) + alpha*self%my_prev_b(:,:)
3166 : : end if
3167 [ + + + + ]: 1987377 : self%my_prev_b(:,:) = self%my_b(:,:, ip)
3168 : :
3169 : : ! Electronic term
3170 : 2331 : self%enterms(1, ip) = self%get_enel(ip)
3171 : : ! Vibrational term
3172 : 2331 : self%enterms(2, ip) = self%get_enph(ip)
3173 : : ! Electron-phonon term
3174 : 2331 : self%enterms(3, ip) = self%get_enelph(ip)
3175 : : ! Polaron energy level
3176 : 2331 : self%enterms(4, ip) = self%enterms(1, ip) + self%enterms(3, ip)
3177 : :
3178 : 2331 : end subroutine polstate_localize
3179 : : !!***
3180 : :
3181 : : !----------------------------------------------------------------------
3182 : :
3183 : : !!****f* m_varpeq/polstate_get_enelph
3184 : : !! NAME
3185 : : !! polstate_get_enelph
3186 : : !!
3187 : : !! FUNCTION
3188 : : !! Returns the electron-phonon term of the polaron bidning energy at a specified
3189 : : !! polaronic state.
3190 : : !!
3191 : : !! INPUTS
3192 : : !! ip=Index of a polaronic state.
3193 : : !!
3194 : : !! OUTPUT
3195 : : !! enelph=Electron-phonon term of the polaron binding energy.
3196 : : !!
3197 : : !! SOURCE
3198 : :
3199 : 2331 : real(dp) function polstate_get_enelph(self, ip) result(enelph)
3200 : :
3201 : : !Arguments ------------------------------------
3202 : : class(polstate_t), intent(inout) :: self
3203 : : integer, intent(in) :: ip
3204 : :
3205 : : !Local variables-------------------------------
3206 : : !scalars
3207 : : class(gqk_t), pointer :: gqk
3208 : : logical :: q_gamma
3209 : : integer :: ierr, my_iq, my_pert, my_ik, ik_forw, ib, jb
3210 : : complex(dp) :: a_from, a_forw, g_forw, g0, b
3211 : : !arrays
3212 : : real(dp) :: kpt(3), qpt(3), kpq(3)
3213 : 4662 : complex(dp) :: ak(self%gqk%nb_k), akq(self%gqk%nb_kq), bq(self%gqk%my_npert)
3214 : : !----------------------------------------------------------------------
3215 : :
3216 : 2331 : gqk => self%gqk
3217 : :
3218 : 2331 : enelph = zero
3219 [ + + ]: 271177 : do my_ik=1,gqk%my_nk
3220 [ + + ]: 1075384 : kpt(:) = self%my_kpts(:, my_ik)
3221 [ + + ]: 1070222 : ak(:) = self%my_a(:, my_ik, ip)
3222 : :
3223 [ + + ]: 34390929 : do my_iq=1,gqk%my_nq
3224 [ + + ]: 136479008 : qpt(:) = self%my_qpts(:, my_iq)
3225 : :
3226 : : ! Find k+q-->k' index in krank_kpts
3227 [ + + ]: 136479008 : kpq(:) = kpt(:) + qpt(:)
3228 : 34119752 : ik_forw = self%krank_kpts%get_index(kpq)
3229 : : ! If erange filter was used in gstore, some transitions are not valid
3230 [ + + ]: 34119752 : if (ik_forw == -1) cycle
3231 : :
3232 : : ! Check if q=\Gamma
3233 : 40994230 : q_gamma = .false.
3234 [ + + + + : 40994230 : if (all(abs(qpt) < tol6)) q_gamma = .true.
+ + ]
3235 : :
3236 [ + + ]: 130774998 : akq(:) = self%a_glob(:, ik_forw, ip)
3237 [ + + ]: 229660228 : bq(:) = self%my_b(:, my_iq, ip)
3238 : :
3239 [ + + ]: 131043844 : do ib=1,gqk%nb_k
3240 : 97966394 : a_from = ak(ib)
3241 : :
3242 [ + + ]: 425525910 : do jb=1,gqk%nb_kq
3243 : 293439764 : a_forw = akq(jb)
3244 : :
3245 [ + + ]: 2152044742 : do my_pert=1,gqk%my_npert
3246 : 1760638584 : b = bq(my_pert)
3247 : :
3248 : 1760638584 : g_forw = gqk%my_g(my_pert, jb, my_iq, ib, my_ik)
3249 : : ! Add long-range correction to matrix elements at Gamma
3250 : 1760638584 : g0 = self%my_g0(my_pert)
3251 [ + + ]: 1760638584 : if (q_gamma .and. (ib == jb)) then
3252 : 4808256 : g_forw = g_forw + g0
3253 : : endif
3254 : :
3255 : 2054078348 : enelph = enelph + real(a_from*conjg(b)*g_forw*conjg(a_forw), dp)
3256 : : enddo
3257 : : enddo
3258 : : enddo
3259 : :
3260 : : enddo
3261 : : enddo
3262 : 2331 : call xmpi_sum(enelph, gqk%comm%value, ierr)
3263 : 2331 : enelph = -two*enelph/(one*self%nkbz*self%nqbz)
3264 : :
3265 : 2331 : end function polstate_get_enelph
3266 : : !!***
3267 : :
3268 : : !----------------------------------------------------------------------
3269 : :
3270 : : !!****f* m_varpeq/polstate_get_enph
3271 : : !! NAME
3272 : : !! polstate_get_enph
3273 : : !!
3274 : : !! FUNCTION
3275 : : !! Returns the vibrational term of the polaron bidning energy at a specified
3276 : : !! polaronic state.
3277 : : !!
3278 : : !! INPUTS
3279 : : !! ip=Index of a polaronic state.
3280 : : !!
3281 : : !! OUTPUT
3282 : : !! enph=Vibrational term of the polaron binding energy.
3283 : : !!
3284 : : !! SOURCE
3285 : :
3286 : 4662 : real(dp) function polstate_get_enph(self, ip) result(enph)
3287 : :
3288 : : !Arguments ------------------------------------
3289 : : class(polstate_t), intent(inout) :: self
3290 : : integer, intent(in) :: ip
3291 : :
3292 : : !Local variables-------------------------------
3293 : : class(gqk_t), pointer :: gqk
3294 : : integer :: ierr, my_iq, my_pert
3295 : : !----------------------------------------------------------------------
3296 : :
3297 : 2331 : gqk => self%gqk
3298 : :
3299 : 2331 : enph = zero
3300 [ + + ]: 285909 : do my_iq=1,gqk%my_nq
3301 [ + + ]: 1987377 : do my_pert=1,gqk%my_npert
3302 : : enph = enph + &
3303 : 1985046 : gqk%my_wnuq(my_pert, my_iq)*abs(self%my_b(my_pert, my_iq, ip))**2
3304 : : enddo
3305 : : enddo
3306 : 2331 : call xmpi_sum(enph, gqk%qpt_pert_comm%value, ierr)
3307 : 2331 : enph = enph/real(self%nqbz, dp)
3308 : :
3309 : 2331 : end function polstate_get_enph
3310 : : !!***
3311 : :
3312 : : !----------------------------------------------------------------------
3313 : :
3314 : : !!****f* m_varpeq/polstate_get_enel
3315 : : !! NAME
3316 : : !! polstate_get_enel
3317 : : !!
3318 : : !! FUNCTION
3319 : : !! Returns the electronic term of the polaron bidning energy at a specified
3320 : : !! polaronic state.
3321 : : !!
3322 : : !! INPUTS
3323 : : !! ip=Index of a polaronic state.
3324 : : !!
3325 : : !! OUTPUT
3326 : : !! enel=Electronic term of the polaron binding energy.
3327 : : !!
3328 : : !! SOURCE
3329 : :
3330 : 4662 : real(dp) function polstate_get_enel(self, ip) result(enel)
3331 : :
3332 : : !Arguments ------------------------------------
3333 : : class(polstate_t), intent(inout) :: self
3334 : : integer, intent(in) :: ip
3335 : :
3336 : : !Local variables-------------------------------
3337 : : class(gqk_t), pointer :: gqk
3338 : : integer :: ierr, my_ik, ik_ibz, ib
3339 : :
3340 : : !----------------------------------------------------------------------
3341 : :
3342 : 2331 : gqk => self%gqk
3343 : :
3344 : 2331 : enel = zero
3345 [ + + ]: 271177 : do my_ik=1,gqk%my_nk
3346 : 268846 : ik_ibz = gqk%my_k2ibz(1, my_ik)
3347 [ + + ]: 1072553 : do ib=1,gqk%nb_k
3348 : 1070222 : enel = enel + self%eig(ib, ik_ibz)*abs(self%my_a(ib, my_ik, ip))**2
3349 : : enddo
3350 : : enddo
3351 : 2331 : call xmpi_sum(enel, gqk%kpt_comm%value, ierr)
3352 : 2331 : enel = enel/self%nkbz
3353 : :
3354 : 2331 : end function polstate_get_enel
3355 : : !!***
3356 : :
3357 : : !----------------------------------------------------------------------
3358 : :
3359 : : !!****f* m_varpeq/polstate_calc_b_from_a
3360 : : !! NAME
3361 : : !! polstate_calc_b_from_a
3362 : : !!
3363 : : !! FUNCTION
3364 : : !! Calculate vibrational coefficients B_q\nu at the current configuration,
3365 : : !! so the energy gradient wrt B_q\nu is 0.
3366 : : !!
3367 : : !! INPUTS
3368 : : !! ip=Index of a polaronic state.
3369 : : !!
3370 : : !! OUTPUT
3371 : : !!
3372 : : !! SOURCE
3373 : :
3374 : 316 : subroutine polstate_calc_b_from_a(self, ip)
3375 : :
3376 : : !Arguments ------------------------------------
3377 : : class(polstate_t), intent(inout) :: self
3378 : : integer, intent(in) :: ip
3379 : :
3380 : : !Local variables-------------------------------
3381 : : !scalars
3382 : : class(gqk_t), pointer :: gqk
3383 : : logical :: q_gamma
3384 : : integer :: ierr, my_iq, my_pert, my_ik, ik_forw, ib, jb, ik_ibz, pert_glob
3385 : : real(dp) :: wqnu
3386 : : complex(dp) :: a_from, a_forw, g_forw, g0, b_tmp
3387 : : !arrays
3388 : : real(dp) :: qpt(3), kpq(3)
3389 : 632 : complex(dp) :: ak(self%gqk%nb_k), akq(self%gqk%nb_kq)
3390 : : !----------------------------------------------------------------------
3391 : :
3392 : 316 : gqk => self%gqk
3393 : :
3394 [ + + ]: 32019 : do my_iq=1,gqk%my_nq
3395 [ + + ]: 126812 : qpt(:) = self%my_qpts(:, my_iq)
3396 : : ! Check if q=\Gamma
3397 : 39301 : q_gamma = .false.
3398 [ + + + + : 39301 : if (all(abs(qpt) < tol6)) q_gamma = .true.
+ + ]
3399 : :
3400 [ + + ]: 222237 : do my_pert=1,gqk%my_npert
3401 : 190218 : pert_glob = gqk%my_pert_start + my_pert - 1
3402 : :
3403 : 190218 : wqnu = gqk%my_wnuq(my_pert, my_iq)
3404 : :
3405 : : ! Skip acoustic modes at Gamma
3406 [ + + ]: 190218 : if (wqnu < EPHTK_WTOL) then
3407 : 948 : self%my_b(my_pert, my_iq, ip) = zero
3408 : 948 : cycle
3409 : : endif
3410 : 189270 : g0 = self%my_g0(my_pert)
3411 : :
3412 : : ! For this q and perturbation, calculate linear B_q\nu sum
3413 : 189270 : b_tmp = zero
3414 [ + + ]: 15950619 : do my_ik=1,self%gqk%my_nk
3415 : : ! Find k+q-->k' index in krank_kpts
3416 [ + + ]: 63045396 : kpq(:) = qpt(:) + self%my_kpts(:, my_ik)
3417 : 15761349 : ik_forw = self%krank_kpts%get_index(kpq)
3418 : : ! If erange filter was used in gstore, some transitions are not valid
3419 [ + + ]: 15761349 : if (ik_forw == -1) cycle
3420 : :
3421 : 7894461 : ik_ibz = gqk%my_k2ibz(1, my_ik)
3422 : :
3423 [ + + ]: 28836822 : ak(:) = self%my_a(:, my_ik, ip)
3424 [ + + ]: 28836822 : akq(:) = self%a_glob(:, ik_forw, ip)
3425 : :
3426 [ + + ]: 29026092 : do ib=1,gqk%nb_k
3427 : 20942361 : a_from = ak(ib)
3428 : :
3429 [ + + ]: 96789771 : do jb=1,gqk%nb_kq
3430 : 60086061 : a_forw = akq(jb)
3431 : :
3432 : 60086061 : g_forw = gqk%my_g(my_pert, jb, my_iq, ib, my_ik)
3433 : : ! Add long-range correction to matrix elements at Gamma
3434 [ + + ]: 60086061 : if (q_gamma .and. (ib == jb)) then
3435 : 137253 : g_forw = g_forw + g0
3436 : : endif
3437 : :
3438 : 81028422 : b_tmp = b_tmp + a_from*g_forw*conjg(a_forw)
3439 : :
3440 : : enddo
3441 : : enddo
3442 : : enddo
3443 : 189270 : call xmpi_sum(b_tmp, gqk%kpt_comm%value, ierr)
3444 : :
3445 : 189270 : b_tmp = b_tmp / (real(self%nkbz, dp) * wqnu)
3446 : :
3447 : 220973 : self%my_b(my_pert, my_iq, ip) = b_tmp
3448 : : enddo
3449 : : enddo
3450 : :
3451 : 316 : end subroutine polstate_calc_b_from_a
3452 : : !!***
3453 : :
3454 : : !----------------------------------------------------------------------
3455 : :
3456 : : !!****f* m_varpeq/polstate_calc_b_from_displ
3457 : : !! NAME
3458 : : !! polstate_calc_b_from_displ
3459 : : !!
3460 : : !! FUNCTION
3461 : : !! Calculate vibrational coefficients B_q\nu from a set of atomic
3462 : : !! displacements.
3463 : : !!
3464 : : !! INPUTS
3465 : : !! ip=Index of a polaronic state.
3466 : : !! scell<supercell_type>=Supercell data structure.
3467 : : !! cryst<crystal_type>=Crystal data structure.
3468 : : !!
3469 : : !! OUTPUT
3470 : : !!
3471 : : !! SOURCE
3472 : :
3473 : 0 : subroutine polstate_calc_b_from_displ(self, ip, scell, cryst)
3474 : :
3475 : : !Arguments ------------------------------------
3476 : : class(polstate_t), intent(inout) :: self
3477 : : integer, intent(in) :: ip
3478 : : class(supercell_type), intent(in) :: scell
3479 : : class(crystal_t), intent(in) :: cryst
3480 : :
3481 : : !Local variables-------------------------------
3482 : : !scalars
3483 : : class(gqk_t), pointer :: gqk
3484 : : integer :: iatom_sc, iatom_uc, typat, idir
3485 : : integer :: my_iq, my_pert
3486 : : real(dp) :: wqnu, phdispl_re, phdispl_im, amass, dtau
3487 : : complex(dp) :: bqnu_tmp, my_phdispl, cphase
3488 : : !arrays
3489 : : integer :: cell_vec(3)
3490 : : real(dp) :: qpt(3)
3491 : :
3492 : : !----------------------------------------------------------------------
3493 : :
3494 : 0 : gqk => self%gqk
3495 : :
3496 : : ! loop over q-vectors and perturbations
3497 [ # # ]: 0 : do my_iq=1,gqk%my_nq
3498 [ # # ]: 0 : qpt(:) = self%my_qpts(:, my_iq)
3499 : :
3500 [ # # ]: 0 : do my_pert=1,gqk%my_npert
3501 : 0 : wqnu = gqk%my_wnuq(my_pert, my_iq)
3502 : :
3503 : 0 : bqnu_tmp = zero
3504 : : ! loop over ALL atoms in the supercell & cartesian directions
3505 [ # # ]: 0 : do iatom_sc=1,scell%natom
3506 : 0 : iatom_uc = scell%atom_indexing(iatom_sc)
3507 : 0 : typat = scell%typat(iatom_sc)
3508 [ # # ]: 0 : cell_vec(:) = scell%uc_indexing(:, iatom_sc)
3509 : :
3510 [ # # ]: 0 : cphase = exp(j_dpc * two_pi * dot_product(qpt, cell_vec))
3511 : 0 : amass = cryst%amu(typat) * amu_emass
3512 : :
3513 [ # # ]: 0 : do idir=1,3
3514 : 0 : phdispl_re = gqk%my_displ_cart(1, idir, iatom_uc, my_pert, my_iq)
3515 : 0 : phdispl_im = gqk%my_displ_cart(2, idir, iatom_uc, my_pert, my_iq)
3516 : 0 : my_phdispl = phdispl_re + j_dpc * phdispl_im
3517 : :
3518 : 0 : dtau = self%displ(idir, iatom_sc, ip)
3519 : :
3520 : 0 : bqnu_tmp = bqnu_tmp + amass * my_phdispl * cphase * dtau
3521 : :
3522 : : enddo
3523 : : enddo
3524 : 0 : bqnu_tmp = -bqnu_tmp * sqrt(wqnu) * sqrthalf
3525 : :
3526 : 0 : self%my_b(my_pert, my_iq, ip) = bqnu_tmp
3527 : :
3528 : : enddo
3529 : : enddo
3530 : :
3531 : 0 : end subroutine polstate_calc_b_from_displ
3532 : : !!***
3533 : :
3534 : : !----------------------------------------------------------------------
3535 : :
3536 : : !!****f* m_varpeq/polstate_calc_displ_from_b
3537 : : !! NAME
3538 : : !! polstate_calc_displ_from_b
3539 : : !!
3540 : : !! FUNCTION
3541 : : !! Calculate atomic displacements from a set of vibrational
3542 : : !! coefficients B_q\nu.
3543 : : !!
3544 : : !! INPUTS
3545 : : !! ip=Index of a polaronic state.
3546 : : !! scell<supercell_type>=Supercell data structure.
3547 : : !!
3548 : : !! OUTPUT
3549 : : !!
3550 : : !! SOURCE
3551 : :
3552 : 0 : subroutine polstate_calc_displ_from_b(self, ip, scell)
3553 : :
3554 : : !Arguments ------------------------------------
3555 : : class(polstate_t), intent(inout) :: self
3556 : : integer, intent(in) :: ip
3557 : : class(supercell_type), intent(in) :: scell
3558 : :
3559 : : !Local variables-------------------------------
3560 : : !scalars
3561 : : class(gqk_t), pointer :: gqk
3562 : : integer :: ierr
3563 : : integer :: iatom_sc, iatom_uc, idir
3564 : : integer :: my_iq, my_pert
3565 : : real(dp) :: wqnu, phdispl_re, phdispl_im
3566 : : complex(dp) :: bqnu, my_phdispl, cphase
3567 : : !arrays
3568 : : integer :: cell_vec(3)
3569 : : real(dp) :: qpt(3)
3570 : :
3571 : : !----------------------------------------------------------------------
3572 : :
3573 : 0 : gqk => self%gqk
3574 : :
3575 [ # # # # ]: 0 : self%displ(:,:,ip) = zero
3576 : :
3577 : : ! loop over q-vectors and perturbations
3578 [ # # ]: 0 : do my_iq=1,gqk%my_nq
3579 [ # # ]: 0 : qpt(:) = self%my_qpts(:, my_iq)
3580 : :
3581 [ # # ]: 0 : do my_pert=1,gqk%my_npert
3582 : 0 : wqnu = gqk%my_wnuq(my_pert, my_iq)
3583 : :
3584 : : ! Skip acoustic modes at Gamma
3585 [ # # ]: 0 : if (abs(wqnu) < tol12) cycle
3586 : :
3587 : 0 : bqnu = self%my_b(my_pert, my_iq, ip)
3588 : :
3589 : : ! loop over ALL atoms in the supercell & cartesian directions
3590 [ # # ]: 0 : do iatom_sc=1,scell%natom
3591 : 0 : iatom_uc = scell%atom_indexing(iatom_sc)
3592 [ # # ]: 0 : cell_vec(:) = scell%uc_indexing(:, iatom_sc)
3593 : :
3594 [ # # ]: 0 : cphase = exp(j_dpc * two_pi * dot_product(qpt, cell_vec))
3595 : :
3596 [ # # ]: 0 : do idir=1,3
3597 : 0 : phdispl_re = gqk%my_displ_cart(1, idir, iatom_uc, my_pert, my_iq)
3598 : 0 : phdispl_im = gqk%my_displ_cart(2, idir, iatom_uc, my_pert, my_iq)
3599 : 0 : my_phdispl = phdispl_re + j_dpc * phdispl_im
3600 : :
3601 : : self%displ(idir, iatom_sc, ip) = self%displ(idir, iatom_sc, ip) + &
3602 : 0 : conjg(bqnu) * my_phdispl * cphase / sqrt(wqnu)
3603 : :
3604 : : enddo
3605 : : enddo
3606 : : enddo
3607 : : enddo
3608 : :
3609 : 0 : call xmpi_sum(self%displ(:,:,ip), gqk%qpt_pert_comm%value, ierr)
3610 [ # # # # ]: 0 : self%displ(:,:,ip) = -sqrt2 / self%nqbz * self%displ(:,:,ip)
3611 : :
3612 : 0 : end subroutine polstate_calc_displ_from_b
3613 : : !!***
3614 : :
3615 : : !----------------------------------------------------------------------
3616 : :
3617 : : !!****f* m_varpeq/calc_clb_displ
3618 : : !! NAME
3619 : : !! calc_clb_displ
3620 : : !!
3621 : : !! FUNCTION
3622 : : !! Calculate Coulomb displacements introduced by a unit charge localized
3623 : : !! on a supercell atom
3624 : : !! Note that internally it is assumed that the localized charge is negative,
3625 : : !! regargdless of the polaron type. However, for hole polaron, the displacements
3626 : : !! are filpped at post-processing and hence physically correct.
3627 : : !!
3628 : : !! INPUTS
3629 : : !! atloc=Index of an atom where charge is localized.
3630 : : !! chrgat(natom)=Charge of the atoms.
3631 : : !! scell<supercell_type>=Supercell data structure.
3632 : : !! cryst<crystal_t>=Crystal data structure.
3633 : : !!
3634 : : !! OUTPUT
3635 : : !!
3636 : : !! SOURCE
3637 : :
3638 : 0 : subroutine polstate_calc_clb_displ(self, atloc, chrgat, scell, cryst)
3639 : :
3640 : : !Arguments ------------------------------------
3641 : : class(polstate_t), intent(inout) :: self
3642 : : integer, intent(in) :: atloc
3643 : : class(supercell_type), intent(in) :: scell
3644 : : class(crystal_t), intent(in) :: cryst
3645 : : real(dp), intent(in) :: chrgat(scell%natom_primcell)
3646 : :
3647 : : !Local variables-------------------------------
3648 : : !scalars
3649 : : integer :: ip, ii, ix, iy, iz, iatom_sc, iatom_uc
3650 : : !arrays
3651 : : integer :: sc_ind(3)
3652 : : integer :: box_dim(3), center_sc(3), vec(3)
3653 : : real(dp) :: rdist(3), center_atom(3)
3654 : 0 : integer, allocatable :: scell_flag(:,:,:)
3655 : 0 : real(dp), allocatable :: scell_displ(:,:,:,:,:)
3656 : :
3657 : : !----------------------------------------------------------------------
3658 : :
3659 : : ! supercell center
3660 [ # # ]: 0 : center_sc(:) = (self%ngkpt(:) + 1) / 2
3661 : : ! select atom in the unit cell
3662 [ # # ]: 0 : center_atom(:) = cryst%xcart(:, atloc)
3663 : :
3664 : : ! displacement box dimensions
3665 [ # # ]: 0 : do ii=1,3
3666 : 0 : box_dim(ii) = min(3, self%ngkpt(ii))
3667 : : enddo
3668 : :
3669 [ # # # # : 0 : ABI_MALLOC(scell_displ, (3, cryst%natom, self%ngkpt(1), self%ngkpt(2), self%ngkpt(3)))
# # # # #
# # # # #
# # # # #
# # # #
# ]
3670 [ # # # # : 0 : ABI_MALLOC(scell_flag, (self%ngkpt(1), self%ngkpt(2), self%ngkpt(3)))
# # # # #
# # # # #
# # # # #
# ]
3671 [ # # # # : 0 : scell_flag(:,:,:) = zero
# # ]
3672 [ # # # # : 0 : scell_displ(:,:,:,:,:) = zero
# # # # #
# ]
3673 : :
3674 [ # # ]: 0 : do iz=1,box_dim(3)
3675 [ # # ]: 0 : do iy=1,box_dim(2)
3676 [ # # ]: 0 : do ix=1,box_dim(1)
3677 : : ! get all displacement vectors wrt centeral supercell
3678 : : vec(:) = [shift_(ix-1, box_dim(1)), &
3679 [ # # ]: 0 : shift_(iy-1, box_dim(2)), shift_(iz-1, box_dim(3))]
3680 : :
3681 : : ! get indices of related supercells
3682 [ # # ]: 0 : do ii=1,3
3683 : : ! add 1 becasue of fortran indexing
3684 : 0 : sc_ind(ii) = mod(center_sc(ii) + vec(ii) - 1, self%ngkpt(ii))
3685 : 0 : sc_ind(ii) = sc_ind(ii) + 1
3686 : : enddo
3687 : 0 : scell_flag(sc_ind(1), sc_ind(2), sc_ind(3)) = one
3688 : :
3689 : : ! calculate displacements in these supercells
3690 [ # # ]: 0 : do iatom_uc=1,cryst%natom
3691 : : rdist(:) = matmul(cryst%rprimd(:,:), vec(:)) + &
3692 [ # # # # : 0 : cryst%xcart(:,iatom_uc) - center_atom(:)
# # # # ]
3693 [ # # # # : 0 : if (norm2(rdist) > tol8) then
# # # # ]
3694 : : scell_displ(:,iatom_uc,sc_ind(1),sc_ind(2),sc_ind(3)) = &
3695 [ # # # # : 0 : -chrgat(iatom_uc) * rdist(:) / norm2(rdist)**3
# # # # ]
3696 : : endif
3697 : :
3698 : : enddo
3699 : :
3700 : : enddo
3701 : : enddo
3702 : : enddo
3703 : :
3704 [ # # # # : 0 : self%displ(:,:,:) = zero
# # ]
3705 : : ! insert displacements
3706 : 0 : ip = 1
3707 [ # # ]: 0 : do iatom_sc=1,scell%natom
3708 : 0 : iatom_uc = scell%atom_indexing(iatom_sc)
3709 : : ! add 1 becasue of fortran indexing
3710 [ # # ]: 0 : vec(:) = scell%uc_indexing(:, iatom_sc) + 1
3711 [ # # ]: 0 : if (scell_flag(vec(1), vec(2), vec(3)) /= 0) then
3712 [ # # ]: 0 : self%displ(:,iatom_sc,ip) = scell_displ(:,iatom_uc, vec(1), vec(2), vec(3))
3713 : : endif
3714 : : enddo
3715 [ # # ]: 0 : do ip=2,self%np
3716 [ # # ]: 0 : self%displ(:,iatom_sc,ip) = self%displ(:,iatom_sc,ip-1)
3717 : : enddo
3718 : :
3719 [ # # ]: 0 : ABI_FREE(scell_flag)
3720 [ # # ]: 0 : ABI_FREE(scell_displ)
3721 : :
3722 : : !----------------------------------------------------------------------
3723 : :
3724 : : contains
3725 : 0 : integer function shift_(x, n) result(x_shift)
3726 : : integer, intent(in) :: x, n
3727 : 0 : x_shift = x
3728 [ # # # # : 0 : if (x > n/2) x_shift = -n + x
# # ]
3729 : : end function shift_
3730 : :
3731 : : end subroutine polstate_calc_clb_displ
3732 : : !!***
3733 : :
3734 : : !----------------------------------------------------------------------
3735 : :
3736 : : !!****f* m_varpeq/polstate_calc_phgrad
3737 : : !! NAME
3738 : : !! polstate_calc_phgrad
3739 : : !!
3740 : : !! FUNCTION
3741 : : !! Calculate the gradient of the polaronic energy wrt phonon
3742 : : !! coefficients B_q\nu.
3743 : : !!
3744 : : !! INPUTS
3745 : : !! ip=Index of a polaronic state.
3746 : : !!
3747 : : !! OUTPUT
3748 : : !!
3749 : : !! SOURCE
3750 : :
3751 : 135 : subroutine polstate_calc_phgrad(self, ip)
3752 : :
3753 : : !Arguments ------------------------------------
3754 : : class(polstate_t), intent(inout) :: self
3755 : : integer, intent(in) :: ip
3756 : :
3757 : : !Local variables-------------------------------
3758 : : !scalars
3759 : : class(gqk_t), pointer :: gqk
3760 : : logical :: q_gamma
3761 : : integer :: ierr
3762 : : integer :: my_iq, my_pert
3763 : : integer:: my_ik, ik_forw, ib, jb
3764 : : real(dp) :: wqnu
3765 : : complex(dp) :: a_from, a_forw, g_forw, phgrad_tmp
3766 : : complex(dp) :: g0, b
3767 : : !arrays
3768 : : real(dp) :: qpt(3), kpq(3)
3769 : 270 : complex(dp) :: ak(self%gqk%nb_k), akq(self%gqk%nb_kq)
3770 : :
3771 : : !----------------------------------------------------------------------
3772 : :
3773 : 135 : gqk => self%gqk
3774 : :
3775 [ + + ]: 17010 : do my_iq=1,gqk%my_nq
3776 [ + + ]: 67500 : qpt(:) = self%my_qpts(:, my_iq)
3777 : : ! Check if q=\Gamma
3778 : 21060 : q_gamma = .false.
3779 [ + + + + : 21060 : if (all(abs(qpt) < tol6)) q_gamma = .true.
+ + ]
3780 : :
3781 [ + + ]: 118260 : do my_pert=1,gqk%my_npert
3782 : 101250 : b = self%my_b(my_pert, my_iq, ip)
3783 : 101250 : wqnu = gqk%my_wnuq(my_pert, my_iq)
3784 : 101250 : g0 = self%my_g0(my_pert)
3785 : :
3786 : : ! For this q and perturbation, calculate B_q\nu sum
3787 : 101250 : phgrad_tmp = zero
3788 : :
3789 [ + + ]: 12757500 : do my_ik=1,self%gqk%my_nk
3790 : : ! Find k+q-->k' index in krank_kpts
3791 [ + + ]: 50625000 : kpq(:) = qpt(:) + self%my_kpts(:, my_ik)
3792 : 12656250 : ik_forw = self%krank_kpts%get_index(kpq)
3793 : :
3794 : : ! If erange filter was used in gstore, some transitions are not valid
3795 [ + - ]: 12656250 : if (ik_forw == -1) cycle
3796 : :
3797 [ + + ]: 50625000 : ak(:) = self%my_a(:, my_ik, ip)
3798 [ + + ]: 50625000 : akq(:) = self%a_glob(:, ik_forw, ip)
3799 : :
3800 [ + + ]: 50726250 : do ib=1,gqk%nb_k
3801 : 37968750 : a_from = ak(ib)
3802 : :
3803 [ + + ]: 164531250 : do jb=1,gqk%nb_kq
3804 : 113906250 : a_forw = akq(jb)
3805 : :
3806 : 113906250 : g_forw = gqk%my_g(my_pert, jb, my_iq, ib, my_ik)
3807 : : ! Add long-range correction to matrix elements at Gamma
3808 [ + + ]: 113906250 : if (q_gamma .and. (ib == jb)) then
3809 : 303750 : g_forw = g_forw + g0
3810 : : endif
3811 : :
3812 : 151875000 : phgrad_tmp = phgrad_tmp + a_from*g_forw*conjg(a_forw)
3813 : : enddo
3814 : : enddo
3815 : : enddo
3816 : 101250 : call xmpi_sum(phgrad_tmp, gqk%kpt_comm%value, ierr)
3817 : :
3818 : : self%my_phgrad(my_pert, my_iq, ip) = &
3819 : 118125 : two/self%nqbz * (b*wqnu - phgrad_tmp / self%nkbz)
3820 : :
3821 : : enddo
3822 : : enddo
3823 : :
3824 : 135 : end subroutine polstate_calc_phgrad
3825 : : !!***
3826 : :
3827 : : !----------------------------------------------------------------------
3828 : :
3829 : : !!****f* m_varpeq/polstate_calc_hpol
3830 : : !! NAME
3831 : : !! polstate_calc_hpol
3832 : : !!
3833 : : !! FUNCTION
3834 : : !! Construct and calculate the polaron Hamiltonian, <A_bra|H_pol(B)|A_ket>
3835 : : !!
3836 : : !! INPUTS
3837 : : !! my_a_bra(gqk%nb_kq,gqk%my_nk)=Electronic coefficients for the bra vector
3838 : : !! a_bra_lglob(gqk%nb_kq,gqk%glob_nk)=Electronic coefficients for the bra vectors
3839 : : !! (global array)
3840 : : !! my_a_ket(gqk%nb_k,gqk%my_nk)=Electronic coefficients for the ket vector
3841 : : !! my_b(gqk%my_npert,gqk%my_nq)=Phonon coeffcients used to construct H_pol(B)
3842 : : !! Note that these arrays are MPI-distributed as in the polstate datatype
3843 : : !!
3844 : : !! OUTPUT
3845 : : !!
3846 : : !! SOURCE
3847 : :
3848 : 6588 : real(dp) function polstate_calc_hpol(self, my_a_bra, a_bra_glob, my_a_ket, my_b) &
3849 : : result(hpol)
3850 : :
3851 : : !Arguments ------------------------------------
3852 : : class(polstate_t), intent(inout) :: self
3853 : : complex(dp), intent(in) :: my_a_bra(self%gqk%nb_kq, self%gqk%my_nk)
3854 : : complex(dp), intent(in) :: a_bra_glob(self%gqk%nb_kq, self%gqk%glob_nk)
3855 : : complex(dp), intent(in) :: my_a_ket(self%gqk%nb_k, self%gqk%my_nk)
3856 : : complex(dp), intent(in) :: my_b(self%gqk%my_npert, self%gqk%my_nq)
3857 : :
3858 : : !Local variables-------------------------------
3859 : : !scalars
3860 : : class(gqk_t), pointer :: gqk
3861 : : logical :: q_gamma
3862 : : integer :: ierr, my_ik, ik_ibz, ib
3863 : : integer :: my_iq, my_pert, ik_forw, jb
3864 : : complex(dp) :: a_from, a_forw, g_forw, g0, b
3865 : : real(dp) :: h_el, h_elph
3866 : : !arrays
3867 : : real(dp) :: kpt(3), qpt(3), kpq(3)
3868 : 13176 : complex(dp) :: a_ket(self%gqk%nb_k), a_bra(self%gqk%nb_kq), bq(self%gqk%my_npert)
3869 : :
3870 : : !----------------------------------------------------------------------
3871 : :
3872 : 6588 : gqk => self%gqk
3873 : :
3874 : : ! <A_1|H_p(B)|A_2> = <A_1|H_el(B)|A_2> + <A_1|H_el-ph(B)|A_2>
3875 : :
3876 : : ! 1st term
3877 : 6588 : h_el = zero
3878 [ + + ]: 764151 : do my_ik=1,gqk%my_nk
3879 : 757563 : ik_ibz = gqk%my_k2ibz(1, my_ik)
3880 [ + + ]: 3021888 : do ib=1,gqk%nb_k
3881 : : h_el = h_el + &
3882 : 3015300 : conjg(my_a_bra(ib, my_ik))*self%eig(ib, ik_ibz)*my_a_ket(ib, my_ik)
3883 : : enddo
3884 : : enddo
3885 : 6588 : call xmpi_sum(h_el, gqk%kpt_comm%value, ierr)
3886 : 6588 : h_el = h_el/self%nkbz
3887 : :
3888 : : ! 2nd term
3889 : 6588 : h_elph = zero
3890 [ + + ]: 764151 : do my_ik=1,gqk%my_nk
3891 [ + + ]: 3030252 : kpt(:) = self%my_kpts(:, my_ik)
3892 [ + + ]: 3015300 : a_ket(:) = my_a_ket(:, my_ik)
3893 : :
3894 [ + + ]: 96930684 : do my_iq=1,gqk%my_nq
3895 [ + + ]: 384666132 : qpt(:) = self%my_qpts(:, my_iq)
3896 : :
3897 : : ! Find k+q-->k' index in krank_kpts
3898 [ + + ]: 384666132 : kpq(:) = kpt(:) + qpt(:)
3899 : 96166533 : ik_forw = self%krank_kpts%get_index(kpq)
3900 : : ! If erange filter was used in gstore, some transitions are not valid
3901 [ + + ]: 96166533 : if (ik_forw == -1) cycle
3902 : :
3903 : : ! Check if q=\Gamma
3904 : 115419480 : q_gamma = .false.
3905 [ + + + + : 115419480 : if (all(abs(qpt) < tol6)) q_gamma = .true.
+ + ]
3906 : :
3907 [ + + ]: 368144172 : a_bra(:) = a_bra_glob(:, ik_forw)
3908 [ + + ]: 646581075 : bq(:) = my_b(:, my_iq)
3909 : :
3910 [ + + ]: 368901735 : do ib=1,gqk%nb_k
3911 : 275775447 : a_from = a_ket(ib)
3912 : :
3913 [ + + ]: 1197937593 : do jb=1,gqk%nb_kq
3914 : 825995613 : a_forw = a_bra(jb)
3915 : :
3916 [ + + ]: 6057744738 : do my_pert=1,gqk%my_npert
3917 : 4955973678 : b = bq(my_pert)
3918 : :
3919 : 4955973678 : g_forw = gqk%my_g(my_pert, jb, my_iq, ib, my_ik)
3920 : : ! Add long-range correction to matrix elements at Gamma
3921 : 4955973678 : g0 = self%my_g0(my_pert)
3922 [ + + ]: 4955973678 : if (q_gamma .and. (ib == jb)) then
3923 : 13546422 : g_forw = g_forw + g0
3924 : : endif
3925 : :
3926 : 5781969291 : h_elph = h_elph + real(a_from*conjg(b)*g_forw*conjg(a_forw), dp)
3927 : : enddo
3928 : : enddo
3929 : : enddo
3930 : :
3931 : : enddo
3932 : : enddo
3933 : 6588 : call xmpi_sum(h_elph, gqk%comm%value, ierr)
3934 : 6588 : h_elph = -two*h_elph/(one*self%nkbz*self%nqbz)
3935 : :
3936 : 6588 : hpol = h_el + h_elph
3937 : :
3938 : 6588 : end function polstate_calc_hpol
3939 : : !!***
3940 : :
3941 : : !----------------------------------------------------------------------
3942 : :
3943 : : !!****f* m_varpeq/polstate_load_a
3944 : : !! NAME
3945 : : !! polstate_load_a
3946 : : !!
3947 : : !! FUNCTION
3948 : : !! Load the initial vector of electronic coefficients A_nk from source.
3949 : : !!
3950 : : !! INPUTS
3951 : : !! a_src(self%gqk%nb_k, self%gqk%glob_nk)=Global A_nk array to be loaded.
3952 : : !!
3953 : : !! OUTPUT
3954 : : !!
3955 : : !! SOURCE
3956 : :
3957 : 0 : subroutine polstate_load_a(self, a_src, ip)
3958 : :
3959 : : !Arguments ------------------------------------
3960 : : !scalars
3961 : : class(polstate_t), intent(inout) :: self
3962 : : integer, intent(in) :: ip
3963 : : !arrays
3964 : : complex(dp), intent(in) :: a_src(self%gqk%nb_k, self%gqk%glob_nk)
3965 : :
3966 : : !Local variables-------------------------------
3967 : : class(gqk_t), pointer :: gqk
3968 : : integer :: my_ik, ik_glob, ib
3969 : : !----------------------------------------------------------------------
3970 : :
3971 : 0 : gqk => self%gqk
3972 : :
3973 [ # # ]: 0 : do my_ik=1,gqk%my_nk
3974 : 0 : ik_glob = gqk%my_kstart + my_ik - 1
3975 [ # # ]: 0 : do ib=1,gqk%nb_k
3976 : 0 : self%my_a(ib, my_ik, ip) = a_src(ib, ik_glob)
3977 : : enddo
3978 : : enddo
3979 : :
3980 : 0 : end subroutine polstate_load_a
3981 : : !!***
3982 : :
3983 : : !----------------------------------------------------------------------
3984 : :
3985 : : !!****f* m_varpeq/polstate_load_b
3986 : : !! NAME
3987 : : !! polstate_load_b
3988 : : !!
3989 : : !! FUNCTION
3990 : : !! Load the initial vector of phonon coefficients B_q\nu from source.
3991 : : !!
3992 : : !! INPUTS
3993 : : !! b_src(self%gqk%natom3, self%gqk%glob_nq)=Global B_q\nu array to be loaded.
3994 : : !! ip=Index of a polaronic state.
3995 : : !! trvec(3) [optional]=Translational vector.
3996 : : !!
3997 : : !! OUTPUT
3998 : : !!
3999 : : !! SOURCE
4000 : :
4001 : 2 : subroutine polstate_load_b(self, b_src, ip, trvec)
4002 : :
4003 : : !Arguments ------------------------------------
4004 : : !scalars
4005 : : class(polstate_t), intent(inout) :: self
4006 : : integer, intent(in) :: ip
4007 : : !arrays
4008 : : complex(dp), intent(in) :: b_src(self%gqk%natom3, self%gqk%glob_nq)
4009 : : integer, optional, intent(in) :: trvec(3)
4010 : :
4011 : : !Local variables-------------------------------
4012 : : !scalars
4013 : : class(gqk_t), pointer :: gqk
4014 : : integer :: my_iq, my_pert, pert_glob, iq_glob
4015 : : complex(dp) :: cphase
4016 : : !arrays
4017 : : integer trvec_(3)
4018 : : real(dp) :: qpt(3)
4019 : :
4020 : : !----------------------------------------------------------------------
4021 : :
4022 : 2 : gqk => self%gqk
4023 : :
4024 : 2 : trvec_ (:) = 0
4025 [ + - ]: 2 : if (present(trvec)) trvec_(:) = trvec(:)
4026 : :
4027 [ + + ]: 252 : do my_iq=1,gqk%my_nq
4028 : 250 : iq_glob = gqk%my_qstart + my_iq - 1
4029 [ + + ]: 1000 : qpt(:) = self%my_qpts(:, my_iq)
4030 : :
4031 [ + + ]: 1000 : cphase = exp(+j_dpc * two_pi * dot_product(qpt, trvec_))
4032 : :
4033 [ + + ]: 1752 : do my_pert=1,gqk%my_npert
4034 : 1500 : pert_glob = gqk%my_pert_start + my_pert - 1
4035 : 1750 : self%my_b(my_pert, my_iq, ip) = b_src(pert_glob, iq_glob) * cphase
4036 : : enddo
4037 : : enddo
4038 : :
4039 : 2 : end subroutine polstate_load_b
4040 : : !!***
4041 : :
4042 : : !----------------------------------------------------------------------
4043 : :
4044 : : !!****f* m_varpeq/polstate_linterp_b
4045 : : !! NAME
4046 : : !! polstate_linterp_b
4047 : : !!
4048 : : !! FUNCTION
4049 : : !! Interpolate the phonon coefficients on uniform mesh between initial
4050 : : !! and final state.
4051 : : !!
4052 : : !! INPUTS
4053 : : !!
4054 : : !! OUTPUT
4055 : : !!
4056 : : !! SOURCE
4057 : :
4058 : 1 : subroutine polstate_linterp_b(self)
4059 : :
4060 : : !Arguments ------------------------------------
4061 : : class(polstate_t), intent(inout) :: self
4062 : :
4063 : : !Local variables-------------------------------
4064 : : !scalars
4065 : : class(gqk_t), pointer :: gqk
4066 : : integer :: ip, from_ip, to_ip
4067 : : !arrays
4068 : 2 : complex(dp) :: my_b_step(self%gqk%my_npert, self%gqk%my_nq)
4069 : :
4070 : : !----------------------------------------------------------------------
4071 : :
4072 : 1 : gqk => self%gqk
4073 : :
4074 : 1 : from_ip = 1; to_ip = self%np
4075 : :
4076 [ + + + + ]: 876 : my_b_step(:,:) = (self%my_b(:,:,to_ip) - self%my_b(:,:,from_ip)) / (self%np - one)
4077 : :
4078 [ + + ]: 8 : do ip=2,self%np-1
4079 [ + + + + ]: 6133 : self%my_b(:,:,ip) = self%my_b(:,:,ip-1) + my_b_step(:,:)
4080 : : enddo
4081 : :
4082 : 1 : end subroutine polstate_linterp_b
4083 : : !!***
4084 : :
4085 : : !----------------------------------------------------------------------
4086 : :
4087 : : !!****f* m_varpeq/polstate_redistr_b
4088 : : !! NAME
4089 : : !! polstate_redistr_b
4090 : : !!
4091 : : !! FUNCTION
4092 : : !! Redistribute the phonon coefficients B_\qnu with spline interpolation.
4093 : : !! Assumes parametrization [0,1] -> B_\qnu.
4094 : : !!
4095 : : !! INPUTS
4096 : : !!
4097 : : !! OUTPUT
4098 : : !!
4099 : : !! SOURCE
4100 : :
4101 : 15 : subroutine polstate_redistr_b(self, mesh_in, mesh_out, nimag)
4102 : :
4103 : : !Arguments ------------------------------------
4104 : : class(polstate_t), intent(inout) :: self
4105 : : integer, intent(in) :: nimag
4106 : : real(dp), intent(in) :: mesh_in(nimag)
4107 : : real(dp), intent(in) :: mesh_out(nimag)
4108 : :
4109 : : !Local variables-------------------------------
4110 : : !scalars
4111 : : class(gqk_t), pointer :: gqk
4112 : : integer :: from_ip, to_ip
4113 : : integer :: my_iq, my_pert
4114 : : complex(dp) :: phgrad_qnu_from, phgrad_qnu_to
4115 : : !arrays
4116 : 30 : complex(dp) :: my_b_mesh_in(nimag)
4117 : 30 : complex(dp) :: my_2der_mesh_out(nimag)
4118 : 30 : complex(dp) :: my_b_mesh_out(nimag)
4119 : :
4120 : : !----------------------------------------------------------------------
4121 : :
4122 : 15 : gqk => self%gqk
4123 : :
4124 : 15 : from_ip = 1; to_ip = self%np
4125 : :
4126 : : !call self%calc_phgrad(from_ip)
4127 : : !call self%calc_phgrad(to_ip)
4128 : :
4129 [ + + ]: 1890 : do my_iq=1,gqk%my_nq
4130 [ + + ]: 13140 : do my_pert=1,gqk%my_npert
4131 : :
4132 : : ! derivatives of the binding energy at endpoints
4133 : 11250 : phgrad_qnu_from = self%my_phgrad(my_pert, my_iq, from_ip)
4134 : 11250 : phgrad_qnu_to = self%my_phgrad(my_pert, my_iq, to_ip)
4135 : :
4136 [ + + ]: 112500 : my_b_mesh_in(:) = self%my_b(my_pert, my_iq, :)
4137 : :
4138 : : ! spline interpolation
4139 : : call spline_complex(mesh_in, my_b_mesh_in, nimag, phgrad_qnu_from, &
4140 : 11250 : phgrad_qnu_to, my_2der_mesh_out)
4141 : : call splint_complex(nimag, mesh_in, my_b_mesh_in, my_2der_mesh_out, nimag, &
4142 : 11250 : mesh_out, my_b_mesh_out)
4143 : :
4144 [ + + ]: 114375 : self%my_b(my_pert, my_iq, :) = my_b_mesh_out(:)
4145 : :
4146 : : enddo
4147 : : enddo
4148 : :
4149 : 15 : end subroutine polstate_redistr_b
4150 : : !!***
4151 : :
4152 : : !----------------------------------------------------------------------
4153 : :
4154 : : !!****f* m_varpeq/polstate_calc_eff_phforce
4155 : : !! NAME
4156 : : !! polstate_calc_eff_phforce
4157 : : !!
4158 : : !! FUNCTION
4159 : : !! Calculate the effective phonon force for the hopping optimization.
4160 : : !!
4161 : : !! INPUTS
4162 : : !! mode=Select the method for effective force calculation:
4163 : : !! "fw_euler" ---> Forward Euler method;
4164 : : !! "rk" ---> 4th order Runge-Kutta method.
4165 : : !! ip=Index of a polaronic state.
4166 : : !!
4167 : : !! OUTPUT
4168 : : !!
4169 : : !! SOURCE
4170 : :
4171 : 135 : subroutine polstate_calc_eff_phforce(self, mode, ip)
4172 : :
4173 : : !Arguments ------------------------------------
4174 : : class(polstate_t), intent(inout) :: self
4175 : : character(len=*), intent(in) :: mode
4176 : : integer, intent(in) :: ip
4177 : :
4178 : : !Local variables-------------------------------
4179 : : !scalars
4180 : : class(gqk_t), pointer :: gqk
4181 : : integer :: ii
4182 : : !arrays
4183 : : real(dp) :: rk_shifts(3) = [half, half, one]
4184 : 270 : complex(dp) :: my_b_copy(self%gqk%my_npert, self%gqk%my_nq)
4185 : 270 : complex(dp) :: rk_coeff(self%gqk%my_npert, self%gqk%my_nq, 4)
4186 : :
4187 : : !----------------------------------------------------------------------
4188 : :
4189 : 135 : gqk => self%gqk
4190 : :
4191 : 135 : call self%calc_phgrad(ip)
4192 : :
4193 : 135 : select case(mode)
4194 : : case ("fw_euler")
4195 [ + + + + ]: 118260 : self%my_eff_phforce(:,:,ip) = -self%my_phgrad(:,:,ip)
4196 : :
4197 : : case ("rk")
4198 : : ! Make a copy of current B_\qnu
4199 [ # # # # ]: 0 : my_b_copy(:,:) = self%my_b(:,:,ip)
4200 : :
4201 : : ! Calculate Runge-Kutta coefficients
4202 [ # # # # ]: 0 : rk_coeff(:,:,1) = self%my_phgrad(:,:,ip)
4203 : :
4204 [ # # ]: 0 : do ii=1,3
4205 [ # # # # ]: 0 : self%my_b(:,:,ip) = my_b_copy(:,:) + rk_shifts(ii) * rk_coeff(:,:,ii)
4206 : 0 : call self%calc_phgrad(ip)
4207 [ # # # # ]: 0 : rk_coeff(:,:,ii+1) = self%my_phgrad(:,:,ip)
4208 : : enddo
4209 : :
4210 : : self%my_eff_phforce(:,:,ip) = -sixth*(rk_coeff(:,:,1) + two*rk_coeff(:,:,2) + &
4211 [ # # # # ]: 0 : two*rk_coeff(:,:,3) + rk_coeff(:,:,4))
4212 : :
4213 : : ! Restore the gradient value
4214 [ # # # # ]: 0 : self%my_phgrad(:,:,ip) = rk_coeff(:,:,1)
4215 : :
4216 : : case default
4217 [ + - - ]: 135 : ABI_ERROR(sjoin("polstate_calc_eff_phforce, unsupported mode: ", mode))
4218 : : end select
4219 : :
4220 : 135 : end subroutine polstate_calc_eff_phforce
4221 : : !!***
4222 : :
4223 : : !----------------------------------------------------------------------
4224 : :
4225 : : !!****f* m_varpeq/polstate_calc_hop_timestep
4226 : : !! NAME
4227 : : !! polstate_calc_hop_timestep
4228 : : !!
4229 : : !! FUNCTION
4230 : : !! Calculate the optimal timestep for hopping optimization at this state.
4231 : : !!
4232 : : !! INPUTS
4233 : : !! ip=Index of a polaronic state.
4234 : : !!
4235 : : !! OUTPUT
4236 : : !!
4237 : : !! SOURCE
4238 : :
4239 : 7 : subroutine polstate_calc_hop_timestep(self, ip)
4240 : :
4241 : : !Arguments ------------------------------------
4242 : : class(polstate_t), intent(inout) :: self
4243 : : integer, intent(in) :: ip
4244 : :
4245 : : !Local variables-------------------------------
4246 : : !scalars
4247 : : class(gqk_t), pointer :: gqk
4248 : : logical :: q_gamma
4249 : : integer :: ierr
4250 : : integer :: my_iq, my_pert
4251 : : integer :: my_ik, ik_forw, ib, jb
4252 : : real(dp) :: wqnu
4253 : : real(dp) :: ts_denom, ts_num_ph, ts_num_elph
4254 : : complex(dp) :: a_from, a_forw
4255 : : complex(dp) :: g_forw, g0, phforce, b
4256 : : !arrays
4257 : : real(dp) :: kpt(3), qpt(3), kpq(3)
4258 : 14 : complex(dp) :: ak(self%gqk%nb_k), akq(self%gqk%nb_kq)
4259 : 14 : complex(dp) :: phforce_q(self%gqk%my_npert)
4260 : :
4261 : : !----------------------------------------------------------------------
4262 : :
4263 : 7 : gqk => self%gqk
4264 : :
4265 : 7 : ts_denom = zero
4266 : 7 : ts_num_ph = zero ! Phonon-dependent component of the numerator
4267 : :
4268 : : ! Phonon-dependent components
4269 [ + + ]: 882 : do my_iq=1,gqk%my_nq
4270 [ + + ]: 6132 : do my_pert=1,gqk%my_npert
4271 : 5250 : wqnu = gqk%my_wnuq(my_pert, my_iq)
4272 : 5250 : phforce = self%my_eff_phforce(my_pert, my_iq, ip)
4273 : 5250 : b = self%my_b(my_pert, my_iq, ip)
4274 : :
4275 : 5250 : ts_denom = ts_denom + wqnu*abs(phforce)**2
4276 : 6125 : ts_num_ph = ts_num_ph + wqnu*real(b*phforce, dp)
4277 : : enddo
4278 : : enddo
4279 : 7 : call xmpi_sum(ts_denom, gqk%qpt_pert_comm%value, ierr)
4280 : 7 : call xmpi_sum(ts_num_ph, gqk%qpt_pert_comm%value, ierr)
4281 : :
4282 : 7 : ts_num_elph = zero
4283 : : ! Scattering-dependent component of the numerator
4284 [ + + ]: 882 : do my_iq=1,gqk%my_nq
4285 [ + + ]: 3500 : qpt(:) = self%my_qpts(:, my_iq)
4286 [ + + ]: 6125 : phforce_q(:) = self%my_eff_phforce(:, my_iq, ip)
4287 : :
4288 : : ! Check if q=\Gamma
4289 : 1092 : q_gamma = .false.
4290 [ + + + + : 1092 : if (all(abs(qpt) < tol6)) q_gamma = .true.
+ + ]
4291 : :
4292 [ + + ]: 110257 : do my_ik=1,gqk%my_nk
4293 [ + + ]: 437500 : kpt(:) = self%my_kpts(:, my_ik)
4294 : :
4295 : : ! Find k+q-->k' index in krank_kpts
4296 [ + + ]: 437500 : kpq(:) = kpt(:) + qpt(:)
4297 : 109375 : ik_forw = self%krank_kpts%get_index(kpq)
4298 : : ! If erange filter was used in gstore, some transitions are not valid
4299 [ + - ]: 109375 : if (ik_forw == -1) cycle
4300 : :
4301 [ + + ]: 437500 : ak(:) = self%my_a(:, my_ik, ip)
4302 [ + + ]: 437500 : akq(:) = self%a_glob(:, ik_forw, ip)
4303 : :
4304 [ + + ]: 438375 : do ib=1,gqk%nb_k
4305 : 328125 : a_from = ak(ib)
4306 : :
4307 [ + + ]: 1421875 : do jb=1,gqk%nb_kq
4308 : 984375 : a_forw = akq(jb)
4309 : :
4310 [ + + ]: 7218750 : do my_pert=1,gqk%my_npert
4311 : 5906250 : phforce = phforce_q(my_pert)
4312 : 5906250 : g_forw = gqk%my_g(my_pert, jb, my_iq, ib, my_ik)
4313 : :
4314 : : ! Add long-range correction to matrix elements at Gamma
4315 : 5906250 : g0 = self%my_g0(my_pert)
4316 [ + + ]: 5906250 : if (q_gamma .and. (ib == jb)) then
4317 : 15750 : g_forw = g_forw + g0
4318 : : endif
4319 : :
4320 : : ts_num_elph = &
4321 : 6890625 : ts_num_elph + real(a_from*g_forw*conjg(phforce)*conjg(a_forw), dp)
4322 : :
4323 : : enddo
4324 : : enddo
4325 : : enddo
4326 : : enddo
4327 : : enddo
4328 : 7 : call xmpi_sum(ts_num_elph, gqk%comm%value, ierr)
4329 : 7 : ts_num_elph = ts_num_elph / self%nkbz
4330 : :
4331 : 7 : self%hop_ts(ip) = (ts_num_elph - ts_num_ph) / ts_denom
4332 : :
4333 : 7 : end subroutine polstate_calc_hop_timestep
4334 : : !!***
4335 : :
4336 : : !----------------------------------------------------------------------
4337 : :
4338 : : !!****f* m_varpeq/polstate_seed_a
4339 : : !! NAME
4340 : : !! polstate_seed_a
4341 : : !!
4342 : : !! FUNCTION
4343 : : !! Specify initial vector of electronic coefficients A_nk at runtime.
4344 : : !!
4345 : : !! INPUTS
4346 : : !! mode=Select the initialization type. Possible options:
4347 : : !! "gau_energy" ---> Gaussian shape based on the energy of electronic states;
4348 : : !! "gau_length" ---> Gaussian shape based on the polaron localization length;
4349 : : !! "even" ---> equal contribution from each electronic state;
4350 : : !! "random" ---> random initalization.
4351 : : !! ip=Index of a polaronic state.
4352 : : !! atloc [optional]=Index of an atom where charge is localized.
4353 : : !! chrgat(natom) [optional]=Charge of the atoms.
4354 : : !! scell<supercell_type> [optional]=Supercell data structure.
4355 : : !! cryst<crystal_t> [optional]=Crystal data structure.
4356 : : !! nstep_loc [optional]=Number of iterations for charge localization.
4357 : : !!
4358 : : !! OUTPUT
4359 : : !!
4360 : : !! SOURCE
4361 : :
4362 [ + - + - : 19 : subroutine polstate_seed_a(self, mode, ip, atloc, chrgat, scell, cryst, nstep_loc)
- + ]
4363 : :
4364 : : !Arguments ------------------------------------
4365 : : class(polstate_t), intent(inout) :: self
4366 : : character(len=*), intent(in) :: mode
4367 : : integer, intent(in) :: ip
4368 : : integer, optional, intent(in) :: atloc
4369 : : class(supercell_type), optional, intent(in) :: scell
4370 : : class(crystal_t), optional, intent(in) :: cryst
4371 : : real(dp), optional, intent(in) :: chrgat(:)
4372 : : integer, optional, intent(in) :: nstep_loc
4373 : :
4374 : : !Local variables-------------------------------
4375 : : class(gqk_t), pointer :: gqk
4376 : : logical :: flag
4377 : : integer :: ii, ierr
4378 : : real(dp) :: a_sqnorm, grad_sqnorm
4379 : : !----------------------------------------------------------------------
4380 : :
4381 : 19 : gqk => self%gqk
4382 : :
4383 : 38 : select case(mode)
4384 : : case ("gau_energy")
4385 : 19 : call gau_energy_()
4386 : : case ("gau_length")
4387 : 0 : call gau_length_()
4388 : : case ("random")
4389 : 0 : call random_()
4390 : : case ("localize")
4391 : : flag = (present(atloc) .and. present(chrgat) .and. present(scell) &
4392 [ # # # # : 0 : .and. present(cryst) .and. present(nstep_loc))
# # # # #
# # # ]
4393 : 0 : ABI_CHECK(flag, "polstate_seed_a: atloc, chrgat and scell are needed to localize")
4394 : :
4395 : : ! enforce Coulomb displacements
4396 [ # # # # : 0 : if (ip == 1) call self%calc_clb_displ(atloc, chrgat, scell, cryst)
# # # # #
# ]
4397 : :
4398 : : ! calcualte associated deformation field
4399 : 0 : call self%calc_b_from_displ(ip, scell, cryst)
4400 : :
4401 : : ! start with random charge distribution
4402 [ # # # # ]: 0 : self%my_a(:,:,ip) = one + j_dpc*one
4403 : :
4404 [ # # ]: 0 : if (self%efilter > zero) call self%filter("a", ip)
4405 : :
4406 : : ! then we do miniminzation with fixed displacements to localize charge distribution
4407 : 0 : a_sqnorm = self%get_sqnorm("a", ip)
4408 [ # # ]: 0 : if (a_sqnorm > tol12) then
4409 [ # # # # ]: 0 : self%my_a(:,:,ip) = sqrt(self%nkbz/a_sqnorm) * self%my_a(:,:,ip)
4410 : : endif
4411 : :
4412 [ # # ]: 0 : do ii=1,nstep_loc
4413 : 0 : call self%localize(ip, alpha=zero, fix_displ=.true.)
4414 : 0 : call self%calc_grad(ip)
4415 : 0 : grad_sqnorm = self%get_sqnorm("grad", ip)
4416 [ # # ]: 0 : if (sqrt(grad_sqnorm) < tol6) then
4417 : : exit
4418 : : endif
4419 : 0 : call self%update_pc(ip)
4420 : 0 : call self%calc_pcjgrad(ip,ii,nstep_ort=0)
4421 : 0 : call self%update_a(ip)
4422 : : enddo
4423 : :
4424 : : case ("even")
4425 [ # # # # ]: 0 : self%my_a(:,:,ip) = one + j_dpc*one
4426 : : case default
4427 [ + - - - : 19 : ABI_ERROR(sjoin("polstate_seed_a, unsupported mode: ", mode))
- - ]
4428 : : end select
4429 : :
4430 : : !----------------------------------------------------------------------
4431 : :
4432 : : contains
4433 : 19 : subroutine gau_energy_()
4434 : : real(dp) :: mu, sigma
4435 : : integer :: my_ik, ik_ibz, ib
4436 : : real(dp) :: eig
4437 : 19 : mu = self%gpr_energy(1); sigma = self%gpr_energy(2)
4438 [ - + ]: 19 : ABI_CHECK(sigma /= 0, "gpr_energy: standard deviation must be non-zero")
4439 [ + + ]: 1746 : do my_ik=1,gqk%my_nk
4440 : 1727 : ik_ibz = gqk%my_k2ibz(1, my_ik)
4441 [ + + ]: 6749 : do ib=1,gqk%nb_k
4442 : 5003 : eig = self%eig(ib, ik_ibz)
4443 : 6730 : self%my_a(ib, my_ik, ip) = exp(-half*(eig - mu)**2/sigma**2)
4444 : : enddo
4445 : : enddo
4446 : 19 : end subroutine gau_energy_
4447 : :
4448 : 0 : subroutine gau_length_()
4449 : : integer :: my_ik, ib
4450 : : real(dp) :: kpt(3)
4451 [ # # ]: 0 : do my_ik=1,gqk%my_nk
4452 [ # # ]: 0 : kpt(:) = self%my_kpts(:, my_ik)
4453 [ # # ]: 0 : do ib=1,gqk%nb_k
4454 [ # # ]: 0 : self%my_a(ib, my_ik, ip) = exp(-sum((kpt(:)*self%gpr_length(:))**2))
4455 : : enddo
4456 : : enddo
4457 : 0 : end subroutine gau_length_
4458 : :
4459 : 0 : subroutine random_()
4460 : 0 : real(dp), allocatable :: re_rand(:,:), im_rand(:,:)
4461 [ # # # # : 0 : ABI_MALLOC(re_rand, (gqk%nb_k, gqk%my_nk))
# # # # #
# # # # #
# # ]
4462 [ # # # # : 0 : ABI_MALLOC(im_rand, (gqk%nb_k, gqk%my_nk))
# # # # #
# # # # #
# # ]
4463 : 0 : call random_number(re_rand)
4464 : 0 : call random_number(im_rand)
4465 [ # # # # ]: 0 : self%my_a(:,:,ip) = re_rand(:,:) + j_dpc*im_rand(:,:)
4466 : 0 : call xmpi_sum(self%my_a(:,:,ip), gqk%qpt_pert_comm%value, ierr)
4467 [ # # ]: 0 : ABI_FREE(re_rand)
4468 [ # # ]: 0 : ABI_FREE(im_rand)
4469 [ # # # # ]: 0 : end subroutine random_
4470 : :
4471 : : end subroutine polstate_seed_a
4472 : : !!***
4473 : :
4474 : : !----------------------------------------------------------------------
4475 : :
4476 : : !!****f* m_varpeq/polstate_get_sqnorm
4477 : : !! NAME
4478 : : !! polstate_get_sqnorm
4479 : : !!
4480 : : !! FUNCTION
4481 : : !! Helper function that calculates squared L^2-norm of an MPI-distributed
4482 : : !! array at current state.
4483 : : !!
4484 : : !! INPUTS
4485 : : !! mode=Select which array to gather. Possible options:
4486 : : !! "a" ---> A_nk coefficients for this state;
4487 : : !! "b" ---> B_q\nu coefficients for this state;
4488 : : !! "grad" ---> current gradient;
4489 : : !! "pcjgrad" ---> current preconditioned conjugate gradient direction.
4490 : : !! ip=Index of a polaronic state.
4491 : : !!
4492 : : !! OUTPUT
4493 : : !! Squared L^2-norm of the specified array.
4494 : : !!
4495 : : !! SOURCE
4496 : :
4497 : 4672 : real(dp) function polstate_get_sqnorm(self, mode, ip) result(sqnorm)
4498 : :
4499 : : !Arguments ------------------------------------
4500 : : class(polstate_t), target, intent(inout) :: self
4501 : : character(len=*), intent(in) :: mode
4502 : : integer, intent(in) :: ip
4503 : :
4504 : : !Local variables-------------------------------
4505 : : class(gqk_t), pointer :: gqk
4506 : : !----------------------------------------------------------------------
4507 : :
4508 : 4672 : gqk => self%gqk
4509 : 4691 : select case(mode)
4510 : : case ("a")
4511 : 19 : sqnorm = get_sqnorm_(self%my_a(:,:,ip), gqk%kpt_comm%value)
4512 : : case ("b")
4513 : 0 : sqnorm = get_sqnorm_(self%my_b(:,:,ip), gqk%qpt_pert_comm%value)
4514 : : case ("grad")
4515 : 2331 : sqnorm = get_sqnorm_(self%my_grad, gqk%kpt_comm%value)
4516 : : case ("pcjgrad")
4517 : 2187 : sqnorm = get_sqnorm_(self%my_pcjgrad, gqk%kpt_comm%value)
4518 : : case ("phgrad")
4519 : 135 : sqnorm = get_sqnorm_(self%my_phgrad(:,:,ip), gqk%qpt_pert_comm%value)
4520 : : case ("eff_phforce")
4521 : 0 : sqnorm = get_sqnorm_(self%my_eff_phforce(:,:,ip), gqk%qpt_pert_comm%value)
4522 : : case default
4523 [ + - + + : 4672 : ABI_ERROR(sjoin("polstate_get_sqnorm, unsupported mode: ", mode))
+ - - ]
4524 : : end select
4525 : :
4526 : : !----------------------------------------------------------------------
4527 : :
4528 : : contains
4529 [ - + ]: 4672 : real(dp) function get_sqnorm_(my_arr, comm) result(sqnorm)
4530 : : integer, intent(in) :: comm
4531 : : complex(dp), intent(in) :: my_arr(:, :)
4532 : : integer :: ierr
4533 [ + + + + ]: 2200349 : sqnorm = sum(abs(my_arr(:,:))**2)
4534 : 4672 : call xmpi_sum(sqnorm, comm, ierr)
4535 : 4672 : end function get_sqnorm_
4536 : :
4537 : : end function polstate_get_sqnorm
4538 : : !!***
4539 : :
4540 : : !----------------------------------------------------------------------
4541 : :
4542 : : !!****f* m_varpeq/polstate_gather
4543 : : !! NAME
4544 : : !! polstate_gather
4545 : : !!
4546 : : !! FUNCTION
4547 : : !! Helper function that gathers a MPI-distributed array from the datatype
4548 : : !! into a global one.
4549 : : !!
4550 : : !! INPUTS
4551 : : !! mode=Select which array to gather. Possible options:
4552 : : !! "a" ---> my_a(:,:,ip) -- array of A_nk coefficients for this state;
4553 : : !! "pcjgrad" ---> my_pcjgrad(:,:) -- gradient.
4554 : : !! ip=Index of a polaronic state.
4555 : : !!
4556 : : !! OUTPUT
4557 : : !!
4558 : : !! SOURCE
4559 : :
4560 : 4518 : subroutine polstate_gather(self, mode, ip)
4561 : :
4562 : : !Arguments ------------------------------------
4563 : : class(polstate_t), target, intent(inout) :: self
4564 : : character(len=*),intent(in) :: mode
4565 : : integer, intent(in) :: ip
4566 : :
4567 : : !Local variables-------------------------------
4568 : : class(gqk_t), pointer :: gqk
4569 : : !----------------------------------------------------------------------
4570 : :
4571 : 4518 : gqk => self%gqk
4572 : 6849 : select case(mode)
4573 : : case ("a")
4574 : : call gather_(self%my_a(:,:,ip), gqk%my_nk, gqk%my_kstart, self%a_glob(:,:,ip), &
4575 : 2331 : gqk%kpt_comm%value)
4576 : : case ("pcjgrad")
4577 : : call gather_(self%my_pcjgrad, gqk%my_nk, gqk%my_kstart, self%pcjgrad_glob, &
4578 : 2187 : gqk%kpt_comm%value)
4579 : : case default
4580 [ + + - ]: 4518 : ABI_ERROR(sjoin("polstate_gather, unsupported mode: ", mode))
4581 : : end select
4582 : :
4583 : : !----------------------------------------------------------------------
4584 : :
4585 : : contains
4586 [ - + - + ]: 4518 : subroutine gather_(my_arr, my_nk, my_kstart, glob_arr, comm)
4587 : :
4588 : : integer, intent(in) :: comm, my_nk, my_kstart
4589 : : complex(dp), intent(in) :: my_arr(:, :)
4590 : : complex(dp), intent(out) :: glob_arr(:, :)
4591 : :
4592 : : integer :: ierr, my_ik, ik_glob
4593 : : !----------------------------------------------------------------------
4594 : :
4595 [ + + + + ]: 2075340 : glob_arr(:, :) = zero
4596 [ + + ]: 524760 : do my_ik=1,my_nk
4597 : 520242 : ik_glob = my_ik + my_kstart - 1
4598 [ + + ]: 2075340 : glob_arr(:, ik_glob) = my_arr(:, my_ik)
4599 : : enddo
4600 : 4518 : call xmpi_sum(glob_arr, comm, ierr)
4601 : :
4602 : 4518 : end subroutine gather_
4603 : :
4604 : : end subroutine polstate_gather
4605 : : !!***
4606 : :
4607 : : !----------------------------------------------------------------------
4608 : :
4609 : : !!****f* m_varpeq/polstate_filter
4610 : : !! NAME
4611 : : !! polstate_filter
4612 : : !!
4613 : : !! FUNCTION
4614 : : !! Helper function that filters a MPI-distributed array from the datatype
4615 : : !!
4616 : : !! INPUTS
4617 : : !! mode=Select which array to filter. Possible options:
4618 : : !! "a" ---> my_a(:,:,ip) -- array of A_nk coefficients for this state;
4619 : : !! "pcjgrad" ---> my_pcjgrad(:,:) -- gradient.
4620 : : !! ip=Index of a polaronic state.
4621 : : !!
4622 : : !! OUTPUT
4623 : : !!
4624 : : !! SOURCE
4625 : :
4626 : 0 : subroutine polstate_filter(self, mode, ip)
4627 : :
4628 : : !Arguments ------------------------------------
4629 : : class(polstate_t), target, intent(inout) :: self
4630 : : character(len=*),intent(in) :: mode
4631 : : integer, intent(in) :: ip
4632 : :
4633 : : !Local variables-------------------------------
4634 : : class(gqk_t), pointer :: gqk
4635 : : !----------------------------------------------------------------------
4636 : :
4637 : 0 : gqk => self%gqk
4638 : 0 : select case(mode)
4639 : : case ("a")
4640 : 0 : call filter_(self%my_a(:,:,ip))
4641 : : case ("grad")
4642 : 0 : call filter_(self%my_grad(:,:))
4643 : : case ("pcjgrad")
4644 : 0 : call filter_(self%my_pcjgrad(:,:))
4645 : : case default
4646 [ # # # # ]: 0 : ABI_ERROR(sjoin("polstate_filter, unsupported mode: ", mode))
4647 : : end select
4648 : :
4649 : : !----------------------------------------------------------------------
4650 : :
4651 : : contains
4652 [ # # ]: 0 : subroutine filter_(my_arr)
4653 : :
4654 : : complex(dp), intent(inout) :: my_arr(:, :)
4655 : :
4656 : : integer :: my_ik, ik_ibz, ib
4657 : : !----------------------------------------------------------------------
4658 : :
4659 [ # # ]: 0 : do my_ik=1,gqk%my_nk
4660 : 0 : ik_ibz = gqk%my_k2ibz(1, my_ik)
4661 [ # # ]: 0 : do ib=1,gqk%nb_k
4662 [ # # # # ]: 0 : if (self%eig(ib, ik_ibz) > self%efilter .or. self%eig(ib, ik_ibz) < -tol6) then
4663 : 0 : my_arr(ib, my_ik) = zero
4664 : : endif
4665 : : enddo
4666 : : enddo
4667 : :
4668 : 0 : end subroutine filter_
4669 : :
4670 : : end subroutine polstate_filter
4671 : : !!***
4672 : :
4673 : : !----------------------------------------------------------------------
4674 : :
4675 : : !!****f* m_varpeq/polstate_get_krank_glob
4676 : : !! NAME
4677 : : !! polstate_get_krank_glob
4678 : : !!
4679 : : !! FUNCTION
4680 : : !! Helper function that computes krank objects for the full BZ q/k-meshes.
4681 : : !!
4682 : : !! INPUTS
4683 : : !! mode=Select reciprocal space for which krank is computed. Possible options:
4684 : : !! "k" ---> k-space;
4685 : : !! "q" ---> q-space.
4686 : : !! kptrlatt(3,3)=Lattice specifiyng the grid.
4687 : : !!
4688 : : !! OUTPUT
4689 : : !! krank<krank_t>=Object proiding mapping between reciprocal space points and
4690 : : !! their indices.
4691 : : !!
4692 : : !! SOURCE
4693 : :
4694 : 18 : type(krank_t) function polstate_get_krank_glob(self, mode, kptrlatt) result(krank_kpts)
4695 : :
4696 : : !Arguments ------------------------------------
4697 : : !scalars
4698 : : class(polstate_t), target, intent(in) :: self
4699 : : character(len=*), intent(in) :: mode
4700 : : !arrays
4701 : : integer, intent(in) :: kptrlatt(3, 3)
4702 : :
4703 : : !Local variables-------------------------------
4704 : : !scalars
4705 : : class(gqk_t), pointer :: gqk
4706 : : !----------------------------------------------------------------------
4707 : :
4708 : 18 : gqk => self%gqk
4709 : :
4710 : 45 : select case(mode)
4711 : : case ("k")
4712 : : krank_kpts = get_krank_glob_(self%my_kpts, gqk%my_nk, gqk%my_kstart, &
4713 [ + - - - : 9 : gqk%glob_nk, gqk%kpt_comm%value)
- - - - -
+ ]
4714 : : case ("q")
4715 : : krank_kpts = get_krank_glob_(self%my_qpts, gqk%my_nq, gqk%my_qstart, &
4716 : 9 : gqk%glob_nq, gqk%qpt_comm%value)
4717 : : case default
4718 [ + + - ]: 18 : ABI_ERROR(sjoin("polstate_get_krank_glob, unsupported mode: ", mode))
4719 : : end select
4720 : :
4721 : : !----------------------------------------------------------------------
4722 : :
4723 : : contains
4724 : 18 : type(krank_t) function get_krank_glob_(my_kpts, my_nk, my_kstart, glob_nk, &
4725 : : comm) result(krank_kpts)
4726 : :
4727 : : integer, intent(in) :: comm, my_nk, my_kstart, glob_nk
4728 : : real(dp), intent(in) :: my_kpts(3, my_nk)
4729 : :
4730 : 18 : type(krank_t) :: krank_tmp
4731 : : integer :: ierr, my_ik, ik_glob
4732 : 36 : real(dp) :: kpts(3, glob_nk)
4733 : :
4734 : : !----------------------------------------------------------------------
4735 : :
4736 [ + + + + ]: 7434 : kpts(:, :) = zero
4737 [ + + ]: 1872 : do my_ik=1,my_nk
4738 : 1854 : ik_glob = my_ik + my_kstart - 1
4739 [ + + ]: 7434 : kpts(:, ik_glob) = my_kpts(:, my_ik)
4740 : : enddo
4741 : 18 : call xmpi_sum(kpts, comm, ierr)
4742 : :
4743 : 18 : call krank_tmp%from_kptrlatt(glob_nk, kpts, kptrlatt, compute_invrank=.true.)
4744 : 18 : krank_kpts = krank_tmp%copy()
4745 : 18 : call krank_tmp%free()
4746 : :
4747 [ - + - + : 36 : end function get_krank_glob_
- + ]
4748 : :
4749 : : end function polstate_get_krank_glob
4750 : : !!***
4751 : :
4752 : : !!****f* m_varpeq/varpeq_plot
4753 : : !! NAME
4754 : : !! varpeq_plot
4755 : : !!
4756 : : !! FUNCTION
4757 : : !! Compute polaron wavefunctions and atomic displacements in the supercell and write results to XSF files
4758 : : !!
4759 : : !! INPUTS
4760 : : !! wfk0_path=String with the path to the GS unperturbed WFK file.
4761 : : !! ngfft(18),ngfftf(18)=Coarse and Fine FFT meshes.
4762 : : !! dtset<dataset_type>=All input variables for this dataset.
4763 : : !! ebands<ebands_t>=The GS KS band structure (energies, occupancies, k-weights...)
4764 : : !! comm=MPI communicator.
4765 : : !!
4766 : : !! OUTPUT
4767 : : !!
4768 : : !! SOURCE
4769 : :
4770 : 2 : subroutine varpeq_plot(wfk0_path, ngfft, dtset, dtfil, cryst, ebands, pawtab, psps, comm)
4771 : :
4772 : : !Arguments ------------------------------------
4773 : : character(len=*),intent(in) :: wfk0_path
4774 : : integer,intent(in) :: ngfft(18) !,ngfftf(18)
4775 : : type(dataset_type), intent(in) :: dtset
4776 : : type(datafiles_type), intent(in) :: dtfil
4777 : : type(crystal_t),intent(in) :: cryst
4778 : : type(ebands_t),intent(in) :: ebands
4779 : : type(pseudopotential_type),intent(in) :: psps
4780 : : type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
4781 : : integer,intent(in) :: comm
4782 : :
4783 : : !Local variables-------------------------------
4784 : : !scalars
4785 : : integer,parameter :: master = 0, ndat1 = 1
4786 : : integer :: my_rank, ib, irsp, ir, uc_idx, mpw, band, bstart, ir1, ir2, ir3, wp1, wp2, wp3, ds_nfft, idir
4787 : : integer :: natom, natom3, nsppol, nspinor, nspden, nkibz, mband, spin, ik, sc_nfft, cnt, nproc, num_writes, ii, uc_nfft
4788 : : integer :: ik_ibz, isym_k, trev_k, npw_k, istwf_k, npw_kq_ibz, istwf_k_ibz, nkpg_k, ierr, nk, spinor, spad, nkbz, ncid
4789 : : integer :: nqibz, iq, iq_ibz, isym_q, trev_q, qptopt, uc_iat, sc_iat, nu, nqbz, ip, ds_iscale
4790 : : logical :: isirr_k, isirr_q, have_scell_q, use_displaced_scell
4791 : : real(dp) :: cpu_all, wall_all, gflops_all, spread, kdotr
4792 : : real(dp) :: psign
4793 : : character(len=500) :: msg
4794 : : character(len=fnlen) :: path
4795 [ + + + + : 104 : type(varpeq_t) :: vpq
+ + + + +
+ + + + +
+ + + + ]
4796 : 2 : type(wfd_t) :: wfd
4797 : 2 : type(supercell_type), target :: scell_q, scell_k
4798 : 2 : type(krank_t) :: krank_ibz, qrank_ibz
4799 : : complex(dp) :: a_nk, bstar_qnu, cphase, cphase_tr, c3tmp(3)
4800 : : complex(gwp) :: c123, c23, c3
4801 : : !arrays
4802 : : integer :: sc_ngfft(18), ds_ngfft(18), mapl_k(6), kptrlatt_(3,3), qptrlatt_(3,3)
4803 : : integer :: units(2), work_ngfft(18), gmax(3), g0_k(3), mapl_qq(6), g0_q(3), ngqpt(3)
4804 : 4 : integer,allocatable :: nband(:,:), wfd_istwfk(:), kg_k(:,:), gbound_k(:,:)
4805 : : real(dp),parameter :: origin0(3) = zero
4806 : : real(dp) :: kk(3), kk_ibz(3), kk_sc(3), qq(3), qq_ibz(3), center_cart(3)
4807 : 4 : real(dp),allocatable :: kpg_k(:,:), ug_k(:,:), work(:,:,:,:), pol_rhor(:), qibz(:,:)
4808 : 2 : real(dp),allocatable :: pheigvec_qibz(:,:,:,:)
4809 : 2 : real(dp),allocatable :: displ_cart_qbz(:,:,:,:), pheigvec_qbz(:,:,:,:) !displ_red_qbz(:,:,:,:), displ_cart_qibz(:,:,:,:),
4810 : 2 : real(dp),allocatable :: phfreqs_ibz(:,:), pheigvec_cart_ibz(:,:,:,:,:) !, pheigvec_cart_qbz(:,:,:,:)
4811 : 2 : real(dp),allocatable :: sc_displ_cart_re(:,:,:,:), sc_displ_cart_im(:,:,:,:)
4812 : 2 : real(dp), contiguous, pointer :: xcart_ptr(:,:)
4813 : 2 : logical,allocatable :: bks_mask(:,:,:),keep_ur(:,:,:)
4814 : 2 : complex(gwp),allocatable :: ur_k(:,:), ds_ur_k(:,:), pol_wfr(:,:,:), sc_ceikr_1d(:,:)
4815 : : !----------------------------------------------------------------------
4816 : :
4817 [ + + ]: 6 : units = [std_out, ab_out]
4818 : 2 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
4819 : :
4820 : : ! Read A_nk and B_qnu and other useful tables from file
4821 : 2 : call vpq%ncread(dtfil%filvpqin, comm, keep_open=.false.)
4822 : : !call wrtout(std_out, " Reading done")
4823 : :
4824 : 2 : psign = -1
4825 [ + + ]: 2 : if (vpq%pkind == "hole") psign = 1
4826 : :
4827 : : ! Copy important dimensions
4828 : 2 : natom = cryst%natom; natom3 = 3 * natom; nsppol = ebands%nsppol; nspinor = ebands%nspinor; nspden = dtset%nspden
4829 : 2 : nkibz = ebands%nkpt; mband = ebands%mband
4830 : :
4831 [ - + ]: 2 : if (dtfil%filgstorein == ABI_NOFILE) then
4832 : 0 : call wrtout(units, "gstore_filepath is not specified in input. Cannot compute polaron-induced displacements!")
4833 : 0 : have_scell_q = .false.
4834 : :
4835 : : else
4836 : : ! Start by reading ph displacements and frequencies in the IBZ from the gstore file.
4837 : : ! First compute displaced supercell then polaron wf so that we can use both when writing the XSF file.
4838 : 2 : call wrtout(units, sjoin(" Computing polaron-induced displacements. Reading phonons from: ", dtfil%filgstorein))
4839 : 2 : call cwtime(cpu_all, wall_all, gflops_all, "start")
4840 : 2 : have_scell_q = .true.
4841 : :
4842 [ - + ]: 2 : NCF_CHECK(nctk_open_read(ncid, dtfil%filgstorein, comm))
4843 [ - + ]: 2 : NCF_CHECK(nctk_get_dim(ncid, "gstore_nqibz", nqibz))
4844 : : !NCF_CHECK(nctk_get_dim(ncid, "gstore_nqbz", nqbz))
4845 : :
4846 : : ! TODO: Wrap phstore API?
4847 : : ! Encapsulate this part as we're gonna re-use it to deal with hopping
4848 : : !call gstore_read_ph_qibz(dtfil%filgstorein, ph, comm)
4849 : : !call ph%free()
4850 : :
4851 [ - + + - : 6 : ABI_MALLOC(qibz, (3, nqibz))
+ - + - -
+ - + -
+ ]
4852 [ - + + - : 8 : ABI_MALLOC(phfreqs_ibz, (natom3, nqibz))
- + + - +
- + - - +
- + - + ]
4853 [ - + + - : 12 : ABI_MALLOC(pheigvec_cart_ibz, (2, 3, cryst%natom, cryst%natom * 3, nqibz))
+ - - + +
- - + + -
+ - + - -
+ - + -
+ ]
4854 [ - + ]: 2 : if (nproc > 1) then
4855 [ # # ]: 0 : NCF_CHECK(nctk_set_collective(ncid, vid("gstore_qibz")))
4856 [ # # ]: 0 : NCF_CHECK(nctk_set_collective(ncid, vid("phfreqs_ibz")))
4857 [ # # ]: 0 : NCF_CHECK(nctk_set_collective(ncid, vid("pheigvec_cart_ibz")))
4858 : : end if
4859 [ - + ]: 2 : NCF_CHECK(nf90_get_var(ncid, vid("gstore_qibz"), qibz))
4860 [ - + ]: 2 : NCF_CHECK(nf90_get_var(ncid, vid("phfreqs_ibz"), phfreqs_ibz))
4861 [ - + ]: 2 : NCF_CHECK(nf90_get_var(ncid, vid("pheigvec_cart_ibz"), pheigvec_cart_ibz))
4862 [ - + ]: 2 : NCF_CHECK(nf90_get_var(ncid, vid("gstore_ngqpt"), ngqpt))
4863 [ - + ]: 2 : NCF_CHECK(nf90_get_var(ncid, vid("gstore_qptopt"), qptopt))
4864 [ - + ]: 2 : NCF_CHECK(nf90_close(ncid))
4865 : :
4866 [ - + + - : 8 : ABI_MALLOC(pheigvec_qibz, (2, 3, cryst%natom, natom3))
- + + - +
- + - - +
- + ]
4867 [ - + + - : 8 : ABI_MALLOC(displ_cart_qbz, (2, 3, cryst%natom, cryst%natom * 3))
- + + - +
- + - - +
- + ]
4868 [ - + + - : 6 : ABI_MALLOC(pheigvec_qbz, (2, 3, cryst%natom, 3*cryst%natom))
- + + - -
+ - + ]
4869 : :
4870 [ + + ]: 8 : nqbz = product(ngqpt)
4871 : 2 : call kptrlatt_from_ngkpt(ngqpt, qptrlatt_)
4872 : 2 : call qrank_ibz%from_kptrlatt(nqibz, qibz, qptrlatt_, compute_invrank=.false.)
4873 : :
4874 : 2 : call scell_q%init(cryst%natom, qptrlatt_, cryst%rprimd, cryst%typat, cryst%xcart, cryst%znucl, xyz_order="xyz")
4875 : :
4876 [ - + + - : 18240 : ABI_CALLOC(sc_displ_cart_re, (3, scell_q%natom, vpq%nstates, nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + + +
+ + + + +
+ ]
4877 [ - + + - : 18238 : ABI_CALLOC(sc_displ_cart_im, (3, scell_q%natom, vpq%nstates, nsppol))
- + + - -
+ + - - +
- + - + +
+ + + + +
+ + ]
4878 : :
4879 : 2 : cnt = 0
4880 [ + + ]: 4 : do spin=1,nsppol
4881 [ + + ]: 628 : do iq=1,vpq%nq_spin(spin)
4882 [ + - ]: 624 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism inside comm.
4883 [ + + ]: 2496 : qq = vpq%qpts_spin(:, iq, spin)
4884 : : ! Note symrec here
4885 [ - + ]: 624 : if (kpts_map("symrec", qptopt, cryst, qrank_ibz, 1, qq, mapl_qq) /= 0) then
4886 : 0 : ABI_ERROR("Cannot map qBZ to IBZ!")
4887 : : end if
4888 : 624 : iq_ibz = mapl_qq(1); isym_q = mapl_qq(2)
4889 : 624 : trev_q = mapl_qq(6); g0_q = mapl_qq(3:5)
4890 : : ! Don't test if umklapp == 0 because we use the periodic gauge:
4891 : : !
4892 : : ! phfreq(q+G) = phfreq(q) and eigvec(q) = eigvec(q+G)
4893 : : !
4894 : 624 : isirr_q = (isym_q == 1 .and. trev_q == 0)
4895 [ + + ]: 2496 : qq_ibz = qibz(:, iq_ibz)
4896 : : !if (all(abs(qq_ibz) < tol6)) cycle
4897 [ + - + - : 79872 : pheigvec_qibz = pheigvec_cart_ibz(:,:,:,:,iq_ibz)
+ - + - -
+ - - + +
+ + + + +
+ ]
4898 : :
4899 [ + + ]: 624 : if (isirr_q) then
4900 : : ! Compute phonon displacements in Cartesian coordinates
4901 : 34 : call phdispl_from_eigvec(cryst%natom, cryst%ntypat, cryst%typat, cryst%amu, pheigvec_qibz, displ_cart_qbz)
4902 : :
4903 : : else
4904 : : ! Rotate phonon eigenvectors from q_ibz to q_bz.
4905 : : ! This part is needed to enforce the gauge in the ph eigenvectors, including e(-q) = e(q)^*
4906 : 590 : call pheigvec_rotate(cryst, qq_ibz, isym_q, trev_q, pheigvec_qibz, pheigvec_qbz, displ_cart_qbz)
4907 : : end if
4908 : :
4909 : : ! Phase due to the primitive translation (default: 0)
4910 [ + + ]: 2496 : cphase_tr = exp(-j_dpc * two_pi * dot_product(qq, dtset%vpq_trvec))
4911 : :
4912 [ + + ]: 2625302 : do sc_iat=1, scell_q%natom
4913 : 2624676 : uc_iat = scell_q%atom_indexing(sc_iat)
4914 : : ! Compute phase e^{iq.R}
4915 [ + + ]: 10498704 : cphase = exp(+j_dpc * two_pi * dot_product(qq, scell_q%uc_indexing(:, sc_iat)))
4916 [ + + ]: 5252892 : do ip=1,vpq%nstates
4917 : : ! Summing over ph modes.
4918 [ + + ]: 21017820 : do nu=1,natom3
4919 : : ! skip acoustic modes at Gamma
4920 [ + + ]: 15765552 : if (abs(phfreqs_ibz(nu, iq_ibz)) < tol12) cycle
4921 : :
4922 : 15751884 : bstar_qnu = conjg(vpq%b_spin(nu, iq, ip, spin)) * cphase_tr / sqrt(phfreqs_ibz(nu, iq_ibz))
4923 [ + + ]: 63007536 : c3tmp = (displ_cart_qbz(1,:,uc_iat,nu) + j_dpc * displ_cart_qbz(2,:,uc_iat,nu)) * bstar_qnu * cphase
4924 [ + + ]: 63007536 : sc_displ_cart_re(:,sc_iat,ip,spin) = sc_displ_cart_re(:,sc_iat,ip,spin) + real(c3tmp)
4925 [ + + ]: 65635128 : sc_displ_cart_im(:,sc_iat,ip,spin) = sc_displ_cart_im(:,sc_iat,ip,spin) + aimag(c3tmp) ! This to check if the imag part is zero.
4926 : : end do
4927 : : end do ! ip
4928 : : end do ! sc_iat
4929 : :
4930 : : end do ! iq
4931 : : end do ! spin
4932 : :
4933 [ - + ]: 2 : ABI_FREE(qibz)
4934 [ - + ]: 2 : ABI_FREE(phfreqs_ibz)
4935 [ - + ]: 2 : ABI_FREE(pheigvec_cart_ibz)
4936 [ - + ]: 2 : ABI_FREE(displ_cart_qbz)
4937 [ - + ]: 2 : ABI_FREE(pheigvec_qbz)
4938 [ - + ]: 2 : ABI_FREE(pheigvec_qibz)
4939 : 2 : call qrank_ibz%free()
4940 : :
4941 : 2 : call xmpi_sum_master(sc_displ_cart_re, master, comm, ierr)
4942 : 2 : call xmpi_sum_master(sc_displ_cart_im, master, comm, ierr)
4943 [ + + + + : 18232 : sc_displ_cart_re = psign * sqrt2 * sc_displ_cart_re / nqbz
+ + + + ]
4944 [ + + + + : 18232 : sc_displ_cart_im = psign * sqrt2 * sc_displ_cart_im / nqbz
+ + + + ]
4945 : :
4946 : : ! Write polaron-induced displacements in XSF format.
4947 [ + - ]: 2 : if (my_rank == master) then
4948 : : ! Handle spin-polarized case by writing two XSF files.
4949 [ + + ]: 4 : do spin=1,nsppol
4950 : : ! Handle multiple polaronic states for each spin.
4951 [ + + ]: 8 : do ip=1,vpq%nstates
4952 : : write(msg, "(2(a,i0),a,es16.6)") &
4953 [ + + + + : 18228 : " For spin: ", spin, ": pstate: ", ip, ": maxval(abs(sc_displ_cart_re)): ", maxval(abs(sc_displ_cart_re(:,:,ip,spin)))
+ + + - -
+ - - ]
4954 : 4 : call wrtout(units, msg)
4955 : : write(msg, "(2(a,i0),a,es16.6)") &
4956 [ + + + + : 18228 : " For spin: ", spin, ": pstate: ", ip, ": maxval(abs(sc_displ_cart_im)): ", maxval(abs(sc_displ_cart_im(:,:,ip,spin)))
+ + + - -
+ - - ]
4957 : 4 : call wrtout(units, msg)
4958 : :
4959 : : ! Here we displace the atoms in the supercell for this spin (only master has the correct values)
4960 [ + - + - : 18232 : scell_q%xcart = scell_q%xcart_ref + sc_displ_cart_re(:,:,ip,spin)
- + - - +
+ + + ]
4961 : :
4962 [ + - ]: 4 : path = strcat(dtfil%filnam_ds(4), "_pstate_", itoa(ip), "_POLARON_DISPL_VECTORS.xsf")
4963 [ - + - - ]: 4 : if (nsppol == 2) path = strcat(dtfil%filnam_ds(4), strcat("_spin_", itoa(spin)), "_pstate_", itoa(ip), "_POLARON_DISPL_VECTORS.xsf")
4964 : 4 : call wrtout(units, sjoin(" Writing displacement vectors to:", path))
4965 : 6 : call scell_q%write_xsf(path)
4966 : : end do
4967 : : end do
4968 : : end if
4969 : :
4970 [ - + ]: 2 : ABI_FREE(sc_displ_cart_im)
4971 : : call cwtime_report(" Computation of polaron-induced displacements completed:", cpu_all, wall_all, gflops_all, &
4972 : 4 : pre_str=ch10, end_str=ch10)
4973 : : end if
4974 : :
4975 : 2 : call wrtout(std_out, " varpeq_plot: computing polaron wavefunction in real space.", pre_newlines=1)
4976 : :
4977 : 2 : call krank_ibz%from_kptrlatt(ebands%nkpt, ebands%kptns, ebands%kptrlatt, compute_invrank=.false.)
4978 : :
4979 : : ! Initialize the wave function descriptor.
4980 [ - + + - : 8 : ABI_MALLOC(nband, (nkibz, nsppol))
- + + - +
- + - - +
- + ]
4981 [ - + + - : 10 : ABI_MALLOC(bks_mask, (mband, nkibz, nsppol))
- + + - -
+ + - + -
+ - - + -
+ ]
4982 [ - + + - : 8 : ABI_MALLOC(keep_ur, (mband, nkibz, nsppol))
- + + - -
+ + - - +
- + ]
4983 [ + + + + : 1328 : nband = mband; bks_mask = .false.; keep_ur = .false.
+ + + + +
+ + + + +
+ + ]
4984 : :
4985 : : ! Here we use brange_spin to select the number of bands that should be read and stored in memory.
4986 : : ! For the time being, spin and k-points are not MPI-distributed inside comm.
4987 [ + + ]: 4 : do spin=1,nsppol
4988 : 2 : bstart = vpq%brange_spin(1, spin)
4989 [ + + ]: 120 : do ik=1, vpq%nk_spin(spin)
4990 [ + + ]: 464 : kk = vpq%kpts_spin(:, ik, spin)
4991 : : ! Note symrel option
4992 [ - + ]: 116 : if (kpts_map("symrel", ebands%kptopt, cryst, krank_ibz, 1, kk, mapl_k) /= 0) then
4993 [ # # ]: 0 : write(msg, '(4a)' )"k-mesh is not closed!",ch10, "k-point could not be generated from a symmetrical one.",trim(ltoa(kk))
4994 : 0 : ABI_ERROR(msg)
4995 : : end if
4996 : 116 : ik_ibz = mapl_k(1)
4997 [ + + ]: 288 : do ib=1,vpq%nb_spin(spin)
4998 : 286 : band = bstart + ib - 1; bks_mask(band, ik_ibz, spin) = .true.
4999 : : end do
5000 : : end do
5001 : : end do
5002 : :
5003 : : ! Impose istwfk = 1 for all k-points. This is also done in respfn (see inkpts)
5004 : : ! wfd_read_wfk will handle a possible conversion if WFK contains istwfk /= 1.
5005 [ - + + - : 6 : ABI_MALLOC(wfd_istwfk, (nkibz))
+ - + - -
+ - + ]
5006 [ + + ]: 90 : wfd_istwfk = 1
5007 : :
5008 : : call wfd%init(cryst, pawtab, psps, keep_ur, mband, nband, nkibz, nsppol, bks_mask,&
5009 : : dtset%nspden, dtset%nspinor, dtset%ecut, dtset%ecutsm, dtset%dilatmx, wfd_istwfk, ebands%kptns, ngfft, &
5010 : 2 : dtset%nloalg, dtset%prtvol, dtset%pawprtvol, comm)
5011 : :
5012 [ + + ]: 4 : call wfd%print([std_out], header="Wavefunctions for varpeq_plot")
5013 : :
5014 [ + - ]: 2 : if (dtset%boxcutmin >= two) then
5015 : 2 : call wrtout(std_out, " To decrease the size of the FFT mesh and the size of the XSF file, reduce boxcutmin from 2 to e.g. 1.1")
5016 : : end if
5017 : :
5018 [ - + ]: 2 : ABI_FREE(nband)
5019 [ - + ]: 2 : ABI_FREE(keep_ur)
5020 [ - + ]: 2 : ABI_FREE(wfd_istwfk)
5021 [ - + ]: 2 : ABI_FREE(bks_mask)
5022 : :
5023 : : ! Read wavefunctions.
5024 : 2 : call wfd%read_wfk(wfk0_path, iomode_from_fname(wfk0_path))
5025 : :
5026 : 2 : call cwtime(cpu_all, wall_all, gflops_all, "start")
5027 : 2 : call wrtout(std_out, " Computing mpw and gmax needed to allocate workspace array.")
5028 [ + + ]: 4 : do spin=1,nsppol
5029 : 2 : nk = vpq%nk_spin(spin)
5030 : : call ephtk_get_mpw_gmax(nk, vpq%kpts_spin(:, 1:nk, spin), dtset%ecut, cryst%gmet, mpw, gmax, comm, &
5031 : 4 : init_with_zero=spin==1)
5032 : : end do
5033 : :
5034 : : ! Init work_ngfft
5035 [ + + ]: 8 : gmax = gmax + 4 ! FIXME: this is to account for umklapp, should also consider Gamma-only and istwfk
5036 [ + + ]: 8 : gmax = 2*gmax + 1
5037 : 2 : call ngfft_seq(work_ngfft, gmax)
5038 : : !write(std_out,*)"work_ngfft(1:3): ",work_ngfft(1:3)
5039 [ - + + - : 10 : ABI_MALLOC(work, (2, work_ngfft(4), work_ngfft(5), work_ngfft(6)))
- + + - -
+ + - + -
+ - - + -
+ ]
5040 : :
5041 : 2 : call wrtout(std_out, sjoin(" Building supercell from ngkpt:", ltoa(vpq%ngkpt)))
5042 : : ! note xyz_order="xyz"
5043 : 2 : call kptrlatt_from_ngkpt(vpq%ngkpt, kptrlatt_)
5044 : 2 : call scell_k%init(cryst%natom, kptrlatt_, cryst%rprimd, cryst%typat, cryst%xcart, cryst%znucl, xyz_order="xyz")
5045 : :
5046 : : ! There are three meshes.
5047 : : ! ngfft: mesh in the unit cell used to compute u(r) via FFT
5048 : : ! ds_ngfft: coarse mesh used to downsample u(r). Note ngfft(1:3)/ds_ngfft(1:3) = ds_iscale
5049 : : ! sc_ngfft: mesh in the real space supercell computed as ds_ngfft * vqp%ngkpt
5050 : : ! the polaron wavefunction is defined on this mesh.
5051 : :
5052 : 2 : ds_iscale = dtset%vpq_mesh_fact
5053 : 2 : ds_ngfft = ngfft
5054 [ + + ]: 8 : ds_ngfft(1:3) = ngfft(1:3) / ds_iscale
5055 [ + + + - : 14 : ABI_CHECK(all(ds_ngfft(1:6) > 0), "ds_iscale too large and ds_ngfft == 0")
- + ]
5056 : 2 : ds_ngfft(4:6) = ds_ngfft(4:6) ! No augmentation
5057 [ + + ]: 8 : ds_nfft = product(ds_ngfft(1:3)) ! Total number of points in the supercell
5058 : :
5059 [ + + ]: 8 : sc_ngfft(1:3) = vpq%ngkpt(1:3) * ds_ngfft(1:3)
5060 [ + + ]: 8 : sc_ngfft(4:6) = sc_ngfft(1:3) ! No augmentation
5061 [ + + ]: 8 : sc_nfft = product(sc_ngfft(1:3)) ! Total number of points in the supercell
5062 : :
5063 : 2 : call wrtout(std_out, " Computing polaron wavefunction in the real-space supercell...")
5064 : 2 : call wrtout(std_out, sjoin(" Using vpq_mesh_fact:", itoa(ds_iscale)))
5065 : : call wrtout(std_out, sjoin(" Memory required by pol_wfr:", &
5066 : 2 : ftoa(two*sc_nfft*nspinor*vpq%nstates*nsppol*storage_size(one)/eight*b2Mb), " (Mb) <<< MEM"))
5067 : :
5068 [ + + ]: 8 : nkbz = product(vpq%ngkpt)
5069 : 2 : uc_nfft = wfd%nfft
5070 [ - + + - : 6 : ABI_MALLOC(kg_k, (3, mpw))
+ - + - -
+ - + -
+ ]
5071 [ + - - + : 8 : ABI_MALLOC(gbound_k, (2*wfd%mgfft+8, 2))
+ - + - +
- + - - +
- + ]
5072 [ - + + - : 6 : ABI_MALLOC(ur_k, (uc_nfft*nspinor, ndat1))
+ - + - -
+ - + ]
5073 [ + - ]: 2 : if (ds_iscale /= 1) then
5074 [ - + + - : 6 : ABI_MALLOC(ds_ur_k, (ds_nfft*nspinor, ndat1))
+ - + - -
+ - + ]
5075 : : end if
5076 : :
5077 [ - + + - : 747943 : ABI_CALLOC(pol_wfr, (sc_nfft*nspinor, vpq%nstates, nsppol)) ! Init output with zeros.
- + + - -
+ + - + -
+ - - + -
+ - + + +
+ + + + ]
5078 [ + + - + : 12 : ABI_MALLOC(sc_ceikr_1d, (maxval(sc_ngfft(1:3)), 3))
+ - + - +
- - + -
+ ]
5079 : :
5080 : 2 : cnt = 0
5081 [ + + ]: 4 : do spin=1,nsppol
5082 : 2 : bstart = vpq%brange_spin(1, spin)
5083 : 2 : nk = vpq%nk_spin(spin)
5084 [ + + ]: 120 : do ik=1, nk
5085 [ - + ]: 116 : cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism inside comm.
5086 : :
5087 [ + + ]: 464 : kk = vpq%kpts_spin(:, ik, spin)
5088 [ - + ]: 116 : if (kpts_map("symrel", ebands%kptopt, cryst, krank_ibz, 1, kk, mapl_k) /= 0) then
5089 [ # # ]: 0 : write(msg, '(4a)' )"k-mesh is not closed!",ch10, "k-point could not be generated from a symmetrical one.",trim(ltoa(kk))
5090 : 0 : ABI_ERROR(msg)
5091 : : end if
5092 : :
5093 [ + + ]: 464 : ik_ibz = mapl_k(1); isym_k = mapl_k(2); trev_k = mapl_k(6); g0_k = mapl_k(3:5)
5094 [ + + + + : 452 : isirr_k = (isym_k == 1 .and. trev_k == 0 .and. all(g0_k == 0))
+ + - + ]
5095 [ + + ]: 464 : kk_ibz = ebands%kptns(:, ik_ibz)
5096 : 116 : istwf_k_ibz = wfd%istwfk(ik_ibz); npw_kq_ibz = wfd%npwarr(ik_ibz)
5097 : :
5098 : : ! Get npw_k, kg_k for this k-point.
5099 : : call wfd%get_gvec_gbound(cryst%gmet, dtset%ecut, kk, ik_ibz, isirr_k, dtset%nloalg, & ! in
5100 [ - + ]: 116 : istwf_k, npw_k, kg_k, nkpg_k, kpg_k, gbound_k) ! out
5101 : :
5102 [ - + + - : 348 : ABI_MALLOC(ug_k, (2, npw_k*nspinor))
+ - + - -
+ - + ]
5103 [ + + ]: 464 : kk_sc = kk * vpq%ngkpt
5104 : :
5105 : : ! Precompute 1d phases e^{ik_j R_j} on the supercell.
5106 [ + + ]: 464 : do idir=1,3
5107 [ + + ]: 24935 : do ii=0,sc_ngfft(idir) - 1
5108 : 24471 : kdotr = two_pi * (kk_sc(idir) * (ii / dble(sc_ngfft(idir))))
5109 : 24819 : sc_ceikr_1d(ii+1, idir) = dcmplx(cos(kdotr), sin(kdotr))
5110 : : end do
5111 : : end do
5112 : :
5113 : : ! Phase due to the primitive translation (default: 0)
5114 [ + + ]: 464 : cphase_tr = exp(-j_dpc * two_pi * dot_product(kk, dtset%vpq_trvec))
5115 : :
5116 : : ! Sum over bands
5117 [ + + ]: 286 : do ib=1,vpq%nb_spin(spin)
5118 : 170 : band = bstart + ib - 1
5119 : : ! Get periodic part on the real space FFT mesh in ur_k
5120 : : call wfd%rotate_cg(band, ndat1, spin, kk_ibz, npw_k, kg_k, istwf_k, &
5121 : 170 : cryst, mapl_k, gbound_k, work_ngfft, work, ug_k, urs_kbz=ur_k)
5122 : : !print *, "int_omega dr |u(r)}^2:", sum(abs(ur_k(:,1)) ** 2) / uc_nfft
5123 : :
5124 : : ! Use linear interpolate to downsample from ngfft to ds_ngfft.
5125 [ + - ]: 170 : if (ds_iscale /= 1) then
5126 : 170 : call interpolate_ur(ngfft, nspinor*ndat1, ur_k, ds_ngfft, ds_ur_k)
5127 : : !print *, "int_omega dr |ds_u(r)}^2:", sum(abs(ds_ur_k(:,1)) ** 2) / product(ds_ngfft(1:3))
5128 : : end if
5129 : :
5130 : : ! Accumulate for each polaron state.
5131 [ + + ]: 618 : do ip=1,vpq%nstates
5132 : 332 : a_nk = vpq%a_spin(ib, ik, ip, spin) * cphase_tr
5133 [ + + ]: 834 : do spinor=1,nspinor
5134 : 332 : spad = (spinor - 1) * sc_nfft
5135 : :
5136 [ - + ]: 664 : if (ds_iscale == 1) then
5137 : : ! Loop over the points in the R supercell without downsampling.
5138 : 0 : ir = 0
5139 [ # # ]: 0 : do ir3=0,sc_ngfft(3)-1
5140 : : ! The FFT index of the point wrapped into the unit cell.
5141 : 0 : wp3 = modulo(ir3, ngfft(3))
5142 : 0 : c3 = sc_ceikr_1d(ir3+1, 3)
5143 [ # # ]: 0 : do ir2=0,sc_ngfft(2)-1
5144 : 0 : wp2 = modulo(ir2, ngfft(2))
5145 : 0 : c23 = sc_ceikr_1d(ir2+1, 2) * c3
5146 [ # # ]: 0 : do ir1=0,sc_ngfft(1)-1
5147 : 0 : wp1 = modulo(ir1, ngfft(1))
5148 : 0 : c123 = sc_ceikr_1d(ir1+1, 1) * c23
5149 : 0 : uc_idx = 1 + wp1 + wp2*ngfft(1) + wp3*ngfft(1)*ngfft(2)
5150 : 0 : ir = ir + 1; irsp = ir + spad
5151 : 0 : pol_wfr(irsp, ip, spin) = pol_wfr(irsp, ip, spin) + a_nk * ur_k(uc_idx,1) * c123
5152 : : end do
5153 : : end do
5154 : : end do
5155 : : else
5156 : : ! Loop over the points in the supercell with downsampling
5157 : 332 : ir = 0
5158 [ + + ]: 18209 : do ir3=0,sc_ngfft(3)-1
5159 : : ! The FFT index of the point wrapped into the unit cell.
5160 : 17877 : wp3 = modulo(ir3, ds_ngfft(3))
5161 : 17877 : c3 = sc_ceikr_1d(ir3+1, 3)
5162 [ + + ]: 1051760 : do ir2=0,sc_ngfft(2)-1
5163 : 1033551 : wp2 = modulo(ir2, ds_ngfft(2))
5164 : 1033551 : c23 = sc_ceikr_1d(ir2+1, 2) * c3
5165 [ + + ]: 65429931 : do ir1=0,sc_ngfft(1)-1
5166 : 64378503 : wp1 = modulo(ir1, ds_ngfft(1))
5167 : 64378503 : c123 = sc_ceikr_1d(ir1+1, 1) * c23
5168 : 64378503 : uc_idx = 1 + wp1 + wp2*ds_ngfft(1) + wp3*ds_ngfft(1)*ds_ngfft(2)
5169 : 64378503 : ir = ir + 1; irsp = ir + spad
5170 : : ! Note the use of the downsampled ds_ur_k here.
5171 : 65412054 : pol_wfr(irsp, ip, spin) = pol_wfr(irsp, ip, spin) + a_nk * ds_ur_k(uc_idx,1) * c123
5172 : : end do
5173 : : end do
5174 : : end do
5175 : : end if
5176 : :
5177 : : end do
5178 : : end do ! ip
5179 : : end do ! ib
5180 : :
5181 [ - + ]: 116 : ABI_FREE(ug_k)
5182 [ - + ]: 118 : ABI_FREE(kpg_k)
5183 : : end do ! ik
5184 : : end do ! spin
5185 : :
5186 [ - + ]: 2 : ABI_FREE(kg_k)
5187 [ - + ]: 2 : ABI_FREE(work)
5188 [ - + ]: 2 : ABI_FREE(ur_k)
5189 [ + - ]: 2 : ABI_SFREE(ds_ur_k)
5190 [ - + ]: 2 : ABI_FREE(gbound_k)
5191 [ - + ]: 2 : ABI_FREE(sc_ceikr_1d)
5192 : 2 : call krank_ibz%free()
5193 : :
5194 : : ! Collect pol_wfr on the master rank who's gonna write the polaron density in XSF format.
5195 : 2 : call xmpi_sum_master(pol_wfr, master, comm, ierr)
5196 : :
5197 [ + - ]: 2 : if (my_rank == master) then
5198 [ + + + + : 747935 : pol_wfr = pol_wfr / (nkbz * sqrt(cryst%ucvol))
+ + ]
5199 : : ! FIXME: Here we're gonna have another big allocation
5200 [ - + + - : 6 : ABI_MALLOC(pol_rhor, (sc_nfft))
+ - + - -
+ - + ]
5201 : :
5202 : : ! Here decide if we are gonna write the polaron wavefunctions with_diplaced atoms or not.
5203 [ + + + + : 26 : use_displaced_scell = all(kptrlatt_ == qptrlatt_) .and. have_scell_q
+ - ]
5204 [ + - ]: 2 : num_writes = 1; if (use_displaced_scell) num_writes = 2
5205 : :
5206 [ + - ]: 2 : if (nspinor == 1) then
5207 : : ! Handle spin-polarized case by writing two XSF files.
5208 [ + + ]: 4 : do spin=1,nsppol
5209 : : ! Handle multiple polaronic states for each spin.
5210 [ + + ]: 8 : do ip=1,vpq%nstates
5211 : : write(msg, "(2(a,i0),a,es16.6)")&
5212 [ + + + + ]: 506 : " For spin: ", spin, ": pstate: ", ip, ": 1/N_k \sum_nk |A_nk|^2 = ", sum(abs(vpq%a_spin(:,:,ip,spin))**2) / nkbz
5213 : 4 : call wrtout(units, msg)
5214 [ + - - + : 747935 : pol_rhor = abs(pol_wfr(:, ip, spin)) ** 2
- - + + ]
5215 : 4 : write(msg, "(2(a,i0),a,es16.6)")" Polaron density for spin: ", spin, ": pstate: ", ip, &
5216 [ + + + + ]: 747947 : " integrates to: ", sum(pol_rhor) * cryst%ucvol / product(ds_ngfft(1:3))
5217 : 4 : call wrtout(units, msg)
5218 [ + - - + : 747935 : write(msg, "(a,es16.6)")" maxval(abs(aimag(pol_wfr))): ", maxval(abs(aimag(pol_wfr(:, ip, spin))))
- - + + ]
5219 : 4 : call wrtout(std_out, msg)
5220 : 4 : call center_and_spread(cryst, vpq%ngkpt, sc_ngfft, pol_rhor, center_cart, spread, units)
5221 : :
5222 [ + + ]: 14 : do ii=1,num_writes
5223 [ + + ]: 8 : if (ii == 1) then
5224 : 4 : xcart_ptr => scell_k%xcart
5225 [ + - ]: 4 : path = strcat(dtfil%filnam_ds(4), "_pstate_", itoa(ip), "_POLARON.xsf")
5226 [ - + - - ]: 4 : if (nsppol == 2) path = strcat(dtfil%filnam_ds(4), strcat("_spin_", itoa(spin)), "_pstate_", itoa(ip), "_POLARON.xsf")
5227 : 4 : call wrtout(units, strcat("- Writing the polaron wavefunction with undisplaced atoms to: ", path))
5228 : : else
5229 [ + - ]: 4 : path = strcat(dtfil%filnam_ds(4), "_pstate_", itoa(ip), "_POLARON_DISPL.xsf")
5230 [ - + - - ]: 4 : if (nsppol == 2) path = strcat(dtfil%filnam_ds(4), strcat("_spin_", itoa(spin)), "_pstate_", itoa(ip), "_POLARON_DISPL.xsf")
5231 : 4 : call wrtout(units, strcat("- Writing the polaron wavefunction with displaced atoms to: ", path))
5232 : :
5233 : : ! Here we displace the atoms in the supercell for this spin (only master has the correct values)
5234 [ + - + - : 18232 : scell_q%xcart = scell_q%xcart_ref + sc_displ_cart_re(:,:,ip,spin)
- + - - +
+ + + ]
5235 : 4 : xcart_ptr => scell_q%xcart
5236 : : end if
5237 : :
5238 : : call write_xsf(path, sc_ngfft(1), sc_ngfft(2), sc_ngfft(3), pol_rhor, scell_k%rprimd, origin0, &
5239 : 12 : scell_k%natom, scell_k%ntypat, scell_k%typat, xcart_ptr, scell_k%znucl, 0)
5240 : : end do ! ii
5241 : : end do ! ip
5242 : : end do ! spin
5243 : :
5244 : : else
5245 : : ! Spinor wavefunctions.
5246 [ # # ]: 0 : do ip=1,vpq%nstates
5247 : : write(msg, "(2(a,i0),a,es16.6)")&
5248 [ # # # # ]: 0 : " For spin: ", spin, ": pstate: ", ip, ": 1/N_k \sum_nk |A_nk|^2 = ", sum(abs(vpq%a_spin(:,:,ip,spin))**2) / nkbz
5249 : 0 : call wrtout(units, msg)
5250 : :
5251 [ # # ]: 0 : pol_rhor(:) = abs(pol_wfr(1:sc_nfft, ip, 1)) ** 2
5252 [ # # ]: 0 : pol_rhor(:) = abs(pol_wfr(sc_nfft+1:, ip, 1)) ** 2 + pol_rhor(:)
5253 : 0 : write(msg, "(2(a,i0),a,es16.6)")" Polaron density for spin: ", spin, ": pstate: ", ip, &
5254 [ # # # # ]: 0 : " integrates to: ", sum(pol_rhor) * cryst%ucvol / product(ds_ngfft(1:3))
5255 : 0 : call wrtout(units, msg)
5256 [ # # # # : 0 : write(msg, "(a,es16.6)")" maxval(abs(aimag(pol_wfr))): ", maxval(abs(aimag(pol_wfr(:, ip, 1))))
# # # # ]
5257 : 0 : call wrtout(units, msg)
5258 : 0 : call center_and_spread(cryst, vpq%ngkpt, sc_ngfft, pol_rhor, center_cart, spread, units)
5259 : :
5260 : 0 : spin = 1
5261 [ # # ]: 0 : do ii=1,num_writes
5262 [ # # ]: 0 : if (ii == 1) then
5263 : 0 : xcart_ptr => scell_k%xcart
5264 [ # # ]: 0 : path = strcat(dtfil%filnam_ds(4), "_pstate_", itoa(ip), "_POLARON.xsf")
5265 : 0 : call wrtout(units, strcat("- Writing the polaron wavefunction with undisplaced atoms to: ", path))
5266 : : else
5267 [ # # ]: 0 : path = strcat(dtfil%filnam_ds(4), "_pstate_", itoa(ip), "_POLARON_DISPL.xsf")
5268 : 0 : call wrtout(units, strcat("- Writing the polaron wavefunction with displaced atoms to: ", path))
5269 : :
5270 : : ! Here we displace the atoms in the supercell for this spin (only master has the correct values)
5271 [ # # # # : 0 : scell_q%xcart = scell_q%xcart_ref + sc_displ_cart_re(:,:,ip,spin)
# # # # #
# # # ]
5272 : 0 : xcart_ptr => scell_q%xcart
5273 : : end if
5274 : :
5275 : : call write_xsf(path, sc_ngfft(1), sc_ngfft(2), sc_ngfft(3), pol_rhor, scell_k%rprimd, origin0, &
5276 : 0 : scell_k%natom, scell_k%ntypat, scell_k%typat, xcart_ptr, scell_k%znucl, 0)
5277 : : end do ! ii
5278 : : end do ! ip
5279 : : end if
5280 [ - + ]: 2 : ABI_FREE(pol_rhor)
5281 : : end if ! master
5282 : :
5283 : 2 : call cwtime_report(" Computation of polaron wavefunction completed", cpu_all, wall_all, gflops_all, pre_str=ch10, end_str=ch10)
5284 : :
5285 [ + - ]: 2 : ABI_SFREE(sc_displ_cart_re)
5286 [ - + ]: 2 : ABI_FREE(pol_wfr)
5287 : :
5288 [ - + - + : 8 : call wfd%free(); call scell_q%free(); call scell_k%free(); call vpq%free()
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - - - -
- - - - -
- - - - -
- + - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + -
+ ]
5289 : :
5290 : : contains
5291 : 10 : integer function vid(var_name)
5292 : : character(len=*),intent(in) :: var_name
5293 : 10 : vid = nctk_idname(ncid, var_name)
5294 : : end function vid
5295 : :
5296 : : end subroutine varpeq_plot
5297 : : !!***
5298 : :
5299 [ - + ]: 4 : subroutine center_and_spread(prim_cryst, ncells, sc_ngfft, rhor, center_cart, spread, units)
5300 : :
5301 : : !Arguments ------------------------------------
5302 : : type(crystal_t),intent(in) :: prim_cryst
5303 : : integer,intent(in) :: ncells(3), sc_ngfft(18)
5304 : : real(dp),intent(in) :: rhor(sc_ngfft(1), sc_ngfft(2), sc_ngfft(3))
5305 : : !real(dp),intent(in) :: rhor(sc_ngfft(4), sc_ngfft(5), sc_ngfft(6)) ! FIXME
5306 : : real(dp),intent(out) :: center_cart(3), spread
5307 : : integer,intent(in) :: units(:)
5308 : :
5309 : : !Local variables-------------------------------
5310 : : integer :: i1, i2, i3, nfft, num_cells
5311 : : real(dp) :: rr(3), rcart(3), rmr0(3), sc_rprimd(3,3), center_red(3), r2_mean, fwhm
5312 : : character(len=500) :: msg
5313 : : !----------------------------------------------------------------------
5314 : :
5315 [ + + ]: 16 : nfft = product(sc_ngfft(1:3))
5316 [ + + ]: 16 : sc_rprimd(:,1) = prim_cryst%rprimd(:,1) * ncells(1)
5317 [ + + ]: 16 : sc_rprimd(:,2) = prim_cryst%rprimd(:,2) * ncells(2)
5318 [ + + ]: 16 : sc_rprimd(:,3) = prim_cryst%rprimd(:,3) * ncells(3)
5319 [ + + ]: 16 : num_cells = product(ncells)
5320 : :
5321 : : ! Compute center_cart = \int r rhor(r) dr
5322 : 4 : center_cart = zero !; r2_mean = zero
5323 [ + + ]: 217 : do i3=1,sc_ngfft(3)
5324 : 213 : rr(3) = (i3 - one) / sc_ngfft(3)
5325 [ + + ]: 12376 : do i2=1,sc_ngfft(2)
5326 : 12159 : rr(2) = (i2 - one) / sc_ngfft(2)
5327 [ + + ]: 760299 : do i1=1,sc_ngfft(1)
5328 : 747927 : rr(1) = (i1 - one) / sc_ngfft(1)
5329 : : ! Go to cartesian coordinates.
5330 [ + + + + ]: 9723051 : rcart = matmul(sc_rprimd, rr)
5331 [ + + ]: 2991708 : center_cart = center_cart + rhor(i1, i2, i3) * rcart
5332 : 760086 : r2_mean = r2_mean + rhor(i1, i2, i3) * dot_product(rcart, rcart)
5333 : : end do
5334 : : end do
5335 : : end do
5336 : :
5337 : : !center_cart = matmul(sc_rprimd, center_cart)
5338 [ + + ]: 16 : center_cart = center_cart * num_cells * prim_cryst%ucvol / (one*nfft)
5339 : : !r2_mean = r2_mean * num_cells * prim_cryst%ucvol / (one*nfft)
5340 : : !spread = sqrt(r2_mean - dot_product(center_cart, center_cart))
5341 : : !write(msg, "(a,2(es16.6,a))")" Polaron spread: ", spread, " (Bohr)", spread * Bohr_Ang, " (Ang)"
5342 : : !call wrtout(units, msg)
5343 : :
5344 : : ! Compute = \int (r - center_cart)^2 rhor dr = <r^2> - <r>^2
5345 : 4 : spread = zero
5346 [ + + ]: 217 : do i3=1,sc_ngfft(3)
5347 : 213 : rr(3) = (i3 - one) / sc_ngfft(3)
5348 [ + + ]: 12376 : do i2=1,sc_ngfft(2)
5349 : 12159 : rr(2) = (i2 - one) / sc_ngfft(2)
5350 [ + + ]: 760299 : do i1=1,sc_ngfft(1)
5351 : 747927 : rr(1) = (i1 - one) / sc_ngfft(1)
5352 : : ! Go to cartesian coordinates.
5353 [ + + + + : 11966832 : rmr0 = matmul(sc_rprimd, rr) - center_cart
+ + ]
5354 [ + + ]: 3003867 : spread = spread + rhor(i1, i2, i3) * dot_product(rmr0, rmr0)
5355 : : end do
5356 : : end do
5357 : : end do
5358 : 4 : spread = sqrt(spread * num_cells * prim_cryst%ucvol / (one*nfft))
5359 : :
5360 : 4 : call xcart2xred(1, prim_cryst%rprimd, center_cart, center_red)
5361 : 4 : call wrtout(units, sjoin(" Polaron center in Cartesian coordinates: ", ltoa(center_cart), " (Bohr)"))
5362 : 4 : call wrtout(units, sjoin(" Fractional coordinates in terms of the primitive cell:", ltoa(center_red)))
5363 : 4 : write(msg, "(a,2(es16.6,a))")" Polaron spread: ", spread, " (Bohr)", spread * Bohr_Ang, " (Ang)"
5364 : 4 : call wrtout(units, msg)
5365 : : ! full width at half-maximum
5366 : 4 : fwhm = (two * sqrt(two * log(two))) * spread
5367 : 4 : write(msg, "(a,2(es16.6,a))")" Full width at half-maximum (FWHM) ", fwhm, " (Bohr) ", fwhm * Bohr_Ang, " (Ang)"
5368 : 4 : call wrtout(units, msg)
5369 : :
5370 : 4 : end subroutine center_and_spread
5371 : :
5372 [ # # # # : 110592 : end module m_varpeq
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
5373 : : !!***
|