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-09-21 19:39:32 Functions: 100.0 % 2 2

            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)
     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