Line data Source code
1 : !!****m* ABINIT/m_io_screening
2 : !! NAME
3 : !! m_io_screening
4 : !!
5 : !! FUNCTION
6 : !! This module contains the definition of the header of the
7 : !! _SCR and _SUSC file as well as methods used to read/write/echo.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2008-2026 ABINIT group (MG)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : MODULE m_io_screening
24 :
25 : use, intrinsic :: iso_c_binding
26 : use defs_basis
27 : use m_abicore
28 : USE_MPI
29 : use m_xmpi
30 : use m_mpiotk
31 : use m_nctk
32 : use m_errors
33 : use m_dtset
34 : use netcdf
35 : use m_hdr
36 : use m_sort
37 : use m_crystal
38 : use m_gwdefs
39 :
40 : use m_time, only : cwtime, cwtime_report !, sec2str, timab
41 : use m_fstrings, only : sjoin, itoa, endswith, replace_ch0
42 : use m_copy, only : alloc_copy
43 : use m_io_tools, only : open_file, file_exists, iomode2str
44 : use m_numeric_tools, only : print_arr, remove_copies, imax_loc
45 : use m_bz_mesh, only : isequalk, kmesh_t
46 : use m_gsphere, only : gsphere_t
47 :
48 : implicit none
49 :
50 : private
51 : !!***
52 :
53 : #if defined HAVE_MPI1
54 : include 'mpif.h'
55 : #endif
56 :
57 : character(len=nctk_slen),public,parameter :: e_ncname = "dielectric_function"
58 : character(len=nctk_slen),public,parameter :: em1_ncname = "inverse_dielectric_function"
59 : character(len=nctk_slen),public,parameter :: chi0_ncname = "polarizability"
60 :
61 : public :: ncname_from_id ! return the name of the netcdf variable from the id
62 :
63 : !!****t* m_io_screening/hscr_t
64 : !! NAME
65 : !! hscr_t
66 : !!
67 : !! FUNCTION
68 : !! The structure defining the header of the SCR/SUSC file.
69 : !! hscr_t contains the most important dimensions associated to the SCR/SUSC matrix,
70 : !! important GW metadata and the Abint header. The SCR/SUS matrices are saved
71 : !! with the same format. There are nqibz blocks, each block contains (npwe,npwe,nomega) matrices.
72 : !! SCR and SUS files mainly differ for what concerns the treatment of the q-->0 limit.
73 : !! The treatment of the non-analytic behaviour is not yet implemented but the main ideas are
74 : !! sketched in the NOTES below.
75 : !!
76 : !! NOTES
77 : !! On the treatment of the q-->0 limit
78 : !!
79 : !! 1) q=Gamma should be the first q-point
80 : !!
81 : !! 2) This point contains an initial section with data used to treat the q-->0 limit, followed
82 : !! by the SCR/SUS matrix evaluated for the small q-point (qlwl). The header should contains
83 : !! enough info so that we can skip this section and use the pre-existing routines to read
84 : !! the matrices.
85 : !!
86 : !! 3) The data stored in the q-->0 section depends on the type of matrix stored in the file:
87 : !!
88 : !! SUS file: we store the tensor and the wings needed to reconstruct the q-dependence around Gamma.
89 : !! This section if followed by the X(G,G') matrix evaluated at qlwl.
90 : !! Note that the content of the SUS file does not depend on a possible cutoff in vcoul.
91 : !!
92 : !! SCR file: two cases must be considered:
93 : !!
94 : !! No cutoff in vcoul:
95 : !! The q-->0 section stores the tensor, the wings as well as the inverse of the body B^{-1}.
96 : !! This info is used to integrate W(q) around q==Gamma.
97 : !!
98 : !! cutoff in vcoul:
99 : !! The content of the q-->0 section depends on dimensionality of the system.
100 : !! In 2D we need info on chi0 as well as A and a. See http://arxiv.org/pdf/1511.00129v1.pdf
101 : !! I think that this kind of calculations are easy to implement if we start from the SUS file.
102 : !! Ok, we have to recompute e-1 at each run but the logic is easier to implement.
103 : !!
104 : !! SOURCE
105 :
106 : type,public :: hscr_t
107 :
108 : integer :: id = -1
109 : ! Matrix identifier: 1 for chi0, 2 for chi, 3 for epsilon, 4 for espilon^{-1}
110 :
111 : integer :: ikxc = 0
112 : ! Kxc kernel used,
113 : ! 0 for None (RPA), >0 for static TDDFT (=ixc), <0 for frequency-dependent TDDFT
114 :
115 : integer :: inclvkb = 2
116 : ! q-->0 treatment, 0 for None, 1-2 for transversal gauge, 3 for longitudinal
117 :
118 : integer :: headform
119 : ! format of the SCR header
120 :
121 : integer :: fform
122 : ! File format
123 :
124 : integer :: gwcalctyp = 0
125 : ! Calculation type (G0W0, G0W, GW ...)
126 :
127 : integer :: nI = 1, nJ = 1
128 : ! Number of spin components (rows,columns) in chi|eps^-1. (1,1) if collinear.
129 : ! The internal representation of the matrix is eps(nI*npwe,nJ*npwe)
130 :
131 : integer :: nqibz = -1
132 : ! Number of q-points in the IBZ.
133 :
134 : integer :: nqlwl = 1
135 : ! Number of points for the treatment of the long wavelength limit.
136 :
137 : integer :: nomega = -1
138 : ! Total number of frequencies.
139 :
140 : integer :: nbnds_used = -1
141 : ! Number of bands used during the screening calculation (only for info)
142 :
143 : integer :: npwe = -1
144 : ! Number of G vectors reported on the file.
145 :
146 : integer :: npwwfn_used = -1
147 : ! Number of G vectors for wavefunctions used during the screening calculation (only for info)
148 :
149 : integer :: spmeth = 0
150 : ! Method used to approximate the delta function in the expression for Im Chi_0
151 :
152 : integer :: test_type
153 : ! 1 for TEST-PARTICLE, 2 for TEST-ELECTRON.
154 :
155 : integer :: tordering = 1
156 : ! 1 for Time-Ordered, 2 for Advanced, 3 for Retarded.
157 :
158 : ! HSCR_NEW
159 : integer :: awtr = 1
160 : ! Input variable (time-reversal symmetry in RPA expression)
161 :
162 : integer :: icutcoul = 0
163 : ! Input variable (Coulomb singularity treatment)
164 :
165 : integer :: gwcomp = 0
166 : ! Input variable (GW compensation energy technique)
167 :
168 : integer :: gwgamma = 0
169 : ! Input variable Vertex correction
170 : ! HSCR_NEW
171 :
172 : real(dp) :: mbpt_sciss = zero
173 : ! Scissor Energy, zero if not used
174 :
175 : real(dp) :: spsmear = zero
176 : ! Smearing of the delta in case of spmeth==2
177 :
178 : real(dp) :: zcut = -one
179 : ! Imaginary shift to avoid the poles along the real axis.
180 :
181 : ! HSCR_NEW
182 : real(dp) :: gwencomp = -one
183 : ! Input variable (GW compensation energy technique)
184 :
185 : character(len=3) :: kind_cdata
186 : ! Flag to signal whether the data is in single or double precision ("spc" or "dp")
187 : ! For the time being, we always write/read in double precision.
188 : ! This flag could be use to reduce the memory requirements if spc:
189 : ! we run calculations in single precision dump the results with the same precision without
190 : ! having to allocate extra memory.
191 : ! HSCR_NEW
192 :
193 : !arrays
194 :
195 : ! HSCR_NEW
196 : real(dp) :: vcutgeo(3) = zero
197 : ! Input variable (defines coulomb cutoff)
198 : ! HSCR_NEW
199 :
200 : character(len=80) :: titles(2)
201 : ! Titles describing the content of the file.
202 :
203 : integer,allocatable :: gvec(:,:)
204 : ! gvec(3,npwe)
205 : ! G vectors in reduced coordinates.
206 :
207 : real(dp),allocatable :: qibz(:,:)
208 : ! qibz(3,nqibz)
209 : ! q-points in the IBZ in reduced coordinates.
210 :
211 : real(dp),allocatable :: qlwl(:,:)
212 : ! qlwl(3,nqlwl)
213 : ! q-points for the long wave-length limit treatment (r.l.u)
214 :
215 : complex(dp),allocatable :: omega(:)
216 : ! omega(nomega)
217 : ! All frequencies calculated both along the real and the imaginary axis.
218 : ! Real frequencies are packed in the first section.
219 :
220 : real(dp),allocatable :: omega_wgs(:)
221 : ! (nomega)
222 : ! Weights for numerical integration. Used for instance for minimax meshes.
223 :
224 : character(len=etsfio_charlen) :: iw_mesh_type="None", rw_mesh_type="None", cw_mesh_type="None"
225 : ! String defining the kind of sampling for imaginary (iw), real (rw) and complex (cw) frequencies
226 :
227 : type(hdr_type) :: hdr
228 : ! The abinit header.
229 :
230 : contains
231 : procedure :: from_file => hscr_from_file ! Read the header from file.
232 : procedure :: print => hscr_print ! Print the SCR-related part of the header.
233 : procedure :: bcast => hscr_bcast ! Broadcast the header.
234 : procedure :: free => hscr_free ! Free the header.
235 : procedure :: copy => hscr_copy ! Copy the SCR|SUSC header.
236 : procedure :: io => hscr_io ! I/O of the header (read/write/echo).
237 : end type hscr_t
238 : !!***
239 :
240 : !integer,private,parameter :: HSCR_KNOWN_HEADFORMS(1) = [80]
241 : integer,private,parameter :: HSCR_KNOWN_HEADFORMS(2) = [80, 81]
242 : ! The list of headforms used for SCR/SUSC so far.
243 :
244 : integer,private,parameter :: size_hscr_known_headforms = size(HSCR_KNOWN_HEADFORMS) ! Need this for Flang
245 : integer,public,parameter :: HSCR_LATEST_HEADFORM = HSCR_KNOWN_HEADFORMS(size_hscr_known_headforms)
246 : ! The latest headform used when writing.
247 :
248 : public :: hscr_new ! Create header.
249 : public :: hscr_merge ! Merge two or more headers.
250 : public :: write_screening ! Write a q-slice of the matrix in G-space.
251 : public :: read_screening ! Read the content of the (SCR|SUSC) file placed after the header.
252 : public :: get_hscr_qmesh_gsph
253 :
254 : ! =====================
255 : ! Tools used in mrgscr
256 : ! =====================
257 : public :: ioscr_qmerge ! Produce new file by merging the q-points stored in other files.
258 : public :: ioscr_qrecover ! Recover q-points from a corrupted file produced e.g. from an interrupted run
259 : public :: ioscr_wmerge ! Produce new file by merging the frequencies stored in other files.
260 : public :: ioscr_wremove ! Produce new file by removing selected frequencies in the initial file.
261 :
262 : CONTAINS !================================================================================================
263 : !!***
264 :
265 : !!****f* m_io_screening/ncname_from_id
266 : !! NAME
267 : !! ncname_from_id
268 : !!
269 : !! FUNCTION
270 : !! Return the name of the netcdf variable (chi0, espilon, em1...) from the id.
271 : !!
272 : !! SOURCE
273 :
274 498 : character(len=nctk_slen) function ncname_from_id(id) result(varname)
275 :
276 : integer,intent(in) :: id
277 :
278 498 : varname = "None"
279 498 : if (id == 1) varname = chi0_ncname
280 498 : if (id == 3) varname = e_ncname
281 498 : if (id == 4) varname = em1_ncname
282 498 : ABI_CHECK(varname /= "None", "Wrong id")
283 :
284 498 : end function ncname_from_id
285 : !!***
286 :
287 : !!****f* m_io_screening/hscr_from_file
288 : !! NAME
289 : !! hscr_from_file
290 : !!
291 : !! FUNCTION
292 : !! Read the header of the (SCR/SUS) file
293 : !!
294 : !! INPUTS
295 : !! path=File name
296 : !! comm = MPI communicator.
297 : !!
298 : !! OUTPUT
299 : !! hscr<hscr_t>=The header.
300 : !! fform=Kind of the array in the file (0 signals an error)
301 : !!
302 : !! SOURCE
303 :
304 212 : subroutine hscr_from_file(hscr, path, fform, comm)
305 :
306 : !Arguments ------------------------------------
307 : !scalars
308 : class(hscr_t),intent(out) :: hscr
309 : character(len=*),intent(in) :: path
310 : integer,intent(out) :: fform
311 : integer,intent(in) :: comm
312 :
313 : !Local variables-------------------------------
314 : !scalars
315 : integer,parameter :: rdwr5 = 5, master = 0
316 : integer :: unt,my_rank,ierr
317 : character(len=500) :: msg
318 : ! *************************************************************************
319 :
320 212 : my_rank = xmpi_comm_rank(comm)
321 :
322 : ! Master reads and broadcasts.
323 212 : if (my_rank == master) then
324 184 : if (.not. endswith(path, ".nc")) then
325 : ! Fortran-IO
326 0 : if (open_file(path,msg,newunit=unt,form="unformatted", status="old",action="read") /= 0) then
327 0 : ABI_ERROR(msg)
328 : end if
329 0 : call hscr%io(fform, rdwr5, unt, xmpi_comm_self, master, IO_MODE_FORTRAN)
330 0 : close(unt)
331 : else
332 : ! Netcdf format
333 184 : NCF_CHECK(nctk_open_read(unt, path, xmpi_comm_self))
334 184 : call hscr%io(fform, rdwr5, unt, xmpi_comm_self, master, IO_MODE_ETSF)
335 184 : NCF_CHECK(nf90_close(unt))
336 : end if
337 :
338 184 : ABI_CHECK(fform /= 0, sjoin("hscr_io returned fform == 0 while reading:", path))
339 : end if
340 :
341 : ! Broadcast data.
342 212 : if (xmpi_comm_size(comm) > 1) then
343 42 : call hscr%bcast(master, my_rank, comm)
344 42 : call xmpi_bcast(fform,master,comm,ierr)
345 : end if
346 :
347 212 : end subroutine hscr_from_file
348 : !!***
349 :
350 : !!****f* m_io_screening/hscr_io
351 : !! NAME
352 : !! hscr_io
353 : !!
354 : !! FUNCTION
355 : !! This subroutine deals with the I/O of the hscr_t structured variables (read/write/echo).
356 : !! According to the value of rdwr, it reads the header of a file, writes it, or echo the value
357 : !! of the structured variable to a file. Note that, when reading, different records of hscr_t
358 : !! are allocated here, according to the values of the read variables. Records of hscr_t should be
359 : !! deallocated correctly by a call to hdr_free when hscr_t is not used anymore.
360 : !!
361 : !! INPUTS
362 : !! iomode=Option defining the file format of the external file.
363 : !! comm=MPI communicator.
364 : !! master=rank of the master node in comm, usually 0
365 : !! rdwr= if 1, read the hscr_t structured variable from the header of the file,
366 : !! if 2, write the header to unformatted file
367 : !! if 3, echo part of the header to formatted file (records 1 and 2)
368 : !! if 4, echo the header to formatted file
369 : !! if 5, read the hscr_t without rewinding (unformatted)
370 : !! if 6, write the hscr_t without rewinding (unformatted)
371 : !! unt=unit number of the file (unformatted if rdwr=1, 2, 5 or 6 formatted if rdwr=3,4)
372 : !!
373 : !! OUTPUT
374 : !! (see side effects)
375 : !!
376 : !! SIDE EFFECTS
377 : !! The following variables are both input or output :
378 : !! fform=kind of the array in the file
379 : !! if rdwr=1,5 : will be output ; if the reading fail, return fform=0
380 : !! if rdwr=2,3,4,6 : should be input, will be written or echo to file
381 : !! hscr_t <type(hscr_t)>=the header structured variable
382 : !! if rdwr=1,5 : will be output
383 : !! if rdwr=2,3,4,6 : should be input, will be written or echo to file
384 : !!
385 : !! NOTES
386 : !! In all cases, the file is supposed to be open already
387 : !! When reading (rdwr=1) or writing (rdwr=2), rewind the file
388 : !! When echoing (rdwr=3) does not rewind the file.
389 : !! When reading (rdwr=5) or writing (rdwr=6), DOES NOT rewind the file
390 : !!
391 : !! In writing mode, the routine is supposed to called by the master node.
392 : !! no check is done, it is up to the developer.
393 : !!
394 : !! SOURCE
395 :
396 901 : subroutine hscr_io(hscr, fform, rdwr, unt, comm, master, iomode)
397 :
398 : !Arguments ------------------------------------
399 : !scalars
400 : class(hscr_t),target,intent(inout) :: hscr
401 : integer,intent(inout) :: fform
402 : integer,intent(in) :: rdwr,unt,iomode,comm,master
403 :
404 : !Local variables-------------------------------
405 : !scalars
406 : integer :: my_rank,nprocs,ncerr,ncid,varid,ierr !ii
407 : character(len=500) :: errmsg
408 : character(len=nctk_slen) :: varname !,head_shape,wing_shape
409 : !arrays
410 901 : real(dp),allocatable :: real_omega(:,:)
411 901 : real(dp), contiguous, pointer :: r2vals(:,:) !,rvals3(:,:,:)
412 : ! *************************************************************************
413 :
414 : DBG_ENTER("COLL")
415 : !@hscr_t
416 : ABI_UNUSED(master) ! FIXME
417 :
418 : ! Initialize MPI info for comm ===
419 901 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
420 :
421 901 : if (rdwr==1 .or. rdwr==5) then
422 :
423 : if (.True.) then
424 : ! TODO: only master should read but then I have to skip the header.
425 : !if (my_rank == master) then
426 : ! Read the abinit header, rewinding of the file (if any) is done here.
427 764 : if (iomode==IO_MODE_FORTRAN) then
428 0 : call hscr%hdr%fort_read(unt, fform, rewind=(rdwr==1))
429 764 : else if (iomode==IO_MODE_ETSF) then
430 764 : call hscr%hdr%ncread(unt, fform)
431 : end if
432 :
433 : ! Reset the variables absent in old versions.
434 764 : Hscr%fform=fform
435 :
436 764 : if (iomode==IO_MODE_FORTRAN .or. iomode==IO_MODE_MPI) then
437 0 : select case (fform)
438 : case (1003, 1004)
439 : ! File format for epsilon^-1, espilon, chi0
440 0 : read(unt, err=10, iomsg=errmsg)hscr%titles
441 : read(unt, err=10, iomsg=errmsg)&
442 0 : hscr%id, hscr%ikxc, hscr%inclvkb, hscr%headform, hscr%fform, hscr%gwcalctyp,&
443 0 : hscr%nI, hscr%nJ, hscr%nqibz, hscr%nqlwl, hscr%nomega, hscr%nbnds_used,&
444 0 : hscr%npwe, hscr%npwwfn_used, hscr%spmeth, hscr%test_type, hscr%tordering,&
445 0 : hscr%awtr, hscr%icutcoul, hscr%gwgamma, hscr%vcutgeo(1:3)
446 :
447 : ! Read real scalars
448 : read(unt, err=10, iomsg=errmsg)&
449 0 : hscr%mbpt_sciss, hscr%spsmear, hscr%zcut, hscr%gwencomp, hscr%kind_cdata
450 :
451 : ! Allocate arrays and read them
452 0 : call hscr_malloc(hscr, hscr%npwe, hscr%nqibz, hscr%nomega, hscr%nqlwl)
453 :
454 0 : read(unt, err=10, iomsg=errmsg)hscr%gvec(:,:)
455 0 : read(unt, err=10, iomsg=errmsg)hscr%qibz(:,:)
456 0 : read(unt, err=10, iomsg=errmsg)hscr%omega(:)
457 :
458 : ! Read data for q-->0 limit.
459 0 : if (hscr%nqlwl>0) then
460 0 : read(unt, err=10, iomsg=errmsg)hscr%qlwl(:,:)
461 : end if
462 :
463 0 : call set_defaults_from_gwcalctyp()
464 0 : if (hscr%headform > 80) then
465 0 : read(unt, err=10, iomsg=errmsg)hscr%rw_mesh_type
466 0 : read(unt, err=10, iomsg=errmsg)hscr%iw_mesh_type
467 0 : read(unt, err=10, iomsg=errmsg)hscr%cw_mesh_type
468 0 : read(unt, err=10, iomsg=errmsg)hscr%omega_wgs
469 : end if
470 :
471 : case default
472 0 : ABI_BUG(sjoin('Wrong fform read:', itoa(fform)))
473 : end select
474 :
475 764 : else if (iomode == IO_MODE_ETSF) then
476 764 : ncid = unt
477 :
478 764 : select case (fform)
479 : case (1003, 1004)
480 : ! Get dimensions and allocate arrays.
481 764 : NCF_CHECK(nctk_get_dim(ncid, "number_of_coefficients_dielectric_function", hscr%npwe))
482 764 : NCF_CHECK(nctk_get_dim(ncid, "number_of_qpoints_dielectric_function", hscr%nqibz))
483 764 : NCF_CHECK(nctk_get_dim(ncid, "number_of_frequencies_dielectric_function", hscr%nomega))
484 764 : NCF_CHECK(nctk_get_dim(ncid, "number_of_qpoints_gamma_limit", hscr%nqlwl))
485 764 : NCF_CHECK(nctk_get_dim(ncid, "nI", hscr%ni))
486 764 : NCF_CHECK(nctk_get_dim(ncid, "nJ", hscr%nj))
487 764 : call hscr_malloc(hscr, hscr%npwe, hscr%nqibz, hscr%nomega, hscr%nqlwl)
488 :
489 764 : varid = nctk_idname(ncid, 'reduced_coordinates_plane_waves_dielectric_function')
490 764 : NCF_CHECK(nf90_get_var(ncid, varid, hscr%gvec, start=[1,1,1]))
491 764 : NCF_CHECK(nf90_get_var(ncid, vid('qpoints_dielectric_function'), hscr%qibz))
492 :
493 2292 : ABI_MALLOC(real_omega, (2, hscr%nomega))
494 764 : NCF_CHECK(nf90_get_var(ncid, vid('frequencies_dielectric_function'), real_omega))
495 5283 : hscr%omega = dcmplx(real_omega(1,:), real_omega(2,:))
496 764 : ABI_FREE(real_omega)
497 :
498 : ! Read extra data added in new header.
499 764 : NCF_CHECK(nf90_get_var(ncid, vid("vcutgeo"), hscr%vcutgeo))
500 764 : NCF_CHECK(nf90_get_var(ncid, vid("id"), hscr%id))
501 764 : NCF_CHECK(nf90_get_var(ncid, vid("ikxc"), hscr%ikxc))
502 764 : NCF_CHECK(nf90_get_var(ncid, vid("inclvkb"), hscr%inclvkb))
503 764 : NCF_CHECK(nf90_get_var(ncid, vid("headform"), hscr%headform))
504 764 : NCF_CHECK(nf90_get_var(ncid, vid("fform"), hscr%fform))
505 764 : NCF_CHECK(nf90_get_var(ncid, vid("gwcalctyp"), hscr%gwcalctyp))
506 764 : NCF_CHECK(nf90_get_var(ncid, vid("nbands_used"), hscr%nbnds_used))
507 764 : NCF_CHECK(nf90_get_var(ncid, vid("npwwfn_used"), hscr%npwwfn_used))
508 764 : NCF_CHECK(nf90_get_var(ncid, vid("spmeth"), hscr%spmeth))
509 764 : NCF_CHECK(nf90_get_var(ncid, vid("test_type"), hscr%test_type))
510 764 : NCF_CHECK(nf90_get_var(ncid, vid("tordering"), hscr%tordering))
511 764 : NCF_CHECK(nf90_get_var(ncid, vid("awtr"), hscr%awtr))
512 764 : NCF_CHECK(nf90_get_var(ncid, vid("gw_icutcoul"), hscr%icutcoul))
513 764 : NCF_CHECK(nf90_get_var(ncid, vid("gwcomp"), hscr%gwcomp))
514 764 : NCF_CHECK(nf90_get_var(ncid, vid("gwgamma"), hscr%gwgamma))
515 764 : NCF_CHECK(nf90_get_var(ncid, vid("mbpt_sciss"), hscr%mbpt_sciss))
516 764 : NCF_CHECK(nf90_get_var(ncid, vid("spsmear"), hscr%spsmear))
517 764 : NCF_CHECK(nf90_get_var(ncid, vid("zcut"), hscr%zcut))
518 764 : NCF_CHECK(nf90_get_var(ncid, vid("gwencomp"), hscr%gwencomp))
519 764 : NCF_CHECK(nf90_get_var(ncid, vid("kind_cdata"), hscr%kind_cdata))
520 764 : call replace_ch0(hscr%kind_cdata)
521 :
522 764 : NCF_CHECK(nf90_get_var(ncid, vid("titles"), hscr%titles))
523 2292 : call replace_ch0(hscr%titles(:))
524 :
525 : ! TODO Read it
526 764 : if (hscr%nqlwl /= 0) then
527 764 : NCF_CHECK(nf90_get_var(ncid, vid("qpoints_gamma_limit"), hscr%qlwl))
528 : end if
529 :
530 764 : call set_defaults_from_gwcalctyp()
531 764 : if (hscr%headform > 80) then
532 764 : NCF_CHECK(nf90_get_var(ncid, vid("rw_mesh_type"), hscr%rw_mesh_type))
533 764 : call replace_ch0(hscr%rw_mesh_type)
534 764 : NCF_CHECK(nf90_get_var(ncid, vid("iw_mesh_type"), hscr%iw_mesh_type))
535 764 : call replace_ch0(hscr%iw_mesh_type)
536 764 : NCF_CHECK(nf90_get_var(ncid, vid("cw_mesh_type"), hscr%cw_mesh_type))
537 764 : call replace_ch0(hscr%cw_mesh_type)
538 764 : NCF_CHECK(nf90_get_var(ncid, vid("omega_wgs"), hscr%omega_wgs))
539 : end if
540 :
541 : case default
542 764 : ABI_BUG(sjoin('Unsupported fform read:',itoa(fform)))
543 : end select
544 : else
545 0 : ABI_ERROR(sjoin("Unsupported value of iomode:", iomode2str(iomode)))
546 : end if
547 :
548 : end if ! master
549 :
550 : !call hscr%bcast(master, my_rank, comm)
551 : !call hscr_mpio_skip(mpio_fh,fform,offset)
552 :
553 137 : else if (rdwr == 2 .or. rdwr == 6) then
554 : ! Writing the header of an unformatted file.
555 : ! Always use the latest version.
556 :
557 137 : if (iomode==IO_MODE_FORTRAN .or. iomode==IO_MODE_MPI) then
558 : ! Write the abinit header.
559 0 : call hscr%hdr%fort_write(unt, fform, ierr)
560 0 : ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr != 0")
561 :
562 0 : write(unt, err=10, iomsg=errmsg)hscr%titles
563 :
564 : ! Write integers
565 : write(unt, err=10, iomsg=errmsg)&
566 0 : hscr%id, hscr%ikxc, hscr%inclvkb, hscr%headform, hscr%fform, hscr%gwcalctyp,&
567 0 : hscr%nI, hscr%nJ, hscr%nqibz, hscr%nqlwl, hscr%nomega, hscr%nbnds_used,&
568 0 : hscr%npwe, hscr%npwwfn_used, hscr%spmeth, hscr%test_type, hscr%tordering,&
569 0 : hscr%awtr, hscr%icutcoul, hscr%gwgamma, hscr%vcutgeo(1:3)
570 :
571 : ! Write real scalars
572 : write(unt, err=10, iomsg=errmsg)&
573 0 : hscr%mbpt_sciss, hscr%spsmear, hscr%zcut, hscr%gwencomp,hscr%kind_cdata
574 :
575 : ! Write arrays
576 0 : write(unt, err=10, iomsg=errmsg)hscr%gvec(:,:)
577 0 : write(unt, err=10, iomsg=errmsg)hscr%qibz(:,:)
578 0 : write(unt, err=10, iomsg=errmsg)hscr%omega(:)
579 :
580 : ! Add q-points for heads and wings for q-->0.
581 0 : if (hscr%nqlwl > 0) then
582 0 : write(unt, err=10, iomsg=errmsg)hscr%qlwl(:,:)
583 : end if
584 :
585 0 : if (hscr%headform > 80) then
586 0 : write(unt, err=10, iomsg=errmsg)hscr%rw_mesh_type
587 0 : write(unt, err=10, iomsg=errmsg)hscr%iw_mesh_type
588 0 : write(unt, err=10, iomsg=errmsg)hscr%cw_mesh_type
589 0 : write(unt, err=10, iomsg=errmsg)hscr%omega_wgs
590 : end if
591 :
592 137 : else if (iomode == IO_MODE_ETSF) then
593 137 : ncid = unt
594 : ! Write the abinit header, rewinding of the file (if any) is done here.
595 137 : NCF_CHECK(hscr%hdr%ncwrite(ncid, fform, nc_define=.True.))
596 :
597 : ! Define dimensions
598 : ! Part 2) of etsf-io specifications
599 : ! FIXME: Spin is only used in particular cases, We usually get the trace of W in spin space
600 : ! and I'm not gonna allocate extra memory just to have up up, down down
601 : ! Besides number_of_spins should be replaced by `number_of_spins_dielectric_function`
602 : ! Should add spin_dependent attribute.
603 : ncerr = nctk_def_dims(ncid, [ &
604 : nctkdim_t("complex", 2), nctkdim_t("number_of_reduced_dimensions", 3), &
605 : nctkdim_t("number_of_frequencies_dielectric_function", hscr%nomega), &
606 : nctkdim_t("number_of_qpoints_dielectric_function", hscr%nqibz), &
607 : nctkdim_t("number_of_qpoints_gamma_limit", hscr%nqlwl), &
608 : nctkdim_t("number_of_spins", hscr%hdr%nsppol), &
609 : nctkdim_t("nI", hscr%nI), nctkdim_t("nJ", hscr%nJ), &
610 1370 : nctkdim_t("number_of_coefficients_dielectric_function", hscr%npwe)], defmode=.True.)
611 137 : NCF_CHECK(ncerr)
612 :
613 : ! Part 3) of the specs
614 : ! (note that, in the specs, the Gs depend on the q-point but npwe is a scalar
615 : ! basis_set is added by the abinit header.
616 : ! FIXME: g-vectors are not written properly.
617 : ncerr = nctk_def_arrays(ncid, [&
618 : ! Standard
619 : nctkarr_t('frequencies_dielectric_function', "dp", 'complex, number_of_frequencies_dielectric_function'), &
620 : nctkarr_t('qpoints_dielectric_function', "dp", 'number_of_reduced_dimensions, number_of_qpoints_dielectric_function'),&
621 : nctkarr_t('qpoints_gamma_limit', "dp", 'number_of_reduced_dimensions, number_of_qpoints_gamma_limit'), &
622 : nctkarr_t('reduced_coordinates_plane_waves_dielectric_function', "i", &
623 : 'number_of_reduced_dimensions, number_of_coefficients_dielectric_function, number_of_qpoints_dielectric_function'), &
624 : ! Abinit
625 : nctkarr_t('vcutgeo', "dp", 'number_of_reduced_dimensions'), &
626 : nctkarr_t('kind_cdata', "char", 'character_string_length'), &
627 : nctkarr_t('titles', "char", 'character_string_length, two'), &
628 : nctkarr_t('rw_mesh_type', "char", 'character_string_length'), &
629 : nctkarr_t('iw_mesh_type', "char", 'character_string_length'), &
630 : nctkarr_t('cw_mesh_type', "char", 'character_string_length'), &
631 : nctkarr_t('omega_wgs', "dp", 'number_of_frequencies_dielectric_function') &
632 1644 : ])
633 137 : NCF_CHECK(ncerr)
634 :
635 : ! FIXME problem with q-points, heads and wings?
636 : ! The order in P in the specs is wrong, q should be the last dimension here I use the "correct" version
637 : ! TODO: Remove. Use abifile_t
638 137 : varname = ncname_from_id(hscr%id)
639 : ncerr = nctk_def_arrays(ncid, &
640 : nctkarr_t(varname, "dp", &
641 : &"complex, number_of_coefficients_dielectric_function, number_of_coefficients_dielectric_function,&
642 137 : &number_of_spins, number_of_spins, number_of_frequencies_dielectric_function, number_of_qpoints_dielectric_function"))
643 137 : NCF_CHECK(ncerr)
644 :
645 : !write(std_out,*)"nqlwl",hscr%nqlwl
646 137 : NCF_CHECK(nctk_set_datamode(ncid))
647 411 : call c_f_pointer(c_loc(hscr%omega(1)), r2vals, shape=[2, size(hscr%omega)])
648 137 : NCF_CHECK(nf90_put_var(ncid, vid('frequencies_dielectric_function'), r2vals))
649 137 : NCF_CHECK(nf90_put_var(ncid, vid('qpoints_dielectric_function'), hscr%qibz))
650 137 : NCF_CHECK(nf90_put_var(ncid, vid('reduced_coordinates_plane_waves_dielectric_function'), hscr%gvec))
651 :
652 137 : NCF_CHECK(nf90_put_var(ncid, vid("titles"), hscr%titles))
653 137 : NCF_CHECK(nf90_put_var(ncid, vid("kind_cdata"), hscr%kind_cdata))
654 137 : NCF_CHECK(nf90_put_var(ncid, vid("vcutgeo"), hscr%vcutgeo))
655 :
656 : ncerr = nctk_defnwrite_ivars(ncid, [character(len=nctk_slen) :: &
657 : "id", "ikxc", "inclvkb", "headform", "fform", "gwcalctyp", &
658 : "nbands_used", "npwwfn_used", "spmeth", "test_type", "tordering", "awtr", "gw_icutcoul", &
659 : "gwcomp", "gwgamma" &
660 : ],&
661 : [ hscr%id, hscr%ikxc, hscr%inclvkb, hscr%headform, hscr%fform, hscr%gwcalctyp, &
662 : hscr%nbnds_used, hscr%npwwfn_used, hscr%spmeth, hscr%test_type, hscr%tordering, hscr%awtr, hscr%icutcoul, &
663 : hscr%gwcomp, hscr%gwgamma &
664 4247 : ])
665 137 : NCF_CHECK(ncerr)
666 :
667 : ncerr = nctk_defnwrite_dpvars(ncid, [character(len=nctk_slen) :: &
668 : "mbpt_sciss", "spsmear", "zcut", "gwencomp"], &
669 : [hscr%mbpt_sciss, hscr%spsmear, hscr%zcut, hscr%gwencomp &
670 1233 : ])
671 137 : NCF_CHECK(ncerr)
672 :
673 : ! Add q-points for heads and wings for q-->0.
674 137 : if (hscr%nqlwl > 0) then
675 : ! MG: This part has been commented out as it's not used
676 : ! head_shape = "complex, number_of_spins, number_of_spins, number_of_frequencies_dielectric_function"
677 : ! head_shape = trim(head_shape)//", number_of_qpoints_gamma_limit"
678 :
679 : ! wing_shape = "complex, number_of_coefficients_dielectric_function, number_of_spins, number_of_spins"
680 : ! wing_shape = trim(wing_shape)//", number_of_frequencies_dielectric_function, number_of_qpoints_gamma_limit"
681 :
682 : ! ncerr = nctk_def_arrays(ncid, [&
683 : ! nctkarr_t("dielectric_function_head", "dp", head_shape),&
684 : ! nctkarr_t("dielectric_function_upper_wing", "dp", wing_shape),&
685 : ! nctkarr_t("dielectric_function_lower_wing", "dp", wing_shape)], defmode=.True.)
686 : ! NCF_CHECK(ncerr)
687 :
688 137 : NCF_CHECK(nctk_set_datamode(ncid))
689 137 : NCF_CHECK(nf90_put_var(ncid, vid('qpoints_gamma_limit'), hscr%qlwl))
690 :
691 : !if (hscr%headform > 80) then
692 137 : NCF_CHECK(nf90_put_var(ncid, vid("rw_mesh_type"), hscr%rw_mesh_type))
693 137 : NCF_CHECK(nf90_put_var(ncid, vid("iw_mesh_type"), hscr%iw_mesh_type))
694 137 : NCF_CHECK(nf90_put_var(ncid, vid("cw_mesh_type"), hscr%cw_mesh_type))
695 137 : NCF_CHECK(nf90_put_var(ncid, vid("omega_wgs"), hscr%omega_wgs))
696 : !end if
697 :
698 : end if
699 : else
700 0 : ABI_ERROR(sjoin('Unsupported iomode:',iomode2str(iomode)))
701 : end if
702 :
703 : else
704 0 : ABI_BUG(sjoin("Wrong value for rdwr:", itoa(rdwr)))
705 : end if ! read/write/echo
706 :
707 : DBG_EXIT("COLL")
708 :
709 901 : return
710 :
711 : ! Handle Fortran IO error
712 : 10 continue
713 1802 : ABI_ERROR(errmsg)
714 :
715 : contains
716 23663 : integer function vid(vname)
717 : character(len=*),intent(in) :: vname
718 23663 : vid = nctk_idname(ncid, vname)
719 : end function vid
720 :
721 764 : subroutine set_defaults_from_gwcalctyp()
722 : integer :: mod10
723 : ! Ppovide default values of mesh type on the basis of gw_calctyp if old format is read.
724 764 : mod10 = mod(hscr%gwcalctyp, 10)
725 764 : hscr%iw_mesh_type = "None"; hscr%rw_mesh_type = "None"; hscr%cw_mesh_type = "None"
726 :
727 764 : if (mod10 == SIG_GW_AC) then
728 32 : hscr%iw_mesh_type = "gauss_legendre"
729 732 : else if (any(mod10 == [SIG_QPGW_CD, SIG_QPGW_CD])) then
730 8 : hscr%rw_mesh_type = "linear"
731 8 : hscr%iw_mesh_type = "logarithmic"
732 : end if
733 764 : end subroutine set_defaults_from_gwcalctyp
734 :
735 : end subroutine hscr_io
736 : !!***
737 :
738 : !----------------------------------------------------------------------
739 :
740 : !!****f* m_io_screening/hscr_print
741 : !! NAME
742 : !! hscr_print
743 : !!
744 : !! FUNCTION
745 : !! Prints info on the header of the SCR|SUSC file.
746 : !!
747 : !! SOURCE
748 :
749 332 : subroutine hscr_print(Hscr, units, prtvol, header)
750 :
751 : !Arguments ------------------------------------
752 : !scalars
753 : class(hscr_t),intent(in) :: hscr
754 : integer,intent(in) :: units(:)
755 : integer,intent(in) :: prtvol
756 : character(len=*),intent(in),optional :: header
757 :
758 : !Local variables-------------------------------
759 : !scalars
760 : integer :: iomega,iq_ibz
761 : character(len=500) :: msg
762 : ! *************************************************************************
763 :
764 166 : if (PRESENT(header)) then
765 11 : msg = ' ==== '//TRIM(ADJUSTL(header))//' ==== '
766 11 : call wrtout(units, msg)
767 : end if
768 :
769 166 : write(msg,'(1x,a)')TRIM(hscr%titles(1))
770 166 : call wrtout(units,msg)
771 166 : write(msg,'(1x,a)')TRIM(hscr%titles(2))
772 166 : call wrtout(units,msg)
773 166 : write(msg,'(a,i8)') ' Identifier ',hscr%ID
774 166 : call wrtout(units,msg)
775 166 : write(msg,'(a,i8)') ' Kxc kernel ',hscr%ikxc
776 166 : call wrtout(units,msg)
777 166 : write(msg,'(a,i8)') ' Treatment of q-->0 limit ',hscr%inclvkb
778 166 : call wrtout(units,msg)
779 166 : write(msg,'(a,i8)') '- headform ',hscr%headform
780 166 : call wrtout(units,msg)
781 166 : write(msg,'(a,i8)') ' fform ',hscr%fform
782 166 : call wrtout(units,msg)
783 166 : write(msg,'(a,i8)') ' gwcalctyp ',hscr%gwcalctyp
784 166 : call wrtout(units,msg)
785 166 : write(msg,'(a,2i8)')' Number of components ',hscr%nI,hscr%nJ
786 166 : call wrtout(units,msg)
787 166 : write(msg,'(a,i8)') ' Number of q-points ',hscr%nqibz
788 166 : call wrtout(units,msg)
789 166 : write(msg,'(a,i8)') ' Number of q-directions ',hscr%nqlwl
790 166 : call wrtout(units,msg)
791 166 : write(msg,'(a,i8)') ' Number of frequencies ',hscr%nomega
792 166 : call wrtout(units,msg)
793 166 : write(msg,'(a,i8)') ' Number of bands used ',hscr%nbnds_used
794 166 : call wrtout(units,msg)
795 166 : write(msg,'(a,i8)') ' Dimension of matrix ',hscr%npwe
796 166 : call wrtout(units,msg)
797 166 : write(msg,'(a,i8)') ' Number of planewaves used ',hscr%npwwfn_used
798 166 : call wrtout(units,msg)
799 166 : write(msg,'(a,i8)') ' Spectral method ',hscr%spmeth
800 166 : call wrtout(units,msg)
801 166 : write(msg,'(a,i8)') ' Test_type ',hscr%test_type
802 166 : call wrtout(units,msg)
803 166 : write(msg,'(a,i8)') ' Time-ordering ',hscr%tordering
804 166 : call wrtout(units,msg)
805 166 : write(msg,'(a,es16.6)')' Scissor Energy ',hscr%mbpt_sciss
806 166 : call wrtout(units,msg)
807 166 : write(msg,'(a,es16.6)')' Spectral smearing ',hscr%spsmear
808 166 : call wrtout(units,msg)
809 166 : write(msg,'(a,es16.6)')' Complex Imaginary Shift ',hscr%zcut
810 166 : call wrtout(units,msg)
811 166 : write(msg,'(2a)') ' rw_mesh_type ',trim(hscr%rw_mesh_type)
812 166 : call wrtout(units,msg)
813 166 : write(msg,'(2a)') ' iw_mesh_type ',trim(hscr%iw_mesh_type)
814 166 : call wrtout(units,msg)
815 166 : write(msg,'(2a)') ' cw_mesh_type ',trim(hscr%cw_mesh_type)
816 166 : call wrtout(units,msg)
817 :
818 166 : if (prtvol == 0) then
819 142 : call wrtout(units,' The header contains additional records.')
820 : else
821 24 : write(msg,'(2a)')ch10,' q-points [r.l.u.]:'
822 24 : call wrtout(units,msg)
823 148 : do iq_ibz=1,hscr%nqibz
824 124 : write(msg,'(i5,3f12.6)')iq_ibz,hscr%qibz(:,iq_ibz)
825 148 : call wrtout(units,msg)
826 : end do
827 :
828 24 : write(msg,'(2a)')ch10,' Frequencies used [eV]:'
829 24 : call wrtout(units,msg)
830 248 : do iomega=1,hscr%nomega
831 224 : write(msg,'(i3,2f7.2)')iomega,REAL(hscr%omega(iomega))*Ha_eV,AIMAG(hscr%omega(iomega))*Ha_eV
832 248 : call wrtout(units,msg)
833 : end do
834 : end if
835 :
836 : ! Echo the abinit header.
837 : !if (prtvol>0) call hdr_echo(hscr%hdr,fform,rdwr,unit=unt)
838 :
839 166 : end subroutine hscr_print
840 : !!***
841 :
842 : !----------------------------------------------------------------------
843 :
844 : !!****f* m_io_screening/hscr_new
845 : !! NAME
846 : !! hscr_new
847 : !!
848 : !! FUNCTION
849 : !! Initialize the Hscr datatype and most of its content from the em1params_t data type Ep.
850 : !!
851 : !! INPUTS
852 : !! varname=Name of the netcdf variable (used to get fform and ID).
853 : !! ikxc=Integer flag defining the type of XC kernel (0 if None i.e RPA)
854 : !! test_type=Integer flag defining the type of probing charge (0 for None)
855 : !! tordering=The time-ordering of the Response function.
856 : !! gvec(3,Ep%npwe)=The G-vectors used.
857 : !! Ep<em1params_t>=Parameters defining the calculation of the screening.
858 : !! hdr_abinit<hdr_type>=The abinit header.
859 : !!
860 : !! OUTPUT
861 : !! Hscr<type(hscr_t)>=the header, initialized.
862 : !!
863 : !! SOURCE
864 :
865 256 : type(hscr_t) function hscr_new(varname, dtset, ep, hdr_abinit, ikxc, test_type, tordering, titles, ngvec, gvec) result(hscr)
866 :
867 : !Arguments ------------------------------------
868 : !scalars
869 : integer,intent(in) :: ikxc,test_type,tordering,ngvec
870 : character(len=*),intent(in) :: varname
871 : type(dataset_type),intent(in) :: dtset
872 : type(em1params_t),intent(in) :: Ep
873 : type(hdr_type),intent(in) :: hdr_abinit
874 : !arrays
875 : integer,intent(in) :: gvec(3,ngvec)
876 : character(len=80),intent(in) :: titles(2)
877 :
878 : !Local variables-------------------------------
879 : integer :: id
880 : type(abifile_t) :: abifile
881 : ! *************************************************************************
882 :
883 : !@hscr_t
884 0 : ABI_CHECK(ngvec == Ep%npwe, 'ngvec/=Ep%npwe')
885 :
886 : ! Identifier used to define the type of response function (e^-1, chi0)
887 128 : id = 0
888 128 : if (varname == "polarizability") id = 1
889 128 : if (varname == "inverse_dielectric_function") id = 4
890 8 : ABI_CHECK(id /= 0, sjoin("Invalid varname: ",varname))
891 :
892 : ! Get fform from abifile.
893 128 : abifile = abifile_from_varname(varname)
894 128 : if (abifile%fform == 0) then
895 0 : ABI_ERROR(sjoin("Cannot find any abifile object associated to varname:", varname))
896 : end if
897 :
898 : ! Copy the abinit header.
899 128 : call hdr_abinit%copy(Hscr%Hdr)
900 :
901 : ! Initialize quantities related to the screening file
902 128 : hscr%id =id
903 128 : hscr%ikxc =ikxc
904 128 : hscr%inclvkb =Ep%inclvkb
905 128 : hscr%headform =HSCR_LATEST_HEADFORM
906 128 : hscr%fform =abifile%fform
907 128 : hscr%gwcalctyp =Ep%gwcalctyp
908 128 : hscr%nI =Ep%nI
909 128 : hscr%nJ =Ep%nJ
910 128 : hscr%nqibz =Ep%nqcalc ! nqcalc == nqibz except if we split the calculation with nqptdm
911 128 : hscr%nqlwl =Ep%nqlwl
912 128 : hscr%nomega =Ep%nomega
913 128 : hscr%nbnds_used =Ep%nbnds
914 128 : hscr%npwe =Ep%npwe
915 128 : hscr%npwwfn_used=Ep%npwwfn
916 128 : hscr%spmeth =Ep%spmeth
917 128 : hscr%test_type =test_type
918 128 : hscr%tordering =tordering
919 128 : hscr%mbpt_sciss =Ep%mbpt_sciss
920 128 : hscr%spsmear =Ep%spsmear
921 128 : hscr%zcut =Ep%zcut
922 :
923 384 : hscr%titles(:)=titles(:)
924 :
925 128 : call hscr_malloc(hscr, hscr%npwe, hscr%nqibz, hscr%nomega, hscr%nqlwl)
926 29808 : hscr%gvec(:,:) = gvec(:,1:Ep%npwe)
927 3156 : hscr%qibz(:,:) = Ep%qcalc
928 640 : hscr%qlwl(:,:) = Ep%qlwl
929 995 : hscr%omega(:) = Ep%omega
930 :
931 995 : hscr%omega_wgs(:) = Ep%omega_wgs
932 128 : hscr%iw_mesh_type = Ep%iw_mesh_type
933 128 : hscr%rw_mesh_type = Ep%rw_mesh_type
934 128 : hscr%cw_mesh_type = Ep%cw_mesh_type
935 :
936 : ! HSCR_NEW
937 128 : hscr%awtr = dtset%awtr
938 128 : hscr%icutcoul = dtset%gw_icutcoul
939 512 : hscr%vcutgeo = dtset%vcutgeo
940 128 : hscr%gwcomp = dtset%gwcomp
941 128 : hscr%gwgamma = dtset%gwgamma
942 128 : hscr%gwencomp = dtset%gwencomp
943 128 : hscr%kind_cdata = "dpc" ! For the time being, data is always written in double-precision
944 : ! HSCR_NEW
945 :
946 512 : end function hscr_new
947 : !!***
948 :
949 : !----------------------------------------------------------------------
950 :
951 : !!****f* m_io_screening/hscr_bcast
952 : !! NAME
953 : !! hscr_bcast
954 : !!
955 : !! FUNCTION
956 : !! This subroutine transmit the header structured datatype initialized
957 : !! on one processor (or a group of processor), to the other processors.
958 : !! It also allocates the needed part of the header.
959 : !!
960 : !! INPUTS
961 : !! master=ID of the master node.
962 : !! my_rank=ID of the node that receives the data.
963 : !! comm=MPI communicator.
964 : !!
965 : !! OUTPUT
966 : !! (no output)
967 : !!
968 : !! SIDE EFFECTS
969 : !! Hscr<type(hscr_t)>=the SCR header. For the master, it is already
970 : !! initialized entirely, while for the other procs, everything has
971 : !! to be transmitted.
972 : !!
973 : !! SOURCE
974 :
975 1487 : subroutine hscr_bcast(hscr, master, my_rank, comm)
976 :
977 : !Arguments ------------------------------------
978 : class(hscr_t),intent(inout) :: hscr
979 : integer, intent(in) :: master, my_rank, comm
980 :
981 : !Local variables-------------------------------
982 : integer :: ierr
983 : ! *************************************************************************
984 :
985 : DBG_ENTER("COLL")
986 59 : if (xmpi_comm_size(comm) == 1) return ! Nothing to do
987 :
988 : ! integer
989 42 : call xmpi_bcast(hscr%id, master,comm,ierr)
990 42 : call xmpi_bcast(hscr%ikxc, master,comm,ierr)
991 42 : call xmpi_bcast(hscr%inclvkb, master,comm,ierr)
992 42 : call xmpi_bcast(hscr%headform, master,comm,ierr)
993 42 : call xmpi_bcast(hscr%fform, master,comm,ierr)
994 42 : call xmpi_bcast(hscr%gwcalctyp, master,comm,ierr)
995 42 : call xmpi_bcast(hscr%nI, master,comm,ierr)
996 42 : call xmpi_bcast(hscr%nJ, master,comm,ierr)
997 42 : call xmpi_bcast(hscr%nqibz, master,comm,ierr)
998 42 : call xmpi_bcast(hscr%nqlwl, master,comm,ierr)
999 42 : call xmpi_bcast(hscr%nomega, master,comm,ierr)
1000 42 : call xmpi_bcast(hscr%nbnds_used, master,comm,ierr)
1001 42 : call xmpi_bcast(hscr%npwe, master,comm,ierr)
1002 42 : call xmpi_bcast(hscr%npwwfn_used,master,comm,ierr)
1003 42 : call xmpi_bcast(hscr%spmeth, master,comm,ierr)
1004 42 : call xmpi_bcast(hscr%test_type, master,comm,ierr)
1005 42 : call xmpi_bcast(hscr%tordering, master,comm,ierr)
1006 :
1007 : ! Real
1008 42 : call xmpi_bcast(hscr%mbpt_sciss, master,comm,ierr)
1009 42 : call xmpi_bcast(hscr%spsmear, master,comm,ierr)
1010 42 : call xmpi_bcast(hscr%zcut, master,comm,ierr)
1011 :
1012 : ! arrays
1013 42 : call xmpi_bcast(hscr%titles, master,comm,ierr)
1014 :
1015 42 : if (my_rank /= master) call hscr_malloc(hscr, hscr%npwe, hscr%nqibz, hscr%nomega, hscr%nqlwl)
1016 :
1017 42 : call xmpi_bcast(hscr%gvec, master,comm,ierr)
1018 42 : call xmpi_bcast(hscr%qibz, master,comm,ierr)
1019 42 : call xmpi_bcast(hscr%qlwl, master,comm,ierr)
1020 42 : call xmpi_bcast(hscr%omega,master,comm,ierr)
1021 :
1022 : ! Communicate the Abinit header.
1023 42 : call hscr%Hdr%bcast(master, my_rank, comm)
1024 :
1025 : ! HSCR_NEW
1026 42 : call xmpi_bcast(hscr%awtr, master, comm, ierr)
1027 42 : call xmpi_bcast(hscr%icutcoul, master, comm, ierr)
1028 42 : call xmpi_bcast(hscr%vcutgeo, master, comm, ierr)
1029 42 : call xmpi_bcast(hscr%gwcomp, master, comm, ierr)
1030 42 : call xmpi_bcast(hscr%gwgamma, master, comm, ierr)
1031 42 : call xmpi_bcast(hscr%gwencomp, master, comm, ierr)
1032 42 : call xmpi_bcast(hscr%kind_cdata, master, comm, ierr)
1033 : ! HSCR_NEW
1034 :
1035 42 : call xmpi_bcast(hscr%omega_wgs, master, comm, ierr)
1036 42 : call xmpi_bcast(hscr%iw_mesh_type, master, comm, ierr)
1037 42 : call xmpi_bcast(hscr%rw_mesh_type, master, comm, ierr)
1038 42 : call xmpi_bcast(hscr%cw_mesh_type, master, comm, ierr)
1039 :
1040 : DBG_EXIT("COLL")
1041 :
1042 : end subroutine hscr_bcast
1043 : !!***
1044 :
1045 : !----------------------------------------------------------------------
1046 :
1047 : !!****f* m_io_screening/hscr_malloc
1048 : !! NAME
1049 : !! hscr_malloc
1050 : !!
1051 : !! FUNCTION
1052 : !! Allocate the components of the header structured datatype except for hscr%hdr
1053 : !!
1054 : !! SOURCE
1055 :
1056 920 : subroutine hscr_malloc(hscr, npwe, nqibz, nomega, nqlwl)
1057 :
1058 : !Arguments ------------------------------------
1059 : !scalars
1060 : class(hscr_t),intent(inout) :: Hscr
1061 : integer,intent(in) :: npwe, nqibz, nomega, nqlwl
1062 : ! *************************************************************************
1063 :
1064 : !@hscr_t
1065 2760 : ABI_MALLOC(hscr%gvec, (3, npwe))
1066 2760 : ABI_MALLOC(hscr%qibz, (3, nqibz))
1067 2760 : ABI_MALLOC(hscr%qlwl, (3, nqlwl))
1068 2760 : ABI_MALLOC(hscr%omega, (nomega))
1069 7478 : ABI_CALLOC(hscr%omega_wgs, (nomega))
1070 :
1071 920 : end subroutine hscr_malloc
1072 : !!***
1073 :
1074 : !----------------------------------------------------------------------
1075 :
1076 : !!****f* m_io_screening/hscr_free
1077 : !! NAME
1078 : !! hscr_free
1079 : !!
1080 : !! FUNCTION
1081 : !! Deallocate the components of the header structured datatype
1082 : !!
1083 : !! SOURCE
1084 :
1085 965 : subroutine hscr_free(hscr)
1086 :
1087 : !Arguments ------------------------------------
1088 : class(hscr_t),intent(inout) :: hscr
1089 : ! *************************************************************************
1090 :
1091 965 : ABI_SFREE(hscr%gvec)
1092 965 : ABI_SFREE(hscr%qibz)
1093 965 : ABI_SFREE(hscr%qlwl)
1094 965 : ABI_SFREE(hscr%omega)
1095 965 : ABI_SFREE(hscr%omega_wgs)
1096 :
1097 965 : call hscr%Hdr%free()
1098 :
1099 965 : end subroutine hscr_free
1100 : !!***
1101 :
1102 : !----------------------------------------------------------------------
1103 :
1104 : !!****f* m_io_screening/hscr_copy
1105 : !! NAME
1106 : !! hscr_copy
1107 : !!
1108 : !! FUNCTION
1109 : !! Deep copy of the header of the _SCR or _SUSC file.
1110 : !!
1111 : !! INPUTS
1112 : !!
1113 : !! SOURCE
1114 :
1115 9 : subroutine hscr_copy(Hscr_in, Hscr_cp)
1116 :
1117 : !Arguments ------------------------------------
1118 : !scalars
1119 : class(hscr_t),intent(in) :: Hscr_in
1120 : class(hscr_t),intent(inout) :: Hscr_cp
1121 : ! *************************************************************************
1122 :
1123 : !@hscr_t
1124 : ! Integer values.
1125 9 : Hscr_cp%id = Hscr_in%id
1126 9 : Hscr_cp%ikxc = Hscr_in%ikxc
1127 9 : Hscr_cp%inclvkb = Hscr_in%inclvkb
1128 9 : Hscr_cp%headform = Hscr_in%headform
1129 9 : Hscr_cp%fform = Hscr_in%fform
1130 9 : Hscr_cp%gwcalctyp = Hscr_in%gwcalctyp
1131 9 : Hscr_cp%nI = Hscr_in%nI
1132 9 : Hscr_cp%nJ = Hscr_in%nJ
1133 9 : Hscr_cp%nqibz = Hscr_in%nqibz
1134 9 : Hscr_cp%nqlwl = Hscr_in%nqlwl
1135 9 : Hscr_cp%nomega = Hscr_in%nomega
1136 9 : Hscr_cp%nbnds_used = Hscr_in%nbnds_used
1137 9 : Hscr_cp%npwe = Hscr_in%npwe
1138 9 : Hscr_cp%npwwfn_used = Hscr_in%npwwfn_used
1139 9 : Hscr_cp%spmeth = Hscr_in%spmeth
1140 9 : Hscr_cp%test_type = Hscr_in%test_type
1141 9 : Hscr_cp%tordering = Hscr_in%tordering
1142 :
1143 : ! Real variables
1144 9 : Hscr_cp%mbpt_sciss = Hscr_in%mbpt_sciss
1145 9 : Hscr_cp%spsmear = Hscr_in%spsmear
1146 9 : Hscr_cp%zcut = Hscr_in%zcut
1147 :
1148 : ! Copy the abinit Header
1149 9 : call Hscr_in%Hdr%copy(Hscr_cp%Hdr)
1150 :
1151 27 : Hscr_cp%titles(:) = Hscr_in%titles(:)
1152 :
1153 : ! Copy allocatable arrays.
1154 9 : call alloc_copy(Hscr_in%gvec , Hscr_cp%gvec)
1155 9 : call alloc_copy(Hscr_in%qibz , Hscr_cp%qibz)
1156 9 : call alloc_copy(Hscr_in%qlwl , Hscr_cp%qlwl)
1157 9 : call alloc_copy(Hscr_in%omega, Hscr_cp%omega)
1158 9 : call alloc_copy(Hscr_in%omega_wgs, Hscr_cp%omega_wgs)
1159 :
1160 : ! HSCR_NEW
1161 9 : hscr_cp%awtr = hscr_in%awtr
1162 9 : hscr_cp%icutcoul = hscr_in%icutcoul
1163 36 : hscr_cp%vcutgeo = hscr_in%vcutgeo
1164 9 : hscr_cp%gwcomp = hscr_in%gwcomp
1165 9 : hscr_cp%gwgamma = hscr_in%gwgamma
1166 9 : hscr_cp%gwencomp = hscr_in%gwencomp
1167 9 : hscr_cp%kind_cdata = hscr_in%kind_cdata
1168 :
1169 9 : hscr_cp%iw_mesh_type = hscr_in%iw_mesh_type
1170 9 : hscr_cp%rw_mesh_type = hscr_in%rw_mesh_type
1171 9 : hscr_cp%cw_mesh_type = hscr_in%cw_mesh_type
1172 : ! HSCR_NEW
1173 :
1174 9 : end subroutine hscr_copy
1175 : !!***
1176 :
1177 : !----------------------------------------------------------------------
1178 :
1179 : !!****f* m_io_screening/hscr_merge
1180 : !! NAME
1181 : !! hscr_merge
1182 : !!
1183 : !! FUNCTION
1184 : !! This subroutine merges different header structured variable (hscr_t)
1185 : !!
1186 : !! INPUTS
1187 : !! Hscr_in(:) <hscr_t)>=List of headers to be merged.
1188 : !!
1189 : !! OUTPUT
1190 : !! Hscr_out<hscr_t>=The output merged header.
1191 : !!
1192 : !! SOURCE
1193 :
1194 18 : subroutine hscr_merge(Hscr_in, Hscr_out)
1195 :
1196 : !Arguments ------------------------------------
1197 : !scalars
1198 : type(hscr_t),intent(in) :: Hscr_in(:)
1199 : type(hscr_t),intent(out) :: Hscr_out
1200 :
1201 : !Local variables-------------------------------
1202 : !scalars
1203 : integer :: nhds,restart,restartpaw,ihd,ii,nqtot,nqneq
1204 : logical :: isok
1205 : character(len=500) :: msg
1206 : !arrays
1207 3 : real(dp),allocatable :: qset(:,:)
1208 : ! *************************************************************************
1209 :
1210 : ! TODO: This should be called hscr_merge_qpoints
1211 :
1212 : !@hscr_t
1213 3 : nhds=SIZE(Hscr_in)
1214 :
1215 : ! Initial copy of the header ===
1216 : ! If multiple headers, select the header containing q-->0 so that we copy also heads and wings
1217 11 : ii = imax_loc(Hscr_in(:)%nqlwl)
1218 3 : call Hscr_in(ii)%copy(Hscr_out)
1219 3 : if (nhds==1) return
1220 :
1221 : ! Check consistency of the abinit Headers.
1222 : ! FFT grid might be q-point dependent so we stop only when restart==0
1223 3 : isok=.TRUE.
1224 8 : do ihd=2,nhds
1225 5 : call hdr_check(Hscr_in(1)%fform,Hscr_in(ihd)%fform,Hscr_in(1)%Hdr,Hscr_in(ihd)%Hdr,'COLL',restart,restartpaw)
1226 8 : if (restart==0) then
1227 0 : isok=.FALSE.
1228 0 : write(msg,'(a,i0,a)')' Abinit header no.',ihd,' is not consistent with the first header '
1229 0 : ABI_WARNING(msg)
1230 : end if
1231 : end do
1232 3 : if (.not.isok) then
1233 0 : ABI_ERROR('Cannot continue, Check headers')
1234 : end if
1235 :
1236 : ! Now check variables related to polarizability|epsilon^{-1}.
1237 : ! 1) Tests quantities that must be equal
1238 11 : ii = assert_eq(Hscr_in(:)%ID, 'Headers have different Identifiers')
1239 11 : ii = assert_eq(Hscr_in(:)%ikxc, 'Headers have different ikxc' )
1240 11 : ii = assert_eq(Hscr_in(:)%headform, 'Headers have different headform' )
1241 11 : ii = assert_eq(Hscr_in(:)%fform, 'Headers have different fform' )
1242 11 : ii = assert_eq(Hscr_in(:)%gwcalctyp,'Headers have different gwcalctyp' )
1243 11 : ii = assert_eq(Hscr_in(:)%nI, 'Headers have different nI' )
1244 11 : ii = assert_eq(Hscr_in(:)%nJ, 'Headers have different nJ' )
1245 11 : ii = assert_eq(Hscr_in(:)%nomega, 'Headers have different nomega' )
1246 11 : ii = assert_eq(Hscr_in(:)%test_type,'Headers have different test_type' )
1247 11 : ii = assert_eq(Hscr_in(:)%tordering,'Headers have different tordering' )
1248 :
1249 : ! This is not mandatory but makes life easier!
1250 11 : ii = assert_eq(Hscr_in(:)%npwe,'Headers have different number of G-vectors' )
1251 :
1252 8 : do ihd=2,nhds
1253 15 : if (ANY(ABS(Hscr_in(ihd)%omega-Hscr_in(1)%omega)>tol6)) then
1254 0 : write(msg,'(a,i0,a)')' Frequencies in the first and the ',ihd,'-th header differ'
1255 0 : ABI_ERROR(msg)
1256 : end if
1257 545 : if (ANY(Hscr_in(ihd)%gvec(:,:)-Hscr_in(1)%gvec(:,:)/=0)) then
1258 0 : write(msg,'(a,i0,a)')' Incompatible G-vector list found in the ',ihd,'-th header'
1259 0 : ABI_ERROR(msg)
1260 : end if
1261 8 : if (hscr_in(ihd)%kind_cdata /= hscr_in(1)%kind_cdata) then
1262 0 : write(msg,'(3a,i0,2a)')' Files contain data with different precisions.',ch10,&
1263 0 : "In particular the ",ihd,'-th header has precision:',trim(hscr_in(ihd)%kind_cdata)
1264 0 : ABI_ERROR(msg)
1265 : end if
1266 : end do !ihd
1267 :
1268 : ! If error is not fatal, just warn ===
1269 11 : if (ANY(Hscr_in(:)%npwwfn_used/=Hscr_in(1)%npwwfn_used)) then
1270 0 : ABI_COMMENT('Files have been produced with a different number of planewaves for the wavefunctions.')
1271 : end if
1272 11 : if (ANY(Hscr_in(:)%nbnds_used/=Hscr_in(1)%nbnds_used)) then
1273 0 : ABI_COMMENT('Files have been produced with a different number of bands.')
1274 : end if
1275 11 : if (ANY(Hscr_in(:)%spmeth/=Hscr_in(1)%spmeth)) then
1276 0 : ABI_COMMENT('Files have been produced with different algorithms.')
1277 : end if
1278 11 : if (ANY(ABS(Hscr_in(:)%mbpt_sciss-Hscr_in(1)%mbpt_sciss)>tol6)) then
1279 0 : ABI_COMMENT('Files have benn produced with different values of mbpt_sciss.')
1280 : end if
1281 11 : if (ANY(ABS(Hscr_in(:)%spsmear-Hscr_in(1)%spsmear)>tol6)) then
1282 0 : ABI_COMMENT('Files have been produced with different values of spsmear.')
1283 : end if
1284 11 : if (ANY(ABS(Hscr_in(:)%zcut-Hscr_in(1)%zcut)>tol6)) then
1285 0 : ABI_COMMENT('Files have been produced with different values of zcut.')
1286 : end if
1287 :
1288 : ! Now merge the list of q-points.
1289 : ! Take the union of the q-points, remove possible duplicated
1290 : ! are change the parameters in hscr_out that depends on q-points.
1291 11 : nqtot=SUM(Hscr_in(:)%nqibz)
1292 9 : ABI_MALLOC(qset,(3,nqtot))
1293 :
1294 3 : ii=0
1295 11 : do ihd=1,nhds
1296 92 : qset(:,ii+1:ii+Hscr_in(ihd)%nqibz)=Hscr_in(ihd)%qibz(:,:)
1297 11 : ii=ii+Hscr_in(ihd)%nqibz
1298 : end do
1299 :
1300 3 : call remove_copies(nqtot,qset,nqneq,isequalk)
1301 :
1302 3 : if (nqneq /= nqtot) then
1303 : write(msg,'(3a,2(i0,a))')&
1304 1 : 'COMMENT: Headers contain duplicated q-points ',ch10,&
1305 2 : 'Found ',nqneq,' distinct q-points among the total ',nqtot,' points reported in the headers. '
1306 1 : call wrtout(std_out, msg)
1307 : end if
1308 :
1309 3 : Hscr_out%nqibz = nqneq
1310 3 : ABI_FREE(Hscr_out%qibz)
1311 9 : ABI_MALLOC(Hscr_out%qibz,(3,nqneq))
1312 75 : Hscr_out%qibz(:,:)=qset(:,1:nqneq)
1313 3 : ABI_FREE(qset)
1314 :
1315 3 : end subroutine hscr_merge
1316 : !!***
1317 :
1318 : !----------------------------------------------------------------------
1319 :
1320 : !!****f* m_io_screening/write_screening
1321 : !! NAME
1322 : !! write_screening
1323 : !!
1324 : !! FUNCTION
1325 : !! For a single q-point, write either \tilde epsilon^{-1} on the _SCR file
1326 : !! or chi0 on the _SUSC file. The file is supposed to have been open in the calling routine.
1327 : !!
1328 : !! INPUTS
1329 : !! varname=The name of the array to write (used if etsf-io format).
1330 : !! unt=The unit number of the file to be written (supposed to be already open)
1331 : !! iomode=Integer flag defining the format of the output file. Available options:
1332 : !! IO_MODE_FORTRAN--> Plain Fortran file
1333 : !! IO_MODE_ETSF--> ETSF format
1334 : !! npwe=Number of plane waves in epsm1.
1335 : !! nomega=Number of frequencies
1336 : !! iq_ibz=Index of the q-points in the IBZ.
1337 : !! epsm1(npwe,npwe,nomega)=The matrix to be written, for different frequencies, and a single q-point.
1338 : !!
1339 : !! NOTES
1340 : !! On some architecture, the code crashes when trying to write or read a record containing the
1341 : !! entire (G1,G2) matrix thus we use smaller records containing the columns of the two-point function.
1342 : !!
1343 : !! OUTPUT
1344 : !! (only writing on file)
1345 : !!
1346 : !! SOURCE
1347 :
1348 812 : subroutine write_screening(varname, unt, iomode, npwe, nomega, iq_ibz, epsm1)
1349 :
1350 : !Arguments ------------------------------------
1351 : !scalars
1352 : character(len=*),intent(in) :: varname
1353 : integer,intent(in) :: nomega,npwe,iq_ibz,unt,iomode
1354 : !arrays
1355 : complex(gwp),target,intent(in) :: epsm1(npwe,npwe,nomega)
1356 :
1357 : !Local variables-------------------------------
1358 : !scalars
1359 : integer :: ipwe,iomega,spins(2),s1,s2
1360 : character(len=500) :: errmsg
1361 : !arrays
1362 812 : complex(dp),allocatable :: epsm1d(:,:)
1363 : integer :: varid,ncerr
1364 : #ifdef HAVE_GW_DPC
1365 812 : real(dp), contiguous, pointer :: real_epsm1(:,:,:,:,:,:,:)
1366 : #else
1367 : real(sp), contiguous, pointer :: real_epsm1(:,:,:,:,:,:,:)
1368 : #endif
1369 : ! *************************************************************************
1370 :
1371 : DBG_ENTER("COLL")
1372 :
1373 812 : select case (iomode)
1374 : case (IO_MODE_FORTRAN, IO_MODE_MPI)
1375 : ! Write a record for each omega, Always use double precision.
1376 0 : ABI_MALLOC(epsm1d,(npwe,1))
1377 :
1378 0 : do iomega=1,nomega
1379 0 : do ipwe=1,npwe
1380 0 : epsm1d(:,1) = epsm1(:,ipwe,iomega) !spc ==> dpc
1381 0 : write(unt, err=10, iomsg=errmsg)epsm1d(1:npwe,1)
1382 : end do
1383 : end do
1384 0 : ABI_FREE(epsm1d)
1385 :
1386 : case (IO_MODE_ETSF)
1387 : ! netcdf does not support complex datatypes. Here I use some C-magic to associate the memory
1388 : ! to a Fortran real pointer with the correct type and shape. Note that the data on file is always in double precision.
1389 : ! but this is ok since: if the type of data differs from the netCDF variable type, type conversion will occur
1390 : ! inside nf90_put_var
1391 812 : varid = nctk_idname(unt, varname)
1392 6496 : call c_f_pointer(c_loc(epsm1(1,1,1)), real_epsm1, [2, npwe, npwe, 1, 1, nomega, 1])
1393 : ! [cplex, npwe, npwe, nspin, nspin, nomega, nqpt]
1394 2436 : spins = 1; s1 = spins(1); s2 = spins(2)
1395 12180 : ncerr = nf90_put_var(unt, varid, real_epsm1, start=[1,1,1,s1,s2,1,iq_ibz], count=[2,npwe,npwe,1,1,nomega,1])
1396 812 : NCF_CHECK_MSG(ncerr, sjoin("putting var:", varname))
1397 :
1398 : case default
1399 0 : ABI_ERROR(sjoin("Wrong iomode:", iomode2str(iomode)))
1400 : end select
1401 :
1402 : DBG_EXIT("COLL")
1403 :
1404 : return
1405 :
1406 : ! Handle IO error
1407 : 10 continue
1408 0 : ABI_ERROR(errmsg)
1409 :
1410 812 : end subroutine write_screening
1411 : !!***
1412 :
1413 : !----------------------------------------------------------------------
1414 :
1415 : !!****f* m_io_screening/read_screening
1416 : !! NAME
1417 : !! read_screening
1418 : !!
1419 : !! FUNCTION
1420 : !! Read either a screening (\tilde epsilon^{-1}) file in the SCR format or
1421 : !! the irreducible polarizability (chi0) in the SUSC format.
1422 : !!
1423 : !! INPUTS
1424 : !! varname=Name of the array to read. Used for ETSF-IO files.
1425 : !! iomode=Integer flag defining the format of the output file. Available options:
1426 : !! IO_MODE_FORTRAN--> Plain Fortran file
1427 : !! IO_MODE_ETSF--> ETSF format
1428 : !! iqiA[optional]=Used if only a particular q-point is required. In this case iqiA define the index
1429 : !! of the required q-point in the array qibz(3,Hscr%nqibz)
1430 : !! nqibzA=number of asked q-points (used to dimension the output arrays).
1431 : !! Equal to Hscr%nqibz if the full matrix is required
1432 : !! comm=MPI communicator.
1433 : !! npweA=number of asked planewaves
1434 : !! nomegaA=number of asked frequencies
1435 : !!
1436 : !! OUTPUT
1437 : !! epsm1(npweA,npweA,nomegaA,nqibzA) = \tilde\epsilon^{-1}(Ng,Ng,Nw,Nq)
1438 : !!
1439 : !! NOTES
1440 : !! * If the epsilon matrix read is bigger than npweA x npweA, it will be truncated;
1441 : !! if it is smaller, an error will occur
1442 : !! * If the number of frequencies asked for is smaller than that reported in the file, the matrix
1443 : !! will be truncated. If nomegaA > Hscr%nomega an error will occur
1444 : !!
1445 : !! SOURCE
1446 :
1447 580 : subroutine read_screening(varname, fname, npweA, nqibzA, nomegaA, epsm1, iomode, comm, &
1448 : iqiA) ! Optional
1449 :
1450 : !Arguments ------------------------------------
1451 : !scalars
1452 : integer,intent(in) :: iomode,nomegaA,npweA,nqibzA,comm
1453 : integer,optional,intent(in) :: iqiA
1454 : character(len=*),intent(in) :: varname,fname
1455 : !arrays
1456 : complex(gwp),target,intent(inout) :: epsm1(npweA,npweA,nomegaA,nqibzA)
1457 :
1458 : !Local variables-------------------------------
1459 : !scalars
1460 : integer,parameter :: master = 0
1461 : integer :: ipwe,fform,iomega,iq_ibz,unt,rdwr,my_rank,nprocs,my_iomode, varid, ncerr
1462 : #ifdef HAVE_MPI_IO
1463 : integer :: test_fform,mpi_err,ierr,sc_mode, bsize_frm,mpi_type_frm
1464 : integer :: mpi_fh,buf_dim !,mat_ggw,mat_ggwq
1465 : integer(XMPI_OFFSET_KIND) :: offset,displ_wq !,my_offpad
1466 : !complex(dp) :: ctmp
1467 : #endif
1468 : real(dp) :: cpu, wall, gflops
1469 : character(len=500) :: msg,errmsg
1470 : logical :: read_qslice
1471 2320 : type(hscr_t) :: Hscr
1472 : !arrays
1473 : #ifdef HAVE_MPI_IO
1474 580 : integer(MPI_OFFSET_KIND),allocatable :: offset_wq(:,:)
1475 : #endif
1476 580 : complex(dp),allocatable :: bufdc2d(:,:),bufdc3d(:,:,:)
1477 : ! pointers passed to netcdf4 routines (complex datatypes are not supported).
1478 : #ifdef HAVE_GW_DPC
1479 580 : real(dp), contiguous, pointer :: real_epsm1(:,:,:,:,:,:,:)
1480 : #else
1481 : real(sp), contiguous, pointer :: real_epsm1(:,:,:,:,:,:,:)
1482 : #endif
1483 : integer :: spins(2),s1,s2
1484 : ! *************************************************************************
1485 :
1486 : DBG_ENTER("COLL")
1487 580 : call cwtime(cpu, wall, gflops, "start")
1488 :
1489 580 : my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
1490 580 : my_iomode = iomode
1491 580 : if (endswith(fname, ".nc")) my_iomode = IO_MODE_ETSF
1492 : !my_iomode = IO_MODE_MPI
1493 : !if (my_iomode == IO_MODE_MPI) my_iomode = IO_MODE_FORTRAN
1494 :
1495 580 : rdwr=1
1496 0 : select case (my_iomode)
1497 : case (IO_MODE_MPI)
1498 : #ifdef HAVE_MPI_IO
1499 0 : bsize_frm = xmpio_bsize_frm ! bsize_frm= Byte length of the Fortran record marker.
1500 0 : mpi_type_frm = xmpio_mpi_type_frm ! MPI type of the record marker.
1501 0 : sc_mode = xmpio_collective
1502 :
1503 : ! Master reads the header via Fortran IO then bcast the data.
1504 0 : call hscr%from_file(fname, fform, comm)
1505 :
1506 : ! Open the file with MPI-IO
1507 0 : call MPI_FILE_OPEN(comm, fname, MPI_MODE_RDONLY, xmpio_info ,mpi_fh, mpi_err)
1508 0 : ABI_CHECK_MPI(mpi_err, sjoin("MPI_FILE_OPEN:", fname))
1509 :
1510 : ! Retrieve the offset of the section immediately below the header.
1511 0 : call hscr_mpio_skip(mpi_fh, test_fform, offset)
1512 0 : ABI_CHECK(test_fform == fform, "mismatch in fform!")
1513 :
1514 : ! Offsets of the Fortran markers corresponding to the (w,q) slices.
1515 0 : ABI_MALLOC(offset_wq,(HScr%nomega,HScr%nqibz))
1516 0 : displ_wq = offset
1517 0 : do iq_ibz=1,Hscr%nqibz
1518 0 : do iomega=1,Hscr%nomega
1519 0 : ABI_CHECK(displ_wq > 0, "displ_wq < 0, your SCR|SUSC file is too big for MPI-IO!")
1520 0 : offset_wq(iomega,iq_ibz) = displ_wq
1521 0 : displ_wq = displ_wq + Hscr%npwe**2 * xmpi_bsize_dpc + Hscr%npwe * 2 * bsize_frm
1522 : end do
1523 : end do
1524 : #else
1525 : ABI_ERROR("MPI-IO support not enabled at configure-time")
1526 : #endif
1527 :
1528 : case (IO_MODE_FORTRAN)
1529 : ! Plain Fortran IO, all nodes read.
1530 0 : if (open_file(fname,msg,newunit=unt,form="unformatted",status="old",action="read") /= 0) then
1531 0 : ABI_ERROR(msg)
1532 : end if
1533 0 : call hscr%io(fform, rdwr, unt, comm, master, my_iomode)
1534 :
1535 : case (IO_MODE_ETSF)
1536 580 : NCF_CHECK(nctk_open_read(unt, fname, xmpi_comm_self))
1537 580 : call hscr%io(fform, rdwr, unt, comm, master, my_iomode)
1538 :
1539 : case default
1540 580 : ABI_ERROR(sjoin("Wrong iomode:", iomode2str(my_iomode)))
1541 : end select
1542 :
1543 : ! Slice or full array?
1544 580 : read_qslice = .False.
1545 580 : if (PRESENT(iqiA)) then
1546 451 : read_qslice = .True.
1547 : !call wrtout(std_out, sjoin('. Reading q-slice for iq = ',itoa(iqiA),' from: ', fname))
1548 451 : if (iqiA <= 0 .or. iqiA > Hscr%nqibz) then
1549 0 : ABI_BUG('iqiA out of range')
1550 : end if
1551 : end if
1552 :
1553 : ! Do some check
1554 580 : if (Hscr%npwe>npweA) then
1555 : write(msg,'(a,i0,2a,i0)')&
1556 65 : 'Total number of G-vectors reported on file = ',Hscr%npwe,ch10,&
1557 130 : 'Reading a smaller matrix of dimension = ',npweA
1558 65 : ABI_COMMENT(msg)
1559 : end if
1560 :
1561 580 : if (npweA > Hscr%npwe) then
1562 0 : write(msg,'(2(a,i0))')' Dimension of matrix = ',Hscr%npwe," requiring a too big matrix = ",npweA
1563 0 : ABI_ERROR(msg)
1564 : end if
1565 :
1566 580 : ABI_CHECK(nqibzA <= Hscr%nqibz, 'Requiring too many q-points')
1567 580 : ABI_CHECK(nomegaA <= Hscr%nomega,'Requiring too many frequencies')
1568 :
1569 0 : select case (my_iomode)
1570 : case (IO_MODE_MPI)
1571 : #ifdef HAVE_MPI_IO
1572 0 : if (read_qslice) then
1573 : !call wrtout(std_out, "calling mpiotk to read_qslice")
1574 0 : buf_dim = (npweA)**2 * nomegaA
1575 0 : offset = offset_wq(1,iqiA)
1576 0 : sc_mode = xmpio_collective
1577 :
1578 : #ifdef HAVE_GW_DPC
1579 : ! Read in-place.
1580 : call mpiotk_read_fsuba_dpc3D(mpi_fh,offset, [HScr%npwe,HScr%npwe,HScr%nomega], [npweA,npweA,nomegaA], [1,1,1],&
1581 0 : buf_dim,epsm1,xmpio_chunk_bsize,sc_mode,comm,ierr)
1582 0 : ABI_CHECK(ierr==0,"Fortran matrix too big")
1583 : #else
1584 : ! Have to allocate workspace for dp data.
1585 : ! FIXME: Change the file format of the SCR and SUC file so that
1586 : ! they are written in single precision if not HAVE_GW_DPC
1587 : ABI_MALLOC_OR_DIE(bufdc3d, (npweA,npweA,nomegaA), ierr)
1588 :
1589 : call mpiotk_read_fsuba_dpc3D(mpi_fh,offset, [HScr%npwe,HScr%npwe,HScr%nomega], [npweA,npweA,nomegaA], [1,1,1],&
1590 : buf_dim,bufdc3d,xmpio_chunk_bsize,sc_mode,comm,ierr)
1591 : ABI_CHECK(ierr == 0,"Fortran matrix too big")
1592 :
1593 : epsm1(:,:,:,1) = bufdc3d
1594 : ABI_FREE(bufdc3d)
1595 : #endif
1596 :
1597 : else
1598 : ! Full matrix (G,G',w,q) is needed.
1599 : !call wrtout(std_out, "calling mpiotk: Full matrix (G,G',w,q) is needed.")
1600 :
1601 : #ifdef HAVE_GW_DPC
1602 : ! Can read all data at once.
1603 0 : buf_dim = (npweA)**2 * nomegaA * HScr%nqibz
1604 0 : offset = offset_wq(1,1)
1605 0 : sc_mode = xmpio_collective
1606 :
1607 : call mpiotk_read_fsuba_dpc4D(mpi_fh,offset,&
1608 : [HScr%npwe,HScr%npwe,HScr%nomega,HScr%nqibz], [npweA,npweA,nomegaA,HScr%nqibz], [1,1,1,1],&
1609 0 : buf_dim,epsm1,xmpio_chunk_bsize,sc_mode,comm,ierr)
1610 0 : ABI_CHECK(ierr==0,"Fortran record too big")
1611 : #else
1612 : ! Have to allocate workspace for dp data.
1613 : ABI_MALLOC_OR_DIE(bufdc3d,(npweA,npweA,nomegaA), ierr)
1614 : sc_mode = xmpio_collective
1615 :
1616 : do iq_ibz=1,Hscr%nqibz
1617 : offset = offset_wq(1,iq_ibz)
1618 : buf_dim = (2*npweA)**2 * nomegaA
1619 :
1620 : call mpiotk_read_fsuba_dpc3D(mpi_fh,offset, &
1621 : [HScr%npwe,HScr%npwe,HScr%nomega], [npweA,npweA,nomegaA], [1,1,1],&
1622 : buf_dim,bufdc3d,xmpio_chunk_bsize,sc_mode,comm,ierr)
1623 : ABI_CHECK(ierr==0,"Fortran matrix too big")
1624 :
1625 : epsm1(:,:,:,iq_ibz) = bufdc3d
1626 : end do
1627 :
1628 : ABI_FREE(bufdc3d)
1629 : #endif
1630 : end if
1631 :
1632 0 : call MPI_FILE_CLOSE(mpi_fh,mpi_err)
1633 0 : ABI_FREE(offset_wq)
1634 : #endif
1635 :
1636 : case (IO_MODE_FORTRAN)
1637 : ! Read epsilon^-1 with Fortran IO
1638 : ! Allocate a single column to save memory.
1639 : ! TODO re-merge the two cases.
1640 0 : ABI_MALLOC(bufdc2d,(Hscr%npwe,1))
1641 :
1642 : ! Two coding for different case just to keep it readable.
1643 : select case (read_qslice)
1644 : case (.True.)
1645 : ! Read only a slice of the full array (useful if the entire array is huge).
1646 : !if (dim_wings==1) STOP 'not implemented'
1647 : !TODO this has to be done in a cleaner way.
1648 : qread_loop: &
1649 0 : & do iq_ibz=1,Hscr%nqibz
1650 0 : if (iq_ibz==iqiA) then
1651 0 : do iomega=1,nomegaA
1652 0 : do ipwe=1,Hscr%npwe
1653 0 : read(unt, err=10, iomsg=errmsg) bufdc2d(1:Hscr%npwe,1)
1654 0 : if (ipwe<=npweA) epsm1(1:npweA,ipwe,iomega,1)=bufdc2d(1:npweA,1)
1655 : end do
1656 : end do
1657 : EXIT qread_loop ! Got data. Do not need to read file till the end.
1658 : else
1659 : ! Skip other q-points i.e bufdc2d(1:Hscr%npwe,1:Hscr%npwe)
1660 0 : do iomega=1,Hscr%nomega
1661 0 : do ipwe=1,Hscr%npwe
1662 0 : read(unt, err=10, iomsg=errmsg)
1663 : end do
1664 : end do
1665 : end if ! iq_ibz==iqiA
1666 : end do qread_loop ! iq_ibz
1667 :
1668 : case (.False.)
1669 : ! Read the entire array.
1670 0 : do iq_ibz=1,Hscr%nqibz
1671 0 : do iomega=1,nomegaA
1672 0 : do ipwe=1,Hscr%npwe
1673 0 : read(unt, err=10, iomsg=errmsg) bufdc2d(1:Hscr%npwe,1)
1674 0 : if (ipwe<=npweA) epsm1(1:npweA,ipwe,iomega,iq_ibz)=bufdc2d(1:npweA,1)
1675 : end do
1676 : end do
1677 : ! Skip other frequencies
1678 0 : do iomega=nomegaA+1,Hscr%nomega
1679 0 : do ipwe=1,Hscr%npwe
1680 0 : read(unt, err=10, iomsg=errmsg)
1681 : end do
1682 : end do
1683 : end do !iq_ibz
1684 : end select
1685 :
1686 0 : close(unt)
1687 :
1688 : case (IO_MODE_ETSF)
1689 : ! netcdf does not support complex datatypes. Here I use some C-magic to associate the memory
1690 : ! to a Fortran real pointer with the correct type and shape. Note that the data on file is always in double precision.
1691 : ! nf90_get_var will automatically convert from double to single if the GW code is in single precision mode.
1692 : ! This is the reason why I'm using CPP option in the declaration of real_epsm1.
1693 :
1694 : ! FIXME: Need to know the type to read
1695 : !write(std_out,*)"in read_screening"
1696 580 : varid = nctk_idname(unt, varname)
1697 :
1698 : ! [cplex, npwe, npwe, nspin, nspin, nomega, nqpt]
1699 4640 : call c_f_pointer(c_loc(epsm1(1,1,1,1)), real_epsm1, [2,npweA,npweA,1,1,nomegaA,nqibzA])
1700 1740 : spins = 1; s1 = spins(1); s2 = spins(2)
1701 580 : if (read_qslice) then
1702 6765 : ncerr = nf90_get_var(unt, varid, real_epsm1, start=[1,1,1,s1,s2,1,iqia], count=[2,npweA,npweA,1,1,nomegaA,1])
1703 : else
1704 1935 : ncerr = nf90_get_var(unt, varid, real_epsm1, start=[1,1,1,s1,s2,1,1], count=[2,npweA,npweA,1,1,nomegaA,nqibzA])
1705 : !do iq_ibz=1,nqibzA
1706 : ! !write(*,*)"epsm1: in read ",iq_ibz,epsm1(1:3,1,1,iq_ibz)
1707 : !end do
1708 : end if
1709 580 : NCF_CHECK_MSG(ncerr, sjoin("getting var:", varname))
1710 580 : NCF_CHECK(nf90_close(unt))
1711 : !write(std_out,*)"read_screening done"
1712 :
1713 : case default
1714 580 : ABI_ERROR(sjoin("Wrong iomode:", iomode2str(my_iomode)))
1715 : end select
1716 :
1717 : ! Free memory
1718 580 : ABI_SFREE(bufdc2d)
1719 : ABI_SFREE(bufdc3d)
1720 :
1721 580 : call Hscr%free()
1722 :
1723 : !call cwtime_report("- read_screening:", cpu, wall, gflops)
1724 : DBG_EXIT("COLL")
1725 :
1726 580 : return
1727 :
1728 : ! Handle Fortran IO error.
1729 : 10 continue
1730 0 : ABI_ERROR(errmsg)
1731 :
1732 1160 : end subroutine read_screening
1733 : !!***
1734 :
1735 : !----------------------------------------------------------------------
1736 :
1737 : !!****f* m_io_screening/hscr_mpio_skip
1738 : !! NAME
1739 : !! hscr_mpio_skip
1740 : !!
1741 : !! FUNCTION
1742 : !! Skip the header of the (SCR|SUSC) file in MPI-IO mode. This routine uses local MPI-IO calls hence
1743 : !! it can be safely called by master node only. Note however that in this case the
1744 : !! offset has to be communicated to the other nodes.
1745 : !!
1746 : !! INPUTS
1747 : !! mpio_fh=MPI-IO file handler
1748 : !! fmarker_bsize = Byte length of Fortran record marker.
1749 : !! fmarker_mpi_type= MPI type of the Fortran record marker
1750 : !!
1751 : !! OUTPUT
1752 : !! fform=kind of the array in the file
1753 : !! offset=The offset of the Fortran record located immediately below the Abinit header.
1754 : !!
1755 : !! SOURCE
1756 :
1757 0 : subroutine hscr_mpio_skip(mpio_fh, fform, offset)
1758 :
1759 : !Arguments ------------------------------------
1760 : integer,intent(in) :: mpio_fh
1761 : integer,intent(out) :: fform
1762 : integer(kind=XMPI_OFFSET_KIND),intent(out) :: offset
1763 :
1764 : !Local variables-------------------------------
1765 : !scalars
1766 : integer :: bsize_frm,mpi_type_frm, headform
1767 : #ifdef HAVE_MPI_IO
1768 : integer :: ierr,isk
1769 : !character(len=500) :: msg
1770 : !arrays
1771 : integer(kind=MPI_OFFSET_KIND) :: fmarker,positloc
1772 : integer :: nqlwl(1),statux(MPI_STATUS_SIZE)
1773 : #endif
1774 : ! *************************************************************************
1775 :
1776 : offset = 0
1777 0 : bsize_frm = xmpio_bsize_frm ! Byte size of the Fortran record marker.
1778 0 : mpi_type_frm = xmpio_mpi_type_frm ! MPI type of the record marker.
1779 :
1780 0 : call hdr_mpio_skip(mpio_fh,fform,offset)
1781 :
1782 : !call wrtout(std_out, sjoin("in hdr_mpio_skip with fform = ",itoa(fform)))
1783 :
1784 : #ifdef HAVE_MPI_IO
1785 0 : select case (fform)
1786 : case (1003, 1004)
1787 : ! Skip the titles
1788 0 : call xmpio_read_frm(mpio_fh,offset,xmpio_single,fmarker,ierr)
1789 :
1790 : ! read headform from the 2d record.
1791 0 : positloc = offset + bsize_frm + 3*xmpi_bsize_int
1792 0 : call MPI_FILE_READ_AT(mpio_fh,positloc,headform,1,MPI_INTEGER,statux,ierr)
1793 : !call wrtout(std_out, sjoin("headform = ",itoa(headform)))
1794 :
1795 : ! read nqlwl from the 2d record.
1796 0 : positloc = offset + bsize_frm + 9*xmpi_bsize_int
1797 0 : call MPI_FILE_READ_AT(mpio_fh,positloc,nqlwl,1,MPI_INTEGER,statux,ierr)
1798 : !call wrtout(std_out, sjoin("nqlwl = ",itoa(nqlwl(1))))
1799 :
1800 0 : do isk=1,5
1801 0 : call xmpio_read_frm(mpio_fh,offset,xmpio_single,fmarker,ierr)
1802 : end do
1803 :
1804 0 : if (nqlwl(1)>0) then ! skip qlwl
1805 0 : call xmpio_read_frm(mpio_fh,offset,xmpio_single,fmarker,ierr)
1806 : end if
1807 :
1808 0 : if (headform > 80) then ! skip new records
1809 0 : do isk=1,4
1810 0 : call xmpio_read_frm(mpio_fh,offset,xmpio_single,fmarker,ierr)
1811 : end do
1812 : end if
1813 :
1814 : case default
1815 0 : ABI_BUG(sjoin('Wrong fform read:', itoa(fform)))
1816 : end select
1817 :
1818 : #else
1819 : ABI_ERROR("hscr_mpio_skip cannot be used when MPI-IO is not enabled")
1820 : #endif
1821 :
1822 0 : end subroutine hscr_mpio_skip
1823 : !!***
1824 :
1825 : !----------------------------------------------------------------------
1826 :
1827 : !!****f* m_io_screening/ioscr_qmerge
1828 : !! NAME
1829 : !! ioscr_qmerge
1830 : !!
1831 : !! FUNCTION
1832 : !! Produce new file by merging the q-points stored in other files.
1833 : !! This routine should be called by a single MPI process.
1834 : !!
1835 : !! INPUTS
1836 : !! nfiles=Number of files to be merged.
1837 : !! filenames(nfiles)=Paths of files to be merged.
1838 : !! hscr_files(nfiles)<hscr_t>=Headers of the files to be merged.
1839 : !! fname_out=Name of the file to be produced.
1840 : !!
1841 : !! OUTPUT
1842 : !! ohscr<hscr_t>=The header of the output file.
1843 : !!
1844 : !! SOURCE
1845 :
1846 15 : subroutine ioscr_qmerge(nfiles, filenames, hscr_files, fname_out, ohscr)
1847 :
1848 : !Arguments ------------------------------------
1849 : !scalars
1850 : integer,intent(in) :: nfiles
1851 : character(len=*),intent(in) :: fname_out
1852 : type(hscr_t),intent(out) :: ohscr
1853 : !arrays
1854 : character(len=*),intent(in) :: filenames(nfiles)
1855 : type(hscr_t),intent(in) :: hscr_files(nfiles)
1856 :
1857 : !Local variables-------------------------------
1858 : !scalars
1859 : integer,parameter :: rdwr2=2,master=0
1860 : integer :: iq_ibz,ifound,ifile,iqf,ount,iomode,fform_merge,comm,nomega4m,npwe4m,iqiA,ierr
1861 : character(len=500) :: msg
1862 : character(len=nctk_slen) :: varname
1863 : type(abifile_t) :: abifile
1864 : !arrays
1865 3 : integer,allocatable :: merge_table(:,:)
1866 : real(dp) :: qdiff(3)
1867 3 : complex(gwp),allocatable :: epsm1(:,:,:,:)
1868 : ! *************************************************************************
1869 :
1870 3 : comm = xmpi_comm_self
1871 :
1872 3 : if (file_exists(fname_out)) then
1873 0 : ABI_ERROR(sjoin("Cannot overwrite existing file:", fname_out))
1874 : end if
1875 :
1876 : ! Merge the headers creating the full list of q-points.
1877 3 : call hscr_merge(Hscr_files(1:nfiles), ohscr)
1878 6 : call ohscr%print([std_out], 1, header='Header of the final file')
1879 :
1880 : ! For each q to be merged, save the index of the file where q is stored as well as its sequential index.
1881 : ! Useful to do the merge point-by-point thus avoiding the allocation of the entire epsm1 array.
1882 9 : ABI_MALLOC(merge_table,(ohscr%nqibz,2))
1883 21 : do iq_ibz=1,ohscr%nqibz
1884 34 : ifound=0
1885 34 : fl: do ifile=1,nfiles
1886 79 : do iqf=1,Hscr_files(ifile)%nqibz
1887 252 : qdiff(:)=ohscr%qibz(:,iq_ibz)-Hscr_files(ifile)%qibz(:,iqf)
1888 148 : if (all(abs(qdiff) < GW_TOLQ)) then
1889 18 : merge_table(iq_ibz,1)=ifile
1890 18 : merge_table(iq_ibz,2)=iqf
1891 18 : ifound=ifound+1
1892 18 : write(msg,'(a,3f12.6,2a)')'. q-point:',ohscr%qibz(:,iq_ibz),' will be taken from ',TRIM(filenames(ifile))
1893 18 : call wrtout(std_out, msg)
1894 : EXIT fl
1895 : end if
1896 : end do
1897 : end do fl
1898 : ! Check if q-point has been found, multiple q-points not allowed.
1899 3 : ABI_CHECK(ifound == 1, 'ifound/=1')
1900 : end do
1901 :
1902 3 : iomode = IO_MODE_FORTRAN; if (endswith(fname_out, ".nc")) iomode = IO_MODE_ETSF
1903 3 : if (iomode == IO_MODE_FORTRAN) then
1904 0 : if (open_file(fname_out,msg,newunit=ount,status='new',form='unformatted') /= 0) then
1905 0 : ABI_ERROR(msg)
1906 : end if
1907 : else
1908 3 : NCF_CHECK(nctk_open_create(ount, fname_out, comm))
1909 : end if
1910 :
1911 : ! Write the header.
1912 3 : fform_merge = hscr_files(1)%fform
1913 3 : abifile = abifile_from_fform(fform_merge)
1914 3 : if (abifile%fform == 0) then
1915 0 : ABI_ERROR(sjoin("Cannot find any abifile object associated to fform:", itoa(fform_merge)))
1916 : end if
1917 3 : varname = abifile%varname
1918 :
1919 11 : if (any(hscr_files(:)%fform /= hscr_files(1)%fform)) then
1920 0 : write(std_out,*)"fforms: ",hscr_files(:)%fform
1921 0 : ABI_ERROR("Files to be merged have different fform. Cannot merge data")
1922 : end if
1923 :
1924 3 : call ohscr%io(fform_merge, rdwr2, ount, comm, master, iomode)
1925 :
1926 3 : npwe4m = ohscr%npwe
1927 3 : nomega4m = ohscr%nomega
1928 :
1929 15 : ABI_MALLOC_OR_DIE(epsm1,(npwe4m,npwe4m,nomega4m,1), ierr)
1930 :
1931 21 : do iq_ibz=1,ohscr%nqibz
1932 18 : ifile = merge_table(iq_ibz,1)
1933 18 : iqiA = merge_table(iq_ibz,2)
1934 18 : call read_screening(varname, filenames(ifile), npwe4m, 1, nomega4m,epsm1, iomode, comm, iqiA=iqiA)
1935 21 : call write_screening(varname, ount, iomode, npwe4m, nomega4m, iq_ibz, epsm1)
1936 : end do
1937 :
1938 3 : ABI_FREE(epsm1)
1939 3 : ABI_FREE(merge_table)
1940 :
1941 3 : if (iomode == IO_MODE_FORTRAN) then
1942 0 : close(ount)
1943 : else
1944 3 : NCF_CHECK(nf90_close(ount))
1945 : end if
1946 :
1947 3 : write(msg,'(3a)')ch10,' ==== Files have been merged successfully === ',ch10
1948 3 : call wrtout(std_out, msg)
1949 :
1950 3 : end subroutine ioscr_qmerge
1951 : !!***
1952 :
1953 : !----------------------------------------------------------------------
1954 :
1955 : !!****f* m_io_screening/ioscr_qrecover
1956 : !! NAME
1957 : !! ioscr_qrecover
1958 : !!
1959 : !! FUNCTION
1960 : !! Recover q-points from a corrupted file produced e.g. from an interrupted run
1961 : !! This routine should be called by a single MPI process.
1962 : !!
1963 : !! INPUTS
1964 : !! path=Corrupted file.
1965 : !! nqrec=Number of q-points to recover.
1966 : !! fname_out=Name of the file to be produced.
1967 : !!
1968 : !! OUTPUT
1969 : !! Output is written to file.
1970 : !!
1971 : !! SOURCE
1972 :
1973 1 : subroutine ioscr_qrecover(ipath, nqrec, fname_out)
1974 :
1975 : !Arguments ------------------------------------
1976 : !scalars
1977 : integer,intent(in) :: nqrec
1978 : character(len=*),intent(in) :: ipath,fname_out
1979 :
1980 : !Local variables-------------------------------
1981 : !scalars
1982 : integer,parameter :: rdwr2=2,master=0
1983 : integer :: iqiA,nqibzA,nomega_asked,unt,npwe_asked,iomode,comm,fform1,ifform,ierr
1984 : character(len=500) :: msg
1985 : character(len=nctk_slen) :: varname
1986 7 : type(hscr_t) :: hscr_recov,hscr
1987 : type(abifile_t) :: abifile
1988 : !arrays
1989 1 : complex(gwp),allocatable :: epsm1(:,:,:,:)
1990 : ! *************************************************************************
1991 :
1992 1 : comm = xmpi_comm_self
1993 :
1994 1 : call wrtout(std_out, sjoin(". Recovering q-points in file:", ipath))
1995 1 : call wrtout(std_out, sjoin(". Data written to file:", fname_out))
1996 :
1997 1 : if (file_exists(fname_out)) then
1998 0 : ABI_ERROR(sjoin("Cannot overwrite existing file:", fname_out))
1999 : end if
2000 :
2001 : ! Find iomode from file extension and open output file.
2002 1 : if (endswith(fname_out, ".nc")) then
2003 1 : iomode = IO_MODE_ETSF
2004 1 : NCF_CHECK(nctk_open_create(unt, fname_out, comm))
2005 : else
2006 0 : iomode = IO_MODE_FORTRAN
2007 0 : if (open_file(fname_out, msg, newunit=unt, status='new', form='unformatted') /= 0) then
2008 0 : ABI_ERROR(msg)
2009 : end if
2010 : end if
2011 :
2012 : ! Read header.
2013 1 : call hscr%from_file(ipath, ifform, comm)
2014 1 : ABI_CHECK(ifform /= 0, sjoin("fform = 0 while reading:", ipath))
2015 :
2016 1 : if (nqrec < 1 .or. nqrec > hscr%nqibz) then
2017 0 : ABI_ERROR(sjoin("Wrong input. nqibz on file:", itoa(hscr%nqibz)))
2018 : end if
2019 :
2020 : ! Copy header
2021 1 : call hscr%copy(hscr_recov)
2022 :
2023 : ! Change dimensions and arrays associated to nqibz.
2024 1 : hscr_recov%nqibz = nqrec
2025 1 : ABI_FREE(hscr_recov%qibz)
2026 3 : ABI_MALLOC(hscr_recov%qibz, (3,nqrec))
2027 14 : hscr_recov%qibz = hscr%qibz(:,1:nqrec)
2028 :
2029 2 : call hscr_recov%print([std_out], 1, header="Header of the new SCR file")
2030 :
2031 : ! Write the header of the recovered file.
2032 1 : fform1 = hscr%fform
2033 :
2034 1 : abifile = abifile_from_fform(fform1)
2035 1 : if (abifile%fform == 0) then
2036 0 : ABI_ERROR(sjoin("Cannot find any abifile object associated to fform:", itoa(fform1)))
2037 : end if
2038 1 : varname = abifile%varname
2039 :
2040 1 : call hscr_recov%io(fform1,rdwr2,unt,comm,master,iomode)
2041 :
2042 1 : nqibzA=1; nomega_asked=hscr%nomega; npwe_asked=hscr%npwe
2043 :
2044 5 : ABI_MALLOC_OR_DIE(epsm1,(npwe_asked,npwe_asked,nomega_asked,1), ierr)
2045 :
2046 4 : do iqiA=1,hscr_recov%nqibz
2047 3 : call read_screening(varname,ipath,npwe_asked,nqibzA,nomega_asked,epsm1,iomode,comm,iqiA=iqiA)
2048 4 : call write_screening(varname,unt,iomode,npwe_asked,nomega_asked,iqiA,epsm1)
2049 : end do
2050 :
2051 1 : if (iomode == IO_MODE_FORTRAN) close(unt)
2052 1 : if (iomode == IO_MODE_ETSF) then
2053 1 : NCF_CHECK(nf90_close(unt))
2054 : end if
2055 :
2056 1 : ABI_FREE(epsm1)
2057 1 : call hscr%free()
2058 1 : call hscr_recov%free()
2059 :
2060 1 : call wrtout(std_out, "Recovery completed")
2061 :
2062 2 : end subroutine ioscr_qrecover
2063 : !!***
2064 :
2065 : !----------------------------------------------------------------------
2066 :
2067 : !!****f* m_io_screening/ioscr_wmerge
2068 : !! NAME
2069 : !! ioscr_wmerge
2070 : !!
2071 : !! FUNCTION
2072 : !! Produce new file by merging the frequencies stored in other files.
2073 : !! This routine should be called by a single MPI process.
2074 : !!
2075 : !! INPUTS
2076 : !! nfiles=Number of files to be merged.
2077 : !! filenames(nfiles)=Paths of files to be merged.
2078 : !! hscr_files(nfiles)<hscr_t>=Headers of the files to be merged.
2079 : !! fname_out=Name of the file to be produced.
2080 : !!
2081 : !! OUTPUT
2082 : !! ohscr<hscr_t>=The header of the output file.
2083 : !!
2084 : !! SOURCE
2085 :
2086 15 : subroutine ioscr_wmerge(nfiles, filenames, hscr_file, freqremax, fname_out, ohscr)
2087 :
2088 : !Arguments ------------------------------------
2089 : !scalars
2090 : integer,intent(in) :: nfiles
2091 : real(dp),intent(in) :: freqremax
2092 : character(len=*),intent(in) :: fname_out
2093 : type(hscr_t),intent(out) :: ohscr
2094 : !arrays
2095 : character(len=*),intent(in) :: filenames(nfiles)
2096 : type(hscr_t),intent(in) :: hscr_file(nfiles)
2097 :
2098 : !Local variables-------------------------------
2099 : !scalars
2100 : integer,parameter :: rdwr2=2,master=0
2101 : integer :: ii,iq_ibz,ifile,ount,iomode,fform_merge,comm,nomega4m
2102 : integer :: nfreq_tot,nfreqre,nfreqim,ifrq,npwe4mI,npwe4mJ,ierr, mod10, order
2103 : character(len=500) :: msg
2104 : logical :: skip
2105 : character(len=nctk_slen) :: varname
2106 : character(len=etsfio_charlen) :: rw_mesh_type, iw_mesh_type, cw_mesh_type
2107 : type(abifile_t) :: abifile
2108 : !arrays
2109 3 : integer,allocatable :: freq_indx(:,:),ifile_indx(:),pos_indx(:),i_temp(:),i2_temp(:,:)
2110 3 : real(dp),allocatable :: real_omega(:), real_omega_wgs(:), imag_omega(:), imag_omega_wgs(:) ,omega_wgs_storage(:)
2111 3 : complex(gwp),allocatable :: epsm1(:,:,:,:),epsm1_temp(:,:,:,:)
2112 3 : complex(dp),allocatable :: omega_storage(:)
2113 : ! *************************************************************************
2114 :
2115 3 : comm = xmpi_comm_self
2116 :
2117 3 : if (file_exists(fname_out)) then
2118 0 : ABI_ERROR(sjoin("Cannot overwrite existing file:", fname_out))
2119 : end if
2120 :
2121 3 : mod10 = mod(hscr_file(1)%gwcalctyp, 10)
2122 :
2123 : ! These are the meshes that will be reported in the final SCR file.
2124 : ! None means that we have a single point or no point at all along that axis
2125 : ! Clearly we cannot merge files with different meshes.
2126 3 : rw_mesh_type = "None"; iw_mesh_type = "None"; cw_mesh_type = "None"
2127 9 : do ifile=1,nfiles
2128 6 : if (hscr_file(ifile)%rw_mesh_type /= "None") then
2129 4 : if (rw_mesh_type /= "None" .and. rw_mesh_type /= hscr_file(ifile)%rw_mesh_type) then
2130 0 : ABI_ERROR(sjoin("Cannot merge rw_mesh_type:", rw_mesh_type, " with: ", hscr_file(ifile)%rw_mesh_type))
2131 : end if
2132 4 : rw_mesh_type = hscr_file(ifile)%rw_mesh_type
2133 : end if
2134 :
2135 6 : if (hscr_file(ifile)%iw_mesh_type /= "None") then
2136 5 : if (iw_mesh_type /= "None" .and. iw_mesh_type /= hscr_file(ifile)%iw_mesh_type) then
2137 0 : ABI_ERROR(sjoin("Cannot merge iw_mesh_type:", iw_mesh_type, " with: ", hscr_file(ifile)%iw_mesh_type))
2138 : end if
2139 5 : iw_mesh_type = hscr_file(ifile)%iw_mesh_type
2140 : end if
2141 :
2142 9 : if (hscr_file(ifile)%cw_mesh_type /= "None") then
2143 0 : if (cw_mesh_type /= "None" .and. cw_mesh_type /= hscr_file(ifile)%cw_mesh_type) then
2144 0 : ABI_ERROR(sjoin("Cannot merge cw_mesh_type:", cw_mesh_type, " with: ", hscr_file(ifile)%cw_mesh_type))
2145 : end if
2146 0 : cw_mesh_type = hscr_file(ifile)%cw_mesh_type
2147 : end if
2148 : end do ! ifile
2149 :
2150 6 : do ifile=2,nfiles
2151 :
2152 : ! Check that q-points are the same
2153 3 : ABI_CHECK_IEQ(Hscr_file(ifile)%nqibz, Hscr_file(1)%nqibz, 'files do not have the same number of q-points!')
2154 23 : do iq_ibz=1,Hscr_file(1)%nqibz
2155 83 : if (ABS(SUM(Hscr_file(ifile)%qibz(:,iq_ibz) - Hscr_file(1)%qibz(:,iq_ibz))) > tol6) then
2156 0 : ABI_ERROR('Q-point set differs between one or more files!')
2157 : end if
2158 : end do
2159 :
2160 : ! Check gwcalctyp and other basic parameters.
2161 3 : ABI_CHECK_IEQ(hscr_file(ifile)%gwcalctyp, hscr_file(1)%gwcalctyp, "Different gwcalctyp")
2162 3 : ABI_CHECK_IEQ(hscr_file(ifile)%npwe, hscr_file(1)%npwe, "Different npwe")
2163 3 : ABI_CHECK_IEQ(hscr_file(ifile)%id, hscr_file(1)%id, "Different IDs")
2164 3 : ABI_CHECK_IEQ(hscr_file(ifile)%ikxc, hscr_file(1)%ikxc, "Different IXCx")
2165 3 : ABI_CHECK_IEQ(hscr_file(ifile)%test_type, hscr_file(1)%test_type, "Different test_type")
2166 3 : ABI_CHECK_IEQ(hscr_file(ifile)%tordering, hscr_file(1)%tordering, "Different tordering")
2167 6 : ABI_CHECK_IEQ(hscr_file(ifile)%gwgamma, hscr_file(1)%gwgamma, "Different gwgamma")
2168 : end do ! ifile
2169 :
2170 : ! nfreq_tot here is the total *possible* number of freqs.
2171 3 : nfreq_tot = 0
2172 9 : do ifile=1,nfiles
2173 9 : nfreq_tot = nfreq_tot + Hscr_file(ifile)%nomega
2174 : end do
2175 :
2176 : ! freq_indx: mapping (global frequency index, file index) to local file index.
2177 : ! ifile_indx: mapping global frequency index to file index.
2178 : !
2179 9 : ABI_MALLOC(omega_storage, (nfreq_tot))
2180 9 : ABI_MALLOC(omega_wgs_storage, (nfreq_tot))
2181 12 : ABI_MALLOC(freq_indx, (nfreq_tot, nfiles))
2182 9 : ABI_MALLOC(ifile_indx, (nfreq_tot))
2183 321 : omega_storage = CMPLX(-one,-one); freq_indx = 0; ifile_indx = 0
2184 :
2185 : ! TODO: One should handle the case of complex frequencies as well.
2186 : ! Calculate the total number of real freqs and store
2187 3 : nfreqre = 0
2188 9 : do ifile=1,nfiles
2189 87 : do ifrq=1,Hscr_file(ifile)%nomega
2190 78 : skip = .FALSE.
2191 : ! Check whether to skip this point
2192 78 : if (AIMAG(Hscr_file(ifile)%omega(ifrq)) > tol16) skip = .TRUE.
2193 78 : if (REAL(Hscr_file(ifile)%omega(ifrq)) > freqremax) skip = .TRUE.
2194 : ! Check for repetition or non-monotonic points
2195 78 : if (nfreqre > 1) then
2196 832 : do ii=1,nfreqre
2197 832 : if (ABS(REAL(Hscr_file(ifile)%omega(ifrq)) - REAL(omega_storage(ii))) < tol6) skip = .TRUE.
2198 : end do
2199 : end if
2200 78 : if (skip) CYCLE
2201 :
2202 48 : nfreqre = nfreqre + 1
2203 :
2204 : ! Store (complex) frequency and index
2205 48 : omega_storage(nfreqre) = Hscr_file(ifile)%omega(ifrq)
2206 48 : omega_wgs_storage(nfreqre) = Hscr_file(ifile)%omega_wgs(ifrq)
2207 :
2208 48 : ifile_indx(nfreqre) = ifile
2209 48 : freq_indx(nfreqre, ifile) = ifrq
2210 : write(std_out,'(a,es16.6,a,i0,2(a,i0))')&
2211 48 : ' Found real frequency: ',REAL(omega_storage(nfreqre))*Ha_eV,' [eV], number: ',nfreqre,&
2212 132 : ', in file: ',ifile,' local index: ',ifrq
2213 : end do
2214 : end do
2215 :
2216 3 : if (nfreqre > 0) then
2217 : ! Sort real frequencies and rearrange weights as well.
2218 9 : ABI_MALLOC(real_omega, (nfreqre))
2219 6 : ABI_MALLOC(real_omega_wgs, (nfreqre))
2220 9 : ABI_MALLOC(pos_indx, (nfreqre))
2221 6 : ABI_MALLOC(i_temp, (nfreqre))
2222 12 : ABI_MALLOC(i2_temp, (nfreqre,nfiles))
2223 :
2224 : ! Copy real frequencies to temp. sorting array.
2225 51 : real_omega(1:nfreqre) = REAL(omega_storage(1:nfreqre))
2226 :
2227 : ! Sort frequencies while keeping track of index
2228 : ! Set up indexing array
2229 150 : pos_indx = [(ii, ii=1,nfreqre)]
2230 3 : call sort_dp(nfreqre, real_omega, pos_indx, tol16)
2231 :
2232 51 : i_temp(1:nfreqre) = ifile_indx(1:nfreqre)
2233 105 : i2_temp(1:nfreqre,1:nfiles) = freq_indx(1:nfreqre,1:nfiles)
2234 :
2235 : ! Copy sorted frequencies plus file and frequency index
2236 51 : do ii=1,nfreqre
2237 48 : omega_storage(ii) = CMPLX(real_omega(ii),zero)
2238 48 : real_omega_wgs(ii) = omega_wgs_storage(pos_indx(ii))
2239 48 : ifile_indx(ii) = i_temp(pos_indx(ii))
2240 147 : freq_indx(ii,1:nfiles) = i2_temp(pos_indx(ii),1:nfiles)
2241 : end do
2242 51 : omega_wgs_storage(1:nfreqre) = real_omega_wgs(1:nfreqre)
2243 :
2244 3 : ABI_FREE(real_omega)
2245 3 : ABI_FREE(real_omega_wgs)
2246 3 : ABI_FREE(pos_indx)
2247 3 : ABI_FREE(i_temp)
2248 3 : ABI_FREE(i2_temp)
2249 : end if
2250 :
2251 : ! Check imaginary frequencies and store them
2252 3 : nfreqim = 0
2253 9 : do ifile=1,nfiles
2254 87 : do ifrq=1,Hscr_file(ifile)%nomega
2255 78 : if (REAL(Hscr_file(ifile)%omega(ifrq)) > tol8) CYCLE
2256 33 : if (AIMAG(Hscr_file(ifile)%omega(ifrq)) < tol8) CYCLE
2257 30 : nfreqim = nfreqim + 1
2258 30 : omega_storage(nfreqre+nfreqim) = Hscr_file(ifile)%omega(ifrq)
2259 30 : omega_wgs_storage(nfreqre+nfreqim) = Hscr_file(ifile)%omega_wgs(ifrq)
2260 30 : ifile_indx(nfreqre+nfreqim) = ifile
2261 30 : freq_indx(nfreqre+nfreqim,ifile) = ifrq
2262 : write(std_out,'(a,es16.6,a,i0,2(a,i0))')&
2263 30 : ' Found imag frequency: ',AIMAG(omega_storage(nfreqre+nfreqim))*Ha_eV,' [eV], number: ',nfreqim,&
2264 114 : ', in file: ',ifile,' local index: ',ifrq
2265 : end do
2266 : end do
2267 :
2268 : ! Sort imaginary frequencies
2269 9 : ABI_MALLOC(imag_omega, (nfreqim))
2270 6 : ABI_MALLOC(imag_omega_wgs, (nfreqim))
2271 9 : ABI_MALLOC(pos_indx, (nfreqim))
2272 6 : ABI_MALLOC(i_temp, (nfreqim))
2273 12 : ABI_MALLOC(i2_temp, (nfreqim, nfiles))
2274 :
2275 : ! Copy imaginary frequencies to temp. sorting array
2276 33 : imag_omega(1:nfreqim) = AIMAG(omega_storage(nfreqre+1:nfreqre+nfreqim))
2277 :
2278 : ! Sort frequencies while keeping track of index (+1 for ascending order, -1 for descending order)
2279 3 : order = +1
2280 3 : if (mod10 == SIG_GW_AC .and. Hscr_file(1)%iw_mesh_type == "gauss_legendre") order = -1
2281 :
2282 : ! Set up indexing array
2283 96 : pos_indx = [(ii, ii=1,nfreqim)]
2284 3 : call sort_dp(nfreqim, imag_omega, pos_indx, tol16, order=order)
2285 :
2286 33 : i_temp(1:nfreqim) = ifile_indx(nfreqre+1:nfreqre+nfreqim)
2287 69 : i2_temp(1:nfreqim,1:nfiles) = freq_indx(nfreqre+1:nfreqre+nfreqim,1:nfiles)
2288 :
2289 : ! Copy sorted frequencies plus file and frequency index
2290 33 : do ii=1,nfreqim
2291 30 : omega_storage(nfreqre+ii) = CMPLX(zero,imag_omega(ii))
2292 30 : ifile = i_temp(pos_indx(ii))
2293 :
2294 30 : ifile_indx(nfreqre+ii) = ifile
2295 90 : freq_indx(nfreqre+ii,1:nfiles) = i2_temp(pos_indx(ii),1:nfiles)
2296 30 : ifrq = i2_temp(pos_indx(ii), ifile)
2297 33 : imag_omega_wgs(ii) = Hscr_file(ifile)%omega_wgs(ifrq) ! TODO
2298 : end do
2299 :
2300 33 : omega_wgs_storage(nfreqre+1:nfreqre+nfreqim) = imag_omega_wgs
2301 :
2302 3 : ABI_FREE(imag_omega)
2303 3 : ABI_FREE(imag_omega_wgs)
2304 3 : ABI_FREE(pos_indx)
2305 3 : ABI_FREE(i_temp)
2306 3 : ABI_FREE(i2_temp)
2307 :
2308 : ! Here nfreq_tot becomes the *true* number of freq
2309 3 : nfreq_tot = nfreqre + nfreqim
2310 3 : write(std_out,'(2a,i0,a)') ch10,' Merging ',nfreq_tot,' frequencies.'
2311 3 : write(std_out,'(2(a,i0),2a)') ' ',nfreqre,' real, and ',nfreqim,' imaginary.',ch10
2312 :
2313 : ! Copy old header
2314 3 : call Hscr_file(1)%copy(ohscr)
2315 :
2316 : ! TODO: hscr_wmerge
2317 : ! Then modify entries for new frequency grid.
2318 3 : ohscr%nomega = nfreq_tot
2319 :
2320 9 : ABI_REMALLOC(ohscr%omega, (nfreq_tot))
2321 9 : ABI_REMALLOC(ohscr%omega_wgs, (nfreq_tot))
2322 84 : ohscr%omega = omega_storage(1:nfreq_tot)
2323 84 : ohscr%omega_wgs = omega_wgs_storage
2324 :
2325 3 : ohscr%rw_mesh_type = rw_mesh_type
2326 3 : ohscr%iw_mesh_type = iw_mesh_type
2327 3 : ohscr%cw_mesh_type = cw_mesh_type
2328 :
2329 3 : npwe4mI = ohscr%npwe*ohscr%nI
2330 3 : npwe4mJ = ohscr%npwe*ohscr%nJ
2331 :
2332 : ! Print new header for info
2333 6 : call ohscr%print([std_out], 1, header='Header of the final file')
2334 :
2335 3 : if (endswith(fname_out, ".nc")) then
2336 3 : iomode = IO_MODE_ETSF
2337 3 : NCF_CHECK(nctk_open_create(ount, fname_out, comm))
2338 : else
2339 0 : iomode = IO_MODE_FORTRAN
2340 0 : if (open_file(fname_out, msg, newunit=ount, status='new',form='unformatted') /= 0) then
2341 0 : ABI_ERROR(msg)
2342 : end if
2343 : end if
2344 :
2345 : ! Write the header.
2346 3 : fform_merge = ohscr%fform
2347 3 : abifile = abifile_from_fform(fform_merge)
2348 3 : if (abifile%fform == 0) then
2349 0 : ABI_ERROR(sjoin("Cannot find any abifile object associated to fform:", itoa(fform_merge)))
2350 : end if
2351 3 : varname = abifile%varname
2352 :
2353 3 : call ohscr%io(fform_merge, rdwr2, ount, comm, master, iomode)
2354 :
2355 3 : npwe4mI = ohscr%npwe*ohscr%nI
2356 3 : npwe4mJ = ohscr%npwe*ohscr%nJ
2357 3 : nomega4m = ohscr%nomega
2358 :
2359 : ! FIXME: Lot of memory allocated here. One can read and write inside the ifile loop
2360 : ! provided that partial frequencies are always contiguous and files are in the proper order
2361 15 : ABI_MALLOC_OR_DIE(epsm1, (npwe4mI, npwe4mJ, nomega4m, 1), ierr)
2362 :
2363 23 : do iq_ibz=1,ohscr%nqibz
2364 60 : do ifile=1,nfiles
2365 : ! allocate temporary array
2366 40 : npwe4mI = Hscr_file(ifile)%npwe*Hscr_file(ifile)%nI
2367 40 : npwe4mJ = Hscr_file(ifile)%npwe*Hscr_file(ifile)%nJ
2368 40 : nomega4m = Hscr_file(ifile)%nomega
2369 200 : ABI_MALLOC_OR_DIE(epsm1_temp, (npwe4mI, npwe4mJ, nomega4m, 1), ierr)
2370 :
2371 : ! read screening
2372 40 : call read_screening(varname,filenames(ifile),npwe4mI,1,nomega4m,epsm1_temp,iomode,comm,iqiA=iq_ibz)
2373 :
2374 : ! Copy matrices for relevant frequencies
2375 1124 : do ifrq=1,nfreq_tot
2376 1124 : if (ifile_indx(ifrq)==ifile) then
2377 1095158 : epsm1(:,:,ifrq,1)=epsm1_temp(:,:,freq_indx(ifrq,ifile),1)
2378 : end if
2379 : end do
2380 :
2381 60 : ABI_FREE(epsm1_temp)
2382 : end do !ifile
2383 :
2384 : ! Write data.
2385 20 : npwe4mI = ohscr%npwe*ohscr%nI
2386 20 : nomega4m = ohscr%nomega
2387 23 : call write_screening(varname,ount,iomode,npwe4mI,nomega4m,iq_ibz,epsm1)
2388 : end do ! iq_ibz
2389 :
2390 3 : ABI_FREE(epsm1)
2391 3 : ABI_FREE(omega_wgs_storage)
2392 3 : ABI_FREE(omega_storage)
2393 3 : ABI_FREE(freq_indx)
2394 3 : ABI_FREE(ifile_indx)
2395 :
2396 3 : if (iomode == IO_MODE_FORTRAN) then
2397 0 : close(ount)
2398 : else
2399 3 : NCF_CHECK(nf90_close(ount))
2400 : end if
2401 :
2402 3 : write(msg,'(3a)')ch10,' ==== Files have been merged successfully === ',ch10
2403 3 : call wrtout(std_out, msg)
2404 :
2405 3 : end subroutine ioscr_wmerge
2406 : !!***
2407 :
2408 : !----------------------------------------------------------------------
2409 :
2410 : !!****f* m_io_screening/ioscr_wremove
2411 : !! NAME
2412 : !! ioscr_wremove
2413 : !!
2414 : !! FUNCTION
2415 : !! Produce new file by removing selected frequencies in the initial file `inpath`.
2416 : !! This routine should be called by a single MPI process.
2417 : !!
2418 : !! INPUTS
2419 : !! inpath=Input file
2420 : !! ihscr<hscr_t>=Headerf of the input file.
2421 : !! fname_out=Output file.
2422 : !! nfreq_tot=Number of frequencies in new file.
2423 : !! freq_indx(nfreq_tot)=Index of frequency to be kept in input file.
2424 : !!
2425 : !! OUTPUT
2426 : !! ohscr<hscr_t>=The header of the output file.
2427 : !!
2428 : !! SOURCE
2429 :
2430 5 : subroutine ioscr_wremove(inpath, ihscr, fname_out, nfreq_tot, freq_indx, ohscr)
2431 :
2432 : !Arguments ------------------------------------
2433 : !scalars
2434 : integer,intent(in) :: nfreq_tot
2435 : character(len=*),intent(in) :: inpath,fname_out
2436 : type(hscr_t),intent(in) :: ihscr
2437 : type(hscr_t),intent(out) :: ohscr
2438 : !arrays
2439 : integer,intent(in) :: freq_indx(nfreq_tot)
2440 :
2441 : !Local variables-------------------------------
2442 : !scalars
2443 : integer,parameter :: rdwr2=2,master=0
2444 : integer :: iq_ibz,fform_merge,comm,nomega4m,ierr
2445 : integer :: ifrq,npwe4mI,npwe4mJ,iomode,ount
2446 : character(len=500) :: msg
2447 : character(len=nctk_slen) :: varname
2448 : type(abifile_t) :: abifile
2449 : !arrays
2450 1 : complex(gwp),allocatable :: epsm1(:,:,:),epsm1_temp(:,:,:)
2451 : ! *************************************************************************
2452 :
2453 1 : comm = xmpi_comm_self
2454 :
2455 : ! check ifreq_idx
2456 1 : ABI_CHECK(nfreq_tot > 0, "nfreq_tot <= 0!")
2457 1 : if (all(freq_indx == 0)) ABI_ERROR("all(freq_indx == 0)")
2458 :
2459 : ! Copy the old header
2460 1 : call ihscr%copy(ohscr)
2461 :
2462 : ! Then modify entries for new frequency grid.
2463 1 : ohscr%nomega = nfreq_tot
2464 3 : ABI_REMALLOC(ohscr%omega, (nfreq_tot))
2465 3 : ABI_REMALLOC(ohscr%omega_wgs, (nfreq_tot))
2466 17 : do ifrq=1,nfreq_tot
2467 16 : ohscr%omega(ifrq) = ihscr%omega(freq_indx(ifrq))
2468 17 : ohscr%omega_wgs(ifrq) = ihscr%omega_wgs(freq_indx(ifrq))
2469 : end do
2470 :
2471 1 : npwe4mI = ohscr%npwe*ohscr%nI
2472 1 : npwe4mJ = ohscr%npwe*ohscr%nJ
2473 :
2474 : ! Print new header for info
2475 2 : call ohscr%print([std_out], 1, header='Header of the final file')
2476 :
2477 : ! Open output file.
2478 1 : if (endswith(fname_out, ".nc")) then
2479 1 : iomode = IO_MODE_ETSF
2480 1 : NCF_CHECK(nctk_open_create(ount, fname_out, comm))
2481 : else
2482 0 : iomode = IO_MODE_FORTRAN
2483 0 : if (open_file(fname_out, msg, newunit=ount, status='new', form='unformatted') /= 0) then
2484 0 : ABI_ERROR(msg)
2485 : end if
2486 : end if
2487 :
2488 : ! Write the header.
2489 1 : fform_merge = ohscr%fform
2490 1 : abifile = abifile_from_fform(fform_merge)
2491 1 : if (abifile%fform == 0) then
2492 0 : ABI_ERROR(sjoin("Cannot find any abifile object associated to fform:", itoa(fform_merge)))
2493 : end if
2494 1 : varname = abifile%varname
2495 :
2496 1 : call ohscr%io(fform_merge,rdwr2,ount,comm,master,iomode)
2497 :
2498 1 : npwe4mI = ohscr%npwe*ohscr%nI; npwe4mJ = ohscr%npwe*ohscr%nJ
2499 1 : nomega4m = ohscr%nomega
2500 :
2501 5 : ABI_MALLOC_OR_DIE(epsm1, (npwe4mI,npwe4mJ,nomega4m), ierr)
2502 :
2503 9 : do iq_ibz=1,ohscr%nqibz
2504 : ! allocate temporary array
2505 8 : npwe4mI = ihscr%npwe * ihscr%nI
2506 8 : npwe4mJ = ihscr%npwe * ihscr%nJ
2507 8 : nomega4m = ihscr%nomega
2508 40 : ABI_MALLOC_OR_DIE(epsm1_temp,(npwe4mI,npwe4mJ,nomega4m), ierr)
2509 :
2510 : ! read full screening matrix for this q-point
2511 8 : call read_screening(varname,inpath,npwe4mI,1,nomega4m,epsm1_temp,iomode,comm,iqiA=iq_ibz)
2512 :
2513 : ! Copy relevant frequencies
2514 136 : do ifrq=1,nfreq_tot
2515 96904 : epsm1(:,:,ifrq) = epsm1_temp(:,:,freq_indx(ifrq))
2516 : end do
2517 :
2518 8 : ABI_FREE(epsm1_temp)
2519 :
2520 8 : npwe4mI = ohscr%npwe*ohscr%nI; nomega4m = ohscr%nomega
2521 9 : call write_screening(varname,ount,iomode,npwe4mI,nomega4m,iq_ibz,epsm1)
2522 : end do ! iq_ibz
2523 :
2524 1 : ABI_FREE(epsm1)
2525 :
2526 1 : if (iomode == IO_MODE_FORTRAN) then
2527 0 : close(ount)
2528 : else
2529 1 : NCF_CHECK(nf90_close(ount))
2530 : end if
2531 :
2532 1 : write(msg,'(3a)')ch10,' ==== Frequencies have been removed successfully === ',ch10
2533 1 : call wrtout(std_out, msg)
2534 :
2535 1 : end subroutine ioscr_wremove
2536 : !!***
2537 :
2538 : !!****f* m_io_screening/get_hscr_qmesh_gsph
2539 : !! NAME
2540 : !! get_hscr_qmesh_gsph
2541 : !!
2542 : !! FUNCTION
2543 : !!
2544 : !! INPUTS
2545 : !!
2546 : !! OUTPUT
2547 : !!
2548 : !! SOURCE
2549 :
2550 306 : subroutine get_hscr_qmesh_gsph(w_fname, dtset, cryst, hscr, qmesh, gsph_c, qlwl, comm)
2551 :
2552 : !Arguments ------------------------------------
2553 : !scalars
2554 : character(len=*),intent(inout) :: w_fname
2555 : type(dataset_type),intent(inout) :: dtset
2556 : type(crystal_t),intent(in) :: cryst
2557 : type(hscr_t),intent(out) :: hscr
2558 : type(kmesh_t),intent(out) :: qmesh
2559 : type(gsphere_t),intent(out) :: gsph_c
2560 : real(dp),allocatable,intent(out) :: qlwl(:,:)
2561 : integer,intent(in) :: comm
2562 :
2563 : !Local variables-------------------------------
2564 : integer,parameter :: master = 0
2565 : integer :: my_rank, fform, npwe_file, nqlwl, ierr
2566 : character(len=500) :: msg
2567 : ! *************************************************************************
2568 :
2569 17 : my_rank = xmpi_comm_rank(comm)
2570 :
2571 17 : if (my_rank == master) then
2572 : ! Read dimensions from the external file.
2573 17 : if (.not. file_exists(w_fname)) then
2574 13 : w_fname = nctk_ncify(w_fname)
2575 13 : ABI_COMMENT(sjoin("File not found. Will try netcdf file: ", w_fname))
2576 : end if
2577 : ! Master reads npw and nqlwl from the SCR file.
2578 17 : call wrtout(std_out, sjoin('Testing SCR file: ', w_fname))
2579 17 : call hscr%from_file(w_fname, fform, xmpi_comm_self)
2580 :
2581 : ! Have to change %npweps if it was larger than dim on disk.
2582 17 : npwe_file = hscr%npwe
2583 17 : nqlwl = hscr%nqlwl
2584 :
2585 17 : if (dtset%npweps > npwe_file) then
2586 : write(msg,'(2(a,i0),2a,i0)')&
2587 0 : "The number of G-vectors stored on file (",npwe_file,") is smaller than input dtset%npweps: ",dtset%npweps,ch10,&
2588 0 : "Calculation will proceed with the maximum available set, npwe_file: ",npwe_file
2589 0 : ABI_WARNING(msg)
2590 0 : dtset%npweps = npwe_file
2591 17 : else if (dtset%npweps < npwe_file .and. dtset%npweps /= 0) then
2592 : write(msg,'(2(a,i0),2a,i0)')&
2593 8 : "The number of G-vectors stored on file (",npwe_file,") is larger than dtset%npweps: ",dtset%npweps,ch10,&
2594 16 : "Calculation will proceed with dtset%npweps: ",dtset%npweps
2595 8 : ABI_COMMENT(msg)
2596 : else
2597 9 : call Gsph_c%init(cryst, 0, ecut=dtset%ecuteps)
2598 9 : if (Gsph_c%ng > npwe_file) then
2599 0 : dtset%npweps = npwe_file
2600 : write(msg,'(2a,f4.1,a,i0,2a,i0)')&
2601 0 : "npweps was not set in input.",&
2602 0 : ch10//"The number of G-vectors generated according to ecuteps (",dtset%ecuteps,") is larger than that stored on file (",npwe_file,")",&
2603 0 : ch10//"Calculation will proceed with the maximum available set: ",npwe_file
2604 0 : ABI_COMMENT(msg)
2605 : else
2606 9 : dtset%npweps = Gsph_c%ng
2607 : write(msg,'(2a,f4.1,a,i0,2a,f4.1)')&
2608 9 : "npweps was not set in input.",&
2609 9 : ch10//"The number of G-vectors generated according to ecuteps (",dtset%ecuteps,") is smaller than that stored on file (",npwe_file,")",&
2610 18 : ch10//"Calculation will proceed with ecuteps: ",dtset%ecuteps
2611 9 : ABI_COMMENT(msg)
2612 : end if
2613 9 : call Gsph_c%free()
2614 : end if
2615 : end if
2616 :
2617 17 : call xmpi_bcast(w_fname, master, comm, ierr)
2618 17 : call hscr%bcast(master, my_rank, comm)
2619 17 : call xmpi_bcast(dtset%npweps, master, comm, ierr)
2620 17 : call xmpi_bcast(nqlwl, master, comm, ierr)
2621 :
2622 17 : if (nqlwl > 0) then
2623 51 : ABI_MALLOC(qlwl, (3, nqlwl))
2624 102 : qlwl = hscr%qlwl
2625 : end if
2626 :
2627 : ! Init qmesh from the SCR file.
2628 17 : call qmesh%init(cryst, hscr%nqibz, hscr%qibz, dtset%kptopt)
2629 :
2630 17 : call gsph_c%init(cryst, dtset%npweps, gvec=hscr%gvec)
2631 :
2632 17 : end subroutine get_hscr_qmesh_gsph
2633 : !!***
2634 :
2635 636 : end module m_io_screening
2636 : !!***
|