LCOV - code coverage report
Current view: top level - src/66_nonlocal - m_opernlb_ylm_mv.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 90 0
Test Date: 2026-11-10 12:08:57 Functions: 0.0 % 1 0
Branches: 0.0 % 98 0

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_opernlb_ylm_mv
       2                 :             : !! NAME
       3                 :             : !!  m_opernlb_ylm_mv
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !! COPYRIGHT
       8                 :             : !!  Copyright (C) 2021-2026 ABINIT group (LB,MT)
       9                 :             : !!  This file is distributed under the terms of the
      10                 :             : !!  GNU General Public License, see ~abinit/COPYING
      11                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      12                 :             : !!
      13                 :             : !! SOURCE
      14                 :             : 
      15                 :             : #if defined HAVE_CONFIG_H
      16                 :             : #include "config.h"
      17                 :             : #endif
      18                 :             : 
      19                 :             : #include "abi_common.h"
      20                 :             : 
      21                 :             : module m_opernlb_ylm_mv
      22                 :             : 
      23                 :             :  use defs_basis
      24                 :             :  use m_abicore
      25                 :             :  use m_errors
      26                 :             : #if defined HAVE_OPENMP
      27                 :             :  use OMP_LIB
      28                 :             : #endif
      29                 :             : 
      30                 :             :  implicit none
      31                 :             : 
      32                 :             :  private
      33                 :             : !!***
      34                 :             : 
      35                 :             :  public :: opernlb_ylm_mv
      36                 :             :  integer,public,save :: opernlb_mv_counter = -1
      37                 :             :  integer,public,save :: opernlb_mv_dgemv_counter = -1
      38                 :             : !!***
      39                 :             : 
      40                 :             : contains
      41                 :             : !!***
      42                 :             : 
      43                 :             : !!****f* ABINIT/opernlb_ylm_mv
      44                 :             : !! NAME
      45                 :             : !! opernlb_ylm_mv
      46                 :             : !!
      47                 :             : !! FUNCTION
      48                 :             : !! "matrix-vector" alternative implementation of "opernlrb_ylm".
      49                 :             : !!
      50                 :             : !! * Operate with the non-local part of the hamiltonian,
      51                 :             : !!   from projected scalars to reciprocal space.
      52                 :             : !! * Operate with the non-local projectors and the overlap matrix,
      53                 :             : !!   from projected scalars to reciprocal space.
      54                 :             : !!
      55                 :             : !!   The input is gxfac (gxfac_sij):
      56                 :             : !!   gxfac(lmn) = Sum_l'm'n' D_l'm'n'.<p_l'm'n|c> (or S_l'm'n' for gxfac_sij)
      57                 :             : !!   and here we compute :
      58                 :             : !!   Sum_lmn <g|p_lmn> gxfac(lmn) = 4pi/sqrt(vol) exp(-2pi.i.g.R) Sum_lmn (-i)^l f_nl(g).Y_lm(g) gxfac(lmn)
      59                 :             : !!   Here this is done in 3 steps:
      60                 :             : !!   (1) compute for every lmn : gxfac_(lmn) = 4pi/sqrt(vol).(-i)^l.gxfac(lmn)
      61                 :             : !!   (2) compute for every g   : scal(g)     = Sum_lmn f_nl(g).Y_lm(g).gxfac_(lmn)
      62                 :             : !!   (3) compute for every g   : vect(g)     = exp(-2pi.i.g.R).scal(g)
      63                 :             : !!
      64                 :             : !!   Step (2) is a real-matrix/complex-vector multiplication, here two options are possible:
      65                 :             : !!   - case nloalg(1)=2 : compute the real and imaginary parts separately using two calls of DGMEV
      66                 :             : !!   - case nloalg(1)=3 : in order to read the matrix only once, we compute both real and imaginary parts at the same time "by hand"
      67                 :             : !!
      68                 :             : !!   Depending on the achitecture and the available blas library, one option could be more interesting than an other...
      69                 :             : !!
      70                 :             : !! INPUTS
      71                 :             : !!  choice=chooses possible output (see below)
      72                 :             : !!  cplex=1 if <p_lmn|c> scalars are real (equivalent to istwfk>1)
      73                 :             : !!        2 if <p_lmn|c> scalars are complex
      74                 :             : !!  cplex_fac=1 if gxfac scalars are real, 2 if gxfac scalars are complex
      75                 :             : !!  dimffnl=second dimension of ffnl
      76                 :             : !!  ffnl(npw,dimffnl,nlmn)= nonlocal quantities containing nonlocal form factors
      77                 :             : !!  gxfac(cplex_fac,nlmn,nincat,nspinor)= reduced projected scalars related to Vnl (NL operator)
      78                 :             : !!  gxfac_sij(cplex,nlmn,nincat,nspinor*(paw_opt/3))= reduced projected scalars related to Sij (overlap)
      79                 :             : !!  ia3=gives the number of the first atom in the subset presently treated
      80                 :             : !!  indlmn(6,nlmn)= array giving l,m,n,lm,ln,s for i=lmn
      81                 :             : !!  matblk=dimension of the array ph3d
      82                 :             : !!  nincat=number of atoms in the subset here treated
      83                 :             : !!  nlmn=number of (l,m,n) numbers for current type of atom
      84                 :             : !!  nloalg(3)=governs the choice of the algorithm for non-local operator.
      85                 :             : !!  npw=number of plane waves in reciprocal space
      86                 :             : !!  nspinor=number of spinorial components of the wavefunctions (on current proc)
      87                 :             : !!  paw_opt= define the nonlocal operator concerned with:
      88                 :             : !!           paw_opt=0 : Norm-conserving Vnl (use of Kleinman-Bylander ener.)
      89                 :             : !!           paw_opt=1 : PAW nonlocal part of H (use of Dij coeffs)
      90                 :             : !!           paw_opt=2 : PAW: (Vnl-lambda.Sij) (Sij=overlap matrix)
      91                 :             : !!           paw_opt=3 : PAW overlap matrix (Sij)
      92                 :             : !!           paw_opt=4 : both PAW nonlocal part of H (Dij) and overlap matrix (Sij)
      93                 :             : !!  ph3d(2,npw,matblk)=three-dimensional phase factors
      94                 :             : !!  ucvol=unit cell volume (bohr^3)
      95                 :             : !!
      96                 :             : !! OUTPUT
      97                 :             : !!  (see side effects)
      98                 :             : !!
      99                 :             : !! SIDE EFFECTS
     100                 :             : !! --if (paw_opt=0)
     101                 :             : !!    vectout(2,npwout*my_nspinor*ndat)=result of the aplication of the concerned operator
     102                 :             : !!                or one of its derivatives to the input vect.
     103                 :             : !! --if (paw_opt=0, 1 or 4)
     104                 :             : !!    vect(2,npwout*nspinor)=result of the aplication of the concerned operator
     105                 :             : !!                or one of its derivatives to the input vect.:
     106                 :             : !!      if (choice=1)  <G|V_nonlocal|vect_in>
     107                 :             : !!  if (paw_opt=2)
     108                 :             : !!    vect(2,npwout*nspinor)=final vector in reciprocal space:
     109                 :             : !!      if (choice=1)  <G|V_nonlocal-lamdba.(I+S)|vect_in> (note: not including <G|I|c>)
     110                 :             : !! --if (paw_opt=3 or 4)
     111                 :             : !!    svect(2,npwout*nspinor)=result of the aplication of Sij (overlap matrix)
     112                 :             : !!                  or one of its derivatives to the input vect.:
     113                 :             : !!      if (choice=1)  <G|I+S|vect_in> (note: not including <G|I|c>)
     114                 :             : !!
     115                 :             : !! NOTES
     116                 :             : !! 1-No openMP available for now
     117                 :             : !! 2-Operate for one type of atom, and within this given type of atom,
     118                 :             : !!   for a subset of at most nincat atoms.
     119                 :             : !! 3-projector derivatives (abs(choice)>1) are not implemented yet
     120                 :             : !!
     121                 :             : !! SOURCE
     122                 :             : 
     123                 :           0 : subroutine opernlb_ylm_mv(choice,cplex,cplex_fac,&
     124                 :           0 : &                      dimffnl,ffnl,gxfac,gxfac_sij,&
     125                 :           0 : &                      ia3,indlmn,matblk,nincat,nlmn,nloalg,npw,&
     126   [ #  #  #  # ]:           0 : &                      nspinor,paw_opt,ph3d,svect,ucvol,vect)
     127                 :             : 
     128                 :             : !Arguments ------------------------------------
     129                 :             : !scalars
     130                 :             :  integer,intent(in) :: choice,cplex,cplex_fac,dimffnl,ia3,matblk,nincat
     131                 :             :  integer,intent(in) :: nlmn,npw,nspinor,paw_opt
     132                 :             :  real(dp),intent(in) :: ucvol
     133                 :             : !arrays
     134                 :             :  integer,intent(in) ::  indlmn(6,nlmn),nloalg(3)
     135                 :             :  real(dp),intent(in),target :: ffnl(npw,dimffnl,nlmn)
     136                 :             :  real(dp),intent(in) :: gxfac(cplex_fac,nlmn,nincat,nspinor)
     137                 :             :  real(dp),intent(in) :: gxfac_sij(cplex,nlmn,nincat,nspinor*(paw_opt/3))
     138                 :             :  real(dp),intent(in) :: ph3d(2,npw,matblk)
     139                 :             :  real(dp),intent(inout) :: svect(:,:),vect(:,:)
     140                 :             : !Local variables-------------------------------
     141                 :             : !Arrays
     142                 :             : !scalars
     143                 :             :  logical :: use_dgemv
     144                 :             :  integer :: ia,iaph3d
     145                 :             :  integer :: il,ilmn,ipw,jpw,ipwshft,ispinor
     146                 :             :  real(dp) :: buffer_r,buffer_i,wt
     147                 :             : !arrays
     148                 :             : ! real(dp) :: tsec(2)
     149                 :           0 :  real(dp) :: gxfac_(nlmn,2),gxfacs_(nlmn,2)
     150                 :           0 :  real(dp),allocatable :: scalr(:),scali(:)
     151                 :           0 :  real(dp),pointer :: ffnl_loc(:,:)
     152                 :             :  complex(dp) :: ctmp, cil(4)
     153                 :             : 
     154                 :             : ! *************************************************************************
     155                 :             : 
     156                 :             :  DBG_ENTER("COLL")
     157                 :             : 
     158                 :             : !Some checks
     159                 :             : ! nthreads=1
     160                 :             : !#if defined HAVE_OPENMP
     161                 :             : ! nthreads=OMP_GET_NUM_THREADS()
     162                 :             : !#endif
     163                 :             : ! if (nthreads>1) then
     164                 :             : !   ABI_ERROR('Only nthreads=1 is available for now.')
     165                 :             : ! end if
     166                 :             : 
     167                 :           0 :  if (abs(choice)>1) then
     168                 :           0 :    ABI_ERROR('Only abs(choice)<=1 is available for now.')
     169                 :             :  end if
     170         [ #  # ]:           0 :  if (nloalg(1)<2.or.nloalg(1)>10) then
     171                 :           0 :    ABI_ERROR('nloalg(1) should be between 2 or 10.')
     172                 :             :  end if
     173                 :             : 
     174         [ #  # ]:           0 :  use_dgemv = nloalg(1)==2.or.nloalg(1)==6.or.nloalg(1)==10
     175                 :             :  if (use_dgemv) then
     176         [ #  # ]:           0 :    if(opernlb_mv_dgemv_counter>=0) then
     177                 :           0 :      opernlb_mv_dgemv_counter = opernlb_mv_dgemv_counter + 1
     178         [ #  # ]:           0 :      if (paw_opt==4) opernlb_mv_dgemv_counter = opernlb_mv_dgemv_counter + 1
     179                 :             :    end if
     180                 :             :  else
     181         [ #  # ]:           0 :    if(opernlb_mv_counter>=0) then
     182                 :           0 :      opernlb_mv_counter = opernlb_mv_counter + 1
     183         [ #  # ]:           0 :      if (paw_opt==4) opernlb_mv_counter = opernlb_mv_counter + 1
     184                 :             :    end if
     185                 :             :  end if
     186                 :             : 
     187                 :             : !Inits
     188                 :           0 :  wt=four_pi/sqrt(ucvol)
     189                 :             : 
     190                 :           0 :  ffnl_loc => ffnl(:,1,:)
     191                 :             : 
     192                 :             : 
     193   [ #  #  #  #  :           0 :  ABI_MALLOC(scalr,(npw))
          #  #  #  #  #  
                #  #  # ]
     194   [ #  #  #  #  :           0 :  ABI_MALLOC(scali,(npw))
             #  #  #  # ]
     195                 :             : 
     196                 :             : !$OMP PARALLEL PRIVATE(buffer_r,buffer_i,cil,il,ilmn,ipw,jpw,ctmp), &
     197                 :             : !$OMP PRIVATE(ispinor,ipwshft,ia,iaph3d,gxfac_,gxfacs_)
     198                 :             : 
     199                 :             : ! (-i)^l
     200                 :           0 :  cil(1) = ( 1.0_DP, 0.0_DP) * wt
     201                 :           0 :  cil(2) = ( 0.0_DP,-1.0_DP) * wt
     202                 :           0 :  cil(3) = (-1.0_DP, 0.0_DP) * wt
     203                 :           0 :  cil(4) = ( 0.0_DP, 1.0_DP) * wt
     204                 :             : 
     205                 :             : ! if (paw_opt/=3) then
     206                 :             : !   ABI_MALLOC(gxfac_,(nlmn,2))
     207                 :             : ! end if
     208                 :             : ! if (paw_opt>=3) then
     209                 :             : !   ABI_MALLOC(gxfacs_,(nlmn,2))
     210                 :             : ! end if
     211                 :             : 
     212                 :             : !Loop on spinorial components
     213         [ #  # ]:           0 :  do ispinor=1,nspinor
     214                 :           0 :    ipwshft=(ispinor-1)*npw
     215                 :             : 
     216                 :             : !  Loop on atoms (blocking)
     217         [ #  # ]:           0 :    do ia=1,nincat
     218         [ #  # ]:           0 :      iaph3d=ia;if (nloalg(2)>0) iaph3d=ia+ia3-1
     219                 :             : !    Step (1) : scale gxfac with 4pi/sqr(omega).(-i)^l
     220         [ #  # ]:           0 :      if (paw_opt/=3) then
     221         [ #  # ]:           0 :        if (cplex_fac==2) then
     222         [ #  # ]:           0 :          do ilmn=1,nlmn
     223                 :           0 :            il=mod(indlmn(1,ilmn),4)+1
     224                 :           0 :            ctmp = cil(il) * cmplx( gxfac(1,ilmn,ia,ispinor), gxfac(2,ilmn,ia,ispinor), kind=DP )
     225                 :           0 :            gxfac_(ilmn,1) =  real(ctmp)
     226                 :           0 :            gxfac_(ilmn,2) = aimag(ctmp)
     227                 :             :          end do
     228         [ #  # ]:           0 :        else if (cplex_fac==1) then
     229         [ #  # ]:           0 :          do ilmn=1,nlmn
     230                 :           0 :            il=mod(indlmn(1,ilmn),4)+1
     231                 :           0 :            ctmp = cil(il) * gxfac(1,ilmn,ia,ispinor)
     232                 :           0 :            gxfac_(ilmn,1) =  real(ctmp)
     233                 :           0 :            gxfac_(ilmn,2) = aimag(ctmp)
     234                 :             :          end do
     235                 :             :        else
     236                 :           0 :          ABI_BUG('Error : should not be possible to be here')
     237                 :             :        end if
     238                 :             :      end if
     239                 :             : 
     240                 :             : !    Step (1) bis: Scale gxfac_sij with 4pi/sqr(omega).(-i)^l
     241         [ #  # ]:           0 :      if (paw_opt>=3) then
     242         [ #  # ]:           0 :        if (cplex==2) then
     243         [ #  # ]:           0 :          do ilmn=1,nlmn
     244                 :           0 :            il=mod(indlmn(1,ilmn),4)+1
     245                 :           0 :            ctmp = cil(il) * cmplx( gxfac_sij(1,ilmn,ia,ispinor), gxfac_sij(2,ilmn,ia,ispinor), kind=DP )
     246                 :           0 :            gxfacs_(ilmn,1) =  real(ctmp)
     247                 :           0 :            gxfacs_(ilmn,2) = aimag(ctmp)
     248                 :             :          end do
     249         [ #  # ]:           0 :        else if (cplex==1) then
     250         [ #  # ]:           0 :          do ilmn=1,nlmn
     251                 :           0 :            il=mod(indlmn(1,ilmn),4)+1
     252                 :           0 :            ctmp = cil(il) * gxfac_sij(1,ilmn,ia,ispinor)
     253                 :           0 :            gxfacs_(ilmn,1) =  real(ctmp)
     254                 :           0 :            gxfacs_(ilmn,2) = aimag(ctmp)
     255                 :             :          end do
     256                 :             :        else
     257                 :           0 :          ABI_BUG('Error : should not be possible to be here')
     258                 :             :        end if
     259                 :             :      end if
     260                 :             : 
     261                 :             : !    Compute <g|Vnl|c> (or derivatives) for each plane wave:
     262         [ #  # ]:           0 :      if (paw_opt/=3) then
     263                 :             : 
     264                 :             : !      Step (2) scal(g) = Sum_lmn f_nl(g).Y_lm(g).gxfac_(lmn)
     265         [ #  # ]:           0 :        if (use_dgemv) then
     266         [ #  # ]:           0 :          call DGEMV('N',npw,nlmn,1.0_DP,ffnl_loc,npw,gxfac_(:,1),1,0.0_DP,scalr,1)
     267         [ #  # ]:           0 :          call DGEMV('N',npw,nlmn,1.0_DP,ffnl_loc,npw,gxfac_(:,2),1,0.0_DP,scali,1)
     268                 :             :        else
     269                 :             : !         scalr(:) = zero
     270                 :             : !         scali(:) = zero
     271                 :             : !         do ilmn=1,nlmn
     272                 :             : !           do ipw=1,npw
     273                 :             : !             scalr(ipw) = scalr(ipw) + ffnl_loc(ipw,ilmn) * gxfac_(ilmn,1)
     274                 :             : !             scali(ipw) = scali(ipw) + ffnl_loc(ipw,ilmn) * gxfac_(ilmn,2)
     275                 :             : !           end do
     276                 :             : !         end do
     277                 :             : !$OMP DO
     278         [ #  # ]:           0 :          do ipw=1,npw
     279                 :             :            buffer_r = zero
     280                 :             :            buffer_i = zero
     281         [ #  # ]:           0 :            do ilmn=1,nlmn
     282                 :           0 :              buffer_r = buffer_r + ffnl_loc(ipw,ilmn) * gxfac_(ilmn,1)
     283                 :           0 :              buffer_i = buffer_i + ffnl_loc(ipw,ilmn) * gxfac_(ilmn,2)
     284                 :             : !             scalr(ipw) = scalr(ipw) + ffnl_loc(ipw,ilmn) * gxfac_(ilmn,1)
     285                 :             : !             scali(ipw) = scali(ipw) + ffnl_loc(ipw,ilmn) * gxfac_(ilmn,2)
     286                 :             :            end do
     287                 :           0 :            scalr(ipw) = buffer_r
     288                 :           0 :            scali(ipw) = buffer_i
     289                 :             :          end do
     290                 :             : !$OMP END DO
     291                 :             :        end if
     292                 :             : 
     293                 :             : !      Step (3) : vect(g) = exp(-2pi.i.g.R).scal(g)
     294                 :             : !$OMP DO
     295         [ #  # ]:           0 :        do ipw=1,npw
     296                 :           0 :          jpw=ipw+ipwshft
     297                 :           0 :          vect(1,jpw)=vect(1,jpw)+scalr(ipw)*ph3d(1,ipw,iaph3d)+scali(ipw)*ph3d(2,ipw,iaph3d)
     298                 :           0 :          vect(2,jpw)=vect(2,jpw)-scalr(ipw)*ph3d(2,ipw,iaph3d)+scali(ipw)*ph3d(1,ipw,iaph3d)
     299                 :             :        end do
     300                 :             : !$OMP END DO
     301                 :             : 
     302                 :             :      end if
     303                 :             : 
     304                 :             : !    Compute <g|S|c> (or derivatives) for each plane wave:
     305         [ #  # ]:           0 :      if (paw_opt>=3) then
     306                 :             : 
     307                 :             : !      Step (2) (bis) scal(g) = Sum_lmn f_nl(g).Y_lm(g).gxfacs_(lmn)
     308         [ #  # ]:           0 :        if (nloalg(1)==3) then
     309                 :             : !         scalr(:) = zero
     310                 :             : !         scali(:) = zero
     311                 :             : !         do ilmn=1,nlmn
     312                 :             : !           do ipw=1,npw
     313                 :             : !             scalr(ipw) = scalr(ipw) + ffnl_loc(ipw,ilmn) * gxfacs_(ilmn,1)
     314                 :             : !             scali(ipw) = scali(ipw) + ffnl_loc(ipw,ilmn) * gxfacs_(ilmn,2)
     315                 :             : !           end do
     316                 :             : !         end do
     317                 :             : !$OMP DO
     318         [ #  # ]:           0 :          do ipw=1,npw
     319                 :             :            buffer_r = zero
     320                 :             :            buffer_i = zero
     321         [ #  # ]:           0 :            do ilmn=1,nlmn
     322                 :           0 :              buffer_r = buffer_r + ffnl_loc(ipw,ilmn) * gxfacs_(ilmn,1)
     323                 :           0 :              buffer_i = buffer_i + ffnl_loc(ipw,ilmn) * gxfacs_(ilmn,2)
     324                 :             : !             scalr(ipw) = scalr(ipw) + ffnl_loc(ipw,ilmn) * gxfacs_(ilmn,1)
     325                 :             : !             scali(ipw) = scali(ipw) + ffnl_loc(ipw,ilmn) * gxfacs_(ilmn,2)
     326                 :             :            end do
     327                 :           0 :            scalr(ipw) = buffer_r
     328                 :           0 :            scali(ipw) = buffer_i
     329                 :             :          end do
     330                 :             : !$OMP END DO
     331         [ #  # ]:           0 :        else if (nloalg(1)==2) then
     332         [ #  # ]:           0 :          call DGEMV('N',npw,nlmn,1.0_DP,ffnl_loc,npw,gxfacs_(:,1),1,0.0_DP,scalr,1)
     333         [ #  # ]:           0 :          call DGEMV('N',npw,nlmn,1.0_DP,ffnl_loc,npw,gxfacs_(:,2),1,0.0_DP,scali,1)
     334                 :             :        end if
     335                 :             : 
     336                 :             : !      Step (3) (bis) : svect(g) = exp(-2pi.i.g.R).scal(g)
     337                 :             : !$OMP DO
     338         [ #  # ]:           0 :        do ipw=1,npw
     339                 :           0 :          jpw=ipw+ipwshft
     340                 :           0 :          svect(1,jpw)=svect(1,jpw)+scalr(ipw)*ph3d(1,ipw,iaph3d)+scali(ipw)*ph3d(2,ipw,iaph3d)
     341                 :           0 :          svect(2,jpw)=svect(2,jpw)-scalr(ipw)*ph3d(2,ipw,iaph3d)+scali(ipw)*ph3d(1,ipw,iaph3d)
     342                 :             :        end do
     343                 :             : !$OMP END DO
     344                 :             : 
     345                 :             :      end if
     346                 :             : 
     347                 :             : !    End loop on atoms
     348                 :             :    end do
     349                 :             :  end do !  End loop on spinors
     350                 :             : ! if (paw_opt/=3) then
     351                 :             : !   ABI_FREE(gxfac_)
     352                 :             : ! end if
     353                 :             : ! if (paw_opt>=3) then
     354                 :             : !   ABI_FREE(gxfacs_)
     355                 :             : ! end if
     356                 :             : !$OMP END PARALLEL
     357                 :             : 
     358         [ #  # ]:           0 :  ABI_FREE(scalr)
     359         [ #  # ]:           0 :  ABI_FREE(scali)
     360                 :             : 
     361                 :             : 
     362                 :             :  DBG_EXIT("COLL")
     363                 :             : 
     364         [ #  # ]:           0 : end subroutine opernlb_ylm_mv
     365                 :             : !!***
     366                 :             : 
     367                 :             : end module m_opernlb_ylm_mv
     368                 :             : !!***
        

Generated by: LCOV version 2.3-1