LCOV - code coverage report
Current view: top level - src/48_diago - m_chebfi2.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 30.1 % 999 301
Test Date: 2026-09-20 18:56:22 Functions: 36.7 % 30 11

            Line data    Source code
       1              : !!****f* ABINIT/m_chebfi2
       2              : !! NAME
       3              : !! m_chebfi2
       4              : !!
       5              : !! FUNCTION
       6              : !! This module contains the types and routines used to apply the
       7              : !! Chebyshev filtering method (2021 implementation using xG abstraction layer)
       8              : !! It mainly defines a 'chebfi' datatypes and associated methods.
       9              : !!
      10              : !! COPYRIGHT
      11              : !! Copyright (C) 2018-2026 ABINIT group (BS, L. Baguet, IML)
      12              : !! This file is distributed under the terms of the
      13              : !! gnu general public license, see ~abinit/COPYING
      14              : !! or http://www.gnu.org/copyleft/gpl.txt .
      15              : !! for the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      16              : !!
      17              : !! SOURCE
      18              : 
      19              : #if defined HAVE_CONFIG_H
      20              : #include "config.h"
      21              : #endif
      22              : 
      23              : #include "abi_common.h"
      24              : 
      25              : ! nvtx related macro definition
      26              : #include "nvtx_macros.h"
      27              : 
      28              : module m_chebfi2
      29              : 
      30              :  use defs_basis
      31              :  use defs_abitypes
      32              :  use m_abicore
      33              :  use m_errors
      34              :  use m_time, only : timab
      35              : 
      36              :  use m_cgtools
      37              :  use m_xg
      38              :  use m_xgTransposer
      39              :  use m_xg_ortho_RR
      40              :  use m_polynomial_filter
      41              : 
      42              :  use m_xmpi
      43              :  use m_xomp
      44              : #ifdef HAVE_OPENMP
      45              :  use omp_lib
      46              : #endif
      47              :  use, intrinsic :: iso_c_binding, only: c_size_t
      48              : 
      49              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
      50              :  use m_gpu_toolbox, only : CPU_DEVICE_ID, gpu_device_synchronize
      51              : #endif
      52              : 
      53              : #if defined(HAVE_GPU_MARKERS)
      54              :  use m_nvtx_data
      55              : #endif
      56              : 
      57              :  implicit none
      58              : 
      59              :  private
      60              : 
      61              : !Several (private) parameters
      62              : !-------------------------------------------------
      63              : 
      64              :  integer, parameter :: tim_init         = 1751
      65              :  integer, parameter :: tim_free         = 1752
      66              :  !                                        1753 is used by chebfi2_nonlop
      67              :  integer, parameter :: tim_getAX_BX     = 1754
      68              :  integer, parameter :: tim_invovl       = 1755
      69              :  integer, parameter :: tim_residu       = 1756
      70              :  integer, parameter :: tim_RR           = 1757
      71              :  integer, parameter :: tim_transpose    = 1758
      72              :  integer, parameter :: tim_RR_q         = 1759
      73              :  integer, parameter :: tim_postinvovl   = 1760
      74              :  integer, parameter :: tim_swap         = 1761
      75              :  integer, parameter :: tim_amp_f        = 1762
      76              :  integer, parameter :: tim_oracle       = 1763
      77              :  integer, parameter :: tim_barrier      = 1764
      78              :  integer, parameter :: tim_copy         = 1765
      79              : 
      80              : !Public 'chebfi' datatype
      81              : !-------------------------------------------------
      82              : 
      83              :  type, public :: chebfi_t
      84              :    integer :: space
      85              :    integer :: spacedim                      ! Space dimension for one vector
      86              :    integer :: total_spacedim                ! Maybe not needed
      87              :    integer :: neigenpairs                   ! Number of eigen values/vectors we want
      88              :    integer :: ndeg_filter                   ! Degree of the polynomial filter
      89              :    integer :: nbdbuf                        ! Number of bands in the buffer
      90              :    integer :: spacecom                      ! Communicator for MPI
      91              :    integer :: oracle                        ! Option to compute ndeg_filter from residuals
      92              :    real(dp) :: tolerance                    ! Tolerance on the residu to stop the minimization
      93              :    real(dp) :: ecut                         ! Ecut for Chebfi oracle
      94              :    real(dp) :: oracle_factor                ! factor used to decrease residuals
      95              :    real(dp) :: oracle_min_occ               ! threshold on occupancies used for nbdbuf=-101
      96              : 
      97              :    integer :: paral_kgb                     ! MPI parallelization variables
      98              :    integer :: bandpp
      99              :    integer :: comm_cols
     100              :    integer :: comm_rows
     101              :    integer :: me_g0
     102              :    integer :: me_g0_fft
     103              : 
     104              :    logical :: from_linalg    ! Transposer allocates representation ColsRows if true, Linalg if false
     105              :    logical :: paw
     106              :    integer :: eigenProblem   !1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
     107              : 
     108              :    ! when GPU with Kokkos is enabled, currently OpenMP is not fully supported, abinit is launched
     109              :    ! with OMP_NUM_THREADS=1, but we may locally increase the number of OpenMP threads
     110              :    ! wherever it is safe to do; in that case we use gpu_kokkos_nthrd to specify
     111              :    ! the number of OpenMP threads. This value is controlled by dtset variable
     112              :    ! dtset%gpu_kokkos_nthrd
     113              :    integer :: gpu_option
     114              :    integer :: gpu_kokkos_nthrd = 1 ! only used if GPU Kokkos is enabled, number of OpenMP threads used
     115              :    integer :: gpu_thread_limit = 1 ! only used if GPU is enabled, max number of OpenMP threads used in sensitive areas
     116              : 
     117              :    !ARRAYS
     118              :    type(xgBlock_t) :: X
     119              : 
     120              :    type(xg_t) :: X_NP
     121              :    type(xgBlock_t) :: X_next
     122              :    type(xgBlock_t) :: X_prev
     123              : 
     124              :    type(xg_t) :: AX
     125              :    type(xg_t) :: BX
     126              :    type(xg_t) :: xAXColsRows_W ! only used if from_linalg is false
     127              :    type(xg_t) :: xBXColsRows_W ! only used if from linalg is false
     128              : 
     129              :    type(xgBlock_t) :: xXColsRows
     130              :    type(xgBlock_t) :: xAXColsRows
     131              :    type(xgBlock_t) :: xBXColsRows
     132              : 
     133              :    type(xgTransposer_t) :: xgTransposerX
     134              :    type(xgTransposer_t) :: xgTransposerAX
     135              :    type(xgTransposer_t) :: xgTransposerBX
     136              : 
     137              :    type(xgBlock_t) :: eigenvalues
     138              : 
     139              :    !SWAP POINTERS
     140              :    type(xgBlock_t) :: X_swap
     141              :    type(xgBlock_t) :: AX_swap
     142              :    type(xgBlock_t) :: BX_swap
     143              : 
     144              :   end type chebfi_t
     145              : 
     146              :   ! Partition Info for column vectors X=(X_lock X_active)
     147              :   ! Function: handles MPI distribution variables and communicators
     148              :   !-------------------------------------------------
     149              :   type, private :: bandPartitionInfo_t
     150              : 
     151              :     integer :: n_locked           ! MPI size in linalg for locked
     152              :     integer :: n_active           ! MPI size in linalg for active
     153              :     integer :: comm_active        ! communicator for processes treating active bands
     154              : 
     155              :   end type bandPartitionInfo_t
     156              : 
     157              :   ! Partition Data for column vectors X=(X_lock X_active)
     158              :   ! Function: handles data (e.g. X, AX, BX) in MPI distributions
     159              :   !-------------------------------------------------
     160              :   type, private :: bandPartitionData_t
     161              : 
     162              :     type(xgBlock_t) :: linalg_active          ! active vectors in linalg MPI distribution
     163              :     type(xgBlock_t) :: linalg_locked          ! locked vectors in linalg MPI distribution
     164              :     type(xgBlock_t) :: colsrows_active        ! active vectors in colsrows MPI distribution
     165              :     type(xgTransposer_t) :: transposer_active ! transposer to switch between MPI distrs for active only
     166              : 
     167              :   end type bandPartitionData_t
     168              : 
     169              : !Public methods associated to 'chebfi' datatype
     170              : !-------------------------------------------------
     171              :  public :: chebfi_init
     172              :  public :: chebfi_free
     173              :  public :: chebfi_memInfo
     174              :  public :: chebfi_run
     175              :  public :: chebfi_runSlice
     176              :  public :: chebfi_runSubspaceIteration
     177              :  public :: chebfi_runSubspaceIterationDummy
     178              :  public :: chebfi_rayleighRitzQuotients
     179              :  public :: chebfi_computeNextOrderChebfiPolynom
     180              :  public :: chebfi_swapInnerBuffers
     181              : 
     182              :  CONTAINS  !========================================================================================
     183              : !!***
     184              : 
     185              : !!****f* m_chebfi2/chebfi_init
     186              : !! NAME
     187              : !! chebfi_init
     188              : !!
     189              : !! FUNCTION
     190              : !! Initialize a 'chebfi' datastructure.
     191              : !!
     192              : !! INPUTS
     193              : !!  bandpp= number of 'bands' handled by a processor
     194              : !!  eigenProblem= type of eigenpb: 1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
     195              : !!  me_g0= 1 if this processors treats G=0, 0 otherwise
     196              : !!  me_g0_fft= 1 if this processors treats G=0 in FFT, 0 otherwise
     197              : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     198              : !!  ndeg_filter= polynomial degree of the Chebyshev filter (.i.e. number of H applications)
     199              : !!  comm_rows= "rows" communicator
     200              : !!  comm_cols= "cols" communicator
     201              : !!  paral_kgb= flag controlling (k,g,bands) parallelization
     202              : !!  space= defines in which space we are (columns, rows, etc.)
     203              : !!  spacecom= MPI communicator
     204              : !!  spacedim= space dimension for one vector
     205              : !!  paw= flag. TRUE if current calculation ses the PAW approach
     206              : !!  ecut= plane-wave cut-off energy
     207              : !!  tolerance= tolerance criterion on the residu to stop the minimization
     208              : !!  nbdbuf= number of bands in the buffer
     209              : !!  oracle= option compute ndeg_filter from residuals
     210              : !!  oracle_factor= factor used to decrease residuals
     211              : !!  oracle_min_occ= threshold on occupancies used for nbdbuf=-101
     212              : !!  gpu_option= flag. Enable GPU if true
     213              : !!  gpu_kokkos_nthrd= number of OpenMP offloaded threads used
     214              : !!  gpu_thread_limit= maximum number of OpenMP offloaded threads
     215              : !!  from_linalg= flag. Transposer allocates representation ColsRows if true, Linalg if false
     216              : !!
     217              : !! OUTPUT
     218              : !!
     219              : !! SIDE EFFECTS
     220              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     221              : !!
     222              : !! SOURCE
     223              : 
     224         9042 : subroutine chebfi_init(chebfi,neigenpairs,spacedim,tolerance,ecut,paral_kgb,bandpp, &
     225              :                        ndeg_filter,nbdbuf,space,eigenProblem,spacecom,me_g0,me_g0_fft,paw,comm_rows,comm_cols, &
     226              :                        oracle,oracle_factor,oracle_min_occ,gpu_option,gpu_kokkos_nthrd,gpu_thread_limit,from_linalg)
     227              : 
     228              :  ! Arguments ------------------------------------
     229              :  integer       , intent(in   ) :: bandpp
     230              :  integer       , intent(in   ) :: eigenProblem
     231              :  integer       , intent(in   ) :: me_g0
     232              :  integer       , intent(in   ) :: me_g0_fft
     233              :  integer       , intent(in   ) :: neigenpairs
     234              :  integer       , intent(in   ) :: ndeg_filter
     235              :  integer       , intent(in   ) :: nbdbuf
     236              :  integer       , intent(in   ) :: comm_cols
     237              :  integer       , intent(in   ) :: comm_rows
     238              :  integer       , intent(in   ) :: paral_kgb
     239              :  integer       , intent(in   ) :: space
     240              :  integer       , intent(in   ) :: spacecom
     241              :  integer       , intent(in   ) :: spacedim
     242              :  integer       , intent(in   ) :: gpu_option
     243              :  integer       , intent(in   ) :: oracle
     244              :  logical       , intent(in   ) :: paw
     245              :  real(dp)      , intent(in   ) :: ecut
     246              :  real(dp)      , intent(in   ) :: tolerance
     247              :  real(dp)      , intent(in   ) :: oracle_factor
     248              :  real(dp)      , intent(in   ) :: oracle_min_occ
     249              :  type(chebfi_t), intent(inout) :: chebfi
     250              :  integer       , intent(in   ), optional :: gpu_kokkos_nthrd
     251              :  integer       , intent(in   ), optional :: gpu_thread_limit
     252              :  logical       , intent(in   ), optional :: from_linalg
     253              : 
     254              :  ! Local variables-------------------------------
     255              :  real(dp)                      :: tsec(2)
     256              : 
     257              :  ! *********************************************************************
     258              : 
     259         9042 :  call timab(tim_init,1,tsec)
     260              : 
     261         9042 :  chebfi%space = space
     262         9042 :  chebfi%neigenpairs = neigenpairs
     263         9042 :  chebfi%spacedim    = spacedim
     264         9042 :  if (tolerance > 0.0) then
     265         3010 :    chebfi%tolerance = tolerance
     266              :  else
     267         6032 :    chebfi%tolerance = 1.0e-20
     268              :  end if
     269         9042 :  chebfi%ecut        = ecut
     270         9042 :  chebfi%paral_kgb   = paral_kgb
     271         9042 :  chebfi%comm_cols   = comm_cols
     272         9042 :  chebfi%bandpp      = bandpp
     273         9042 :  chebfi%comm_rows   = comm_rows
     274         9042 :  chebfi%ndeg_filter = ndeg_filter
     275         9042 :  chebfi%nbdbuf      = nbdbuf
     276         9042 :  chebfi%spacecom    = spacecom
     277         9042 :  chebfi%eigenProblem = eigenProblem
     278         9042 :  chebfi%me_g0        = me_g0
     279         9042 :  chebfi%me_g0_fft    = me_g0_fft
     280         9042 :  chebfi%paw          = paw
     281         9042 :  chebfi%gpu_option  = gpu_option
     282         9042 :  chebfi%oracle      = oracle
     283         9042 :  chebfi%oracle_factor = oracle_factor
     284         9042 :  chebfi%oracle_min_occ = oracle_min_occ
     285              : 
     286         9042 :  chebfi%gpu_kokkos_nthrd = 1
     287         9042 :  if (present(gpu_kokkos_nthrd)) chebfi%gpu_kokkos_nthrd = gpu_kokkos_nthrd
     288         9042 :  chebfi%gpu_thread_limit = 0
     289         9042 :  if (present(gpu_thread_limit)) chebfi%gpu_thread_limit = gpu_thread_limit
     290         9042 :  chebfi%from_linalg = .true.
     291         9042 :  if (present(from_linalg)) chebfi%from_linalg = from_linalg
     292              : 
     293         9042 :  call chebfi_allocateAll(chebfi)
     294              : 
     295         9042 :  call timab(tim_init,2,tsec)
     296              : 
     297         9042 : end subroutine chebfi_init
     298              : !!***
     299              : 
     300              : !----------------------------------------------------------------------
     301              : 
     302              : !!****f* m_chebfi2/chebfi_allocateAll
     303              : !! NAME
     304              : !! chebfi_allocateAll
     305              : !!
     306              : !! FUNCTION
     307              : !! Allocate all memory spaces in a 'chebfi' datastructure.
     308              : !!
     309              : !! INPUTS
     310              : !!
     311              : !! OUTPUT
     312              : !!
     313              : !! SIDE EFFECTS
     314              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     315              : !!
     316              : !! SOURCE
     317              : 
     318         9042 : subroutine chebfi_allocateAll(chebfi)
     319              : 
     320              :  ! Arguments ------------------------------------
     321              :  type(chebfi_t)  , intent(inout) :: chebfi
     322              : 
     323              :  ! Local variables-------------------------------
     324              :  ! scalars
     325              :  integer  :: neigenpairs
     326              :  integer  :: space
     327              :  integer  :: spacedim
     328              :  integer  :: total_spacedim, ierr
     329              : 
     330              : ! *********************************************************************
     331              : 
     332         9042 :  space       = chebfi%space
     333         9042 :  spacedim    = chebfi%spacedim
     334         9042 :  neigenpairs = chebfi%neigenpairs
     335              : 
     336         9042 :  call chebfi_free(chebfi)
     337              : 
     338         9042 :  if (chebfi%paral_kgb == 0) then
     339         2722 :    chebfi%total_spacedim = spacedim
     340         2722 :    call xg_init(chebfi%X_NP,space,spacedim,2*neigenpairs,chebfi%spacecom,me_g0=chebfi%me_g0,gpu_option=chebfi%gpu_option) !regular arrays
     341         2722 :    call xg_setBlock(chebfi%X_NP, chebfi%X_next,spacedim, neigenpairs)
     342         2722 :    call xg_setBlock(chebfi%X_NP, chebfi%X_prev,spacedim, neigenpairs, fcol=neigenpairs+1)
     343              :  else
     344         6320 :    if (chebfi%from_linalg) then
     345         6304 :     total_spacedim = spacedim
     346         6304 :     call xmpi_sum(total_spacedim,chebfi%spacecom,ierr)
     347         6304 :     chebfi%total_spacedim = total_spacedim
     348              :    else
     349           16 :     chebfi%total_spacedim = chebfi%spacedim
     350              :    end if
     351              :    call xg_init(chebfi%X_NP,space,chebfi%total_spacedim,2*chebfi%bandpp,chebfi%spacecom,me_g0=chebfi%me_g0_fft,&
     352         6320 :      & gpu_option=chebfi%gpu_option) !transposed arrays
     353         6320 :    call xg_setBlock(chebfi%X_NP, chebfi%X_next, chebfi%total_spacedim, chebfi%bandpp)
     354         6320 :    call xg_setBlock(chebfi%X_NP, chebfi%X_prev, chebfi%total_spacedim, chebfi%bandpp, fcol=chebfi%bandpp+1)
     355              :  end if
     356              : 
     357              :  !transposer will handle these arrays automatically
     358         9042 :  if (chebfi%from_linalg) then
     359         9024 :     call xg_init(chebfi%AX,space,spacedim,neigenpairs,chebfi%spacecom,me_g0=chebfi%me_g0,gpu_option=chebfi%gpu_option)
     360         9024 :     call xg_init(chebfi%BX,space,spacedim,neigenpairs,chebfi%spacecom,me_g0=chebfi%me_g0,gpu_option=chebfi%gpu_option)
     361              :  else
     362              :     call xg_init(chebfi%xAXColsRows_W,space,chebfi%total_spacedim,chebfi%bandpp,chebfi%comm_rows,&
     363           18 :         me_g0=chebfi%me_g0_fft,gpu_option=chebfi%gpu_option)
     364              :     call xg_init(chebfi%xBXColsRows_W,space,chebfi%total_spacedim,chebfi%bandpp,chebfi%comm_rows,&
     365           18 :         me_g0=chebfi%me_g0_fft,gpu_option=chebfi%gpu_option)
     366           18 :     chebfi%xAXColsRows = chebfi%xAXColsRows_W%self
     367           18 :     chebfi%xBXColsRows = chebfi%xBXColsRows_W%self
     368              :  end if
     369              : 
     370         9042 : end subroutine chebfi_allocateAll
     371              : !!***
     372              : 
     373              : !----------------------------------------------------------------------
     374              : 
     375              : !!****f* m_chebfi2/chebfi_free
     376              : !! NAME
     377              : !! chebfi_free
     378              : !!
     379              : !! FUNCTION
     380              : !! Destroy a 'chebfi' datastructure.
     381              : !!
     382              : !! INPUTS
     383              : !!
     384              : !! OUTPUT
     385              : !!  arraymem(2)= memory information
     386              : !!
     387              : !! SIDE EFFECTS
     388              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     389              : !!
     390              : !! SOURCE
     391              : 
     392        18084 : subroutine chebfi_free(chebfi)
     393              : 
     394              : !Arguments ------------------------------------
     395              :  type(chebfi_t) , intent(inout) :: chebfi
     396              : 
     397              : ! *********************************************************************
     398              : 
     399        18084 :  call xg_free(chebfi%X_NP)
     400              : 
     401        18084 :  if (chebfi%from_linalg) then
     402        18048 :     call xg_free(chebfi%AX)
     403        18048 :     call xg_free(chebfi%BX)
     404              :  else
     405           36 :     call xg_free(chebfi%xAXColsRows_W)
     406           36 :     call xg_free(chebfi%xBXColsRows_W)
     407              :  end if
     408              : 
     409        18084 : end subroutine chebfi_free
     410              : !!***
     411              : 
     412              : !----------------------------------------------------------------------
     413              : 
     414              : !!****f* m_chebfi2/chebfi_memInfo
     415              : !! NAME
     416              : !! chebfi_memInfo
     417              : !!
     418              : !! FUNCTION
     419              : !! Provides memory information about a 'chebfi' datastructure.
     420              : !!
     421              : !! INPUTS
     422              : !!  bandpp= number of 'bands' handled by a processor
     423              : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     424              : !!  paral_kgb= flag controlling (k,g,bands) parallelization
     425              : !!  space= defines in which space we are (columns, rows, etc.)
     426              : !!  spacedim= dimension of MPI communicator
     427              : !!  total_spacedim= size of global KGB communicator (typically 'banspinorfft' comm.)
     428              : !!
     429              : !! OUTPUT
     430              : !!  arraymem(2)= memory information
     431              : !!
     432              : !! SIDE EFFECTS
     433              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     434              : !!
     435              : !! SOURCE
     436              : 
     437            0 : function chebfi_memInfo(neigenpairs,spacedim,space,paral_kgb,total_spacedim,bandpp) result(arraymem)
     438              : 
     439              : !Arguments ------------------------------------
     440              :  integer, intent(in   ) :: bandpp
     441              :  integer, intent(in   ) :: neigenpairs
     442              :  integer, intent(in   ) :: paral_kgb
     443              :  integer, intent(in   ) :: space
     444              :  integer, intent(in   ) :: spacedim
     445              :  integer, intent(in   ) :: total_spacedim
     446              : 
     447              : !Local variables-------------------------------
     448              : !scalars
     449              :  integer(kind=c_size_t) :: memX
     450              :  integer(kind=c_size_t) :: memX_next
     451              :  integer(kind=c_size_t) :: memX_prev
     452              :  integer(kind=c_size_t) :: memAX
     453              :  integer(kind=c_size_t) :: memBX
     454              : !Transposer variables
     455              :  integer(kind=c_size_t) :: memX_CR
     456              :  integer(kind=c_size_t) :: memAX_CR
     457              :  integer(kind=c_size_t) :: memBX_CR
     458              :  integer(kind=c_size_t) :: mem_sendrecv_CR
     459              : !chebfi_rayleighRitz function variables
     460              :  integer(kind=c_size_t) :: memA_und_X
     461              :  integer(kind=c_size_t) :: memB_und_X
     462              :  integer(kind=c_size_t) :: memEigenvalues
     463              :  integer(kind=c_size_t) :: cplx
     464              : !arrays
     465              :  integer(kind=c_size_t) :: arraymem(2)
     466              : 
     467              : ! *********************************************************************
     468            0 :  cplx = 1
     469            0 :  if ( space == SPACE_C ) cplx = 2 !for now only complex
     470              : 
     471              :  !Permanent in chebfi
     472            0 :  memX = int(cplx,c_size_t) * kind(1.d0) * spacedim * neigenpairs
     473              : 
     474            0 :  if (paral_kgb == 0) then
     475              :    memX_next = int(cplx,c_size_t) * kind(1.d0) * spacedim * neigenpairs
     476              :    memX_prev = int(cplx,c_size_t) * kind(1.d0) * spacedim * neigenpairs
     477              :  else
     478            0 :    memX_next = int(cplx,c_size_t) * kind(1.d0) * total_spacedim * bandpp
     479            0 :    memX_prev = int(cplx,c_size_t) * kind(1.d0) * total_spacedim * bandpp
     480              :  end if
     481              : 
     482            0 :  memAX = int(cplx,c_size_t) * kind(1.d0) * spacedim * neigenpairs
     483            0 :  memBX = int(cplx,c_size_t) * kind(1.d0) * spacedim * neigenpairs
     484              : 
     485              :  !Transposer colrow array
     486            0 :  if (paral_kgb == 1) then
     487            0 :    memX_CR = int(cplx,c_size_t) * kind(1.d0) * total_spacedim * bandpp
     488            0 :    memAX_CR = int(cplx,c_size_t) * kind(1.d0) * total_spacedim * bandpp
     489            0 :    memBX_CR = int(cplx,c_size_t) * kind(1.d0) * total_spacedim * bandpp
     490            0 :    mem_sendrecv_CR = int(cplx,c_size_t) * kind(1.d0) * total_spacedim * bandpp
     491              :  else
     492              :    memX_CR = 0
     493              :    memAX_CR = 0
     494              :    memBX_CR = 0
     495              :    mem_sendrecv_CR = 0
     496              :  end if
     497              : 
     498              :  !chebfi_rayleighRitz function variables
     499            0 :  memA_und_X = int(cplx,c_size_t) * kind(1.d0) * neigenpairs * neigenpairs
     500            0 :  memB_und_X = int(cplx,c_size_t) * kind(1.d0) * neigenpairs * neigenpairs
     501            0 :  memEigenvalues = int(kind(1.d0),c_size_t) * neigenpairs
     502              : 
     503              :  arraymem(1) = memX + memX_next + memX_prev + &
     504            0 :                memAX + memBX + memX_CR + memAX_CR + memBX_CR + mem_sendrecv_CR
     505            0 :  arraymem(2) = memA_und_X + memB_und_X + memEigenvalues
     506              : 
     507            0 : end function chebfi_memInfo
     508              : !!***
     509              : 
     510              : !----------------------------------------------------------------------
     511              : 
     512              : !!****f* m_chebfi2/chebfi_run
     513              : !! NAME
     514              : !! chebfi_run
     515              : !!
     516              : !! FUNCTION
     517              : !! Apply the Chebyshev Filtering algorithm on a set of vectors.
     518              : !!
     519              : !! INPUTS
     520              : !!  getAX_BX= pointer to the function giving A|X> and B|X>
     521              : !!            A is typically the Hamiltonian H, and B the overlap operator S
     522              : !!  getBm1X= pointer to the function giving B^-1|X>
     523              : !!           B is typically the overlap operator S
     524              : !!  nspinor= number of spinorial components of the wavefunctions
     525              : !!
     526              : !! OUTPUT
     527              : !!
     528              : !! SIDE EFFECTS
     529              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     530              : !!  eigen= Full eigenvalues (initial values on entry)
     531              : !!  residu= residuals, i.e. norm of (A-lambdaB)|X>
     532              : !!  X0= Full set of vectors (initial values on entry) distributed in Linalg representation
     533              : !!
     534              : !! SOURCE
     535              : 
     536         9024 : subroutine chebfi_run(chebfi,X0,getAX_BX,getBm1X,eigen,occ,residu,nspinor)
     537              : 
     538              : !Arguments ------------------------------------
     539              :  type(chebfi_t) , intent(inout) :: chebfi
     540              :  integer,         intent(in)    :: nspinor
     541              :  type(xgBlock_t), intent(inout) :: X0
     542              :  type(xgBlock_t), intent(inout) :: eigen
     543              :  type(xgBlock_t), intent(in)    :: occ
     544              :  type(xgBlock_t), intent(inout) :: residu
     545              :  interface
     546              :    subroutine getAX_BX(X,AX,BX)
     547              :      use m_xg, only : xgBlock_t
     548              :      type(xgBlock_t), intent(inout) :: X
     549              :      type(xgBlock_t), intent(inout) :: AX
     550              :      type(xgBlock_t), intent(inout) :: BX
     551              :    end subroutine getAX_BX
     552              :  end interface
     553              :  interface
     554              :    subroutine getBm1X(X,Bm1X)
     555              :      use m_xg, only : xgBlock_t
     556              :      type(xgBlock_t), intent(inout) :: X
     557              :      type(xgBlock_t), intent(inout) :: Bm1X
     558              :    end subroutine getBm1X
     559              :  end interface
     560              : 
     561              : !Local variables-------------------------------
     562              : !scalars
     563              :  integer :: spacedim
     564              :  integer :: space_res
     565              :  integer :: neigenpairs,bandpp
     566              :  integer :: ndeg_filter,ndeg_filter_max
     567              :  integer :: ideg, ierr
     568              :  real(dp) :: tolerance
     569              :  real(dp) :: maxeig, maxeig_global
     570              :  real(dp) :: mineig, mineig_global
     571              :  real(dp) :: lambda_minus
     572              :  real(dp) :: lambda_plus
     573              :  real(dp) :: one_over_r
     574              :  real(dp) :: two_over_r
     575              :  real(dp) :: center
     576              :  real(dp) :: radius
     577              :  type(xg_t) :: DivResults
     578              : !arrays
     579              :  real(dp) :: tsec(2)
     580              :  !Pointers similar to old Chebfi
     581         9024 :  integer,allocatable :: ndeg_filter_bands(:) !Oracle variable
     582              : 
     583              : ! *********************************************************************
     584              : 
     585              : ! call timab(tim_run,1,tsec)
     586              : 
     587         9024 :  spacedim = chebfi%spacedim
     588         9024 :  neigenpairs = chebfi%neigenpairs
     589         9024 :  bandpp = chebfi%bandpp
     590         9024 :  ndeg_filter = chebfi%ndeg_filter
     591         9024 :  chebfi%eigenvalues = eigen
     592              : 
     593         9024 :  if (chebfi%space==SPACE_C) then
     594         5488 :    space_res = SPACE_C
     595         3536 :  else if (chebfi%space==SPACE_CR) then
     596         3536 :    space_res = SPACE_R
     597              :  else
     598            0 :    ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
     599              :  end if
     600              : 
     601         9024 :  if (chebfi%paral_kgb == 0) then
     602         8160 :    ABI_MALLOC(ndeg_filter_bands,(neigenpairs))
     603         2720 :    call xg_init(DivResults, space_res, neigenpairs, 1, gpu_option=chebfi%gpu_option)
     604              :  else
     605        18912 :    ABI_MALLOC(ndeg_filter_bands,(bandpp))
     606         6304 :    call xg_init(DivResults, space_res, bandpp, 1, gpu_option=chebfi%gpu_option)
     607              :  end if
     608              : 
     609         9024 :  tolerance = chebfi%tolerance
     610         9024 :  lambda_plus = chebfi%ecut
     611         9024 :  chebfi%X = X0
     612              : 
     613              :  ! Transpose
     614         9024 :  if (chebfi%paral_kgb == 1) then
     615              : 
     616         6304 :    call timab(tim_transpose,1,tsec)
     617              :    call xgTransposer_constructor(chebfi%xgTransposerX,chebfi%X,chebfi%xXColsRows,nspinor,&
     618              :      STATE_LINALG,TRANS_ALL2ALL,chebfi%comm_rows,chebfi%comm_cols,0,0,chebfi%me_g0_fft,&
     619         6304 :      gpu_option=chebfi%gpu_option,gpu_thread_limit=chebfi%gpu_thread_limit)
     620              : 
     621         6304 :    call xgTransposer_copyConstructor(chebfi%xgTransposerAX,chebfi%xgTransposerX,chebfi%AX%self,chebfi%xAXColsRows,STATE_LINALG)
     622         6304 :    call xgTransposer_copyConstructor(chebfi%xgTransposerBX,chebfi%xgTransposerX,chebfi%BX%self,chebfi%xBXColsRows,STATE_LINALG)
     623              : 
     624         6304 :    chebfi%xgTransposerX%gpu_kokkos_nthrd  = chebfi%gpu_kokkos_nthrd
     625         6304 :    chebfi%xgTransposerAX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
     626         6304 :    chebfi%xgTransposerBX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
     627              : 
     628              :    ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
     629         6304 :    call xgTransposer_transpose(chebfi%xgTransposerX,STATE_COLSROWS)
     630         6304 :    chebfi%xgTransposerAX%state = STATE_COLSROWS
     631         6304 :    chebfi%xgTransposerBX%state = STATE_COLSROWS
     632              :    ABI_NVTX_END_RANGE()
     633         6304 :    call timab(tim_transpose,2,tsec)
     634              :  else
     635         2720 :    call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)   !use xXColsRows instead of X notion
     636         2720 :    call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)   !use xAXColsRows instead of AX notion
     637         2720 :    call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
     638              :  end if
     639              : 
     640         9024 :  call timab(tim_getAX_BX,1,tsec)
     641              :  ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
     642         9024 :  call getAX_BX(chebfi%xXColsRows,chebfi%xAXColsRows,chebfi%xBXColsRows)
     643         9024 :  call xgBlock_zero_im_g0(chebfi%xAXColsRows)
     644         9024 :  call xgBlock_zero_im_g0(chebfi%xBXColsRows)
     645              :  ABI_NVTX_END_RANGE()
     646         9024 :  call timab(tim_getAX_BX,2,tsec)
     647              : 
     648         9024 :  if (chebfi%paral_kgb == 1) then
     649         6304 :    call timab(tim_barrier,1,tsec)
     650         6304 :    call xmpi_barrier(chebfi%spacecom)
     651         6304 :    call timab(tim_barrier,2,tsec)
     652              :  end if
     653              : 
     654              : !********************* Compute Rayleigh quotients for every band, and set lambda equal to the largest one *****
     655              :  ABI_NVTX_START_RANGE(NVTX_CHEBFI2_RRQ)
     656              : 
     657              :  ! NOTICE : the following lines are kept for reference
     658              :  ! they are no longer necessary as chebfi_rayleighRitzQuotients can fully run on GPU
     659              :  ! it is no longer necessary to issue a data prefetch, data are already present on device
     660              : 
     661              : !  if (chebfi%gpu_option == ABI_GPU_KOKKOS) then
     662              : ! #if defined(HAVE_GPU_CUDA)
     663              : !    call xgBlock_prefetch_async(chebfi%xXColsRows,  CPU_DEVICE_ID)
     664              : !    call xgBlock_prefetch_async(chebfi%xAXColsRows, CPU_DEVICE_ID)
     665              : !    call xgBlock_prefetch_async(chebfi%xBXColsRows, CPU_DEVICE_ID)
     666              : ! #endif
     667              : !  end if
     668              : 
     669         9024 :  call timab(tim_RR_q, 1, tsec)
     670         9024 :  call chebfi_rayleighRitzQuotients(chebfi, maxeig, mineig, DivResults%self)
     671              : 
     672         9024 :  if (chebfi%paral_kgb == 1) then
     673         6304 :    call xmpi_max(maxeig,maxeig_global,chebfi%spacecom,ierr)
     674         6304 :    call xmpi_min(mineig,mineig_global,chebfi%spacecom,ierr)
     675              :  else
     676         2720 :    maxeig_global = maxeig
     677         2720 :    mineig_global = mineig
     678              :  end if
     679         9024 :  call timab(tim_RR_q, 2, tsec)
     680              :  ABI_NVTX_END_RANGE()
     681              : 
     682         9024 :  lambda_minus = maxeig_global
     683              : 
     684         9024 :  call timab(tim_oracle,1,tsec)
     685              : 
     686              :  ! ndeg_filter_max limits the reduction of the residual of the smallest eigenvalue (i.e. the most amplified one by the filter) by a factor 1e8.
     687              :  ! Also, the maximal value of ndeg_filter_max is 40.
     688         9024 :  ndeg_filter_max = cheb_oracle1(mineig_global, lambda_minus, lambda_plus, 1D-16, 40)
     689         9024 :  ndeg_filter = MIN(ndeg_filter_max,chebfi%ndeg_filter)
     690         9024 :  if (chebfi%oracle>0) then
     691         2312 :    call chebfi_set_ndeg_from_residu(chebfi,lambda_minus,lambda_plus,occ,DivResults%self,ndeg_filter_max,ndeg_filter)
     692              :  end if
     693        53520 :  ndeg_filter_bands(:) = ndeg_filter
     694              : 
     695         9024 :  call timab(tim_oracle,2,tsec)
     696              : 
     697         9024 :  center = (lambda_plus + lambda_minus)*0.5
     698         9024 :  radius = (lambda_plus - lambda_minus)*0.5
     699              : 
     700         9024 :  one_over_r = 1/radius
     701         9024 :  two_over_r = 2/radius
     702              : 
     703              :  ABI_NVTX_START_RANGE(NVTX_CHEBFI2_CORE)
     704        72586 :  do ideg = 0, ndeg_filter - 1
     705              : 
     706              :    ABI_NVTX_START_RANGE(NVTX_CHEBFI2_NEXT_ORDER)
     707        63562 :    call chebfi_computeNextOrderChebfiPolynom(chebfi, ideg, center, one_over_r, two_over_r, getBm1X)
     708              :    ABI_NVTX_END_RANGE()
     709              : 
     710        63562 :    call timab(tim_swap,1,tsec)
     711              :    ABI_NVTX_START_RANGE(NVTX_CHEBFI2_SWAP_BUF)
     712        63562 :    if (chebfi%paral_kgb == 0) then
     713        19050 :      call chebfi_swapInnerBuffers(chebfi, spacedim, neigenpairs)
     714              :    else
     715        44512 :      call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, bandpp)
     716              :    end if
     717              :    ABI_NVTX_END_RANGE()
     718        63562 :    call timab(tim_swap,2,tsec)
     719              : 
     720              :    !A * Psi
     721        63562 :    call timab(tim_getAX_BX,1,tsec)
     722              :    ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
     723        63562 :    call getAX_BX(chebfi%xXColsRows,chebfi%xAXColsRows,chebfi%xBXColsRows)
     724        63562 :    call xgBlock_zero_im_g0(chebfi%xAXColsRows)
     725        63562 :    call xgBlock_zero_im_g0(chebfi%xBXColsRows)
     726              :    ABI_NVTX_END_RANGE()
     727        72586 :    call timab(tim_getAX_BX,2,tsec)
     728              : 
     729              :  end do ! ideg
     730              :  ABI_NVTX_END_RANGE()
     731              : 
     732         9024 :  if (chebfi%paral_kgb == 1) then
     733         6304 :    call timab(tim_barrier,1,tsec)
     734         6304 :    call xmpi_barrier(chebfi%spacecom)
     735         6304 :    call timab(tim_barrier,2,tsec)
     736              :  end if
     737              : 
     738         9024 :  call timab(tim_amp_f,1,tsec)
     739         9024 :  call chebfi_ampfactor(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
     740         9024 :  call timab(tim_amp_f,2,tsec)
     741              : 
     742         9024 :  call xg_free(DivResults)
     743         9024 :  ABI_SFREE(ndeg_filter_bands)
     744              : 
     745         9024 :  call timab(tim_transpose,1,tsec)
     746              :  ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
     747         9024 :  if (chebfi%paral_kgb == 1) then
     748         6304 :    call xmpi_barrier(chebfi%spacecom)
     749              : 
     750         6304 :    call xgTransposer_transpose(chebfi%xgTransposerX, STATE_LINALG)
     751         6304 :    call xgTransposer_transpose(chebfi%xgTransposerAX,STATE_LINALG)
     752         6304 :    call xgTransposer_transpose(chebfi%xgTransposerBX,STATE_LINALG)
     753              : 
     754              :    !only one MPI proc reset buffers to right addresses (because of X-Xcolwise swaps)
     755         6304 :    if (xmpi_comm_size(chebfi%spacecom) == 1) then
     756            0 :      call xgBlock_setBlock(chebfi%xXColsRows,  chebfi%X,       spacedim, neigenpairs)
     757            0 :      call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
     758            0 :      call xgBlock_setBlock(chebfi%xBXColsRows, chebfi%BX%self, spacedim, neigenpairs)
     759              :    end if
     760              :  else
     761         2720 :    call xgBlock_setBlock(chebfi%xXColsRows,  chebfi%X,       spacedim, neigenpairs)
     762         2720 :    call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
     763         2720 :    call xgBlock_setBlock(chebfi%xBXColsRows, chebfi%BX%self, spacedim, neigenpairs)
     764              :  end if
     765              :  ABI_NVTX_END_RANGE()
     766         9024 :  call timab(tim_transpose,2,tsec)
     767              : 
     768              :  ! Apply Rayleigh-Ritz
     769              :  ABI_NVTX_START_RANGE(NVTX_CHEBFI2_RR)
     770              :  call xg_RayleighRitz(chebfi%X,chebfi%AX%self,chebfi%BX%self,chebfi%eigenvalues,ierr,0,tim_RR,&
     771         9024 : &                     chebfi%gpu_option,solve_ax_bx=.true.)
     772              :  ABI_NVTX_END_RANGE()
     773              : 
     774              :  ! Compute residual
     775         9024 :  call timab(tim_residu, 1, tsec)
     776         9024 :  if (chebfi%paw) then
     777         7528 :    call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%BX%self,chebfi%AX%self)
     778              :  else
     779         1496 :    call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%X,chebfi%AX%self)
     780              :  end if
     781              : 
     782         9024 :  call xgBlock_colwiseNorm2(chebfi%AX%self, residu)
     783         9024 :  call timab(tim_residu, 2, tsec)
     784              : 
     785         9024 :  call timab(tim_copy, 1, tsec)
     786         9024 :  call xgBlock_copy(chebfi%X,X0)
     787         9024 :  call timab(tim_copy, 2, tsec)
     788              : 
     789              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
     790              :    if (chebfi%gpu_option==ABI_GPU_KOKKOS) then
     791              :      call gpu_device_synchronize()
     792              :    end if
     793              : #endif
     794              : 
     795         9024 :  if (chebfi%paral_kgb == 1) then
     796         6304 :    call xgTransposer_free(chebfi%xgTransposerX)
     797         6304 :    call xgTransposer_free(chebfi%xgTransposerAX)
     798         6304 :    call xgTransposer_free(chebfi%xgTransposerBX)
     799              :  end if
     800              : 
     801              : ! call timab(tim_run,2,tsec)
     802              : 
     803        18048 : end subroutine chebfi_run
     804              : !!***
     805              : 
     806              : !----------------------------------------------------------------------
     807              : 
     808              : !!****f* m_chebfi2/chebfi_rayleighRitzQuotients
     809              : !! NAME
     810              : !! chebfi_rayleighRitzQuotients
     811              : !!
     812              : !! FUNCTION
     813              : !! Compute the Rayleigh-Ritz quotients.
     814              : !!
     815              : !! INPUTS
     816              : !!
     817              : !! OUTPUT
     818              : !!
     819              : !! SIDE EFFECTS
     820              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     821              : !!  maxeig= highest eigenvalue
     822              : !!  mineig= lowest eigenvalue
     823              : !!  DivResults= Rayleigh-Ritz quotients
     824              : !!
     825              : !! SOURCE
     826              : 
     827         9024 : subroutine chebfi_rayleighRitzQuotients(chebfi,maxeig,mineig,DivResults)
     828              : 
     829              : !Arguments ------------------------------------
     830              :  real(dp), intent(inout) :: maxeig
     831              :  real(dp), intent(inout) :: mineig
     832              :  type(chebfi_t), intent(inout) :: chebfi
     833              :  type(xgBlock_t), intent(inout) :: DivResults
     834              : 
     835              : !Local variables-------------------------------
     836              : !scalars
     837              :  type(xg_t)::Results1
     838              :  type(xg_t)::Results2
     839              : !arrays
     840              :  integer :: maxeig_pos(2)
     841              :  integer :: mineig_pos(2)
     842              :  integer :: space_res
     843              : 
     844              : ! *********************************************************************
     845              : 
     846         9024 :  if (chebfi%space==SPACE_C) then
     847         5488 :    space_res = SPACE_C
     848         3536 :  else if (chebfi%space==SPACE_CR) then
     849         3536 :    space_res = SPACE_R
     850              :  else
     851            0 :    ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
     852              :  end if
     853              : 
     854              : !Doesnt work with npfft (ncols=1 in the formula below) ???
     855         9024 :  if (chebfi%paral_kgb == 0) then
     856         2720 :    call xg_init(Results1, space_res, chebfi%neigenpairs, 1, gpu_option=chebfi%gpu_option)
     857         2720 :    call xg_init(Results2, space_res, chebfi%neigenpairs, 1, gpu_option=chebfi%gpu_option)
     858              :  else
     859         6304 :    call xg_init(Results1, space_res, chebfi%bandpp, 1, gpu_option=chebfi%gpu_option)
     860         6304 :    call xg_init(Results2, space_res, chebfi%bandpp, 1, gpu_option=chebfi%gpu_option)
     861              :  end if
     862              : 
     863              :  ! <Psi|H|Psi>
     864         9024 :  call xgBlock_colwiseDotProduct(chebfi%xXColsRows, chebfi%xAXColsRows, Results1%self, comm_loc=xmpi_comm_null)
     865              : 
     866              :  ! <Psi|S|Psi>
     867         9024 :  call xgBlock_colwiseDotProduct(chebfi%xXColsRows, chebfi%xBXColsRows, Results2%self, comm_loc=xmpi_comm_null)
     868              : 
     869              :  ! eig = <Psi|H|Psi> / <Psi|S|Psi>
     870              :  call xgBlock_colwiseDivision(Results1%self, Results2%self, DivResults, &
     871         9024 :    & maxeig, maxeig_pos, mineig, mineig_pos)
     872              : 
     873         9024 :  call xg_free(Results1)
     874         9024 :  call xg_free(Results2)
     875              : 
     876         9024 : end subroutine chebfi_rayleighRitzQuotients
     877              : !!***
     878              : 
     879              : !----------------------------------------------------------------------
     880              : 
     881              : !!****f* m_chebfi2/chebfi_computeNextOrderChebfiPolynom
     882              : !! NAME
     883              : !! chebfi_computeNextOrderChebfiPolynom
     884              : !!
     885              : !! FUNCTION
     886              : !! From P_n(B-^1.A)|X> (where P_n is the Chebyshev polynom of order n),
     887              : !!   computes P_n+1(B-^1.A)|X>
     888              : !!
     889              : !! INPUTS
     890              : !!  ideg=current degree of polynom
     891              : !!  center=filter center
     892              : !!  one_over_r,two_over_r=1/R, 2/R, R being the radius of the filter
     893              : !!  getBm1X= pointer to the function giving B^-1|X>
     894              : !!           B is typically the overlap operator S
     895              : !!
     896              : !! OUTPUT
     897              : !!
     898              : !! SIDE EFFECTS
     899              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     900              : !!
     901              : !! SOURCE
     902              : 
     903        63742 : subroutine chebfi_computeNextOrderChebfiPolynom(chebfi,ideg,center,one_over_r,two_over_r,getBm1X)
     904              : 
     905              : !Arguments ------------------------------------
     906              :  real(dp)       , intent(in) :: center
     907              :  integer        , intent(in) :: ideg
     908              :  real(dp)       , intent(in) :: one_over_r
     909              :  real(dp)       , intent(in) :: two_over_r
     910              :  type(chebfi_t) , intent(inout) :: chebfi
     911              :  interface
     912              :    subroutine getBm1X(X,Bm1X)
     913              :      use m_xg, only : xgBlock_t
     914              :      type(xgBlock_t), intent(inout) :: X
     915              :      type(xgBlock_t), intent(inout) :: Bm1X
     916              :    end subroutine getBm1X
     917              :  end interface
     918              : 
     919              :  !Local variables-------------------------------
     920              :  real(dp) :: tsec(2)
     921              : 
     922              :  ! *********************************************************************
     923              : 
     924        63742 :  if (chebfi%paw) then
     925        51898 :    call timab(tim_invovl, 1, tsec)
     926              :    ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_BM1X)
     927        51898 :    call getBm1X(chebfi%xAXColsRows, chebfi%X_next)
     928              :    ABI_NVTX_END_RANGE()
     929        51898 :    call timab(tim_invovl, 2, tsec)
     930              :  else
     931        11844 :    call timab(tim_copy, 1, tsec)
     932        11844 :    call xgBlock_copy(chebfi%xAXColsRows,chebfi%X_next)
     933        11844 :    call timab(tim_copy, 2, tsec)
     934              :  end if
     935              : 
     936        63742 :  call timab(tim_postinvovl, 1, tsec)
     937              :  ABI_NVTX_START_RANGE(NVTX_INVOVL_POST3)
     938        63742 :  call xgBlock_scale(chebfi%xXColsRows, center, 1) !scale by center
     939              : 
     940              :  !(B-1 * A * Psi^i-1 - c * Psi^i-1)
     941        63742 :  call xgBlock_saxpy(chebfi%X_next, dble(-1.0), chebfi%xXColsRows)
     942              : 
     943              :  !Psi^i-1  = 1/c * Psi^i-1
     944        63742 :  call xgBlock_scale(chebfi%xXColsRows, dble(1.0)/center, 1) !counter scale by 1/center
     945              : 
     946        63742 :  if (ideg == 0) then
     947         8658 :    call xgBlock_scale(chebfi%X_next, one_over_r, 1)
     948              :  else
     949        55084 :    call xgBlock_scale(chebfi%X_next, two_over_r, 1)
     950              : 
     951        55084 :    call xgBlock_saxpy(chebfi%X_next, dble(-1.0), chebfi%X_prev)
     952              :  end if
     953              : 
     954              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
     955              :  if (chebfi%gpu_option==ABI_GPU_KOKKOS) then
     956              :    call gpu_device_synchronize()
     957              :  end if
     958              : #endif
     959              :  ABI_NVTX_END_RANGE()
     960        63742 :  call timab(tim_postinvovl, 2, tsec)
     961              : 
     962        63742 : end subroutine chebfi_computeNextOrderChebfiPolynom
     963              : !!***
     964              : 
     965              : !----------------------------------------------------------------------
     966              : 
     967              : !!****f* m_chebfi2/chebfi_swapInnerBuffers
     968              : !! NAME
     969              : !! chebfi_swapInnerBuffers
     970              : !!
     971              : !! FUNCTION
     972              : !! Swap buffers inside a 'chebfi' datastructure.
     973              : !!
     974              : !! INPUTS
     975              : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     976              : !!  spacedim= space dimension for one vector
     977              : !!
     978              : !! OUTPUT
     979              : !!
     980              : !! SIDE EFFECTS
     981              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     982              : !!
     983              : !! SOURCE
     984              : 
     985        63742 : subroutine chebfi_swapInnerBuffers(chebfi,spacedim,neigenpairs)
     986              : 
     987              :   ! Arguments ------------------------------------
     988              :   integer        , intent(in   ) :: spacedim
     989              :   integer        , intent(in   ) :: neigenpairs
     990              :   type(chebfi_t) , intent(inout) :: chebfi
     991              : 
     992              :   ! *********************************************************************
     993              : 
     994        63742 :   call xgBlock_setBlock(chebfi%X_prev,     chebfi%X_swap,     spacedim, neigenpairs) !X_swap = X_prev
     995        63742 :   call xgBlock_setBlock(chebfi%xXColsRows, chebfi%X_prev,     spacedim, neigenpairs) !X_prev = xXColsRows
     996        63742 :   call xgBlock_setBlock(chebfi%X_next,     chebfi%xXColsRows, spacedim, neigenpairs) !xXColsRows = X_next
     997        63742 :   call xgBlock_setBlock(chebfi%X_swap,     chebfi%X_next,     spacedim, neigenpairs) !X_next = X_swap
     998              : 
     999        63742 : end subroutine chebfi_swapInnerBuffers
    1000              : !!***
    1001              : 
    1002              : !----------------------------------------------------------------------
    1003              : 
    1004              : !!****f* m_chebfi2/chebfi_prepareAmpfactor
    1005              : !! NAME
    1006              : !! chebfi_prepAmpfactor
    1007              : !!
    1008              : !! FUNCTION
    1009              : !! Utility function to distribute correctly eigenvalues to MPI procs.
    1010              : !! Performs MPI communication
    1011              : !!
    1012              : !! INPUTS
    1013              : !! chebfi=
    1014              : !! eigen= eigenvalues not distributed
    1015              : !!
    1016              : !! OUTPUT
    1017              : !! DivResults= prepared eigenvalues same array as in chebfi_run
    1018              : !!
    1019              : !! SOURCE
    1020              : 
    1021            0 : subroutine chebfi_prepAmpfactor(chebfi, eigen, DivResults)
    1022              : 
    1023              :     implicit none
    1024              : 
    1025              :     ! Arguments ------------------------------------
    1026              :     type(xg_t), intent(inout) :: DivResults
    1027              :     type(xgBlock_t), intent(inout) :: eigen
    1028              :     type(chebfi_t),  intent(inout) :: chebfi
    1029              : 
    1030              :     ! Local variables-------------------------------
    1031              :     ! scalars
    1032              :     integer :: space_res
    1033              :     integer :: my_rank, num_proc, shift, ierr
    1034              :     type(xgBlock_t) :: eigen_block
    1035              :     ! Arrays
    1036            0 :     integer, allocatable, target :: allbandpp(:)
    1037            0 :     real(dp), allocatable, target :: theta_reshaped(:,:)
    1038              :     integer, pointer :: allbandpp_ptr(:) => null()
    1039              :     real(dp), pointer :: theta_reshaped_ptr(:,:) => null()
    1040              :     real(dp), pointer :: theta(:,:) => null()
    1041              : 
    1042              :     ! *********************************************************************
    1043              : 
    1044            0 :     if (chebfi%space==SPACE_C) then
    1045            0 :         space_res = SPACE_C
    1046            0 :     else if (chebfi%space==SPACE_CR) then
    1047            0 :         space_res = SPACE_R
    1048              :     else
    1049            0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
    1050              :     end if
    1051              : 
    1052            0 :     if (chebfi%paral_kgb == 0) then
    1053            0 :         call xg_init(DivResults, space_res, rows=chebfi%neigenpairs, cols=1, gpu_option=chebfi%gpu_option)
    1054              :         ! Fill DivResults with full eigenvalues
    1055              :         ! TODO fix for workaround copy between space_res and SPACE_R
    1056            0 :         if (space_res==SPACE_R) then
    1057            0 :             call xgBlock_copy(eigen, DivResults%self)
    1058              :         else
    1059              :             ! workaround to copy from SPACE_R to SPACE_C
    1060            0 :             ABI_MALLOC_IFNOT(theta_reshaped,(2,chebfi%neigenpairs))
    1061            0 :             theta_reshaped_ptr => theta_reshaped
    1062            0 :             call xgBlock_reverseMap(eigen, theta, rows=1, cols=chebfi%neigenpairs)
    1063            0 :             theta_reshaped = 0.d0
    1064            0 :             theta_reshaped(1,1:chebfi%neigenpairs) = theta(1,1:chebfi%neigenpairs)
    1065              : #ifdef HAVE_OPENMP_OFFLOAD
    1066              :             !$OMP TARGET ENTER DATA MAP(to:theta_reshaped) IF(chebfi%gpu_option==ABI_GPU_OPENMP)
    1067              : #endif
    1068              :             call xgBlock_map(eigen, theta_reshaped_ptr, space_res, rows=1, &
    1069            0 :                 cols=chebfi%neigenpairs, gpu_option=chebfi%gpu_option)
    1070            0 :             call xgBlock_copy(eigen, DivResults%self)
    1071              : #ifdef HAVE_OPENMP_OFFLOAD
    1072              :             !$OMP TARGET EXIT DATA MAP(delete:theta_reshaped) IF(chebfi%gpu_option==ABI_GPU_OPENMP)
    1073              : #endif
    1074            0 :             ABI_SFREE(theta_reshaped)
    1075              :         end if
    1076              :     else
    1077            0 :         call xg_init(DivResults, space_res, chebfi%bandpp, 1, gpu_option=chebfi%gpu_option)
    1078            0 :         if (xmpi_comm_size(chebfi%spacecom) > 1) then
    1079            0 :             my_rank = xmpi_comm_rank(chebfi%spacecom)
    1080              :             !shift = my_rank * chebfi%bandpp ! FIXME not working for different bandpp per rank
    1081            0 :             num_proc = xmpi_comm_size(chebfi%spacecom)
    1082            0 :             ABI_MALLOC_IFNOT(allbandpp,(num_proc))
    1083            0 :             allbandpp_ptr => allbandpp
    1084            0 :             call xmpi_allgather(chebfi%bandpp, allbandpp_ptr, chebfi%spacecom, ierr)
    1085            0 :             if ( ierr /= xmpi_success ) then
    1086            0 :                 ABI_ERROR("Error while gathering number of bandpp for spacecom")
    1087              :             end if
    1088            0 :             if (my_rank==0) then
    1089              :                 shift = 0
    1090              :             else
    1091            0 :                 shift = sum(allbandpp(1:my_rank)) ! fixed
    1092              :             end if
    1093            0 :             ABI_SFREE(allbandpp)
    1094              :         else
    1095              :             shift = 0
    1096              :         end if
    1097              :         ! Fill DivResults(bandpp,1) with block of eigen(neigenpairs,1) of size bandpp
    1098              :         ! reshape to access column range
    1099            0 :         call xgBlock_reshape(DivResults%self, 1, chebfi%bandpp)
    1100            0 :         call xgBlock_reshape(eigen, 1, chebfi%neigenpairs)
    1101            0 :         if (space_res==SPACE_R) then
    1102            0 :             call xgBlock_setBlock(eigen, eigen_block, rows=1, cols=chebfi%bandpp, fcol=1+shift)
    1103            0 :             call xgBlock_copy(eigen_block, DivResults%self)
    1104              :         else
    1105              :             ! workaround to copy from SPACE_R to SPACE_C
    1106            0 :             ABI_MALLOC_IFNOT(theta_reshaped,(2,chebfi%bandpp))
    1107            0 :             theta_reshaped_ptr => theta_reshaped
    1108            0 :             call xgBlock_setBlock(eigen, eigen_block, rows=1, cols=chebfi%bandpp, fcol=1+shift)
    1109            0 :             call xgBlock_reverseMap(eigen_block, theta, rows=1, cols=chebfi%bandpp)
    1110            0 :             theta_reshaped = 0.d0
    1111            0 :             theta_reshaped(1,1:chebfi%bandpp) = theta(1,1:chebfi%bandpp)
    1112              : #ifdef HAVE_OPENMP_OFFLOAD
    1113              :             !$OMP TARGET ENTER DATA MAP(to:theta_reshaped) IF(chebfi%gpu_option==ABI_GPU_OPENMP)
    1114              : #endif
    1115              :             call xgBlock_map(eigen_block, theta_reshaped_ptr, space_res, rows=1, &
    1116            0 :                 cols=chebfi%bandpp, gpu_option=chebfi%gpu_option)
    1117            0 :             call xgBlock_copy(eigen_block, DivResults%self)
    1118              : #ifdef HAVE_OPENMP_OFFLOAD
    1119              :             !$OMP TARGET EXIT DATA MAP(delete:theta_reshaped) IF(chebfi%gpu_option==ABI_GPU_OPENMP)
    1120              : #endif
    1121            0 :             ABI_SFREE(theta_reshaped)
    1122              :         end if
    1123              :         ! restore dimensions
    1124            0 :         call xgBlock_reshape(eigen, chebfi%neigenpairs, 1)
    1125            0 :         call xgBlock_reshape(DivResults%self, chebfi%bandpp, 1)
    1126              :     end if
    1127              : 
    1128              :     ! DivResults must be on CPU for ampfactor routine
    1129            0 :     if (chebfi%gpu_option==ABI_GPU_OPENMP) then
    1130            0 :         call xgBlock_copy_from_gpu(DivResults%self)
    1131              :     end if
    1132              : 
    1133            0 : end subroutine chebfi_prepAmpfactor
    1134              : !!***
    1135              : 
    1136              : !----------------------------------------------------------------------
    1137              : 
    1138              : !!****f* m_chebfi2/chebfi_ampfactor
    1139              : !! NAME
    1140              : !! chebfi_ampfactor
    1141              : !!
    1142              : !! FUNCTION
    1143              : !! Compute amplification factor
    1144              : !!
    1145              : !! INPUTS
    1146              : !! eig (:,:)= eigenvalues
    1147              : !! lambda_minus,lambda_plus=
    1148              : !! ndeg_filter_bands(:)= degree of Chebyshev polynomial filter for each band
    1149              : !!
    1150              : !! OUTPUT
    1151              : !!
    1152              : !! SIDE EFFECTS
    1153              : !!  residu<type(xgBlock_t)>= vector of residuals
    1154              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
    1155              : !!
    1156              : !! SOURCE
    1157              : 
    1158         9024 : subroutine chebfi_ampfactor(chebfi,DivResults,lambda_minus,lambda_plus,ndeg_filter_bands)
    1159              : 
    1160              :   ! Arguments ------------------------------------
    1161              :   integer,           intent(in   ) :: ndeg_filter_bands(:)
    1162              :   type(xgBlock_t),   intent(in   ) :: DivResults
    1163              :   real(dp),          intent(in   ) :: lambda_minus
    1164              :   real(dp),          intent(in   ) :: lambda_plus
    1165              :   type(chebfi_t),    intent(inout) :: chebfi
    1166              : 
    1167              :   ! Local variables-------------------------------
    1168              :   ! scalars
    1169              :   integer         :: iband,nbands
    1170              :   real(dp)        :: ampfactor
    1171              :   real(dp)        :: eig_per_band
    1172              :   type(xgBlock_t) :: X_part
    1173              :   type(xgBlock_t) :: AX_part
    1174              :   type(xgBlock_t) :: BX_part
    1175         9024 :   real(dp),pointer :: eig(:,:)
    1176              : 
    1177              :   ! *********************************************************************
    1178              : 
    1179         9024 :   if (chebfi%paral_kgb == 0) then
    1180         2720 :     nbands = chebfi%neigenpairs
    1181              :   else
    1182         6304 :     nbands = chebfi%bandpp
    1183              :   end if
    1184              : 
    1185         9024 :   call xgBlock_reverseMap(DivResults,eig,rows=1,cols=chebfi%bandpp)
    1186              : 
    1187        53520 :   do iband = 1, nbands
    1188              : 
    1189        44496 :     eig_per_band = eig(1,iband)
    1190              : 
    1191              :     !cheb_poly1(x, n, a, b)
    1192        44496 :     ampfactor = cheb_poly1(eig_per_band, ndeg_filter_bands(iband), lambda_minus, lambda_plus)
    1193              : 
    1194        44496 :     if(abs(ampfactor) < 1e-3) ampfactor = 1e-3 !just in case, avoid amplifying too much
    1195              : 
    1196        44496 :     call xgBlock_setBlock(chebfi%xXColsRows, X_part, chebfi%total_spacedim, 1, fcol=iband)
    1197        44496 :     call xgBlock_setBlock(chebfi%xAXColsRows, AX_part, chebfi%total_spacedim, 1, fcol=iband)
    1198        44496 :     call xgBlock_setBlock(chebfi%xBXColsRows, BX_part, chebfi%total_spacedim, 1, fcol=iband)
    1199              : 
    1200        44496 :     call xgBlock_scale(X_part, 1/ampfactor, 1)
    1201        44496 :     call xgBlock_scale(AX_part, 1/ampfactor, 1)
    1202        53520 :     call xgBlock_scale(BX_part, 1/ampfactor, 1)
    1203              : 
    1204              :   end do
    1205              : 
    1206         9024 : end subroutine chebfi_ampfactor
    1207              : !!***
    1208              : 
    1209              : !----------------------------------------------------------------------
    1210              : 
    1211              : !!****f* m_chebfi2/chebfi_ampfactorBandpass
    1212              : !! NAME
    1213              : !! chebfi_ampfactorBandpass
    1214              : !!
    1215              : !! FUNCTION
    1216              : !! Compute amplification factor for bandpass polynomial
    1217              : !! Numerical zero is 1e-3. Assumes prepAmpfactor prior to this.
    1218              : !!
    1219              : !! INPUTS
    1220              : !! eig (:,:)= eigenvalues
    1221              : !! lambda_minus,lambda_plus=
    1222              : !! center,radius= used to rescale bandpass filter to interval
    1223              : !! ndeg_filter= degree of bandpass polynomial filter
    1224              : !!
    1225              : !! OUTPUT
    1226              : !!
    1227              : !! SIDE EFFECTS
    1228              : !!  residu<type(xgBlock_t)>= vector of residuals
    1229              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
    1230              : !!
    1231              : !! SOURCE
    1232              : 
    1233              : subroutine chebfi_ampfactorBandpass(chebfi,DivResults,lambda_minus,lambda_plus,center,radius,ndeg_filter)
    1234              : 
    1235              :   implicit none
    1236              : 
    1237              :   ! Arguments ------------------------------------
    1238              :   integer,           intent(in   ) :: ndeg_filter
    1239              :   type(xgBlock_t),   intent(in   ) :: DivResults
    1240              :   real(dp),          intent(in   ) :: lambda_minus
    1241              :   real(dp),          intent(in   ) :: lambda_plus
    1242              :   real(dp),          intent(in   ) :: center
    1243              :   real(dp),          intent(in   ) :: radius
    1244              :   type(chebfi_t),    intent(inout) :: chebfi
    1245              : 
    1246              :   ! Local variables-------------------------------
    1247              :   ! scalars
    1248              :   integer         :: iband,nbands
    1249              :   real(dp)        :: ampfactor
    1250              :   real(dp)        :: xred, ls, us
    1251              :   real(dp)        :: eig_per_band
    1252              :   type(xgBlock_t) :: X_part
    1253              :   type(xgBlock_t) :: AX_part
    1254              :   type(xgBlock_t) :: BX_part
    1255              :   real(dp),pointer :: eig(:,:)
    1256              : 
    1257              :   ! *********************************************************************
    1258              : 
    1259              :   if (chebfi%paral_kgb == 0) then
    1260              :     nbands = chebfi%neigenpairs
    1261              :   else
    1262              :     nbands = chebfi%bandpp
    1263              :   end if
    1264              :   ls = (lambda_minus-center)/radius
    1265              :   us = (lambda_plus-center)/radius
    1266              : 
    1267              :   call xgBlock_reverseMap(DivResults,eig,rows=1,cols=chebfi%bandpp)
    1268              : 
    1269              :   do iband = 1, nbands
    1270              : 
    1271              :     eig_per_band = eig(1,iband)
    1272              : 
    1273              :     !poly(x, a, b, n), where x,a,b are scaled!!!
    1274              :     xred = (eig_per_band-center)/radius
    1275              :     ampfactor = bandpassIndicator_sca(xred, ls, us, ndeg_filter)
    1276              : 
    1277              :     if(abs(ampfactor) < 1e-3) ampfactor = 1e-3 !just in case, avoid amplifying too much
    1278              : 
    1279              :     call xgBlock_setBlock(chebfi%xXColsRows, X_part, chebfi%total_spacedim, 1, fcol=iband)
    1280              :     call xgBlock_setBlock(chebfi%xAXColsRows, AX_part, chebfi%total_spacedim, 1, fcol=iband)
    1281              :     call xgBlock_setBlock(chebfi%xBXColsRows, BX_part, chebfi%total_spacedim, 1, fcol=iband)
    1282              : 
    1283              :     !write(std_out,*) 'ampfactor, eig, iband=', eig_per_band, ampfactor, iband
    1284              : 
    1285              :     call xgBlock_scale(X_part, 1/ampfactor, 1)
    1286              :     call xgBlock_scale(AX_part, 1/ampfactor, 1)
    1287              :     call xgBlock_scale(BX_part, 1/ampfactor, 1)
    1288              : 
    1289              :   end do
    1290              : 
    1291              : end subroutine chebfi_ampfactorBandpass
    1292              : !!***
    1293              : 
    1294              : !----------------------------------------------------------------------
    1295              : 
    1296              : !!****f* m_chebfi/chebfi_runSlice
    1297              : !! NAME
    1298              : !! chebfi_runSlice
    1299              : !!
    1300              : !! FUNCTION
    1301              : !! Apply Polynomial filtering to set of vectors.
    1302              : !!
    1303              : !! NOTES
    1304              : !! List of differences with chebfi_run:
    1305              : !! - X0 input and output is in ColsRows MPI representation (not Linalg!).
    1306              : !! - the filter polynomial can be lowpass or bandpass.
    1307              : !! - Rayleigh Quotients are read from eigen.
    1308              : !!
    1309              : !! INPUT
    1310              : !! chebfi <type(chebfi_t)>= all data used to apply Polynomial Filtering algorithm
    1311              : !! X0= eigenvector guess distributed in ColsRows representation
    1312              : !! getAX_BX= pointer to the function giving A|X> and B|X>
    1313              : !!           A is typically the Hamiltonian H, and B the overlap operator S
    1314              : !! getBm1X= pointer to the function giving B^-1|X>
    1315              : !!          B is typically the overlap operator S
    1316              : !! eigen= Rayleigh quotients associated to X0
    1317              : !! residu= empty array
    1318              : !! nspinor= number of spinorial components of the wavefunctions
    1319              : !! lambda_minus= lower interval to amplify/diminish for bandpass/lowpass
    1320              : !! lambda_plus= upper interval to amplify/diminish for bandpass/lowpass
    1321              : !! mineig_global= guaranteed lower bound for entire spectrum
    1322              : !! maxeig_global= guaranteed upper bound for entire spectrum
    1323              : !! is_lowpass= flag. True if Chebyshev otherwise use bandpass Chebyshev-Jackson
    1324              : !! nrows_blockrows= number of rows per MPI block in Linalg representation
    1325              : !!
    1326              : !! SIDE EFFECTS
    1327              : !! chebfi= workspaces used
    1328              : !! X0= full set of vectors distributed in ColsRows representation
    1329              : !! eigen= full eigenvalues
    1330              : !! residu= residuals, i.e. norm of (A-lambdaB)|X>
    1331              : !!
    1332              : !! SOURCE
    1333              : 
    1334            0 : subroutine chebfi_runSlice(chebfi,X0,getAX_BX,getBm1X,eigen,residu,nspinor,&
    1335              :         mineig_global,maxeig_global,lambda_minus,lambda_plus,is_lowpass,nrows_blockrows)
    1336              : 
    1337              :     implicit none
    1338              : 
    1339              :     !Arguments ------------------------------------
    1340              :     type(chebfi_t) , intent(inout) :: chebfi
    1341              :     type(xgBlock_t), intent(inout) :: X0
    1342              :     type(xgBlock_t), intent(inout) :: eigen
    1343              :     type(xgBlock_t), intent(inout) :: residu
    1344              :     integer        , intent(in   ) :: nspinor
    1345              :     integer, pointer, intent(in  ) :: nrows_blockrows(:)
    1346              :     real(dp)       , intent(in   ) :: mineig_global
    1347              :     real(dp)       , intent(in   ) :: maxeig_global
    1348              :     real(dp)       , intent(in   ) :: lambda_minus
    1349              :     real(dp)       , intent(in   ) :: lambda_plus
    1350              :     logical        , intent(in   ) :: is_lowpass
    1351              :     interface
    1352              :         subroutine getAX_BX(X,AX,BX)
    1353              :             use m_xg, only : xgBlock_t
    1354              :             type(xgBlock_t), intent(inout) :: X
    1355              :             type(xgBlock_t), intent(inout) :: AX
    1356              :             type(xgBlock_t), intent(inout) :: BX
    1357              :         end subroutine getAX_BX
    1358              :     end interface
    1359              :     interface
    1360              :         subroutine getBm1X(X,Bm1X)
    1361              :             use m_xg, only : xgBlock_t
    1362              :             type(xgBlock_t), intent(inout) :: X
    1363              :             type(xgBlock_t), intent(inout) :: Bm1X
    1364              :         end subroutine getBm1X
    1365              :     end interface
    1366              : 
    1367              :     !Local variables-------------------------------
    1368              :     integer :: spacedim, neigenpairs, num_proc, ierr
    1369              :     !type(xg_t) :: X_k
    1370              :     ! Arrays
    1371            0 :     integer, target, allocatable :: nrowsLinalg(:)
    1372              :     integer, pointer :: nrowsLinalg_ptr(:) => null()
    1373              :     real(dp) :: tsec(2)
    1374              : 
    1375              :     ! *********************************************************************
    1376              : 
    1377            0 :     if (chebfi%from_linalg) then
    1378            0 :         ABI_ERROR("chebfi should be from colsrows")
    1379              :     end if
    1380              : 
    1381            0 :     spacedim = chebfi%spacedim
    1382            0 :     neigenpairs = chebfi%neigenpairs
    1383            0 :     num_proc = xmpi_comm_size(chebfi%spacecom)
    1384            0 :     chebfi%eigenvalues = eigen
    1385              : 
    1386            0 :     ABI_MALLOC_IFNOT(nrowsLinalg,(num_proc))
    1387            0 :     nrowsLinalg_ptr => nrowsLinalg
    1388            0 :     nrowsLinalg = nrows_blockrows
    1389              : 
    1390              :     !write(std_out,*) 'getid inside runSlice xXColsRows', xgBlock_getId(chebfi%xXColsRows)
    1391              :     !write(std_out,*) 'getid inside runSlice xAXColsRows', xgBlock_getId(chebfi%xAXColsRows)
    1392              :     !flush(std_out)
    1393              : 
    1394              :     !A * Psi
    1395            0 :     call timab(tim_getAX_BX,1,tsec)
    1396              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    1397            0 :     call getAX_BX(chebfi%xXColsRows, chebfi%xAXColsRows, chebfi%xBXColsRows)
    1398            0 :     call xgBlock_zero_im_g0(chebfi%xAXColsRows)
    1399            0 :     call xgBlock_zero_im_g0(chebfi%xBXColsRows)
    1400              :     ABI_NVTX_END_RANGE()
    1401            0 :     call timab(tim_getAX_BX,2,tsec)
    1402              : 
    1403              :     !write(std_out,*) 'getid inside runSlice xXColsRows (filtered 1)', xgBlock_getId(chebfi%xXColsRows)
    1404              :     !write(std_out,*) 'getid inside runSlice xAXColsRows (filtered 1)', xgBlock_getId(chebfi%xAXColsRows)
    1405              : 
    1406            0 :     write(std_out,*) 'starting filter in proc', xmpi_comm_rank(chebfi%spacecom)
    1407            0 :     flush(std_out)
    1408              : 
    1409              :     ! Apply polynomial filtering to active MPI ColsRows block-column
    1410            0 :     if (is_lowpass) then
    1411              :         ! [lambda_minus,lambda_plus) is diminished using Chebyshev
    1412            0 :         write(std_out,*) 'lambda_minus=', lambda_minus
    1413            0 :         write(std_out,*) 'lambda_plus=', lambda_plus
    1414            0 :         flush(std_out)
    1415            0 :         call chebfi_lowpassFilter(chebfi,eigen,lambda_minus,lambda_plus,getAX_BX,getBm1X)
    1416              :     else
    1417            0 :         write(std_out,*) 'lambda_minus=', lambda_minus
    1418            0 :         write(std_out,*) 'lambda_plus=', lambda_plus
    1419            0 :         write(std_out,*) 'mineig_global=', mineig_global
    1420            0 :         write(std_out,*) 'maxeig_global=', maxeig_global
    1421            0 :         flush(std_out)
    1422              :         call chebfi_bandpassFilter(chebfi,lambda_minus,lambda_plus,mineig_global,&
    1423            0 :             maxeig_global,getAX_BX,getBm1X)
    1424              :     end if
    1425              : 
    1426              :     !write(std_out,*) 'getid inside runSlice xXColsRows (filtered N)', xgBlock_getId(chebfi%xXColsRows)
    1427              :     !write(std_out,*) 'getid inside runSlice xAXColsRows (filtered N)', xgBlock_getId(chebfi%xAXColsRows)
    1428              :     !flush(std_out)
    1429              : 
    1430              :     ! MPI transpose to linalg state
    1431            0 :     call timab(tim_transpose,1,tsec)
    1432              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1433            0 :     if (chebfi%paral_kgb==1) then
    1434              : 
    1435              :         ! Allocate chebfi%X
    1436              :         call xgTransposer_constructor(chebfi%xgTransposerX,chebfi%X,chebfi%xXColsRows,nspinor,&
    1437              :             STATE_COLSROWS,TRANS_ALL2ALL,chebfi%comm_rows,chebfi%comm_cols,0,0,chebfi%me_g0,&
    1438              :             gpu_option=chebfi%gpu_option,gpu_thread_limit=chebfi%gpu_thread_limit,&
    1439            0 :             custom_ncolsColsRows=.true.,nrowsLinalg_sub=nrowsLinalg_ptr)
    1440              :         ! Note: bandpp is custom because it is created from resource allocator
    1441              : 
    1442              :         ! Allocate chebfi%AX, chebfi%BX
    1443              :         call xgTransposer_copyConstructor(chebfi%xgTransposerAX,chebfi%xgTransposerX,&
    1444            0 :             chebfi%AX%self,chebfi%xAXColsRows,STATE_COLSROWS)
    1445              :         call xgTransposer_copyConstructor(chebfi%xgTransposerBX,chebfi%xgTransposerX,&
    1446            0 :             chebfi%BX%self,chebfi%xBXColsRows,STATE_COLSROWS)
    1447              :         ! Note: at this point chebfi%AX and chebfi%BX are empty. Must transpose
    1448              :         !       to fill with correct values.
    1449              : 
    1450              :         ! todo use copy constructor to create an object by copying an existing object
    1451              :         ! actually copy constructor *allocates* memory for chebfi%AX. Write a version
    1452              :         ! that does not allocate memory and only reassigns pointers. Can pointers be reassigned
    1453              :         ! directly then used in the global constructor? Perform tests.
    1454              : 
    1455              :         !write(std_out,*) 'getid before transpose AX', xgBlock_getId(chebfi%AX%self)
    1456              :         !write(std_out,*) 'getid before transpose xAX', xgBlock_getId(chebfi%xAXColsRows)
    1457              :         !write(std_out,*) 'getid before transpose xX', xgBlock_getId(chebfi%xXColsRows)
    1458              :         !flush(std_out)
    1459              : 
    1460            0 :         chebfi%xgTransposerX%gpu_kokkos_nthrd  = chebfi%gpu_kokkos_nthrd
    1461            0 :         chebfi%xgTransposerAX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
    1462            0 :         chebfi%xgTransposerBX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
    1463              : 
    1464            0 :         call xgTransposer_transpose(chebfi%xgTransposerX, STATE_LINALG)
    1465            0 :         call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_LINALG)
    1466            0 :         call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_LINALG)
    1467            0 :         call xmpi_barrier(chebfi%spacecom)
    1468              : 
    1469              :         !write(std_out,*) 'getid after transpose AX', xgBlock_getId(chebfi%AX%self)
    1470              :         !flush(std_out)
    1471              : 
    1472              :     else
    1473            0 :         call xgBlock_setBlock(chebfi%xXColsRows, chebfi%X, spacedim, neigenpairs)
    1474            0 :         call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
    1475            0 :         call xgBlock_setBlock(chebfi%xBXColsRows, chebfi%BX%self, spacedim, neigenpairs)
    1476              :     end if
    1477            0 :     call timab(tim_transpose,2,tsec)
    1478              :     ABI_NVTX_END_RANGE()
    1479              : 
    1480            0 :     if (chebfi%paral_kgb==1 .and. rows(chebfi%X) /= nrowsLinalg(xmpi_comm_rank(chebfi%spacecom)+1)) then
    1481            0 :         ABI_ERROR("wrong linalg representation")
    1482              :     end if
    1483            0 :     write(std_out,'(a,i6,i6)') 'local # proc has # rows ', xmpi_comm_rank(chebfi%spacecom), rows(chebfi%X)
    1484              : 
    1485              :     !write(std_out,*) 'chebfi%eigenvalues before RR'
    1486              :     !call xgBlock_print(chebfi%eigenvalues,std_out)
    1487              : 
    1488              :     !write(std_out,*) 'id of X, (before RR) ncols=', xgBlock_getId(chebfi%X), cols(chebfi%X)
    1489              :     !flush(std_out)
    1490              : 
    1491              :     !call xg_Borthonormalize(chebfi%xXColsRows,chebfi%xBxColsRows,ierr,1,chebfi%gpu_option,AX=chebfi%xAXColsRows)
    1492              : 
    1493              :     ! Apply Rayleigh-Ritz to active MPI Linalg row-block
    1494              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_RR)
    1495              :     call xg_RayleighRitz(chebfi%X,chebfi%AX%self,chebfi%BX%self,eigen,ierr,0,tim_RR,&
    1496            0 :         chebfi%gpu_option,solve_ax_bx=.true.)
    1497              :     ABI_NVTX_END_RANGE()
    1498              : 
    1499              :     !write(std_out,*) 'id of X, (after RR) ncols=', xgBlock_getId(chebfi%X), cols(chebfi%X)
    1500              : 
    1501            0 :     if ( ierr /= 0 ) then
    1502            0 :         ABI_WARNING("RayleighRitz did not work")
    1503              :     else
    1504              :         !write(std_out,*) 'is lowpass=', is_lowpass
    1505              :         !write(std_out,*) 'chebfi%eigenvalues after RR'
    1506              :         !call xgBlock_print(chebfi%eigenvalues,std_out)
    1507              :         !flush(std_out)
    1508              :     end if
    1509              : 
    1510              :     ! Compute residual norm *squared*
    1511            0 :     if (chebfi%paw) then
    1512            0 :         call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%BX%self,chebfi%AX%self)
    1513              :     else
    1514            0 :         call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%X,chebfi%AX%self)
    1515              :     end if
    1516            0 :     call xgBlock_colwiseNorm2(chebfi%AX%self,residu) ! performs MPI comm
    1517              : 
    1518              :     !write(std_out,*) 'max colwise residual norm squared='; call xgBlock_print(residu, std_out)
    1519              :     !flush(std_out)
    1520              : 
    1521              :     ! Copy in Linalg representation (see chebfi_run, kept for reference)
    1522              :     ! call xgBlock_copy(chebfi%X,X0)
    1523              : 
    1524              :     ! MPI Transpose to recover colsrows state (X only)
    1525            0 :     call timab(tim_transpose,1,tsec)
    1526              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1527            0 :     if (chebfi%paral_kgb == 1) then
    1528            0 :         call xmpi_barrier(chebfi%spacecom)
    1529            0 :         call xgTransposer_transpose(chebfi%xgTransposerX, STATE_COLSROWS)
    1530            0 :         call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_COLSROWS)
    1531            0 :         call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_COLSROWS)
    1532            0 :         if (xmpi_comm_size(chebfi%spacecom) == 1) then
    1533            0 :             call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)
    1534            0 :             call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)
    1535            0 :             call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
    1536              :         end if
    1537              :     else
    1538            0 :         call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)
    1539            0 :         call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)
    1540            0 :         call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
    1541              :     end if
    1542              :     ABI_NVTX_END_RANGE()
    1543            0 :     call timab(tim_transpose,2,tsec)
    1544              : 
    1545              :     ! Copy in ColsRows representation
    1546            0 :     call xgBlock_copy(chebfi%xXColsRows, X0)
    1547              : 
    1548            0 :     if (cols(X0) /= chebfi%bandpp) then
    1549            0 :         ABI_ERROR('wrong colsrows representation')
    1550              :     end if
    1551            0 :     write(std_out,'(a,i6,i6,i6)') 'local # proc has # rows cols ', xmpi_comm_rank(chebfi%spacecom), rows(X0), cols(X0)
    1552              : 
    1553              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
    1554              :     if (chebfi%gpu_option==ABI_GPU_KOKKOS) then
    1555              :         call gpu_device_synchronize()
    1556              :     end if
    1557              : #endif
    1558              : 
    1559              :     ! Free transposer objects
    1560            0 :     if (chebfi%paral_kgb == 1) then
    1561            0 :         call xgTransposer_free(chebfi%xgTransposerX)
    1562            0 :         call xgTransposer_free(chebfi%xgTransposerAX)
    1563            0 :         call xgTransposer_free(chebfi%xgTransposerBX)
    1564              :     end if
    1565              : 
    1566              :     ! Free temporary memory
    1567            0 :     ABI_SFREE(nrowsLinalg)
    1568              : 
    1569            0 : end subroutine chebfi_runSlice
    1570              : !!***
    1571              : 
    1572              : !----------------------------------------------------------------------
    1573              : 
    1574              : !!****f* m_chebfi/chebfi_runSubspaceIteration
    1575              : !! NAME
    1576              : !! chebfi_runSubspaceIteration
    1577              : !!
    1578              : !! FUNCTION
    1579              : !! Applies subspace iteration by Chebyshev polynomial filtering on slice
    1580              : !! then extracts eigenvectors using Rayleigh-Ritz. This execution is completely
    1581              : !! local on slice processors. Each slice does not see others.
    1582              : !!
    1583              : !! NOTES
    1584              : !! Restart logic in subspace iteration:
    1585              : !!   Allocate constructor (state=colsrows)
    1586              : !!   while (convergence not reached):
    1587              : !!    |  if (state=linalg) Transpose
    1588              : !!    |  Filter
    1589              : !!    |  Transpose (state=linalg)
    1590              : !!    |  Orthogonalize
    1591              : !!   Rayleigh-Ritz
    1592              : !!
    1593              : !! INPUTS
    1594              : !! X0 input vectors distibuted by colsrows along slice processors
    1595              : !!
    1596              : !! OUTPUTS
    1597              : !! X0 (in-place) converged vectors distributed by linalg along slice processors
    1598              : !!
    1599              : !! dev=============
    1600              : !! - version 1: count number of converged vectors within iteration
    1601              : !!
    1602              : !! SOURCE
    1603              : 
    1604            0 : subroutine chebfi_runSubspaceIteration(chebfi,X0,getAX_BX,getBm1X,eigen,residu,nspinor,&
    1605              :         mineig_global,maxeig_global,lambda_minus,lambda_plus,is_lowpass,k_conv,nrows_blockrows)
    1606              : 
    1607              :     implicit none
    1608              : 
    1609              :     !Arguments ------------------------------------
    1610              :     type(chebfi_t) , intent(inout) :: chebfi
    1611              :     type(xgBlock_t), intent(inout) :: X0
    1612              :     type(xgBlock_t), intent(inout) :: eigen
    1613              :     type(xgBlock_t), intent(inout) :: residu
    1614              :     integer        , intent(in   ) :: nspinor
    1615              :     integer        , intent(in   ) :: k_conv
    1616              :     integer, pointer, intent(in  ) :: nrows_blockrows(:)
    1617              :     real(dp)       , intent(in   ) :: mineig_global
    1618              :     real(dp)       , intent(in   ) :: maxeig_global
    1619              :     real(dp)       , intent(in   ) :: lambda_minus
    1620              :     real(dp)       , intent(in   ) :: lambda_plus
    1621              :     logical        , intent(in   ) :: is_lowpass
    1622              :     interface
    1623              :         subroutine getAX_BX(X,AX,BX)
    1624              :             use m_xg, only : xgBlock_t
    1625              :             type(xgBlock_t), intent(inout) :: X
    1626              :             type(xgBlock_t), intent(inout) :: AX
    1627              :             type(xgBlock_t), intent(inout) :: BX
    1628              :         end subroutine getAX_BX
    1629              :     end interface
    1630              :     interface
    1631              :         subroutine getBm1X(X,Bm1X)
    1632              :             use m_xg, only : xgBlock_t
    1633              :             type(xgBlock_t), intent(inout) :: X
    1634              :             type(xgBlock_t), intent(inout) :: Bm1X
    1635              :         end subroutine getBm1X
    1636              :     end interface
    1637              : 
    1638              :     !Local variables-------------------------------
    1639              :     integer :: iter_subspace, niter_subspace_max, n_locked, n_locked_prev
    1640              :     integer :: spacedim, neigenpairs, num_proc, nrows, nrows_mpi, ierr
    1641              :     !type(xg_t) :: X_k
    1642              :     type(xg_t) :: resid_active
    1643              :     type(bandPartitionInfo_t) :: mpiInfo
    1644            0 :     type(bandPartitionData_t) :: X_part
    1645            0 :     type(bandPartitionData_t) :: AX_part
    1646            0 :     type(bandPartitionData_t) :: BX_part
    1647              :     ! Arrays
    1648            0 :     integer, target, allocatable :: nrowsLinalg(:)
    1649              :     integer, pointer :: nrowsLinalg_ptr(:) => null()
    1650              :     real(dp) :: tsec(2)
    1651              : 
    1652              :     ! *********************************************************************
    1653              : 
    1654            0 :     if (chebfi%from_linalg) then
    1655            0 :         ABI_ERROR("chebfi should be from colsrows")
    1656              :     end if
    1657              : 
    1658            0 :     spacedim = chebfi%spacedim
    1659            0 :     neigenpairs = chebfi%neigenpairs
    1660            0 :     num_proc = xmpi_comm_size(chebfi%spacecom)
    1661            0 :     chebfi%eigenvalues = eigen
    1662              : 
    1663            0 :     ABI_MALLOC_IFNOT(nrowsLinalg,(num_proc))
    1664            0 :     nrowsLinalg_ptr => nrowsLinalg
    1665            0 :     nrowsLinalg = nrows_blockrows
    1666              : 
    1667            0 :     call xg_init(resid_active, SPACE_R, neigenpairs, 1, gpu_option=chebfi%gpu_option)
    1668              : 
    1669              :     ! Initialize values of AX and BX
    1670            0 :     call timab(tim_getAX_BX,1,tsec)
    1671              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    1672            0 :     call getAX_BX(chebfi%xXColsRows, chebfi%xAXColsRows, chebfi%xBXColsRows)
    1673            0 :     call xgBlock_zero_im_g0(chebfi%xAXColsRows)
    1674            0 :     call xgBlock_zero_im_g0(chebfi%xBXColsRows)
    1675              :     ABI_NVTX_END_RANGE()
    1676            0 :     call timab(tim_getAX_BX,2,tsec)
    1677              : 
    1678              :     ! Allocate memory for linalg distribution from colsrows
    1679              :     ! Note: bandpp is custom because it is created from resource allocator
    1680            0 :     call timab(tim_transpose,1,tsec)
    1681              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1682            0 :     if (chebfi%paral_kgb==1) then
    1683              : 
    1684              :         ! Allocate chebfi%X
    1685              :         call xgTransposer_constructor(chebfi%xgTransposerX,chebfi%X,chebfi%xXColsRows,nspinor,&
    1686              :             STATE_COLSROWS,TRANS_ALL2ALL,chebfi%comm_rows,chebfi%comm_cols,0,0,chebfi%me_g0,&
    1687              :             gpu_option=chebfi%gpu_option,gpu_thread_limit=chebfi%gpu_thread_limit,&
    1688            0 :             custom_ncolsColsRows=.true.,nrowsLinalg_sub=nrowsLinalg_ptr)
    1689              : 
    1690              :         ! Allocate chebfi%AX, chebfi%BX
    1691              :         call xgTransposer_copyConstructor(chebfi%xgTransposerAX,chebfi%xgTransposerX,&
    1692            0 :             chebfi%AX%self,chebfi%xAXColsRows,STATE_COLSROWS)
    1693              :         call xgTransposer_copyConstructor(chebfi%xgTransposerBX,chebfi%xgTransposerX,&
    1694            0 :             chebfi%BX%self,chebfi%xBXColsRows,STATE_COLSROWS)
    1695              :         ! Note: at this point chebfi%AX and chebfi%BX are empty. Must transpose
    1696              :         !       to fill with correct values.
    1697              : 
    1698            0 :         chebfi%xgTransposerX%gpu_kokkos_nthrd  = chebfi%gpu_kokkos_nthrd
    1699            0 :         chebfi%xgTransposerAX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
    1700            0 :         chebfi%xgTransposerBX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
    1701              : 
    1702              :     else
    1703            0 :         call xgBlock_setBlock(chebfi%xXColsRows, chebfi%X, spacedim, neigenpairs)
    1704            0 :         call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
    1705            0 :         call xgBlock_setBlock(chebfi%xBXColsRows, chebfi%BX%self, spacedim, neigenpairs)
    1706              :     end if
    1707            0 :     call timab(tim_transpose,2,tsec)
    1708              :     ABI_NVTX_END_RANGE()
    1709              : 
    1710            0 :     write(std_out,*) 'starting filter in proc', xmpi_comm_rank(chebfi%spacecom)
    1711            0 :     flush(std_out)
    1712              : 
    1713            0 :     niter_subspace_max = 10
    1714            0 :     n_locked = 0
    1715            0 :     n_locked_prev = 0
    1716            0 :     nrows = rows(chebfi%xXColsRows)
    1717            0 :     nrows_mpi = rows(chebfi%X)
    1718              : 
    1719              :     ! Initialize active vectors (in colsrows distribution)
    1720            0 :     call xgBlock_setBlock(chebfi%xXColsRows , X_part%colsrows_active , nrows, chebfi%bandpp)
    1721            0 :     call xgBlock_setBlock(chebfi%xAXColsRows, AX_part%colsrows_active, nrows, chebfi%bandpp)
    1722            0 :     call xgBlock_setBlock(chebfi%xBXColsRows, BX_part%colsrows_active, nrows, chebfi%bandpp)
    1723              : 
    1724            0 :     do iter_subspace=1, niter_subspace_max
    1725              : 
    1726            0 :         write(std_out,*) 'subspace iteration no=', iter_subspace
    1727            0 :         flush(std_out)
    1728              : 
    1729              :         ! ############################   Manage MPI   ##############################
    1730            0 :         if (iter_subspace>1 .and. chebfi%paral_kgb==1) then
    1731              : 
    1732            0 :             if (n_locked > 0 .and. n_locked /= n_locked_prev ) then
    1733              : 
    1734              :                 ! Assign active bands to processes
    1735            0 :                 call bandPartitionInfo_initActiveSubcomm(mpiInfo, chebfi%comm_cols, chebfi%bandpp)
    1736              : 
    1737              :                 ! Allocate colsrows distributions for active vectors (from linalg distribution)
    1738            0 :                 call bandPartitionData_allocActiveColsrows(X_part, chebfi, mpiInfo, nspinor)
    1739            0 :                 call bandPartitionData_allocActiveColsrows(AX_part, chebfi, mpiInfo, nspinor)
    1740            0 :                 call bandPartitionData_allocActiveColsrows(BX_part, chebfi, mpiInfo, nspinor)
    1741              : 
    1742              :                 ! Transpose active vectors to colsrows distribution
    1743              :                 ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1744            0 :                 call timab(tim_transpose,1,tsec)
    1745            0 :                 call xgTransposer_transpose(X_part%transposer_active, STATE_COLSROWS)
    1746            0 :                 call xgTransposer_transpose(AX_part%transposer_active, STATE_COLSROWS)
    1747            0 :                 call xgTransposer_transpose(BX_part%transposer_active, STATE_COLSROWS)
    1748            0 :                 call timab(tim_transpose,2,tsec)
    1749              :                 ABI_NVTX_END_RANGE()
    1750              : 
    1751              :             else
    1752              : 
    1753              :                 ! Use global transposer
    1754              :                 ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1755            0 :                 call timab(tim_transpose,1,tsec)
    1756            0 :                 call xgTransposer_transpose(chebfi%xgTransposerX, STATE_COLSROWS)
    1757            0 :                 call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_COLSROWS)
    1758            0 :                 call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_COLSROWS)
    1759            0 :                 call timab(tim_transpose,2,tsec)
    1760              :                 ABI_NVTX_END_RANGE()
    1761              :             end if
    1762              : 
    1763              :         end if
    1764              : 
    1765              :         ! ############################ Filter active  ##############################
    1766              :         ! ############################ column vectors ##############################
    1767            0 :         if (is_lowpass) then
    1768              :             call chebfi_lowpassFilterActive(chebfi,X_part%colsrows_active,AX_part%colsrows_active,&
    1769            0 :                 BX_part%colsrows_active,eigen,lambda_minus,lambda_plus,getAX_BX,getBm1X)
    1770              :         else
    1771              :             call chebfi_bandpassFilterActive(chebfi,X_part%colsrows_active,AX_part%colsrows_active,&
    1772              :                 BX_part%colsrows_active,lambda_minus,lambda_plus,mineig_global,maxeig_global,&
    1773            0 :                 getAX_BX,getBm1X)
    1774              :         end if
    1775              :         ! todo prevent bug X_next, X_prev might need resetting
    1776              : 
    1777              :         ! ############################   Manage MPI   ##############################
    1778            0 :         if (chebfi%paral_kgb==1) then
    1779              : 
    1780            0 :             if (n_locked > 0) then
    1781              : 
    1782            0 :                 call timab(tim_transpose,1,tsec)
    1783              :                 ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1784            0 :                 call xgTransposer_transpose(X_part%transposer_active, STATE_LINALG)
    1785            0 :                 call xgTransposer_transpose(AX_part%transposer_active, STATE_LINALG)
    1786            0 :                 call xgTransposer_transpose(BX_part%transposer_active, STATE_LINALG)
    1787              :                 ABI_NVTX_END_RANGE()
    1788            0 :                 call timab(tim_transpose,2,tsec)
    1789              : 
    1790              :             else
    1791              : 
    1792              :                 ! Use global transposer
    1793              :                 ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1794            0 :                 call timab(tim_transpose,1,tsec)
    1795            0 :                 call xgTransposer_transpose(chebfi%xgTransposerX, STATE_LINALG)
    1796            0 :                 call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_LINALG)
    1797            0 :                 call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_LINALG)
    1798            0 :                 call timab(tim_transpose,2,tsec)
    1799              :                 ABI_NVTX_END_RANGE()
    1800              : 
    1801              :                 ! Initialize active vectors (in linalg distribution)
    1802            0 :                 call xgBlock_setBlock(chebfi%X      , X_part%linalg_active , nrows_mpi, neigenpairs)
    1803            0 :                 call xgBlock_setBlock(chebfi%AX%self, AX_part%linalg_active, nrows_mpi, neigenpairs)
    1804            0 :                 call xgBlock_setBlock(chebfi%BX%self, BX_part%linalg_active, nrows_mpi, neigenpairs)
    1805              : 
    1806              :             end if
    1807              : 
    1808              :         end if
    1809              : 
    1810            0 :         write(std_out,'(a,i6,i6)') 'chebfi%X # rows # cols ', rows(chebfi%X), cols(chebfi%X)
    1811            0 :         write(std_out,'(a,i6,i6)') 'X_active(linalg) # rows # cols ', nrows_mpi, neigenpairs
    1812            0 :         flush(std_out)
    1813              : 
    1814            0 :         write(std_out,*) 'getid X     ', xgBlock_getid(chebfi%X)
    1815            0 :         write(std_out,*) 'getid AX    ', xgBlock_getid(chebfi%AX%self)
    1816            0 :         write(std_out,*) 'getid BX    ', xgBlock_getid(chebfi%BX%self)
    1817            0 :         write(std_out,*) 'space(X)    ', space(chebfi%X)
    1818            0 :         write(std_out,*) 'comm(X)     ', comm(chebfi%X)
    1819            0 :         write(std_out,*) 'getid Xpart ', xgBlock_getid(X_part%linalg_active)
    1820            0 :         write(std_out,*) 'getid AXpart', xgBlock_getid(AX_part%linalg_active)
    1821            0 :         write(std_out,*) 'getid BXpart', xgBlock_getid(BX_part%linalg_active)
    1822            0 :         write(std_out,*) 'space(Xpart)', space(X_part%linalg_active)
    1823            0 :         write(std_out,*) 'comm(Xpart) ', comm(X_part%linalg_active)
    1824            0 :         flush(std_out)
    1825              : 
    1826              :         ! #######################   Deflate+Ortho+Residual  ##############################
    1827              :         ! ####################### for active column vectors ##############################
    1828              : 
    1829            0 :         if (n_locked > 0) then
    1830            0 :             call chebfi_deflateActiveWrtLocked(chebfi, n_locked, X_part, AX_part, BX_part)
    1831              :         end if
    1832              : 
    1833              :         call xg_Borthonormalize(X_part%linalg_active,BX_part%linalg_active,ierr,1,&
    1834            0 :             chebfi%gpu_option,AX=AX_part%linalg_active)
    1835              : 
    1836            0 :         call chebfi_getSubspaceResidual(chebfi, resid_active%self)
    1837              : 
    1838              : 
    1839              : 
    1840            0 :         call chebfi_swapConvergedVectors(chebfi, resid_active%self, 1e-3_dp, n_locked)
    1841              :         ! todo check if residual of wanted bands has converged if yes skip parts
    1842              :         ! use k_conv as number of wanted bands
    1843            0 :         write(std_out,*) 'keeping', k_conv, 'bands'
    1844            0 :         flush(std_out)
    1845              : 
    1846            0 :         if (chebfi%paral_kgb==1 .and. iter_subspace>1 .and. n_locked > 0 .and. n_locked /= n_locked_prev) then
    1847            0 :             call bandPartitionData_setLinalg(chebfi%X      , X_part , n_locked)
    1848            0 :             call bandPartitionData_setLinalg(chebfi%AX%self, AX_part, n_locked)
    1849            0 :             call bandPartitionData_setLinalg(chebfi%BX%self, BX_part, n_locked)
    1850              : 
    1851              :             ! free colsrows active objects
    1852            0 :             call xgTransposer_free(X_part%transposer_active)
    1853            0 :             call xgTransposer_free(AX_part%transposer_active)
    1854            0 :             call xgTransposer_free(BX_part%transposer_active)
    1855              :         end if
    1856              : 
    1857            0 :         n_locked_prev = n_locked
    1858            0 :         mpiInfo%n_locked = n_locked
    1859            0 :         mpiInfo%n_active = chebfi%neigenpairs - n_locked
    1860              : 
    1861              :         ! todo debug by recomputing the getSubspaceResidual for locked vectors and verify it is smaller than tol
    1862              : 
    1863              :     end do
    1864              : 
    1865              :     ! Transfer active data to full workspace
    1866            0 :     call xgBlock_copy(X_part%linalg_active, chebfi%X)
    1867            0 :     call xgBlock_copy(AX_part%linalg_active, chebfi%BX%self)
    1868            0 :     call xgBlock_copy(BX_part%linalg_active, chebfi%BX%self)
    1869              : 
    1870              :     ! Apply Rayleigh-Ritz to active MPI Linalg row-block
    1871              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_RR)
    1872              :     call xg_RayleighRitz(chebfi%X,chebfi%AX%self,chebfi%BX%self,eigen,ierr,0,tim_RR,&
    1873            0 :         chebfi%gpu_option,solve_ax_bx=.true.)
    1874              :     ABI_NVTX_END_RANGE()
    1875              : 
    1876              :     !write(std_out,*) 'id of X, (after RR) ncols=', xgBlock_getId(chebfi%X), cols(chebfi%X)
    1877              : 
    1878            0 :     if ( ierr /= 0 ) then
    1879            0 :         ABI_WARNING("RayleighRitz did not work")
    1880              :     end if
    1881              : 
    1882              :     ! Compute residual norm *squared*
    1883            0 :     if (chebfi%paw) then
    1884            0 :         call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%BX%self,chebfi%AX%self)
    1885              :     else
    1886            0 :         call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%X,chebfi%AX%self)
    1887              :     end if
    1888            0 :     call xgBlock_colwiseNorm2(chebfi%AX%self,residu) ! performs MPI comm
    1889              : 
    1890              :     ! MPI Transpose to recover colsrows state
    1891            0 :     call timab(tim_transpose,1,tsec)
    1892              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    1893            0 :     if (chebfi%paral_kgb == 1) then
    1894            0 :         call xmpi_barrier(chebfi%spacecom)
    1895            0 :         call xgTransposer_transpose(chebfi%xgTransposerX, STATE_COLSROWS)
    1896            0 :         call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_COLSROWS)
    1897            0 :         call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_COLSROWS)
    1898            0 :         if (xmpi_comm_size(chebfi%spacecom) == 1) then
    1899            0 :             call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)
    1900            0 :             call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)
    1901            0 :             call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
    1902              :         end if
    1903              :     else
    1904            0 :         call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)
    1905            0 :         call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)
    1906            0 :         call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
    1907              :     end if
    1908              :     ABI_NVTX_END_RANGE()
    1909            0 :     call timab(tim_transpose,2,tsec)
    1910              : 
    1911              :     ! Copy in ColsRows representation
    1912            0 :     call xgBlock_copy(chebfi%xXColsRows, X0)
    1913              : 
    1914            0 :     if (cols(X0) /= chebfi%bandpp) then
    1915            0 :         ABI_ERROR('wrong colsrows representation')
    1916              :     end if
    1917            0 :     write(std_out,'(a,i6,i6,i6)') 'local # proc has # rows cols ', xmpi_comm_rank(chebfi%spacecom), rows(X0), cols(X0)
    1918              : 
    1919              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
    1920              :     if (chebfi%gpu_option==ABI_GPU_KOKKOS) then
    1921              :         call gpu_device_synchronize()
    1922              :     end if
    1923              : #endif
    1924              : 
    1925              :     ! Free transposer objects
    1926            0 :     if (chebfi%paral_kgb == 1) then
    1927            0 :         call xgTransposer_free(chebfi%xgTransposerX)
    1928            0 :         call xgTransposer_free(chebfi%xgTransposerAX)
    1929            0 :         call xgTransposer_free(chebfi%xgTransposerBX)
    1930              :     end if
    1931              : 
    1932              :     ! Free temporary memory
    1933            0 :     ABI_SFREE(nrowsLinalg)
    1934            0 :     call xg_free(resid_active)
    1935              : 
    1936            0 : end subroutine chebfi_runSubspaceIteration
    1937              : !!***
    1938              : 
    1939              : !----------------------------------------------------------------------
    1940              : 
    1941              : !!****f* m_chebfi/chebfi_runSubspaceIterationDummy
    1942              : !! NAME
    1943              : !! chebfi_runSubspaceIterationDummy
    1944              : !!
    1945              : !! FUNCTION
    1946              : !! Applies subspace iteration by Chebyshev polynomial filtering on slice
    1947              : !! then extracts eigenvectors using Rayleigh-Ritz. This execution is completely
    1948              : !! local on slice processors. Each slice does not see others.
    1949              : !!
    1950              : !! NOTES
    1951              : !! Restart logic in subspace iteration:
    1952              : !!   Allocate constructor (state=colsrows)
    1953              : !!   while (convergence not reached):
    1954              : !!    |  if (state=linalg) Transpose
    1955              : !!    |  Filter
    1956              : !!    |  Transpose (state=linalg)
    1957              : !!    |  Orthogonalize
    1958              : !!   Rayleigh-Ritz
    1959              : !!
    1960              : !! INPUTS
    1961              : !! X0 input vectors distibuted by colsrows along slice processors
    1962              : !!
    1963              : !! OUTPUTS
    1964              : !! X0 (in-place) converged vectors distributed by linalg along slice processors
    1965              : !!
    1966              : !! dev=============
    1967              : !! - version 1: count number of converged vectors within iteration
    1968              : !!
    1969              : !! SOURCE
    1970              : 
    1971            0 : subroutine chebfi_runSubspaceIterationDummy(chebfi,X0,getAX_BX,getBm1X,eigen,residu,nspinor,&
    1972              :         mineig_global,maxeig_global,lambda_minus,lambda_plus,is_lowpass,k_rank,nrows_blockrows)
    1973              : 
    1974              :     implicit none
    1975              : 
    1976              :     !Arguments ------------------------------------
    1977              :     type(chebfi_t) , intent(inout) :: chebfi
    1978              :     type(xgBlock_t), intent(inout) :: X0
    1979              :     type(xgBlock_t), intent(inout) :: eigen
    1980              :     type(xgBlock_t), intent(inout) :: residu
    1981              :     integer        , intent(in   ) :: nspinor
    1982              :     integer        , intent(in   ) :: k_rank
    1983              :     integer, pointer, intent(in  ) :: nrows_blockrows(:)
    1984              :     real(dp)       , intent(in   ) :: mineig_global
    1985              :     real(dp)       , intent(in   ) :: maxeig_global
    1986              :     real(dp)       , intent(in   ) :: lambda_minus
    1987              :     real(dp)       , intent(in   ) :: lambda_plus
    1988              :     logical        , intent(in   ) :: is_lowpass
    1989              :     interface
    1990              :         subroutine getAX_BX(X,AX,BX)
    1991              :             use m_xg, only : xgBlock_t
    1992              :             type(xgBlock_t), intent(inout) :: X
    1993              :             type(xgBlock_t), intent(inout) :: AX
    1994              :             type(xgBlock_t), intent(inout) :: BX
    1995              :         end subroutine getAX_BX
    1996              :     end interface
    1997              :     interface
    1998              :         subroutine getBm1X(X,Bm1X)
    1999              :             use m_xg, only : xgBlock_t
    2000              :             type(xgBlock_t), intent(inout) :: X
    2001              :             type(xgBlock_t), intent(inout) :: Bm1X
    2002              :         end subroutine getBm1X
    2003              :     end interface
    2004              : 
    2005              :     !Local variables-------------------------------
    2006              :     integer :: iter_subspace, niter_subspace_max, n_locked, n_active, n_locked_prev
    2007              :     integer :: spacedim, neigenpairs, num_proc, nrows, ierr
    2008              :     !type(xg_t) :: X_k
    2009              :     type(xg_t) :: resid_active
    2010              :     type(xg_t) :: X_locked, AX_locked, BX_locked ! spaces needed for deflation in linalg distr
    2011              :     type(xgBlock_t) :: chebfi_X_locked, chebfi_AX_locked, chebfi_BX_locked ! pointers used for copy
    2012              :     type(xgBlock_t) :: X_active, AX_active, BX_active
    2013              :     ! Arrays
    2014            0 :     integer, target, allocatable :: nrowsLinalg(:)
    2015              :     integer, pointer :: nrowsLinalg_ptr(:) => null()
    2016              :     real(dp) :: tsec(2)
    2017              : 
    2018              :     ! *********************************************************************
    2019              : 
    2020            0 :     if (chebfi%from_linalg) then
    2021            0 :         ABI_ERROR("chebfi should be from colsrows")
    2022              :     end if
    2023              : 
    2024            0 :     spacedim = chebfi%spacedim
    2025            0 :     neigenpairs = chebfi%neigenpairs
    2026            0 :     num_proc = xmpi_comm_size(chebfi%spacecom)
    2027            0 :     chebfi%eigenvalues = eigen
    2028              : 
    2029            0 :     ABI_MALLOC_IFNOT(nrowsLinalg,(num_proc))
    2030            0 :     nrowsLinalg_ptr => nrowsLinalg
    2031            0 :     nrowsLinalg = nrows_blockrows
    2032              : 
    2033            0 :     call xg_init(resid_active, SPACE_R, neigenpairs, 1, gpu_option=chebfi%gpu_option)
    2034              : 
    2035            0 :     write(std_out,*) 'wanted rank=', k_rank
    2036              : 
    2037              :     !write(std_out,*) 'getid inside runSlice xXColsRows', xgBlock_getId(chebfi%xXColsRows)
    2038              :     !write(std_out,*) 'getid inside runSlice xAXColsRows', xgBlock_getId(chebfi%xAXColsRows)
    2039              :     !flush(std_out)
    2040              : 
    2041              :     ! Initialize values of AX and BX
    2042            0 :     call timab(tim_getAX_BX,1,tsec)
    2043              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    2044            0 :     call getAX_BX(chebfi%xXColsRows, chebfi%xAXColsRows, chebfi%xBXColsRows)
    2045            0 :     call xgBlock_zero_im_g0(chebfi%xAXColsRows)
    2046            0 :     call xgBlock_zero_im_g0(chebfi%xBXColsRows)
    2047              :     ABI_NVTX_END_RANGE()
    2048            0 :     call timab(tim_getAX_BX,2,tsec)
    2049              : 
    2050              :     ! Allocate memory for linalg distribution
    2051            0 :     call timab(tim_transpose,1,tsec)
    2052              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    2053            0 :     if (chebfi%paral_kgb==1) then
    2054              : 
    2055              :         ! Allocate chebfi%X
    2056              :         call xgTransposer_constructor(chebfi%xgTransposerX,chebfi%X,chebfi%xXColsRows,nspinor,&
    2057              :             STATE_COLSROWS,TRANS_ALL2ALL,chebfi%comm_rows,chebfi%comm_cols,0,0,chebfi%me_g0,&
    2058              :             gpu_option=chebfi%gpu_option,gpu_thread_limit=chebfi%gpu_thread_limit,&
    2059            0 :             custom_ncolsColsRows=.true.,nrowsLinalg_sub=nrowsLinalg_ptr)
    2060              :         ! Note: bandpp is custom because it is created from resource allocator
    2061              : 
    2062              :         ! Allocate chebfi%AX, chebfi%BX
    2063              :         call xgTransposer_copyConstructor(chebfi%xgTransposerAX,chebfi%xgTransposerX,&
    2064            0 :             chebfi%AX%self,chebfi%xAXColsRows,STATE_COLSROWS)
    2065              :         call xgTransposer_copyConstructor(chebfi%xgTransposerBX,chebfi%xgTransposerX,&
    2066            0 :             chebfi%BX%self,chebfi%xBXColsRows,STATE_COLSROWS)
    2067              :         ! Note: at this point chebfi%AX and chebfi%BX are empty. Must transpose
    2068              :         !       to fill with correct values.
    2069              : 
    2070              :         ! todo use copy constructor to create an object by copying an existing object
    2071              :         ! actually copy constructor *allocates* memory for chebfi%AX. Write a version
    2072              :         ! that does not allocate memory and only reassigns pointers. Can pointers be reassigned
    2073              :         ! directly then used in the global constructor? Perform tests.
    2074              : 
    2075            0 :         chebfi%xgTransposerX%gpu_kokkos_nthrd  = chebfi%gpu_kokkos_nthrd
    2076            0 :         chebfi%xgTransposerAX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
    2077            0 :         chebfi%xgTransposerBX%gpu_kokkos_nthrd = chebfi%gpu_kokkos_nthrd
    2078              : 
    2079              :     else
    2080            0 :         call xgBlock_setBlock(chebfi%xXColsRows, chebfi%X, spacedim, neigenpairs)
    2081            0 :         call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
    2082            0 :         call xgBlock_setBlock(chebfi%xBXColsRows, chebfi%BX%self, spacedim, neigenpairs)
    2083              :     end if
    2084            0 :     call timab(tim_transpose,2,tsec)
    2085              :     ABI_NVTX_END_RANGE()
    2086              : 
    2087            0 :     write(std_out,*) '@dummy starting filter in proc', xmpi_comm_rank(chebfi%spacecom)
    2088            0 :     flush(std_out)
    2089              : 
    2090            0 :     niter_subspace_max = 5
    2091            0 :     n_locked = 0
    2092            0 :     n_locked_prev = 0
    2093              : 
    2094              :     ! chebfi%X    contains active vectors
    2095              :     ! X_lock      contains locked vectors
    2096              : 
    2097              :     !xX_active = chebfi%xXColsRows
    2098              :     !xAX_active = chebfi%xAXColsRows
    2099              :     !xBX_active = chebfi%xBXColsRows
    2100              : 
    2101            0 :     do iter_subspace=1, niter_subspace_max
    2102              : 
    2103            0 :         write(std_out,*) 'subspace iteration no=', iter_subspace
    2104            0 :         flush(std_out)
    2105              : 
    2106            0 :         if (iter_subspace>1 .and. chebfi%paral_kgb==1) then
    2107              : 
    2108            0 :             call timab(tim_transpose,1,tsec)
    2109              :             ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    2110            0 :             call xgTransposer_transpose(chebfi%xgTransposerX, STATE_COLSROWS)
    2111            0 :             call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_COLSROWS)
    2112            0 :             call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_COLSROWS)
    2113            0 :             call timab(tim_transpose,2,tsec)
    2114              :             ABI_NVTX_END_RANGE()
    2115              : 
    2116              :             !if (n_locked>1) then
    2117              :             !    ! n_locked_mpi each rank has different number of locked vectors todo (find this in v2)
    2118              :             !    call xgBlock_setBlock(chebfi%xXColsRows , xX_active , spacedim, n_locked_mpi)
    2119              :             !    call xgBlock_setBlock(chebfi%xAXColsRows, xAX_active, spacedim, n_locked_mpi)
    2120              :             !    call xgBlock_setBlock(chebfi%xBXColsRows, xBX_active, spacedim, n_locked_mpi)
    2121              :             !end if
    2122              :         end if
    2123              :         ! todo this will transform the active+locked in colsrows. Locked is not necessary
    2124              :         ! therefore try to communicate less data is possible.
    2125              : 
    2126              :         ! ############################ Filter active  ##############################
    2127              :         ! ############################ column vectors ##############################
    2128            0 :         if (is_lowpass) then
    2129            0 :             call chebfi_lowpassFilter(chebfi,eigen,lambda_minus,lambda_plus,getAX_BX,getBm1X)
    2130              :         else
    2131              :             call chebfi_bandpassFilter(chebfi,lambda_minus,lambda_plus,mineig_global,&
    2132            0 :                 maxeig_global,getAX_BX,getBm1X)
    2133              :         end if
    2134              : 
    2135            0 :         write(std_out,'(a,i6,i6)') 'chebfi%xXColsRows # rows # cols ', &
    2136            0 :             rows(chebfi%xXColsRows), cols(chebfi%xXColsRows)
    2137            0 :         flush(std_out)
    2138              : 
    2139            0 :         if (chebfi%paral_kgb==1) then
    2140            0 :             call timab(tim_transpose,1,tsec)
    2141              :             ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    2142            0 :             call xgTransposer_transpose(chebfi%xgTransposerX, STATE_LINALG)
    2143            0 :             call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_LINALG)
    2144            0 :             call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_LINALG)
    2145            0 :             call timab(tim_transpose,2,tsec)
    2146              :             ABI_NVTX_END_RANGE()
    2147              :         end if
    2148              : 
    2149            0 :         if (n_locked > 0) then
    2150              :             ! undo the effect of filtering in locked vectors
    2151            0 :             call xgBlock_setBlock(chebfi%X, chebfi_X_locked, nrows, n_locked)
    2152            0 :             call xgBlock_setBlock(chebfi%AX%self, chebfi_AX_locked, nrows, n_locked)
    2153            0 :             call xgBlock_setBlock(chebfi%BX%self, chebfi_BX_locked, nrows, n_locked)
    2154            0 :             call xgBlock_copy(X_locked%self, chebfi_X_locked)
    2155            0 :             call xgBlock_copy(AX_locked%self, chebfi_AX_locked)
    2156            0 :             call xgBlock_copy(BX_locked%self, chebfi_BX_locked)
    2157              :         end if
    2158              : 
    2159            0 :         write(std_out,'(a,i6,i6)') 'chebfi%X # rows # cols ', rows(chebfi%X), cols(chebfi%X)
    2160            0 :         write(std_out,*) xgBlock_getid(chebfi%X)
    2161            0 :         flush(std_out)
    2162              : 
    2163              :         ! recover active vectors in linalg
    2164            0 :         n_active = chebfi%neigenpairs - n_locked
    2165            0 :         nrows = rows(chebfi%X)
    2166              : 
    2167            0 :         write(std_out,*) 'n_active=', n_active; flush(std_out)
    2168            0 :         call xgBlock_setBlock(chebfi%X, X_active, nrows, n_active, fcol=n_locked+1)
    2169            0 :         call xgBlock_setBlock(chebfi%AX%self, AX_active, nrows, n_active, fcol=n_locked+1)
    2170            0 :         call xgBlock_setBlock(chebfi%BX%self, BX_active, nrows, n_active, fcol=n_locked+1)
    2171              : 
    2172            0 :         write(std_out,*) 'start deflation'
    2173            0 :         write(std_out,*) xgBlock_getid(chebfi%X), comm(chebfi%X), me_g0(chebfi%X), cols(chebfi%X), space(chebfi%X)
    2174            0 :         write(std_out,*) xgBlock_getid(X_active), comm(X_active), me_g0(X_active), cols(X_active), space(X_active)
    2175            0 :         flush(std_out)
    2176              : 
    2177            0 :         if (n_locked>0) then
    2178            0 :             call chebfi_deflateWrtLocked(chebfi, n_locked, X_locked%self, BX_locked%self)
    2179              :             !call chebfi_deflateActiveWrtLocked(chebfi, n_locked, X_part, AX_part, BX_part)
    2180              :         end if
    2181              : 
    2182            0 :         write(std_out,*) 'exit deflation'; flush(std_out)
    2183            0 :         write(std_out,*) 'start ortho'; flush(std_out)
    2184              : 
    2185            0 :         write(std_out,*) 'cols=', cols(chebfi%X); flush(std_out)
    2186              : 
    2187            0 :         call xg_Borthonormalize(X_active,BX_active,ierr,1,chebfi%gpu_option,AX=AX_active)
    2188              :         !call xg_Borthonormalize(chebfi%X,chebfi%BX%self,ierr,1,chebfi%gpu_option,AX=chebfi%AX%self)
    2189              : 
    2190            0 :         write(std_out,*) 'exit ortho'; flush(std_out)
    2191            0 :         write(std_out,*) 'start residual'; flush(std_out)
    2192              : 
    2193            0 :         call chebfi_getSubspaceResidual(chebfi, resid_active%self)
    2194              : 
    2195              :         ! prevent errors in pointer corruption to non-contiguous memory
    2196            0 :         call xgBlock_setBlock(chebfi%X, X_active, nrows, 1)
    2197            0 :         call xgBlock_setBlock(chebfi%AX%self, AX_active, nrows, 1)
    2198            0 :         call xgBlock_setBlock(chebfi%BX%self, BX_active, nrows, 1)
    2199            0 :         call xgBlock_setBlock(chebfi%X, chebfi_X_locked, nrows, 1)
    2200            0 :         call xgBlock_setBlock(chebfi%BX%self, chebfi_BX_locked, nrows, 1)
    2201              : 
    2202            0 :         call chebfi_swapConvergedVectors(chebfi, resid_active%self, 1e-3_dp, n_locked)
    2203              : 
    2204            0 :         if (n_locked>0) then
    2205            0 :             if (n_locked /= n_locked_prev) then
    2206              : 
    2207            0 :                 if (n_locked_prev>0) then
    2208            0 :                     call xg_free(X_locked)
    2209            0 :                     call xg_free(AX_locked)
    2210            0 :                     call xg_free(BX_locked)
    2211              :                 end if
    2212              : 
    2213              :                 ! Allocate locked vectors in linalg representation
    2214              :                 call xg_init(X_locked, chebfi%space, nrows, n_locked, &
    2215            0 :                     chebfi%spacecom, me_g0=chebfi%me_g0, gpu_option=chebfi%gpu_option)
    2216              : 
    2217              :                 ! same for AX
    2218              :                 call xg_init(AX_locked, chebfi%space, nrows, n_locked, &
    2219            0 :                     chebfi%spacecom, me_g0=chebfi%me_g0, gpu_option=chebfi%gpu_option)
    2220              : 
    2221              :                 ! same for BX
    2222              :                 call xg_init(BX_locked, chebfi%space, nrows, n_locked, &
    2223            0 :                     chebfi%spacecom, me_g0=chebfi%me_g0, gpu_option=chebfi%gpu_option)
    2224              :             end if
    2225              : 
    2226            0 :             call xgBlock_setBlock(chebfi%X, chebfi_X_locked, nrows, n_locked)
    2227            0 :             call xgBlock_copy(chebfi_X_locked, X_locked%self)
    2228              : 
    2229            0 :             call xgBlock_setBlock(chebfi%AX%self, chebfi_AX_locked, nrows, n_locked)
    2230            0 :             call xgBlock_copy(chebfi_AX_locked, AX_locked%self)
    2231              : 
    2232            0 :             call xgBlock_setBlock(chebfi%BX%self, chebfi_BX_locked, nrows, n_locked)
    2233            0 :             call xgBlock_copy(chebfi_BX_locked, BX_locked%self)
    2234              :         end if
    2235              : 
    2236              :         ! todo debug by recomputing the getSubspaceResidual for locked vectors and verify it is smaller than tol
    2237              : 
    2238              :         ! lock vectors in small residual
    2239              :         ! actually redefine pointers Xactive and Xlock pointing to X that's all
    2240              : 
    2241            0 :         n_locked_prev = n_locked
    2242              : 
    2243              :     end do
    2244              : 
    2245            0 :     call xg_free(X_locked)
    2246            0 :     call xg_free(AX_locked)
    2247            0 :     call xg_free(BX_locked)
    2248              : 
    2249              :     ! Apply Rayleigh-Ritz to active MPI Linalg row-block
    2250              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_RR)
    2251              :     call xg_RayleighRitz(chebfi%X,chebfi%AX%self,chebfi%BX%self,eigen,ierr,0,tim_RR,&
    2252            0 :         chebfi%gpu_option,solve_ax_bx=.true.)
    2253              :     ABI_NVTX_END_RANGE()
    2254              : 
    2255              :     !write(std_out,*) 'id of X, (after RR) ncols=', xgBlock_getId(chebfi%X), cols(chebfi%X)
    2256              : 
    2257            0 :     if ( ierr /= 0 ) then
    2258            0 :         ABI_WARNING("RayleighRitz did not work")
    2259              :     else
    2260              :         !write(std_out,*) 'is lowpass=', is_lowpass
    2261              :         !write(std_out,*) 'chebfi%eigenvalues after RR'
    2262              :         !call xgBlock_print(chebfi%eigenvalues,std_out)
    2263              :         !flush(std_out)
    2264              :     end if
    2265              : 
    2266              :     ! Compute residual norm *squared*
    2267            0 :     if (chebfi%paw) then
    2268            0 :         call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%BX%self,chebfi%AX%self)
    2269              :     else
    2270            0 :         call xgBlock_colwiseCymax(chebfi%AX%self,chebfi%eigenvalues,chebfi%X,chebfi%AX%self)
    2271              :     end if
    2272            0 :     call xgBlock_colwiseNorm2(chebfi%AX%self,residu) ! performs MPI comm
    2273              : 
    2274              :     !write(std_out,*) 'max colwise residual norm squared='; call xgBlock_print(residu, std_out)
    2275              :     !flush(std_out)
    2276              : 
    2277              :     ! Copy in Linalg representation (see chebfi_run, kept for reference)
    2278              :     ! call xgBlock_copy(chebfi%X,X0)
    2279              : 
    2280              :     ! MPI Transpose to recover colsrows state (X only)
    2281            0 :     call timab(tim_transpose,1,tsec)
    2282              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    2283            0 :     if (chebfi%paral_kgb == 1) then
    2284            0 :         call xmpi_barrier(chebfi%spacecom)
    2285            0 :         call xgTransposer_transpose(chebfi%xgTransposerX, STATE_COLSROWS)
    2286            0 :         call xgTransposer_transpose(chebfi%xgTransposerAX, STATE_COLSROWS)
    2287            0 :         call xgTransposer_transpose(chebfi%xgTransposerBX, STATE_COLSROWS)
    2288            0 :         if (xmpi_comm_size(chebfi%spacecom) == 1) then
    2289            0 :             call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)
    2290            0 :             call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)
    2291            0 :             call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
    2292              :         end if
    2293              :     else
    2294            0 :         call xgBlock_setBlock(chebfi%X, chebfi%xXColsRows, spacedim, neigenpairs)
    2295            0 :         call xgBlock_setBlock(chebfi%AX%self, chebfi%xAXColsRows, spacedim, neigenpairs)
    2296            0 :         call xgBlock_setBlock(chebfi%BX%self, chebfi%xBXColsRows, spacedim, neigenpairs)
    2297              :     end if
    2298              :     ABI_NVTX_END_RANGE()
    2299            0 :     call timab(tim_transpose,2,tsec)
    2300              : 
    2301              :     ! Copy in ColsRows representation
    2302            0 :     call xgBlock_copy(chebfi%xXColsRows, X0)
    2303              : 
    2304            0 :     if (cols(X0) /= chebfi%bandpp) then
    2305            0 :         ABI_ERROR('wrong colsrows representation')
    2306              :     end if
    2307            0 :     write(std_out,'(a,i6,i6,i6)') 'local # proc has # rows cols ', xmpi_comm_rank(chebfi%spacecom), rows(X0), cols(X0)
    2308              : 
    2309              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
    2310              :     if (chebfi%gpu_option==ABI_GPU_KOKKOS) then
    2311              :         call gpu_device_synchronize()
    2312              :     end if
    2313              : #endif
    2314              : 
    2315              :     ! Free transposer objects
    2316            0 :     if (chebfi%paral_kgb == 1) then
    2317            0 :         call xgTransposer_free(chebfi%xgTransposerX)
    2318            0 :         call xgTransposer_free(chebfi%xgTransposerAX)
    2319            0 :         call xgTransposer_free(chebfi%xgTransposerBX)
    2320              :     end if
    2321              : 
    2322              :     ! Free temporary memory
    2323            0 :     ABI_SFREE(nrowsLinalg)
    2324            0 :     call xg_free(resid_active)
    2325              : 
    2326            0 : end subroutine chebfi_runSubspaceIterationDummy
    2327              : !!***
    2328              : 
    2329              : !----------------------------------------------------------------------
    2330              : 
    2331              : !!****f* m_chebfi/chebfi_lowpassFilter
    2332              : !! NAME
    2333              : !! chebfi_lowpassFilter
    2334              : !!
    2335              : !! FUNCTION
    2336              : !! Apply Lowpass filter using Chebyshev polynomial on a set of vectors.
    2337              : !! Amplifies interval [-oo, lambda_minus) and diminishes [lambda_minus,lambda_plus).
    2338              : !!
    2339              : !! INPUTS
    2340              : !! chebfi <type(chebfi_t)>=memory workspace used to apply filter
    2341              : !! eigen= Rayleigh quotients to use in amplification of chebfi%xXColsRows
    2342              : !! lambda_minus= lower bound of interval to diminish
    2343              : !! lambda_plus= upper bound of interval to diminish
    2344              : !! getAX_BX= pointer to the function giving A|X> and B|X>
    2345              : !!           A is typically the Hamiltonian H, and B the overlap operator S
    2346              : !! getBm1X= pointer to the function giving B^-1|X>
    2347              : !!          B is typically the overlap operator S
    2348              : !!
    2349              : !! SIDE EFFECTS
    2350              : !!  chebfi%xXColsRows= Filtered vectors to use in Subspace iteration
    2351              : !!
    2352              : !! SOURCE
    2353              : 
    2354            0 : subroutine chebfi_lowpassFilter(chebfi,eigen,lambda_minus,lambda_plus,getAX_BX,getBm1X)
    2355              : 
    2356              :     implicit none
    2357              : 
    2358              :     ! Arguments ------------------------------------
    2359              :     type(chebfi_t), intent(inout) :: chebfi
    2360              :     type(xgBlock_t), intent(inout) :: eigen
    2361              :     real(dp), intent(in) :: lambda_minus
    2362              :     real(dp), intent(in) :: lambda_plus
    2363              :     interface
    2364              :         subroutine getAX_BX(X,AX,BX)
    2365              :             use m_xg, only : xgBlock_t
    2366              :             type(xgBlock_t), intent(inout) :: X
    2367              :             type(xgBlock_t), intent(inout) :: AX
    2368              :             type(xgBlock_t), intent(inout) :: BX
    2369              :         end subroutine getAX_BX
    2370              :     end interface
    2371              :     interface
    2372              :         subroutine getBm1X(X,Bm1X)
    2373              :             use m_xg, only : xgBlock_t
    2374              :             type(xgBlock_t), intent(inout) :: X
    2375              :             type(xgBlock_t), intent(inout) :: Bm1X
    2376              :         end subroutine getBm1X
    2377              :     end interface
    2378              : 
    2379              :     !Local variables-------------------------------
    2380              :     integer :: ideg
    2381              :     real(dp) :: center, radius, one_over_r, two_over_r
    2382              :     type(xg_t) :: DivResults ! Rayleigh quotients
    2383              :     ! Arrays
    2384              :     real(dp) :: tsec(2)
    2385            0 :     integer, allocatable :: ndeg_filter_bands(:)
    2386              : 
    2387              :     ! *********************************************************************
    2388              : 
    2389            0 :     if (chebfi%paral_kgb == 0) then
    2390            0 :         ABI_MALLOC_IFNOT(ndeg_filter_bands,(chebfi%neigenpairs))
    2391              :     else
    2392            0 :         ABI_MALLOC_IFNOT(ndeg_filter_bands,(chebfi%bandpp))
    2393              :     end if
    2394              : 
    2395              :     ! [lambda_minus,lambda_plus) is diminished using Chebyshev
    2396            0 :     write(std_out,*) '@lowpass lambda_minus=', lambda_minus
    2397            0 :     write(std_out,*) '@lowpass lambda_plus=', lambda_plus
    2398            0 :     flush(std_out)
    2399              : 
    2400              :     ! Filter parameters
    2401            0 :     ndeg_filter_bands(:) = chebfi%ndeg_filter
    2402            0 :     center = (lambda_plus + lambda_minus)*0.5
    2403            0 :     radius = (lambda_plus - lambda_minus)*0.5
    2404            0 :     one_over_r = 1/radius
    2405            0 :     two_over_r = 2/radius
    2406              : 
    2407              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_CORE)
    2408            0 :     do ideg = 0, chebfi%ndeg_filter - 1
    2409              : 
    2410              :         ! X_next=2/r*(AX_next-c*X_next)-X_prev
    2411              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_NEXT_ORDER)
    2412            0 :         call chebfi_computeNextOrderChebfiPolynom(chebfi, ideg, center, one_over_r, two_over_r, getBm1X)
    2413              :         ABI_NVTX_END_RANGE()
    2414              : 
    2415              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_SWAP_BUF)
    2416            0 :         if (chebfi%paral_kgb == 0) then
    2417            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%spacedim, chebfi%neigenpairs)
    2418              :         else
    2419            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, chebfi%bandpp)
    2420              :         end if
    2421              :         ABI_NVTX_END_RANGE()
    2422              : 
    2423              :         !A * Psi (=AX_next=A*X_next)
    2424            0 :         call timab(tim_getAX_BX,1,tsec)
    2425              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    2426            0 :         call getAX_BX(chebfi%xXColsRows, chebfi%xAXColsRows, chebfi%xBXColsRows)
    2427            0 :         call xgBlock_zero_im_g0(chebfi%xAXColsRows)
    2428            0 :         call xgBlock_zero_im_g0(chebfi%xBXColsRows)
    2429              :         ABI_NVTX_END_RANGE()
    2430            0 :         call timab(tim_getAX_BX,2,tsec)
    2431              : 
    2432              :     end do ! ideg
    2433              :     ABI_NVTX_END_RANGE()
    2434              : 
    2435              :     ! Avoid overflow rescale
    2436            0 :     call chebfi_prepAmpfactor(chebfi, eigen, DivResults)
    2437            0 :     call chebfi_ampfactor(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
    2438              : 
    2439              :     ! Free temporary memory
    2440            0 :     call xg_free(DivResults)
    2441            0 :     ABI_SFREE(ndeg_filter_bands)
    2442              : 
    2443            0 : end subroutine chebfi_lowpassFilter
    2444              : !!***
    2445              : 
    2446              : !----------------------------------------------------------------------
    2447              : 
    2448              : !!****f* m_chebfi/chebfi_lowpassFilterActive
    2449              : !! NAME
    2450              : !! chebfi_lowpassFilterActive
    2451              : !!
    2452              : !! FUNCTION
    2453              : !! Apply Lowpass filter on Active vectors only
    2454              : !! TODO this function will replace lowpassFilter
    2455              : !!
    2456              : !! SOURCE
    2457              : 
    2458            0 : subroutine chebfi_lowpassFilterActive(chebfi,X_active,AX_active,BX_active,eigen,&
    2459              :         lambda_minus,lambda_plus,getAX_BX,getBm1X)
    2460              : 
    2461              :     implicit none
    2462              : 
    2463              :     ! Arguments ------------------------------------
    2464              :     type(chebfi_t), intent(inout) :: chebfi
    2465              :     type(xgBlock_t), intent(inout) :: X_active
    2466              :     type(xgBlock_t), intent(inout) :: AX_active
    2467              :     type(xgBlock_t), intent(inout) :: BX_active
    2468              :     type(xgBlock_t), intent(inout) :: eigen
    2469              :     real(dp), intent(in) :: lambda_minus
    2470              :     real(dp), intent(in) :: lambda_plus
    2471              :     interface
    2472              :         subroutine getAX_BX(X,AX,BX)
    2473              :             use m_xg, only : xgBlock_t
    2474              :             type(xgBlock_t), intent(inout) :: X
    2475              :             type(xgBlock_t), intent(inout) :: AX
    2476              :             type(xgBlock_t), intent(inout) :: BX
    2477              :         end subroutine getAX_BX
    2478              :     end interface
    2479              :     interface
    2480              :         subroutine getBm1X(X,Bm1X)
    2481              :             use m_xg, only : xgBlock_t
    2482              :             type(xgBlock_t), intent(inout) :: X
    2483              :             type(xgBlock_t), intent(inout) :: Bm1X
    2484              :         end subroutine getBm1X
    2485              :     end interface
    2486              : 
    2487              :     !Local variables-------------------------------
    2488              :     integer :: ideg
    2489              :     real(dp) :: center, radius, one_over_r, two_over_r
    2490              :     type(xg_t) :: DivResults ! Rayleigh quotients
    2491              :     ! Arrays
    2492              :     real(dp) :: tsec(2)
    2493            0 :     integer, allocatable :: ndeg_filter_bands(:)
    2494              : 
    2495              :     ! *********************************************************************
    2496              : 
    2497            0 :     if (chebfi%paral_kgb == 0) then
    2498            0 :         ABI_MALLOC_IFNOT(ndeg_filter_bands,(chebfi%neigenpairs))
    2499              :     else
    2500            0 :         ABI_MALLOC_IFNOT(ndeg_filter_bands,(chebfi%bandpp))
    2501              :     end if
    2502              : 
    2503              :     ! [lambda_minus,lambda_plus) is diminished using Chebyshev
    2504            0 :     write(std_out,*) '@lowpass lambda_minus=', lambda_minus
    2505            0 :     write(std_out,*) '@lowpass lambda_plus=', lambda_plus
    2506            0 :     flush(std_out)
    2507              : 
    2508              :     ! Filter parameters
    2509            0 :     ndeg_filter_bands(:) = chebfi%ndeg_filter
    2510            0 :     center = (lambda_plus + lambda_minus)*0.5
    2511            0 :     radius = (lambda_plus - lambda_minus)*0.5
    2512            0 :     one_over_r = 1/radius
    2513            0 :     two_over_r = 2/radius
    2514              : 
    2515              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_CORE)
    2516            0 :     do ideg = 0, chebfi%ndeg_filter - 1
    2517              : 
    2518              :         ! X_next=2/r*(AX_next-c*X_next)-X_prev
    2519              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_NEXT_ORDER)
    2520            0 :         call chebfi_computeNextOrderChebfiPolynom(chebfi, ideg, center, one_over_r, two_over_r, getBm1X)
    2521              :         ABI_NVTX_END_RANGE()
    2522              : 
    2523              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_SWAP_BUF)
    2524            0 :         if (chebfi%paral_kgb == 0) then
    2525            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%spacedim, chebfi%neigenpairs)
    2526              :         else
    2527            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, chebfi%bandpp)
    2528              :         end if
    2529              :         ABI_NVTX_END_RANGE()
    2530              : 
    2531              :         !A * Psi (=AX_next=A*X_next)
    2532            0 :         call timab(tim_getAX_BX,1,tsec)
    2533              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    2534            0 :         call getAX_BX(X_active, AX_active, BX_active)
    2535            0 :         call xgBlock_zero_im_g0(AX_active)
    2536            0 :         call xgBlock_zero_im_g0(BX_active)
    2537              :         ABI_NVTX_END_RANGE()
    2538            0 :         call timab(tim_getAX_BX,2,tsec)
    2539              : 
    2540              :     end do ! ideg
    2541              :     ABI_NVTX_END_RANGE()
    2542              : 
    2543              :     ! Avoid overflow rescale
    2544            0 :     call chebfi_prepAmpfactor(chebfi, eigen, DivResults)
    2545            0 :     call chebfi_ampfactor(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
    2546              : 
    2547              :     ! Free temporary memory
    2548            0 :     call xg_free(DivResults)
    2549            0 :     ABI_SFREE(ndeg_filter_bands)
    2550              : 
    2551            0 : end subroutine chebfi_lowpassFilterActive
    2552              : !!***
    2553              : 
    2554              : !----------------------------------------------------------------------
    2555              : 
    2556              : !!****f* m_chebfi/chebfi_bandpassFilter
    2557              : !! NAME
    2558              : !! chebfi_bandpassFilter
    2559              : !!
    2560              : !! FUNCTION
    2561              : !! Apply Bandpass filter using Chebyshev-Jackson polynomial, that is an
    2562              : !! approximation of Heaviside step function by a Chebyshev expansion plus
    2563              : !! Jackson damping to reduce oscillations, applied on a set of vectors.
    2564              : !! Amplifies interval [lambda_minus, lambda_plus).
    2565              : !!
    2566              : !! INPUTS
    2567              : !! chebfi <type(chebfi_t)>=memory workspace used to apply filter
    2568              : !! eigen= Rayleigh quotients to use in amplification of chebfi%xXColsRows
    2569              : !! lambda_minus= lower bound of interval to amplify
    2570              : !! lambda_plus= upper bound of interval to amplify
    2571              : !! mineig_global= used to rescale to [-1,1), will le -1
    2572              : !! maxeig_global= used to rescale to [-1,1), will be 1
    2573              : !! getAX_BX= pointer to the function giving A|X> and B|X>
    2574              : !!           A is typically the Hamiltonian H, and B the overlap operator S
    2575              : !! getBm1X= pointer to the function giving B^-1|X>
    2576              : !!          B is typically the overlap operator S
    2577              : !!
    2578              : !! SIDE EFFECTS
    2579              : !!  chebfi%xXColsRows= Filtered vectors to use in Subspace iteration
    2580              : !!
    2581              : !! SOURCE
    2582              : 
    2583            0 : subroutine chebfi_bandpassFilter(chebfi,lambda_minus,lambda_plus,mineig_global,&
    2584              :         maxeig_global,getAX_BX,getBm1X)
    2585              : 
    2586              :     implicit none
    2587              : 
    2588              :     ! Arguments ------------------------------------
    2589              :     type(chebfi_t), intent(inout) :: chebfi
    2590              :     !type(xgBlock_t), intent(inout) :: eigen
    2591              :     real(dp), intent(in) :: lambda_minus
    2592              :     real(dp), intent(in) :: lambda_plus
    2593              :     real(dp), intent(in) :: mineig_global
    2594              :     real(dp), intent(in) :: maxeig_global
    2595              :     interface
    2596              :         subroutine getAX_BX(X,AX,BX)
    2597              :             use m_xg, only : xgBlock_t
    2598              :             type(xgBlock_t), intent(inout) :: X
    2599              :             type(xgBlock_t), intent(inout) :: AX
    2600              :             type(xgBlock_t), intent(inout) :: BX
    2601              :         end subroutine getAX_BX
    2602              :     end interface
    2603              :     interface
    2604              :         subroutine getBm1X(X,Bm1X)
    2605              :             use m_xg, only : xgBlock_t
    2606              :             type(xgBlock_t), intent(inout) :: X
    2607              :             type(xgBlock_t), intent(inout) :: Bm1X
    2608              :         end subroutine getBm1X
    2609              :     end interface
    2610              : 
    2611              :     ! Local variables-------------------------------
    2612              :     integer :: ndeg, n
    2613              :     real(dp) :: center, radius, one_over_r, two_over_r
    2614              :     real(dp) :: ls, us, cdeg, mu, damp
    2615              :     type(xg_t) :: Heaviside
    2616              :     type(xg_t) :: DivResults ! Rayleigh quotients
    2617              :     real(dp) :: tsec(2)
    2618              : 
    2619              :     ! *********************************************************************
    2620              : 
    2621            0 :     ndeg = chebfi%ndeg_filter
    2622              : 
    2623              :     ! Allocate memory for Chebyshev expansion of Heaviside step function
    2624              :     call xg_init(Heaviside, chebfi%space, chebfi%total_spacedim, chebfi%bandpp, chebfi%spacecom, &
    2625            0 :         gpu_option=chebfi%gpu_option)
    2626              :     !call xgBlock_zero(Heaviside%self)
    2627              : 
    2628            0 :     write(std_out,*) '@bandpass lambda_minus=', lambda_minus
    2629            0 :     write(std_out,*) '@bandpass lambda_plus=', lambda_plus
    2630            0 :     write(std_out,*) '@bandpass mineig_global=', mineig_global
    2631            0 :     write(std_out,*) '@bandpass maxeig_global=', maxeig_global
    2632            0 :     flush(std_out)
    2633              : 
    2634              :     ! Filter parameters
    2635            0 :     center = (maxeig_global + mineig_global)*0.5
    2636            0 :     radius = (maxeig_global - mineig_global)*0.5
    2637            0 :     one_over_r = 1/radius
    2638            0 :     two_over_r = 2/radius
    2639              : 
    2640              :     ! Scaled slice bounds to be amplified
    2641            0 :     ls = (lambda_minus - center) / radius
    2642            0 :     us = (lambda_plus - center) / radius
    2643              : 
    2644              :     ! TODO IL 10/3/2025 Deflate vectors to reduce linear dependence: Y=X-(B-projection)
    2645              :     !call xg_Borthonormalize(chebfi%xXColsRows,chebfi%xBxColsRows,ierr,1,chebfi%gpu_option,AX=chebfi%xAXColsRows)
    2646              : 
    2647              :     ! Initialize expansion: Heaviside = mu(0)*damp(0)*X + Heaviside
    2648            0 :     cdeg = Pi/(ndeg+2)
    2649            0 :     mu = 1/Pi*(ACOS(ls)-ACOS(us))
    2650            0 :     damp = 1.d0 ! Jackson damping
    2651            0 :     call xgBlock_saxpy(Heaviside%self, mu*damp, chebfi%xXColsRows)
    2652              : 
    2653              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_CORE)
    2654            0 :     do n = 0, ndeg - 1
    2655              : 
    2656              :         ! X_next=2/r*(AX_next-c*X_next)-X_prev
    2657              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_NEXT_ORDER)
    2658            0 :         call chebfi_computeNextOrderChebfiPolynom(chebfi, n, center, one_over_r, two_over_r, getBm1X)
    2659              :         ABI_NVTX_END_RANGE()
    2660              : 
    2661              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_SWAP_BUF)
    2662            0 :         if (chebfi%paral_kgb == 0) then
    2663            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%spacedim, chebfi%neigenpairs)
    2664              :         else
    2665            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, chebfi%bandpp)
    2666              :         end if
    2667              :         ABI_NVTX_END_RANGE()
    2668              : 
    2669              :         ! Update expansion: Heaviside = damp(i+1)*mu(i+1)*X_next + Heaviside
    2670            0 :         mu = 2/Pi * (SIN((n+1)*ACOS(ls)) - SIN((n+1)*ACOS(us)))/(n+1)
    2671            0 :         damp = ((1 - (n+1)/(ndeg+2))*SIN(cdeg)*COS((n+1)*cdeg) + 1/(ndeg+2)*COS(cdeg)*SIN((n+1)*cdeg))/SIN(cdeg)
    2672            0 :         call xgBlock_saxpy(Heaviside%self, mu*damp, chebfi%xXColsRows)
    2673              : 
    2674              :         ! Store final expansion before exit, X_next=Heaviside
    2675            0 :         if (n==ndeg-1) then
    2676            0 :             call xgBlock_copy(Heaviside%self, chebfi%xXColsRows)
    2677              :         end if
    2678              : 
    2679              :         !A * Psi (=AX_next=A*X_next)
    2680            0 :         call timab(tim_getAX_BX,1,tsec)
    2681              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    2682            0 :         call getAX_BX(chebfi%xXColsRows, chebfi%xAXColsRows, chebfi%xBXColsRows)
    2683            0 :         call xgBlock_zero_im_g0(chebfi%xAXColsRows)
    2684            0 :         call xgBlock_zero_im_g0(chebfi%xBXColsRows)
    2685              :         ABI_NVTX_END_RANGE()
    2686            0 :         call timab(tim_getAX_BX,2,tsec)
    2687              : 
    2688              :     end do ! end n
    2689              :     ABI_NVTX_END_RANGE()
    2690              : 
    2691              :     ! Avoid overflow
    2692              :     !call chebfi_prepAmpfactor(chebfi, eigen, DivResults)
    2693              :     !call chebfi_ampfactorBandpass(chebfi, DivResults%self, lambda_minus, lambda_plus, center, radius, ndeg)
    2694              : 
    2695              :     ! Free temporary memory
    2696            0 :     call xg_free(DivResults)
    2697            0 :     call xg_free(Heaviside)
    2698              : 
    2699            0 : end subroutine chebfi_bandpassFilter
    2700              : !!***
    2701              : 
    2702              : !----------------------------------------------------------------------
    2703              : 
    2704              : !!****f* m_chebfi/chebfi_bandpassFilterActive
    2705              : !! NAME
    2706              : !! chebfi_bandpassFilterActive
    2707              : !!
    2708              : !! FUNCTION
    2709              : !! Apply Bandpass filter using Chebyshev-Jackson polynomial, that is an
    2710              : !! approximation of Heaviside step function by a Chebyshev expansion plus
    2711              : !! Jackson damping to reduce oscillations, applied on a set of vectors.
    2712              : !! Amplifies interval [lambda_minus, lambda_plus).
    2713              : !!
    2714              : !! INPUTS
    2715              : !! chebfi <type(chebfi_t)>=memory workspace used to apply filter
    2716              : !! eigen= Rayleigh quotients to use in amplification of chebfi%xXColsRows
    2717              : !! lambda_minus= lower bound of interval to amplify
    2718              : !! lambda_plus= upper bound of interval to amplify
    2719              : !! mineig_global= used to rescale to [-1,1), will le -1
    2720              : !! maxeig_global= used to rescale to [-1,1), will be 1
    2721              : !! getAX_BX= pointer to the function giving A|X> and B|X>
    2722              : !!           A is typically the Hamiltonian H, and B the overlap operator S
    2723              : !! getBm1X= pointer to the function giving B^-1|X>
    2724              : !!          B is typically the overlap operator S
    2725              : !!
    2726              : !! SIDE EFFECTS
    2727              : !!  chebfi%xXColsRows= Filtered vectors to use in Subspace iteration
    2728              : !!
    2729              : !! SOURCE
    2730              : 
    2731            0 : subroutine chebfi_bandpassFilterActive(chebfi,X_active,AX_active,BX_active,&
    2732              :         lambda_minus,lambda_plus,mineig_global,maxeig_global,getAX_BX,getBm1X)
    2733              : 
    2734              :     implicit none
    2735              : 
    2736              :     ! Arguments ------------------------------------
    2737              :     type(chebfi_t), intent(inout) :: chebfi
    2738              :     type(xgBlock_t), intent(inout) :: X_active
    2739              :     type(xgBlock_t), intent(inout) :: AX_active
    2740              :     type(xgBlock_t), intent(inout) :: BX_active
    2741              :     !type(xgBlock_t), intent(inout) :: eigen
    2742              :     real(dp), intent(in) :: lambda_minus
    2743              :     real(dp), intent(in) :: lambda_plus
    2744              :     real(dp), intent(in) :: mineig_global
    2745              :     real(dp), intent(in) :: maxeig_global
    2746              :     interface
    2747              :         subroutine getAX_BX(X,AX,BX)
    2748              :             use m_xg, only : xgBlock_t
    2749              :             type(xgBlock_t), intent(inout) :: X
    2750              :             type(xgBlock_t), intent(inout) :: AX
    2751              :             type(xgBlock_t), intent(inout) :: BX
    2752              :         end subroutine getAX_BX
    2753              :     end interface
    2754              :     interface
    2755              :         subroutine getBm1X(X,Bm1X)
    2756              :             use m_xg, only : xgBlock_t
    2757              :             type(xgBlock_t), intent(inout) :: X
    2758              :             type(xgBlock_t), intent(inout) :: Bm1X
    2759              :         end subroutine getBm1X
    2760              :     end interface
    2761              : 
    2762              :     ! Local variables-------------------------------
    2763              :     integer :: ndeg, n
    2764              :     real(dp) :: center, radius, one_over_r, two_over_r
    2765              :     real(dp) :: ls, us, cdeg, mu, damp
    2766              :     type(xg_t) :: Heaviside
    2767              :     type(xg_t) :: DivResults ! Rayleigh quotients
    2768              :     real(dp) :: tsec(2)
    2769              : 
    2770              :     ! *********************************************************************
    2771              : 
    2772            0 :     ndeg = chebfi%ndeg_filter
    2773              : 
    2774              :     ! Allocate memory for Chebyshev expansion of Heaviside step function
    2775              :     call xg_init(Heaviside, chebfi%space, chebfi%total_spacedim, chebfi%bandpp, chebfi%spacecom, &
    2776            0 :         gpu_option=chebfi%gpu_option)
    2777              :     !call xgBlock_zero(Heaviside%self)
    2778              : 
    2779            0 :     write(std_out,*) '@bandpass lambda_minus=', lambda_minus
    2780            0 :     write(std_out,*) '@bandpass lambda_plus=', lambda_plus
    2781            0 :     write(std_out,*) '@bandpass mineig_global=', mineig_global
    2782            0 :     write(std_out,*) '@bandpass maxeig_global=', maxeig_global
    2783            0 :     flush(std_out)
    2784              : 
    2785              :     ! Filter parameters
    2786            0 :     center = (maxeig_global + mineig_global)*0.5
    2787            0 :     radius = (maxeig_global - mineig_global)*0.5
    2788            0 :     one_over_r = 1/radius
    2789            0 :     two_over_r = 2/radius
    2790              : 
    2791              :     ! Scaled slice bounds to be amplified
    2792            0 :     ls = (lambda_minus - center) / radius
    2793            0 :     us = (lambda_plus - center) / radius
    2794              : 
    2795              :     ! TODO IL 10/3/2025 Deflate vectors to reduce linear dependence: Y=X-(B-projection)
    2796              :     !call xg_Borthonormalize(chebfi%xXCols,chebfi%xBxColsRows,ierr,1,chebfi%gpu_option,AX=chebfi%xAXColsRows)
    2797              : 
    2798              :     ! Initialize expansion: Heaviside = mu(0)*damp(0)*X + Heaviside
    2799            0 :     cdeg = Pi/(ndeg+2)
    2800            0 :     mu = 1/Pi*(ACOS(ls)-ACOS(us))
    2801            0 :     damp = 1.d0 ! Jackson damping
    2802            0 :     call xgBlock_saxpy(Heaviside%self, mu*damp, X_active)
    2803              : 
    2804              :     ABI_NVTX_START_RANGE(NVTX_CHEBFI2_CORE)
    2805            0 :     do n = 0, ndeg - 1
    2806              : 
    2807              :         ! X_next=2/r*(AX_next-c*X_next)-X_prev
    2808              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_NEXT_ORDER)
    2809            0 :         call chebfi_computeNextOrderChebfiPolynom(chebfi, n, center, one_over_r, two_over_r, getBm1X)
    2810              :         ABI_NVTX_END_RANGE()
    2811              : 
    2812              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_SWAP_BUF)
    2813            0 :         if (chebfi%paral_kgb == 0) then
    2814            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%spacedim, chebfi%neigenpairs)
    2815              :         else
    2816            0 :             call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, chebfi%bandpp)
    2817              :         end if
    2818              :         ABI_NVTX_END_RANGE()
    2819              : 
    2820              :         ! Update expansion: Heaviside = damp(i+1)*mu(i+1)*X_next + Heaviside
    2821            0 :         mu = 2/Pi * (SIN((n+1)*ACOS(ls)) - SIN((n+1)*ACOS(us)))/(n+1)
    2822            0 :         damp = ((1 - (n+1)/(ndeg+2))*SIN(cdeg)*COS((n+1)*cdeg) + 1/(ndeg+2)*COS(cdeg)*SIN((n+1)*cdeg))/SIN(cdeg)
    2823            0 :         call xgBlock_saxpy(Heaviside%self, mu*damp, X_active)
    2824              : 
    2825              :         ! Store final expansion before exit, X_next=Heaviside
    2826            0 :         if (n==ndeg-1) then
    2827            0 :             call xgBlock_copy(Heaviside%self, X_active)
    2828              :         end if
    2829              : 
    2830              :         !A * Psi (=AX_next=A*X_next)
    2831            0 :         call timab(tim_getAX_BX,1,tsec)
    2832              :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_AX_BX)
    2833            0 :         call getAX_BX(X_active, AX_active, BX_active)
    2834            0 :         call xgBlock_zero_im_g0(AX_active)
    2835            0 :         call xgBlock_zero_im_g0(BX_active)
    2836              :         ABI_NVTX_END_RANGE()
    2837            0 :         call timab(tim_getAX_BX,2,tsec)
    2838              : 
    2839              :     end do ! end n
    2840              :     ABI_NVTX_END_RANGE()
    2841              : 
    2842              :     ! Avoid overflow
    2843              :     !call chebfi_prepAmpfactor(chebfi, eigen, DivResults)
    2844              :     !call chebfi_ampfactorBandpass(chebfi, DivResults%self, lambda_minus, lambda_plus, center, radius, ndeg)
    2845              : 
    2846              :     ! Free temporary memory
    2847            0 :     call xg_free(DivResults)
    2848            0 :     call xg_free(Heaviside)
    2849              : 
    2850            0 : end subroutine chebfi_bandpassFilterActive
    2851              : !!***
    2852              : 
    2853              : !----------------------------------------------------------------------
    2854              : 
    2855              : !!****f* m_chebfi2/chebfi_oracle1
    2856              : !! NAME
    2857              : !! chebfi_oracle1
    2858              : !!
    2859              : !! FUNCTION
    2860              : !! Compute order of Chebyshev polynom necessary to converge to a given tol
    2861              : !!
    2862              : !! INPUTS
    2863              : !!  xx= input variable
    2864              : !!  aa= left bound of the interval
    2865              : !!  bb= right bound of the interval
    2866              : !!  tol= needed precision
    2867              : !!  nmax= max number of iterations
    2868              : !!
    2869              : !! OUTPUT
    2870              : !!
    2871              : !! SIDE EFFECTS
    2872              : !!
    2873              : !! SOURCE
    2874              : 
    2875        16276 : function cheb_oracle1(xx,aa,bb,tol,nmax) result(nn)
    2876              : 
    2877              :   ! Arguments ------------------------------------
    2878              :   integer              :: nn
    2879              :   integer,  intent(in) :: nmax
    2880              :   real(dp), intent(in) :: xx,aa,bb
    2881              :   real(dp), intent(in) :: tol
    2882              : 
    2883              :   ! Local variables-------------------------------
    2884              :   integer :: ii
    2885              :   real(dp) :: yy,yim1,xred,temp
    2886              : 
    2887              :   ! *************************************************************************
    2888              : 
    2889        16276 :   xred = (xx-(aa+bb)/2)/(bb-aa)*2
    2890        16276 :   yy = xred
    2891        16276 :   yim1 = 1 !ONE
    2892              : 
    2893        16276 :   nn = nmax
    2894        16276 :   if(1/(yy**2) < tol) then
    2895              :     nn = 1
    2896              :   else
    2897       294686 :     do ii=2, nmax-1
    2898       294362 :       temp = yy
    2899       294362 :       yy = 2*xred*yy - yim1
    2900       294362 :       yim1 = temp
    2901       294686 :       if(1/(yy**2) < tol) then
    2902              :         nn = ii
    2903              :         exit
    2904              :       end if
    2905              :     end do
    2906              :   end if
    2907              : 
    2908        16276 : end function cheb_oracle1
    2909              : !!***
    2910              : 
    2911              : !----------------------------------------------------------------------
    2912              : 
    2913              : !!****f* m_chebfi2/chebfi_poly1
    2914              : !! NAME
    2915              : !! chebfi_poly1
    2916              : !!
    2917              : !! FUNCTION
    2918              : !! Compute Chebyshev polynomial???
    2919              : !!
    2920              : !! INPUTS
    2921              : !!  xx= input variable
    2922              : !!  aa= left bound of the interval
    2923              : !!  bb= right bound of the interval
    2924              : !!  nn=
    2925              : !!
    2926              : !! OUTPUT
    2927              : !!
    2928              : !! SIDE EFFECTS
    2929              : !!
    2930              : !! SOURCE
    2931              : 
    2932        44496 : function cheb_poly1(xx,nn,aa,bb) result(yy)
    2933              : 
    2934              :   ! Arguments ------------------------------------
    2935              :   integer,  intent(in) :: nn
    2936              :   real(dp), intent(in) :: xx, aa, bb
    2937              :   real(dp)             :: yy
    2938              : 
    2939              :   ! Local variables-------------------------------
    2940              :   integer  :: ii
    2941              :   real(dp) :: xred,yim1,temp
    2942              : 
    2943              :   ! *************************************************************************
    2944              : 
    2945        44496 :   xred = (xx-(aa+bb)/2)/(bb-aa)*2
    2946        44496 :   yy = xred
    2947        44496 :   yim1 = 1
    2948       317168 :   do ii= 2, nn
    2949       272672 :     temp = yy
    2950       272672 :     yy = 2*xred*yy - yim1
    2951       317168 :     yim1 = temp
    2952              :   end do
    2953              : 
    2954        44496 : end function cheb_poly1
    2955              : !!***
    2956              : 
    2957              : !----------------------------------------------------------------------
    2958              : 
    2959              : !!****f* m_chebfi2/chebfi_set_ndeg_from_residu
    2960              : !! NAME
    2961              : !! chebfi_set_ndeg_from_residu
    2962              : !!
    2963              : !! FUNCTION
    2964              : !! Compute ndeg_filter using the oracle and residuals.
    2965              : !!
    2966              : !! INPUTS
    2967              : !!
    2968              : !! OUTPUT
    2969              : !!
    2970              : !! SIDE EFFECTS
    2971              : !!
    2972              : !! SOURCE
    2973              : 
    2974         2312 : subroutine chebfi_set_ndeg_from_residu(chebfi,lambda_minus,lambda_plus,occ,DivResults,ndeg_filter_max,ndeg_filter)
    2975              : 
    2976              :  integer,intent(in) :: ndeg_filter_max
    2977              :  integer,intent(out) :: ndeg_filter
    2978              :  type(chebfi_t), intent(inout) :: chebfi
    2979              :  type(xgBlock_t), intent(in)    :: occ
    2980              :  type(xgBlock_t), intent(in)    :: DivResults
    2981              :  real(dp), intent(in) :: lambda_minus, lambda_plus
    2982              : 
    2983              :  logical :: test1,test2,test3
    2984              :  integer :: iband_tot,iband
    2985              :  integer :: bandpp,ierr,ndeg_filter_tolwfr,ndeg_filter_decrease,nbdbuf,ndeg_filter_all,shift
    2986         2312 :  integer,allocatable :: ndeg_filter_bands(:)
    2987              :  type(xgBlock_t) :: occBlock,occ_reshaped
    2988              :  type(xg_t) :: residu
    2989         2312 :  real(dp),pointer :: residu_(:,:),occ_(:,:)
    2990              :  real(dp) :: eig_iband,res_iband,occ_iband
    2991         2312 :  real(dp),pointer :: eig(:,:)
    2992              : ! character(len=500) :: msg
    2993              : 
    2994         2312 :  bandpp = chebfi%bandpp
    2995              : 
    2996              :  !Compute residu here for oracle, use X_next as a work space
    2997              :  ! X_next = S|Psi>
    2998         2312 :  call xgBlock_copy(chebfi%xBXColsRows,chebfi%X_next)
    2999              :  ! X_next = - eig * S|Psi>
    3000         2312 :  call xgBlock_ymax(chebfi%X_next,DivResults,0,1)
    3001              :  ! X_next = H|Psi> - eig * S|Psi>
    3002         2312 :  call xgBlock_add(chebfi%X_next,chebfi%xAXColsRows)
    3003              :  ! resid = |X_next|^2
    3004         2312 :  call xg_init(residu,SPACE_R,bandpp,1)
    3005         2312 :  call xgBlock_colwiseNorm2(chebfi%X_next, residu%self,comm_loc=xmpi_comm_null)
    3006              : 
    3007         2312 :  occ_reshaped = occ
    3008         2312 :  shift=xmpi_comm_rank(chebfi%comm_cols)*bandpp
    3009         2312 :  call xgBlock_reshape(occ_reshaped,1,chebfi%neigenpairs)
    3010         2312 :  call xgBlock_setBlock(occ_reshaped,occBlock,1,bandpp,fcol=1+shift)
    3011         2312 :  call xgBlock_reshape(occBlock,bandpp,1)
    3012         2312 :  if (chebfi%nbdbuf==-101) then
    3013          952 :    call xgBlock_apply_diag(residu%self,occBlock,1)
    3014              :  end if
    3015              : 
    3016         6936 :  ABI_MALLOC(ndeg_filter_bands,(bandpp))
    3017              : 
    3018              :  ! DivResults could be complex (with null imaginary part), so bandpp has to be in cols, not rows
    3019         2312 :  call xgBlock_reverseMap(DivResults,eig,rows=1,cols=bandpp)
    3020         2312 :  call xgBlock_reverseMap(residu%self,residu_,rows=1,cols=bandpp)
    3021         2312 :  call xgBlock_reverseMap(occBlock,occ_,rows=1,cols=bandpp)
    3022              : 
    3023         2312 :  if (chebfi%nbdbuf>0) then
    3024              :    nbdbuf = chebfi%nbdbuf
    3025          952 :  else if (chebfi%nbdbuf==-101) then
    3026          952 :    nbdbuf = 0
    3027              :  end if
    3028              : 
    3029        12104 :  do iband=1, bandpp
    3030         9792 :    eig_iband = eig(1,iband)
    3031         9792 :    res_iband = residu_(1,iband)
    3032         9792 :    occ_iband = occ_(1,iband)
    3033         9792 :    iband_tot = iband + shift
    3034         9792 :    test1 = res_iband<chebfi%tolerance ! band already converged
    3035         9792 :    test2 = iband_tot>chebfi%neigenpairs-nbdbuf ! band in the buffer
    3036         9792 :    test3 = chebfi%nbdbuf==-101.and.occ_iband<chebfi%oracle_min_occ ! occupancy is too low
    3037        12104 :    if (test1.or.test2.or.test3) then
    3038         5750 :      ndeg_filter_bands(iband) = 0
    3039              :    else
    3040              :      !ndeg_filter necessary to converge to tolerance
    3041         4042 :      ndeg_filter_tolwfr = cheb_oracle1(eig_iband, lambda_minus, lambda_plus, chebfi%tolerance / res_iband, 1000)
    3042         4042 :      if (chebfi%oracle==1) then
    3043          832 :        ndeg_filter_bands(iband) = MIN(ndeg_filter_max, ndeg_filter_tolwfr, chebfi%ndeg_filter)
    3044         3210 :      else if (chebfi%oracle==2) then
    3045              :        !ndeg_filter necessary to decrease residual by a constant factor
    3046         3210 :        ndeg_filter_decrease = cheb_oracle1(eig_iband, lambda_minus, lambda_plus, chebfi%oracle_factor, 15)
    3047         3210 :        ndeg_filter_bands(iband) = MIN(ndeg_filter_max, ndeg_filter_tolwfr, ndeg_filter_decrease)
    3048              :      else
    3049            0 :        ABI_ERROR('Wrong value for chebfi%oracle')
    3050              :      end if
    3051              :    end if
    3052              :  end do
    3053        12104 :  ndeg_filter = MAXVAL(ndeg_filter_bands)
    3054         2312 :  call xmpi_max(ndeg_filter,ndeg_filter_all,chebfi%comm_cols,ierr)
    3055         2312 :  ndeg_filter=ndeg_filter_all
    3056              : 
    3057         2312 :  call xg_free(residu)
    3058         2312 :  ABI_SFREE(ndeg_filter_bands)
    3059              : 
    3060         4624 : end subroutine chebfi_set_ndeg_from_residu
    3061              : !!***
    3062              : 
    3063              : !----------------------------------------------------------------------
    3064              : 
    3065              : !!****f* m_chebfi2/chebfi_getSubspaceResidual
    3066              : !! NAME
    3067              : !! chebfi_getSubspaceResidual
    3068              : !!
    3069              : !! FUNCTION
    3070              : !! || (I-QQ'B)Aq_j ||^2 for j=1,..,bandpp
    3071              : !! stored to resid
    3072              : 
    3073            0 : subroutine chebfi_getSubspaceResidual(chebfi, resid)
    3074              : 
    3075              :     implicit none
    3076              : 
    3077              :     type(chebfi_t), intent(inout) :: chebfi
    3078              :     type(xgBlock_t), intent(inout) :: resid
    3079              : 
    3080              :     type(xg_t) :: M, R
    3081              :     integer :: nrows, ncols
    3082              :     integer :: space_buf
    3083              : 
    3084              : ! *********************************************************************
    3085              : 
    3086            0 :     nrows = rows(chebfi%X) ! todo this should be chebfi%spacedim
    3087            0 :     ncols = chebfi%neigenpairs ! todo active part only
    3088              : 
    3089            0 :     if (chebfi%space==SPACE_C) then
    3090            0 :         space_buf = SPACE_C
    3091            0 :     else if (chebfi%space==SPACE_CR) then
    3092            0 :         space_buf = SPACE_R
    3093              :     else
    3094            0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
    3095              :     end if
    3096              : 
    3097            0 :     call xg_init(M, space_buf, ncols, ncols, comm=chebfi%spacecom, gpu_option=chebfi%gpu_option)
    3098            0 :     call xg_init(R, space_buf, nrows, ncols, comm=chebfi%spacecom, gpu_option=chebfi%gpu_option)
    3099              : 
    3100              :     ! Compute M = X^T*AX
    3101              :     ! sum all process contribution
    3102            0 :     call xgBlock_gemm('t','n',1.0d0,chebfi%X,chebfi%AX%self,0.d0,M%self,comm=chebfi%spacecom)
    3103              : 
    3104              :     ! Compute R = AX - BX*M
    3105            0 :     call xgBlock_copy(chebfi%AX%self, R%self)
    3106            0 :     call xgBlock_gemm('n','n',-1.0d0,chebfi%BX%self,M%self,1.0d0,R%self)
    3107              : 
    3108              :     ! sum along rows communicator
    3109            0 :     call xgBlock_colwiseNorm2(R%self, resid)
    3110              : 
    3111            0 :     call xg_free(M)
    3112            0 :     call xg_free(R)
    3113              : 
    3114            0 : end subroutine chebfi_getSubspaceResidual
    3115              : !!***
    3116              : 
    3117              : !----------------------------------------------------------------------
    3118              : 
    3119              : !!****f* m_chebfi2/chebfi_swapConvergedVectors
    3120              : !! NAME
    3121              : !! chebfi_swapConvergedVectors
    3122              : !!
    3123              : !! FUNCTION
    3124              : !! In-place contiguous-in-memory locking of column vectors in row distribution.
    3125              : !! Algorithm is based on swapping: at the end first k are locked last are active.
    3126              : !! | locked columns | active columns |
    3127              : !! |   1 ... k      |  k+1 ... m     |
    3128              : !! TODO logic could also be applied to divide Xext to slices.
    3129              : !!
    3130              : 
    3131            0 : subroutine chebfi_swapConvergedVectors(chebfi, resid, tol, n_locked)
    3132              : 
    3133              :     implicit none
    3134              : 
    3135              :     type(chebfi_t), intent(inout) :: chebfi
    3136              :     type(xgBlock_t), intent(in) :: resid
    3137              :     real(dp), intent(in) :: tol
    3138              :     integer, intent(out) :: n_locked
    3139              : 
    3140              :     integer :: i, nrows
    3141              :     integer :: j, left
    3142            0 :     real(dp), pointer :: resid_vals(:,:)
    3143            0 :     logical, allocatable :: mask(:)
    3144            0 :     logical, allocatable :: is_locked(:)
    3145            0 :     integer, allocatable :: idx(:)
    3146              :     integer :: space_buf
    3147              :     type(xg_t) :: T_swap ! temporary column buffer
    3148              : 
    3149              : ! *********************************************************************
    3150              : 
    3151            0 :     nrows = rows(resid)
    3152              : 
    3153            0 :     if (chebfi%space==SPACE_C) then
    3154            0 :         space_buf = SPACE_C
    3155            0 :     else if (chebfi%space==SPACE_CR) then
    3156            0 :         space_buf = SPACE_R
    3157              :     else
    3158            0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
    3159              :     end if
    3160              : 
    3161            0 :     ABI_MALLOC(mask, (nrows))
    3162            0 :     ABI_MALLOC(is_locked, (nrows))
    3163              : 
    3164            0 :     call xg_init(T_swap, space_buf, nrows, 1, comm=chebfi%spacecom, gpu_option=chebfi%gpu_option)
    3165              : 
    3166            0 :     call xgBlock_reverseMap(resid, resid_vals, rows=nrows, cols=1)
    3167              : 
    3168            0 :     mask = resid_vals(:,1) < tol
    3169            0 :     idx = pack([(i, i=1,nrows)], mask)
    3170            0 :     n_locked = size(idx)
    3171              : 
    3172            0 :     write(std_out,*) 'n_locked=', n_locked
    3173            0 :     write(std_out,*) 'locked indices=', idx(:)
    3174            0 :     write(std_out,*) 'residuals=', resid_vals(:,1)
    3175            0 :     flush(std_out)
    3176              : 
    3177            0 :     is_locked = .false.
    3178            0 :     is_locked(idx) = .true.
    3179              : 
    3180              :     ! partition via swapping (in-place)
    3181            0 :     left = 1
    3182            0 :     do j = 1, nrows
    3183            0 :         if (is_locked(j)) then
    3184            0 :             if (j /= left) then
    3185            0 :                 call xgBlock_colwiseSwap(chebfi%X, j, left, T_swap%self)
    3186            0 :                 call xgBlock_colwiseSwap(chebfi%AX%self, j, left, T_swap%self)
    3187            0 :                 call xgBlock_colwiseSwap(chebfi%BX%self, j, left, T_swap%self)
    3188              : 
    3189              :                 ! keep mask consistent after swap
    3190            0 :                 is_locked(j)    = is_locked(left)
    3191            0 :                 is_locked(left) = .true.
    3192              :             end if
    3193            0 :             left = left + 1
    3194              :         end if
    3195              :     end do
    3196              : 
    3197            0 :     ABI_FREE(mask)
    3198            0 :     ABI_FREE(is_locked)
    3199            0 :     call xg_free(T_swap)
    3200              : 
    3201            0 : end subroutine chebfi_swapConvergedVectors
    3202              : !!***
    3203              : 
    3204              : !----------------------------------------------------------------------
    3205              : 
    3206              : !!****f* m_chebfi2/chebfi_deflateWrtLocked
    3207              : !! NAME
    3208              : !! chebfi_deflateWrtLocked
    3209              : !!
    3210              : 
    3211            0 :   subroutine chebfi_deflateWrtLocked(chebfi, n_locked, X_locked, BX_locked)
    3212              : 
    3213              :     type(chebfi_t), intent(inout) :: chebfi
    3214              :     integer, intent(in) :: n_locked
    3215              :     type(xgBlock_t), intent(inout) :: X_locked
    3216              :     type(xgBlock_t), intent(inout) :: BX_locked
    3217              : 
    3218              :     integer :: nrows
    3219              :     integer :: space_buf
    3220              :     integer :: n_active
    3221              :     type(xg_t) :: buffer
    3222              :     type(xgBlock_t) :: X_active, AX_active, BX_active
    3223              : 
    3224              : ! *********************************************************************
    3225              : 
    3226            0 :     if (chebfi%space==SPACE_C) then
    3227            0 :         space_buf = SPACE_C
    3228            0 :     else if (chebfi%space==SPACE_CR) then
    3229            0 :         space_buf = SPACE_R
    3230              :     else
    3231            0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
    3232              :     end if
    3233              : 
    3234            0 :     nrows = rows(chebfi%X)
    3235            0 :     n_active = chebfi%neigenpairs - n_locked
    3236            0 :     call xg_init(buffer,space_buf,n_locked,n_active,comm=chebfi%spacecom,gpu_option=chebfi%gpu_option)
    3237              : 
    3238            0 :     write(std_out,*) 'start gemm with sum over comm'; flush(std_out)
    3239            0 :     write(std_out,*) 'getid', xgBlock_getid(buffer%self); flush(std_out)
    3240            0 :     write(std_out,*) 'getid', xgBlock_getid(buffer%self,comm=xmpi_comm_null); flush(std_out)
    3241            0 :     write(std_out,*) 'getid', xgBlock_getid(buffer%self,comm=chebfi%spacecom); flush(std_out)
    3242              : 
    3243              :     ! buffer = BX0^T*X
    3244              :     ! sum all process contribution
    3245            0 :     call xgBlock_setBlock(chebfi%X, X_active, nrows, n_active, fcol=n_locked+1)
    3246            0 :     call xgBlock_gemm('t','n',1.0d0,BX_locked,X_active,0.d0,buffer%self, comm=chebfi%spacecom)
    3247              : 
    3248            0 :     write(std_out,*) 'exit gemm with sum over comm'; flush(std_out)
    3249              : 
    3250            0 :     write(std_out,*) '@deflate W', rows(buffer%self), cols(buffer%self)
    3251            0 :     write(std_out,*) '@deflate A', rows(BX_locked), cols(BX_locked)
    3252            0 :     write(std_out,*) '@deflate B', rows(X_active), cols(X_active)
    3253            0 :     flush(std_out)
    3254              : 
    3255              :     ! X = X - X0*buffer
    3256            0 :     call xgBlock_gemm('n','n',-1.0d0,X_locked,buffer%self,1.0d0,X_active)
    3257              :     ! AX = AX - X0*buffer
    3258            0 :     call xgBlock_setBlock(chebfi%AX%self, AX_active, nrows, n_active, fcol=n_locked+1)
    3259            0 :     call xgBlock_gemm('n','n',-1.0d0,X_locked,buffer%self,1.0d0,AX_active)
    3260              :     ! BX = BX - X0*buffer
    3261            0 :     call xgBlock_setBlock(chebfi%BX%self, BX_active, nrows, n_active, fcol=n_locked+1)
    3262            0 :     call xgBlock_gemm('n','n',-1.0d0,X_locked,buffer%self,1.0d0,BX_active)
    3263              : 
    3264            0 :     call xg_free(buffer)
    3265              : 
    3266            0 :   end subroutine chebfi_deflateWrtLocked
    3267              : !!***
    3268              : 
    3269              : !----------------------------------------------------------------------
    3270              : 
    3271              : !!****f* m_chebfi2/chebfi_deflateActiveWrtLocked
    3272              : !! NAME
    3273              : !! chebfi_deflateActiveWrtLocked
    3274              : !!
    3275              : !! FUNCTION
    3276              : !! Deflate active vectors with respect to locked vectors in linalg representation
    3277              : 
    3278            0 :   subroutine chebfi_deflateActiveWrtLocked(chebfi, n_locked, X_part, AX_part, BX_part)
    3279              : 
    3280              :     type(chebfi_t), intent(inout) :: chebfi
    3281              :     integer, intent(in) :: n_locked
    3282              :     type(bandPartitionData_t), intent(inout) :: X_part
    3283              :     type(bandPartitionData_t), intent(inout) :: AX_part
    3284              :     type(bandPartitionData_t), intent(inout) :: BX_part
    3285              : 
    3286              :     integer :: space_buf
    3287              :     integer :: n_active
    3288              :     type(xg_t) :: buffer
    3289              : 
    3290              : ! *********************************************************************
    3291              : 
    3292            0 :     if (chebfi%space==SPACE_C) then
    3293            0 :         space_buf = SPACE_C
    3294            0 :     else if (chebfi%space==SPACE_CR) then
    3295            0 :         space_buf = SPACE_R
    3296              :     else
    3297            0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
    3298              :     end if
    3299              : 
    3300            0 :     n_active = chebfi%neigenpairs - n_locked
    3301            0 :     call xg_init(buffer,space_buf,n_locked,n_active,comm=chebfi%spacecom,gpu_option=chebfi%gpu_option)
    3302              : 
    3303            0 :     write(std_out,*) '@deflate W', rows(buffer%self), cols(buffer%self)
    3304            0 :     write(std_out,*) '@deflate A', rows(BX_part%linalg_locked), cols(BX_part%linalg_locked)
    3305            0 :     write(std_out,*) '@deflate B', rows(X_part%linalg_active), cols(X_part%linalg_active)
    3306            0 :     flush(std_out)
    3307              : 
    3308              :     ! buffer = BX0^T*X
    3309              :     call xgBlock_gemm('t','n',1.0d0,BX_part%linalg_locked,X_part%linalg_active,0.d0,&
    3310            0 :         buffer%self,comm=chebfi%spacecom)
    3311              : 
    3312              :     ! sum all process contribution
    3313              :     ! X = X - X0*buffer
    3314            0 :     call xgBlock_gemm('n','n',-1.0d0,X_part%linalg_locked,buffer%self,1.0d0,X_part%linalg_active)
    3315              :     ! AX = AX - X0*buffer
    3316            0 :     call xgBlock_gemm('n','n',-1.0d0,X_part%linalg_locked,buffer%self,1.0d0,AX_part%linalg_active)
    3317              :     ! BX = BX - X0*buffer
    3318            0 :     call xgBlock_gemm('n','n',-1.0d0,X_part%linalg_locked,buffer%self,1.0d0,BX_part%linalg_active)
    3319              : 
    3320            0 :     call xg_free(buffer)
    3321              : 
    3322            0 :   end subroutine chebfi_deflateActiveWrtLocked
    3323              : !!***
    3324              : 
    3325              : !----------------------------------------------------------------------
    3326              : 
    3327              : !!****f* m_chebfi2/bandPartitionInfo_initActiveSubcomm
    3328              : !! NAME
    3329              : !! bandPartitionInfo_initActiveSubcomm
    3330              : !!
    3331              : !! FUNCTION
    3332              : !! Every process can treat between 1 and bandpp bands
    3333              : !! with p processes we cover p x bandpp bands at maximum.
    3334              : !! Solve problem find minimal p to cover n_active bands.
    3335              : !! Constraints: use at least 1 process and at max nproc.
    3336              : !!
    3337              : !! INPUT
    3338              : !! comm                       global communicator
    3339              : !!
    3340              : !! OUTPUT
    3341              : !! mpiInfo%n_active_bandpp    stores the result per mpi rank
    3342              : !! mpiInfo%rank_active        true if process treats active bands
    3343              : 
    3344            0 :   subroutine bandPartitionInfo_initActiveSubcomm(mpiInfo, comm, bandpp_max)
    3345              : 
    3346              :       implicit none
    3347              : 
    3348              :       type(bandPartitionInfo_t), intent(inout) :: mpiInfo
    3349              :       integer, intent(in) :: comm
    3350              :       integer, intent(in) :: bandpp_max
    3351              : 
    3352            0 :       integer, allocatable :: ranks(:)
    3353              :       integer :: nproc
    3354              :       integer :: nproc_active, min_p, ii
    3355              : 
    3356              :   ! *********************************************************************
    3357              : 
    3358            0 :       nproc = xmpi_comm_size(comm)
    3359            0 :       min_p = ceiling(1.d0 * mpiInfo%n_active / bandpp_max)
    3360            0 :       nproc_active = min(nproc, max(1, min_p))
    3361              : 
    3362            0 :       ABI_MALLOC(ranks,(0:nproc_active-1))
    3363            0 :       ranks(0:nproc_active-1)=(/((ii),ii=0,nproc_active-1)/)
    3364            0 :       mpiInfo%comm_active=xmpi_subcomm(comm,nproc_active,ranks)
    3365            0 :       ABI_FREE(ranks)
    3366              : 
    3367              :       ! todo @debug all processes of slice must create the same active subcomm
    3368            0 :       write(std_out,*) '@initActiveSubcomm comm_active=', mpiInfo%comm_active
    3369            0 :       flush(std_out)
    3370              : 
    3371              : 
    3372            0 :   end subroutine bandPartitionInfo_initActiveSubcomm
    3373              : !!***
    3374              : 
    3375              : !----------------------------------------------------------------------
    3376              : 
    3377              : !!****f* m_chebfi2/bandPartitionData_allocActiveColsrows
    3378              : !! NAME
    3379              : !! bandPartitionData_allocActiveColsrows
    3380              : 
    3381            0 :   subroutine bandPartitionData_allocActiveColsrows(bpart, chebfi, mpiInfo, nspinor)
    3382              : 
    3383              :       implicit none
    3384              : 
    3385              :       type(bandPartitionData_t), intent(inout) :: bpart
    3386              :       type(chebfi_t), intent(in) :: chebfi
    3387              :       type(bandPartitionInfo_t), intent(inout) :: mpiInfo
    3388              :       integer, intent(in)    :: nspinor
    3389              : 
    3390              :       integer :: n_active
    3391              :       integer :: comm_active
    3392              :       real(dp) :: tsec(2)
    3393              : 
    3394              :   ! *********************************************************************
    3395              : 
    3396            0 :       n_active = mpiInfo%n_active
    3397            0 :       comm_active = mpiInfo%comm_active
    3398              : 
    3399              :       ABI_NVTX_START_RANGE(NVTX_CHEBFI2_TRANSPOSE)
    3400            0 :       call timab(tim_transpose,1,tsec)
    3401              : 
    3402              :       call xgTransposer_constructor(bpart%transposer_active,bpart%linalg_active,bpart%colsrows_active,&
    3403              :           nspinor,STATE_LINALG,TRANS_ALL2ALL,chebfi%comm_rows,comm_active,0,0,chebfi%me_g0_fft,&
    3404            0 :           gpu_option=chebfi%gpu_option,gpu_thread_limit=chebfi%gpu_thread_limit)
    3405              : 
    3406            0 :       bpart%transposer_active%gpu_kokkos_nthrd  = chebfi%gpu_kokkos_nthrd
    3407              : 
    3408              :       ABI_NVTX_END_RANGE()
    3409            0 :       call timab(tim_transpose,2,tsec)
    3410              : 
    3411            0 :   end subroutine bandPartitionData_allocActiveColsrows
    3412              : !!***
    3413              : 
    3414              : !----------------------------------------------------------------------
    3415              : 
    3416              : !!****f* m_chebfi2/bandPartitionData_setLinalg
    3417              : !! NAME
    3418              : !! bandPartitionData_setLinalg
    3419              : !!
    3420              : !! FUNCTION
    3421              : !! Set active and locked vectors in linalg representation
    3422              : 
    3423            0 :   subroutine bandPartitionData_setLinalg(X_in, bpart, n_locked)
    3424              : 
    3425              :       implicit none
    3426              : 
    3427              :       type(xgBlock_t), intent(in) :: X_in
    3428              :       type(bandPartitionData_t), intent(inout) :: bpart
    3429              :       integer, intent(in) :: n_locked
    3430              : 
    3431              :       integer :: nrows
    3432              :       integer :: n_active
    3433              : 
    3434              :   ! *********************************************************************
    3435              : 
    3436            0 :       nrows = rows(X_in)
    3437            0 :       n_active = cols(X_in) - n_locked
    3438              : 
    3439            0 :       call xgBlock_setBlock(X_in, bpart%linalg_locked, nrows, n_locked)
    3440            0 :       call xgBlock_setBlock(X_in, bpart%linalg_active, nrows, n_active, fcol=n_locked+1)
    3441              : 
    3442            0 :   end subroutine bandPartitionData_setLinalg
    3443              : !!***
    3444              : 
    3445            0 : end module m_chebfi2
    3446              : !!***
        

Generated by: LCOV version 2.3-1