Line data Source code
1 : !!****m* ABINIT/m_screen
2 : !! NAME
3 : !! m_screen
4 : !!
5 : !! FUNCTION
6 : !! Screening object used in the BSE/GWPT code.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2014-2026 ABINIT group (MG)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !!
14 : !! TODO
15 : !! Integrate these objects with quartic GW.
16 : !!
17 : !! SOURCE
18 :
19 : #if defined HAVE_CONFIG_H
20 : #include "config.h"
21 : #endif
22 :
23 : #include "abi_common.h"
24 :
25 : module m_screen
26 :
27 : use defs_basis
28 : use m_xmpi
29 : use m_hide_blas
30 : use m_errors
31 : use m_splines
32 : use m_abicore
33 : use m_kxc
34 : use m_screening
35 : use m_nctk
36 : use m_sort
37 : use m_yaml
38 :
39 : use m_gwdefs, only : GW_TOLQ0, czero_gw
40 : use m_fstrings, only : firstchar, endswith, strcat, itoa, sjoin
41 : use m_numeric_tools, only : print_arr
42 : use m_geometry, only : normv
43 : use m_crystal, only : crystal_t
44 : use m_bz_mesh, only : kmesh_t
45 : use m_gsphere, only : gsphere_t
46 : use m_vcoul, only : vcoul_t
47 : use m_io_screening, only : read_screening, hscr_t, ncname_from_id, em1_ncname
48 : use m_ppmodel, only : ppmodel_t, PPM_NONE, PPM_NOTAB
49 : use m_pstat, only : pstat_proc
50 :
51 : implicit none
52 :
53 : private
54 :
55 : public :: em1_symmetrize_ip
56 : public :: em1_symmetrize_op
57 :
58 : ! Flags defining the content of the %mat buffer in the fgg_t type.
59 : integer,public,parameter :: MAT_NOTYPE = 0
60 : integer,public,parameter :: MAT_CHI0 = 1
61 : integer,public,parameter :: MAT_CHI = 2
62 : integer,public,parameter :: MAT_EPSILON = 3
63 : integer,public,parameter :: MAT_INV_EPSILON = 4
64 : integer,public,parameter :: MAT_INV_EPSILON_M1 = 5
65 : integer,public,parameter :: MAT_W = 6
66 : integer,public,parameter :: MAT_W_M1 = 7
67 : !
68 : ! Family vertex.
69 : integer,public,parameter :: VTX_FAMILY_NONE = 0 ! No vertex correction.
70 : integer,public,parameter :: VTX_FAMILY_TDDFT = 1 ! TDDFT-based vertex.
71 : integer,public,parameter :: VTX_FAMILY_ADA = 2 ! ADA vertex.
72 : !
73 : ! Test charge or test particle.
74 : integer,public,parameter :: VTX_TEST_CHARGE = 0
75 : integer,public,parameter :: VTX_TEST_PARTICLE = 1
76 : !
77 : ! Named constants for the frequency mesh.
78 : integer,private,parameter :: WMESH_LINEAR = 1
79 : integer,private,parameter :: WMESH_GAUSS_LEG = 2
80 : integer,private,parameter :: WMESH_TAN_GRID = 3
81 : !
82 : ! Method used for the frequency integration.
83 : integer,public,parameter :: WINT_NONE = 0
84 : integer,public,parameter :: WINT_PPMODEL = 1
85 : integer,public,parameter :: WINT_CONTOUR = 2
86 : integer,public,parameter :: WINT_AC = 3
87 : !
88 : ! Parameters used for the model dielectric function.
89 : integer,public,parameter :: MDL_NONE = 0
90 : integer,public,parameter :: MDL_BECHSTEDT = 1
91 : !
92 : ! Flags giving the status of the local buffers defined in fgg_t.
93 : integer,private,parameter :: MAT_NODATA = 0
94 : integer,private,parameter :: MAT_ALLOCATED = 1
95 : integer,private,parameter :: MAT_STORED = 2
96 : !
97 : ! Flags giving the status of the local buffers defined in fgg_t.
98 : integer,private,parameter :: FGG_QBZ_ISPOINTER =1 ! Fgg_qbz is used to store the address in memory.
99 : integer,private,parameter :: FGG_QBZ_ISALLOCATED=2 ! Fgg_qbz is used as an allocable array.
100 : !!***
101 :
102 : !----------------------------------------------------------------------
103 :
104 : !!****t* m_screen/screen_info_t
105 : !! NAME
106 : !! screen_info_t
107 : !!
108 : !! FUNCTION
109 : !! Container storing the parameters used to initialize a screen_t datatype or to
110 : !! calculate a new SCR file from the SUSC file containing the independent-particle
111 : !! polarizability.
112 : !!
113 : !! NOTES
114 : !! The list of parameters passed to screening_init is copied in W%Info.
115 : !! At present there is no need to provide a copy method since the structure does
116 : !! not contain pointers but such a method must be defined and used if
117 : !! dynamic entities are added to the datatype.
118 : !!
119 : !! SOURCE
120 :
121 : type,public :: screen_info_t
122 :
123 : integer :: mat_type = MAT_NOTYPE
124 : ! Matrix identifier. See MAT_* flags.
125 :
126 : integer :: vtx_family = VTX_FAMILY_NONE
127 : ! Vertex correction family.
128 :
129 : integer :: invalid_freq = 0
130 : ! Sets the procedure to follow when a ppm frequency is invalid (negative or imaginary),
131 : ! see input variable gw_invalid_freq
132 :
133 : integer :: ixc = 0
134 : ! XC functional used for the TDDFT-based vertex.
135 :
136 : integer :: use_ada = 0
137 : ! >0 if ADA vertex is used.
138 :
139 : integer :: use_mdf = MDL_NONE
140 : ! >0 if model dielectric function is used.
141 :
142 : integer :: use_ppm = PPM_NONE
143 : ! >0 if ppmodel is used.
144 :
145 : integer :: vtx_test = VTX_TEST_CHARGE
146 : ! test charge or test particle.
147 :
148 : integer :: wint_method = WINT_NONE
149 : ! Defines the frequency integration technique. See WIN_ flags.
150 : ! NOTE that this flag can be changed at run time. For example
151 : ! one can switch from the CD to the PPm if the ppmodel parameters are in memory
152 :
153 : real(dp) :: ada_kappa = 2.1_dp
154 : ! Inverse smearing length used for ADA.
155 :
156 : real(dp) :: eps_inf = 12.0_dp
157 : ! Dielectric constant used for the model dielectric function.
158 :
159 : real(dp) :: drude_plsmf = zero
160 : ! Drude plasma frequency used for PPmodel 1.
161 :
162 : contains
163 :
164 : procedure :: print => screen_info_print
165 :
166 : end type screen_info_t
167 : !!***
168 :
169 : !----------------------------------------------------------------------
170 :
171 : !!****t* m_screen/fgg_t
172 : !! NAME
173 : !! fgg_t
174 : !!
175 : !! FUNCTION
176 : !! Object used to store F(G,G')(w) for a given q-point.
177 : !!
178 : !! SOURCE
179 :
180 : type,public :: fgg_t
181 :
182 : integer :: nomega
183 : ! Number of frequencies.
184 :
185 : integer :: npw
186 : ! Number of G vectors.
187 :
188 : integer :: nqlwl
189 : ! Number of points for the treatment of the long wave-length limit.
190 :
191 : integer :: has_mat = MAT_NODATA
192 : ! Flag giving the status of mat.
193 :
194 : complex(gwp),allocatable :: mat(:,:,:)
195 : ! (npw, npw, nomega)
196 : ! The component of the two-point function $F_{G,G',w}$ for a given q.
197 :
198 : !complex(dp),allocatable :: head(:,:,:)
199 : ! head(3,3,nomega)
200 :
201 : !complex(dp),allocatable :: lwing(:,:,:)
202 : ! lwing(3,npwe,nomega)
203 : ! Lower wings
204 :
205 : !complex(dp),allocatable :: uwing(:,:,:)
206 : ! uwing(3,npwe,nomega)
207 : ! Upper wings.
208 :
209 : contains
210 :
211 : procedure :: init => fgg_init ! Creation method.
212 : !procedure :: free => fgg_free
213 : end type fgg_t
214 :
215 : public :: fgg_free ! Free memory.
216 : !!***
217 :
218 : interface fgg_free
219 : module procedure fgg_free_0D
220 : module procedure fgg_free_1D
221 : end interface fgg_free
222 :
223 : !----------------------------------------------------------------------
224 :
225 : !!****t* m_screen/screen_t
226 : !! NAME
227 : !! screen_t
228 : !!
229 : !! FUNCTION
230 : !! Object used to store the screening matrix in reciprocal space.
231 : !!
232 : !! SOURCE
233 :
234 : type,public :: screen_t
235 :
236 : ! scalars
237 : integer :: iomode ! Flag defining the IO mode.
238 : integer :: debug_level=0 ! Internal Flag defining the debug level.
239 : integer :: mqmem ! =0 for out-of-core solution, =nqibz if entire matrix is stored in memory.
240 : integer :: nI,nJ ! Number of components (rows,columns) in chi|eps^-1. (1,1) if collinear.
241 : integer :: nqibz ! Number of q-points in the IBZ used.
242 : integer :: nqlwl ! Number of points used for the treatment of the long wave-length limit.
243 : integer :: nomega ! Total Number of frequencies used.
244 : integer :: nomega_i ! Number of purely imaginary frequencies used.
245 : integer :: nomega_r ! Number of real frequencies used.
246 : integer :: npw ! Number of G vectors.
247 : integer :: prtvol ! Verbosity level.
248 : integer :: has_ppmodel ! 1 if PPmodel tables are stored.
249 : integer :: has_fgg ! 1 if Fgg tables are stored.
250 : integer :: nfftf_tot
251 : integer :: nspden
252 :
253 : ! arrays
254 : integer :: ngfftf(18) ! Info on the FFT mesh used for ae_rhor (used for the model dielectric function)
255 :
256 : real(dp),allocatable :: ae_rhor(:,:)
257 : ! ae_rhor(nfft,nspden)
258 : ! Density in real space used to construct the TDDFT kernel or the model dielectric function.
259 : ! NOTE that ae_rhor is given on the dense mesh as it contains the PAW onsite contribution.
260 :
261 : character(len=fnlen) :: fname = ABI_NOFILE ! Name of the file used for the out-of-core solution.
262 :
263 : real(dp),allocatable :: qibz(:,:)
264 : ! (3,nqibz)
265 : ! q-points in reduced coordinates
266 :
267 : real(dp),allocatable :: qlwl(:,:)
268 : ! (3,nqlwl)
269 : ! q-points used for the long wave-length limit treatment.
270 :
271 : complex(dp),allocatable :: omega(:)
272 : ! (nomega)
273 : ! List of frequencies. Real frequencies are packed first.
274 :
275 : integer,allocatable :: gvec(:,:)
276 : ! (3,npw)
277 : ! G-vectors used to describe the two-point function (r.l.u.).
278 :
279 : logical,allocatable :: keep_qibz(:)
280 : ! (nqibz)
281 : ! Storage strategy: keep or not keep Em1(q) in memory.
282 :
283 : type(fgg_t),pointer :: Fgg(:) => null()
284 : ! (nqibz)
285 : ! F_{G,G'}(q,w) for q in the IBZ.
286 :
287 : integer :: fgg_qbz_stat = FGG_QBZ_ISPOINTER
288 : ! Status of Fgg_qbz
289 :
290 : integer :: fgg_qbz_idx = 0
291 : ! The index of the q-point in BZ pointed by Fgg_qbz. Used for debugging purpose.
292 :
293 : type(fgg_t),pointer :: Fgg_qbz => null()
294 : ! Buffer used for storing F_GG' at the point q_bz in the BZ
295 : ! If q_bz is in the IBZ, Fgg_qbz *points* to Fgg(iq_ibz)
296 : ! If q_bz is not in the IBZ, Fgg_qbz is *allocated* and used to store the symmetrized matrix.
297 :
298 : type(ppmodel_t) :: ppm
299 : ! Structure storing the plasmon-pole parameters.
300 :
301 : type(screen_info_t) :: info
302 : ! Parameters used to construct the screening.
303 :
304 : contains
305 :
306 : procedure :: nullify => screen_nullify
307 : ! Nullify all pointers before use.
308 :
309 : procedure :: init => screen_init
310 : ! Creation method.
311 :
312 : procedure :: print => screen_print
313 : ! Print info on object
314 :
315 : procedure :: free => screen_free
316 : ! Free dynamic memory
317 :
318 : procedure :: rotate_iqbz => screen_rotate_iqbz
319 : ! Prepare the object for applying W_qbz.
320 :
321 : procedure :: w0gemv => screen_w0gemv
322 : ! Matrix vector multiplication \sum_{G'} F_{G,G') |u(G')>.
323 :
324 : procedure :: calc_sigc => screen_calc_sigc
325 : ! Compute the frequency convolution.
326 :
327 : procedure :: ihave_fgg => screen_ihave_fgg
328 : ! Inquire the processor whether it has a particular F_{GG')(q) and with which status.
329 :
330 : end type screen_t
331 : !!***
332 :
333 : contains
334 : !----------------------------------------------------------------------
335 :
336 : !!****f* m_screen/screen_info_print
337 : !! NAME
338 : !! screen_info_print
339 : !!
340 : !! FUNCTION
341 : !! Printout object
342 : !!
343 : !! INPUTS
344 : !! units=Unit numbers for output
345 : !! header=String to be printed as header for additional info.
346 : !!
347 : !! SOURCE
348 :
349 58 : subroutine screen_info_print(W_info, units, header)
350 :
351 : !Arguments ------------------------------------
352 : !scalars
353 : class(screen_info_t),intent(in) :: W_info
354 : integer,intent(in) :: units(:)
355 : character(len=*),optional,intent(in) :: header
356 :
357 : !Local variables-------------------------------
358 : character(len=500) :: msg
359 : ! *********************************************************************
360 :
361 29 : msg=' ==== Info on the screen_info_t% object ==== '
362 29 : if (PRESENT(header)) msg=' ==== '//TRIM(ADJUSTL(header))//' ==== '
363 29 : call wrtout(units, msg)
364 :
365 : !integer
366 29 : write(msg,'(a,i3)')" mat_type ",W_info%mat_type
367 29 : call wrtout(units, msg)
368 29 : write(msg,'(a,i3)')" vtx_family ",W_info%vtx_family
369 29 : call wrtout(units, msg)
370 29 : write(msg,'(a,i3)')" invalid_freq",W_info%invalid_freq
371 29 : call wrtout(units, msg)
372 29 : write(msg,'(a,i3)')" ixc ",W_info%ixc
373 29 : call wrtout(units, msg)
374 29 : write(msg,'(a,i3)')" use_ada ",W_info%use_ada
375 29 : call wrtout(units, msg)
376 29 : write(msg,'(a,i3)')" use_mdf ",W_info%use_mdf
377 29 : call wrtout(units, msg)
378 29 : write(msg,'(a,i3)')" use_ppm ",W_info%use_ppm
379 29 : call wrtout(units, msg)
380 29 : write(msg,'(a,i3)')" vtx_test ",W_info%vtx_test
381 29 : call wrtout(units, msg)
382 29 : write(msg,'(a,i3)')" wint_method ",W_info%wint_method
383 29 : call wrtout(units, msg)
384 :
385 : !real
386 29 : write(msg,'(a,f8.3)')" ada_kappa ",W_info%ada_kappa
387 29 : call wrtout(units, msg)
388 29 : write(msg,'(a,f8.3)')" eps_inf ",W_info%eps_inf
389 29 : call wrtout(units, msg)
390 29 : write(msg,'(a,f8.3)')" drude_plsmf ",W_info%drude_plsmf
391 29 : call wrtout(units, msg)
392 :
393 29 : end subroutine screen_info_print
394 : !!***
395 :
396 : !----------------------------------------------------------------------
397 :
398 : !!****f* m_screen/fgg_free_0D
399 : !! NAME
400 : !! fgg_free_0D
401 : !!
402 : !! FUNCTION
403 : !! Free dynamic memory.
404 : !!
405 : !! SOURCE
406 :
407 2155 : subroutine fgg_free_0D(Fgg)
408 :
409 : !Arguments ------------------------------------
410 : type(fgg_t),intent(inout) :: Fgg
411 : ! *************************************************************************
412 :
413 2155 : ABI_SFREE(Fgg%mat)
414 2155 : Fgg%has_mat = MAT_NODATA
415 :
416 2155 : end subroutine fgg_free_0D
417 : !!***
418 :
419 : !----------------------------------------------------------------------
420 :
421 : !!****f* m_screen/fgg_free_1D
422 : !! NAME
423 : !! fgg_free_1D
424 : !!
425 : !! FUNCTION
426 : !! Deallocate all the memory.
427 : !!
428 : !! INPUT
429 : !! [keep_qibz(:)]=Optional logical mask used to select the q-points that are deallocated.
430 : !!
431 : !! SOURCE
432 :
433 29 : subroutine fgg_free_1D(Fgg, keep_qibz)
434 :
435 : !Arguments ------------------------------------
436 : !scalars
437 : type(fgg_t),intent(inout) :: Fgg(:)
438 : logical,optional,intent(in) :: keep_qibz(:)
439 :
440 : !Local variables ------------------------------
441 : !scalars
442 : integer :: iq_ibz
443 : logical :: keep_it
444 : ! *************************************************************************
445 :
446 234 : do iq_ibz=LBOUND(Fgg,DIM=1),UBOUND(Fgg,DIM=1)
447 176 : keep_it = .FALSE.; if (PRESENT(keep_qibz)) keep_it = keep_qibz(iq_ibz)
448 205 : if (.not. keep_it) call fgg_free_0D(Fgg(iq_ibz))
449 : end do
450 :
451 29 : end subroutine fgg_free_1D
452 : !!***
453 :
454 : !----------------------------------------------------------------------
455 :
456 : !!****f* m_screen/fgg_init
457 : !! NAME
458 : !! fgg_init
459 : !!
460 : !! FUNCTION
461 : !! Initialize the structure allocating the memory and initializing the internal variables.
462 : !!
463 : !! INPUT
464 : !! npw
465 : !! nqlwl
466 : !!
467 : !! SOURCE
468 :
469 2149 : subroutine fgg_init(Fgg, npw, nomega, nqlwl)
470 :
471 : !Arguments ------------------------------------
472 : !scalars
473 : class(fgg_t),intent(inout) :: Fgg
474 : integer,intent(in) :: npw, nqlwl, nomega
475 :
476 : !Local variables ------------------------------
477 : integer :: ierr
478 : ! *************************************************************************
479 :
480 2149 : Fgg%nomega = nomega; Fgg%npw = npw; Fgg%nqlwl = nqlwl
481 :
482 2149 : if (npw > 0 .and. nomega > 0) then
483 10745 : ABI_MALLOC_OR_DIE(Fgg%mat, (npw, npw, nomega), ierr)
484 2149 : Fgg%has_mat = MAT_ALLOCATED
485 : end if
486 :
487 2149 : end subroutine fgg_init
488 : !!***
489 :
490 : !----------------------------------------------------------------------
491 :
492 : !!****f* m_screen/screen_fgg_qbz_set
493 : !! NAME
494 : !! screen_fgg_qbz_set
495 : !!
496 : !! FUNCTION
497 : !! Helper function used to perform the setup W%Fgg_qbz setting also the internal
498 : !! flag that defines its status.
499 : !!
500 : !! INPUTS
501 : !! iq_bz=Index of the q-point in the BZ.
502 : !! nqlwl=Number of wings wanted.
503 : !! how= "Pointer" is a true pointer is wanted.
504 : !! "Allocated" if memory has to be allocated.
505 : !!
506 : !! NOTES
507 : !! iq_bz and nqlwl are not used if how="Pointer".
508 : !!
509 : !! SOURCE
510 :
511 22740 : subroutine screen_fgg_qbz_set(screen, iq_bz, nqlwl, how)
512 :
513 : !Arguments ------------------------------------
514 : !scalars
515 : class(screen_t),intent(inout) :: screen
516 : integer,intent(in) :: iq_bz,nqlwl
517 : character(len=*),intent(in) :: how
518 :
519 : !Local variables ------------------------------
520 : !scalars
521 : !character(len=500) :: msg
522 : !************************************************************************
523 :
524 : ! Save the index of the q-point in the BZ.
525 22740 : screen%fgg_qbz_idx = iq_bz
526 :
527 45480 : if (firstchar(how, (/"P"/)) ) then
528 : ! We want a pointer.
529 4607 : select case (screen%fgg_qbz_stat)
530 : case (FGG_QBZ_ISALLOCATED)
531 1978 : call fgg_free_0D(screen%Fgg_qbz)
532 1978 : ABI_FREE(screen%Fgg_qbz)
533 : nullify(screen%Fgg_qbz)
534 1978 : screen%fgg_qbz_stat = FGG_QBZ_ISPOINTER
535 :
536 : case (FGG_QBZ_ISPOINTER)
537 : ! Set it to null().
538 651 : nullify(screen%Fgg_qbz)
539 :
540 : case default
541 2629 : ABI_ERROR(sjoin("Wrong status:", itoa(screen%fgg_qbz_stat)))
542 : end select
543 :
544 40222 : else if (firstchar(how, (/"A"/)) ) then
545 : ! We want an allocatable array.
546 :
547 22090 : select case (screen%fgg_qbz_stat)
548 : case (FGG_QBZ_ISPOINTER)
549 : ! Allocate memory
550 : nullify(screen%Fgg_qbz)
551 1979 : ABI_MALLOC(screen%Fgg_qbz,)
552 :
553 1979 : call screen%Fgg_qbz%init(screen%npw, screen%nomega, nqlwl)
554 1979 : screen%fgg_qbz_stat = FGG_QBZ_ISALLOCATED
555 :
556 : case (FGG_QBZ_ISALLOCATED)
557 18132 : screen%Fgg_qbz%has_mat = MAT_ALLOCATED ! STORED --> ALLOCATED
558 :
559 : case default
560 20111 : ABI_ERROR(sjoin("Wrong status:", itoa(screen%fgg_qbz_stat)))
561 : end select
562 :
563 : else
564 0 : ABI_BUG(sjoin("Wrong how:", how))
565 : end if
566 :
567 22740 : end subroutine screen_fgg_qbz_set
568 : !!***
569 :
570 : !----------------------------------------------------------------------
571 :
572 : !!****f* m_screen/screen_ihave_fgg
573 : !! NAME
574 : !! screen_ihave_fgg
575 : !!
576 : !! FUNCTION
577 : !! Inquire the processor whether it has a particular F_{GG')(q) and with which status.
578 : !!
579 : !! INPUTS
580 : !! iq_ibz=k-point index
581 : !! [how]=string defining which status is checked. By default the function returns
582 : !! .TRUE. if the wave is either MAT_ALLOCATED or MAT_STORED.
583 : !! Possible mutually exclusive values: "Allocated", "Stored".
584 : !! Only the first character is checked (no case-sensitive)
585 : !!
586 : !! NOTES
587 : !! A zero index can be used to inquire the status of the full set of q-points.
588 : !!
589 : !! SOURCE
590 :
591 23268 : logical pure function screen_ihave_fgg(screen, iq_ibz, how)
592 :
593 : !Arguments ------------------------------------
594 : !scalars
595 : class(screen_t),intent(in) :: screen
596 : integer,intent(in) :: iq_ibz
597 : character(len=*),optional,intent(in) :: how
598 :
599 : !Local variables ------------------------------
600 : integer :: ii, check(2)
601 : !************************************************************************
602 :
603 23268 : check = [MAT_ALLOCATED, MAT_STORED]
604 23268 : if (PRESENT(how)) then
605 69804 : if (firstchar(how, (/"A","a"/))) check = [MAT_ALLOCATED, MAT_ALLOCATED]
606 69804 : if (firstchar(how, (/"S","s"/))) check = [MAT_STORED, MAT_STORED]
607 : end if
608 :
609 23268 : if (iq_ibz > 0) then
610 : screen_ihave_fgg = (screen%Fgg(iq_ibz)%has_mat == check(1) .or.&
611 23268 : screen%Fgg(iq_ibz)%has_mat == check(2) )
612 : else
613 : ! check the status of the full set of q-tables.
614 0 : screen_ihave_fgg=.TRUE.
615 0 : do ii=1,screen%nqibz
616 : screen_ihave_fgg = screen_ihave_fgg .and. &
617 : (screen%Fgg(ii)%has_mat == check(1) .or.&
618 0 : screen%Fgg(ii)%has_mat == check(2) )
619 : end do
620 : end if
621 :
622 23268 : end function screen_ihave_fgg
623 : !!***
624 :
625 : !----------------------------------------------------------------------
626 :
627 : !!****f* m_screen/screen_nullify
628 : !! NAME
629 : !! screen_nullify
630 : !!
631 : !! FUNCTION
632 : !! Initialize the pointers to null()
633 : !!
634 : !! SOURCE
635 :
636 58 : subroutine screen_nullify(screen)
637 :
638 : !Arguments ------------------------------------
639 : class(screen_t),intent(inout) :: screen
640 : ! *************************************************************************
641 :
642 58 : nullify(screen%Fgg_qbz); screen%fgg_qbz_stat=FGG_QBZ_ISPOINTER ! Needed since the initial status is undefined.
643 58 : nullify(screen%Fgg)
644 :
645 58 : end subroutine screen_nullify
646 : !!***
647 :
648 : !----------------------------------------------------------------------
649 :
650 : !!****f* m_screen/screen_free
651 : !! NAME
652 : !! screen_free
653 : !!
654 : !! FUNCTION
655 : !! Free the memory allocated in the datatype.
656 : !!
657 : !! SOURCE
658 :
659 29 : subroutine screen_free(screen)
660 :
661 : !Arguments ------------------------------------
662 : class(screen_t),intent(inout) :: screen
663 : ! *************************************************************************
664 :
665 : ! integer
666 29 : ABI_SFREE(screen%gvec)
667 :
668 : !real
669 29 : ABI_SFREE(screen%ae_rhor)
670 29 : ABI_SFREE(screen%qibz)
671 29 : ABI_SFREE(screen%qlwl)
672 :
673 : !complex
674 29 : ABI_SFREE(screen%omega)
675 :
676 : ! logical
677 29 : ABI_SFREE(screen%keep_qibz)
678 :
679 : ! types
680 : ! Here be careful with dangling pointers.
681 : ! First Fgg_qbz that might point to one of the %Fgg then %Fgg.
682 30 : select case (screen%fgg_qbz_stat)
683 :
684 : case (FGG_QBZ_ISALLOCATED)
685 1 : call fgg_free_0D(screen%Fgg_qbz)
686 1 : ABI_FREE(screen%Fgg_qbz)
687 : nullify(screen%Fgg_qbz)
688 1 : screen%fgg_qbz_stat=FGG_QBZ_ISPOINTER
689 :
690 : case (FGG_QBZ_ISPOINTER)
691 28 : nullify(screen%Fgg_qbz)
692 28 : screen%fgg_qbz_stat=FGG_QBZ_ISPOINTER
693 :
694 : case default
695 29 : continue
696 : end select
697 :
698 : ! Free the Fgg matrices.
699 29 : if (associated(screen%Fgg)) then
700 29 : call fgg_free(screen%Fgg)
701 29 : ABI_FREE(screen%Fgg)
702 : end if
703 :
704 : ! Free the plasmon pole tables.
705 29 : call screen%ppm%free()
706 :
707 29 : end subroutine screen_free
708 : !!***
709 :
710 : !----------------------------------------------------------------------
711 :
712 : !!****f* m_screen/screen_print
713 : !! NAME
714 : !! screen_print
715 : !!
716 : !! FUNCTION
717 : !! Print info on the object.
718 : !!
719 : !! SOURCE
720 :
721 0 : subroutine screen_print(screen, units, header)
722 :
723 : !Arguments ------------------------------------
724 : class(screen_t),intent(in) :: screen
725 : integer,intent(in) :: units(:)
726 : character(len=*),optional,intent(in) :: header
727 :
728 : !Local variables-------------------------------
729 : character(len=500) :: msg
730 : type(yamldoc_t) :: ydoc
731 : ! *************************************************************************
732 :
733 0 : msg = ' ==== Info on the screen_t object ==== '; if (present(header)) msg=' ==== '//trim(adjustl(header))//' ==== '
734 0 : call wrtout(units, msg)
735 :
736 0 : ydoc = yamldoc_open('screen_params') !, width=11, real_fmt='(3f8.3)')
737 0 : call ydoc%add_int("nomega_r", screen%nomega_r)
738 0 : call ydoc%add_int("nomega_i", screen%nomega_i)
739 : !call ydoc%add_real("drude_plsmf", ppm%drude_plsmf)
740 : !call ydoc%add_int1d("has_qibz", ppm%has_qibz)
741 :
742 0 : call ydoc%write_units_and_free(units)
743 :
744 0 : end subroutine screen_print
745 : !!***
746 :
747 : !----------------------------------------------------------------------
748 :
749 : !!****f* m_screen/screen_init
750 : !! NAME
751 : !! screen_init
752 : !!
753 : !! FUNCTION
754 : !! Initialize basic dimensions and other important arrays
755 : !! starting from a file containing either epsilon^{-1} (_SCR) or chi0 (_SUSC).
756 : !!
757 : !! INPUTS
758 : !! W_Info<screen_info_t>=The list of parameters used to construct the screen function.
759 : !! Cryst<crystal_t>=Info on the unit cell.
760 : !! Qmesh<kmesh_t>=Info on the Q-mesh.
761 : !! Gsph<gsphere_t>=Info on the plane-wave basis set used for the two-point function.
762 : !! Vcp<vcoul_t>=Structure gathering data on the Coulombian interaction.
763 : !! ifname=The name of the external file used to read the matrix.
764 : !! id_required=Identifier used to specify the type of two-point function that is wanted.
765 : !! iomode=Option defining the file format of the external file.
766 : !! mqmem=0 for out-of-core solution, /=0 if entire matrix has to be stored in memory.
767 : !! npw_asked=Number of G-vector to be used in the calculation, if <=0 use Max allowed number.
768 : !! ngfftf(18)=Info on the (fine) mesh used for the density.
769 : !! nfftf_tot=Total number of point in the FFT mesh for ae_rhor
770 : !! nsppol=Number of independent spin polarizations.
771 : !! nspden=Number of spin density components in ae_rhor
772 : !! ae_rhor(nfftf_tot,nspden)
773 : !! prtvol=Verbosity level.
774 : !! comm=MPI communicator.
775 : !!
776 : !! SOURCE
777 :
778 29 : subroutine screen_init(screen, W_Info, Cryst, Qmesh, Gsph, Vcp, ifname, mqmem, npw_asked, &
779 29 : iomode, ngfftf, nfftf_tot, nsppol, nspden, ae_rhor, prtvol, comm)
780 :
781 : !Arguments ------------------------------------
782 : !scalars
783 : class(screen_t),intent(out) :: screen
784 : integer,intent(in) :: mqmem,iomode,npw_asked,comm,prtvol,nsppol, nfftf_tot,nspden
785 : character(len=fnlen),intent(in) :: ifname
786 : type(crystal_t),intent(in) :: Cryst
787 : type(gsphere_t),intent(in) :: Gsph
788 : type(vcoul_t),intent(in) :: Vcp
789 : type(kmesh_t),intent(in) :: Qmesh
790 : type(screen_info_t),intent(in) :: W_Info
791 : !arrays
792 : integer,intent(in) :: ngfftf(18)
793 : real(dp),intent(in) :: ae_rhor(nfftf_tot,nspden)
794 :
795 : !Local variables-------------------------------
796 : !scalars
797 : integer,parameter :: master=0
798 : integer :: option_test,approx_type,ixc_required,id_required !,nkxc
799 : integer :: fform,my_rank,mat_type_read, nqibz,nomega,iq_ibz,npw,nqlwl
800 : integer :: nI,nJ,iq_bz,mdf_type,ppmodel,ierr, iw,qsort,ii
801 : real(dp) :: eps_inf,drude_plsmf
802 : logical :: free_Fgg,found,from_file,is_qeq0,remove_dgg !only_one_kpt,
803 : character(len=500) :: msg
804 : character(len=fnlen) :: sus_fname,scr_fname
805 : character(len=nctk_slen) :: varname
806 116 : type(hscr_t) :: Hscr
807 : !arrays
808 58 : integer :: units(2), g0(3), iperm(Qmesh%nibz)
809 29 : real(dp) :: wt_list(Qmesh%nibz)
810 : !complex(gwp),contiguous, pointer :: em1_ggw(:,:,:)
811 : ! *********************************************************************
812 :
813 : DBG_ENTER("COLL")
814 : ABI_UNUSED(nsppol)
815 :
816 29 : my_rank = xmpi_comm_rank(comm); units = [std_out, ab_out]
817 29 : call screen%nullify()
818 :
819 : ! Initialize basic parameters
820 29 : screen%info = w_info
821 58 : call screen%info%print([std_out], header="W info")
822 :
823 29 : id_required = W_Info%mat_type
824 29 : approx_type = W_Info%vtx_family
825 29 : option_test = W_Info%vtx_test
826 29 : ixc_required = W_Info%ixc
827 29 : varname = ncname_from_id(id_required)
828 :
829 29 : if (all(id_required /= [MAT_INV_EPSILON])) then
830 0 : ABI_ERROR(sjoin("id_required:", itoa(id_required), " not available"))
831 : end if
832 :
833 : ! This part must be rationalized.
834 29 : remove_dgg = (id_required == MAT_W_M1)
835 :
836 29 : if (screen%info%use_mdf == MDL_NONE) screen%fname = ifname
837 29 : screen%nI = 1; screen%nJ = 1
838 :
839 : ! The q-point sampling is initialized from qmesh.
840 29 : screen%nqibz = Qmesh%nibz
841 87 : ABI_MALLOC(screen%qibz, (3, screen%nqibz))
842 762 : screen%qibz= Qmesh%ibz
843 :
844 29 : screen%mqmem = mqmem; if (screen%mqmem /= 0) screen%mqmem = screen%nqibz !; screen%mqmem = 0
845 :
846 87 : ABI_MALLOC(screen%keep_qibz, (screen%nqibz))
847 211 : screen%keep_qibz = .TRUE.; if (screen%mqmem == 0) screen%keep_qibz = .False.
848 :
849 29 : if (screen%mqmem /= 0 .and. screen%mqmem < screen%nqibz) then
850 : ! Keep in memory the most representative q-points.
851 0 : screen%keep_qibz = .FALSE.
852 0 : wt_list = Qmesh%wt; iperm = (/(ii,ii=1,Qmesh%nibz)/)
853 0 : call sort_dp(Qmesh%nibz, wt_list, iperm, tol12)
854 0 : do qsort=Qmesh%nibz,Qmesh%nibz-mqmem+1,1
855 0 : iq_ibz = iperm(qsort)
856 0 : screen%keep_qibz(iq_ibz) = .TRUE.
857 : end do
858 : end if
859 :
860 29 : screen%fgg_qbz_idx = 0
861 29 : screen%iomode = iomode
862 29 : screen%prtvol = prtvol
863 29 : screen%has_ppmodel = 0; if (screen%info%use_ppm /= PPM_NONE) screen%has_ppmodel = 1
864 :
865 : ! Copy the AE density for the model dielectric function or for the vertex corrections.
866 29 : screen%nspden = nspden
867 551 : screen%ngfftf = ngfftf
868 29 : screen%nfftf_tot = nfftf_tot
869 :
870 116 : ABI_MALLOC(screen%ae_rhor, (nfftf_tot, nspden))
871 286992 : screen%ae_rhor = ae_rhor
872 :
873 29 : free_Fgg = .FALSE.
874 :
875 29 : screen%has_fgg = 0; if (ANY(screen%info%wint_method == [WINT_CONTOUR, WINT_AC])) screen%has_fgg = 1
876 :
877 29 : if (screen%has_fgg > 0 .and. screen%has_ppmodel > 0) then
878 0 : ABI_WARNING("Both PPmodel tables and F_(GG')(q,w) are stored in memory")
879 : end if
880 :
881 : ! Default values used if external file is not read.
882 29 : nqlwl = 0; nomega = 1
883 29 : screen%npw = npw_asked
884 :
885 : ! Model dielectric function does not require any external file.
886 29 : from_file = (screen%info%use_mdf == MDL_NONE)
887 :
888 29 : if (from_file) then
889 : ! Open file and check its content.
890 11 : if (endswith(screen%fname, ".nc")) screen%iomode = IO_MODE_ETSF
891 11 : call hscr%from_file(screen%fname, fform, comm)
892 : ! Echo of the header
893 11 : if (my_rank == master .and. screen%prtvol > 0) call hscr%print([std_out], 0)
894 :
895 11 : mat_type_read = Hscr%id
896 11 : nqlwl = Hscr%nqlwl
897 11 : nomega = Hscr%nomega
898 : end if
899 :
900 29 : screen%nqlwl = nqlwl
901 29 : screen%nomega = nomega
902 :
903 87 : ABI_MALLOC(screen%qlwl, (3, screen%nqlwl))
904 87 : ABI_MALLOC(screen%omega, (screen%nomega))
905 :
906 29 : if (from_file) then
907 66 : screen%qlwl = Hscr%qlwl
908 33 : screen%omega = Hscr%omega
909 :
910 : ! G-vectors.
911 11 : screen%npw = Hscr%npwe
912 11 : if (npw_asked > 0) then
913 11 : if (npw_asked > Hscr%npwe) then
914 : write(msg,'(a,i0,2a,i0)') &
915 0 : 'The number of G-vectors saved on file is less than the value required: ',npw_asked,ch10,&
916 0 : 'Calculation will proceed with the Max available npw: ',Hscr%npwe
917 0 : ABI_WARNING(msg)
918 : else
919 11 : screen%npw = npw_asked ! Redefine the no. of G"s for W.
920 : write(msg,'(a,i0,2a,i0)')&
921 11 : 'The number of G-vectors saved on file is larger than the value required: ',npw_asked,ch10,&
922 22 : 'Calculation will proceed with npw: ',screen%npw
923 11 : ABI_COMMENT(msg)
924 : end if
925 : end if
926 :
927 : ! Here consistency check on G-vectors and q-points.
928 2303 : if (ANY(Hscr%gvec(:,1:screen%npw) /= Gsph%gvec(:,1:screen%npw))) then
929 : !write(std_out) W%gvec, Gsph%gvec
930 0 : ABI_ERROR("Hscr%gvec /= Gsph%gvec(1:W%npw)")
931 : end if
932 11 : ABI_CHECK(Hscr%nqibz == Qmesh%nibz, "Mismatch in the number of q-points in the IBZ")
933 11 : ierr = 0
934 78 : do iq_ibz=1,Hscr%nqibz
935 279 : if (ANY(ABS(Qmesh%ibz(:,iq_ibz) - Hscr%qibz(:,iq_ibz)) > tol6) ) then
936 0 : ierr = ierr + 1
937 0 : write(std_out,'(i0,2(3f7.3,1x))')iq_ibz, Qmesh%ibz(:,iq_ibz), Hscr%qibz(:,iq_ibz)
938 : end if
939 : end do
940 11 : ABI_CHECK(ierr == 0, "Wrong ordering in q-point list, Aborting now")
941 : end if
942 :
943 87 : ABI_MALLOC(screen%gvec, (3, screen%npw))
944 6246 : screen%gvec = Gsph%gvec(:,1:screen%npw)
945 :
946 : ! Frequency mesh.
947 29 : screen%nomega_r = 1; screen%nomega_i = 0
948 29 : if (screen%nomega == 2 ) then
949 0 : screen%nomega_r = 1; screen%nomega_i = 1
950 : else
951 : ! Real frequencies are packed in the first locations.
952 : screen%nomega_r = 1
953 58 : do iw=1,screen%nomega
954 58 : if (DBLE(screen%omega(iw))>0.001*Ha_eV) screen%nomega_r=iw
955 : end do
956 29 : screen%nomega_i = screen%nomega - screen%nomega_r
957 : end if
958 :
959 : ! ------------------------------ Initialization completed --------------------------------
960 : !
961 : ! Just to keep the code below more readable.
962 29 : npw = screen%npw
963 29 : nqibz = screen%nqibz
964 29 : nomega = screen%nomega
965 29 : nI = screen%ni
966 29 : nJ = screen%nj
967 263 : ABI_MALLOC(screen%Fgg, (nqibz))
968 :
969 29 : if (from_file) then
970 :
971 : ! Read ab-initio em1 from file.
972 11 : select case (mat_type_read)
973 : case (MAT_INV_EPSILON)
974 11 : call wrtout(std_out, strcat(" Em1 will be initialized from SCR file: ", screen%fname))
975 :
976 : case (MAT_CHI0)
977 : ! Should Write new SCR file.
978 0 : ABI_ERROR("Not coded yet")
979 0 : sus_fname = screen%fname; scr_fname="TESTING_SUS2SCR"
980 :
981 0 : screen%fname = scr_fname ! Change the name of the file associated to W.
982 :
983 : case default
984 0 : write(msg,'(a,i0)')" Unsupported conversion from mat_type ",mat_type_read
985 11 : ABI_ERROR(msg)
986 : end select
987 :
988 : ! Begin reading.
989 78 : do iq_ibz=1,nqibz
990 67 : if (.not. screen%keep_qibz(iq_ibz)) then
991 : !call wrtout(std_out, strcat("Skipping iq_ibz: ",itoa(iq_ibz)))
992 : CYCLE
993 : end if
994 :
995 67 : nqlwl = 0; is_qeq0 = (normv(screen%qibz(:,iq_ibz),Cryst%gmet,'G') < GW_TOLQ0)
996 67 : if (is_qeq0) nqlwl=screen%nqlwl
997 :
998 : ! Allocate F_{GG'}(w)
999 67 : call screen%Fgg(iq_ibz)%init(npw, nomega, nqlwl)
1000 :
1001 : ! Read data from file (use MPI-IO if possible)
1002 67 : if (screen%iomode /= IO_MODE_ETSF .and. xmpi_mpiio == 1) then
1003 : !call wrtout(std_out, "read_screening with MPI_IO")
1004 0 : call read_screening(varname, screen%fname, npw, 1, nomega, screen%Fgg(iq_ibz)%mat, IO_MODE_MPI, comm, iqiA=iq_ibz)
1005 : else
1006 67 : call read_screening(varname, screen%fname, npw, 1, nomega, screen%Fgg(iq_ibz)%mat, screen%iomode, comm, iqiA=iq_ibz)
1007 : end if
1008 :
1009 : ! W contains Em1 and is ready to use.
1010 78 : screen%Fgg(iq_ibz)%has_mat = MAT_STORED
1011 : end do
1012 :
1013 : else
1014 :
1015 : ! Model dielectric function. Only epsm-1 is supported here.
1016 18 : call wrtout(std_out," Calculating model dielectric function... ")
1017 18 : ABI_CHECK(screen%nomega == 1, "Cannot use nomega > 1 in model dielectric function")
1018 :
1019 127 : do iq_ibz=1,nqibz
1020 109 : if (.not.screen%keep_qibz(iq_ibz)) CYCLE
1021 :
1022 : ! The wings are not used here.
1023 103 : nqlwl=0; is_qeq0= (normv(screen%qibz(:,iq_ibz),Cryst%gmet,'G')<GW_TOLQ0)
1024 :
1025 : ! Calculate the model. Note that mdielf awaits an index in the BZ.
1026 103 : found = qmesh%has_bz_item(Qmesh%ibz(:,iq_ibz),iq_bz,g0)
1027 412 : if (.not.found .or. any(g0 /= 0)) then
1028 0 : ABI_ERROR("Problem in retrieving ibz points")
1029 : end if
1030 :
1031 : ! Allocate F_{GG'}(w).
1032 103 : call screen%Fgg(iq_ibz)%init(npw, nomega, nqlwl)
1033 :
1034 103 : eps_inf = screen%info%eps_inf
1035 103 : mdf_type = screen%info%use_mdf
1036 : !em1_ggw => screen%Fgg(iq_ibz)%mat
1037 :
1038 : ! Construct W TODO check the new implementation.
1039 : call screen_mdielf(iq_bz,npw,nomega,mdf_type,eps_inf,Cryst,Qmesh,Vcp,Gsph,&
1040 103 : nspden,nfftf_tot,ngfftf,ae_rhor,"EM1",screen%Fgg(iq_ibz)%mat,comm)
1041 :
1042 103 : screen%Fgg(iq_ibz)%has_mat = MAT_STORED
1043 :
1044 121 : if (screen%prtvol > 0) then
1045 0 : do iw=1,nomega
1046 0 : write(msg,'(a,i3,a,i4,a)')' Model symmetrical e^{-1} (q=',iq_ibz,', omega=',iw,', G,G'')'
1047 0 : call wrtout(std_out,msg)
1048 0 : call print_arr([std_out], screen%Fgg(iq_ibz)%mat(:,:,iw))
1049 : end do
1050 : end if
1051 : end do ! iq_ibz
1052 : end if
1053 :
1054 : ! Init plasmon-pole parameters from em1.
1055 29 : if (screen%has_ppmodel > 0) then
1056 0 : call wrtout(std_out, " Calling ppm_init ...")
1057 0 : ppmodel = screen%info%use_ppm; drude_plsmf = screen%info%drude_plsmf
1058 0 : call screen%ppm%init(screen%mqmem, screen%nqibz, screen%npw, ppmodel, drude_plsmf, screen%info%invalid_freq)
1059 : !call screen%ppm%print(units)
1060 :
1061 0 : do iq_ibz=1,nqibz
1062 0 : if (screen%ihave_fgg(iq_ibz, how="Stored")) then
1063 : !call wrtout(std_out, sjoin(" Calling ppm%new_setup for iq_ibz:", itoa(iq_ibz)))
1064 : call screen%ppm%new_setup(iq_ibz, Cryst, Qmesh, npw, nomega, screen%omega, &
1065 0 : screen%Fgg(iq_ibz)%mat, nfftf_tot, Gsph%gvec, ngfftf, screen%ae_rhor(:,1))
1066 : end if
1067 : end do
1068 :
1069 : end if
1070 : !stop
1071 :
1072 : ! Deallocate Fgg if the matrices are not needed anymore.
1073 : if (free_Fgg) then
1074 : call screen_fgg_qbz_set(screen, 0, 0, "Pointer") ! Avoid dangling pointer.
1075 : call fgg_free(screen%Fgg, keep_qibz=screen%keep_qibz)
1076 : end if
1077 :
1078 29 : if (from_file) call Hscr%free()
1079 :
1080 29 : call pstat_proc%print(_PSTAT_ARGS_)
1081 :
1082 : DBG_EXIT("COLL")
1083 :
1084 29 : end subroutine screen_init
1085 : !!***
1086 :
1087 : !----------------------------------------------------------------------
1088 :
1089 : !!****f* m_screen/screen_rotate_iqbz
1090 : !! NAME
1091 : !! screen_rotate_iqbz
1092 : !!
1093 : !! FUNCTION
1094 : !! Modify the status of the object so that the symmetrized component F(q_bz)_GG' is calculated
1095 : !! (if needed) and is made available in the internal buffer. This routine must be called before
1096 : !! performing any operation that involves the symmetrized component of the two-point function.
1097 : !!
1098 : !! INPUTS
1099 : !! iq_bz=Index of the q-point in the BZ where F(q_bz)_GG' is wanted.
1100 : !! Cryst=Crystal structure.
1101 : !! Gsph=The G-sphere
1102 : !! Qmesh=Structure defining the q-mesh used for sampling the BZ.
1103 : !!
1104 : !! SIDE EFFECTS
1105 : !! screen%ppm
1106 : !! screen%Fgg_qbz
1107 : !!
1108 : !! NOTES
1109 : !! In the present implementation, we are not considering a possible umklapp vector G0 in the
1110 : !! expression Sq = q+G0. Treating this case would require some changes in the G-sphere
1111 : !! since we have to consider G-G0. The code however stops in sigma if a nonzero G0 is required
1112 : !! to reconstruct the BZ.
1113 : !!
1114 : !! SOURCE
1115 :
1116 22740 : subroutine screen_rotate_iqbz(screen, iq_bz, Cryst, Gsph, Qmesh, Vcp)
1117 :
1118 : !Arguments ------------------------------------
1119 : !scalars
1120 : class(screen_t),intent(inout) :: screen
1121 : integer,intent(in) :: iq_bz
1122 : type(crystal_t),intent(in) :: Cryst
1123 : type(gsphere_t),intent(in) :: Gsph
1124 : type(kmesh_t),intent(in) :: Qmesh
1125 : type(vcoul_t),intent(in) :: Vcp
1126 :
1127 : !Local variables-------------------------------
1128 : !scalars
1129 : integer,parameter :: nqlwl0=0
1130 : integer :: iq_ibz,isym_q,itim_q,npw,nomega,nqibz,mdf_type
1131 : real(dp) :: eps_inf
1132 : logical :: q_isirred
1133 : !character(len=500) :: msg
1134 : !arrays
1135 : real(dp) :: qbz(3)
1136 : ! *********************************************************************
1137 :
1138 : DBG_ENTER("COLL")
1139 :
1140 22740 : npw = screen%npw; nqibz = screen%nqibz; nomega = screen%nomega
1141 22740 : call qmesh%get_bz_item(iq_bz, qbz, iq_ibz, isym_q, itim_q, isirred=q_isirred)
1142 :
1143 : ! ========================================================
1144 : ! ==== Branching for in-core or out-of-core solutions ====
1145 : ! ========================================================
1146 22740 : if (screen%ihave_fgg(iq_ibz, how="Stored")) then
1147 :
1148 22212 : if (q_isirred) then
1149 : ! Symmetrization is not needed. Target the data in memory.
1150 2629 : call screen_fgg_qbz_set(screen, iq_bz, nqlwl0, "Pointer")
1151 2629 : screen%Fgg_qbz => screen%Fgg(iq_ibz)
1152 : else
1153 : ! Allocate space. ! TODO Wings are not symmetrized but oh well
1154 19583 : call screen_fgg_qbz_set(screen, iq_bz, nqlwl0, "Allocate") ! Dimensions should not be changed.
1155 :
1156 : ! Out-of-place symmetrization.
1157 : !em1_qibz => screen%Fgg(iq_ibz)%mat; em1_qbz => screen%Fgg_qbz%mat
1158 19583 : call em1_symmetrize_op(iq_bz, npw, nomega, Gsph, Qmesh, screen%Fgg(iq_ibz)%mat, screen%Fgg_qbz%mat)
1159 : end if
1160 :
1161 22212 : if (screen%has_ppmodel > 0) then
1162 : ! Symmetrize the ppmodel tables: em1_qibz => W%Fgg(iq_ibz)%mat
1163 : call screen%ppm%rotate_iqbz(iq_bz, Cryst, Qmesh, Gsph, npw, nomega, screen%omega, screen%Fgg(iq_ibz)%mat, &
1164 0 : screen%nfftf_tot, screen%ngfftf, screen%ae_rhor(:,1))
1165 :
1166 : !call screen%ppm_get_qbz(Gsph, Qmesh, iq_bz, botsq_qbz, otq_qbz, eig_qbz)
1167 : end if
1168 :
1169 528 : else if (screen%ihave_fgg(iq_ibz, how="Allocated")) then
1170 0 : ABI_ERROR("Fgg_iqibz is allocated but not initialized!")
1171 :
1172 : else
1173 : ! Out of core branch
1174 :
1175 528 : if (screen%fgg_qbz_idx /= iq_bz) then
1176 : ! Must compute em1_qbz here. em1_qbz => W%Fgg_qbz%mat
1177 : ! Allocate the BZ buffer.
1178 528 : call screen_fgg_qbz_set(screen, iq_bz, nqlwl0, "Allocate")
1179 :
1180 528 : if (screen%info%use_mdf /= MDL_NONE) then
1181 : ! Compute the model-dielectric function at qbz on-the fly and in sequential
1182 : !call wrtout(std_out,"Will compute MDF on the fly")
1183 : call screen_mdielf(iq_bz,npw,nomega,screen%info%use_mdf,screen%info%eps_inf,Cryst,Qmesh,Vcp,Gsph,&
1184 : screen%nspden,screen%nfftf_tot,screen%ngfftf,screen%ae_rhor,"EM1", &
1185 528 : screen%Fgg_qbz%mat,xmpi_comm_self)
1186 :
1187 : else
1188 : ! Read W(q_ibz) and symmetrize it (do this only if we don't have the correct q_bz in memory).
1189 0 : call wrtout(std_out,sjoin("Out of core with file: ",screen%fname))
1190 : call read_screening(em1_ncname, screen%fname, npw, 1, nomega, screen%Fgg_qbz%mat, &
1191 0 : screen%iomode, xmpi_comm_self, iqiA=iq_ibz)
1192 :
1193 : ! In-place symmetrization to get the q-point in the BZ.
1194 0 : if (.not. q_isirred) then
1195 0 : call em1_symmetrize_ip(iq_bz, npw, nomega, Gsph, Qmesh, screen%Fgg_qbz%mat)
1196 : end if
1197 : end if
1198 :
1199 528 : screen%Fgg_qbz%has_mat = MAT_STORED
1200 : end if
1201 :
1202 528 : ABI_CHECK(screen%Fgg_qbz%has_mat == MAT_STORED, "Wrong has_mat")
1203 :
1204 : ! Ppmodel calculations with ppm tables in memory.
1205 : ! TODO treat the case in which IBZ tables are stored in memory.
1206 528 : if (screen%has_ppmodel > 0) then
1207 0 : ABI_ERROR("Not implemented error")
1208 : ! Symmetrize the ppmodel using em1_qibz.
1209 : call screen%ppm%rotate_iqbz(iq_bz, Cryst, Qmesh, Gsph, npw, nomega, screen%omega, &
1210 0 : screen%Fgg_qbz%mat, screen%nfftf_tot, screen%ngfftf, screen%ae_rhor(:,1))
1211 : end if
1212 : end if
1213 :
1214 : ! Calculate model dielectric function for this q-point in the BZ.
1215 22740 : eps_inf = screen%info%eps_inf; mdf_type = screen%info%use_mdf
1216 :
1217 : ! Model dielectric function. Only epsm-1 is supported here.
1218 : !call wrtout(std_out," Calculating model dielectric function... ")
1219 : !ABI_CHECK(W%nomega==1,"Cannot use nomega>1 in model dielectric function")
1220 :
1221 : ! screen%Fgg_qbz%mat
1222 :
1223 : !% call screen_mdielf(iq_bz,npw,nomega,mdf_type,eps_inf,Cryst,Qmesh,Vcp,Gsph,&
1224 : !% & screen%nspden,screen%nfftf_tot,screen%ngfftf,screen%ae_rhor,"EM1",em1_qbz,xmpi_comm_self)
1225 :
1226 : ! Store the index of the q-point in the BZ for checking purpose.
1227 22740 : screen%fgg_qbz_idx = iq_bz
1228 :
1229 : DBG_EXIT("COLL")
1230 :
1231 22740 : end subroutine screen_rotate_iqbz
1232 : !!***
1233 :
1234 : !----------------------------------------------------------------------
1235 :
1236 : !!****f* m_screen/screen_w0gemv
1237 : !! NAME
1238 : !! screen_w0gemv
1239 : !!
1240 : !! FUNCTION
1241 : !! Perform the matrix multiplication W x vector in reciprocal space.
1242 : !!
1243 : !! INPUTS
1244 : !! in_npw=Number of G vectors in in_ket
1245 : !! nspinor=Number of spinorial components.
1246 : !! in_ket(in_npw)= |\phi> in reciprocal space.
1247 : !! trans= On entry, TRANS specifies the operation to be performed as follows:
1248 : !! TRANS = 'N' or 'n' y := alpha*A*x + beta*y.
1249 : !! TRANS = 'T' or 't' y := alpha*A**T*x + beta*y.
1250 : !! TRANS = 'C' or 'c' y := alpha*A**H*x + beta*y.
1251 : !!
1252 : !! OUTPUT
1253 : !! out_ket(in_npw)= W |\phi\> in reciprocal space.
1254 : !! ZGEMV performs one of the matrix-vector operations
1255 : !! *
1256 : !! * y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, or
1257 : !! *
1258 : !! * y := alpha*A**H*x + beta*y,
1259 : !! *
1260 : !! * where alpha and beta are scalars, x and y are vectors and A is an m by n matrix.
1261 : !!
1262 : !! SOURCE
1263 :
1264 217920 : subroutine screen_w0gemv(screen, trans, in_npw, nspinor, only_diago, alpha, beta, in_ket, out_ket)
1265 :
1266 : !Arguments ------------------------------------
1267 : !scalars
1268 : class(screen_t),intent(in) :: screen
1269 : integer,intent(in) :: in_npw,nspinor
1270 : complex(gwp),intent(in) :: alpha,beta
1271 : logical,intent(in) :: only_diago
1272 : character(len=*),intent(in) :: trans
1273 : !arrays
1274 : complex(gwp),intent(in) :: in_ket(in_npw*nspinor)
1275 : complex(gwp),intent(out) :: out_ket(in_npw*nspinor)
1276 :
1277 : !Local variables-------------------------------
1278 : !scalars
1279 : integer :: ig,lda
1280 : !arrays
1281 217920 : complex(gwp),contiguous, pointer :: em1_qbz(:,:)
1282 : ! *************************************************************************
1283 :
1284 217920 : lda = screen%npw; em1_qbz => screen%Fgg_qbz%mat(:,:,1)
1285 :
1286 217920 : if (.not.only_diago) then
1287 190880 : call xgemv(trans,in_npw,in_npw,alpha,em1_qbz,lda,in_ket,1,beta,out_ket,1)
1288 :
1289 : else
1290 27040 : if (beta /= czero_gw) then
1291 0 : if (firstchar(trans, (/"C"/))) then
1292 0 : do ig=1,in_npw
1293 0 : out_ket(ig) = alpha * CONJG(em1_qbz(ig,ig)) * in_ket(ig) + beta * out_ket(ig)
1294 : end do
1295 0 : else if (firstchar(trans, (/"N","T"/))) then
1296 0 : do ig=1,in_npw
1297 0 : out_ket(ig) = alpha * em1_qbz(ig,ig) * in_ket(ig) + beta * out_ket(ig)
1298 : end do
1299 : else
1300 0 : ABI_ERROR(sjoin("Wrong trans:", trans))
1301 : end if
1302 :
1303 : else
1304 : ! beta == 0
1305 54080 : if (firstchar(trans, (/"C"/)) ) then
1306 757120 : do ig=1,in_npw
1307 757120 : out_ket(ig) = alpha * CONJG(em1_qbz(ig,ig)) * in_ket(ig)
1308 : end do
1309 0 : else if (firstchar(trans, (/"N","T"/))) then
1310 0 : do ig=1,in_npw
1311 0 : out_ket(ig) = alpha * em1_qbz(ig,ig) * in_ket(ig)
1312 : end do
1313 : else
1314 0 : ABI_ERROR(sjoin("Wrong trans:", trans))
1315 : end if
1316 : end if
1317 : end if
1318 :
1319 217920 : end subroutine screen_w0gemv
1320 : !!***
1321 :
1322 : !----------------------------------------------------------------------
1323 :
1324 : !!****f* m_screen/screen_calc_sigc
1325 : !! NAME
1326 : !! screen_calc_sigc
1327 : !!
1328 : !! FUNCTION
1329 : !!
1330 : !! INPUTS
1331 : !! npw_c=Number of G vectors in in_ket
1332 : !! nspinor=Number of spinorial components.
1333 : !! in_ket(npw_c)= |\phi> in reciprocal space.
1334 : !! trans= On entry, TRANS specifies the operation to be performed as follows:
1335 : !! TRANS = 'N' or 'n' y := alpha*A*x + beta*y.
1336 : !! TRANS = 'T' or 't' y := alpha*A**T*x + beta*y.
1337 : !! TRANS = 'T' or 't' y := alpha*A**T*x + beta*y.
1338 : !!
1339 : !! OUTPUT
1340 : !!
1341 : !! SOURCE
1342 :
1343 0 : subroutine screen_calc_sigc(screen, trans, nomega, omegame0i, theta_mu_minus_e0i, zcut, &
1344 0 : nspinor, npw_x, npw_c, rhotwgp, out_ket, sigcme)
1345 :
1346 : !Arguments ------------------------------------
1347 : !scalars
1348 : class(screen_t),intent(in) :: screen
1349 : character(len=*),intent(in) :: trans
1350 : integer,intent(in) :: nomega, nspinor, npw_x, npw_c
1351 : real(dp),intent(in) :: theta_mu_minus_e0i, zcut
1352 : !arrays
1353 : real(dp),intent(in) :: omegame0i(nomega)
1354 : complex(gwp),intent(in) :: rhotwgp(npw_x*nspinor)
1355 : complex(gwp),intent(inout) :: out_ket(npw_c*nspinor, nomega)
1356 : complex(gwp),intent(out) :: sigcme(nomega)
1357 :
1358 : !Local variables-------------------------------
1359 0 : complex(gwp),allocatable :: botsq_conjg_transp(:,:), otq_transp(:,:)
1360 : ! *************************************************************************
1361 :
1362 0 : out_ket = czero_gw
1363 :
1364 0 : select case (screen%info%wint_method)
1365 :
1366 : case (WINT_PPMODEL)
1367 : !call wrtout(std_out, "screen in WINT_PPMODEL")
1368 0 : ABI_CHECK_IGE(screen%has_ppmodel, 0, "has_ppmodel should be > 0")
1369 :
1370 0 : select case (trans)
1371 : case ("N")
1372 : associate (botsq => screen%ppm%bigomegatwsq_qbz_vals, &
1373 : otq => screen%ppm%omegatw_qbz_vals, &
1374 0 : eig => screen%ppm%eigpot_qbz_vals)
1375 :
1376 : call screen%ppm%calc_sigc(nspinor, npw_c, nomega, rhotwgp, botsq, otq, &
1377 0 : omegame0i, zcut, theta_mu_minus_e0i, eig, npw_x, out_ket, sigcme)
1378 :
1379 : end associate
1380 :
1381 : case ("T")
1382 : associate (ppm => screen%ppm, &
1383 : botsq => screen%ppm%bigomegatwsq_qbz_vals, &
1384 : otq => screen%ppm%omegatw_qbz_vals, &
1385 0 : eig => screen%ppm%eigpot_qbz_vals)
1386 :
1387 0 : ABI_MALLOC(botsq_conjg_transp,(PPm%dm2_botsq,npw_c))
1388 0 : botsq_conjg_transp=TRANSPOSE(botsq) ! Keep these two lines separated, otherwise gfortran messes up
1389 : !botsq_conjg_transp=CONJG(botsq_conjg_transp)
1390 0 : ABI_MALLOC(otq_transp,(ppm%dm2_otq, ppm%npwc))
1391 0 : otq_transp=TRANSPOSE(otq)
1392 :
1393 : call screen%ppm%calc_sigc(nspinor, npw_c, nomega, rhotwgp, botsq_conjg_transp, otq_transp, &
1394 0 : omegame0i, zcut, theta_mu_minus_e0i, eig, npw_x, out_ket, sigcme)
1395 :
1396 0 : ABI_FREE(botsq_conjg_transp)
1397 0 : ABI_FREE(otq_transp)
1398 : end associate
1399 :
1400 : case default
1401 0 : ABI_ERROR(sjoin("Invalid trans:", trans))
1402 : end select
1403 :
1404 : case default
1405 0 : ABI_ERROR(sjoin("Unsupported wint_method:", itoa(screen%info%wint_method)))
1406 : end select
1407 :
1408 0 : end subroutine screen_calc_sigc
1409 : !!***
1410 :
1411 : !----------------------------------------------------------------------
1412 :
1413 :
1414 : !!****f* m_screen/em1_symmetrize_ip
1415 : !! NAME
1416 : !! em1_symmetrize_ip
1417 : !!
1418 : !! FUNCTION
1419 : !! Symmetrizes the two-point function in G-space. Symmetrization is done
1420 : !! inplace through an auxiliary work array of dimension (npw_c,npw_c)
1421 : !!
1422 : !! INPUTS
1423 : !! nomega=All frequencies from 1 up to nomega are symmetrized.
1424 : !! npw_c=Number of G vectors in the symmetrized matrix.
1425 : !! Gsph<gsphere_t>=data related to the G-sphere
1426 : !! Qmesh<kmesh_t>=Structure defining the q-mesh used for Er.
1427 : !! iq_bz=Index of the q-point in the BZ where epsilon^-1 is required.
1428 : !!
1429 : !! SIDE EFFECTS
1430 : !! epsm1(npw_c,npw_c,nomega)
1431 : !! input: filled with the matrix at the q-point that has to be symmetrized.
1432 : !! output: symmetrised matrix.
1433 : !!
1434 : !! NOTES
1435 : !! In the present implementation we are not considering a possible umklapp vector G0 in the
1436 : !! expression Sq = q+G0. Treating this case would require some changes in the G-sphere
1437 : !! since we have to consider G-G0. The code however stops in sigma if a nonzero G0 is required
1438 : !! to reconstruct the BZ.
1439 : !!
1440 : !! * Remember the symmetry properties of E
1441 : !! If q_bz=Sq_ibz+G0:
1442 : !!
1443 : !! $ E_{SG1-G0,SG2-G0}(q_bz) = e^{+iS(G2-G1).\tau} E_{G1,G2)}(q)
1444 : !!
1445 : !! The invariance under exchange of the real space position E(1,2) = E(2,1) leads to:
1446 : !! $ E_{-G2,-G1}(-q) = E_{G1,G2)
1447 : !!
1448 : !! SOURCE
1449 :
1450 0 : subroutine em1_symmetrize_ip(iq_bz, npw_c, nomega, Gsph, Qmesh, epsm1)
1451 :
1452 : !Arguments ------------------------------------
1453 : !scalars
1454 : integer,intent(in) :: iq_bz,nomega,npw_c
1455 : type(gsphere_t),intent(in) :: Gsph
1456 : type(kmesh_t),intent(in) :: Qmesh
1457 : !arrays
1458 : complex(gwp),intent(inout) :: epsm1(npw_c,npw_c,nomega)
1459 :
1460 : !Local variables-------------------------------
1461 : !scalars
1462 : integer :: iw,g1,g2,isg1,isg2,iq_ibz,itim_q,isym_q,ierr
1463 : logical :: q_isirred
1464 : complex(gwp) :: phmsg1t,phmsg2t_star
1465 : !character(len=500) :: msg
1466 : !arrays
1467 : real(dp) :: qbz(3)
1468 0 : complex(gwp),allocatable :: work(:,:)
1469 : ! *********************************************************************
1470 :
1471 : ! Get iq_ibz, and symmetries from iq_ibz.
1472 0 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q,isirred=q_isirred)
1473 :
1474 0 : if (q_isirred) RETURN ! Nothing to do
1475 :
1476 : !write(msg,'(a,f8.2,a)')" out of memory in work , requiring ",npw_c**2*gwp*b2Mb," Mb"
1477 0 : ABI_MALLOC_OR_DIE(work, (npw_c,npw_c), ierr)
1478 :
1479 : !$OMP PARALLEL DO PRIVATE(isg2,isg1,phmsg1t,phmsg2t_star,work) IF (nomega > 1)
1480 0 : do iw=1,nomega
1481 0 : do g2=1,npw_c
1482 0 : isg2 = Gsph%rottb(g2,itim_q,isym_q)
1483 0 : phmsg2t_star = CONJG(Gsph%phmSGt(g2,isym_q))
1484 0 : do g1=1,npw_c
1485 0 : isg1 = Gsph%rottb(g1,itim_q,isym_q)
1486 0 : phmsg1t = Gsph%phmSGt(g1,isym_q)
1487 0 : work(isg1,isg2) = epsm1(g1,g2,iw) * phmsg1t * phmsg2t_star
1488 : end do
1489 : end do
1490 0 : epsm1(:,:,iw) = work
1491 : end do
1492 :
1493 0 : ABI_FREE(work)
1494 :
1495 : ! Account for time-reversal
1496 0 : if (itim_q==2) then
1497 : !$OMP PARALLEL DO IF (nomega > 1)
1498 0 : do iw=1,nomega
1499 0 : call sqmat_itranspose(npw_c, epsm1(:,:,iw))
1500 : end do
1501 : end if
1502 :
1503 : end subroutine em1_symmetrize_ip
1504 : !!***
1505 :
1506 : !----------------------------------------------------------------------
1507 :
1508 : !!****f* m_screen/em1_symmetrize_op
1509 : !! NAME
1510 : !! em1_symmetrize_op
1511 : !!
1512 : !! FUNCTION
1513 : !! Symmetrizes the two-point function in G-space. Symmetrization is done outofplace.
1514 : !!
1515 : !! INPUTS
1516 : !! nomega=All frequencies from 1 up to nomega are symmetrized.
1517 : !! npw_c=Number of G vectors in the symmetrized matrix.
1518 : !! Gsph<gsphere_t>=data related to the G-sphere
1519 : !! Qmesh<kmesh_t>=Structure defining the q-mesh used for Er.
1520 : !! iq_bz=Index of the q-point in the BZ where epsilon^-1 is required.
1521 : !! in_epsm1(npw_c,npw_c,nomega)
1522 : !!
1523 : !! OUTPUT
1524 : !! out_epsm1(npw_c,npw_c,nomega)
1525 : !!
1526 : !! NOTES
1527 : !! In the present implementation we are not considering a possible umklapp vector G0 in the
1528 : !! expression Sq = q+G0. Treating this case would require some changes in the G-sphere
1529 : !! since we have to consider G-G0. The code however stops in sigma if a nonzero G0 is required
1530 : !! to reconstruct the BZ.
1531 : !!
1532 : !! * Remember the symmetry properties of E
1533 : !! If q_bz=Sq_ibz+G0:
1534 : !!
1535 : !! $ E_{SG1-G0,SG2-G0}(q_bz) = e^{+iS(G2-G1).\tau} E_{G1,G2)}(q)
1536 : !!
1537 : !! The invariance under exchange of the real space position E(1,2) = E(2,1) leads to:
1538 : !! $ E_{-G2,-G1}(-q) = E_{G1,G2)
1539 : !!
1540 : !! SOURCE
1541 :
1542 19583 : subroutine em1_symmetrize_op(iq_bz, npw_c, nomega, Gsph, Qmesh, in_epsm1, out_epsm1)
1543 :
1544 : !Arguments ------------------------------------
1545 : !scalars
1546 : integer,intent(in) :: iq_bz,nomega,npw_c
1547 : type(gsphere_t),target,intent(in) :: Gsph
1548 : type(kmesh_t),intent(in) :: Qmesh
1549 : !arrays
1550 : complex(gwp),intent(in) :: in_epsm1(npw_c,npw_c,nomega)
1551 : complex(gwp),intent(out) :: out_epsm1(npw_c,npw_c,nomega)
1552 :
1553 : !Local variables-------------------------------
1554 : !scalars
1555 : integer :: iw,g1,g2,isg1,isg2,iq_ibz,itim_q,isym_q
1556 : logical :: q_isirred
1557 : complex(gwp) :: phmsg1t,phmsg2t_star
1558 : !arrays
1559 : real(dp) :: qbz(3)
1560 : ! *********************************************************************
1561 :
1562 : ! Get iq_ibz, and symmetries from iq_ibz.
1563 19583 : call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q,isirred=q_isirred)
1564 :
1565 19583 : if (q_isirred) then
1566 0 : out_epsm1 = in_epsm1; return
1567 : end if
1568 :
1569 : ! grottb is a 1-1 mapping.
1570 : !$OMP PARALLEL DO PRIVATE(isg1,isg2,phmsg1t,phmsg2t_star) COLLAPSE(2) IF (nomega > 1)
1571 39166 : do iw=1,nomega
1572 921363 : do g2=1,npw_c
1573 882197 : isg2 = Gsph%rottb(g2,itim_q,isym_q)
1574 882197 : phmsg2t_star = CONJG(Gsph%phmSGt(g2,isym_q))
1575 44918267 : do g1=1,npw_c
1576 44016487 : isg1 = Gsph%rottb(g1,itim_q,isym_q)
1577 44016487 : phmsg1t = Gsph%phmSGt(g1,isym_q)
1578 44898684 : out_epsm1(isg1,isg2,iw) = in_epsm1(g1,g2,iw) * phmsg1t * phmsg2t_star
1579 : end do
1580 : end do
1581 : end do
1582 :
1583 : ! Account for time-reversal
1584 19583 : if (itim_q==2) then
1585 : !$OMP PARALLEL DO IF (nomega > 1)
1586 0 : do iw=1,nomega
1587 0 : call sqmat_itranspose(npw_c, out_epsm1(:,:,iw))
1588 : end do
1589 : end if
1590 :
1591 : end subroutine em1_symmetrize_op
1592 : !!***
1593 :
1594 : !----------------------------------------------------------------------
1595 :
1596 87 : end module m_screen
1597 : !!***
|