LCOV - code coverage report
Current view: top level - src/70_gw - m_screen.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.4 % 348 245
Test Date: 2026-09-21 13:49:52 Functions: 65.0 % 20 13

            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              : !!***
        

Generated by: LCOV version 2.3-1