LCOV - code coverage report
Current view: top level - src/79_seqpar_mpi - m_lobpcgwf_cprj.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.2 % 74 69
Test Date: 2026-09-20 15:27:41 Functions: 100.0 % 4 4

            Line data    Source code
       1              : !!****f* ABINIT/m_lobpcgwf_cprj
       2              : !! NAME
       3              : !! m_lobpcgwf_cprj
       4              : !!
       5              : !! FUNCTION
       6              : !! This routine updates the whole wave functions at a given k-point,
       7              : !! using the lobpcg method
       8              : !! for a given spin-polarization, from a fixed hamiltonian
       9              : !! but might also simply compute eigenvectors and eigenvalues at this k point.
      10              : !! it will also update the matrix elements of the hamiltonian.
      11              : !!
      12              : !! COPYRIGHT
      13              : !! Copyright (C) 1998-2026 ABINIT group (LB)
      14              : !! this file is distributed under the terms of the
      15              : !! gnu general public license, see ~abinit/COPYING
      16              : !! or http://www.gnu.org/copyleft/gpl.txt .
      17              : !! for the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      18              : !!
      19              : !! SOURCE
      20              : 
      21              : #if defined HAVE_CONFIG_H
      22              : #include "config.h"
      23              : #endif
      24              : 
      25              : #include "abi_common.h"
      26              : 
      27              : module m_lobpcgwf_cprj
      28              : 
      29              :  use, intrinsic :: iso_c_binding
      30              :  use defs_basis
      31              :  use m_abicore
      32              :  use m_lobpcg
      33              :  use m_errors
      34              :  use m_time
      35              :  use m_xomp
      36              :  use m_fstrings
      37              :  use m_xg
      38              :  use m_xg_nonlop
      39              :  use m_xgTransposer
      40              :  use m_lobpcg2_cprj
      41              :  use m_dtset
      42              : 
      43              :  use defs_abitypes, only : mpi_type
      44              :  use m_hamiltonian, only : gs_hamiltonian_type
      45              :  use m_getghc,      only : multithreaded_getghc
      46              :  use m_pawcprj,     only : pawcprj_type
      47              : 
      48              :  implicit none
      49              : 
      50              :  private
      51              : 
      52              :  integer, parameter :: l_tim_getghc=5
      53              : 
      54              : ! For use in getghc_gsc1
      55              :  integer, save :: l_prtvol
      56              :  type(mpi_type),pointer,save :: l_mpi_enreg
      57              :  type(gs_hamiltonian_type),pointer,save :: l_gs_hamk
      58              : 
      59              :  public :: lobpcgwf2_cprj
      60              : 
      61              :  contains
      62              : !!***
      63              : 
      64         4036 : subroutine lobpcgwf2_cprj(cg,dtset,eig,occ,enl_out,gs_hamk,isppol,ikpt,inonsc,istep,kinpw,mpi_enreg,&
      65         4036 : &                   nband,npw,nspinor,prtvol,resid,nbdbuf,xg_nonlop)
      66              : 
      67              : 
      68              :  use m_cgtools, only : dotprod_g
      69              : 
      70              : !Arguments ------------------------------------
      71              :  integer,intent(in) :: nband,npw,prtvol,nspinor
      72              :  integer,intent(in) :: isppol,ikpt,inonsc,istep,nbdbuf
      73              :  type(gs_hamiltonian_type),target,intent(inout) :: gs_hamk
      74              :  type(dataset_type)              ,intent(in   ) :: dtset
      75              :  type(mpi_type)           ,target,intent(in)    :: mpi_enreg
      76              :  real(dp)                 ,target,intent(inout) :: cg(2,nspinor*nband*npw)
      77              :  real(dp)                        ,intent(in   ) :: kinpw(npw)
      78              :  real(dp)                 ,target,intent(  out) :: resid(nband)
      79              :  real(dp)                        ,intent(  out) :: enl_out(nband)
      80              :  real(dp)                 ,target,intent(  out) :: eig(nband)
      81              :  real(dp)                 ,target,intent(in   ) :: occ(nband)
      82              :  type(xg_nonlop_t)        ,target,intent(in   ) :: xg_nonlop
      83              : 
      84              : !Local variables-------------------------------
      85              : 
      86              :  type(xgBlock_t) :: xgx0
      87              :  !type(xgBlock_t) :: cprj_xgx0
      88              :  type(xg_t) :: cprj_xgx0
      89              :  type(xgBlock_t) :: xgeigen
      90              :  type(xgBlock_t) :: xgresidu
      91              :  type(xgBlock_t) :: xgocc
      92              :  type(xgBlock_t) :: xgenl
      93              :  type(xgBlock_t) :: xg_precond,xg_kin
      94         4036 :  type(lobpcg_t) :: lobpcg
      95              : 
      96              :  integer :: space, space_cprj, blockdim, cprjdim, nband_cprj
      97              :  integer :: me_g0, me_g0_fft
      98              : 
      99              :  integer, parameter :: tim_lobpcgwf2 = 2030
     100              :  real(dp) :: tsec(2)
     101              : 
     102         4036 :  real(dp), allocatable :: occ_tmp(:)
     103              :  ! Important things for NC
     104         4036 :  real(dp), allocatable :: pcon(:),kin(:)
     105              : ! real(dp), allocatable :: cprj_contiguous(:,:)
     106              : 
     107              : ! *********************************************************************
     108              : 
     109         4036 :  call timab(tim_lobpcgwf2,1,tsec)
     110              : 
     111              :  ! Set module variables
     112         4036 :  l_prtvol = prtvol
     113         4036 :  l_mpi_enreg => mpi_enreg
     114         4036 :  l_gs_hamk => gs_hamk
     115              : 
     116         4036 :  cprjdim = xg_nonlop%cprjdim
     117              : 
     118              : !Variables
     119         4036 :  blockdim=nband/dtset%nblock_lobpcg
     120         4036 :  if (blockdim/=mpi_enreg%nproc_band*mpi_enreg%bandpp) then
     121            0 :    ABI_ERROR('blockdim is not consistent with nproc_band and bandpp')
     122              :  end if
     123         4036 :  nband_cprj=nband/mpi_enreg%nproc_band
     124              : 
     125              : !Depends on istwfk
     126         4036 :  if ( gs_hamk%istwf_k > 1 ) then ! Real only
     127              :    ! SPACE_CR mean that we have complex numbers but no re*im terms only re*re
     128              :    ! and im*im so that a vector of complex is consider as a long vector of real
     129              :    ! therefore the number of data is (2*npw*nspinor)*nband
     130              :    ! This space is completely equivalent to SPACE_R but will correctly set and
     131              :    ! get the array data into the xgBlock
     132         2124 :    space      = SPACE_CR
     133              :  else ! complex
     134         1912 :    space      = SPACE_C
     135              :  end if
     136         4036 :  space_cprj = xg_nonlop%space_cprj
     137              : 
     138              :  !For kinetic part of the Hamiltonian
     139        12108 :  ABI_MALLOC(kin,(npw))
     140         4036 :  call build_kin(kin,kinpw,npw)
     141         4036 :  call xgBlock_map_1d(xg_kin,kin,SPACE_R,npw)
     142              : 
     143              :  !For preconditionning
     144         8072 :  ABI_MALLOC(pcon,(npw))
     145         4036 :  call build_pcon(pcon,kinpw,npw)
     146              : 
     147              :  ! Local variables for lobpcg
     148         4036 :  me_g0 = -1
     149         4036 :  me_g0_fft = -1
     150         4036 :  if (space==SPACE_CR) then
     151         2124 :    me_g0 = 0
     152         2124 :    me_g0_fft = 0
     153         2124 :    if (gs_hamk%istwf_k == 2) then
     154          339 :      if (l_mpi_enreg%me_g0 == 1) me_g0 = 1
     155          339 :      if (l_mpi_enreg%me_g0_fft == 1) me_g0_fft = 1
     156              :    end if
     157              :  end if
     158         4036 :  call xgBlock_map(xgx0,cg,space,npw*nspinor,nband,l_mpi_enreg%comm_band,me_g0=me_g0)
     159              : 
     160         4036 :  call xgBlock_map_1d(xg_precond,pcon,SPACE_R,npw)
     161              : 
     162         4036 :  call xgBlock_map_1d(xgeigen,eig,SPACE_R,nband)
     163              : 
     164         4036 :  call xgBlock_map_1d(xgresidu,resid,SPACE_R,nband)
     165              : 
     166         4036 :  call xgBlock_map_1d(xgenl,enl_out,SPACE_R,nband)
     167              : 
     168         4036 :  call xg_init(cprj_xgx0,space_cprj,xg_nonlop%cprjdim,nband_cprj*nspinor,comm=l_mpi_enreg%comm_band)
     169              : 
     170              :  ! Occupancies in LOBPCG are used for convergence criteria only
     171         4036 :  if (dtset%nbdbuf==-101.and.nspinor==1.and.dtset%nsppol==1) then
     172            0 :    ABI_MALLOC(occ_tmp,(nband))
     173            0 :    occ_tmp(:) = half*occ(:)
     174            0 :    call xgBlock_map_1d(xgocc,occ_tmp,SPACE_R,nband,gpu_option=dtset%gpu_option)
     175              :  else
     176         4036 :    call xgBlock_map_1d(xgocc,occ,SPACE_R,nband,gpu_option=dtset%gpu_option)
     177              :  end if
     178              : 
     179              :  call lobpcg_init(lobpcg,mpi_enreg%bandpp,nband,npw*nspinor,cprjdim,blockdim,dtset%tolwfr_diago,dtset%nline,&
     180              :    space,space_cprj,l_mpi_enreg%comm_band,dtset%paral_kgb,xg_nonlop,l_mpi_enreg%comm_spinorfft,l_mpi_enreg%comm_band,&
     181         4036 :    me_g0,me_g0_fft)
     182              : 
     183              :  ! Run lobpcg
     184              :  call lobpcg_run_cprj(lobpcg,xgx0,cprj_xgx0%self,xg_getghc,xg_kin,xg_precond,xgeigen,xgocc,xgresidu,xgenl,&
     185         4036 :    prtvol,nspinor,isppol,ikpt,inonsc,istep,nbdbuf)
     186              : 
     187         4036 :  if (allocated(occ_tmp)) then
     188            0 :    ABI_FREE(occ_tmp)
     189              :  end if
     190              :  ! Free preconditionning since not needed anymore
     191         4036 :  ABI_FREE(pcon)
     192         4036 :  ABI_FREE(kin)
     193              : 
     194         4036 :  call xg_free(cprj_xgx0)
     195              : 
     196              :  ! Free lobpcg
     197         4036 :  call lobpcg_free(lobpcg)
     198              : 
     199         4036 :  call timab(tim_lobpcgwf2,2,tsec)
     200              : 
     201              :  DBG_EXIT("COLL")
     202              : 
     203         8072 : end subroutine lobpcgwf2_cprj
     204              : !!***
     205              : 
     206              : !!****f* m_lobpcg/xg_getghc
     207              : !! NAME
     208              : !! xg_getghc
     209              : !!
     210              : !! FUNCTION
     211              : !! This routine computes H|C> and possibly S|C> for a given wave function C.
     212              : !!  It acts as a driver for getghc, taken into account parallelism, multithreading, etc.
     213              : !!
     214              : !! SIDE EFFECTS
     215              : !!  X  <type(xgBlock_t)>= memory block containing |C>
     216              : !!  AX <type(xgBlock_t)>= memory block containing H|C>
     217              : !!
     218              : !! SOURCE
     219              : !
     220        75096 : subroutine xg_getghc(X,AX)
     221              : 
     222              : !Arguments ------------------------------------
     223              :  type(xgBlock_t), intent(inout) :: X
     224              :  type(xgBlock_t), intent(inout) :: AX
     225              : 
     226              : !Local variables-------------------------------
     227              : !scalars
     228              :  integer         :: blockdim
     229              :  integer         :: spacedim
     230              :  integer,parameter :: sij_opt=0,cpopt=-1,type_calc=1 ! Compute local part only
     231              : ! integer :: iatom,iband,ispinor,cprj_index,cprj_rows,cprj_cols,ncpgr,nlmn
     232              :  real(dp) :: eval
     233      1051344 :  type(pawcprj_type) :: cprj_dum(l_gs_hamk%natom,1)
     234              : !arrays
     235        75096 :  real(dp), pointer :: cg(:,:)
     236        75096 :  real(dp), pointer :: ghc(:,:)
     237              :  real(dp) :: gsc(1,1),gvnlxc(1,1)
     238              : 
     239              : ! *********************************************************************
     240              : 
     241        75096 :  call xgBlock_getSize(X,spacedim,blockdim)
     242        75096 :  call xgBlock_check(X,AX)
     243              : 
     244        75096 :  call xgBlock_reverseMap(X,cg,rows=1,cols=spacedim*blockdim)
     245        75096 :  call xgBlock_reverseMap(AX,ghc,rows=1,cols=spacedim*blockdim)
     246              : 
     247              :  ! Apply only local part of the Hamiltonian
     248              :  call multithreaded_getghc(cpopt,cg,cprj_dum,ghc,gsc,&
     249        75096 :    l_gs_hamk,gvnlxc,eval,l_mpi_enreg,blockdim,l_prtvol,sij_opt,l_tim_getghc,type_calc)
     250              : 
     251       150192 : end subroutine xg_getghc
     252              : !!***
     253              : 
     254         4036 : subroutine build_pcon(pcon,kinpw,npw)
     255              : 
     256              :   integer,intent(in) :: npw
     257              :   real(dp),intent(in) :: kinpw(:)
     258              :   real(dp),intent(out) :: pcon(:)
     259              : 
     260              :   integer :: ipw
     261              : 
     262              :   !$omp parallel do schedule(static), shared(pcon,kinpw)
     263       269445 :   do ipw=1,npw
     264       269445 :     if(kinpw(ipw)>huge(0.0_dp)*1.d-11) then
     265         5848 :       pcon(ipw)=0.d0
     266              :     else
     267              :       pcon(ipw) = (27+kinpw(ipw)*(18+kinpw(ipw)*(12+8*kinpw(ipw)))) &
     268       259561 : &     / (27+kinpw(ipw)*(18+kinpw(ipw)*(12+8*kinpw(ipw))) + 16*kinpw(ipw)**4)
     269              :     end if
     270              :   end do
     271              : 
     272         4036 : end subroutine build_pcon
     273              : 
     274         4036 : subroutine build_kin(kin,kinpw,npw)
     275              : 
     276              :   integer,intent(in) :: npw
     277              :   real(dp),intent(in) :: kinpw(:)
     278              :   real(dp),intent(out) :: kin(:)
     279              : 
     280              :   integer :: ipw
     281              : 
     282              :   !$omp parallel do schedule(static), shared(kin,kinpw)
     283       269445 :   do ipw=1,npw
     284       269445 :     if(kinpw(ipw)>huge(0.0_dp)*1.d-11) then
     285         5848 :       kin(ipw)=0.d0
     286              :     else
     287       259561 :       kin(ipw) = kinpw(ipw)
     288              :     end if
     289              :   end do
     290              : 
     291         4036 : end subroutine build_kin
     292              : 
     293              : end module m_lobpcgwf_cprj
     294              : !!***
        

Generated by: LCOV version 2.3-1