Line data Source code
1 : !!****m* ABINIT/m_gwr_driver
2 : !! NAME
3 : !! m_gwr_driver
4 : !!
5 : !! FUNCTION
6 : !! Driver for GWR calculations
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2021-2026 ABINIT group (MG)
10 : !! This file is distributed under the terms of the
11 : !! APACHE license version 2.0, see ~abinit/COPYING
12 : !! or https://www.apache.org/licenses/LICENSE-2.0 .
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_gwr_driver
23 :
24 : use, intrinsic :: iso_c_binding
25 : USE_MPI
26 : use defs_basis
27 : use defs_wvltypes
28 : use m_errors
29 : use m_abicore
30 : use m_xmpi
31 : use m_xomp
32 : use m_hdr
33 : use libxc_functionals
34 : use m_crystal
35 : use m_ebands
36 : use m_dtset
37 : use m_dtfil
38 : use m_wfk
39 : use netcdf
40 : use m_nctk
41 :
42 : use defs_datatypes, only : pseudopotential_type
43 : use defs_abitypes, only : MPI_type
44 : use m_time, only : timab
45 : use m_io_tools, only : file_exists, open_file, get_unit, iomode_from_fname
46 : use m_time, only : cwtime, cwtime_report, sec2str
47 : use m_fstrings, only : strcat, sjoin, ftoa, itoa, string_in, ltoa
48 : use m_fftcore, only : print_ngfft, get_kg
49 : use m_fft, only : fourdp
50 : use m_ioarr, only : read_rhor
51 : use m_energies, only : energies_type
52 : use m_mpinfo, only : destroy_mpi_enreg, initmpi_seq
53 : use m_pawang, only : pawang_type
54 : use m_pawrad, only : pawrad_type
55 : use m_pawtab, only : pawtab_type, pawtab_print, pawtab_get_lsize
56 : use m_paw_an, only : paw_an_type, paw_an_init, paw_an_free, paw_an_nullify
57 : use m_paw_ij, only : paw_ij_type, paw_ij_init, paw_ij_free, paw_ij_nullify
58 : use m_pawfgrtab, only : pawfgrtab_type, pawfgrtab_init, pawfgrtab_free, pawfgrtab_print
59 : use m_pawrhoij, only : pawrhoij_type, pawrhoij_alloc, pawrhoij_copy, pawrhoij_free, &
60 : pawrhoij_inquire_dim, pawrhoij_symrhoij, pawrhoij_unpack
61 : use m_pawdij, only : pawdij, symdij_all
62 : use m_pawfgr, only : pawfgr_type, pawfgr_init, pawfgr_destroy
63 : use m_paw_pwaves_lmn, only : paw_pwaves_lmn_t, paw_pwaves_lmn_init, paw_pwaves_lmn_free
64 : use m_pawpwij, only : pawpwff_t, pawpwff_init, pawpwff_free, paw_rho_tw_g
65 : use m_kg, only : getph
66 : use m_wfd, only : wfd_t, test_charge
67 : use m_pspini, only : pspini
68 : use m_paw_correlations,only : pawpuxinit
69 : use m_paw_dmft, only : paw_dmft_type
70 : use m_paw_sphharm, only : setsym_ylm
71 : use m_paw_mkrho, only : denfgr
72 : use m_paw_nhat, only : nhatgrid, pawmknhat
73 : use m_paw_tools, only : chkpawovlp, pawprt
74 : use m_paw_denpot, only : pawdenpot
75 : use m_paw_init, only : pawinit, paw_gencond
76 : use m_pawcprj, only : pawcprj_type, pawcprj_free, pawcprj_alloc ! , paw_overlap
77 : use m_pawxc, only : pawxc_get_usekden
78 : use m_ksdiago, only : ugb_t, hyb_t
79 : use m_mkrho, only : prtrhomxmn
80 : use m_melemts, only : melflags_t
81 : use m_setvtr, only : setvtr
82 : use m_vhxc_me, only : calc_vhxc_me
83 : use m_gwr, only : gwr_t
84 : use m_vcoul, only : vcgen_t
85 : use m_ephtk, only : ephtk_update_ebands
86 : use m_pstat, only : pstat_proc
87 :
88 : implicit none
89 :
90 : private
91 : !!***
92 :
93 : public :: gwr_driver
94 :
95 : #ifdef HAVE_MPI1
96 : include 'mpif.h'
97 : #endif
98 : !!***
99 :
100 : contains
101 : !!***
102 :
103 : !!****f* m_gwr_driver/gwr_driver
104 : !! NAME
105 : !! gwr_driver
106 : !!
107 : !! FUNCTION
108 : !! Main routine for GWR calculations.
109 : !!
110 : !! INPUTS
111 : !! acell(3)=Length scales of primitive translations (bohr)
112 : !! codvsn=Code version
113 : !! dtfil<datafiles_type>=Variables related to files.
114 : !! dtset<dataset_type>=All input variables for this dataset.
115 : !! pawang<pawang_type)>=PAW angular mesh and related data.
116 : !! pawrad(ntypat*usepaw)<pawrad_type>=Paw radial mesh and related data.
117 : !! pawtab(ntypat*usepaw)<pawtab_type>=Paw tabulated starting data.
118 : !! psps<pseudopotential_type>=Variables related to pseudopotentials.
119 : !! Before entering the first time in the routine, a significant part of Psps has been initialized :
120 : !! the integers dimekb,lmnmax,lnmax,mpssang,mpssoang,mpsso,mgrid,ntypat,n1xccc,usepaw,useylm,
121 : !! and the arrays dimensioned to npsp. All the remaining components of Psps are to be initialized in
122 : !! the call to pspini. The next time the code enters bethe_salpeter, Psps might be identical to the
123 : !! one of the previous Dtset, in which case, no reinitialisation is scheduled in pspini.F90.
124 : !! xred(3,natom)=Reduced atomic coordinates.
125 : !!
126 : !! NOTES
127 : !!
128 : !! ON THE USE OF FFT GRIDS:
129 : !! =================
130 : !! In case of PAW:
131 : !! ---------------
132 : !! Two FFT grids are used:
133 : !! - A "coarse" FFT grid (defined by ecut) for the application of the Hamiltonian on the plane waves basis.
134 : !! It is defined by nfft, ngfft, mgfft, ...
135 : !! Hamiltonian, wave-functions, density related to WFs (rhor here), ... are expressed on this grid.
136 : !! - A "fine" FFT grid (defined) by ecutdg) for the computation of the density inside PAW spheres.
137 : !! It is defined by nfftf, ngfftf, mgfftf, ... Total density, potentials, ... are expressed on this grid.
138 : !! In case of norm-conserving:
139 : !! ---------------------------
140 : !! - Only the usual FFT grid (defined by ecut) is used. It is defined by nfft, ngfft, mgfft, ...
141 : !! For compatibility reasons, (nfftf,ngfftf,mgfftf) are set equal to (nfft,ngfft,mgfft) in that case.
142 : !!
143 : !! SOURCE
144 :
145 0 : subroutine gwr_driver(codvsn, dtfil, dtset, pawang, pawrad, pawtab, psps, xred)
146 :
147 : !Arguments ------------------------------------
148 : !scalars
149 : character(len=8),intent(in) :: codvsn
150 : type(datafiles_type),intent(in) :: dtfil
151 : type(dataset_type),intent(inout) :: dtset
152 : type(pawang_type),intent(inout) :: pawang
153 : type(pseudopotential_type),intent(inout) :: psps
154 : !arrays
155 : real(dp),intent(in) :: xred(3,dtset%natom)
156 : type(pawrad_type),intent(inout) :: pawrad(psps%ntypat*psps%usepaw)
157 : type(pawtab_type),intent(inout) :: pawtab(psps%ntypat*psps%usepaw)
158 :
159 : !Local variables ------------------------------
160 : !scalars
161 : integer,parameter :: master = 0, cplex1 = 1, ipert0 = 0, idir0 = 0, optrhoij1 = 1
162 : integer :: ii, comm, nprocs, my_rank, mgfftf, nfftf, omp_ncpus, work_size, nks_per_proc
163 : integer :: ierr, spin, ik_ibz, nband_k, iomode__, color, io_comm, usevxctau_paw !, kg_varid
164 : real(dp) :: eff, mempercpu_mb, max_wfsmem_mb, nonscal_mem, el_temp
165 : real(dp) :: ecore, ecut_eff, ecutdg_eff, cpu, wall, gflops, diago_cpu, diago_wall, diago_gflops
166 : logical, parameter :: is_dfpt = .false.
167 : logical :: read_wfk, write_wfk, cc4s_task, rectangular, with_pools, rdm_update, call_pawinit, cc4s_from_wfk
168 : character(len=500) :: msg
169 : character(len=fnlen) :: wfk_path, den_path, kden_path, out_path
170 0 : type(hdr_type) :: wfk_hdr, den_hdr, kden_hdr, owfk_hdr
171 0 : type(crystal_t) :: cryst, den_cryst, wfk_cryst
172 0 : type(ebands_t) :: ks_ebands, owfk_ebands, tmp_ebands
173 : type(pawfgr_type) :: pawfgr
174 0 : type(wvl_data) :: wvl
175 0 : type(mpi_type) :: mpi_enreg_seq
176 0 : type(gwr_t) :: gwr
177 0 : type(wfk_t) :: owfk
178 : !arrays
179 : real(dp), parameter :: k0(3) = zero
180 : integer :: cplex, cplex_dij, cplex_rhoij
181 : integer :: gnt_option,has_dijU,has_dijso,ider,izero
182 : integer :: istep, moved_atm_inside, moved_rhor, n3xccc, sc_mode
183 : !integer :: ngrvdw,nhatgrdim,nkxc,nkxc1,nprocs,nscf,nspden_rhoij,nzlmopt,optene
184 : integer :: ndij !,ndim,nfftf,nfftf_tot,nkcalc,gwc_nfft,gwc_nfftot,gwx_nfft,gwx_nfftot
185 : integer :: ngrvdw, nhatgrdim, nkxc, nkxc1, nspden_rhoij, optene, nzlmopt
186 : integer :: optcut, optgr0, optgr1, optgr2, optrad, psp_gencond, option
187 : integer :: rhoxsp_method, usexcnhat !, use_umklp
188 : real(dp) :: compch_fft, compch_sph !,r_s,rhoav,alpha
189 : !real(dp) :: drude_plsmf !,my_plsmf,ecut_eff,ecutdg_eff,ehartree
190 : real(dp) :: gsqcutc_eff, gsqcutf_eff, gsqcut_shp, vxcavg, gw_gsq, gs_fermie
191 : type(energies_type) :: KS_energies
192 : type(melflags_t) :: KS_mflags
193 0 : type(paw_dmft_type) :: Paw_dmft
194 0 : type(ugb_t) :: ugb
195 0 : type(hyb_t) :: hyb
196 0 : type(xmpi_pool2d_t) :: diago_pool
197 : !arrays
198 : integer :: ngfftc(18),ngfftf(18),units(2) !, grid3(3)
199 0 : integer,allocatable :: nq_spl(:), l_size_atm(:)
200 0 : integer,allocatable :: tmp_kstab(:,:,:), npwarr_ik(:), gvec_(:,:), istwfk_ik(:), nband_iks(:,:)
201 0 : real(dp) :: strsxc(6), diago_info(3, dtset%nkpt, dtset%nsppol),tsec(2)
202 0 : real(dp),allocatable :: grchempottn(:,:),grewtn(:,:),grvdw(:,:),qmax(:)
203 0 : real(dp),allocatable :: ks_nhat(:,:),ks_nhatgr(:,:,:),ks_rhog(:,:)
204 0 : real(dp),allocatable :: ks_rhor(:,:),ks_vhartr(:), ks_vtrial(:,:), ks_vxc(:,:)
205 0 : real(dp),allocatable :: ks_taur(:,:) !, ks_vxctau(:,:), xcctau3d(:)
206 0 : real(dp),allocatable :: kxc(:,:), ph1d(:,:), ph1df(:,:) !qp_kxc(:,:),
207 0 : real(dp),allocatable :: vpsp(:), xccc3d(:), dijexc_core(:,:,:) !, dij_hf(:,:,:)
208 0 : real(dp),allocatable :: eig_k(:), occ_k(:)
209 0 : real(dp),contiguous,pointer :: cg_k_ptr(:,:)
210 0 : type(paw_an_type),allocatable :: KS_paw_an(:)
211 0 : type(paw_ij_type),allocatable :: KS_paw_ij(:)
212 0 : type(pawfgrtab_type),allocatable :: Pawfgrtab(:)
213 0 : type(pawrhoij_type),allocatable :: KS_Pawrhoij(:)
214 0 : type(pawpwff_t),allocatable :: Paw_pwff(:)
215 : !type(pawcprj_type),allocatable :: cprj_k(:,:)
216 : !************************************************************************
217 :
218 : ! This part performs the initialization of the basic objects used to perform e-ph calculations:
219 : !
220 : ! 1) Crystal structure `cryst`
221 : ! 2) Ground state band energies: `ks_ebands`
222 : ! 5) Pseudos and PAW basic objects.
223 : !
224 : ! Once we have these objects, we can call specialized routines for e-ph calculations.
225 : ! Notes:
226 : !
227 : ! * Any modification to the basic objects mentioned above should be done here (e.g. change of efermi)
228 : ! * This routines shall not allocate big chunks of memory. The CPU-demanding sections should be
229 : ! performed in the subdriver that will employ different MPI distribution schemes optimized for that particular task.
230 :
231 : ! abirules!
232 : if (.False.) write(std_out,*)xred
233 :
234 0 : comm = xmpi_world; nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
235 0 : units(:) = [std_out, ab_out]
236 :
237 0 : call cwtime(cpu, wall, gflops, "start")
238 0 : call pstat_proc%print(_PSTAT_ARGS_)
239 :
240 : ! write(msg,'(a)')&
241 : ! ' GWR: Calculation of the GW corrections with GWR code ',ch10,ch10,&
242 : ! call wrtout(units, msg)
243 : !
244 : #if defined HAVE_GW_DPC
245 0 : write(msg,'(a,i2,a)')'.Using double precision arithmetic; gwpc = ',gwp,ch10
246 : #else
247 : write(msg,'(a,i2,a)')'.Using single precision arithmetic; gwpc = ',gwp,ch10
248 : #endif
249 0 : call wrtout(units, msg)
250 :
251 : ! autoparal section
252 : ! TODO: This just to activate autoparal in AbiPy. Lot of things should be improved.
253 0 : if (dtset%max_ncpus /= 0) then
254 0 : write(ab_out,'(a)')"--- !Autoparal"
255 0 : write(ab_out,"(a)")"# Autoparal section for GWR runs"
256 0 : write(ab_out,"(a)") "info:"
257 0 : write(ab_out,"(a,i0)")" autoparal: ",dtset%autoparal
258 0 : write(ab_out,"(a,i0)")" max_ncpus: ",dtset%max_ncpus
259 0 : write(ab_out,"(a,i0)")" nkpt: ",dtset%nkpt
260 0 : write(ab_out,"(a,i0)")" nsppol: ",dtset%nsppol
261 0 : write(ab_out,"(a,i0)")" nspinor: ",dtset%nspinor
262 0 : write(ab_out,"(a,i0)")" mband: ",dtset%mband
263 0 : write(ab_out,"(3a)") " gwr_task: '",trim(dtset%gwr_task),"'"
264 :
265 0 : if (string_in(dtset%gwr_task, "HDIAGO, HDIAGO_FULL, CC4S, CC4S_FULL")) then
266 0 : work_size = dtset%nkpt * dtset%nsppol * dtset%mpw
267 0 : max_wfsmem_mb = (two * dp * dtset%mpw * dtset%mband * dtset%nkpt * dtset%nsppol * dtset%nspinor * b2Mb) * 1.1_dp
268 : else
269 0 : work_size = dtset%gwr_ntau * dtset%nkpt * dtset%nsppol * dtset%mpw
270 0 : max_wfsmem_mb = (two * dp * dtset%mpw * dtset%mband * dtset%nkpt * dtset%nsppol * dtset%nspinor * b2Mb) * 1.1_dp
271 : end if
272 : ! Non-scalable memory in Mb i.e. memory that is not distributed with MPI.
273 0 : nonscal_mem = zero
274 :
275 : ! List of configurations.
276 : ! Assuming an OpenMP implementation with perfect speedup!
277 0 : write(ab_out,"(a)")"configurations:"
278 :
279 0 : do ii=1,dtset%max_ncpus
280 0 : nks_per_proc = work_size / ii
281 0 : nks_per_proc = nks_per_proc + mod(work_size, ii)
282 0 : eff = (one * work_size) / (ii * nks_per_proc)
283 : ! Add the non-scalable part and increase by 10% to account for other datastructures.
284 0 : mempercpu_mb = (max_wfsmem_mb + nonscal_mem) * 1.1_dp
285 0 : do omp_ncpus=1,1 !xomp_get_max_threads()
286 0 : write(ab_out,"(a,i0)")" - tot_ncpus: ",ii * omp_ncpus
287 0 : write(ab_out,"(a,i0)")" mpi_ncpus: ",ii
288 0 : write(ab_out,"(a,i0)")" omp_ncpus: ",omp_ncpus
289 0 : write(ab_out,"(a,f12.9)")" efficiency: ",eff
290 0 : write(ab_out,"(a,f12.2)")" mem_per_cpu: ",mempercpu_mb
291 : end do
292 : end do
293 0 : write(ab_out,'(a)')"..."
294 0 : call wrtout(std_out, "Stopping now!")
295 0 : call abi_abort('PERS', exit_status=0, print_config=.false.)
296 : end if
297 :
298 0 : cryst = dtset%get_crystal(img=1)
299 :
300 : ! Some variables need to be initialized/nullify at start
301 0 : usexcnhat = 0
302 0 : call KS_energies%init()
303 :
304 : !Get electronic temperature from dtset
305 0 : el_temp = merge(dtset%tphysel,dtset%tsmear,dtset%tphysel>tol8.and.dtset%occopt/=3.and.dtset%occopt/=9)
306 :
307 0 : den_path = dtfil%fildensin; wfk_path = dtfil%fnamewffk; kden_path = dtfil%filkdensin
308 : !use_den = f (string_in(dtset%gwr_task, "CC4S_FROM_WFK")) then
309 :
310 0 : if (my_rank == master) then
311 : ! Initialize filenames. Accept files in Fortran or in netcdf format.
312 0 : if (nctk_try_fort_or_ncfile(den_path, msg) /= 0) then
313 0 : ABI_ERROR(sjoin("Cannot find DEN file:", den_path, ". Error:", msg))
314 : end if
315 0 : call wrtout(units, sjoin("- Reading GS density from: ", den_path))
316 :
317 0 : if (dtset%usekden == 1) then
318 0 : if (nctk_try_fort_or_ncfile(kden_path, msg) /= 0) then
319 0 : ABI_ERROR(sjoin("Cannot find KDEN file:", kden_path, ". Error:", msg))
320 : end if
321 0 : call wrtout(units, sjoin("- Reading KDEN kinetic energy density from: ", kden_path))
322 : end if
323 0 : call wrtout(ab_out, ch10//ch10)
324 : end if ! master
325 :
326 : ! Broadcast filenames (needed if we are using netcdf files)
327 0 : call xmpi_bcast(den_path, master, comm, ierr)
328 0 : call xmpi_bcast(kden_path, master, comm, ierr)
329 :
330 : ! TODO: FFT meshes for DEN/POT should be initialized from the DEN file instead of the dtset.
331 : ! Interpolating the DEN indeed breaks degeneracies in the vxc matrix elements.
332 : call pawfgr_init(pawfgr, dtset, mgfftf, nfftf, ecut_eff, ecutdg_eff, ngfftc, ngfftf, &
333 0 : gsqcutc_eff=gsqcutc_eff, gsqcutf_eff=gsqcutf_eff, gmet=cryst%gmet, k0=k0)
334 :
335 0 : call print_ngfft([std_out], ngfftc, header='Coarse FFT mesh for the wavefunctions')
336 0 : call print_ngfft([std_out], ngfftf, header='Dense FFT mesh for densities and potentials')
337 :
338 : ! Fake MPI_type for the sequential part.
339 0 : call initmpi_seq(mpi_enreg_seq)
340 0 : call mpi_enreg_seq%distribfft%init_seq('c', ngfftc(2), ngfftc(3), 'all')
341 0 : call mpi_enreg_seq%distribfft%init_seq('f', ngfftf(2), ngfftf(3), 'all')
342 :
343 : ! ===========================================
344 : ! === Open and read pseudopotential files ===
345 : ! ===========================================
346 0 : call pspini(dtset, dtfil, ecore, psp_gencond, gsqcutc_eff, gsqcutf_eff, pawrad, pawtab, psps, cryst%rprimd, comm_mpi=comm)
347 :
348 : ! ============================
349 : ! ==== PAW initialization ====
350 : ! ============================
351 0 : if (dtset%usepaw == 1) then
352 0 : call chkpawovlp(cryst%natom, cryst%ntypat, dtset%pawovlp, pawtab, cryst%rmet, cryst%typat, cryst%xred)
353 :
354 0 : cplex_dij = dtset%nspinor; cplex = 1; ndij = 1
355 :
356 0 : ABI_MALLOC(ks_pawrhoij, (cryst%natom))
357 : call pawrhoij_inquire_dim(cplex_rhoij=cplex_rhoij, nspden_rhoij=nspden_rhoij, &
358 0 : nspden=dtset%nspden, spnorb=dtset%pawspnorb, cpxocc=dtset%pawcpxocc)
359 0 : call pawrhoij_alloc(ks_pawrhoij, cplex_rhoij, nspden_rhoij, dtset%nspinor, dtset%nsppol, cryst%typat, pawtab=pawtab)
360 :
361 : ! Test if we have to call pawinit
362 0 : gnt_option = 1; if (dtset%pawxcdev == 2 .or. (dtset%pawxcdev == 1 .and. dtset%positron /= 0)) gnt_option = 2
363 0 : call paw_gencond(dtset, gnt_option, "test", call_pawinit)
364 : !call_pawinit = .True.
365 :
366 0 : if (psp_gencond == 1 .or. call_pawinit) then
367 0 : call timab(553, 1, tsec)
368 0 : gsqcut_shp = two * abs(dtset%diecut) * dtset%dilatmx**2 / pi**2
369 : call pawinit(dtset%effmass_free, gnt_option, gsqcut_shp, zero, dtset%pawlcutd, dtset%pawlmix, &
370 : psps%mpsang, dtset%pawnphi, cryst%nsym, dtset%pawntheta, pawang, pawrad, &
371 0 : dtset%pawspnorb, pawtab, dtset%pawxcdev, dtset%ixc, dtset%usepotzero)
372 0 : call timab(553,2,tsec)
373 :
374 : ! Update internal values
375 0 : call paw_gencond(dtset, gnt_option, "save", call_pawinit)
376 : else
377 0 : if (pawtab(1)%has_kij ==1) pawtab(1:cryst%ntypat)%has_kij = 2
378 0 : if (pawtab(1)%has_nabla==1) pawtab(1:cryst%ntypat)%has_nabla = 2
379 : end if
380 :
381 0 : psps%n1xccc = maxval(pawtab(1:cryst%ntypat)%usetcore)
382 :
383 : ! Initialize optional flags in Pawtab to zero
384 : ! Cannot be done in Pawinit since the routine is called only if some parts. are changed
385 0 : pawtab(:)%has_nabla = 0
386 0 : pawtab(:)%lamb_shielding = zero
387 :
388 0 : call setsym_ylm(cryst%gprimd, pawang%l_max-1, cryst%nsym, dtset%pawprtvol, cryst%rprimd, cryst%symrec, pawang%zarot)
389 :
390 : ! Initialize and compute data for DFT+U
391 0 : Paw_dmft%use_dmft = Dtset%usedmft
392 : call pawpuxinit(Dtset%dmatpuopt,Dtset%exchmix,Dtset%f4of2_sla,Dtset%f6of2_sla, &
393 : is_dfpt,Dtset%jpawu,Dtset%lexexch,Dtset%lpawu,dtset%nspinor,Cryst%ntypat,dtset%optdcmagpawu,Pawang,Dtset%pawprtvol, &
394 0 : Pawrad,Pawtab,Dtset%upawu,Dtset%usedmft,Dtset%useexexch,Dtset%usepawu,dtset%ucrpa)
395 :
396 0 : if (my_rank == master) call pawtab_print(Pawtab)
397 :
398 : ! Get Pawrhoij from the header of the WFK file.
399 : !call pawrhoij_copy(wfk_hdr%pawrhoij, KS_Pawrhoij)
400 :
401 : ! Evaluate form factor of radial part of phi.phj-tphi.tphj.
402 0 : gw_gsq = max(Dtset%ecutsigx, Dtset%ecuteps) / (two*pi**2)
403 :
404 : ! Set up q-grid, make qmax 20% larger than largest expected.
405 0 : ABI_MALLOC(nq_spl, (Psps%ntypat))
406 0 : ABI_MALLOC(qmax, (Psps%ntypat))
407 0 : qmax = SQRT(gw_gsq)*1.2d0
408 0 : nq_spl = Psps%mqgrid_ff
409 : ! write(std_out,*)"using nq_spl",nq_spl,"qmax=",qmax
410 :
411 0 : rhoxsp_method = 1 ! Arnaud-Alouani (default in sigma)
412 : !rhoxsp_method = 2 ! Shiskin-Kresse
413 0 : if (Dtset%pawoptosc /= 0) rhoxsp_method = Dtset%pawoptosc
414 :
415 0 : ABI_MALLOC(paw_pwff, (psps%ntypat))
416 0 : call pawpwff_init(Paw_pwff, rhoxsp_method, nq_spl, qmax, cryst%gmet, pawrad, pawtab, psps)
417 :
418 0 : ABI_FREE(nq_spl)
419 0 : ABI_FREE(qmax)
420 :
421 : ! Variables/arrays related to the fine FFT grid
422 0 : ABI_CALLOC(ks_nhat, (nfftf, Dtset%nspden))
423 :
424 0 : ABI_MALLOC(pawfgrtab, (cryst%natom))
425 0 : call pawtab_get_lsize(pawtab, l_size_atm, cryst%natom, cryst%typat)
426 :
427 : cplex = 1
428 0 : call pawfgrtab_init(pawfgrtab, cplex, l_size_atm, dtset%nspden, dtset%typat)
429 0 : ABI_FREE(l_size_atm)
430 0 : compch_fft=greatest_real
431 0 : usexcnhat = maxval(Pawtab(:)%usexcnhat)
432 : ! * 0 if Vloc in atomic data is Vbare (Blochl's formulation)
433 : ! * 1 if Vloc in atomic data is VH(tnzc) (Kresse's formulation)
434 0 : call wrtout(std_out, sjoin(' using usexcnhat: ', itoa(usexcnhat)))
435 : !
436 : ! Identify parts of the rectangular grid where the density has to be calculated
437 0 : optcut = 0; optgr0 = Dtset%pawstgylm; optgr1 = 0; optgr2 = 0; optrad = 1 - Dtset%pawstgylm
438 0 : if (Dtset%pawcross==1) optrad=1
439 0 : if (Dtset%xclevel==2.and.usexcnhat>0) optgr1=Dtset%pawstgylm
440 :
441 : call nhatgrid(cryst%atindx1, cryst%gmet, cryst%natom, cryst%natom, cryst%nattyp, ngfftf, cryst%ntypat,&
442 0 : optcut,optgr0,optgr1,optgr2,optrad,Pawfgrtab,Pawtab,Cryst%rprimd,Cryst%typat,Cryst%ucvol,Cryst%xred)
443 :
444 0 : call pawfgrtab_print(Pawfgrtab,Cryst%natom,unit=std_out,prtvol=Dtset%pawprtvol)
445 :
446 : else
447 0 : ABI_MALLOC(Paw_pwff, (0))
448 0 : ABI_MALLOC(Pawfgrtab, (0))
449 : end if ! End of PAW Initialization
450 :
451 : ! Allocate these arrays anyway, since they are passed to subroutines.
452 0 : ABI_MALLOC_IFNOT(ks_nhat, (nfftf, 0))
453 0 : ABI_MALLOC_IFNOT(dijexc_core, (1, 1, 0))
454 :
455 : !=============================================
456 : ! Read density and compare crystal structures
457 : ! ============================================
458 0 : ABI_MALLOC(ks_rhor, (nfftf, dtset%nspden))
459 :
460 : call read_rhor(den_path, cplex1, dtset%nspden, nfftf, ngfftf, dtset%usepaw, mpi_enreg_seq, ks_rhor, &
461 0 : den_hdr, ks_pawrhoij, comm, allow_interp=.False., want_varname="density")
462 :
463 0 : den_cryst = den_hdr%get_crystal()
464 0 : if (cryst%compare(den_cryst, header=" Comparing input crystal with DEN crystal") /= 0) then
465 0 : ABI_ERROR("Crystal structure from input and from DEN file do not agree! Check messages above!")
466 : end if
467 : ! Get fermie from the GS calculation.
468 : ! NB: It might understimate the real fermi level, especially if the den was computed on a shifted k-mesh
469 : ! at present it's only used to implement pseudobands
470 0 : gs_fermie = den_hdr%fermie
471 0 : call den_cryst%free(); call den_hdr%free()
472 :
473 0 : ABI_MALLOC(ks_taur, (nfftf, dtset%nspden * dtset%usekden))
474 0 : if (dtset%usekden == 1) then
475 : call read_rhor(kden_path, cplex1, dtset%nspden, nfftf, ngfftf, 0, mpi_enreg_seq, ks_taur, &
476 0 : kden_hdr, ks_pawrhoij, comm, allow_interp=.False., want_varname="kinedr")
477 0 : call kden_hdr%free()
478 0 : call prtrhomxmn(std_out, mpi_enreg_seq, nfftf, ngfftf, dtset%nspden, 1, ks_taur, optrhor=1, ucvol=cryst%ucvol)
479 : end if
480 :
481 : !========================================
482 : !==== Additional computation for PAW ====
483 : !========================================
484 0 : nhatgrdim = 0
485 0 : if (dtset%usepaw == 1) then
486 : ! Calculate the compensation charge nhat.
487 0 : if (Dtset%xclevel==2) nhatgrdim = usexcnhat * Dtset%pawnhatxc
488 0 : cplex = 1; ider = 2 * nhatgrdim; izero = 0
489 0 : if (nhatgrdim > 0) then
490 0 : ABI_MALLOC(ks_nhatgr,(nfftf,Dtset%nspden,3*nhatgrdim))
491 : end if
492 0 : if (nhatgrdim == 0) then
493 0 : ABI_MALLOC(ks_nhatgr,(0,0,0))
494 : end if
495 :
496 : call pawmknhat(compch_fft,cplex,ider,idir0,ipert0,izero,Cryst%gprimd,&
497 : Cryst%natom,Cryst%natom,nfftf,ngfftf,nhatgrdim,Dtset%nspden,Cryst%ntypat,Pawang,&
498 : Pawfgrtab,ks_nhatgr,ks_nhat,KS_Pawrhoij,KS_Pawrhoij,Pawtab,k0,Cryst%rprimd,&
499 0 : Cryst%ucvol,dtset%usewvl,Cryst%xred)
500 :
501 : ! === Evaluate onsite energies, potentials, densities ===
502 : ! Initialize variables/arrays related to the PAW spheres.
503 : ! Initialize also lmselect (index of non-zero LM-moments of densities).
504 0 : ABI_MALLOC(KS_paw_ij, (Cryst%natom))
505 0 : has_dijso = Dtset%pawspnorb; has_dijU = merge(0, 1, Dtset%usepawu == 0)
506 :
507 0 : call paw_ij_nullify(KS_paw_ij)
508 : call paw_ij_init(KS_paw_ij,cplex,Dtset%nspinor,Dtset%nsppol,&
509 : Dtset%nspden,Dtset%pawspnorb,Cryst%natom,Cryst%ntypat,Cryst%typat,Pawtab,&
510 : has_dij=1,has_dijhartree=1,has_dijhat=1,has_dijxc=1,has_dijxc_hat=1,has_dijxc_val=1,&
511 : has_dijso=has_dijso,has_dijU=has_dijU,has_exexch_pot=1,has_pawu_occ=1, &
512 0 : has_dijfock=dtset%usefock)
513 :
514 0 : nkxc1 = 0
515 0 : ABI_MALLOC(KS_paw_an, (Cryst%natom))
516 0 : call paw_an_nullify(KS_paw_an)
517 0 : usevxctau_paw=pawxc_get_usekden(dtset%ixc)
518 : call paw_an_init(KS_paw_an,Cryst%natom,Cryst%ntypat,nkxc1,0,Dtset%nspden,&
519 0 : cplex,Dtset%pawxcdev,Cryst%typat,Pawang,Pawtab,has_vxc=1,has_vxcval=1,has_vxctau=usevxctau_paw)
520 :
521 : ! Calculate onsite vxc with and without core charge.
522 0 : nzlmopt=-1; option=0; compch_sph=greatest_real
523 : call pawdenpot(compch_sph,el_temp,Cryst%gprimd,ipert0,Dtset%ixc,Cryst%natom,Cryst%natom,Dtset%nspden,&
524 : Cryst%ntypat,Dtset%nucdipmom,nzlmopt,option,KS_Paw_an,KS_Paw_an,KS_energies%paw,KS_paw_ij,&
525 : Pawang,Dtset%pawprtvol,Pawrad,KS_Pawrhoij,Dtset%pawspnorb,&
526 : Pawtab,Dtset%pawxcdev,Dtset%spnorbscl,Dtset%xclevel,Dtset%xc_denpos,Dtset%xc_taupos,&
527 0 : Cryst%xred,Cryst%ucvol,Psps%znuclpsp,Dtset%spinaxis)
528 :
529 : else
530 0 : ABI_MALLOC(ks_nhatgr, (0, 0, 0))
531 0 : ABI_MALLOC(ks_paw_ij, (0))
532 0 : ABI_MALLOC(ks_paw_an, (0))
533 : end if ! PAW
534 :
535 : !call test_charge(nfftf,ks_ebands%nelect,Dtset%nspden,ks_rhor,Cryst%ucvol,&
536 : ! Dtset%usepaw,usexcnhat,Pawfgr%usefinegrid,compch_sph,compch_fft,drude_plsmf)
537 :
538 : ! For PAW, add the compensation charge on the FFT mesh, then get rho(G).
539 : ! NB: ks_nhat is already included in the density stored on file so we don't need to add it.to ks_rhor
540 : !if (dtset%usepaw==1) ks_rhor = ks_rhor + ks_nhat
541 :
542 : ! TODO: Overloaded interface with units or just change the API to accept units
543 0 : call prtrhomxmn(std_out, mpi_enreg_seq, nfftf, ngfftf, dtset%nspden, 1, ks_rhor, ucvol=cryst%ucvol)
544 0 : call prtrhomxmn(ab_out, mpi_enreg_seq, nfftf, ngfftf, dtset%nspden, 1, ks_rhor, ucvol=cryst%ucvol)
545 :
546 0 : if (dtset%usekden==1) then
547 0 : call prtrhomxmn(std_out,MPI_enreg_seq,nfftf,ngfftf,Dtset%nspden,1,ks_taur,optrhor=1,ucvol=cryst%ucvol)
548 0 : call prtrhomxmn(ab_out,MPI_enreg_seq,nfftf,ngfftf,Dtset%nspden,1,ks_taur,optrhor=1,ucvol=cryst%ucvol)
549 : end if
550 :
551 : ! FFT n(r) --> n(g)
552 0 : ABI_MALLOC(ks_rhog, (2, nfftf))
553 0 : call fourdp(cplex1, ks_rhog, ks_rhor(:, 1), -1, mpi_enreg_seq, nfftf, 1, ngfftf, 0)
554 :
555 : ! Compute structure factor phases and large sphere cutoff
556 0 : ABI_MALLOC(ph1d, (2, 3 * (2 * Dtset%mgfft + 1) * Cryst%natom))
557 0 : ABI_MALLOC(ph1df, (2, 3 * (2 * mgfftf + 1) * Cryst%natom))
558 :
559 0 : call getph(cryst%atindx, cryst%natom, ngfftc(1), ngfftc(2), ngfftc(3), ph1d, cryst%xred)
560 :
561 0 : if (psps%usepaw == 1 .and. pawfgr%usefinegrid == 1) then
562 0 : call getph(cryst%atindx, cryst%natom, ngfftf(1), ngfftf(2), ngfftf(3), ph1df, cryst%xred)
563 : else
564 0 : ph1df(:,:)=ph1d(:,:)
565 : end if
566 :
567 : ! The following steps have been gathered in the setvtr routine:
568 : ! - get Ewald energy and Ewald forces
569 : ! - compute local ionic pseudopotential vpsp
570 : ! - eventually compute 3D core electron density xccc3d
571 : ! - eventually compute vxc and vhartr
572 : ! - set up ks_vtrial
573 : !
574 : !*******************************************************************
575 : !**** NOTE THAT HERE Vxc CONTAINS THE CORE-DENSITY CONTRIBUTION ****
576 : !*******************************************************************
577 :
578 0 : ngrvdw = 0
579 0 : ABI_MALLOC(grvdw, (3, ngrvdw))
580 0 : ABI_MALLOC(grchempottn, (3, cryst%natom))
581 0 : ABI_MALLOC(grewtn, (3, cryst%natom))
582 0 : nkxc = 0
583 0 : if (dtset%nspden == 1) nkxc = 2
584 0 : if (dtset%nspden >= 2) nkxc = 3 ! check GGA and spinor, quite a messy part!!!
585 : ! In case of MGGA, fxc and kxc are not available and we dont need them (for now ...)
586 0 : if (dtset%ixc < 0 .and. libxc_functionals_ismgga()) nkxc = 0
587 0 : if (nkxc /= 0) then
588 0 : ABI_MALLOC(kxc, (nfftf, nkxc))
589 : end if
590 :
591 0 : n3xccc = 0; if (psps%n1xccc /= 0) n3xccc = nfftf
592 0 : ABI_MALLOC(xccc3d, (n3xccc))
593 0 : ABI_MALLOC(ks_vhartr, (nfftf))
594 0 : ABI_MALLOC(ks_vtrial, (nfftf, dtset%nspden))
595 0 : ABI_MALLOC(vpsp, (nfftf))
596 0 : ABI_MALLOC(ks_vxc, (nfftf, dtset%nspden))
597 :
598 : ! TODO: I don't think direct diago can be used with mega-GGA due to the functional derivative wrt KS states.
599 : ! TB-BK should be OK though.
600 :
601 : !usevxctau=merge(1,0,xc_need_kden(dtset%ixc))
602 : !ABI_MALLOC(ks_vxctau, (nfftf, dtset%nspden * usevxctau))
603 : !ABI_MALLOC(xcctau3d, (n3xccc * dtset%usekden))
604 : !ABI_FREE(ks_vxctau)
605 : !ABI_FREE(xcctau3d)
606 :
607 0 : optene = 4; moved_atm_inside = 0; moved_rhor = 0; istep = 1
608 :
609 : call setvtr(Cryst%atindx1,Dtset,KS_energies,cryst%gmet,cryst%gprimd,grchempottn,grewtn,grvdw,gsqcutf_eff,&
610 : istep,kxc,mgfftf,moved_atm_inside,moved_rhor,MPI_enreg_seq,&
611 : Cryst%nattyp,nfftf,ngfftf,ngrvdw,ks_nhat,ks_nhatgr,nhatgrdim,nkxc,Cryst%ntypat,Psps%n1xccc,n3xccc,&
612 : optene,Pawang,Pawrad,KS_pawrhoij,Pawtab,ph1df,Psps,ks_rhog,ks_rhor,cryst%rmet,cryst%rprimd,strsxc,&
613 : Cryst%ucvol,usexcnhat,ks_vhartr,vpsp,ks_vtrial,ks_vxc,vxcavg,Wvl,xccc3d,Cryst%xred, &
614 0 : taur=ks_taur) !xcctau3d=xcctau3d, vxctau=ks_vxctau)
615 :
616 0 : ABI_FREE(grvdw)
617 0 : ABI_FREE(grchempottn)
618 0 : ABI_FREE(grewtn)
619 :
620 : !============================
621 : !==== Compute KS PAW Dij ====
622 : !============================
623 0 : if (dtset%usepaw == 1) then
624 0 : call timab(561,1,tsec)
625 :
626 : ! Calculate the unsymmetrized Dij.
627 : call pawdij(cplex,Dtset%enunit,Cryst%gprimd,ipert0,&
628 : Cryst%natom,Cryst%natom,nfftf,ngfftf(1)*ngfftf(2)*ngfftf(3),&
629 : Dtset%nspden,Cryst%ntypat,KS_paw_an,KS_paw_ij,Pawang,Pawfgrtab,&
630 : Dtset%pawprtvol,Pawrad,KS_Pawrhoij,Dtset%pawspnorb,Pawtab,Dtset%pawxcdev,&
631 : k0,Dtset%spnorbscl,Cryst%ucvol,dtset%cellcharge(1),ks_vtrial,&
632 : ks_vxc,Cryst%xred,Dtset%znucl,&
633 0 : nucdipmom=Dtset%nucdipmom,spinaxis=Dtset%spinaxis)
634 :
635 : ! Symmetrize KS Dij
636 : call symdij_all(Cryst%gprimd,Cryst%indsym,ipert0,&
637 : Cryst%natom,Cryst%natom,Cryst%nsym,Cryst%ntypat,KS_paw_ij,Pawang,&
638 0 : Dtset%pawprtvol,Pawtab,Cryst%rprimd,Cryst%symafm,Cryst%symrec)
639 :
640 : ! Output the pseudopotential strengths Dij and the augmentation occupancies Rhoij.
641 0 : call pawprt(Dtset,Cryst%natom,KS_paw_ij,KS_Pawrhoij,Pawtab)
642 0 : call timab(561,2,tsec)
643 : end if
644 :
645 0 : call pstat_proc%print(_PSTAT_ARGS_)
646 0 : call cwtime_report(" prepare gwr_driver_init", cpu, wall, gflops)
647 :
648 0 : if (string_in(dtset%gwr_task, "HDIAGO, HDIAGO_FULL, CC4S, CC4S_FULL")) then
649 : ! ==========================================
650 : ! Direct diagonalization of the Hamiltonian
651 : ! ==========================================
652 0 : ABI_MALLOC(nband_iks, (dtset%nkpt, dtset%nsppol))
653 0 : ABI_MALLOC(npwarr_ik, (dtset%nkpt))
654 0 : ABI_MALLOC(istwfk_ik, (dtset%nkpt))
655 0 : istwfk_ik = 1
656 :
657 : ! Compute npw_k from ecut so that we can update the header and redefine %mpw
658 0 : do ik_ibz=1,dtset%nkpt
659 : !if (dtset%istwfk(ik_ibz) == 2) istwfk_ik(ik_ibz) = 2 ! TODO: istwkf 2 is not yet supported.
660 0 : call get_kg(dtset%kptns(:,ik_ibz), istwfk_ik(ik_ibz), dtset%ecut, cryst%gmet, npwarr_ik(ik_ibz), gvec_)
661 0 : ABI_FREE(gvec_)
662 : end do
663 0 : dtset%mpw = maxval(npwarr_ik)
664 :
665 : ! CC4S does not need to output the WFK file.
666 0 : write_wfk = string_in(dtset%gwr_task, "HDIAGO, HDIAGO_FULL")
667 :
668 : ! Use input nband or min of npwarr_ik to set the number of bands.
669 0 : if (string_in(dtset%gwr_task, "HDIAGO, CC4S")) nband_iks(:,:) = maxval(dtset%nband)
670 0 : if (string_in(dtset%gwr_task, "HDIAGO_FULL, CC4S_FULL")) nband_iks(:,:) = minval(npwarr_ik)
671 0 : cc4s_task = string_in(dtset%gwr_task, "CC4S, CC4S_FULL")
672 0 : if (cc4s_task) then
673 0 : ABI_CHECK_IEQ(dtset%nkpt, 1, "CC4S interface does not support more than one k-point.")
674 : end if
675 :
676 : ! Build header with new npwarr and nband.
677 0 : call owfk_ebands%from_dtset(dtset, npwarr_ik, nband=nband_iks)
678 0 : owfk_ebands%eig = zero
679 0 : owfk_ebands%istwfk = istwfk_ik
680 : !print *, "owfk_ebands%npwarr:", owfk_ebands%npwarr; stop
681 0 : call owfk_hdr%init(owfk_ebands, codvsn, dtset, pawtab, 0, psps, wvl%descr)
682 :
683 : ! Change the value of istwfk taken from dtset and set the Fermie level from gs_fermie.
684 0 : ABI_REMALLOC(owfk_hdr%istwfk, (dtset%nkpt))
685 0 : owfk_hdr%istwfk(:) = istwfk_ik
686 0 : owfk_hdr%fermie = gs_fermie
687 :
688 : ! Build MPI pools to distribute (kpt, spin).
689 : ! Try to get rectangular grids in each pool to improve efficiency in slk diago.
690 0 : rectangular = .True.; if (dtset%nkpt == 1) rectangular = .False.
691 0 : with_pools = .True.
692 0 : if (any(dtset%gwr_np_kgts /= 0) .and. (nprocs == dtset%gwr_np_kgts(2))) then
693 0 : with_pools = .False.; call wrtout(std_out, " Deactivating pools in HDIAGO")
694 : end if
695 : !with_pools = .False.
696 0 : call diago_pool%from_dims(dtset%nkpt, dtset%nsppol, comm, with_pools, rectangular=rectangular)
697 0 : diago_info = zero
698 :
699 : ! TODO: Build hyb descriptor with hybrid orbitals from WFK file.
700 0 : cc4s_from_wfk = .False.
701 : if (dtset%usefock == 1 .and. cc4s_from_wfk) then
702 : call hyb%from_wfk_file(cryst, dtfil, dtset, psps, pawtab, ngfftc, diago_pool, comm)
703 : end if
704 :
705 0 : if (write_wfk) then
706 : ! Master writes the Abinit header and the Fortran record markers
707 0 : out_path = dtfil%fnameabo_wfk; if (dtset%iomode == IO_MODE_ETSF) out_path = nctk_ncify(out_path)
708 0 : iomode__ = iomode_from_fname(out_path)
709 0 : call wrtout(std_out, sjoin(" Writing wavefunctions to file:", out_path))
710 0 : if (my_rank == master) then
711 0 : call owfk%open_write(owfk_hdr, out_path, 0, iomode__, get_unit(), xmpi_comm_self, write_hdr=.True., write_frm=.True.)
712 0 : call owfk%close()
713 : end if
714 0 : call xmpi_barrier(comm)
715 : end if
716 :
717 : ! Build H_k(g,g') for each k-point and spin and diagonalize the Hamiltonian with Scalapack/ELPA.
718 0 : do spin=1,dtset%nsppol
719 0 : do ik_ibz=1,dtset%nkpt
720 0 : if (.not. diago_pool%treats(ik_ibz, spin)) cycle
721 0 : nband_k = nband_iks(ik_ibz, spin)
722 :
723 0 : if (dtset%usefock == 1 .and. .not. cc4s_from_wfk) then
724 0 : call wrtout(units, "Reading ugb datatype from WFK file")
725 0 : ABI_CHECK(.not. string_in(dtset%gwr_task, "CC4S_FULL"), "CC4S_FULL cannot be used with Fock, please specify nband")
726 : call ugb%from_wfk_file(ik_ibz, spin, istwfk_ik(ik_ibz), dtset%kptns(:,ik_ibz), nband_k, dtset, &
727 0 : dtfil, cryst, eig_k, diago_pool%comm%value)
728 :
729 : else
730 0 : call cwtime(diago_cpu, diago_wall, diago_gflops, "start")
731 : call ugb%from_diago(spin, istwfk_ik(ik_ibz), dtset%kptns(:,ik_ibz), dtset%ecut, gs_fermie, nband_k, ngfftc, nfftf, &
732 0 : dtset, pawtab, pawfgr, ks_paw_ij, cryst, psps, ks_vtrial, eig_k, hyb, diago_pool%comm%value)
733 0 : call cwtime(diago_cpu, diago_wall, diago_gflops, "stop")
734 :
735 0 : if (diago_pool%comm%me == 0) diago_info(1, ik_ibz, spin) = diago_wall
736 0 : call cwtime(diago_cpu, diago_wall, diago_gflops, "start")
737 : end if
738 :
739 0 : owfk_ebands%eig(1:nband_k, ik_ibz, spin) = eig_k(1:nband_k)
740 :
741 0 : if (write_wfk) then
742 : ! occupancies are set to zero. Client code is responsible for recomputing occ and fermie when reading this WFK.
743 0 : call wrtout(std_out, sjoin(" Writing kpoint ik_ibz:", itoa(ik_ibz), ", spin: ", itoa(spin), " to disk ..."))
744 0 : ABI_CALLOC(occ_k, (nband_k))
745 0 : color = merge(1, 0, ugb%my_nband > 0)
746 0 : call xmpi_comm_split(diago_pool%comm%value, color, diago_pool%comm%me, io_comm, ierr)
747 : call wrtout(std_out, sjoin(" Number of MPI procs involved in IO operation:", &
748 0 : itoa(xmpi_comm_size(io_comm)), "/", itoa(diago_pool%comm%nproc)))
749 :
750 0 : if (ugb%my_nband > 0) then
751 0 : ABI_CHECK(all(shape(ugb%cg_k) == [2, ugb%npwsp, ugb%my_nband]), "Wrong shape")
752 0 : ABI_CHECK_IEQ(ugb%npw_k, owfk_hdr%npwarr(ik_ibz), "Wrong npw_k")
753 0 : call c_f_pointer(c_loc(ugb%cg_k), cg_k_ptr, shape=[2, ugb%npwsp * ugb%my_nband])
754 :
755 : ! Reopen file inside io_comm.
756 0 : call owfk%open_write(owfk_hdr, out_path, 0, iomode__, get_unit(), io_comm, write_hdr=.False., write_frm=.False.)
757 : !call wrtout(std_out, "After owfk%open_write")
758 :
759 : ! Write my bands.
760 : !sc_mode = merge(xmpio_single, xmpio_collective, ugb%has_idle_procs)
761 : !sc_mode = xmpio_collective
762 0 : sc_mode = xmpio_single
763 : call owfk%write_band_block([ugb%my_bstart, ugb%my_bstop], ik_ibz, spin, sc_mode, &
764 0 : kg_k=ugb%kg_k, cg_k=cg_k_ptr, eig_k=owfk_ebands%eig(:, ik_ibz, spin), occ_k=occ_k)
765 0 : call owfk%close()
766 : end if
767 0 : call xmpi_comm_free(io_comm)
768 0 : ABI_FREE(occ_k)
769 : end if
770 :
771 0 : call cwtime(diago_cpu, diago_wall, diago_gflops, "stop")
772 0 : if (diago_pool%comm%me == 0) diago_info(2:3, ik_ibz, spin) = [diago_wall, dble(diago_pool%comm%nproc)]
773 :
774 : ! Compute and write matrix elements required by CC4S
775 0 : if (cc4s_task) call cc4s_gamma(spin, ik_ibz, dtset, dtfil, cryst, owfk_ebands, psps, pawtab, paw_pwff, ugb)
776 :
777 0 : ABI_FREE(eig_k)
778 0 : call ugb%free()
779 : end do ! ik_ibz
780 : end do ! spin
781 0 : call wrtout(std_out, " Direct diago completed by this MPI pool. Other pools might take more time if k != 0")
782 :
783 0 : call xmpi_sum_master(diago_info, master, comm, ierr)
784 0 : if (my_rank == master) then
785 0 : do spin=1,dtset%nsppol
786 0 : do ik_ibz=1,dtset%nkpt
787 0 : associate (info => diago_info(:, ik_ibz, spin))
788 0 : write(std_out, "(2(a,i0),5a,i0)") " ik_ibz: ", ik_ibz, ", spin: ", spin, &
789 0 : ", diago_wall: ", trim(sec2str(info(1))), ", io_wall: ", trim(sec2str(info(2))), ", nprocs: ", int(info(3))
790 : end associate
791 : end do
792 : end do
793 : end if
794 :
795 : ! Collect eigenvalues for the different k-points/spins.
796 0 : do spin=1,dtset%nsppol
797 0 : do ik_ibz=1,dtset%nkpt
798 0 : if (diago_pool%treats(ik_ibz, spin) .and. diago_pool%comm%me /= 0) owfk_ebands%eig(:, ik_ibz, spin) = zero
799 : end do
800 : end do
801 0 : call xmpi_sum(owfk_ebands%eig, comm, ierr)
802 :
803 0 : call owfk_ebands%update_occ(dtset%spinmagntarget, prtvol=dtset%prtvol, fermie_to_zero=.False.)
804 :
805 0 : if (my_rank == master) then
806 0 : if (write_wfk .and. iomode__ == IO_MODE_ETSF) then
807 0 : NCF_CHECK(owfk_ebands%ncwrite_path(cryst, out_path))
808 : end if
809 0 : call owfk_ebands%print_gaps(units, header="KS gaps after direct diagonalization")
810 0 : if (cc4s_task) call cc4s_write_eigens(owfk_ebands, dtfil)
811 : end if
812 :
813 0 : ABI_FREE(npwarr_ik)
814 0 : ABI_FREE(istwfk_ik)
815 0 : ABI_FREE(nband_iks)
816 0 : call owfk_hdr%free(); call owfk_ebands%free(); call hyb%free(); call diago_pool%free()
817 :
818 0 : else if (string_in(dtset%gwr_task, "CC4S_FROM_WFK")) then
819 : ! Read orbitals from an external WFK file and produce output files for CC4S.
820 :
821 : ! Construct crystal and ks_ebands from the GS WFK file.
822 0 : tmp_ebands = wfk_read_ebands(wfk_path, comm, out_hdr=wfk_hdr)
823 0 : ks_ebands = tmp_ebands%chop(1, maxval(dtset%nband))
824 :
825 : ! Make sure that ef is inside the gap if semiconductor.
826 : !call ks_ebands%update_occ(dtset%spinmagntarget, prtvol=dtset%prtvol, fermie_to_zero=.True.)
827 :
828 0 : call tmp_ebands%free()
829 0 : call wfk_hdr%vs_dtset(dtset)
830 :
831 0 : wfk_cryst = wfk_hdr%get_crystal()
832 0 : if (cryst%compare(wfk_cryst, header=" Comparing input crystal with WFK crystal") /= 0) then
833 0 : ABI_ERROR("Crystal structure from input and from WFK file do not agree! Check messages above!")
834 : end if
835 0 : call wfk_cryst%free()
836 :
837 0 : if (my_rank == master) call cc4s_write_eigens(ks_ebands, dtfil)
838 :
839 : ! Build MPI pools to distribute (kpt, spin).
840 0 : with_pools = .True.
841 0 : if (any(dtset%gwr_np_kgts /= 0) .and. (nprocs == dtset%gwr_np_kgts(2))) then
842 0 : with_pools = .False.; call wrtout(std_out, " Deactivating pools in HDIAGO")
843 : end if
844 0 : call diago_pool%from_dims(dtset%nkpt, dtset%nsppol, comm, with_pools, rectangular=.False.)
845 0 : ABI_CHECK_IEQ(dtset%nkpt, 1, "Only Gamma-point sampling is supported")
846 0 : ABI_CHECK_IEQ(dtset%nsppol, 1, "Only spin-unpolarized calculations are supported")
847 :
848 0 : do spin=1,dtset%nsppol
849 0 : do ik_ibz=1,dtset%nkpt
850 0 : if (.not. diago_pool%treats(ik_ibz, spin)) cycle
851 0 : nband_k = dtset%nband(ik_ibz + (spin-1)*dtset%nkpt)
852 : call ugb%from_wfk_file(ik_ibz, spin, dtset%istwfk(ik_ibz), dtset%kptns(:,ik_ibz), nband_k, dtset, &
853 0 : dtfil, cryst, eig_k, diago_pool%comm%value)
854 0 : ABI_FREE(eig_k)
855 0 : call cc4s_gamma(spin, ik_ibz, dtset, dtfil, cryst, ks_ebands, psps, pawtab, paw_pwff, ugb)
856 0 : call ugb%free()
857 : end do
858 : end do
859 0 : call wfk_hdr%free(); call ks_ebands%free(); call diago_pool%free()
860 :
861 : else
862 : ! ====================================================
863 : ! === This is the real GWR stuff once all is ready ===
864 : ! ====================================================
865 0 : ABI_CHECK(dtset%usepaw == 0, "PAW in GWR not yet implemented.")
866 0 : read_wfk = .True.
867 : if (read_wfk) then
868 0 : if (my_rank == master) then
869 0 : if (nctk_try_fort_or_ncfile(wfk_path, msg) /= 0) then
870 0 : ABI_ERROR(sjoin("Cannot find GS WFK file:", wfk_path, ". Error:", msg))
871 : end if
872 0 : call wrtout(units, sjoin("- Reading GS states from WFK file:", wfk_path))
873 : end if
874 :
875 : ! Broadcast filenames (needed because they might have been changed if we are using netcdf files)
876 0 : call xmpi_bcast(wfk_path, master, comm, ierr)
877 :
878 : ! Construct crystal and ks_ebands from the GS WFK file.
879 0 : tmp_ebands = wfk_read_ebands(wfk_path, comm, out_hdr=wfk_hdr)
880 0 : ks_ebands = tmp_ebands%chop(1, maxval(dtset%nband))
881 0 : call tmp_ebands%free()
882 0 : call wfk_hdr%vs_dtset(dtset)
883 :
884 0 : wfk_cryst = wfk_hdr%get_crystal()
885 0 : if (cryst%compare(wfk_cryst, header=" Comparing input crystal with WFK crystal") /= 0) then
886 0 : ABI_ERROR("Crystal structure from input and from WFK file do not agree! Check messages above!")
887 : end if
888 : !call wfk_cryst%print(header="crystal structure from WFK file")
889 0 : call wfk_cryst%free()
890 :
891 : ! Make sure that ef is inside the gap if semiconductor.
892 0 : call ks_ebands%update_occ(dtset%spinmagntarget, prtvol=dtset%prtvol, fermie_to_zero=.True.)
893 :
894 : ! Here we change the GS bands (Fermi level, scissors operator ...)
895 : ! All the modifications to ebands should be done here.
896 : !call ephtk_update_ebands(dtset, dtfil%filqpdatain, ks_ebands, "Ground state energies", comm)
897 : end if
898 0 : call pstat_proc%print(_PSTAT_ARGS_)
899 :
900 0 : call gwr%init(dtset, dtfil, cryst, psps, pawtab, ks_ebands, mpi_enreg_seq, comm)
901 0 : if (gwr%idle_proc) goto 100
902 :
903 : !=== Calculate Vxc(b1,b2,k,s)=<b1,k,s|v_{xc}|b2,k,s> for all the states included in GW ===
904 : ! * This part is parallelized within wfd%comm since each node has all GW wavefunctions.
905 : ! * Note that vH matrix elements are calculated using the true uncutted interaction.
906 :
907 0 : rdm_update = dtset%gwr_task == "GAMMA_GW"
908 :
909 0 : call KS_mflags%reset()
910 0 : if (rdm_update) then
911 0 : KS_mflags%has_hbare=1
912 0 : KS_mflags%has_kinetic=1
913 : end if
914 0 : KS_mflags%has_vhartree=1
915 0 : KS_mflags%has_vxc =1
916 0 : KS_mflags%has_vxcval =1
917 0 : if (Dtset%usepawu /= 0 ) KS_mflags%has_vu = 1
918 0 : if (Dtset%useexexch /= 0) KS_mflags%has_lexexch = 1
919 0 : if (Dtset%usepaw==1 .and. Dtset%gw_sigxcore == 1) KS_mflags%has_sxcore = 1
920 : ! off-diagonal elements only for SC on wavefunctions.
921 0 : KS_mflags%only_diago = 1
922 0 : if (rdm_update) KS_mflags%only_diago = 0
923 :
924 : ! Load wavefunctions for Sigma_nk in gwr%kcalc_wfd.
925 0 : call gwr%load_kcalc_wfd(wfk_path, tmp_kstab)
926 :
927 : ! Compute gwr%ks_me matrix elements.
928 0 : if (.not. string_in(dtset%gwr_task, "RPA_ENERGY")) then
929 : ! FIXME: This routine allocates (nband, nband) matrices and should be rewritten!
930 : call calc_vhxc_me(gwr%kcalc_wfd, ks_mflags, gwr%ks_me, cryst, dtset, nfftf, ngfftf, &
931 : ks_vtrial, ks_vhartr, ks_vxc, psps, pawtab, ks_paw_an, pawang, pawfgrtab, ks_paw_ij, dijexc_core, &
932 0 : ks_rhor, usexcnhat, ks_nhat, ks_nhatgr, nhatgrdim, tmp_kstab, taur=ks_taur)
933 0 : if (my_rank == master) call gwr%ks_me%print(header="KS matrix elements", unit=std_out)
934 : end if
935 :
936 0 : ABI_FREE(tmp_kstab)
937 :
938 : if (read_wfk) then
939 : ! Read wavefunctions from WFK file.
940 0 : call gwr%read_ugb_from_wfk(wfk_path)
941 : else
942 : ! Diagonalize H on the fly and
943 : !call gwr%get_ugb_from_vtrial(ngfftf, ks_vtrial)
944 : !gwr%wfk_hdr = ?
945 : end if
946 :
947 : ! Now call high-level routines depending on gwr_task.
948 0 : select case (dtset%gwr_task)
949 : case ("RPA_ENERGY")
950 0 : call gwr%rpa_energy()
951 : case ("GAMMA_GW")
952 0 : call gwr%gamma_gw(nfftf, ngfftf, vpsp)
953 : case ("CHI0")
954 0 : call gwr%run_chi0()
955 : case ("G0W0")
956 0 : call gwr%run_g0w0()
957 : case ("G0V")
958 0 : call gwr%build_sigxme(compute_qp=.True.)
959 : case ("EGEW", "EGW0", "G0EW")
960 0 : call gwr%run_energy_scf()
961 : case default
962 0 : ABI_ERROR(sjoin("Invalid value for gwr_task:", dtset%gwr_task))
963 : end select
964 : end if
965 :
966 : !=====================
967 : !==== Free memory ====
968 : !=====================
969 0 : 100 call xmpi_barrier(comm)
970 0 : ABI_FREE(ks_nhat)
971 0 : ABI_FREE(ks_nhatgr)
972 0 : ABI_FREE(dijexc_core)
973 0 : call pawfgr_destroy(pawfgr)
974 :
975 0 : if (dtset%usepaw == 1) then
976 : ! Deallocation for PAW.
977 0 : call pawrhoij_free(ks_pawrhoij)
978 0 : ABI_FREE(ks_pawrhoij)
979 0 : call pawfgrtab_free(pawfgrtab)
980 0 : call paw_ij_free(ks_paw_ij)
981 0 : ABI_FREE(ks_paw_ij)
982 0 : call paw_an_free(ks_paw_an)
983 0 : call pawpwff_free(Paw_pwff)
984 : end if
985 :
986 0 : ABI_FREE(ph1d)
987 0 : ABI_FREE(ph1df)
988 0 : ABI_FREE(ks_rhor)
989 0 : ABI_FREE(ks_rhog)
990 0 : ABI_FREE(ks_taur)
991 0 : ABI_FREE(kxc)
992 0 : ABI_FREE(xccc3d)
993 0 : ABI_FREE(ks_vhartr)
994 0 : ABI_FREE(ks_vtrial)
995 0 : ABI_FREE(vpsp)
996 0 : ABI_FREE(ks_vxc)
997 : ! PAW stuff
998 0 : ABI_SFREE(paw_pwff)
999 0 : ABI_SFREE(pawfgrtab)
1000 0 : ABI_SFREE(ks_paw_an)
1001 :
1002 0 : call cryst%free(); call wfk_hdr%free(); call ks_ebands%free(); call destroy_mpi_enreg(mpi_enreg_seq)
1003 : #if defined FC_NVHPC
1004 : call wrtout(units, "- Cannot deallocate gwr datatype if FC_NVHPC, DO NOT USE DATASETS!")
1005 : #else
1006 0 : call gwr%free()
1007 : #endif
1008 :
1009 0 : call pstat_proc%print(_PSTAT_ARGS_)
1010 :
1011 0 : end subroutine gwr_driver
1012 : !!***
1013 :
1014 : !!****f* m_gwr_driver/cc4s_write_eigens
1015 : !! NAME
1016 : !! cc4s_write_eigens
1017 : !!
1018 : !! FUNCTION
1019 : !! Write eigenvalues in CC4S format. Only master proc should call this routine.
1020 : !!
1021 : !! INPUTS
1022 :
1023 0 : subroutine cc4s_write_eigens(ebands, dtfil)
1024 :
1025 : !Arguments ------------------------------------
1026 : type(ebands_t),intent(in) :: ebands
1027 : type(datafiles_type),intent(in) :: dtfil
1028 :
1029 : !Local variables-------------------------------
1030 : integer :: unt, ik_ibz, spin, band, gap_err
1031 : real(dp) :: my_fermie
1032 : character(len=500) :: msg
1033 : character(len=fnlen) :: filepath
1034 0 : type(gaps_t) :: ks_gaps
1035 : ! *************************************************************************
1036 :
1037 0 : ks_gaps = ebands%get_gaps(gap_err)
1038 0 : call ks_gaps%print([std_out], header="Kohn-Sham gaps and band edges from IBZ mesh")
1039 0 : if (any(ks_gaps%ierr /= 0)) then
1040 0 : ABI_ERROR("Cannot compute gaps!")
1041 : end if
1042 :
1043 : ! Make sure fermi level is within the gap. I know, the case nsppol = 2 is treated in a dirty way!
1044 0 : my_fermie = zero
1045 0 : do spin=1,ebands%nsppol
1046 0 : my_fermie = ks_gaps%vb_max(spin) + (ks_gaps%cb_min(spin) - ks_gaps%vb_max(spin)) / two
1047 : end do
1048 0 : my_fermie = my_fermie / ebands%nsppol
1049 0 : call ks_gaps%free()
1050 :
1051 : ! See https://manuals.cc4s.org/user-manual/objects/EigenEnergies.html
1052 0 : filepath = trim(dtfil%filnam_ds(4))//'_EigenEnergies.yaml'
1053 0 : write(ab_out, "(3a)")ch10," Writing Eigenenergies metadata to file: ", trim(filepath)
1054 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1055 0 : ABI_ERROR(msg)
1056 : end if
1057 0 : write(unt,'(A)') 'version: 100'
1058 0 : write(unt,'(A)') 'type: Tensor'
1059 0 : write(unt,'(A)') 'scalarType: Real64'
1060 0 : write(unt,'(A)') 'dimensions:'
1061 0 : write(unt,'(A,I0)') '- length: ',ebands%mband * ebands%nkpt * ebands%nsppol
1062 0 : write(unt,'(A)') ' type: State'
1063 0 : write(unt,'(A)') 'elements:'
1064 0 : write(unt,'(A)') ' type: TextFile'
1065 0 : write(unt,'(A)') 'unit: 1.0 # Hartree units'
1066 0 : write(unt,'(A)') 'metaData:'
1067 0 : write(unt,'(A,E22.15)') ' fermiEnergy: ',my_fermie
1068 0 : write(unt,'(A)') ' energies:'
1069 :
1070 0 : do spin=1,ebands%nsppol
1071 0 : do ik_ibz=1,ebands%nkpt
1072 0 : do band=1,ebands%nband(ik_ibz + (spin-1)*ebands%nkpt)
1073 0 : write(unt,"(a,e22.15)") ' - ',ebands%eig(band,ik_ibz,spin)
1074 : end do
1075 : end do
1076 : end do
1077 0 : close(unt)
1078 :
1079 0 : filepath = trim(dtfil%filnam_ds(4))//'_EigenEnergies.elements'
1080 0 : write(ab_out, "(3a)")ch10," Writing Eigenenergies to file: ", trim(filepath)
1081 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1082 0 : ABI_ERROR(msg)
1083 : end if
1084 :
1085 0 : do spin=1,ebands%nsppol
1086 0 : do ik_ibz=1,ebands%nkpt
1087 0 : do band=1,ebands%nband(ik_ibz + (spin-1)*ebands%nkpt)
1088 0 : write(unt,"(e22.15)") ebands%eig(band,ik_ibz,spin)
1089 : end do
1090 : end do
1091 : end do
1092 :
1093 0 : close(unt)
1094 :
1095 0 : end subroutine cc4s_write_eigens
1096 : !!***
1097 :
1098 : !!****f* m_gwr_driver/cc4s_gamma
1099 : !! NAME
1100 : !! cc4s_gamma
1101 : !!
1102 : !! FUNCTION
1103 : !! Interface with CC4S code.
1104 : !! Compute <b1,k|e^{-iGr}|b2,k> matrix elements and store them to disk
1105 : !!
1106 : !! INPUTS
1107 :
1108 0 : subroutine cc4s_gamma(spin, ik_ibz, dtset, dtfil, cryst, ebands, psps, pawtab, paw_pwff, ugb)
1109 :
1110 : use m_numeric_tools, only : blocked_loop
1111 : use m_gwdefs, only : GW_Q0_DEFAULT
1112 : use m_fftcore, only : sphereboundary
1113 : use m_fft_mesh, only : setmesh
1114 : use m_fft, only : uplan_t
1115 : use m_vcoul, only : vcgen_t
1116 :
1117 : use m_sort, only : sort_gvecs
1118 : use m_pawpwij, only : pawpwij_t, pawpwij_init, pawpwij_free
1119 :
1120 : !Arguments ------------------------------------
1121 : integer,intent(in) :: spin, ik_ibz
1122 : type(dataset_type),intent(in) :: dtset
1123 : type(datafiles_type),intent(in) :: dtfil
1124 : type(crystal_t),intent(in) :: cryst
1125 : type(ebands_t),intent(in) :: ebands
1126 : type(Pseudopotential_type),intent(in) :: psps
1127 : type(pawpwff_t),intent(in) :: paw_pwff(dtset%ntypat*dtset%usepaw)
1128 : type(pawtab_type),intent(in) :: pawtab(psps%ntypat*psps%usepaw)
1129 : type(ugb_t),target,intent(in) :: ugb
1130 :
1131 : !Local variables-------------------------------
1132 : !scalars
1133 : integer,parameter :: mG0(3) = 0, master = 0
1134 : integer :: nproc, my_rank, my_ib2st, npw_k, nspinor, m_npw, npwvec, ig, mpierr, fh, comm, buf_size, ierr
1135 : integer :: band1, band1_start, batch1_size, n1dat, idat1, m_istwfk, iatom, dim_rtwg
1136 : integer :: band2, band2_start, batch2_size, n2dat, idat2, units(2), ii, unt, nqibz_, nqbz_, nkbz_, test_unt, M_
1137 : integer(XMPI_OFFSET_KIND) :: offset
1138 : real(dp) :: cpu, wall, gflops, qpt(3), qbz_(3,1), gcart(3), kpt(3), max_abs_err, abs_err, my_gw_qlwl(3), mem_mb
1139 : character(len=500) :: msg
1140 : character(len=fnlen) :: filepath, cvx_filepath
1141 : logical :: k_is_gamma
1142 : logical,parameter :: trust_no_one = .False.
1143 0 : type(uplan_t) :: uplan_1, uplan_2, uplan_m
1144 0 : type(vcgen_t) :: vcgen
1145 0 : integer :: u_ngfft(18), u_nfft, u_mgfft, enforce_sym, method, nlmn_atm(cryst%natom)
1146 0 : integer,pointer :: gvec_max(:,:)
1147 0 : integer,allocatable,target :: m_gvec(:,:), sorted_kg_k(:,:)
1148 0 : complex(dp),allocatable :: ug1_batch(:,:), ur1_batch(:,:), ur2_batch(:,:), ur12_batch(:,:), ug12_batch(:,:), cwork(:)
1149 0 : complex(gwp),allocatable :: sqrt_vc(:), paw_rhotwg(:)
1150 0 : type(pawpwij_t),allocatable :: pwij(:)
1151 0 : type(pawcprj_type),allocatable :: cprj1(:,:)
1152 : ! *************************************************************************
1153 :
1154 0 : call cwtime(cpu, wall, gflops, "start")
1155 :
1156 0 : comm = ugb%comm; nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1157 0 : units = [std_out, ab_out]
1158 0 : npw_k = ugb%npw_k; nspinor = ugb%nspinor
1159 :
1160 0 : if (dtset%prtvol > 10) call ugb%print([std_out], dtset%prtvol, header="ugb for CC4S")
1161 :
1162 : ! m_gvec is the g-sphere for the oscillators M computed from ecuteps (half-sphere if wavefunctions have TR).
1163 : ! setmesh assumes g-vectors sorted by norm so use kin_sorted = True and sort ug%kg_k below.
1164 0 : kpt = dtset%kptns(:,ik_ibz); k_is_gamma = all(abs(kpt) < tol12)
1165 0 : m_istwfk = 1; if (ugb%istwf_k == 2) m_istwfk = 2
1166 0 : call get_kg(kpt, m_istwfk, dtset%ecuteps, cryst%gmet, m_npw, m_gvec, kin_sorted=.True.)
1167 :
1168 : ! Setup FFT mesh
1169 0 : u_ngfft = dtset%ngfft
1170 0 : method = 2
1171 0 : if (dtset%fftgw==00 .or. dtset%fftgw==01) method=0
1172 0 : if (dtset%fftgw==10 .or. dtset%fftgw==11) method=1
1173 0 : if (dtset%fftgw==20 .or. dtset%fftgw==21) method=2
1174 0 : if (dtset%fftgw==30 .or. dtset%fftgw==31) method=3
1175 0 : enforce_sym = mod(dtset%fftgw, 10)
1176 : ! Gamma only --> we don't need to rotate wavefunctions in the BZ
1177 0 : if (k_is_gamma) enforce_sym = 0
1178 :
1179 0 : call sort_gvecs(npw_k, kpt, cryst%gmet, ugb%kg_k, sorted_kg_k)
1180 :
1181 0 : npwvec = npw_k; gvec_max => sorted_kg_k
1182 0 : if (m_npw > npw_k) then
1183 0 : npwvec = m_npw; gvec_max => m_gvec
1184 : end if
1185 0 : call setmesh(cryst%gmet, gvec_max, u_ngfft, npwvec, m_npw, npw_k, u_nfft, method, mG0, cryst, enforce_sym, unit=std_out)
1186 0 : ABI_FREE(sorted_kg_k)
1187 :
1188 : u_mgfft = maxval(u_ngfft(1:3))
1189 0 : qpt = zero
1190 :
1191 0 : nqibz_ = 1; nqbz_ = 1; qbz_ = zero; nkbz_ = 1
1192 : ! TODO: MC technique does not seem to work as expected, even in the legacy code.
1193 : call vcgen%init(cryst, ebands%kptrlatt, nkbz_, nqibz_, nqbz_, qbz_, &
1194 0 : dtset%gw_rcut, dtset%gw_icutcoul, dtset%vcutgeo, dtset%ecuteps, comm)
1195 :
1196 : ! NB: npweps = m_npw
1197 0 : ABI_MALLOC(sqrt_vc, (m_npw))
1198 0 : my_gw_qlwl(:) = GW_Q0_DEFAULT; if (dtset%gw_nqlwl > 0) my_gw_qlwl = dtset%gw_qlwl(:,1)
1199 0 : call vcgen%get_vc_sqrt(qpt, m_npw, m_gvec, my_gw_qlwl, cryst, sqrt_vc, comm)
1200 : ! Override the G=0 component with the correct value set by gw_icutcoulomb method
1201 0 : sqrt_vc(1) = sqrt(vcgen%i_sz)
1202 : !sqrt_vc(1) = zero
1203 0 : call vcgen%free()
1204 :
1205 0 : if (my_rank == master) then
1206 0 : call wrtout(units, " Computing oscilator matrix elements for CC4S.")
1207 0 : call print_ngfft([std_out], u_ngfft, header='FFT mesh for wavefunctions')
1208 :
1209 : ! =====================
1210 : ! Write files for CC4S
1211 : ! =====================
1212 0 : if (ik_ibz == 1 .and. spin == 1) then
1213 : ! Write g-vector files, see https://manuals.cc4s.org/user-manual/objects/GridVectors.html
1214 0 : filepath = trim(dtfil%filnam_ds(4))//'_GridVectors.yaml'
1215 0 : write(ab_out, "(3a)")ch10," Writing Gridvectors metadata to file: ", trim(filepath)
1216 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1217 0 : ABI_ERROR(msg)
1218 : end if
1219 0 : write(unt,'(a)') 'version: 100'
1220 0 : write(unt,'(a)') 'type: Tensor'
1221 0 : write(unt,'(a)') 'scalarType: Real64'
1222 0 : write(unt,'(a)') 'dimensions:'
1223 0 : write(unt,'(a)') ' - length: 3'
1224 0 : write(unt,'(a)') ' type: Vector'
1225 0 : write(unt,'(a,i0)') ' - length: ',m_npw
1226 0 : write(unt,'(a)') ' type: Momentum'
1227 0 : write(unt,'(a)') 'elements:'
1228 0 : write(unt,'(a)') ' type: TextFile'
1229 0 : write(unt,'(a)') 'unit: 1.0 # Bohr^-1'
1230 : ! The last three lines correspond to the reciprocal lattice vectors (including the factor 2pi)
1231 0 : write(unt,'(a)') 'metaData:'
1232 : write(unt,'(" Gi: [",E22.15,",",E22.15,",",E22.15,"]")') &
1233 0 : two_pi*cryst%gprimd(1,1), two_pi*cryst%gprimd(2,1), two_pi*cryst%gprimd(3,1)
1234 : write(unt,'(" Gj: [",E22.15,",",E22.15,",",E22.15,"]")') &
1235 0 : two_pi*cryst%gprimd(1,2), two_pi*cryst%gprimd(2,2), two_pi*cryst%gprimd(3,2)
1236 : write(unt,'(" Gk: [",E22.15,",",E22.15,",",E22.15,"]")') &
1237 0 : two_pi*cryst%gprimd(1,3), two_pi*cryst%gprimd(2,3), two_pi*cryst%gprimd(3,3)
1238 0 : close(unt)
1239 :
1240 : ! Write g-vectors (cart coords)
1241 0 : filepath = trim(dtfil%filnam_ds(4))//'_GridVectors.elements'
1242 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1243 0 : ABI_ERROR(msg)
1244 : end if
1245 :
1246 : !TODO: k-points to be implemented.
1247 0 : do ig=1,m_npw
1248 0 : gcart = two_pi * matmul(cryst%gprimd, m_gvec(:,ig))
1249 0 : do ii=1,3
1250 0 : write(unt, *) gcart(ii)
1251 : end do
1252 : end do
1253 0 : close(unt)
1254 :
1255 : ! https://manuals.cc4s.org/user-manual/objects/CoulombVertex.html
1256 0 : filepath = trim(dtfil%filnam_ds(4))//'_CoulombVertex.yaml'
1257 0 : write(ab_out, "(3a)")ch10, ' Writing CoulombVertex metadata to file: ', trim(filepath)
1258 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1259 0 : ABI_ERROR(msg)
1260 : end if
1261 0 : write(unt,'(a)') 'version: 100'
1262 0 : write(unt,'(a)') 'type: Tensor'
1263 0 : write(unt,'(a)') 'scalarType: Complex64'
1264 0 : write(unt,'(a)') 'dimensions:'
1265 0 : write(unt,'(a,i0)') '- length: ',m_npw
1266 0 : write(unt,'(a)') ' type: AuxiliaryField'
1267 0 : write(unt,'(a,i0)') '- length: ',ugb%nband_k
1268 0 : write(unt,'(a)') ' type: State'
1269 0 : write(unt,'(a,i0)') '- length: ',ugb%nband_k
1270 0 : write(unt,'(a)') ' type: State'
1271 0 : write(unt,'(a)') 'elements:'
1272 0 : write(unt,'(a)') ' type: IeeeBinaryFile'
1273 0 : write(unt,'(a)') 'unit: 1.0 # Atomic units'
1274 0 : write(unt,'(a)') 'metaData:'
1275 0 : if (m_istwfk == 2) then
1276 0 : write(unt,'(a)') ' halfGrid: 1'
1277 : else
1278 0 : write(unt,'(a)') ' halfGrid: 0'
1279 : end if
1280 0 : close(unt)
1281 :
1282 : ! https://manuals.cc4s.org/user-manual/objects/CoulombPotential.html
1283 0 : filepath = trim(dtfil%filnam_ds(4))//'_CoulombPotential.yaml'
1284 0 : write(ab_out, "(3a)")ch10, ' Writing CoulombPotential metadata to file: ', trim(filepath)
1285 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1286 0 : ABI_ERROR(msg)
1287 : end if
1288 0 : write(unt,'(a)') 'version: 100'
1289 0 : write(unt,'(a)') 'type: Tensor'
1290 0 : write(unt,'(a)') 'scalarType: Real64'
1291 0 : write(unt,'(a)') 'dimensions:'
1292 0 : write(unt,'(a,i0)') ' - length: ',m_npw
1293 0 : write(unt,'(a)') ' type: Momentum'
1294 0 : write(unt,'(a)') 'elements:'
1295 0 : write(unt,'(a)') ' type: TextFile'
1296 0 : write(unt,'(a)') 'unit: 1.0 # Atomic units '
1297 0 : close(unt)
1298 :
1299 0 : filepath = trim(dtfil%filnam_ds(4))//'_CoulombPotential.elements'
1300 0 : write(ab_out, "(3a)")ch10, ' Writing CoulombPotential data to file: ', trim(filepath)
1301 0 : if (open_file(filepath, msg, newunit=unt, access="stream", form="formatted", status="replace", action="write") /= 0) then
1302 0 : ABI_ERROR(msg)
1303 : end if
1304 0 : do ig=1,m_npw
1305 0 : write(unt,*)real(sqrt_vc(ig) * conjg(sqrt_vc(ig)), kind=dp)
1306 : !write(unt,*)real(sqrt_vc(ig)**2)
1307 : end do
1308 0 : close(unt)
1309 : end if ! ik_ibz == 1 .and. spin == 1
1310 : end if ! my_rank == master
1311 :
1312 : ! Open binary file to store CoulombVertex
1313 0 : cvx_filepath = trim(dtfil%filnam_ds(4))//'_CoulombVertex.elements'
1314 0 : if (my_rank == master) write(ab_out, "(3a)")ch10, ' Writing CoulombVertex data to file: ', trim(cvx_filepath)
1315 :
1316 : #ifdef HAVE_MPI_IO
1317 0 : call MPI_FILE_OPEN(comm, cvx_filepath, MPI_MODE_CREATE + MPI_MODE_WRONLY, xmpio_info, fh, mpierr)
1318 0 : ABI_CHECK_MPI(mpierr, "MPI_FILE_OPEN")
1319 : #else
1320 : ABI_ERROR("CC4S interface requires MPI-IO!")
1321 : #endif
1322 :
1323 : if (trust_no_one .and. my_rank == 0) then
1324 : if (open_file("test_mg", msg, newunit=test_unt, form="formatted", status="replace", action="write") /= 0) then
1325 : ABI_ERROR(msg)
1326 : end if
1327 : end if
1328 :
1329 : ! Define batch sizes and allocate workspace arrays.
1330 : ! Increasing this value improves efficiency (less communication) at the price of more memory.
1331 0 : batch1_size = min(48, ugb%nband_k); batch2_size = min(48, ugb%nband_k) !; batch1_size = 1; batch2_size = 1
1332 0 : call wrtout(std_out, sjoin(" Using batch1_size:", itoa(batch1_size), ", batch2_size:", itoa(batch2_size)))
1333 :
1334 : mem_mb = (two * u_nfft * nspinor * batch1_size + &
1335 : two * u_nfft * nspinor * batch2_size * two + &
1336 0 : two * m_npw * nspinor * batch2_size) * dp * b2Mb
1337 0 : call wrtout(std_out, sjoin(" Memory for workspace arrays ", ftoa(mem_mb, fmt="f8.1"), "[Mb] <<< MEM"))
1338 :
1339 0 : ABI_MALLOC(ur1_batch, (u_nfft * nspinor, batch1_size))
1340 0 : ABI_MALLOC(ur2_batch, (u_nfft * nspinor, batch2_size))
1341 0 : ABI_MALLOC(ur12_batch, (u_nfft * nspinor, batch2_size))
1342 0 : ABI_MALLOC(ug12_batch, (m_npw * nspinor, batch2_size))
1343 :
1344 0 : if (psps%usepaw == 1) then
1345 : ! Evaluate oscillator matrix elements btw partial waves. Note q=Gamma
1346 0 : ABI_MALLOC(pwij, (psps%ntypat))
1347 0 : call pawpwij_init(pwij, m_npw, qpt, m_gvec, cryst%rprimd, psps, pawtab, paw_pwff)
1348 0 : do iatom=1,cryst%natom
1349 0 : nlmn_atm(iatom) = pawtab(cryst%typat(iatom))%lmn_size
1350 : end do
1351 0 : ABI_MALLOC(cprj1, (cryst%natom, nspinor*batch1_size))
1352 0 : call pawcprj_alloc(cprj1, 0, nlmn_atm)
1353 0 : dim_rtwg = nspinor
1354 0 : ABI_MALLOC(paw_rhotwg, (m_npw*dim_rtwg))
1355 : end if
1356 :
1357 : ! TODO:
1358 : ! 1) take advantage of M_{b1,b2}(g) = <b1|e^{-ig.r}|b2> => M_{b1,b2}(g) = M_{b2,b1}(-g)^*
1359 : ! once I have a better understanding of the fileformat expected by CC4S.
1360 : ! 2) Handle parallel IO if nsppol 2 (we are inside the spin loop that is already MPI distributed!)
1361 : ! 3) Clarify ordering of CoulombVertex (b1,b2 vs b2,b1) and eigenvalues (spin?)
1362 : ! 4) Treatment of q--> 0 in vc_coul
1363 : ! 4) See other TODOs below.
1364 :
1365 0 : call uplan_1%init(npw_k, nspinor, batch1_size, u_ngfft, ugb%istwf_k, ugb%kg_k, dp, dtset%gpu_option)
1366 0 : call uplan_2%init(npw_k, nspinor, batch2_size, u_ngfft, ugb%istwf_k, ugb%kg_k, dp, dtset%gpu_option)
1367 0 : call uplan_m%init(m_npw, nspinor, batch2_size, u_ngfft, m_istwfk, m_gvec, dp, dtset%gpu_option)
1368 :
1369 0 : M_ = m_npw
1370 :
1371 : ! Blocked loop over group of b1 indices. NB: Assuming bands distributed in contiguous blocks.
1372 0 : do band1_start=1, ugb%nband_k, batch1_size
1373 : ! Collect n1dat bands starting from band1_start on each proc.
1374 0 : n1dat = blocked_loop(band1_start, ugb%nband_k, batch1_size)
1375 :
1376 0 : call ugb%mat%collect_cplx(ugb%npwsp, n1dat, [1, band1_start], ug1_batch)
1377 0 : if (psps%usepaw == 1) call ugb%collect_cprj(nspinor, n1dat, band1_start, cprj1)
1378 :
1379 : ! FFT: ug1_batch --> ur1_batch
1380 0 : call uplan_1%execute_gr(n1dat, ug1_batch(:,1), ur1_batch(:,1))
1381 0 : if (ugb%istwf_k /= 2) ur1_batch = conjg(ur1_batch) ! Not needed if k == Gamma as ur1 is real.
1382 0 : ABI_FREE(ug1_batch)
1383 :
1384 : ! Blocked loop over MY group of b2 indices (contiguous blocks)
1385 0 : do band2_start=ugb%my_bstart, ugb%my_bstop, batch2_size
1386 0 : n2dat = blocked_loop(band2_start, ugb%my_bstop, batch2_size)
1387 0 : my_ib2st = band2_start - ugb%my_bstart + 1
1388 :
1389 : ! FFT: ugb%mat --> ur2_batch for n2dat states.
1390 0 : call uplan_2%execute_gr(n2dat, ugb%mat%buffer_cplx(:,my_ib2st), ur2_batch(:,1))
1391 :
1392 : ! For each row of the submatrix, build n2dat products (band1, idat2) in r-space, then r --> g.
1393 0 : do idat1=1,n1dat
1394 0 : band1 = band1_start + idat1 - 1
1395 :
1396 0 : do idat2=1,n2dat
1397 0 : ur12_batch(:,idat2) = ur1_batch(:,idat1) * ur2_batch(:,idat2)
1398 : end do
1399 0 : call uplan_m%execute_rg(n2dat, ur12_batch(:,1), ug12_batch(:,1))
1400 :
1401 0 : if (psps%usepaw == 1) then
1402 : ! Add PAW on-site contributions
1403 0 : do idat2=1,n2dat
1404 : associate (cprj1_kmq => cprj1(:, 1 + (idat1-1)*nspinor), &
1405 0 : cprj2_k => ugb%cprj_k(:, 1 + (my_ib2st+idat2-2)*nspinor)) ! NB: ugb%cprj_k(2, nspinor*my_nband)
1406 0 : paw_rhotwg = zero
1407 0 : call paw_rho_tw_g(cryst, pwij, m_npw, dim_rtwg, nspinor, m_gvec, cprj1_kmq, cprj2_k, paw_rhotwg)
1408 0 : ug12_batch(:,idat2) = ug12_batch(:,idat2) + paw_rhotwg
1409 : end associate
1410 : end do
1411 : end if
1412 :
1413 : ! This to zero the matrix elements for certain (band1, band2) entries.
1414 : ! in this case: band1 = 1, band2 = 1.
1415 : !if (band1 == 1) then
1416 : ! do idat2=1,n2dat
1417 : ! ! This is the condition for band2
1418 : ! if (band2_start + idat2 - 1 == 1) ug12_batch(:,idat2) = zero
1419 : ! end do
1420 : !end if
1421 :
1422 0 : if (nspinor == 2) then
1423 : ! Sum over spinors and repack data in the first n2dat positions to prepare IO operation.
1424 0 : do idat2=1,n2dat
1425 0 : ug12_batch(1:m_npw,idat2) = ug12_batch(1:m_npw,idat2) + ug12_batch(m_npw+1:,idat2)
1426 : end do
1427 0 : do idat2=2,n2dat,2
1428 0 : ug12_batch(m_npw+1:,idat2-1) = ug12_batch(1:m_npw,idat2)
1429 : end do
1430 : end if
1431 :
1432 0 : do idat2=1,n2dat
1433 : !if (band1 == band2_start + idat2 -1) then
1434 : ! write(std_out,*) " ug12_batch(g=0,band1,band2), band", ug12_batch(1,idat2), band1, band2_start + idat2 -1
1435 : !end if
1436 : ! Multiply by sqrt(vc(g))
1437 : ! This renormalization is needed to make CC4S converge (work done by AlejandroG, FabienB, MatteoG)
1438 0 : ug12_batch(:,idat2) = ug12_batch(:,idat2) * sqrt_vc(:) / sqrt(cryst%ucvol)
1439 : !FBru:
1440 : ! CC4S convention:
1441 : ! When using time-reversal, include a factor sqrt(2) for the non-zero G's
1442 : ! Then CC4S will perform the sum only over half the grid so all the G/=0 component should be counted twice.
1443 0 : if (m_istwfk == 2) ug12_batch(2:,idat2) = ug12_batch(2:,idat2) * sqrt(two)
1444 : end do
1445 : !write(std_out,*)" max(abs(ug12_batch)):", maxval(abs(ug12_batch(:,1:n2dat)))
1446 :
1447 : #ifdef HAVE_MPI_IO
1448 : ! Write ug12_batch using Stream-IO
1449 0 : buf_size = m_npw * n2dat
1450 :
1451 : ! FBru convert to longer integer before the multiplication
1452 : offset = INT(m_npw, KIND=XMPI_OFFSET_KIND) &
1453 : * INT( (band2_start-1) + (band1-1) * ugb%nband_k, KIND=XMPI_OFFSET_KIND) &
1454 0 : * INT(xmpi_bsize_dpc, KIND=XMPI_OFFSET_KIND)
1455 :
1456 0 : call MPI_FILE_WRITE_AT(fh, offset, ug12_batch, buf_size, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
1457 0 : ABI_HANDLE_MPIERR(mpierr)
1458 :
1459 0 : if (my_rank == 0 .and. trust_no_one) then
1460 : do idat2=1,n2dat
1461 : band2 = band2_start + idat2 - 1
1462 : write(test_unt,*)band1, band2, ug12_batch(1:M_,idat2)
1463 : end do
1464 : end if
1465 : #endif
1466 : end do ! idat1
1467 :
1468 : end do ! band2_start
1469 : end do ! band1_start
1470 :
1471 : #ifdef HAVE_MPI_IO
1472 0 : call MPI_FILE_CLOSE(fh, mpierr)
1473 0 : ABI_CHECK_MPI(mpierr, "FILE_CLOSE!")
1474 0 : call xmpi_barrier(comm)
1475 :
1476 0 : if (my_rank == 0) then
1477 0 : buf_size = 4
1478 0 : call wrtout(units, sjoin(" Reading norm of Coulomb vertex for testing purposes with ng:", itoa(buf_size)), newlines=1, pre_newlines=1)
1479 0 : call wrtout(units, " List of g-vectors in the Coulomb vertex:")
1480 0 : do ig=1,buf_size
1481 0 : call wrtout(units, sjoin(itoa(ig), ":", ltoa(m_gvec(:,ig))))
1482 : end do
1483 0 : ABI_MALLOC(cwork, (buf_size))
1484 0 : call MPI_FILE_OPEN(xmpi_comm_self, cvx_filepath, MPI_MODE_RDONLY, xmpio_info, fh, mpierr)
1485 0 : ABI_CHECK_MPI(mpierr, "MPI_FILE_OPEN")
1486 0 : ierr = 0
1487 0 : band1_loop: do band1=1, ugb%nband_k
1488 0 : do band2=1, ugb%nband_k
1489 0 : ierr = ierr + 1; if (ierr == 6) exit band1_loop
1490 0 : offset = ((band2-1) * m_npw + (band1-1) * m_npw * ugb%nband_k) * xmpi_bsize_dpc
1491 0 : call MPI_FILE_READ_AT(fh, offset, cwork, buf_size, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
1492 0 : ABI_HANDLE_MPIERR(mpierr)
1493 0 : call wrtout(units, sjoin(" For band1:", itoa(band1), ", band2:", itoa(band2)))
1494 0 : where (abs(cwork) < tol8)
1495 : cwork = zero
1496 : end where
1497 0 : write(msg, "(*(1x, es12.5))")abs(cwork(1:buf_size))
1498 0 : call wrtout(units, msg)
1499 : end do
1500 : end do band1_loop
1501 0 : ABI_FREE(cwork)
1502 : end if
1503 : #endif
1504 :
1505 : ! =============
1506 : ! DEBUG SECTION
1507 : ! =============
1508 : #ifdef HAVE_MPI_IO
1509 : if (my_rank == 0 .and. trust_no_one) then
1510 : close(test_unt)
1511 : if (open_file("test_mg", msg, newunit=test_unt, form="formatted", status="old", action="read") /= 0) then
1512 : ABI_ERROR(msg)
1513 : end if
1514 :
1515 : call MPI_FILE_OPEN(xmpi_comm_self, cvx_filepath, MPI_MODE_RDONLY, xmpio_info, fh, mpierr)
1516 : ABI_CHECK_MPI(mpierr, "MPI_FILE_OPEN")
1517 :
1518 : ABI_MALLOC(cwork, (m_npw))
1519 : max_abs_err = zero
1520 : do ig=1, ugb%nband_k**2
1521 : read(test_unt,*) band1, band2, ug12_batch(1:M_,1)
1522 : offset = ((band2-1) * m_npw + (band1-1) * m_npw * ugb%nband_k) * xmpi_bsize_dpc
1523 : call MPI_FILE_READ_AT(fh, offset, cwork, m_npw, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
1524 : ABI_HANDLE_MPIERR(mpierr)
1525 :
1526 : abs_err = maxval(abs(ug12_batch(1:M_,1) - cwork(1:M_)))
1527 : max_abs_err = max(max_abs_err, abs_err)
1528 : if (abs_err > zero) write(std_out, *)" For ig:", ig, "/", ugb%nband_k**2, "abs_err", abs_err
1529 : !write(std_out, *)"1:", ug12_batch(1:M_,1); write(std_out, *)"2:", cwork(1:M_)
1530 : end do
1531 :
1532 : close(test_unt)
1533 : call MPI_FILE_CLOSE(fh, mpierr)
1534 : ABI_CHECK_MPI(mpierr, "FILE_CLOSE!")
1535 : ABI_FREE(cwork)
1536 :
1537 : write(std_out,*)" max_abs_err:", max_abs_err
1538 : ABI_CHECK(max_abs_err < tol16, sjoin("max_abs_err:", ftoa(max_abs_err)))
1539 : call wrtout(std_out, " Debugging section OK!!!")
1540 : end if
1541 : #endif
1542 :
1543 : ! Free memory
1544 0 : call uplan_1%free(); call uplan_2%free(); call uplan_m%free()
1545 :
1546 0 : ABI_FREE(m_gvec)
1547 0 : ABI_FREE(ur1_batch)
1548 0 : ABI_FREE(ur2_batch)
1549 0 : ABI_FREE(ur12_batch)
1550 0 : ABI_FREE(ug12_batch)
1551 0 : ABI_FREE(sqrt_vc)
1552 :
1553 0 : if (psps%usepaw == 1) then
1554 0 : call pawpwij_free(pwij)
1555 0 : ABI_FREE(pwij)
1556 0 : call pawcprj_free(cprj1)
1557 0 : ABI_FREE(cprj1)
1558 0 : ABI_FREE(paw_rhotwg)
1559 : end if
1560 :
1561 0 : call cwtime_report(" cc4s_gamma", cpu, wall, gflops)
1562 :
1563 0 : end subroutine cc4s_gamma
1564 : !!***
1565 :
1566 0 : end module m_gwr_driver
1567 : !!***
|