LCOV - code coverage report
Current view: top level - src/66_wfs - m_chebfi.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.7 % 229 210
Test Date: 2026-11-08 04:19:34 Functions: 100.0 % 2 2
Branches: 58.6 % 538 315

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_chebfi
       2                 :             : !! NAME
       3                 :             : !!  m_chebfi
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 2014-2026 ABINIT group (AL)
      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                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_chebfi
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_errors
      26                 :             :  use m_xmpi
      27                 :             :  use m_abicore
      28                 :             :  use m_abi_linalg
      29                 :             :  use m_rayleigh_ritz
      30                 :             :  use m_invovl
      31                 :             :  use m_dtset
      32                 :             : 
      33                 :             :  use defs_abitypes, only : mpi_type
      34                 :             :  use m_time,          only : timab
      35                 :             :  use m_cgtools,       only : dotprod_g
      36                 :             :  use m_bandfft_kpt,   only : bandfft_kpt, bandfft_kpt_get_ikpt
      37                 :             :  use m_pawcprj,       only : pawcprj_type, pawcprj_alloc, pawcprj_free, pawcprj_axpby, pawcprj_copy
      38                 :             :  use m_hamiltonian,   only : gs_hamiltonian_type
      39                 :             :  use m_getghc,        only : getghc
      40                 :             :  use m_prep_kgb,      only : prep_getghc, prep_index_wavef_bandpp
      41                 :             : 
      42                 :             :  implicit none
      43                 :             : 
      44                 :             :  private
      45                 :             : !!***
      46                 :             : 
      47                 :             :  public :: chebfi
      48                 :             : !!***
      49                 :             : 
      50                 :             : contains
      51                 :             : !!***
      52                 :             : 
      53                 :             : 
      54                 :             : !!****f* ABINIT/chebfi
      55                 :             : !! NAME
      56                 :             : !! chebfi
      57                 :             : !!
      58                 :             : !! FUNCTION
      59                 :             : !! this routine updates the wave functions at a given k-point,
      60                 :             : !! using the ChebFi method (see paper by A. Levitt and M. Torrent)
      61                 :             : !!
      62                 :             : !! INPUTS
      63                 :             : !!  dtset <type(dataset_type)>=all input variales for this dataset
      64                 :             : !!  gs_hamk <type(gs_hamiltonian_type)>=all data for the hamiltonian at k
      65                 :             : !!  kinpw(npw)=(modified) kinetic energy for each plane wave (hartree)
      66                 :             : !!  mpi_enreg=information about MPI parallelization
      67                 :             : !!  nband=number of bands at this k point for that spin polarization
      68                 :             : !!  npw=number of plane waves at this k point
      69                 :             : !!  nspinor=number of plane waves at this k point
      70                 :             : !!  prtvol=control print volume and debugging output
      71                 :             : !!
      72                 :             : !! OUTPUT
      73                 :             : !!  eig(nband)=array for holding eigenvalues (hartree)
      74                 :             : !!  resid(nband)=residuals for each states
      75                 :             : !!  If gs_hamk%usepaw==1:
      76                 :             : !!    gsc(2,*)=<g|s|c> matrix elements (s=overlap)
      77                 :             : !!  If gs_hamk%usepaw==0
      78                 :             : !!    enlx(nband)=contribution from each band to nonlocal psp + potential Fock ACE part of total energy, at this k-point
      79                 :             : !!
      80                 :             : !! SIDE EFFECTS
      81                 :             : !!  cg(2,*)=updated wavefunctions
      82                 :             : !!
      83                 :             : !! NOTES
      84                 :             : !!  -- TODO --
      85                 :             : !!  Normev?
      86                 :             : !!  Ecutsm
      87                 :             : !!  nspinor 2
      88                 :             : !!  spinors parallelisation
      89                 :             : !!  fock
      90                 :             : !!  -- Performance --
      91                 :             : !!  Improve load balancing
      92                 :             : !!  Don't diagonalize converged eigenvectors, just orthogonalize
      93                 :             : !!  Maybe don't diagonalize so often (once every two outer iterations?)
      94                 :             : !!  Benchmark diagonalizations, choose np_slk
      95                 :             : !!  How to chose npfft?
      96                 :             : !!  Implement MINRES for invovl
      97                 :             : !!  -- LOBPCG --
      98                 :             : !!  Improve stability (see paper by Lehoucq Sorensen, maybe use bunch-kaufman factorizations?)
      99                 :             : !!
     100                 :             : !! SOURCE
     101                 :             : 
     102                 :          48 : subroutine chebfi(cg,dtset,eig,enlx,gs_hamk,gsc,kinpw,mpi_enreg,nband,npw,nspinor,prtvol,resid)
     103                 :             : 
     104                 :             : !Arguments ------------------------------------
     105                 :             :  type(gs_hamiltonian_type),intent(inout) :: gs_hamk
     106                 :             :  type(dataset_type),intent(in) :: dtset
     107                 :             :  type(mpi_type),intent(inout) :: mpi_enreg
     108                 :             :  integer,intent(in) :: nband,npw,prtvol,nspinor
     109                 :             :  real(dp),intent(inout), target :: cg(2,npw*nspinor*nband),gsc(2,npw*nspinor*nband)
     110                 :             :  real(dp),intent(in) :: kinpw(npw)
     111                 :             :  real(dp),intent(out) :: resid(nband)
     112                 :             :  real(dp),intent(out) :: enlx(nband)
     113                 :             :  real(dp),intent(out) :: eig(nband)
     114                 :             : 
     115                 :             : !Local variables-------------------------------
     116                 :          96 :  real(dp) :: pcon(npw)
     117                 :             :  real(dp) :: filter_low
     118                 :             :  real(dp) :: filter_center, filter_radius
     119                 :         144 :  real(dp), dimension(2, npw*nspinor*nband), target :: ghc, gvnlxc
     120                 :          48 :  real(dp), allocatable, dimension(:,:) :: cg_filter_next, cg_filter_prev, gsm1hc_filter, gsc_filter_prev, gsc_filter_next
     121                 :          48 :  real(dp), allocatable, dimension(:,:), target :: cg_alltoall1,gsc_alltoall1,ghc_alltoall1,gvnlxc_alltoall1
     122                 :          48 :  real(dp), allocatable, dimension(:,:), target :: cg_alltoall2,gsc_alltoall2,ghc_alltoall2,gvnlxc_alltoall2
     123                 :          48 :  real(dp), pointer, dimension(:,:) :: cg_filter, gsc_filter, ghc_filter, gvnlxc_filter
     124                 :          96 :  real(dp) :: resid_vec(2, npw*nspinor)
     125                 :             :  logical :: has_fock,paw
     126                 :             :  integer :: shift, shift_cg_loadbalanced
     127                 :             :  integer :: iband, ideg, ispinor
     128                 :             :  integer :: sij_opt, cpopt
     129                 :             :  real(dp) :: eval, tsec(2)
     130                 :             :  integer :: tim_getghc = 5, ierr
     131                 :             :  integer :: i
     132                 :          48 :  integer, allocatable :: index_wavef_band(:)
     133                 :             :  real(dp) :: maxeig, mineig
     134                 :          48 :  real(dp), allocatable :: resids_filter(:), residvec_filter(:,:)
     135                 :          48 :  integer, allocatable :: ndeg_filter_bands(:)
     136                 :             :  integer :: iactive, nactive
     137                 :             :  real(dp) :: ampfactor
     138                 :             :  integer :: ndeg_filter_max, ndeg_filter_decrease, ndeg_filter_tolwfr
     139                 :             :  ! real(dp) :: load_imbalance
     140                 :             :  integer :: mcg
     141                 :             :  real(dp) :: dprod_r, dprod_i
     142                 :             :  character(len=500) :: message
     143                 :          96 :  integer :: rdisplsloc(mpi_enreg%nproc_band), recvcountsloc(mpi_enreg%nproc_band)
     144                 :          96 :  integer :: sdisplsloc(mpi_enreg%nproc_band), sendcountsloc(mpi_enreg%nproc_band)
     145                 :             :  integer :: ikpt_this_proc, npw_filter, nband_filter
     146                 :          48 :  type(pawcprj_type), allocatable :: cwaveprj(:,:), cwaveprj_next(:,:), cwaveprj_prev(:,:)
     147                 :             :  ! integer :: ndeg_filter_total
     148                 :             : 
     149                 :             :  ! timers
     150                 :             :  integer, parameter :: timer_chebfi = 1600, timer_alltoall = 1601, timer_apply_inv_ovl = 1602, timer_rotation = 1603
     151                 :             :  integer, parameter :: timer_subdiago = 1604, timer_subham = 1605, timer_ortho = 1606, timer_getghc = 1607
     152                 :             :  integer, parameter :: timer_residuals = 1608, timer_update_eigen = 1609, timer_sync = 1610
     153                 :             : 
     154                 :             : ! *************************************************************************
     155                 :             : 
     156                 :             :  !======================================================================================================
     157                 :             :  ! Initialize, transpose input cg if paral_kgb
     158                 :             :  !======================================================================================================
     159                 :          48 :  call timab(timer_chebfi,1,tsec)
     160                 :             : 
     161                 :             :  !Initializations
     162                 :          48 :  paw = gs_hamk%usepaw == 1
     163                 :          48 :  has_fock=(associated(gs_hamk%fockcommon))
     164                 :          48 :  mcg = npw*nspinor*nband
     165                 :             : 
     166                 :             :  ! Init pcon
     167         [ +  + ]:        3156 :  pcon = (27+kinpw*(18+kinpw*(12+8*kinpw))) / (27+kinpw*(18+kinpw*(12+8*kinpw)) + 16*kinpw**4)
     168                 :             : 
     169   [ +  +  +  +  :      223824 :  ghc=zero; gvnlxc=zero
             +  +  +  + ]
     170                 :             : 
     171                 :             :  ! Initialize the _filter pointers. Depending on paral_kgb, they might point to the actual arrays or to _alltoall variables
     172         [ +  - ]:          48 :  if (dtset%paral_kgb == 1) then
     173                 :          48 :    ikpt_this_proc = bandfft_kpt_get_ikpt()
     174                 :          48 :    npw_filter     = bandfft_kpt(ikpt_this_proc)%ndatarecv
     175                 :          48 :    nband_filter   = mpi_enreg%bandpp
     176                 :             : 
     177   [ -  +  +  -  :         144 :    ABI_MALLOC(cg_alltoall1,     (2, npw_filter*nspinor*nband_filter))
          +  -  +  -  -  
                +  -  + ]
     178   [ -  +  +  -  :          96 :    ABI_MALLOC(gsc_alltoall1,    (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     179   [ -  +  +  -  :          96 :    ABI_MALLOC(ghc_alltoall1,    (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     180   [ -  +  +  -  :          96 :    ABI_MALLOC(gvnlxc_alltoall1, (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     181   [ -  +  +  -  :          96 :    ABI_MALLOC(cg_alltoall2,     (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     182   [ -  +  +  -  :          96 :    ABI_MALLOC(gsc_alltoall2,    (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     183   [ -  +  +  -  :          96 :    ABI_MALLOC(ghc_alltoall2,    (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     184   [ -  +  +  -  :          96 :    ABI_MALLOC(gvnlxc_alltoall2, (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     185                 :             : 
     186                 :             :    ! Init tranpose variables
     187         [ +  + ]:         144 :    recvcountsloc = bandfft_kpt(ikpt_this_proc)%recvcounts * 2 * nspinor * mpi_enreg%bandpp
     188         [ +  + ]:         144 :    rdisplsloc    = bandfft_kpt(ikpt_this_proc)%rdispls    * 2 * nspinor * mpi_enreg%bandpp
     189         [ +  + ]:         144 :    sendcountsloc = bandfft_kpt(ikpt_this_proc)%sendcounts * 2 * nspinor
     190         [ +  + ]:         144 :    sdisplsloc    = bandfft_kpt(ikpt_this_proc)%sdispls    * 2 * nspinor
     191                 :             : 
     192                 :             :    ! Load balancing, so that each processor has approximately the same number of converged and non-converged bands
     193                 :             :    ! for two procs, rearrange 1 2 3 4 5 6 as 1 4 2 5 3 6
     194                 :             :    !
     195                 :             :    ! trick to save memory: ghc has the necessary size, and will be overwritten afterwards anyway
     196                 :             : #define cg_loadbalanced ghc
     197                 :          48 :    shift = 0
     198         [ +  + ]:         144 :    do i=1, mpi_enreg%nproc_band
     199         [ +  + ]:         720 :      do iband=1, mpi_enreg%bandpp
     200                 :         576 :        shift_cg_loadbalanced = (i-1 + (iband-1)*mpi_enreg%nproc_band)*npw*nspinor
     201   [ +  +  +  + ]:      112464 :        cg_loadbalanced(:, shift+1:shift+npw*nspinor) = cg(:, shift_cg_loadbalanced+1:shift_cg_loadbalanced+npw*nspinor)
     202                 :         672 :        shift = shift + npw*nspinor
     203                 :             :      end do
     204                 :             :    end do
     205                 :             : 
     206                 :             :    ! Transpose input cg into cg_alloall1. cg_alltoall1 is now (npw_filter, nband_filter)
     207                 :          48 :    call timab(timer_alltoall, 1, tsec)
     208                 :             :    call xmpi_alltoallv(cg_loadbalanced,sendcountsloc,sdisplsloc,cg_alltoall1,&
     209                 :          48 : &   recvcountsloc,rdisplsloc,mpi_enreg%comm_band,ierr)
     210                 :          48 :    call timab(timer_alltoall, 2, tsec)
     211                 :             : #undef cg_loadbalanced
     212                 :             : 
     213                 :             :    ! sort according to bandpp (from lobpcg, I don't fully understand what's going on but it works and it's fast)
     214                 :             :    call prep_index_wavef_bandpp(mpi_enreg%nproc_band,mpi_enreg%bandpp,&
     215                 :             :         &   nspinor,bandfft_kpt(ikpt_this_proc)%ndatarecv,&
     216                 :             :         &   bandfft_kpt(ikpt_this_proc)%recvcounts,bandfft_kpt(ikpt_this_proc)%rdispls,&
     217                 :          48 :         &   index_wavef_band)
     218                 :             : 
     219   [ +  +  +  + ]:      111936 :    cg_alltoall2(:,:) = cg_alltoall1(:,index_wavef_band)
     220                 :             : 
     221                 :          48 :    cg_filter => cg_alltoall2
     222                 :          48 :    gsc_filter => gsc_alltoall2
     223                 :          48 :    ghc_filter => ghc_alltoall2
     224                 :          48 :    gvnlxc_filter => gvnlxc_alltoall2
     225                 :             :  else
     226                 :           0 :    npw_filter = npw
     227                 :           0 :    nband_filter = nband
     228                 :             : 
     229                 :           0 :    cg_filter => cg
     230                 :           0 :    gsc_filter => gsc
     231                 :           0 :    ghc_filter => ghc
     232                 :           0 :    gvnlxc_filter => gvnlxc
     233                 :             :  end if
     234                 :             :  ! from here to the next alltoall, all computation is done on _filter variables, agnostic
     235                 :             :  ! to whether it's nband x npw (paral_kgb == 0) or ndatarecv*bandpp (paral_kgb = 1)
     236                 :             : 
     237                 :             :  ! Allocate filter variables for the application of the Chebyshev polynomial
     238   [ -  +  +  -  :         144 :  ABI_MALLOC(cg_filter_next, (2, npw_filter*nspinor*nband_filter))
          +  -  +  -  -  
                +  -  + ]
     239   [ -  +  +  -  :          96 :  ABI_MALLOC(cg_filter_prev, (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     240   [ -  +  +  -  :          96 :  ABI_MALLOC(gsc_filter_prev, (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     241   [ -  +  +  -  :          96 :  ABI_MALLOC(gsc_filter_next, (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     242   [ -  +  +  -  :          96 :  ABI_MALLOC(gsm1hc_filter, (2, npw_filter*nspinor*nband_filter))
             -  +  -  + ]
     243                 :             : 
     244                 :             :  ! PAW init
     245         [ +  - ]:          48 :  if(paw) then
     246   [ -  +  +  -  :        1056 :    ABI_MALLOC(cwaveprj, (gs_hamk%natom,nspinor*nband_filter))
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  -  +  +  
             +  +  +  +  
                      - ]
     247   [ -  +  +  -  :        1056 :    ABI_MALLOC(cwaveprj_next, (gs_hamk%natom,nspinor*nband_filter))
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  +  +  +  
                      + ]
     248   [ -  +  +  -  :        1056 :    ABI_MALLOC(cwaveprj_prev, (gs_hamk%natom,nspinor*nband_filter))
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  +  +  +  
                      + ]
     249                 :          48 :    call pawcprj_alloc(cwaveprj,0,gs_hamk%dimcprj)
     250                 :          48 :    call pawcprj_alloc(cwaveprj_next,0,gs_hamk%dimcprj)
     251                 :          48 :    call pawcprj_alloc(cwaveprj_prev,0,gs_hamk%dimcprj)
     252                 :             : 
     253                 :          48 :    sij_opt = 1 ! recompute S
     254                 :          48 :    cpopt = 0 ! save cprojs
     255                 :             :  else
     256                 :           0 :    sij_opt = 0
     257                 :           0 :    cpopt = -1
     258                 :             :  end if
     259                 :             : 
     260                 :             : 
     261                 :             : 
     262                 :             :  !======================================================================================================
     263                 :             :  ! Data in npfft x npband distribution. First getghc, update eigenvalues and residuals
     264                 :             :  !======================================================================================================
     265                 :          48 :  write(message, *) 'First getghc'
     266                 :          48 :  call wrtout(std_out,message,'COLL')
     267                 :             : 
     268                 :             :  ! get_ghc on cg
     269                 :          48 :  call timab(timer_getghc, 1, tsec)
     270         [ -  + ]:          48 :  if (dtset%paral_kgb == 0) then
     271                 :             :    call getghc(cpopt,cg_filter,cwaveprj,ghc_filter,gsc_filter,gs_hamk,gvnlxc_filter,&
     272                 :           0 : &   eval,mpi_enreg,nband,prtvol,sij_opt,tim_getghc,0)
     273                 :             :  else
     274                 :             :    call prep_getghc(cg_filter,gs_hamk,gvnlxc_filter,ghc_filter,gsc_filter,eval,nband,mpi_enreg,&
     275                 :          48 : &   prtvol,sij_opt,cpopt,cwaveprj,already_transposed=.true.)
     276                 :             :  end if
     277                 :          48 :  call timab(timer_getghc, 2, tsec)
     278                 :             : 
     279                 :             :  ! Debug barrier: should be invisible
     280                 :          48 :  call timab(timer_sync, 1, tsec)
     281                 :          48 :  call xmpi_barrier(mpi_enreg%comm_band)
     282                 :          48 :  call timab(timer_sync, 2, tsec)
     283                 :             : 
     284                 :          48 :  write(message, *) 'Computing residuals'
     285                 :          48 :  call wrtout(std_out,message,'COLL')
     286                 :             :  ! update eigenvalues and residuals
     287                 :          48 :  call timab(timer_update_eigen, 1, tsec)
     288   [ -  +  +  -  :         144 :  ABI_MALLOC(resids_filter, (nband_filter))
          +  -  +  -  -  
                +  -  + ]
     289   [ -  +  +  -  :         144 :  ABI_MALLOC(residvec_filter, (2, npw_filter*nspinor))
          +  -  +  -  -  
                +  -  + ]
     290   [ -  +  +  -  :         144 :  ABI_MALLOC(ndeg_filter_bands, (nband_filter))
          +  -  +  -  -  
                +  -  + ]
     291         [ +  + ]:         336 :  do iband=1, nband_filter
     292                 :         288 :    shift = npw_filter*nspinor*(iband-1)
     293                 :             :    call dotprod_g(eig(iband),dprod_i,gs_hamk%istwf_k,npw_filter*nspinor,1,ghc_filter(:, shift+1:shift+npw_filter*nspinor),&
     294   [ -  +  -  + ]:         288 : &   cg_filter(:, shift+1:shift+npw_filter*nspinor),mpi_enreg%me_g0,mpi_enreg%comm_spinorfft)
     295         [ -  + ]:         288 :    if(paw) then
     296                 :             :      call dotprod_g(dprod_r,dprod_i,gs_hamk%istwf_k,npw_filter*nspinor,1,gsc_filter(:, shift+1:shift+npw_filter*nspinor),&
     297   [ -  +  -  + ]:         288 : &     cg_filter(:, shift+1:shift+npw_filter*nspinor),mpi_enreg%me_g0,mpi_enreg%comm_spinorfft)
     298                 :         288 :      eig(iband) = eig(iband)/dprod_r
     299                 :             :    end if
     300                 :             : 
     301                 :             :    if(paw) then
     302                 :             :      residvec_filter = ghc_filter(:, shift+1 : shift+npw_filter*nspinor) &
     303   [ +  -  -  +  :      112464 : &     - eig(iband)*gsc_filter(:, shift+1 : shift+npw_filter*nspinor)
          -  -  +  +  +  
                      + ]
     304                 :             :    else
     305                 :             :      residvec_filter = ghc_filter(:, shift+1 : shift+npw_filter*nspinor) &
     306   [ #  #  #  #  :           0 : &     - eig(iband)*cg_filter(:, shift+1 : shift+npw_filter*nspinor)
          #  #  #  #  #  
                      # ]
     307                 :             :    end if
     308   [ +  +  +  + ]:      112224 :    resids_filter(iband) = SUM(residvec_filter**2)
     309                 :             :  end do
     310                 :          48 :  call xmpi_sum(resids_filter,mpi_enreg%comm_fft,ierr)
     311   [ +  -  -  +  :         384 :  call xmpi_max(MAXVAL(eig(1:nband_filter)),maxeig,mpi_enreg%comm_band,ierr)
             -  -  +  + ]
     312   [ +  -  -  +  :         384 :  call xmpi_min(MINVAL(eig(1:nband_filter)),mineig,mpi_enreg%comm_band,ierr)
             -  -  +  + ]
     313                 :          48 :  filter_low = maxeig
     314                 :          48 :  call timab(timer_update_eigen, 2, tsec)
     315                 :             : 
     316                 :             :  ! Decide which polynomial filter degree per band is needed
     317                 :             :  ! don't go above this, or face bad conditioning of the Gram matrix.
     318                 :          48 :  ndeg_filter_max = cheb_oracle(mineig, filter_low, dtset%ecut, 1e-16_dp, 40)
     319         [ +  + ]:         336 :  do iband=1, nband_filter
     320                 :             :    ! Filter degree necessary to converge to tolwfr
     321                 :         288 :    ndeg_filter_tolwfr = cheb_oracle(eig(iband), filter_low, dtset%ecut, dtset%tolwfr_diago / resids_filter(iband), dtset%mdeg_filter)
     322                 :             :    ! Filter degree necessary to decrease residual by a constant factor
     323                 :             :    ndeg_filter_decrease = cheb_oracle(eig(iband), filter_low, dtset%ecut, 0.1_dp, dtset%mdeg_filter)
     324                 :             : 
     325                 :         288 :    ndeg_filter_bands(iband) = MAX(MIN(ndeg_filter_tolwfr, ndeg_filter_decrease, ndeg_filter_max, dtset%mdeg_filter), 1)
     326                 :         336 :    ndeg_filter_bands(iband) = dtset%mdeg_filter ! fiddle with this to use locking
     327                 :             :  end do
     328                 :             : 
     329                 :             : 
     330                 :             :  !!!!! Uncomment for diagnostics
     331                 :             :  ! ndeg_filter_total = SUM(ndeg_filter_bands)
     332                 :             :  ! call xmpi_sum(ndeg_filter_total, mpi_enreg%comm_band, ierr)
     333                 :             :  ! load_imbalance = (SUM(ndeg_filter_bands) - REAL(ndeg_filter_total)/REAL(mpi_enreg%nproc_band)) / &
     334                 :             :  ! &                (REAL(ndeg_filter_total)/REAL(mpi_enreg%nproc_band))
     335                 :             :  ! call xmax_mpi(load_imbalance, mpi_enreg%comm_band, ierr)
     336                 :             : 
     337                 :             :  ! write(message, *) 'Mean ndeg_filter', REAL(ndeg_filter_total)/REAL(nband), 'max imbalance (%)', load_imbalance*100
     338                 :             :  ! call wrtout(std_out,message,'COLL')
     339                 :             : 
     340         [ -  + ]:          48 :  ABI_FREE(resids_filter)
     341         [ -  + ]:          48 :  ABI_FREE(residvec_filter)
     342                 :             : 
     343                 :             :  !======================================================================================================
     344                 :             :  ! Chebyshev polynomial application
     345                 :             :  !======================================================================================================
     346                 :             :  ! Filter by a chebyshev polynomial of max. degree mdeg_filter
     347         [ +  + ]:         336 :  do ideg=1,dtset%mdeg_filter
     348                 :             :    ! Filter only on [iactive, iactive+nactive-1]
     349                 :         288 :    iactive = nband_filter
     350         [ +  - ]:         288 :    do iband = 1, nband_filter
     351                 :             :      ! does iband need a higher degree for polynomila filter?
     352         [ -  + ]:         288 :      if (ndeg_filter_bands(iband) >= ideg) then
     353                 :             :        iactive = iband
     354                 :             :        exit
     355                 :             :      end if
     356                 :             :    end do
     357                 :         288 :    nactive = nband_filter - iactive + 1
     358                 :         288 :    shift = npw_filter*nspinor*(iactive-1) + 1
     359                 :             :    ! trick the legacy prep_getghc
     360                 :         288 :    mpi_enreg%bandpp = nactive
     361                 :             : 
     362                 :             :    ! Define the filter position
     363                 :         288 :    filter_center = (dtset%ecut+filter_low)/2
     364                 :         288 :    filter_radius = (dtset%ecut-filter_low)/2
     365                 :             : 
     366                 :             :    ! write(message, *) 'Applying invovl, iteration', ideg
     367                 :             :    ! call wrtout(std_out,message,'COLL')
     368                 :             : 
     369                 :             :    ! If paw, have to apply S^-1
     370         [ +  - ]:         288 :    if(paw) then
     371                 :         288 :      call timab(timer_apply_inv_ovl, 1, tsec)
     372                 :             :      call apply_invovl(gs_hamk, ghc_filter(:,shift:), gsm1hc_filter(:,shift:), cwaveprj_next(:,iactive:), &
     373         [ -  + ]:         288 : &     npw_filter, nactive, mpi_enreg, nspinor, dtset%invovl_blksliced, dtset%invovl_precision)
     374                 :         288 :      call timab(timer_apply_inv_ovl, 2, tsec)
     375                 :             :    else
     376   [ #  #  #  # ]:           0 :      gsm1hc_filter(:,shift:) = ghc_filter(:,shift:)
     377                 :             :    end if
     378                 :             : 
     379                 :             :    ! Chebyshev iteration: UPDATE cg
     380         [ +  + ]:         288 :    if(ideg == 1) then
     381   [ +  +  +  + ]:      111936 :      cg_filter_next(:,shift:) = one/filter_radius * (gsm1hc_filter(:,shift:) - filter_center*cg_filter(:,shift:))
     382                 :             :    else
     383                 :             :      cg_filter_next(:,shift:) = two/filter_radius * (gsm1hc_filter(:,shift:) - filter_center*cg_filter(:,shift:)) &
     384   [ +  +  +  + ]:      559680 : &     - cg_filter_prev(:,shift:)
     385                 :             :    end if
     386                 :             :    ! Update gsc and cwaveprj
     387         [ +  - ]:         288 :    if(paw) then
     388         [ +  + ]:         288 :      if(ideg == 1) then
     389   [ +  +  +  + ]:      111936 :        gsc_filter_next(:,shift:) = one/filter_radius * (ghc_filter(:,shift:) - filter_center*gsc_filter(:,shift:))
     390                 :             :        !cwaveprj_next = one/filter_radius * (cwaveprj_next - filter_center*cwaveprj)
     391                 :          48 :        call pawcprj_axpby(-filter_center/filter_radius, one/filter_radius,cwaveprj(:,iactive:),cwaveprj_next(:,iactive:))
     392                 :             :      else
     393                 :             :        gsc_filter_next(:,shift:) = two/filter_radius * (ghc_filter(:,shift:) - filter_center*gsc_filter(:,shift:))&
     394   [ +  +  +  + ]:      559680 : &       - gsc_filter_prev(:,shift:)
     395                 :             :        !cwaveprj_next = two/filter_radius * (cwaveprj_next - filter_center*cwaveprj) - cwaveprj_prev
     396                 :         240 :        call pawcprj_axpby(-two*filter_center/filter_radius, two/filter_radius,cwaveprj(:,iactive:),cwaveprj_next(:,iactive:))
     397                 :         240 :        call pawcprj_axpby(-one, one,cwaveprj_prev(:,iactive:),cwaveprj_next(:,iactive:))
     398                 :             :      end if
     399                 :             :    end if
     400                 :             : 
     401                 :             :    ! Bookkeeping of the _prev variables
     402   [ +  +  +  + ]:      671616 :    cg_filter_prev(:,shift:) = cg_filter(:,shift:)
     403   [ +  +  +  + ]:      671616 :    cg_filter(:,shift:) = cg_filter_next(:,shift:)
     404         [ -  + ]:         288 :    if(paw) then
     405   [ +  +  +  + ]:      671616 :      gsc_filter_prev(:,shift:) = gsc_filter(:,shift:)
     406   [ +  +  +  + ]:      671616 :      gsc_filter(:,shift:) = gsc_filter_next(:,shift:)
     407                 :             : 
     408                 :         288 :      call pawcprj_copy(cwaveprj(:,iactive:),cwaveprj_prev(:,iactive:))
     409                 :         288 :      call pawcprj_copy(cwaveprj_next(:,iactive:),cwaveprj(:,iactive:))
     410                 :             :    end if
     411                 :             : 
     412                 :             :    ! Update ghc
     413                 :             :    if(paw) then
     414                 :             :      !! DEBUG use this to remove the optimization and recompute gsc/cprojs
     415                 :             :      ! sij_opt = 1
     416                 :             :      ! cpopt = 0
     417                 :             : 
     418                 :         288 :      sij_opt = 0 ! gsc is already computed
     419                 :         288 :      cpopt = 2 ! reuse cprojs
     420                 :             :    else
     421                 :           0 :      sij_opt = 0
     422                 :           0 :      cpopt = -1
     423                 :             :    end if
     424                 :             : 
     425                 :         288 :    write(message, *) 'Getghc, degree of polynom', ideg
     426                 :         288 :    call wrtout(std_out,message,'COLL')
     427                 :             : 
     428                 :         288 :    call timab(timer_getghc, 1, tsec)
     429         [ -  + ]:         288 :    if (dtset%paral_kgb == 0) then
     430                 :             :      call getghc(cpopt,cg_filter(:,shift:),cwaveprj(:,iactive:),ghc_filter(:,shift:),&
     431                 :             : &     gsc_filter(:,shift:),gs_hamk,gvnlxc_filter(:,shift:),eval,mpi_enreg,&
     432                 :           0 : &     nband,prtvol,sij_opt,tim_getghc,0)
     433                 :             :    else
     434                 :             :      call prep_getghc(cg_filter(:,shift:),gs_hamk,gvnlxc_filter(:,shift:),ghc_filter(:,shift:),&
     435                 :             : &     gsc_filter(:,shift:),eval,nband,mpi_enreg,prtvol,sij_opt,cpopt,&
     436                 :         288 : &     cwaveprj(:,iactive:),already_transposed=.true.)
     437                 :             :    end if
     438                 :             : 
     439                 :             :    ! end of the trick
     440                 :         288 :    mpi_enreg%bandpp = nband_filter
     441                 :             : 
     442                 :         336 :    call timab(timer_getghc, 2, tsec)
     443                 :             :  end do ! end loop on ideg
     444                 :             : 
     445                 :             :  ! normalize according to the previously computed rayleigh quotients (inaccurate, but cheap)
     446         [ +  + ]:         336 :  do iband = 1, nband_filter
     447                 :         288 :    ampfactor = cheb_poly(eig(iband), ndeg_filter_bands(iband), filter_low, dtset%ecut)
     448         [ -  + ]:         288 :    if(abs(ampfactor) < 1e-3) ampfactor = 1e-3 ! just in case, avoid amplifying too much
     449                 :         288 :    shift = npw_filter*nspinor*(iband-1)
     450   [ +  +  +  + ]:      112176 :    cg_filter(:, shift+1:shift+npw_filter*nspinor) = cg_filter(:, shift+1:shift+npw_filter*nspinor) / ampfactor
     451   [ +  +  +  + ]:      112176 :    ghc_filter(:, shift+1:shift+npw_filter*nspinor) = ghc_filter(:, shift+1:shift+npw_filter*nspinor) / ampfactor
     452         [ +  - ]:         288 :    if(paw) then
     453   [ +  +  +  + ]:      112176 :      gsc_filter(:, shift+1:shift+npw_filter*nspinor) = gsc_filter(:, shift+1:shift+npw_filter*nspinor) / ampfactor
     454                 :             :    endif
     455         [ -  + ]:         336 :    if(.not.paw .or. has_fock)then
     456   [ #  #  #  # ]:           0 :      gvnlxc_filter(:, shift+1:shift+npw_filter*nspinor) = gvnlxc_filter(:, shift+1:shift+npw_filter*nspinor) / ampfactor
     457                 :             :    end if
     458                 :             :  end do
     459                 :             : 
     460                 :             :  ! Cleanup
     461         [ +  - ]:          48 :  if(paw) then
     462                 :          48 :    call pawcprj_free(cwaveprj)
     463                 :          48 :    call pawcprj_free(cwaveprj_next)
     464                 :          48 :    call pawcprj_free(cwaveprj_prev)
     465   [ +  -  +  +  :         624 :    ABI_FREE(cwaveprj)
          -  +  -  +  -  
                      + ]
     466   [ +  -  +  +  :         624 :    ABI_FREE(cwaveprj_next)
          -  +  -  +  -  
                      + ]
     467   [ +  -  +  +  :         624 :    ABI_FREE(cwaveprj_prev)
          -  +  -  +  -  
                      + ]
     468                 :             :  end if
     469         [ -  + ]:          48 :  ABI_FREE(ndeg_filter_bands)
     470         [ -  + ]:          48 :  ABI_FREE(cg_filter_next)
     471         [ -  + ]:          48 :  ABI_FREE(cg_filter_prev)
     472         [ -  + ]:          48 :  ABI_FREE(gsc_filter_prev)
     473         [ -  + ]:          48 :  ABI_FREE(gsc_filter_next)
     474         [ -  + ]:          48 :  ABI_FREE(gsm1hc_filter)
     475                 :             : 
     476                 :             :  !======================================================================================================
     477                 :             :  ! Filtering done, tranpose back
     478                 :             :  !======================================================================================================
     479                 :             : 
     480                 :          48 :  write(message, *) 'Filtering done, transposing back'
     481                 :          48 :  call wrtout(std_out,message,'COLL')
     482                 :             : 
     483                 :             :  ! transpose back
     484         [ -  + ]:          48 :  if(dtset%paral_kgb == 1) then
     485   [ +  +  +  + ]:      111936 :    cg_alltoall1(:,index_wavef_band) = cg_alltoall2(:,:)
     486   [ +  +  +  + ]:      111936 :    ghc_alltoall1(:,index_wavef_band) = ghc_alltoall2(:,:)
     487         [ +  - ]:          48 :    if(paw) then
     488   [ +  +  +  + ]:      111936 :      gsc_alltoall1(:,index_wavef_band) = gsc_alltoall2(:,:)
     489                 :             :    else
     490   [ #  #  #  # ]:           0 :      gvnlxc_alltoall1(:,index_wavef_band) = gvnlxc_alltoall2(:,:)
     491                 :             :    end if
     492                 :             : 
     493         [ -  + ]:          48 :    ABI_FREE(index_wavef_band)
     494                 :             : 
     495                 :          48 :    call timab(timer_sync, 1, tsec)
     496                 :          48 :    call xmpi_barrier(mpi_enreg%comm_band)
     497                 :          48 :    call timab(timer_sync, 2, tsec)
     498                 :             : 
     499                 :          48 :    call timab(timer_alltoall, 1, tsec)
     500                 :             : 
     501                 :             :   ! Do we pack the arrays in the alltoall, saving latency, or do we do it separately, saving memory and copies?
     502                 :             :    call xmpi_alltoallv(cg_alltoall1,recvcountsloc,rdisplsloc,cg,&
     503                 :          48 : &   sendcountsloc,sdisplsloc,mpi_enreg%comm_band,ierr)
     504                 :             :    call xmpi_alltoallv(ghc_alltoall1,recvcountsloc,rdisplsloc,ghc,&
     505                 :          48 : &   sendcountsloc,sdisplsloc,mpi_enreg%comm_band,ierr)
     506         [ +  - ]:          48 :    if(paw) then
     507                 :             :      call xmpi_alltoallv(gsc_alltoall1,recvcountsloc,rdisplsloc,gsc,&
     508                 :          48 : &     sendcountsloc,sdisplsloc,mpi_enreg%comm_band,ierr)
     509                 :             :    else
     510                 :             :      call xmpi_alltoallv(gvnlxc_alltoall1,recvcountsloc,rdisplsloc,gvnlxc,&
     511                 :           0 : &     sendcountsloc,sdisplsloc,mpi_enreg%comm_band,ierr)
     512                 :             :    end if
     513                 :          48 :    call timab(timer_alltoall, 2, tsec)
     514                 :             : 
     515         [ -  + ]:          48 :    if(mpi_enreg%paral_kgb == 1) then
     516         [ -  + ]:          48 :      ABI_FREE(cg_alltoall1)
     517         [ -  + ]:          48 :      ABI_FREE(gsc_alltoall1)
     518         [ -  + ]:          48 :      ABI_FREE(ghc_alltoall1)
     519         [ -  + ]:          48 :      ABI_FREE(gvnlxc_alltoall1)
     520         [ -  + ]:          48 :      ABI_FREE(cg_alltoall2)
     521         [ -  + ]:          48 :      ABI_FREE(gsc_alltoall2)
     522         [ -  + ]:          48 :      ABI_FREE(ghc_alltoall2)
     523         [ -  + ]:          48 :      ABI_FREE(gvnlxc_alltoall2)
     524                 :             :    end if
     525                 :             :  else
     526                 :             :    ! nothing to do, the _filter variables already point to the right ones
     527                 :             :  end if
     528                 :             : 
     529                 :             : 
     530                 :             : 
     531                 :             :  !======================================================================================================
     532                 :             :  ! Data in (npfft*npband) x 1 distribution. Rayleigh-Ritz step
     533                 :             :  !======================================================================================================
     534                 :             : 
     535                 :             :  ! _subdiago might use less memory when using only one proc, should maybe call it, or just remove it
     536                 :             :  ! and always call _distributed
     537                 :             : #if defined HAVE_LINALG_SCALAPACK
     538                 :             :  call rayleigh_ritz_distributed(cg,ghc,gsc,gvnlxc,eig,has_fock,gs_hamk%istwf_k,mpi_enreg,nband,npw,nspinor,gs_hamk%usepaw)
     539                 :             : #else
     540                 :          48 :  call rayleigh_ritz_subdiago(cg,ghc,gsc,gvnlxc,eig,has_fock,gs_hamk%istwf_k,mpi_enreg,nband,npw,nspinor,gs_hamk%usepaw)
     541                 :             : #endif
     542                 :             : 
     543                 :             :  ! Build residuals
     544                 :          48 :  call timab(timer_residuals, 1, tsec)
     545         [ +  + ]:         624 :  do iband=1,nband
     546                 :         576 :    shift = npw*nspinor*(iband-1)
     547         [ +  - ]:         576 :    if(paw) then
     548   [ +  +  +  + ]:      112464 :      resid_vec = ghc(:, shift+1 : shift+npw*nspinor) - eig(iband)*gsc(:, shift+1 : shift+npw*nspinor)
     549                 :             :    else
     550   [ #  #  #  # ]:           0 :      resid_vec = ghc(:, shift+1 : shift+npw*nspinor) - eig(iband)*cg (:, shift+1 : shift+npw*nspinor)
     551                 :             :    end if
     552                 :             : 
     553                 :             :    ! precondition resid_vec
     554         [ +  + ]:        1152 :    do ispinor = 1,nspinor
     555         [ +  + ]:       37872 :      resid_vec(1, npw*(ispinor-1)+1:npw*ispinor) = resid_vec(1, npw*(ispinor-1)+1:npw*ispinor) * pcon
     556         [ +  + ]:       38448 :      resid_vec(2, npw*(ispinor-1)+1:npw*ispinor) = resid_vec(2, npw*(ispinor-1)+1:npw*ispinor) * pcon
     557                 :             :    end do
     558                 :             : 
     559                 :             :    call dotprod_g(resid(iband),dprod_i,gs_hamk%istwf_k,npw*nspinor,1,resid_vec,&
     560                 :         576 : &   resid_vec,mpi_enreg%me_g0,mpi_enreg%comm_bandspinorfft)
     561                 :             : 
     562   [ +  -  -  + ]:         624 :    if(.not. paw .or. has_fock) then
     563                 :             :      call dotprod_g(enlx(iband),dprod_i,gs_hamk%istwf_k,npw*nspinor,1,cg(:, shift+1:shift+npw*nspinor),&
     564                 :           0 : &     gvnlxc(:, shift+1:shift+npw_filter*nspinor),mpi_enreg%me_g0,mpi_enreg%comm_bandspinorfft)
     565                 :             :    end if
     566                 :             :  end do
     567                 :          48 :  call timab(timer_residuals, 2, tsec)
     568                 :             : 
     569                 :             :  ! write(message, '(a,4e10.2)') 'Resids (1, N, min, max) ', resid(1), resid(nband), MINVAL(resid), MAXVAL(resid)
     570                 :             :  ! call wrtout(std_out,message,'COLL')
     571                 :             : 
     572                 :             :  ! write(message,*)'Eigens(1,nocc,nband) ',eig(1), eig(ilastocc),eig(nband)
     573                 :             :  ! call wrtout(std_out,message,'COLL')
     574                 :             :  ! write(message,*)'Resids(1,nocc,nband) ',resid(1), resid(ilastocc),resid(nband)
     575                 :             :  ! call wrtout(std_out,message,'COLL')
     576                 :             : 
     577                 :          48 :  call timab(timer_chebfi,2,tsec)
     578                 :             : 
     579   [ -  +  -  +  :         144 : end subroutine chebfi
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  -  
          -  -  -  -  +  
          -  -  -  -  -  
          -  -  +  -  -  
          -  -  -  -  -  
                +  -  + ]
     580                 :             : !!***
     581                 :             : 
     582                 :             : !!****f* ABINIT/cheb_poly
     583                 :             : !! NAME
     584                 :             : !! cheb_poly
     585                 :             : !!
     586                 :             : !! FUNCTION
     587                 :             : !! Computes the value of the Chebyshev polynomial of degree n on the interval [a,b] at x
     588                 :             : !!
     589                 :             : !! INPUTS
     590                 :             : !! x= input variable
     591                 :             : !! n= degree
     592                 :             : !! a= left bound of the interval
     593                 :             : !! b= right bound of the interval
     594                 :             : !!
     595                 :             : !! OUTPUT
     596                 :             : !! y= Tn(x)
     597                 :             : !!
     598                 :             : !! NOTES
     599                 :             : !!
     600                 :             : !! SOURCE
     601                 :             : 
     602                 :         288 : function cheb_poly(x, n, a, b) result(y)
     603                 :             : 
     604                 :             :  integer, intent(in) :: n
     605                 :             :  integer :: i
     606                 :             :  real(dp), intent(in) :: x, a, b
     607                 :             :  real(dp) :: y, xred, temp
     608                 :             :  real(dp) :: yim1
     609                 :             : 
     610                 :             : ! *************************************************************************
     611                 :             : 
     612                 :         288 :  xred = (x-(a+b)/2)/(b-a)*2
     613                 :         288 :  y = xred
     614                 :         288 :  yim1 = one
     615         [ +  + ]:        1728 :  do i=2, n
     616                 :        1440 :    temp = y
     617                 :        1440 :    y = 2*xred*y - yim1
     618                 :        1728 :    yim1 = temp
     619                 :             :  end do
     620                 :             : 
     621                 :         288 : end function cheb_poly
     622                 :             : !!***
     623                 :             : 
     624                 :             : !!****f* ABINIT/cheb_oracle
     625                 :             : !! NAME
     626                 :             : !! cheb_oracle
     627                 :             : !!
     628                 :             : !! FUNCTION
     629                 :             : !! Returns the number of necessary iterations to decrease residual by at least tol
     630                 :             : !! Here as in the rest of the code, the convention is that residuals are squared (||Ax-lx||^2)
     631                 :             : !!
     632                 :             : !! INPUTS
     633                 :             : !! x= input variable
     634                 :             : !! a= left bound of the interval
     635                 :             : !! b= right bound of the interval
     636                 :             : !! tol= needed precision
     637                 :             : !! nmax= max number of iterations
     638                 :             : !!
     639                 :             : !! OUTPUT
     640                 :             : !! n= number of iterations needed to decrease residual by tol
     641                 :             : !!
     642                 :             : !! NOTES
     643                 :             : !!
     644                 :             : !! SOURCE
     645                 :             : 
     646                 :             : function cheb_oracle(x, a, b, tol, nmax) result(n)
     647                 :             : 
     648                 :             :  real(dp) :: tol
     649                 :             : 
     650                 :             :  integer :: nmax
     651                 :             :  integer :: n, i
     652                 :             :  real(dp), intent(in) :: x, a, b
     653                 :             :  real(dp) :: y, xred, temp
     654                 :             :  real(dp) :: yim1
     655                 :             : 
     656                 :             : ! *************************************************************************
     657                 :             : 
     658                 :             :  xred = (x-(a+b)/2)/(b-a)*2
     659                 :             :  y = xred
     660                 :             :  yim1 = one
     661                 :             : 
     662                 :             :  n = nmax
     663                 :             :  if(1/(y**2) < tol) then
     664                 :             :    n = 1
     665                 :             :  else
     666                 :             :    do i=2, nmax-1
     667                 :             :      temp = y
     668                 :             :      y = 2*xred*y - yim1
     669                 :             :      yim1 = temp
     670                 :             :      if(1/(y**2) < tol) then
     671                 :             :        n = i
     672                 :             :        exit
     673                 :             :      end if
     674                 :             :    end do
     675                 :             :  end if
     676                 :             : 
     677                 :             : end function cheb_oracle
     678                 :             : !!***
     679                 :             : 
     680                 :             : end module m_chebfi
     681                 :             : !!***
        

Generated by: LCOV version 2.3-1