Branch data Line data Source code
1 : : !!****m* ABINIT/m_eph_path
2 : : !! NAME
3 : : !! m_eph_path
4 : : !!
5 : : !! FUNCTION
6 : : !! Compute e-ph matrix elements g(k,q) along an arbitrary path either in k- or q-space.
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 2008-2026 ABINIT group (MG)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! SOURCE
15 : :
16 : : #if defined HAVE_CONFIG_H
17 : : #include "config.h"
18 : : #endif
19 : :
20 : : #include "abi_common.h"
21 : :
22 : : module m_eph_path
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_xmpi
27 : : use m_mpinfo
28 : : use m_errors
29 : : use m_copy
30 : : use m_hamiltonian
31 : : use m_pawcprj
32 : : use m_ephtk
33 : : use netcdf
34 : : use m_nctk
35 : :
36 : : use defs_abitypes, only : mpi_type
37 : : use defs_datatypes, only : pseudopotential_type
38 : : use m_time, only : cwtime, cwtime_report, timab, sec2str
39 : : use m_fstrings, only : itoa, ftoa, sjoin, ktoa, ltoa, strcat
40 : : use m_cgtools, only : cg_zdotc
41 : : use m_crystal, only : crystal_t
42 : : use m_dtset, only : dataset_type
43 : : use m_dtfil, only : datafiles_type
44 : : use m_ebands, only : ebands_t
45 : : use m_getgh1c, only : getgh1c, rf_transgrid_and_pack
46 : : use m_pawang, only : pawang_type
47 : : use m_pawrad, only : pawrad_type
48 : : use m_pawtab, only : pawtab_type
49 : : use m_pawfgr, only : pawfgr_type
50 : : use m_cgwf, only : nscf_t
51 : : use m_bz_mesh, only : kpath_t
52 : : use m_wfd, only : u0_cache_t
53 : : use m_ifc, only : ifc_type
54 : : use m_dvdb, only : dvdb_t
55 : : use m_mlwfovlp, only : wan_t
56 : :
57 : : implicit none
58 : :
59 : : private
60 : : !!***
61 : :
62 : : public :: eph_path_run
63 : :
64 : : contains !=====================================================
65 : : !!***
66 : :
67 : : !----------------------------------------------------------------------
68 : :
69 : : !!****f* m_eph_path/eph_path_run
70 : : !! NAME
71 : : !! eph_path_run
72 : : !!
73 : : !! FUNCTION
74 : : !! Compute e-ph matrix elements g(k,q) along an arbitrary path either in k- or q-space.
75 : : !! Wavefunctions at k and k+q are computed non-self-consistently by invoking the CG eigensolver
76 : : !! starting from the GS potential read from file.
77 : : !! The DFPT potentials at q are usually obtained via Fourier interpolation, but it is also possible
78 : : !! to use fully ab-initio potentials provided the DVDB file contains all the q-points along the path.
79 : : !! This requires performing DFPT calculations for all the q-points, and then merging
80 : : !! all the POT1 files with the mrgdv utility.
81 : : !!
82 : : !! INPUTS
83 : : !! dtfil<datafiles_type>=Variables related to files.
84 : : !! dtset<dataset_type>=All input variables for this dataset.
85 : : !! cryst<crystal_t>=crystal structure parameters
86 : : !! wfk_ebands: electron bands from the input WFK file (used to propagate nelect and fermie to GPATH.nc)
87 : : !! dvdb<dbdb_type>=Database with the DFPT SCF potentials.
88 : : !! ifc<ifc_type>=interatomic force constants and corresponding real space grid info.
89 : : !! pawfgr <type(pawfgr_type)>=fine grid parameters and related data
90 : : !! pawang<pawang_type)>=PAW angular mesh and related data.
91 : : !! pawrad(ntypat*usepaw)<pawrad_type>=Paw radial mesh and related data.
92 : : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
93 : : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
94 : : !! comm=MPI communicator.
95 : : !!
96 : : !! OUTPUT
97 : : !! Only writing.
98 : : !!
99 : : !! SOURCE
100 : :
101 : 2 : subroutine eph_path_run(dtfil, dtset, cryst, wfk_ebands, dvdb, ifc, pawfgr, pawang, pawrad, pawtab, psps, comm)
102 : :
103 : : !Arguments ------------------------------------
104 : : !scalars
105 : : type(datafiles_type),intent(in) :: dtfil
106 : : type(dataset_type),intent(in) :: dtset
107 : : type(crystal_t),intent(in) :: cryst
108 : : type(ebands_t),intent(in) :: wfk_ebands
109 : : type(dvdb_t),intent(inout) :: dvdb
110 : : type(pawang_type),intent(in) :: pawang
111 : : type(pseudopotential_type),intent(in) :: psps
112 : : type(pawfgr_type),intent(in) :: pawfgr
113 : : type(ifc_type),intent(in) :: ifc
114 : : integer,intent(in) :: comm
115 : : !arrays
116 : : type(pawrad_type),intent(in) :: pawrad(psps%ntypat*psps%usepaw)
117 : : type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
118 : :
119 : : !Local variables ------------------------------
120 : : !scalars
121 : : integer,parameter :: istwfk_1 = 1, tim_getgh1c = 1, berryopt0 = 0, master = 0, ndims = 3, ndat1 = 1
122 : : integer :: sij_opt,usecprj,usevnl,optlocal,optnl,opt_gvnlx1, nu
123 : : integer :: spin, iq, ik, nk_path, nq_path, ierr, npw_k, npw_kq, my_rank, nprocs, n1, n2, n3, n4, n5, n6, cplex
124 : : integer :: natom, natom3, nsppol, nspden, nspinor, qptopt, comm_cart, me_cart
125 : : integer :: nfft,nfftf,mgfft,mgfftf, my_npert, my_ip, idir, ipert, ipc, ncerr, ncid, my_nkpath, my_nqpath
126 : : integer :: in_k, im_kq, my_is, my_ik, my_iq, nband, nb_in_g, ii, band_n, band_m, bstart, bstop, my_nspins, np, tot_nscf_ierr
127 : : integer :: my_pert_start_glob, nwan_glob, iglob
128 : : real(dp) :: cpu_all,wall_all,gflops_all, eig0nk, eshift
129 : : logical :: qq_is_gamma, need_ftinterp, gen_eigenpb, use_cg_k, use_cg_kq, use_cache, has_gwan
130 : 2 : type(gs_hamiltonian_type) :: gs_ham_k, gs_ham_kq
131 : 2 : type(rf_hamiltonian_type) :: rf_ham_kq
132 : 2 : type(nscf_t) :: nscf
133 : 2 : type(kpath_t) :: qpath, kpath
134 : : type(xcomm_t),target :: kpt_comm, qpt_comm, pert_comm
135 [ + + + + ]: 14 : type(u0_cache_t) :: ucache_kq, ucache_k
136 [ + + + + ]: 14 : type(wan_t) :: wan
137 : : character(len=fnlen) :: gpath_path
138 : : character(len=5000) :: msg
139 : : character(len=10) :: priority
140 : : !!arrays
141 : : integer :: units(2), ngfft(18),ngfftf(18), coords_spin(ndims), dims(ndims)
142 : 2 : integer,allocatable :: kg_k(:,:), kg_kq(:,:), qmap_symrec(:,:), my_ik_inds(:), my_iq_inds(:), my_spins(:), my_iperts(:)
143 : 2 : integer,allocatable :: pert_table(:,:), my_pinfo(:,:)
144 : 4 : real(dp) :: kk(3), qq(3), kq(3), phfreqs(3*cryst%natom), phfreqs_ev(3*cryst%natom), fake_path(3,2)
145 : 2 : real(dp),allocatable :: grad_berry(:,:), kinpw_k(:), kinpw_kq(:)
146 : 2 : real(dp),allocatable :: cg_k(:,:,:), cg_kq(:,:,:), gsc_k(:,:,:), gsc_kq(:,:,:),eig_k(:), eig_kq(:)
147 : 2 : real(dp),allocatable :: eig_k_wan(:), eig_kq_wan(:,:)
148 : 4 : real(dp),allocatable :: v1scf(:,:,:,:), vlocal1(:,:,:,:), vlocal(:,:,:,:), gkq_atm(:,:,:,:), gkq_nu(:,:,:,:), gkq2_nu(:,:,:)
149 : 2 : real(dp),allocatable :: gkq_atm_wan(:,:,:,:), gkq_nu_wan(:,:,:,:), gkq2_nu_wan(:,:,:)
150 : 2 : complex(dp),allocatable :: g_atm_wan_local(:,:,:,:)
151 : 2 : real(dp),allocatable :: gvnlx1(:,:), gs1c(:,:), h1_kets_kq(:,:,:), displ_cart(:,:,:,:),displ_red_qq(:,:,:,:)
152 : 4 : real(dp),allocatable :: kpg_k(:,:), ph3d_k(:,:,:), ffnl_k(:,:,:,:), vlocal_k(:,:,:,:)
153 : 2 : real(dp),allocatable :: kpg_kq(:,:), ph3d_kq(:,:,:), ffnl_kq(:,:,:,:), vlocal_kq(:,:,:,:), real_vec(:)
154 : : logical :: reorder, periods(ndims), keepdim(ndims)
155 : 2 : type(pawcprj_type),allocatable :: cwaveprj0(:,:)
156 : 2 : type(xcomm_t),allocatable :: comm_my_is(:)
157 : : !************************************************************************
158 : :
159 [ - + ]: 2 : if (psps%usepaw == 1) then
160 : 0 : ABI_ERROR("PAW not implemented")
161 : : ABI_UNUSED((/pawang%nsym, pawrad(1)%mesh_size/))
162 : : end if
163 : :
164 : 2 : call cwtime(cpu_all, wall_all, gflops_all, "start")
165 : 2 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
166 [ + + ]: 6 : units = [std_out, ab_out]
167 : :
168 : : ! Copy important dimensions.
169 : 2 : natom = cryst%natom; natom3 = 3 * natom; nsppol = dtset%nsppol; nspinor = dtset%nspinor; nspden = dtset%nspden
170 : :
171 : : ! Build (k/q)-path. NB: Input variables have been already checked for consistency in chkinp.
172 : 1 : select case (dtset%eph_fix_korq)
173 : : case ("k")
174 : 1 : call qpath%init(dtset%ph_qpath(:,1:dtset%ph_nqpath), cryst%gprimd, dtset%ph_ndivsm)
175 : 1 : nq_path = qpath%npts
176 : 1 : call qpath%print(units, header=sjoin("q-point path for g(k,q) with fixed k:", ktoa(dtset%eph_fix_wavevec)), prtvol=dtset%prtvol)
177 [ + + + + ]: 7 : fake_path(:,1) = dtset%eph_fix_wavevec; fake_path(:,2) = dtset%eph_fix_wavevec + one
178 : 1 : call kpath%init(fake_path, cryst%gprimd, 0)
179 : 1 : nk_path = 1
180 : :
181 : : case ("q")
182 : 1 : call kpath%init(dtset%kptbounds(:,1:dtset%nkpath), cryst%gprimd, dtset%ndivsm)
183 : 1 : nk_path = kpath%npts
184 : 1 : call kpath%print(units, header=sjoin("k-point path for g(k,q) with fixed q:", ktoa(dtset%eph_fix_wavevec)), prtvol=dtset%prtvol)
185 [ + + + + ]: 7 : fake_path(:,1) = dtset%eph_fix_wavevec; fake_path(:,2) = dtset%eph_fix_wavevec + one
186 : 1 : call qpath%init(fake_path, cryst%gprimd, 0)
187 : 1 : nq_path = 1
188 : :
189 : : case default
190 [ + + - ]: 2 : ABI_ERROR(sjoin("Invalid value of eph_fix_korq:", dtset%eph_fix_korq))
191 : : end select
192 : :
193 : : ! Define band range and nb_in_g from eph_path_brange.
194 : 2 : nband = dtset%mband; bstart = dtset%eph_path_brange(1); bstop = dtset%eph_path_brange(2)
195 : :
196 : : ! Check whether e-ph matrix elements should also be computed via Wannier interpolation from
197 : : ! GWAN.nc, for comparison against the ab-initio results computed below.
198 : 2 : has_gwan = (dtfil%filgwanin /= ABI_NOFILE)
199 : 2 : nwan_glob = 0
200 [ - + ]: 2 : if (has_gwan) then
201 [ # # ]: 0 : ABI_CHECK(dtfil%filabiwanin /= ABI_NOFILE, "getgwan_filepath requires getabiwan_filepath to be given as well when eph_task=18.")
202 [ # # ]: 0 : ABI_CHECK(dtset%nsppol == 1, "has_gwan with nsppol == 2 is not yet supported in eph_path_run.")
203 : :
204 : : ! Cheap, non-collective read of ABIWAN.nc metadata, purely to validate/auto-set eph_path_brange
205 : : ! (mirrors gstore_init's has_abiwan branch, m_gstore.F90).
206 : 0 : call wan%from_abiwan(dtfil%filabiwanin, 1, dtset%nsppol, .False., "", xmpi_comm_self)
207 [ # # ]: 0 : if (bstart <= 0 .and. bstop <= 0) then
208 : 0 : bstart = wan%bmin; bstop = wan%bmax
209 [ # # ]: 0 : call wrtout(units, sjoin(" has_gwan: auto-setting eph_path_brange to Wannier band window:", ltoa([bstart,bstop])))
210 : : else
211 [ # # ]: 0 : if (bstart <= 0) bstart = 1
212 [ # # ]: 0 : if (bstop <= 0) bstop = nband
213 : : msg = sjoin("eph_path_brange:", ltoa([bstart,bstop]), "must equal [wan%bmin, wan%bmax]:", ltoa([wan%bmin, wan%bmax]), &
214 [ # # # # : 0 : "when getgwan_filepath is given (the gauge-invariant trace comparison needs the same electronic subspace).")
# # ]
215 [ # # # # ]: 0 : ABI_CHECK(bstart == wan%bmin .and. bstop == wan%bmax, msg)
216 : : end if
217 : 0 : nwan_glob = wan%nwan
218 : 0 : call wan%free()
219 : : else
220 [ - + ]: 2 : if (bstart <= 0) bstart = 1
221 [ - + ]: 2 : if (bstop <= 0) bstop = nband
222 : : end if
223 : :
224 : 2 : nb_in_g = bstop - bstart + 1
225 : :
226 : : ! The values of eph_path_brange must be validated at this level!
227 [ - + ]: 2 : ABI_CHECK_IRANGE(bstart, 1, nband, "Wrong eph_path_brange(1)")
228 [ + - - + ]: 2 : ABI_CHECK_IRANGE(bstop, 1, nband, "Wrong eph_path_brange(2)")
229 [ - + ]: 2 : ABI_CHECK_IGEQ(bstop, bstart, "eph_path_brange(2) < eph_path_brange(1)")
230 [ + + ]: 6 : call wrtout(units, sjoin(" Computing g(k,q) with eph_path_brange:", ltoa([bstart, bstop])))
231 : :
232 : : ! Distribute spins inside input comm.
233 [ - + - + ]: 2 : call xmpi_split_nsppol(comm, nsppol, my_nspins, my_spins, comm_my_is)
234 : :
235 : : ! ==================
236 : : ! MPI cartesian grid
237 : : ! ==================
238 : 2 : my_npert = natom3
239 [ + + ]: 4 : do my_is=1,my_nspins
240 : 2 : spin = my_spins(my_is)
241 : 2 : np = comm_my_is(my_is)%nproc; priority = "12"
242 : :
243 [ + + + - : 12 : if (any(dtset%eph_np_pqbks /= 0)) then
- + ]
244 : : ! Take MPI grid from input.
245 : 0 : pert_comm%nproc = dtset%eph_np_pqbks(1)
246 : 0 : qpt_comm%nproc = dtset%eph_np_pqbks(2)
247 [ # # ]: 0 : ABI_CHECK_IEQ(dtset%eph_np_pqbks(3), 1, "Band parallelism not implemented in eph_path")
248 : 0 : kpt_comm%nproc = dtset%eph_np_pqbks(4)
249 : :
250 : : else
251 : : ! Automatic MPI grid generation.
252 [ + + ]: 2 : if (nk_path == 1) then
253 : 1 : call xmpi_distrib_2d(np, priority, nq_path, natom3, qpt_comm%nproc, pert_comm%nproc, ierr)
254 : : else
255 : 1 : call xmpi_distrib_2d(np, priority, nk_path, natom3, kpt_comm%nproc, pert_comm%nproc, ierr)
256 : : end if
257 [ - + ]: 2 : ABI_CHECK(ierr == 0, sjoin("Cannot distribute nprocs:", itoa(np), " with priority: ", priority, ". Decrease MPI nprocs"))
258 : : end if
259 : :
260 : : ! Consistency check
261 : 2 : write(msg, "(a,i2,a,3(i0,1x))")"P Cartesian grid for spin", spin, ": (pert_comm%nproc, qpt_comm%nproc, kpt_comm%nproc) = ", &
262 : 4 : pert_comm%nproc, qpt_comm%nproc, kpt_comm%nproc
263 : 2 : call wrtout(units, msg)
264 : :
265 [ - + ]: 2 : if (pert_comm%nproc * qpt_comm%nproc * kpt_comm%nproc /= np) then
266 : : write(msg, "(a,i0,3a, 4(a,1x,i0))") &
267 : 0 : "Cannot create Cartesian grid with nproc(spin): ", np, ch10, &
268 : 0 : "Idle processes are not supported. The product of the `nproc_*` vars should be equal to nproc.", ch10, &
269 : 0 : "qpt_nproc (", qpt_comm%nproc, ") x kpt_nproc (", kpt_comm%nproc, ") x pert_nproc", pert_comm%nproc, &
270 : 0 : ") != ", np
271 : 0 : ABI_ERROR(msg)
272 : : end if
273 : :
274 : : ! For each spin treated by this rank, create MPI cartesian communicator of rank ndims.
275 : 2 : periods(:) = .False.; reorder = .False.
276 [ + + ]: 8 : dims = [pert_comm%nproc, qpt_comm%nproc, kpt_comm%nproc]
277 : :
278 : : #ifdef HAVE_MPI
279 : 2 : call MPI_CART_CREATE(comm_my_is(my_is)%value, ndims, dims, periods, reorder, comm_cart, ierr)
280 : : ! Find the index and coordinates of the current processor
281 : 2 : call MPI_COMM_RANK(comm_cart, me_cart, ierr)
282 : 2 : call MPI_CART_COORDS(comm_cart, me_cart, ndims, coords_spin, ierr)
283 : :
284 : : ! Communicator for q-points in g(k,q)
285 : 2 : keepdim = .False.; keepdim(1) = .True.; call pert_comm%from_cart_sub(comm_cart, keepdim)
286 : 2 : keepdim = .False.; keepdim(2) = .True.; call qpt_comm%from_cart_sub(comm_cart, keepdim)
287 : 2 : keepdim = .False.; keepdim(3) = .True.; call kpt_comm%from_cart_sub(comm_cart, keepdim)
288 : 4 : call xmpi_comm_free(comm_cart)
289 : : #endif
290 : : end do ! my_is
291 : :
292 : : ! Distribute k-points (q-points) inside kpt_comm (qpt_comm) using block distribution.
293 [ - + ]: 2 : call xmpi_split_block(nk_path, kpt_comm%value, my_nkpath, my_ik_inds)
294 [ - + ]: 2 : call xmpi_split_block(nq_path, qpt_comm%value, my_nqpath, my_iq_inds)
295 [ - + ]: 2 : call xmpi_split_block(natom3, pert_comm%value, my_npert, my_iperts)
296 : 2 : my_pert_start_glob = my_iperts(1)
297 : 2 : ABI_FREE(my_iperts)
298 : :
299 : : ! Idle processors are not supported (tested).
300 [ - + ]: 2 : ABI_CHECK_IGEQ(my_nkpath, 1, "Too many procs for k-point parallelism.")
301 [ - + ]: 2 : ABI_CHECK_IGEQ(my_nqpath, 1, "Too many procs for q-point parallelism.")
302 [ - + ]: 2 : ABI_CHECK_IGEQ(my_npert, 1, "Too many procs for perturbation parallelism.")
303 : :
304 [ - + ]: 2 : if (pert_comm%nproc > 1) then
305 : : ! Build table with list of perturbations treated by this CPU inside pert_comm
306 [ # # # # ]: 0 : call ephtk_set_pertables(cryst%natom, my_npert, pert_table, my_pinfo, pert_comm%value)
307 : : ! Activate parallelism over perturbations
308 : 0 : call dvdb%set_pert_distrib(my_npert, natom3, my_pinfo, pert_table, pert_comm%value)
309 [ # # ]: 0 : ABI_FREE(my_pinfo)
310 [ # # ]: 0 : ABI_FREE(pert_table)
311 : 0 : ABI_WARNING("Parallelism over perturbations should be tested!")
312 : : end if
313 : :
314 : : ! Load KS potential from file.
315 : 2 : call nscf%init(dtset, dtfil, cryst, comm)
316 : :
317 : : ! FFT meshes (taken from the GS POT file)
318 [ + + + + ]: 74 : ngfft = nscf%ngfft; ngfftf = nscf%ngfftf
319 [ + + ]: 8 : nfftf = product(ngfftf(1:3)); mgfftf = maxval(ngfftf(1:3))
320 [ + + ]: 8 : nfft = product(ngfft(1:3)) ; mgfft = maxval(ngfft(1:3))
321 : 2 : n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); n4 = ngfft(4); n5 = ngfft(5); n6 = ngfft(6)
322 : :
323 : : ! Open the DVDB file and make sure we have POT1 files.
324 : 2 : call dvdb%open_read(ngfftf, xmpi_comm_self)
325 [ - + ]: 2 : ABI_CHECK(dvdb%has_fields("pot1", msg), msg)
326 : :
327 : : ! Check if all the q-points are present in the DVDB.
328 [ - + ]: 2 : qptopt = dtset%kptopt; if (dtset%qptopt /= 0) qptopt = dtset%qptopt
329 [ - + ]: 2 : call dvdb%need_ftinterp(nq_path, qpath%points, qptopt, qmap_symrec, need_ftinterp)
330 : :
331 [ - + - - ]: 2 : if (.not. need_ftinterp .and. dtset%eph_use_ftinterp /= 0) then
332 : 0 : ABI_COMMENT("Enforcing FT interpolation for q-points even if it's not strictly needed.")
333 : 0 : need_ftinterp = .True.
334 : : end if
335 : :
336 [ + - ]: 2 : if (need_ftinterp) then
337 : 2 : call wrtout(units, " Cannot find all q-points in the DVDB --> Activating Fourier interpolation.")
338 : 2 : call dvdb%ftinterp_setup(dtset%ddb_ngqpt, qptopt, 1, dtset%ddb_shiftq, nfftf, ngfftf, xmpi_comm_self)
339 : : else
340 : 0 : call wrtout(units, " DVDB file contains all q-points along the path --> Reading DFPT potentials from file.")
341 : : end if
342 : :
343 : : ! Prepare call to getgh1c
344 : 2 : usevnl = 0
345 : 2 : optlocal = 1 ! local part of H^(1) is computed in gh1c=<G|H^(1)|C>
346 : 2 : optnl = 2 ! non-local part of H^(1) is totally computed in gh1c=<G|H^(1)|C>
347 : 2 : opt_gvnlx1 = 0 ! gvnlx1 is output
348 : 2 : usecprj = 0
349 : :
350 [ - + ]: 2 : ABI_MALLOC(gvnlx1, (2, usevnl))
351 [ - + - + ]: 2 : ABI_MALLOC(grad_berry, (2, nspinor*(berryopt0/4)))
352 [ - + + - : 4 : ABI_MALLOC(cwaveprj0, (natom, nspinor*usecprj))
- + - + -
+ ]
353 [ - + + - : 8 : ABI_MALLOC(displ_cart, (2, 3, cryst%natom, natom3))
- + + - +
- + - - +
- + - + ]
354 [ - + + - : 6 : ABI_MALLOC(displ_red_qq, (2, 3, cryst%natom, natom3))
- + + - -
+ - + ]
355 [ - + + - : 10 : ABI_MALLOC(gkq_atm, (2, nb_in_g, nb_in_g, natom3))
- + + - -
+ + - + -
+ - - + -
+ - + ]
356 [ - + + - : 8 : ABI_MALLOC(gkq_nu, (2, nb_in_g, nb_in_g, natom3))
- + + - -
+ + - - +
- + ]
357 [ - + + - : 10 : ABI_MALLOC(gkq2_nu, (nb_in_g, nb_in_g, natom3))
- + + - -
+ + - + -
+ - - + -
+ - + ]
358 : :
359 [ - + ]: 2 : if (has_gwan) then
360 [ # # # # : 0 : ABI_MALLOC(gkq_atm_wan, (2, nwan_glob, nwan_glob, natom3))
# # # # #
# # # # #
# # # # #
# # # ]
361 [ # # # # : 0 : ABI_MALLOC(gkq_nu_wan, (2, nwan_glob, nwan_glob, natom3))
# # # # #
# # # # #
# # ]
362 [ # # # # : 0 : ABI_MALLOC(gkq2_nu_wan, (nwan_glob, nwan_glob, natom3))
# # # # #
# # # # #
# # # # #
# # # ]
363 [ # # # # : 0 : ABI_MALLOC(eig_k_wan, (nwan_glob))
# # # # #
# # # #
# ]
364 [ # # # # : 0 : ABI_MALLOC(eig_kq_wan, (nwan_glob, 1))
# # # # ]
365 : : end if
366 : :
367 : : ! Master writes metadata to GPATH file.
368 [ + - ]: 2 : gpath_path = strcat(dtfil%filnam_ds(4), "_GPATH.nc")
369 : :
370 [ + - ]: 2 : if (my_rank == master) then
371 [ - + ]: 2 : NCF_CHECK(nctk_open_create(ncid, gpath_path, xmpi_comm_self))
372 : : ! Add crystalline structure.
373 [ - + ]: 2 : NCF_CHECK(cryst%ncwrite(ncid))
374 : :
375 : : ! Write dimensions.
376 : : ncerr = nctk_def_dims(ncid, [ &
377 : : nctkdim_t("nspinor", nspinor), nctkdim_t("nspden", nspden), nctkdim_t("nsppol", nsppol), &
378 : : nctkdim_t("nband", nband), nctkdim_t("nb_in_g", nb_in_g), &
379 : : nctkdim_t("nq_path", nq_path), nctkdim_t("nk_path", nk_path), &
380 : : nctkdim_t("natom", cryst%natom), nctkdim_t("natom3", natom3), nctkdim_t("number_of_phonon_modes", natom3) &
381 [ + + ]: 22 : ], defmode=.True.)
382 [ - + ]: 2 : NCF_CHECK(ncerr)
383 : :
384 : : ! integer scalars
385 : : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: &
386 : : "bstart", "bstop", "dvdb_add_lr", "used_ftinterp" &
387 [ + + ]: 10 : ])
388 [ - + ]: 2 : NCF_CHECK(ncerr)
389 : :
390 : : ! double precision scalars
391 : : ncerr = nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: &
392 : : "nelect", "fermie" &
393 [ + + ]: 6 : ])
394 [ - + ]: 2 : NCF_CHECK(ncerr)
395 : :
396 : : ncerr = nctk_def_arrays(ncid, [ &
397 : : nctkarr_t("kpoints", "dp", "three, nk_path"), &
398 : : nctkarr_t("qpoints", "dp", "three, nq_path"), &
399 : : nctkarr_t("qweights", "dp", "nq_path"), &
400 : : nctkarr_t("all_eigens_k", "dp", "nband, nk_path, nsppol"), &
401 : : nctkarr_t("all_eigens_kq", "dp", "nband, nq_path, nsppol"), &
402 : : nctkarr_t("gkq2_nu", "dp", "nb_in_g, nb_in_g, natom3, nq_path, nk_path, nsppol"), &
403 : : nctkarr_t("phfreqs", "dp", "natom3, nq_path"), &
404 : : nctkarr_t("phdispl_cart", "dp", "two, three, natom, natom3, nq_path"), &
405 : : nctkarr_t("eph_fix_korq", "c", "one"), &
406 : : nctkarr_t("eph_fix_wavevec", "dp", "three") &
407 [ + + ]: 22 : ])
408 [ - + ]: 2 : NCF_CHECK(ncerr)
409 : :
410 [ - + ]: 2 : NCF_CHECK(nf90_def_var_fill(ncid, vid("gkq2_nu"), NF90_FILL, -one))
411 [ - + ]: 2 : NCF_CHECK(nf90_def_var_fill(ncid, vid("phfreqs"), NF90_FILL, -one))
412 : :
413 [ - + ]: 2 : if (has_gwan) then
414 [ # # ]: 0 : ncerr = nctk_def_dims(ncid, [nctkdim_t("nwan", nwan_glob)], defmode=.True.)
415 [ # # ]: 0 : NCF_CHECK(ncerr)
416 : : ncerr = nctk_def_arrays(ncid, [ &
417 : : ! Use the same path convention as the ab-initio eigenvalues: k varies when q
418 : : ! is fixed, whereas k+q varies with q when k is fixed.
419 : : nctkarr_t("all_eigens_wan_k", "dp", "nwan, nk_path, nsppol"), &
420 : : nctkarr_t("all_eigens_wan_kq", "dp", "nwan, nq_path, nsppol"), &
421 : : nctkarr_t("gkq2_nu_wan", "dp", "nwan, nwan, natom3, nq_path, nk_path, nsppol") &
422 [ # # ]: 0 : ])
423 [ # # ]: 0 : NCF_CHECK(ncerr)
424 [ # # ]: 0 : NCF_CHECK(nf90_def_var_fill(ncid, vid("gkq2_nu_wan"), NF90_FILL, -one))
425 : : end if
426 : :
427 : : ! Write data.
428 [ - + ]: 2 : NCF_CHECK(nctk_set_datamode(ncid))
429 [ - + ]: 2 : ii = merge(1, 0, need_ftinterp)
430 : : ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: &
431 : : "bstart", "bstop", "dvdb_add_lr", "used_ftinterp"], &
432 : : [bstart, bstop, dtset%dvdb_add_lr, ii &
433 [ + + + + ]: 18 : ])
434 [ - + ]: 2 : NCF_CHECK(ncerr)
435 : :
436 : : ncerr = nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: &
437 : : "nelect", "fermie"], &
438 : : [wfk_ebands%nelect, wfk_ebands%fermie &
439 [ + + + + ]: 10 : ])
440 [ - + ]: 2 : NCF_CHECK(ncerr)
441 : :
442 : : ! arrays
443 [ - + ]: 2 : NCF_CHECK(nf90_put_var(ncid, vid("kpoints"), kpath%points(:,1:nk_path)))
444 [ - + ]: 2 : NCF_CHECK(nf90_put_var(ncid, vid("qpoints"), qpath%points(:,1:nq_path)))
445 [ - + + - : 6 : ABI_MALLOC(real_vec, (nq_path))
+ - + - -
+ - + -
+ ]
446 [ + + ]: 45 : real_vec = one
447 [ - + ]: 2 : NCF_CHECK(nf90_put_var(ncid, vid("qweights"), real_vec))
448 [ - + ]: 2 : ABI_FREE(real_vec)
449 [ - + ]: 2 : NCF_CHECK(nf90_put_var(ncid, vid("eph_fix_korq"), dtset%eph_fix_korq))
450 [ - + ]: 2 : NCF_CHECK(nf90_put_var(ncid, vid("eph_fix_wavevec"), dtset%eph_fix_wavevec))
451 : :
452 : : ! Compute non-analytic phonons for q--> 0 in polar materials.
453 [ + - + - : 2 : if (nq_path > 1 .and. (any(ifc%zeff /= zero))) call ifc%calcnwrite_nana_terms_qpath(qpath, cryst, ncid, units)
+ - - + +
+ + - ]
454 [ - + ]: 2 : NCF_CHECK(nf90_close(ncid))
455 : : end if ! master
456 : :
457 : : ! Make sure the netcdf file has been written by master before continuing.
458 : 2 : call xmpi_barrier(comm)
459 : :
460 : : ! All procs open the GPATH file here.
461 : : ! FIXME
462 : : !NCF_CHECK(nctk_open_modify(ncid, gpath_path, comm))
463 [ - + ]: 2 : NCF_CHECK(nctk_open_modify(ncid, gpath_path, xmpi_comm_self))
464 : :
465 : : ! The cache allows one the reuse the wavefunctions of the previous k/q to init the NSCF cycle
466 : : ! It usually reduces the number of iterations by 3-4 but it requires more memory.
467 : 2 : tot_nscf_ierr = 0; use_cache = .True. !; use_cache = .False.
468 [ + + ]: 3 : call ucache_k%init(use_cache .and. my_nkpath > 1, ngfft)
469 [ + + ]: 3 : call ucache_kq%init(use_cache .and. my_nqpath > 1, ngfft)
470 : :
471 : : ! Loop over spins (MPI parallelized)
472 [ + + ]: 4 : do my_is=1,my_nspins
473 : 2 : spin = my_spins(my_is)
474 : :
475 [ - + ]: 2 : if (has_gwan) then
476 : : ! Build wan for this spin from the ABIWAN.nc file, set the perturbation distribution
477 : : ! from THIS routine's own pert_comm (same natom3 block-distribution used for the
478 : : ! ab-initio gkq_atm below), then load g(R_e, R_p) from GWAN.nc.
479 : 0 : call wan%from_abiwan(dtfil%filabiwanin, spin, dtset%nsppol, .False., "", comm_my_is(my_is)%value)
480 : 0 : wan%my_pert_start = my_pert_start_glob; wan%my_npert = my_npert; wan%pert_comm => pert_comm
481 : 0 : call wan%load_gwan(dtfil%filgwanin, cryst, spin, dtset%nsppol, comm_my_is(my_is))
482 : : end if
483 : :
484 : : ! Loop over k-points in k-path (MPI parallelized).
485 [ + + ]: 45 : do my_ik=1,my_nkpath
486 [ + + ]: 172 : ik = my_ik_inds(my_ik); kk = kpath%points(:, ik)
487 : : !print *, "ik, kk", ik, kk
488 : :
489 : : ! Prepare NSCF run at k.
490 : : ! gs_ham_k has pointers to the *_k arrays in output so we cannot deallocate them till the end.
491 : : ! This is the reason why we use vlocal_k although this term does not depend on k
492 : : call nscf%setup_kpt(spin, kk, istwfk_1, nband, cryst, dtset, psps, pawtab, pawfgr, & ! in
493 [ - + - + : 43 : npw_k, kg_k, kpg_k, ph3d_k, kinpw_k, ffnl_k, vlocal_k, cg_k, gsc_k, gs_ham_k) ! out
- + - + -
+ - + - +
- + ]
494 : :
495 : : ! Cache to initialize u_{nk}(g).
496 [ + + - + ]: 43 : use_cg_k = (my_ik > 1 .and. ucache_k%use_cache)
497 [ + + ]: 43 : if (use_cg_k) call ucache_k%get_kpt(kk, istwfk_1, npw_k, nspinor, nband, kg_k, cg_k)
498 : :
499 : : ! Compute u_{nk}(g)
500 : : call nscf%solve_kpt(spin, kk, istwfk_1, nband, cryst, dtset, dtfil, gs_ham_k, &
501 [ - + ]: 43 : use_cg_k, npw_k, cg_k, gsc_k, eig_k, msg, ierr)
502 : :
503 [ - + ]: 43 : ABI_WARNING_IF(ierr /= 0, msg)
504 : 43 : tot_nscf_ierr = tot_nscf_ierr + ierr
505 : :
506 : 43 : call ucache_k%store_kpt(kk, istwfk_1, npw_k, nspinor, nband, kg_k, cg_k)
507 : :
508 : : !if (pert_comm%me == master) then
509 [ + + - + : 172 : NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_k"), eig_k, start=[1,ik,spin]))
- - ]
510 : : !end if
511 : :
512 : : ! Make sure all procs in pert_comm have the same wavefunctions at k.
513 : 43 : call xmpi_bcast(cg_k, master, pert_comm%value, ierr)
514 [ - + ]: 43 : if (psps%usepaw == 1) call xmpi_bcast(gsc_k, master, pert_comm%value, ierr)
515 : :
516 : : ! Allocate vlocal. Note nvloc
517 [ - + + - : 258 : ABI_MALLOC(vlocal, (n4, n5, n6, gs_ham_k%nvloc))
- + + - -
+ + - - +
+ - + - +
- - + -
+ ]
518 : :
519 : : ! Loop over q-points in q-path (MPI parallelized).
520 : : ! All procs in pert_comm enter this loop with the same ik/iq indices.
521 [ + + ]: 127 : do my_iq=1,my_nqpath
522 [ + + + + ]: 588 : iq = my_iq_inds(my_iq); qq = qpath%points(:,iq); qq_is_gamma = sum(qq**2) < tol14
523 [ + + ]: 336 : kq = kk + qq
524 : : !print *, "iq, kq", iq, kq
525 : :
526 : : ! Prepare NSCF run at k+q.
527 : : ! gs_ham_kq has pointers to the *_kq arrays in output so we cannot deallocate them till the end.
528 : : ! This is the reason why we use vlocal_kq although this term does not depend on k+q.
529 : : call nscf%setup_kpt(spin, kq, istwfk_1, nband, cryst, dtset, psps, pawtab, pawfgr, & ! in
530 [ - + - + : 84 : npw_kq, kg_kq, kpg_kq, ph3d_kq, kinpw_kq, ffnl_kq, vlocal_kq, cg_kq, gsc_kq, gs_ham_kq) ! out
- + - + -
+ - + - +
- + ]
531 : :
532 : : ! Cache for u_{m k+q}(g).
533 [ + + - + ]: 84 : use_cg_kq = (my_iq > 1 .and. ucache_kq%use_cache)
534 [ + + ]: 84 : if (use_cg_kq) call ucache_kq%get_kpt(kq, istwfk_1, npw_kq, nspinor, nband, kg_kq, cg_kq)
535 : :
536 : : ! We can use cg_k as input for the NSCF for a very quick return.
537 [ + + ]: 84 : if (qq_is_gamma) then
538 [ + - + - : 134284 : use_cg_kq = .True.; cg_kq = cg_k
+ - - + -
- - - - -
- - + + +
+ + + ]
539 : : end if
540 : :
541 : : ! Compute u_{m k+q}(g)
542 : : call nscf%solve_kpt(spin, kq, istwfk_1, nband, cryst, dtset, dtfil, gs_ham_kq, &
543 [ - + ]: 84 : use_cg_kq, npw_kq, cg_kq, gsc_kq, eig_kq, msg, ierr)
544 : :
545 [ - + ]: 84 : ABI_WARNING_IF(ierr /= 0, msg)
546 : 84 : tot_nscf_ierr = tot_nscf_ierr + ierr
547 : :
548 : 84 : call ucache_kq%store_kpt(kq, istwfk_1, npw_kq, nspinor, nband, kg_kq, cg_kq)
549 : :
550 : : ! This to have the same gauge when qq = 0.
551 [ + + + - : 134366 : if (qq_is_gamma) cg_kq = cg_k
+ - + - -
+ - - - -
- - - - +
+ + + +
+ ]
552 : :
553 : : ! Make sure all procs in pert_comm have the same wavefunctions at k+q.
554 : 84 : call xmpi_bcast(cg_kq, master, pert_comm%value, ierr)
555 [ - + ]: 84 : if (psps%usepaw == 1) call xmpi_bcast(gsc_kq, master, pert_comm%value, ierr)
556 : :
557 : : ! Get phonons for this q-point.
558 : 84 : call ifc%fourq(cryst, qq, phfreqs, displ_cart, out_displ_red=displ_red_qq)
559 [ + + ]: 588 : phfreqs_eV = phfreqs * Ha_eV
560 : :
561 : : ! Only the global first k-point contributes to q-path-only variables.
562 [ + + ]: 84 : if (ik == 1) then
563 [ + + - + : 172 : NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_kq"), eig_kq, start=[1,iq,spin]))
- - ]
564 : : ! Write phonons for this qpt.
565 [ + - ]: 43 : if (spin == 1) then
566 [ + + - + : 129 : NCF_CHECK(nf90_put_var(ncid, vid("phfreqs"), phfreqs_ev, start=[1,iq]))
- - ]
567 [ + + - + : 258 : NCF_CHECK(nf90_put_var(ncid, vid("phdispl_cart"), displ_cart, start=[1,1,1,1,iq]))
- - ]
568 : : end if
569 : : end if
570 : :
571 : : ! For PAW, one has to solve a generalized eigenproblem.
572 [ - + ]: 84 : gen_eigenpb = psps%usepaw == 1; sij_opt = 0; if (gen_eigenpb) sij_opt = 1
573 [ + - - - : 252 : ABI_MALLOC(gs1c, (2, npw_kq*nspinor*((sij_opt+1)/2)))
+ - - + -
+ - + ]
574 [ - + + - : 336 : ABI_MALLOC(h1_kets_kq, (2, npw_kq*nspinor, nb_in_g))
- + + - +
- + - - +
- + ]
575 : :
576 : : ! ====================================
577 : : ! Get DFPT potentials for this q-point
578 : : ! ====================================
579 : : ! After this branch we have allocated v1scf(cplex, nfftf, nspden, my_npert)).
580 [ + - ]: 84 : if (need_ftinterp) then
581 [ - + ]: 84 : call dvdb%get_ftqbz(qq, cplex, nfftf, ngfftf, v1scf, pert_comm%value)
582 : : else
583 : : ! Read and reconstruct the dvscf potentials for qq and my_npert perturbations.
584 [ # # ]: 0 : call dvdb%readsym_qbz(cryst, qq, qmap_symrec(:,iq), cplex, nfftf, ngfftf, v1scf, pert_comm%value)
585 : : end if
586 : :
587 : : ! Allocate vlocal1 with correct cplex. Note nvloc.
588 [ - + + - : 504 : ABI_MALLOC(vlocal1, (cplex*n4, n5, n6, gs_ham_kq%nvloc))
- + + - -
+ + - - +
+ - + - +
- - + - +
- + ]
589 : :
590 : : ! Load the k/k+q dependent parts of the Hamiltonian.
591 : : ! NB: In this routine we have to use gs_ham_k to have {k+q}_H0_k.
592 : : ! Using gs_ham_kq would be wrong as it would lead to {k+q}_H0_{k+q}.
593 : :
594 : : call gs_ham_k%load_kprime(kpt_kp=kq, npw_kp=npw_kq, istwf_kp=istwfk_1, kg_kp=kg_kq, kpg_kp=kpg_kq, kinpw_kp=kinpw_kq, &
595 : 84 : ph3d_kp=ph3d_kq, ffnl_kp=ffnl_kq, compute_ph3d=.true., compute_gbound=.true.)
596 : : !call gs_ham_k%print([std_out], "gs_ham_k after load", dtset%prtvol)
597 : :
598 : : ! Loop over my atomic perturbations: apply H1_{kappa, alpha} and compute gkq_atm.
599 [ + + + + : 15708 : gkq_atm = zero
+ + + + ]
600 [ + + ]: 588 : do my_ip=1,my_npert
601 : 504 : idir = dvdb%my_pinfo(1, my_ip); ipert = dvdb%my_pinfo(2, my_ip); ipc = dvdb%my_pinfo(3, my_ip)
602 : :
603 : : ! Set up local potential vlocal1 with proper dimensioning from vtrial1 taking into account the spin.
604 : : call rf_transgrid_and_pack(spin, nspden, psps%usepaw, cplex, nfftf, nfft, ngfft, gs_ham_kq%nvloc,&
605 : 504 : pawfgr, nscf%mpi_enreg, nscf%vtrial, v1scf(:,:,:,my_ip), vlocal, vlocal1)
606 : :
607 : : ! Prepare application of the NL part.
608 : 504 : call rf_ham_kq%init(cplex, gs_ham_k, ipert, has_e1kbsc=.true.)
609 : 504 : call rf_ham_kq%load_spin(spin, vlocal1=vlocal1, with_nonlocal=.true.)
610 : : ! Load k-dependent part in the 1st-order Hamiltonian datastructure
611 : : !call rf_ham_kq%load_k(npw_k=npw_k)
612 : :
613 : : ! Calculate dvscf * psi_k, results stored in h1_kets_kq on the k+q sphere.
614 : : ! Compute H(1) applied to GS wavefunction Psi(0).
615 [ + + ]: 2016 : do in_k=1,nb_in_g
616 : 1512 : band_n = in_k + bstart - 1
617 : 1512 : eig0nk = eig_k(band_n)
618 : : ! Use scissor shift on 0-order eigenvalue.
619 : 1512 : eshift = eig0nk - dtset%dfpt_sciss
620 : :
621 : : call getgh1c(berryopt0, cg_k(:,:,band_n), cwaveprj0, h1_kets_kq(:,:,in_k), &
622 : : grad_berry, gs1c, gs_ham_k, gvnlx1, idir, ipert, [eshift], nscf%mpi_enreg, ndat1, optlocal, &
623 [ + + ]: 3528 : optnl, opt_gvnlx1, rf_ham_kq, sij_opt, tim_getgh1c, usevnl)
624 : : !print *, "maxval(abs(h1_kets_kq(:,:,in_k))): ", maxval(abs(h1_kets_kq(:,:,in_k)))
625 : : end do ! in_k
626 : :
627 : : ! Calculate <psi_{k+q,j}|dvscf_q*psi_{k,i}> for this perturbation. No need to handle istwf_kq because it's always 1.
628 : : !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(band_m)
629 [ + + ]: 2100 : do in_k=1,nb_in_g
630 [ + + ]: 6552 : do im_kq=1,nb_in_g
631 : 4536 : band_m = im_kq + bstart - 1
632 : 6048 : gkq_atm(:, im_kq, in_k, ipc) = cg_zdotc(npw_kq*nspinor, cg_kq(:,:,band_m), h1_kets_kq(:,:,in_k))
633 : : end do
634 : : end do
635 : :
636 : : end do ! my_ip
637 : :
638 : : ! Collect gkq_atm inside pert_comm so that all procs can operate on the data.
639 [ - + ]: 84 : if (pert_comm%nproc > 1) call xmpi_sum(gkq_atm, pert_comm%value, ierr)
640 : :
641 : : ! From atom to phonon mode representation. Results stored in gkq_nu.
642 : 84 : call ephtk_gkknu_from_atm(nb_in_g, nb_in_g, 1, natom, gkq_atm, phfreqs, displ_red_qq, gkq_nu)
643 : : !print *, "gkq_atm:", gkq_atm; print *, "displ_red_qq:", displ_red_qq; print *, "gkq_nu:", gkq_nu
644 : :
645 : : ! Write |g|^2 for this q.
646 : : !if (pert_comm%me == master) then
647 [ + - + - : 6720 : gkq2_nu = gkq_nu(1,:,:,:)**2 + gkq_nu(2,:,:,:)**2
+ - - + -
- + + + +
+ + ]
648 [ + + - + : 588 : NCF_CHECK(nf90_put_var(ncid, vid("gkq2_nu"), gkq2_nu, start=[1,1,1,iq,ik,spin]))
- - ]
649 : : !end if
650 : :
651 [ - + ]: 84 : if (has_gwan) then
652 : : ! Interpolate e-ph matrix elements from GWAN.nc at this same (k,q) for comparison.
653 [ # # # # : 0 : ABI_MALLOC(g_atm_wan_local, (nwan_glob, nwan_glob, my_npert, 1))
# # # # #
# # # # #
# # # # #
# ]
654 : : ! The routine already diagonalizes H^W(k) and H^W(k+q) to rotate g to the
655 : : ! interpolated eigenstate basis, hence it also returns these eigenvalues.
656 : : call wan%interp_eph_manyq(cryst, 1, qq, kk, g_atm_wan_local, &
657 : 0 : out_eigens_k=eig_k_wan, out_eigens_kq=eig_kq_wan)
658 [ # # ]: 0 : if (iq == 1) then
659 [ # # # # : 0 : NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_wan_k"), eig_k_wan, start=[1,ik,spin]))
# # ]
660 : : end if
661 [ # # ]: 0 : if (ik == 1) then
662 [ # # # # : 0 : NCF_CHECK(nf90_put_var(ncid, vid("all_eigens_wan_kq"), eig_kq_wan(:,1), start=[1,iq,spin]))
# # ]
663 : : end if
664 : :
665 [ # # # # : 0 : gkq_atm_wan = zero
# # # # ]
666 [ # # ]: 0 : do my_ip=1,my_npert
667 : 0 : iglob = wan%my_pert_start + my_ip - 1
668 [ # # # # ]: 0 : gkq_atm_wan(1,:,:,iglob) = real(g_atm_wan_local(:,:,my_ip,1), kind=dp)
669 [ # # # # ]: 0 : gkq_atm_wan(2,:,:,iglob) = aimag(g_atm_wan_local(:,:,my_ip,1))
670 : : end do
671 [ # # ]: 0 : if (pert_comm%nproc > 1) call xmpi_sum(gkq_atm_wan, pert_comm%value, ierr)
672 : :
673 : : ! Reuses phfreqs/displ_red_qq already computed above (ifc%fourq) for this same q --
674 : : ! no new gauge issue, same literal-q call already used for the ab-initio side.
675 : 0 : call ephtk_gkknu_from_atm(nwan_glob, nwan_glob, 1, natom, gkq_atm_wan, phfreqs, displ_red_qq, gkq_nu_wan)
676 [ # # # # : 0 : gkq2_nu_wan = gkq_nu_wan(1,:,:,:)**2 + gkq_nu_wan(2,:,:,:)**2
# # # # #
# # # # #
# # ]
677 [ # # # # : 0 : NCF_CHECK(nf90_put_var(ncid, vid("gkq2_nu_wan"), gkq2_nu_wan, start=[1,1,1,iq,ik,spin]))
# # ]
678 : :
679 [ # # ]: 0 : ABI_FREE(g_atm_wan_local)
680 : : end if
681 : :
682 [ - + ]: 84 : ABI_FREE(gs1c)
683 [ - + ]: 84 : ABI_FREE(vlocal1)
684 [ - + ]: 84 : ABI_FREE(v1scf)
685 [ - + ]: 84 : ABI_FREE(vlocal_kq)
686 [ - + ]: 84 : ABI_FREE(ph3d_kq)
687 [ - + ]: 84 : ABI_FREE(kpg_kq)
688 [ - + ]: 84 : ABI_FREE(kinpw_kq)
689 [ - + ]: 84 : ABI_FREE(ffnl_kq)
690 [ - + ]: 84 : ABI_FREE(kg_kq)
691 [ - + ]: 84 : ABI_FREE(eig_kq)
692 [ - + ]: 84 : ABI_FREE(cg_kq)
693 [ - + ]: 84 : ABI_FREE(gsc_kq)
694 [ - + ]: 84 : ABI_FREE(h1_kets_kq)
695 : 127 : call gs_ham_kq%free(); call rf_ham_kq%free()
696 : : end do ! my_iq
697 : :
698 [ - + ]: 43 : ABI_FREE(vlocal)
699 [ - + ]: 43 : ABI_FREE(vlocal_k)
700 [ - + ]: 43 : ABI_FREE(ph3d_k)
701 [ - + ]: 43 : ABI_FREE(kpg_k)
702 [ - + ]: 43 : ABI_FREE(kinpw_k)
703 [ - + ]: 43 : ABI_FREE(ffnl_k)
704 [ - + ]: 43 : ABI_FREE(kg_k)
705 [ - + ]: 43 : ABI_FREE(eig_k)
706 [ - + ]: 43 : ABI_FREE(cg_k)
707 [ - + ]: 43 : ABI_FREE(gsc_k)
708 : 45 : call gs_ham_k%free()
709 : : end do ! my_ik
710 : :
711 [ - + ]: 4 : if (has_gwan) call wan%free()
712 : : end do ! my_is
713 : :
714 [ - + ]: 2 : NCF_CHECK(nf90_close(ncid))
715 : 2 : call xmpi_barrier(comm)
716 : :
717 : : ! ===========================================
718 : : ! Write results to ab_out for automatic tests
719 : : ! ===========================================
720 : 2 : call xmpi_sum(tot_nscf_ierr, comm, ierr)
721 : 2 : tot_nscf_ierr = int(tot_nscf_ierr / dble(pert_comm%nproc))
722 : :
723 [ + - ]: 2 : if (my_rank == master) then
724 [ + - ]: 2 : if (tot_nscf_ierr == 0) then
725 : : call wrtout(units, &
726 : 2 : sjoin("Computation of g(k,q) completed. All NSCF runs converged within tolwfr: ", ftoa(dtset%tolwfr)), pre_newlines=1)
727 : : else
728 [ # # ]: 0 : msg = sjoin("WARNING:", itoa(tot_nscf_ierr), "NSCF runs did not converge within tolwfr: ", ftoa(dtset%tolwfr))
729 [ # # ]: 0 : msg = sjoin(msg, ". Use nbdbuf and/or increase nstep!")
730 : 0 : call wrtout(ab_out, msg)
731 : 0 : ABI_WARNING(msg)
732 : : end if
733 : :
734 [ - + ]: 2 : NCF_CHECK(nctk_open_read(ncid, gpath_path, xmpi_comm_self))
735 : :
736 : : ! Write k/q wavevectors.
737 : 2 : call wrtout(units, "kpoints:")
738 [ + + ]: 45 : do ik=1, nk_path
739 : 45 : call wrtout(units, sjoin(char(9), itoa(ik), ktoa(kpath%points(:,ik))))
740 : : end do
741 : 2 : call wrtout(units, "qpoints:")
742 [ + + ]: 45 : do iq=1, nq_path
743 : 45 : call wrtout(units, sjoin(char(9), itoa(iq), ktoa(qpath%points(:,iq))))
744 : : end do
745 : :
746 : : ! Write KS eigenvalues.
747 [ + + ]: 2 : if (nq_path > 1) then
748 [ - + + - : 3 : ABI_MALLOC(eig_kq, (nband))
+ - + - -
+ - + -
+ ]
749 [ + + ]: 2 : do spin=1,nsppol
750 : 1 : call wrtout(units, sjoin(" Energies_kq in eV for spin:", itoa(spin)))
751 [ + + ]: 44 : do iq=1, nq_path
752 [ + + + + : 42 : if (all(iq /= [1, 2, nq_path-1, nq_path])) cycle
+ + ]
753 [ + + - + : 16 : NCF_CHECK(nf90_get_var(ncid, vid("all_eigens_kq"), eig_kq, start=[1,iq,spin]))
- - ]
754 [ + + ]: 17 : do ii=0,(nband-1)/8
755 [ + - + + ]: 84 : write(msg, '(a, 8es16.6)' )' ene:',(eig_kq(band_m) * Ha_eV, band_m=1+ii*8,min(nband,8+ii*8))
756 : 54 : call wrtout(units, msg)
757 : : end do
758 : : end do
759 : : end do
760 [ - + ]: 1 : ABI_FREE(eig_kq)
761 : :
762 : : else
763 : : ! nk_path > 1
764 [ - + + - : 3 : ABI_MALLOC(eig_k, (nband))
+ - + - -
+ - + -
+ ]
765 [ + + ]: 2 : do spin=1,nsppol
766 : 1 : call wrtout(units, sjoin(" Energies_k in eV for spin:", itoa(spin)))
767 [ + + ]: 44 : do ik=1, nk_path
768 [ + + - + : 168 : NCF_CHECK(nf90_get_var(ncid, vid("all_eigens_k"), eig_k, start=[1,ik,spin]))
- - ]
769 [ + + + + : 42 : if (all(ik /= [1, 2, nk_path-1, nk_path])) cycle
+ + ]
770 [ + + ]: 17 : do ii=0,(nband-1)/8
771 [ + - + + ]: 84 : write(msg, '(a, 8es16.6)' )' ene:',(eig_k(band_n) * Ha_eV, band_n=1+ii*8,min(nband,8+ii*8))
772 : 54 : call wrtout(units, msg)
773 : : end do
774 : : end do
775 : : end do
776 [ - + ]: 1 : ABI_FREE(eig_k)
777 : : end if
778 : :
779 : : ! Save g^2 in nc format without any average. This operation will be performed by AbiPy (need ph freqs and eigenergies)
780 : 2 : call wrtout(units, " Writing sqrt(1/N_b^2 \sum_{mn} |g_{mn,nu}(k, q)|^2) in meV for testing purpose.", pre_newlines=2)
781 : 2 : write(msg, "(1x,4(a5,1x),a16)") "nu","iq", "ik", "spin", "|g| in meV"
782 : 2 : call wrtout(units, msg)
783 : :
784 [ + + ]: 4 : do spin=1,nsppol
785 [ + + ]: 47 : do ik=1, nk_path
786 [ + + + + : 43 : if (all(ik /= [1, 2, nk_path-1, nk_path])) cycle
+ + ]
787 [ + + ]: 53 : do iq=1, nq_path
788 [ + + + + : 46 : if (all(iq /= [1, 2, nq_path-1, nq_path])) cycle
+ + ]
789 [ + + - + : 56 : NCF_CHECK(nf90_get_var(ncid, vid("gkq2_nu"), gkq2_nu, start=[1,1,1,iq,ik,spin]))
- - ]
790 [ + + ]: 99 : do nu=1,natom3
791 [ + + + + ]: 624 : write(msg, "(1x,4(i5,1x),es16.6)") nu, iq, ik, spin, sqrt(sum(gkq2_nu(:,:, nu)) / nb_in_g**2) * Ha_meV
792 : 94 : call wrtout(units, msg)
793 : : end do
794 : : end do ! iq
795 : : end do ! ik
796 : : end do ! spin
797 : :
798 [ - + ]: 2 : if (has_gwan) then
799 : : call wrtout(units, &
800 : 0 : " Writing sqrt(1/N^2 sum |g|^2): ab-initio vs Wannier-interpolated (gauge-invariant trace), meV.", pre_newlines=2)
801 : 0 : write(msg, "(1x,4(a5,1x),2(a18,1x))") "nu","iq","ik","spin", "|g|_abinitio(meV)", "|g|_wannier(meV)"
802 : 0 : call wrtout(units, msg)
803 [ # # ]: 0 : do spin=1,nsppol
804 [ # # ]: 0 : do ik=1, nk_path
805 [ # # # # : 0 : if (all(ik /= [1, 2, nk_path-1, nk_path])) cycle
# # ]
806 [ # # ]: 0 : do iq=1, nq_path
807 [ # # # # : 0 : if (all(iq /= [1, 2, nq_path-1, nq_path])) cycle
# # ]
808 [ # # # # : 0 : NCF_CHECK(nf90_get_var(ncid, vid("gkq2_nu"), gkq2_nu, start=[1,1,1,iq,ik,spin]))
# # ]
809 [ # # # # : 0 : NCF_CHECK(nf90_get_var(ncid, vid("gkq2_nu_wan"), gkq2_nu_wan, start=[1,1,1,iq,ik,spin]))
# # ]
810 [ # # ]: 0 : do nu=1,natom3
811 : 0 : write(msg, "(1x,4(i5,1x),2(es18.6,1x))") nu, iq, ik, spin, &
812 [ # # # # : 0 : sqrt(sum(gkq2_nu(:,:,nu)) / nb_in_g**2) * Ha_meV, sqrt(sum(gkq2_nu_wan(:,:,nu)) / nwan_glob**2) * Ha_meV
# # # # ]
813 : 0 : call wrtout(units, msg)
814 : : end do
815 : : end do ! iq
816 : : end do ! ik
817 : : end do ! spin
818 : : end if
819 : :
820 [ - + ]: 2 : NCF_CHECK(nf90_close(ncid))
821 : : end if ! master
822 : :
823 : : ! Free memory.
824 [ - + ]: 2 : ABI_FREE(my_ik_inds)
825 [ - + ]: 2 : ABI_FREE(my_iq_inds)
826 [ - + ]: 2 : ABI_FREE(gvnlx1)
827 [ - + ]: 2 : ABI_FREE(grad_berry)
828 [ - + ]: 2 : ABI_FREE(qmap_symrec)
829 [ - + ]: 2 : ABI_FREE(gkq_atm)
830 [ - + ]: 2 : ABI_FREE(gkq_nu)
831 [ - + ]: 2 : ABI_FREE(gkq2_nu)
832 [ - + ]: 2 : if (has_gwan) then
833 [ # # ]: 0 : ABI_FREE(gkq_atm_wan)
834 [ # # ]: 0 : ABI_FREE(gkq_nu_wan)
835 [ # # ]: 0 : ABI_FREE(gkq2_nu_wan)
836 [ # # ]: 0 : ABI_FREE(eig_k_wan)
837 [ # # ]: 0 : ABI_FREE(eig_kq_wan)
838 : : end if
839 [ - + ]: 2 : ABI_FREE(displ_cart)
840 [ - + ]: 2 : ABI_FREE(displ_red_qq)
841 [ - + ]: 2 : ABI_FREE(my_spins)
842 : :
843 : 2 : call pawcprj_free(cwaveprj0)
844 [ + - - + : 2 : ABI_FREE(cwaveprj0)
- - - - -
+ ]
845 [ + + ]: 4 : do my_is=1,my_nspins
846 : 4 : call comm_my_is(my_is)%free()
847 : : end do
848 [ - + ]: 2 : ABI_FREE(comm_my_is)
849 : :
850 : 2 : call qpath%free(); call kpath%free(); call ucache_k%free(); call ucache_kq%free()
851 : 2 : call qpt_comm%free(); call kpt_comm%free(); call pert_comm%free(); call nscf%free()
852 : :
853 [ - + - + : 8 : call cwtime_report(" eph_path: MPI barrier before returning.", cpu_all, wall_all, gflops_all, end_str=ch10, comm=comm)
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - - -
- - - - +
- + - + ]
854 : : !stop
855 : :
856 : : contains
857 : 324 : integer function vid(var_name)
858 : : character(len=*),intent(in) :: var_name
859 : 324 : vid = nctk_idname(ncid, var_name)
860 : : end function vid
861 : :
862 : : end subroutine eph_path_run
863 : : !!***
864 : :
865 : : end module m_eph_path
866 : : !!***
|