LCOV - code coverage report
Current view: top level - src/49_gw_toolbox_oop - m_melemts.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.2 % 236 201
Test Date: 2026-09-21 22:40:37 Functions: 75.0 % 12 9

            Line data    Source code
       1              : !!****m* ABINIT/m_melemts
       2              : !! NAME
       3              : !!  m_melemts
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module defines an object used as database to store matrix
       7              : !!  elements of several potentials and operators between two Bloch states.
       8              : !!  These values are used in the GW part of abinit to evaluate QP energies
       9              : !!  using the perturbative approach.
      10              : !!
      11              : !! COPYRIGHT
      12              : !! Copyright (C) 2008-2026 ABINIT group (MG)
      13              : !! This file is distributed under the terms of the
      14              : !! GNU General Public License, see ~abinit/COPYING
      15              : !! or http://www.gnu.org/copyleft/gpl.txt .
      16              : !!
      17              : !! TODO
      18              : 
      19              : !! NOTES
      20              : !!  * This module is supposed to be used only in the GW part to facilitate
      21              : !!    we might decide to use ragged arrays
      22              : !!
      23              : !!     Mels(nkcalc, nsppol*nspinor**2)%data
      24              : !!
      25              : !!    or replaced nkibz with nkcalc with reduce memory
      26              : !!
      27              : !! SOURCE
      28              : 
      29              : #if defined HAVE_CONFIG_H
      30              : #include "config.h"
      31              : #endif
      32              : 
      33              : #include "abi_common.h"
      34              : 
      35              : module m_melemts
      36              : 
      37              :  use defs_basis
      38              :  use m_errors
      39              :  use m_xmpi
      40              :  use m_abicore
      41              : 
      42              :  use m_fstrings,       only : tolower, sjoin
      43              :  use m_numeric_tools,  only : print_arr
      44              : 
      45              :  implicit none
      46              : 
      47              :  private
      48              : !!***
      49              : 
      50              : !----------------------------------------------------------------------
      51              : 
      52              : !!****t* m_melemts/melflags_t
      53              : !! NAME
      54              : !!
      55              : !! FUNCTION
      56              : !!  Container for the flags defining the status of the corresponding
      57              : !!  pointer defined in the type melements_t. Possible values are:
      58              : !!    * 0 if the correspondending array is not allocated.
      59              : !!    * 1 if allocated but not yet calculated.
      60              : !!    * 2 if allocated and calculated
      61              : !!
      62              : !! SOURCE
      63              : 
      64              :  type,public :: melflags_t
      65              : 
      66              :   integer :: has_kinetic = 0
      67              :   integer :: has_hbare = 0
      68              :   integer :: has_lexexch = 0
      69              :   integer :: has_sxcore = 0
      70              :   integer :: has_vhartree = 0
      71              :   integer :: has_vu = 0
      72              :   integer :: has_vxc = 0
      73              :   integer :: has_vxcval = 0
      74              :   integer :: has_vxcval_hybrid = 0
      75              :   integer :: only_diago = 0
      76              :   ! 1 if only diagonal elements are calculated
      77              : 
      78              :   contains
      79              :     procedure :: reset => melflags_reset  ! Reset the value of the flags.
      80              :     procedure :: copy  => melflags_copy   ! Copy the object
      81              :  end type melflags_t
      82              : !!***
      83              : 
      84              : !----------------------------------------------------------------------
      85              : 
      86              : !!****t* m_melemts/melements_t
      87              : !! NAME
      88              : !!
      89              : !! FUNCTION
      90              : !!  Structure defining a database to store the matrix elements of operators
      91              : !!  needed for GW calculations.
      92              : !!
      93              : !! SOURCE
      94              : 
      95              :  type,public :: melements_t
      96              : 
      97              :   integer :: nkibz
      98              :   ! Number of k-points in the IBZ.
      99              : 
     100              :   integer :: nsppol
     101              :   ! Number of independent spin-polarizations.
     102              : 
     103              :   integer :: nspinor
     104              :   ! 1 for collinear, 2 for noncollinear.
     105              : 
     106              :   integer :: nspden
     107              :   ! Number of independent spin-density components.
     108              : 
     109              :   integer :: bmin, bmax
     110              :   ! min and Max band index over k-points and spin.
     111              :   ! Used to dimension the arrays below.
     112              : 
     113              :   integer, allocatable :: bands_idx(:,:,:)
     114              :   ! (2, nkibz, nsppol)
     115              :   ! min and Max band index for each k-point and spin.
     116              : 
     117              :   integer, allocatable :: iscalc(:,:)
     118              :   ! (nkibz, nsppol)
     119              :   ! 1 if this k-point and spin has been calculated, 0 otherwise.
     120              : 
     121              :   real(dp), allocatable :: kibz(:,:)
     122              :   ! (3, nkibz)
     123              :   ! The list of k-points in reduced coordinates.
     124              : 
     125              :   complex(dp), allocatable :: kinetic(:,:,:,:)
     126              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     127              :   ! Matrix elements of the kinetic energy.
     128              : 
     129              :   complex(dp), allocatable :: hbare(:,:,:,:)
     130              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     131              :   ! Matrix elements of the bare Hamiltonian.
     132              : 
     133              :   complex(dp), allocatable :: sxcore(:,:,:,:)
     134              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     135              :   ! Matrix elements of the Fock operator generated by core electrons.
     136              : 
     137              :   complex(dp), allocatable :: vhartree(:,:,:,:)
     138              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     139              :   ! Matrix elements of the Hartree potential.
     140              : 
     141              :   complex(dp), allocatable :: vlexx(:,:,:,:)
     142              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     143              :   ! Matrix elements of the local exact exchange potential.
     144              : 
     145              :   complex(dp), allocatable :: vu(:,:,:,:)
     146              :   ! vu(b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     147              :   ! Matrix elements of the U Hamiltonian.
     148              : 
     149              :   complex(dp), allocatable :: vxc(:,:,:,:)
     150              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     151              :   ! Matrix elements of XC potential, including model core if present.
     152              : 
     153              :   complex(dp), allocatable :: vxcval(:,:,:,:)
     154              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     155              :   ! Matrix elements of the XC potential, valence-only contribution.
     156              : 
     157              :   complex(dp), allocatable :: vxcval_hybrid(:,:,:,:)
     158              :   ! (b1:b2, b1:b2, nkibz, nsppol*nspinor**2)
     159              :   ! Matrix elements of the XC potential for hybrid calculations, valence-only contribution.
     160              : 
     161              :   type(melflags_t) :: flags
     162              : 
     163              :  contains
     164              : 
     165              :    procedure :: init => melements_init        ! Initialize the object
     166              :    procedure :: free => melements_free        ! Free memory
     167              :    procedure :: herm => melements_herm        ! Construct the lower triangle from the upper triangle
     168              :    procedure :: mpisum => melements_mpisum    ! Perform a collective SUM within the MPI communicator comm
     169              :    procedure :: print => melements_print      ! Print matrix elements
     170              :    procedure :: zero => melements_zero        ! Set matrix elements connecting states with different irrep to zero.
     171              :    !procedure :: mels_get_exene_core
     172              : 
     173              :  end type melements_t
     174              : !!***
     175              : 
     176              :  integer,parameter,private :: NNAMES = 9
     177              :  integer,parameter,private :: NAMELEN = 13
     178              : 
     179              :  ! List of matrix element names.
     180              :  ! IMPORTANT: Remember to add a new entry here when you add a new matrix element.
     181              :  ! then change the routine my_select_melements accordingly.
     182              :  character(len=NAMELEN),parameter,private :: ANAMES(NNAMES) = [ &
     183              :    "vxc          ", &
     184              :    "vxcval       ", &
     185              :    "vxcval_hybrid", &
     186              :    "sxcore       ", &
     187              :    "vu           ", &
     188              :    "vlexx        ", &
     189              :    "vhartree     ", &
     190              :    "kinetic      ", &
     191              :    "hbare        "  &
     192              : ]
     193              : 
     194              : CONTAINS  !========================================================================================
     195              : 
     196              : !!****f* m_melemts/melflags_reset
     197              : !! NAME
     198              : !! melflags_reset
     199              : !!
     200              : !! FUNCTION
     201              : !!  Set all flags in melflags_t to 0.
     202              : !!
     203          839 : subroutine melflags_reset(Mflags)
     204              : 
     205              : !Arguments ------------------------------------
     206              :  class(melflags_t),intent(inout) :: Mflags
     207              : ! *************************************************************************
     208              : 
     209          839 :  Mflags%has_kinetic         = 0
     210          839 :  Mflags%has_hbare           = 0
     211          839 :  Mflags%has_sxcore          = 0
     212          839 :  Mflags%has_vhartree        = 0
     213          839 :  Mflags%has_vu              = 0
     214          839 :  Mflags%has_vxc             = 0
     215          839 :  Mflags%has_vxcval          = 0
     216          839 :  Mflags%has_vxcval_hybrid   = 0
     217          839 :  Mflags%has_lexexch         = 0
     218          839 :  Mflags%only_diago          = 0
     219              : 
     220          839 : end subroutine melflags_reset
     221              : !!***
     222              : 
     223              : !----------------------------------------------------------------------
     224              : 
     225              : !!****f* m_melemts/melflags_copy
     226              : !! NAME
     227              : !! melflags_copy
     228              : !!
     229              : !! FUNCTION
     230              : !!  Copy an object storing the flags.
     231              : !!
     232              : !! INPUTS
     233              : !!  Mflags_in=The flags to be copied.
     234              : !!
     235              : !! OUTPUT
     236              : !!  Mflags_out=The new set of flags.
     237              : !!
     238              : !! SOURCE
     239              : 
     240          281 : subroutine melflags_copy(Mflags_in, Mflags_out)
     241              : 
     242              : !Arguments ------------------------------------
     243              :  class(melflags_t),intent(in)    :: Mflags_in
     244              :  class(melflags_t),intent(inout) :: Mflags_out
     245              : ! *************************************************************************
     246              : 
     247          281 :  call Mflags_out%reset()
     248              : 
     249              :  ! @melflags_t
     250          281 :  Mflags_out%has_kinetic         = Mflags_in%has_kinetic
     251          281 :  Mflags_out%has_hbare           = Mflags_in%has_hbare
     252          281 :  Mflags_out%has_sxcore          = Mflags_in%has_sxcore
     253          281 :  Mflags_out%has_vhartree        = Mflags_in%has_vhartree
     254          281 :  Mflags_out%has_vu              = Mflags_in%has_vu
     255          281 :  Mflags_out%has_vxc             = Mflags_in%has_vxc
     256          281 :  Mflags_out%has_vxcval          = Mflags_in%has_vxcval
     257          281 :  Mflags_out%has_vxcval_hybrid   = Mflags_in%has_vxcval_hybrid
     258          281 :  Mflags_out%has_lexexch         = Mflags_in%has_lexexch
     259          281 :  Mflags_out%only_diago          = Mflags_in%only_diago
     260              : 
     261          281 : end subroutine melflags_copy
     262              : !!***
     263              : 
     264              : !----------------------------------------------------------------------
     265              : 
     266              : !!****f* m_melemts/melements_free
     267              : !! NAME
     268              : !! melements_free
     269              : !!
     270              : !! FUNCTION
     271              : !!  Free all dynamic memory of the database
     272              : !!
     273              : !! SOURCE
     274              : 
     275          281 : subroutine melements_free(Mels)
     276              : 
     277              : !Arguments ------------------------------------
     278              :  class(melements_t),intent(inout) :: Mels
     279              : ! *************************************************************************
     280              : 
     281              :  ! integer arrays
     282          281 :  ABI_SFREE(Mels%bands_idx)
     283          281 :  ABI_SFREE(Mels%iscalc)
     284              : 
     285              :  ! real arrays
     286          281 :  ABI_SFREE(Mels%kibz)
     287              : 
     288              :  ! complex arrays
     289          281 :  ABI_SFREE(Mels%kinetic)
     290          281 :  ABI_SFREE(Mels%hbare)
     291          281 :  ABI_SFREE(Mels%sxcore)
     292          281 :  ABI_SFREE(Mels%vhartree)
     293          281 :  ABI_SFREE(Mels%vlexx)
     294          281 :  ABI_SFREE(Mels%vu)
     295          281 :  ABI_SFREE(Mels%vxc)
     296          281 :  ABI_SFREE(Mels%vxcval)
     297          281 :  ABI_SFREE(Mels%vxcval_hybrid)
     298              : 
     299              :  ! Reset all has_* flags.
     300          281 :  call Mels%flags%reset()
     301              : 
     302          281 : end subroutine melements_free
     303              : !!***
     304              : 
     305              : !----------------------------------------------------------------------
     306              : 
     307              : !!****f* m_melemts/my_select_melements
     308              : !! NAME
     309              : !!  my_select_melements
     310              : !!
     311              : !! FUNCTION
     312              : !!  Helper function returning a pointer to the array "aname" as well as the status of the array
     313              : !!
     314              : !! INPUTS
     315              : !!  Mels<melements_t>=The database.
     316              : !!  aname=String with the name of the array.
     317              : !!
     318              : !! OUTPUT
     319              : !!  flag_p=Pointer to the integer defining the status of the array, see melflags_t.
     320              : !!  arr_p=The pointer to the array.
     321              : !!
     322              : !! SOURCE
     323              : 
     324         7551 : subroutine my_select_melements(Mels, aname, flag_p, arr_p)
     325              : 
     326              : !Arguments ------------------------------------
     327              : !scalars
     328              :  integer,pointer :: flag_p
     329              :  character(len=*),intent(in) :: aname
     330              :  type(melements_t),target,intent(in) :: Mels
     331              : !arrays
     332              :  complex(dp),contiguous, pointer :: arr_p(:,:,:,:)
     333              : ! *************************************************************************
     334              : 
     335        15941 :  SELECT CASE (tolower(aname))
     336              :  CASE ("kinetic")
     337          839 :    flag_p => Mels%flags%has_kinetic
     338          839 :    arr_p  => Mels%kinetic
     339              :  CASE ("hbare")
     340          839 :    flag_p => Mels%flags%has_hbare
     341          839 :    arr_p  => Mels%hbare
     342              :  CASE ("sxcore")
     343          839 :    flag_p => Mels%flags%has_sxcore
     344          839 :    arr_p  => Mels%sxcore
     345              :  CASE ("vhartree")
     346          839 :    flag_p => Mels%flags%has_vhartree
     347          839 :    arr_p  => Mels%vhartree
     348              :  CASE ("vlexx")
     349          839 :    flag_p => Mels%flags%has_lexexch
     350          839 :    arr_p  => Mels%vlexx
     351              :  CASE ("vu")
     352          839 :    flag_p => Mels%flags%has_vu
     353          839 :    arr_p  => Mels%vu
     354              :  CASE ("vxc")
     355          839 :    flag_p => Mels%flags%has_vxc
     356          839 :    arr_p  => Mels%vxc
     357              :  CASE ("vxcval")
     358          839 :    flag_p => Mels%flags%has_vxcval
     359          839 :    arr_p  => Mels%vxcval
     360              :  CASE ("vxcval_hybrid")
     361          839 :    flag_p => Mels%flags%has_vxcval_hybrid
     362          839 :    arr_p  => Mels%vxcval_hybrid
     363              :  CASE DEFAULT
     364         7551 :    ABI_ERROR(sjoin("Wrong aname: ", aname))
     365              :  END SELECT
     366              : 
     367         7551 : end subroutine my_select_melements
     368              : !!***
     369              : 
     370              : !----------------------------------------------------------------------
     371              : 
     372              : !!****f* m_melemts/melements_init
     373              : !! NAME
     374              : !! melements_init
     375              : !!
     376              : !! FUNCTION
     377              : !!  Initialize the database, allocate arrays according to
     378              : !!  Mflags_in, zeroing the content of the allocated arrays.
     379              : !!
     380              : !! INPUTS
     381              : !!  nsppol=Number of independent spin polarizations.
     382              : !!  nspden=Number of spin-density components
     383              : !!  nspinor=Number of spinor components
     384              : !!  band_idx=min and Max band index for each ik_ibz and spin
     385              : !!
     386              : !! OUTPUT
     387              : !!  Mels=The initialized database with dimensions and allocated memory.
     388              : !!
     389              : !! SOURCE
     390              : 
     391          281 : subroutine melements_init(Mels, Mflags_in, nsppol, nspden, nspinor, nkibz, kibz, bands_idx)
     392              : 
     393              : !Arguments ------------------------------------
     394              : !scalars
     395              :  class(melements_t),intent(out) :: Mels
     396              :  integer,intent(in) :: nspinor,nspden,nsppol,nkibz
     397              :  type(melflags_t),intent(in) :: Mflags_in
     398              : !arrays
     399              :  integer,intent(in) :: bands_idx(2, nkibz, nsppol)
     400              :  real(dp),intent(in) :: kibz(3,nkibz)
     401              : 
     402              : !Local variables-------------------------------
     403              :  integer :: ikibz,isppol,bmin,bmax,b1,b2
     404              : ! *************************************************************************
     405              : 
     406              :  ! Copy flags.
     407          281 :  call Mflags_in%copy(Mels%flags)
     408              : 
     409              :  ! Copy dimensions.
     410          281 :  Mels%nkibz   = nkibz
     411          281 :  Mels%nsppol  = nsppol
     412          281 :  Mels%nspinor = nspinor
     413          281 :  Mels%nspden  = nspden
     414              : 
     415         1124 :  ABI_MALLOC(Mels%bands_idx, (2, nkibz, nsppol))
     416         5976 :  Mels%bands_idx = bands_idx
     417              : 
     418         1124 :  ABI_MALLOC(Mels%iscalc,(nkibz, nsppol))
     419         2277 :  Mels%iscalc = 0
     420              : 
     421          281 :  bmin = HUGE(1); bmax =-HUGE(1)
     422          568 :  do isppol=1,Mels%nsppol
     423         2277 :    do ikibz=1,Mels%nkibz
     424         3274 :      if (ANY(Mels%bands_idx(:,ikibz,isppol)/=0)) then
     425         1070 :        b1 = Mels%bands_idx(1,ikibz,isppol)
     426         1070 :        b2 = Mels%bands_idx(2,ikibz,isppol)
     427         1070 :        Mels%iscalc(ikibz, isppol)=1
     428         1070 :        bmin = MIN(bmin,b1)
     429         1070 :        bmax = MAX(bmax,b2)
     430         1070 :        ABI_CHECK(b2 >= b1 .and. b1 > 0, "Wrong b1, b2")
     431              :      end if
     432              :    end do
     433              :  end do
     434              : 
     435          281 :  if (bmin==HUGE(1).or.bmax==-HUGE(1)) then
     436            0 :    ABI_BUG("Wrong bands_idx")
     437              :  end if
     438              : 
     439          281 :  Mels%bmin = bmin
     440          281 :  Mels%bmax = bmax
     441              : 
     442          281 :  b1 = Mels%bmin; b2 = Mels%bmax
     443              : 
     444              :  ! real arrays
     445          843 :  ABI_MALLOC(Mels%kibz, (3,nkibz))
     446         7350 :  Mels%kibz = kibz
     447              : 
     448              :  ! complex arrays
     449          281 :  if (Mels%flags%has_kinetic == 1) then
     450         3909 :    ABI_CALLOC(Mels%kinetic, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     451              :  end if
     452          281 :  if (Mels%flags%has_hbare == 1) then
     453         3909 :    ABI_CALLOC(Mels%hbare, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     454              :  end if
     455          281 :  if (Mels%flags%has_sxcore == 1) then
     456         1090 :    ABI_CALLOC(Mels%sxcore, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     457              :  end if
     458          281 :  if (Mels%flags%has_vhartree == 1) then
     459       160810 :    ABI_CALLOC(Mels%vhartree, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     460              :  end if
     461          281 :  if (Mels%flags%has_lexexch == 1) then
     462            0 :    ABI_CALLOC(Mels%vlexx, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     463              :  end if
     464          281 :  if (Mels%flags%has_vu == 1) then
     465            0 :    ABI_CALLOC(Mels%vu, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     466              :  end if
     467          281 :  if (Mels%flags%has_vxc == 1) then
     468       107903 :    ABI_CALLOC(Mels%vxc, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     469              :  end if
     470          281 :  if (Mels%flags%has_vxcval == 1) then
     471       107903 :    ABI_CALLOC(Mels%vxcval, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     472              :  end if
     473          281 :  if (Mels%flags%has_vxcval_hybrid == 1) then
     474        28278 :    ABI_CALLOC(Mels%vxcval_hybrid, (b1:b2,b1:b2,nkibz,nsppol*nspinor**2))
     475              :  end if
     476              : 
     477          281 : end subroutine melements_init
     478              : !!***
     479              : 
     480              : !----------------------------------------------------------------------
     481              : 
     482              : !!****f* m_melemts/melements_herm
     483              : !! NAME
     484              : !! melements_herm
     485              : !!
     486              : !! FUNCTION
     487              : !!  Reconstruc the lower triangle of all calculated arrays.
     488              : !!  Assuming Hermitian operator. Works both for collinear and non-collinear case.
     489              : !!
     490              : !! INPUTS
     491              : !!  Mels=The database
     492              : !!  [aname]=The name of the array to be symmetrized, by default all calculated arrays are filled.
     493              : !!
     494              : !! SIDE EFFECTS
     495              : !!  All arrays whose flag is 2, are filled assuming an Hermitian operator.
     496              : !!
     497              : !! SOURCE
     498              : 
     499          281 : subroutine melements_herm(Mels, aname)
     500              : 
     501              : !Arguments ------------------------------------
     502              : !scalars
     503              :  class(melements_t),intent(inout) :: Mels
     504              :  character(len=*),optional,intent(in) :: aname
     505              : 
     506              : !Local variables-------------------------------
     507              :  integer :: is,ik,ib,jb,iab,iab_tr,iname
     508              :  integer,pointer :: flag_p
     509              :  character(len=NAMELEN) :: key
     510              : !arrays
     511              :  integer,parameter :: trsp_idx(2:4) = [2,4,3]
     512          281 :  complex(dp),contiguous, pointer :: arr_p(:,:,:,:)
     513              : ! *************************************************************************
     514              : 
     515              :  ! === Symmetrize matrix elements ===
     516              :  ! * In the collinear case, generate the lower triangle by just doing a complex conjugate.
     517              :  ! * In the noncollinear case do also a transposition since A_{12}^{ab} = A_{21}^{ba}^*
     518              :  !   2-->2, 3-->4, 4-->3
     519              :  !
     520         2810 :  do iname=1,NNAMES
     521         2529 :    key = ANAMES(iname)
     522         2529 :    if (PRESENT(aname)) then
     523            0 :      if (key /= aname) CYCLE
     524              :    end if
     525              : 
     526         2529 :    call my_select_melements(Mels, key, flag_p, arr_p)
     527              : 
     528         2810 :    if (flag_p>0) then
     529         5230 :      do ik=1,Mels%nkibz
     530         9759 :        do is=1,Mels%nsppol
     531              : 
     532        43495 :          do jb=Mels%bmin,Mels%bmax
     533       215484 :            do ib=Mels%bmin,jb ! Upper triangle
     534              : 
     535       210955 :              if (ib/=jb) then
     536       142017 :                arr_p(jb,ib,ik,is)=CONJG(arr_p(ib,jb,ik,is))
     537       142017 :                if (Mels%nspinor==2) then
     538        29052 :                  do iab=2,4
     539        21789 :                    iab_tr=trsp_idx(iab)
     540        29052 :                    arr_p(jb,ib,ik,iab)=CONJG(arr_p(ib,jb,ik,iab_tr))
     541              :                  end do
     542              :                end if
     543              :              else ! For ib==jb force real-valued
     544        34469 :                arr_p(jb,ib,ik,is)=half*(arr_p(jb,ib,ik,is)+CONJG(arr_p(jb,ib,ik,is)))
     545        34469 :                if (Mels%nspinor==2) arr_p(jb,ib,ik,2)=half*(arr_p(ib,jb,ik,2)+CONJG(arr_p(ib,jb,ik,2)))
     546              :              end if
     547              : 
     548              :            end do !ib
     549              :          end do !jb
     550              : 
     551              :        end do !is
     552              :      end do !ik
     553              :    end if
     554              : 
     555              :  end do !inames
     556              : 
     557          281 : end subroutine melements_herm
     558              : !!***
     559              : 
     560              : !----------------------------------------------------------------------
     561              : 
     562              : !!****f* m_melemts/melements_mpisum
     563              : !! NAME
     564              : !! melements_mpisum
     565              : !!
     566              : !! FUNCTION
     567              : !!  Perform a collective SUM within the MPI communicator comm
     568              : !!  of the matrix elements stored in the database.
     569              : !!
     570              : !! INPUTS
     571              : !!  Mels=The database
     572              : !!  [aname]=The name of a particular array to be summed, by default
     573              : !!    all allocated arrays are considered.
     574              : !!
     575              : !! SIDE EFFECTS
     576              : !!  All arrays whose flag==1 are summed within the MPI communicator comm.
     577              : !!  In output the corresponding flas is set to 2.
     578              : !!
     579              : !! SOURCE
     580              : 
     581          281 : subroutine melements_mpisum(Mels, comm, aname)
     582              : 
     583              : !Arguments ------------------------------------
     584              : !scalars
     585              :  class(melements_t),intent(inout) :: Mels
     586              :  integer,intent(in) :: comm
     587              :  character(len=*),optional,intent(in) :: aname
     588              : 
     589              : !Local variables-------------------------------
     590              :  integer :: iname,ierr
     591              :  integer,pointer :: flag_p
     592              :  character(len=NAMELEN) :: key
     593              :  !character(len=500) :: msg
     594              : !arrays
     595          281 :  complex(dp),contiguous, pointer :: arr_p(:,:,:,:)
     596              : ! *************************************************************************
     597              : 
     598         2810 :  do iname=1,NNAMES
     599         2529 :    key = ANAMES(iname)
     600         2529 :    if (PRESENT(aname)) then
     601            0 :      if (key /= aname) CYCLE
     602              :    end if
     603              : 
     604         2529 :    call my_select_melements(Mels, key, flag_p, arr_p)
     605              : 
     606         2810 :    if (flag_p == 1) then
     607          733 :      call xmpi_sum(arr_p, comm, ierr)
     608          733 :      flag_p = 2 ! Tag this array as calculated
     609              :    end if
     610              :  end do
     611              : 
     612          281 : end subroutine melements_mpisum
     613              : !!***
     614              : 
     615              : !----------------------------------------------------------------------
     616              : 
     617              : !!****f* m_melemts/melements_print
     618              : !! NAME
     619              : !! melements_print
     620              : !!
     621              : !! FUNCTION
     622              : !!  Printout of the content of all calculated array.
     623              : !!  Optionally, it is possible to print the content of a single entry of the database.
     624              : !!
     625              : !! INPUTS
     626              : !!  Mels=The database
     627              : !!  [unit]=the unit number for output, defaults to std_out
     628              : !!  [prtvol]=verbosity level, defaults to 0
     629              : !!  [mode_paral]=either "COLL" or "PERS", default to "COLL"
     630              : !!  [header]=title for info
     631              : !!
     632              : !! OUTPUT
     633              : !!  Only writing
     634              : !!
     635              : !! SOURCE
     636              : 
     637            0 : subroutine melements_print(Mels, names_list, header, unit, prtvol, mode_paral)
     638              : 
     639              : !Arguments ------------------------------------
     640              : !scalars
     641              :  class(melements_t),intent(in) :: Mels
     642              :  integer,optional,intent(in) :: prtvol,unit
     643              :  character(len=*),optional,intent(in) :: names_list(:)
     644              :  character(len=*),optional,intent(in) :: header
     645              :  character(len=4),optional,intent(in) :: mode_paral
     646              : 
     647              : !Local variables-------------------------------
     648              :  integer :: my_unt,my_prtvol,max_r,max_c,ii, isppol,ikibz,iab,ib,b1,b2,my_nkeys,ikey
     649              :  integer,pointer :: flag_p
     650              :  character(len=4) :: my_mode
     651              :  character(len=NAMELEN) :: key
     652              :  character(len=500) :: msg,str,fmt
     653              : !arrays
     654          277 :  integer,allocatable :: tab(:)
     655          277 :  character(len=NAMELEN),allocatable :: my_keys(:)
     656          277 :  complex(dp),allocatable :: mat(:,:)
     657              : 
     658              :  type rarr_dpc4
     659              :    complex(dp),contiguous, pointer :: arr_p(:,:,:,:)
     660              :  end type rarr_dpc4
     661          277 :  type(rarr_dpc4),allocatable :: data_p(:)
     662              : ! *************************************************************************
     663              : 
     664              :  !@melements_t
     665          277 :  my_unt   =std_out; if (PRESENT(unit      )) my_unt   =unit
     666          277 :  my_prtvol=0      ; if (PRESENT(prtvol    )) my_prtvol=prtvol
     667          277 :  my_mode  ='COLL' ; if (PRESENT(mode_paral)) my_mode  =mode_paral
     668              : 
     669          277 :  if (Mels%nspinor == 2) ABI_WARNING("nspinor=2 not coded")
     670              : 
     671          277 :  if (present(names_list)) then
     672            0 :    my_nkeys=SIZE(names_list)
     673            0 :    ABI_MALLOC(my_keys, (my_nkeys))
     674            0 :    my_keys = names_list
     675              :  else
     676          277 :    my_nkeys = NNAMES
     677          277 :    ABI_MALLOC(my_keys, (NNAMES))
     678         3047 :    my_keys = ANAMES
     679              :  end if
     680              : 
     681          831 :  ABI_MALLOC(data_p, (my_nkeys))
     682          831 :  ABI_MALLOC(tab, (my_nkeys))
     683         2770 :  tab = 0
     684              : 
     685          277 :  my_nkeys=0; str = "  ib"; ii=4
     686         2770 :  do ikey=1,size(my_keys)
     687         2493 :    key = my_keys(ikey)
     688         2493 :    call my_select_melements(Mels,key,flag_p,data_p(ikey)%arr_p)
     689         2770 :    if (flag_p == 2) then
     690          713 :      my_nkeys = my_nkeys+1
     691          713 :      tab(my_nkeys) = ikey
     692          713 :      str(ii+1:)=" "//TRIM(tolower(key))
     693          713 :      ii = ii+MAX(1+LEN_TRIM(key),10)
     694          713 :      ABI_CHECK(ii <490, "I'm gonna SIGFAULT!")
     695              :    end if
     696              :  end do
     697              : 
     698          277 :  write(msg,'(2a)')ch10,' === Matrix Elements stored in Mels% [eV] === '
     699          277 :  if (PRESENT(header)) write(msg,'(4a)')ch10,' === '//TRIM(ADJUSTL(header))//' [eV] === '
     700          277 :  call wrtout(my_unt,msg,my_mode)
     701          277 :  if (Mels%nspinor == 2) then
     702            7 :    call wrtout(my_unt, "Sum_ab M_ab, M_11, M_22, Re(M_12), IM(Re_12)" ,my_mode)
     703              :  end if
     704              : 
     705          277 :  if (my_nkeys==0) GOTO 10
     706          277 :  write(fmt,'(a,i4,a)')'(1x,i3,',my_nkeys,'(1x,f9.5))' ! width of 10 chars
     707              : 
     708          560 :  do isppol=1,Mels%nsppol
     709         2245 :    do ikibz=1,Mels%nkibz
     710         1685 :     if (Mels%iscalc(ikibz,isppol)/=1) CYCLE
     711              : 
     712         1046 :     write(msg,'(a,3es16.8,a,i2,a)')" kpt= (",Mels%kibz(:,ikibz),") spin=",isppol,":"
     713         1046 :     call wrtout(my_unt,msg,my_mode)
     714              : 
     715         1046 :     b1 = Mels%bands_idx(1,ikibz,isppol)
     716         1046 :     b2 = Mels%bands_idx(2,ikibz,isppol)
     717              : 
     718         1329 :     if (Mels%flags%only_diago==1 .or. my_prtvol==0) then
     719              :       ! Print only the diagonal.
     720          814 :       write(msg,'(a)')str
     721          814 :       call wrtout(my_unt,msg,my_mode)
     722         7195 :       do ib=b1,b2
     723         7195 :         if (Mels%nspinor == 1) then
     724        20888 :           write(msg,fmt)ib,(REAL(data_p(tab(ikey))%arr_p(ib,ib,ikibz,1))*Ha_eV, ikey=1,my_nkeys)
     725         6237 :           call wrtout(my_unt,msg,my_mode)
     726              :         else
     727              :           ! Write sum_ab, then diagonal elements, finally Re_12, Im_12
     728         2304 :           write(msg,fmt)ib,(real(sum(data_p(tab(ikey))%arr_p(ib,ib,ikibz,:)))*Ha_eV, ikey=1,my_nkeys)
     729          144 :           call wrtout(my_unt,msg,my_mode)
     730          144 :           if (my_prtvol > 0) then
     731            0 :             write(msg,fmt)ib,(real(data_p(tab(ikey))%arr_p(ib,ib,ikibz,1))*Ha_eV, ikey=1,my_nkeys)
     732            0 :             call wrtout(my_unt,msg,my_mode)
     733            0 :             write(msg,fmt)ib,(real(data_p(tab(ikey))%arr_p(ib,ib,ikibz,2))*Ha_eV, ikey=1,my_nkeys)
     734            0 :             call wrtout(my_unt,msg,my_mode)
     735            0 :             write(msg,fmt)ib,(real(data_p(tab(ikey))%arr_p(ib,ib,ikibz,3))*Ha_eV, ikey=1,my_nkeys)
     736            0 :             call wrtout(my_unt,msg,my_mode)
     737            0 :             write(msg,fmt)ib,(aimag(data_p(tab(ikey))%arr_p(ib,ib,ikibz,3))*Ha_eV, ikey=1,my_nkeys)
     738            0 :             call wrtout(my_unt,msg,my_mode)
     739              :           end if
     740              :         end if
     741              :       end do
     742              : 
     743              :     else
     744              :       ! Print full matrix.
     745          232 :       max_r = b2-b1+1
     746          232 :       max_c = MIN(b2-b1+1, 9)
     747          928 :       ABI_MALLOC(mat,(b1:b2,b1:b2))
     748          786 :       do ikey=1,my_nkeys
     749          554 :         write(msg,'(3a)')" **** Off-diagonal elements of ",TRIM(my_keys(tab(ikey)))," **** "
     750          554 :         call wrtout(my_unt,msg,my_mode)
     751         1108 :         do iab=1,Mels%nspinor**2
     752       111072 :           mat = data_p(tab(ikey))%arr_p(b1:b2,b1:b2,ikibz,iab) * Ha_eV
     753         1662 :           call print_arr([my_unt], mat, max_r, max_c)
     754              :         end do
     755          554 :         write(msg,'(a)')ch10
     756          786 :         call wrtout(my_unt,msg,my_mode)
     757              :       end do
     758          232 :       ABI_FREE(mat)
     759              :     end if
     760              : 
     761              :    end do !ikibz
     762              :  end do ! isppol
     763              : 
     764              : 10 continue
     765              : 
     766          277 :  ABI_FREE(my_keys)
     767          277 :  ABI_FREE(data_p)
     768          277 :  ABI_FREE(tab)
     769              : 
     770          554 : end subroutine melements_print
     771              : !!***
     772              : 
     773              : !----------------------------------------------------------------------
     774              : 
     775              : !!****f* m_melemts/melements_zero
     776              : !! NAME
     777              : !! melements_zero
     778              : !!
     779              : !! FUNCTION
     780              : !!  Set matrix elements connecting states with different irreducible representation to zero.
     781              : !!
     782              : !! INPUTS
     783              : !!   irrep_tab=Array used to select the entries that have to be set to zero.
     784              : !!     irrep_tab(ib,ik,is)=gives the index of the irreducible representation associated to state (ib,ik,is).
     785              : !!  [aname]=The name of the array to be symmetrized, by default
     786              : !!    all calculated arrays are filled.
     787              : !!
     788              : !! SIDE EFFECTS
     789              : !!  Mels= All arrays elements connecting states belonging to different irreps are set to zero.
     790              : !!
     791              : !! SOURCE
     792              : 
     793            0 : subroutine melements_zero(Mels, irrep_tab, aname)
     794              : 
     795              : !Arguments ------------------------------------
     796              : !scalars
     797              :  class(melements_t),intent(inout) :: Mels
     798              :  character(len=*),optional,intent(in) :: aname
     799              : !arrays
     800              :  integer,intent(in) :: irrep_tab(Mels%bmin:Mels%bmax,Mels%nkibz,Mels%nsppol)
     801              : 
     802              : !Local variables-------------------------------
     803              :  integer :: is,ik,ib,jb,iname,irrep_j,irrep_i
     804              :  integer,pointer :: flag_p
     805              :  character(len=NAMELEN) :: key
     806              : !arrays
     807              :  complex(dp),contiguous, pointer :: arr_p(:,:,:,:)
     808              : ! *************************************************************************
     809              : 
     810            0 :  do iname=1,NNAMES
     811            0 :    key = ANAMES(iname)
     812            0 :    if (PRESENT(aname)) then
     813            0 :      if (key /= aname) CYCLE
     814              :    end if
     815              : 
     816            0 :    call my_select_melements(Mels,key,flag_p,arr_p)
     817              : 
     818            0 :    if (flag_p>0) then
     819            0 :      do is=1,Mels%nsppol
     820            0 :        do ik=1,Mels%nkibz
     821              : 
     822            0 :          do jb=Mels%bmin,Mels%bmax
     823            0 :            irrep_j = irrep_tab(jb,ik,is)
     824            0 :            do ib=Mels%bmin,Mels%bmax
     825            0 :              irrep_i = irrep_tab(ib,ik,is)
     826              :              !
     827              :              ! Set this matrix element to zero if the irreps are known and they differ.
     828            0 :              if (irrep_i/=irrep_j .and. ALL((/irrep_i,irrep_j/) /=0) ) then
     829              :                !write(std_out,*)"setting to zero ",ib,jb,ik,is
     830            0 :                if (Mels%nspinor==2) then
     831            0 :                  arr_p(ib,jb,ik,is)=czero
     832              :                else
     833            0 :                  arr_p(ib,jb,ik,:)=czero
     834              :                end if
     835              :              end if
     836              : 
     837              :            end do !ib
     838              :          end do !jb
     839              : 
     840              :        end do !is
     841              :      end do !ik
     842              :    end if
     843              : 
     844              :  end do !inames
     845              : 
     846            0 : end subroutine melements_zero
     847              : !!***
     848              : 
     849              : !----------------------------------------------------------------------
     850              : 
     851              : !!****f* m_sigma/mels_get_exene_core
     852              : !! NAME
     853              : !!  mels_get_exene_core
     854              : !!
     855              : !! FUNCTION
     856              : !!  Compute exchange energy.
     857              : !!
     858              : !! INPUTS
     859              : !!  mels<melements_t>=Matrix elements.
     860              : !!  kmesh<kmesh_t>=BZ sampling.
     861              : !!  bands<band_t>=Bands with occupation factors
     862              : !!
     863              : !! SOURCE
     864              : 
     865              : !pure function mels_get_exene_core(mels,kmesh,bands) result(ex_energy)
     866              : !
     867              : !!Arguments ------------------------------------
     868              : !!scalars
     869              : ! real(dp) :: ex_energy
     870              : ! type(melements_t),intent(in) :: mels
     871              : ! type(kmesh_t),intent(in) :: kmesh
     872              : ! type(ebands_t),intent(in) :: bands
     873              : !
     874              : !!Local variables-------------------------------
     875              : !!scalars
     876              : ! integer :: ik,ib,spin
     877              : ! real(dp) :: wtk,occ_bks
     878              : !! *************************************************************************
     879              : !
     880              : ! ex_energy = zero
     881              : !
     882              : ! do spin=1,mels%nsppol
     883              : !   do ik=1,mels%nkibz
     884              : !     wtk = kmesh%wt(ik)
     885              : !     do ib=mels%bmin,mels%bmax
     886              : !       occ_bks = bands%occ(ib,ik,spin)
     887              : !       if (mels%nspinor==1) then
     888              : !         ex_energy = ex_energy + half * occ_bks * wtk * mels%sxcore(ib,ib,ik,spin)
     889              : !       else
     890              : !         ex_energy = ex_energy + half * occ_bks wtk *SUM(mels%sxcore(ib,ib,ik,:))
     891              : !       end if
     892              : !     end do
     893              : !   end do
     894              : ! end do
     895              : !
     896              : !end function mels_get_exene_core
     897              : !!!***
     898              : 
     899          843 : end module m_melemts
     900              : !!***
        

Generated by: LCOV version 2.3-1