LCOV - code coverage report
Current view: top level - src/48_diago - m_chebfi2_cprj.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.3 % 313 292
Test Date: 2026-09-19 17:42:43 Functions: 73.3 % 15 11

            Line data    Source code
       1              : !!****f* ABINIT/m_chebfi2_cprj
       2              : !! NAME
       3              : !! m_chebfi2_cprj
       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) 2023-2026 ABINIT group (LB)
      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              : module m_chebfi2_cprj
      26              : 
      27              :  use defs_basis
      28              :  use defs_abitypes
      29              :  use m_abicore
      30              :  use m_errors
      31              :  use m_time, only : timab
      32              : 
      33              :  use m_cgtools
      34              :  use m_xg
      35              :  use m_xgTransposer
      36              :  use m_xg_ortho_RR
      37              :  use m_xg_nonlop
      38              : 
      39              :  use m_xmpi
      40              :  use m_xomp
      41              : #ifdef HAVE_OPENMP
      42              :  use omp_lib
      43              : #endif
      44              : 
      45              :  implicit none
      46              : 
      47              :  private
      48              : 
      49              : !Several (private) parameters
      50              : !-------------------------------------------------
      51              : 
      52              :  integer, parameter :: tim_init         = 2061
      53              :  integer, parameter :: tim_free         = 2062
      54              :  integer, parameter :: tim_cprj         = 2063
      55              :  integer, parameter :: tim_invovl       = 2065
      56              :  integer, parameter :: tim_residu       = 2066
      57              :  integer, parameter :: tim_RR           = 2067
      58              :  integer, parameter :: tim_transpose    = 2068
      59              :  integer, parameter :: tim_RR_q         = 2069
      60              :  integer, parameter :: tim_postinvovl   = 2070
      61              :  integer, parameter :: tim_swap         = 2071
      62              :  integer, parameter :: tim_amp_f        = 2072
      63              :  integer, parameter :: tim_oracle       = 2073
      64              :  integer, parameter :: tim_barrier      = 2074
      65              :  integer, parameter :: tim_copy         = 2075
      66              :  integer, parameter :: tim_ax_k         = 2076
      67              :  integer, parameter :: tim_ax_v         = 2077
      68              :  integer, parameter :: tim_ax_nl        = 2078
      69              :  integer, parameter :: tim_enl          = 2079
      70              : 
      71              : !Public 'chebfi' datatype
      72              : !-------------------------------------------------
      73              : 
      74              :  type, public :: chebfi_t
      75              :    integer :: space
      76              :    integer :: space_cprj
      77              :    integer :: spacedim                      ! Space dimension for one vector
      78              :    integer :: cprjdim                       ! cprj dimension
      79              :    integer :: total_spacedim                ! Maybe not needed
      80              :    integer :: neigenpairs                   ! Number of eigen values/vectors we want
      81              :    integer :: ndeg_filter                   ! Degree of the polynomial filter
      82              :    integer :: nbdbuf                        ! Number of bands in the buffer
      83              :    integer :: spacecom                      ! Communicator for MPI
      84              :    integer :: oracle                        ! Option to compute ndeg_filter from residuals
      85              :    real(dp) :: tolerance            ! Tolerance on the residu to stop the minimization
      86              :    real(dp) :: ecut                 ! Ecut for Chebfi oracle
      87              :    real(dp) :: oracle_factor                ! factor used to decrease residuals
      88              :    real(dp) :: oracle_min_occ               ! threshold on occupancies used for nbdbuf=-101
      89              : 
      90              :    integer :: bandpp
      91              : 
      92              :    logical :: paw
      93              :    integer :: eigenProblem   !1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
      94              :    integer :: me_g0
      95              :    integer :: me_g0_fft
      96              : 
      97              :    type(xg_nonlop_t) :: xg_nonlop
      98              : 
      99              :    !ARRAYS
     100              :    type(xgBlock_t) :: X
     101              : 
     102              :    type(xg_t) :: X_NP
     103              :    type(xgBlock_t) :: X_next
     104              :    type(xgBlock_t) :: X_prev
     105              : 
     106              :    type(xg_t) :: AX
     107              :    type(xgBlock_t) :: cprjX
     108              :    type(xg_t) :: cprj_work
     109              :    type(xg_t) :: cprj_work2
     110              :    type(xg_t) :: proj_work
     111              : 
     112              :    type(xgBlock_t) :: xXColsRows
     113              :    type(xgBlock_t) :: xAXColsRows
     114              : 
     115              :    type(xgTransposer_t) :: xgTransposerX
     116              :    type(xgTransposer_t) :: xgTransposerAX
     117              : 
     118              :    type(xgBlock_t) :: eigenvalues
     119              : 
     120              :    !SWAP POINTERS
     121              :    type(xgBlock_t) :: X_swap
     122              :    type(xgBlock_t) :: AX_swap
     123              : 
     124              :   end type chebfi_t
     125              : 
     126              : !Public methods associated to 'chebfi' datatype
     127              : !-------------------------------------------------
     128              :  public :: chebfi_init
     129              :  public :: chebfi_free
     130              :  public :: chebfi_memInfo
     131              :  public :: chebfi_run_cprj
     132              : 
     133              :  CONTAINS  !========================================================================================
     134              : !!***
     135              : 
     136              : !!****f* m_chebfi2_cprj/chebfi_init
     137              : !! NAME
     138              : !! chebfi_init
     139              : !!
     140              : !! FUNCTION
     141              : !! Initialize a 'chebfi' datastructure.
     142              : !!
     143              : !! INPUTS
     144              : !!  bandpp= number of 'bands' handled by a processor
     145              : !!  eigenProblem= type of eigenpb: 1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
     146              : !!  me_g0= 1 if this processors treats G=0, 0 otherwise
     147              : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     148              : !!  ndeg_filter= polynomial degree of the Chebyshev filter (.i.e. number of H applications)
     149              : !!  space= defines in which space we are (columns, rows, etc.)
     150              : !!  spacecom= MPI communicator
     151              : !!  spacedim= space dimension for one vector
     152              : !!  paw= flag. TRUE if current calculation ses the PAW approach
     153              : !!  ecut= plane-wave cut-off energy
     154              : !!  tolerance= tolerance criterion on the residu to stop the minimization
     155              : !!
     156              : !! OUTPUT
     157              : !!
     158              : !! SIDE EFFECTS
     159              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     160              : !!
     161              : !! SOURCE
     162              : 
     163        15368 : subroutine chebfi_init(chebfi,neigenpairs,spacedim,cprjdim,tolerance,ecut,bandpp, &
     164              :                        ndeg_filter,nbdbuf,space,space_cprj,eigenProblem,spacecom,me_g0,paw,&
     165              :                        oracle,oracle_factor,oracle_min_occ,xg_nonlop,me_g0_fft)
     166              : 
     167              : !Arguments ------------------------------------
     168              :  integer          , intent(in   ) :: bandpp
     169              :  integer          , intent(in   ) :: eigenProblem
     170              :  integer          , intent(in   ) :: me_g0
     171              :  integer          , intent(in   ) :: me_g0_fft
     172              :  integer          , intent(in   ) :: neigenpairs
     173              :  integer          , intent(in   ) :: ndeg_filter
     174              :  integer          , intent(in   ) :: nbdbuf
     175              :  integer          , intent(in   ) :: space
     176              :  integer          , intent(in   ) :: space_cprj
     177              :  integer          , intent(in   ) :: spacecom
     178              :  integer          , intent(in   ) :: spacedim
     179              :  integer          , intent(in   ) :: cprjdim
     180              :  integer          , intent(in   ) :: oracle
     181              :  logical          , intent(in   ) :: paw
     182              :  real(dp)         , intent(in   ) :: ecut
     183              :  real(dp)         , intent(in   ) :: tolerance
     184              :  real(dp)         , intent(in   ) :: oracle_factor
     185              :  real(dp)         , intent(in   ) :: oracle_min_occ
     186              :  type(xg_nonlop_t), intent(in   ) :: xg_nonlop
     187              :  type(chebfi_t)   , intent(inout) :: chebfi
     188              : 
     189              : !Local variables-------------------------------
     190              :  real(dp)                    :: tsec(2)
     191              : 
     192              : ! *********************************************************************
     193              : 
     194        15368 :  call timab(tim_init,1,tsec)
     195              : 
     196        15368 :  chebfi%space         = space
     197        15368 :  chebfi%space_cprj    = space_cprj
     198        15368 :  chebfi%neigenpairs   = neigenpairs
     199        15368 :  chebfi%spacedim      = spacedim
     200        15368 :  chebfi%cprjdim       = cprjdim
     201        15368 :  if (tolerance > 0.0) then
     202         2312 :    chebfi%tolerance = tolerance
     203              :  else
     204        13056 :    chebfi%tolerance = 1.0e-20
     205              :  end if
     206        15368 :  chebfi%ecut          = ecut
     207        15368 :  chebfi%bandpp        = bandpp
     208        15368 :  chebfi%ndeg_filter   = ndeg_filter
     209        15368 :  chebfi%nbdbuf        = nbdbuf
     210        15368 :  chebfi%spacecom      = spacecom
     211        15368 :  chebfi%eigenProblem  = eigenProblem
     212        15368 :  chebfi%me_g0         = me_g0
     213        15368 :  chebfi%me_g0_fft     = me_g0_fft
     214        15368 :  chebfi%paw           = paw
     215        15368 :  chebfi%xg_nonlop     = xg_nonlop
     216        15368 :  chebfi%oracle        = oracle
     217        15368 :  chebfi%oracle_factor = oracle_factor
     218        15368 :  chebfi%oracle_min_occ = oracle_min_occ
     219              : 
     220        15368 :  call chebfi_allocateAll(chebfi)
     221              : 
     222        15368 :  call timab(tim_init,2,tsec)
     223              : 
     224        15368 : end subroutine chebfi_init
     225              : !!***
     226              : 
     227              : !----------------------------------------------------------------------
     228              : 
     229              : !!****f* m_chebfi2_cprj/chebfi_allocateAll
     230              : !! NAME
     231              : !! chebfi_allocateAll
     232              : !!
     233              : !! FUNCTION
     234              : !! Allocate all memory spaces in a 'chebfi' datastructure.
     235              : !!
     236              : !! INPUTS
     237              : !!
     238              : !! OUTPUT
     239              : !!
     240              : !! SIDE EFFECTS
     241              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     242              : !!
     243              : !! SOURCE
     244              : 
     245        30736 : subroutine chebfi_allocateAll(chebfi)
     246              : 
     247              :  ! Arguments ------------------------------------
     248              :  type(chebfi_t)  , intent(inout) :: chebfi
     249              : 
     250              :  ! Local variables-------------------------------
     251              :  ! scalars
     252              :  integer  :: neigenpairs
     253              :  integer  :: space,space_cprj
     254              :  integer  :: spacedim
     255              :  integer  :: total_spacedim, ierr
     256              :  integer  :: nspinor
     257              : 
     258              : ! *********************************************************************
     259              : 
     260        15368 :  space       = chebfi%space
     261        15368 :  space_cprj  = chebfi%space_cprj
     262        15368 :  spacedim    = chebfi%spacedim
     263        15368 :  neigenpairs = chebfi%neigenpairs
     264        15368 :  nspinor = chebfi%xg_nonlop%nspinor
     265              : 
     266        15368 :  call chebfi_free(chebfi)
     267              : 
     268        15368 :  total_spacedim = spacedim
     269        15368 :  call xmpi_sum(total_spacedim,chebfi%spacecom,ierr)
     270        15368 :  chebfi%total_spacedim = total_spacedim
     271        15368 :  call xg_init(chebfi%X_NP,space,total_spacedim,2*chebfi%bandpp,xmpi_comm_self,me_g0=chebfi%me_g0_fft) !transposed arrays
     272        15368 :  call xg_setBlock(chebfi%X_NP,chebfi%X_next,total_spacedim,chebfi%bandpp)
     273        15368 :  call xg_setBlock(chebfi%X_NP,chebfi%X_prev,total_spacedim,chebfi%bandpp,fcol=chebfi%bandpp+1)
     274              : 
     275        15368 :  call xg_init(chebfi%AX,space,spacedim,neigenpairs,chebfi%spacecom,me_g0=chebfi%me_g0)
     276        15368 :  call xg_init(chebfi%cprj_work ,space_cprj,chebfi%cprjdim,chebfi%bandpp*nspinor,chebfi%spacecom)
     277        15368 :  call xg_init(chebfi%cprj_work2,space_cprj,chebfi%cprjdim,chebfi%bandpp*nspinor,chebfi%spacecom)
     278              : 
     279        15368 :  call xg_init(chebfi%proj_work,space,chebfi%xg_nonlop%max_npw_k,chebfi%xg_nonlop%cprjdim,chebfi%spacecom,me_g0=chebfi%me_g0)
     280              : 
     281        15368 : end subroutine chebfi_allocateAll
     282              : !!***
     283              : 
     284              : !----------------------------------------------------------------------
     285              : 
     286              : !!****f* m_chebfi2_cprj/chebfi_free
     287              : !! NAME
     288              : !! chebfi_free
     289              : !!
     290              : !! FUNCTION
     291              : !! Destroy a 'chebfi' datastructure.
     292              : !!
     293              : !! INPUTS
     294              : !!
     295              : !! OUTPUT
     296              : !!  arraymem(2)= memory information
     297              : !!
     298              : !! SIDE EFFECTS
     299              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     300              : !!
     301              : !! SOURCE
     302              : 
     303        30736 : subroutine chebfi_free(chebfi)
     304              : 
     305              : !Arguments ------------------------------------
     306              :  type(chebfi_t) , intent(inout) :: chebfi
     307              : 
     308              : ! *********************************************************************
     309              : 
     310        30736 :  call xg_free(chebfi%X_NP)
     311              : 
     312        30736 :  call xg_free(chebfi%AX)
     313        30736 :  call xg_free(chebfi%cprj_work)
     314        30736 :  call xg_free(chebfi%cprj_work2)
     315        30736 :  call xg_free(chebfi%proj_work)
     316              : 
     317        30736 : end subroutine chebfi_free
     318              : !!***
     319              : 
     320              : !----------------------------------------------------------------------
     321              : 
     322              : !!****f* m_chebfi2_cprj/chebfi_memInfo
     323              : !! NAME
     324              : !! chebfi_memInfo
     325              : !!
     326              : !! FUNCTION
     327              : !! Provides memory information about a 'chebfi' datastructure.
     328              : !!
     329              : !! INPUTS
     330              : !!  bandpp= number of 'bands' handled by a processor
     331              : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     332              : !!  paral_kgb= flag controlling (k,g,bands) parallelization
     333              : !!  space= defines in which space we are (columns, rows, etc.)
     334              : !!  spacedim= dimension of MPI communicator
     335              : !!  total_spacedim= size of global KGB communicator (typically 'banspinorfft' comm.)
     336              : !!
     337              : !! OUTPUT
     338              : !!  arraymem(2)= memory information
     339              : !!
     340              : !! SIDE EFFECTS
     341              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     342              : !!
     343              : !! SOURCE
     344              : 
     345            0 : function chebfi_memInfo(neigenpairs,spacedim,space,total_spacedim,bandpp) result(arraymem)
     346              : 
     347              : !Arguments ------------------------------------
     348              :  integer, intent(in   ) :: bandpp
     349              :  integer, intent(in   ) :: neigenpairs
     350              :  integer, intent(in   ) :: space
     351              :  integer, intent(in   ) :: spacedim
     352              :  integer, intent(in   ) :: total_spacedim
     353              : 
     354              : !Local variables-------------------------------
     355              : !scalars
     356              :  real(dp) :: memX
     357              :  real(dp) :: memX_next
     358              :  real(dp) :: memX_prev
     359              :  real(dp) :: memAX
     360              :  real(dp) :: memBX
     361              : !Transposer variables
     362              :  real(dp) :: memX_CR
     363              :  real(dp) :: memAX_CR
     364              :  real(dp) :: memBX_CR
     365              : !chebfi_rayleighRitz function variables
     366              :  real(dp) :: memA_und_X
     367              :  real(dp) :: memB_und_X
     368              :  real(dp) :: memEigenvalues
     369              :  real(dp) :: cplx
     370              : !arrays
     371              :  real(dp) :: arraymem(2)
     372              : 
     373              : ! *********************************************************************
     374            0 :  cplx = 1
     375            0 :  if ( space == SPACE_C ) cplx = 2 !for now only complex
     376              : 
     377              :  !Permanent in chebfi
     378            0 :  memX = cplx * kind(1.d0) * spacedim * neigenpairs
     379              : 
     380              : ! if (paral_kgb == 0) then
     381              : !   memX_next = cplx * kind(1.d0) * spacedim * neigenpairs
     382              : !   memX_prev = cplx * kind(1.d0) * spacedim * neigenpairs
     383              : ! else
     384            0 :    memX_next = cplx * kind(1.d0) * total_spacedim * bandpp
     385            0 :    memX_prev = cplx * kind(1.d0) * total_spacedim * bandpp
     386              : ! end if
     387              : 
     388            0 :  memAX = cplx * kind(1.d0) * spacedim * neigenpairs
     389            0 :  memBX = cplx * kind(1.d0) * spacedim * neigenpairs
     390              : 
     391              :  !Transposer colrow array
     392              : ! if (paral_kgb == 1) then
     393            0 :    memX_CR = cplx * kind(1.d0) * total_spacedim * bandpp
     394            0 :    memAX_CR = cplx * kind(1.d0) * total_spacedim * bandpp
     395            0 :    memBX_CR = cplx * kind(1.d0) * total_spacedim * bandpp
     396              : ! else
     397              : !   memX_CR = 0
     398              : !   memAX_CR = 0
     399              : !   memBX_CR = 0
     400              : ! end if
     401              : 
     402              :  !chebfi_rayleighRitz function variables
     403            0 :  memA_und_X = cplx * kind(1.d0) * neigenpairs * neigenpairs
     404            0 :  memB_und_X = cplx * kind(1.d0) * neigenpairs * neigenpairs
     405            0 :  memEigenvalues = kind(1.d0) * neigenpairs
     406              : 
     407              :  arraymem(1) = memX + memX_next + memX_prev + &
     408            0 :                memAX + memBX + memX_CR + memAX_CR + memBX_CR
     409            0 :  arraymem(2) = memA_und_X + memB_und_X + memEigenvalues
     410              : 
     411            0 : end function chebfi_memInfo
     412              : !!***
     413              : 
     414              : !----------------------------------------------------------------------
     415              : 
     416              : !!****f* m_chebfi2_cprj/chebfi_run
     417              : !! NAME
     418              : !! chebfi_run
     419              : !!
     420              : !! FUNCTION
     421              : !! Apply the Chebyshev Filtering algorithm on a set of vectors.
     422              : !!
     423              : !! INPUTS
     424              : !!  mpi_enreg = information about MPI parallelization
     425              : !!  getAX_BX= pointer to the function giving A|X> and B|X>
     426              : !!            A is typically the Hamiltonian H, and B the overlap operator S
     427              : !!  getBm1X= pointer to the function giving B^-1|X>
     428              : !!           B is typically the overlap operator S
     429              : !!
     430              : !! OUTPUT
     431              : !!
     432              : !! SIDE EFFECTS
     433              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     434              : !!  eigen= Full eigenvalues (initial values on entry)
     435              : !!  residu= residuals, i.e. norm of (A-lambdaB)|X>
     436              : !!  X0= Full set of vectors (initial values on entry)
     437              : !!
     438              : !! SOURCE
     439              : 
     440        15368 : subroutine chebfi_run_cprj(chebfi,X0,cprjX0,getAX,kin,eigen,occ,residu,enl,nspinor)
     441              : 
     442              : !Arguments ------------------------------------
     443              :  type(chebfi_t) , intent(inout) :: chebfi
     444              :  integer,         intent(in)    :: nspinor
     445              :  type(xgBlock_t), intent(inout) :: X0
     446              :  type(xgBlock_t), intent(inout) :: cprjX0
     447              :  type(xgBlock_t), intent(inout) :: eigen
     448              :  type(xgBlock_t), intent(in)    :: occ
     449              :  type(xgBlock_t), intent(inout) :: residu
     450              :  type(xgBlock_t), intent(inout) :: enl
     451              :  type(xgBlock_t), intent(in   ) :: kin
     452              :  interface
     453              :    subroutine getAX(X,AX)
     454              :      use m_xg, only : xgBlock_t
     455              :      type(xgBlock_t), intent(inout) :: X
     456              :      type(xgBlock_t), intent(inout) :: AX
     457              :    end subroutine getAX
     458              :  end interface
     459              : 
     460              : !Local variables-------------------------------
     461              : !scalars
     462              :  integer :: spacedim
     463              :  integer :: space_res
     464              :  integer :: neigenpairs
     465              :  integer :: ndeg_filter,ndeg_filter_max
     466              :  integer :: ideg, ierr
     467              :  real(dp) :: tolerance
     468              :  real(dp) :: maxeig, maxeig_global
     469              :  real(dp) :: mineig, mineig_global
     470              :  real(dp) :: lambda_minus
     471              :  real(dp) :: lambda_plus
     472              :  real(dp) :: one_over_r
     473              :  real(dp) :: two_over_r
     474              :  real(dp) :: center
     475              :  real(dp) :: radius
     476              :  type(xg_t) :: DivResults
     477              : !arrays
     478              :  real(dp) :: tsec(2)
     479              :  !Pointers similar to old Chebfi
     480        15368 :  integer,allocatable :: ndeg_filter_bands(:) !Oracle variable
     481        15368 :  type(xg_nonlop_t) :: xg_nonlop
     482              : 
     483              : ! *********************************************************************
     484              : 
     485        15368 :  spacedim = chebfi%spacedim
     486        15368 :  neigenpairs = chebfi%neigenpairs
     487        15368 :  ndeg_filter = chebfi%ndeg_filter
     488        15368 :  xg_nonlop = chebfi%xg_nonlop
     489        15368 :  chebfi%eigenvalues = eigen
     490              : 
     491        46104 :  ABI_MALLOC(ndeg_filter_bands,(chebfi%bandpp))
     492        15368 :  if (chebfi%space==SPACE_C) then
     493         9112 :    space_res = SPACE_C
     494         6256 :  else if (chebfi%space==SPACE_CR) then
     495         6256 :    space_res = SPACE_R
     496              :  else
     497            0 :    ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
     498              :  end if
     499        15368 :  call xg_init(DivResults, space_res, chebfi%bandpp, 1)
     500              : 
     501        15368 :  tolerance = chebfi%tolerance
     502        15368 :  lambda_plus = chebfi%ecut
     503        15368 :  chebfi%X = X0
     504        15368 :  chebfi%cprjX = cprjX0
     505              : 
     506              : ! Transpose
     507        15368 :  call timab(tim_transpose,1,tsec)
     508              :  call xgTransposer_constructor(chebfi%xgTransposerX,chebfi%X,chebfi%xXColsRows,nspinor,&
     509        15368 :    STATE_LINALG,TRANS_ALL2ALL,xmpi_comm_self,chebfi%spacecom,0,0,chebfi%me_g0_fft)
     510              : 
     511        15368 :  call xgTransposer_copyConstructor(chebfi%xgTransposerAX,chebfi%xgTransposerX,chebfi%AX%self,chebfi%xAXColsRows,STATE_LINALG)
     512              : 
     513        15368 :  call xgTransposer_transpose(chebfi%xgTransposerX,STATE_COLSROWS)
     514        15368 :  chebfi%xgTransposerAX%state = STATE_COLSROWS
     515        15368 :  call timab(tim_transpose,2,tsec)
     516              : 
     517        15368 :  call timab(tim_cprj,1,tsec)
     518        15368 :  call xg_nonlop_getcprj(xg_nonlop,chebfi%xXColsRows,chebfi%cprjX,chebfi%proj_work%self)
     519        15368 :  call timab(tim_cprj,2,tsec)
     520        15368 :  call timab(tim_AX_v,1,tsec)
     521        15368 :  call getAX(chebfi%xXColsRows,chebfi%xAXColsRows)
     522        15368 :  call timab(tim_AX_v,2,tsec)
     523        15368 :  call timab(tim_AX_k,1,tsec)
     524        15368 :  call xgBlock_add_diag(chebfi%xXColsRows,kin,nspinor,chebfi%xAXColsRows)
     525        15368 :  call timab(tim_AX_k,2,tsec)
     526        15368 :  call timab(tim_AX_nl,1,tsec)
     527        15368 :  call xg_nonlop_getHX(xg_nonlop,chebfi%xAXcolsRows,chebfi%cprjX,chebfi%cprj_work%self,chebfi%proj_work%self)
     528        15368 :  call timab(tim_AX_nl,2,tsec)
     529              : 
     530        15368 :  call timab(tim_barrier,1,tsec)
     531        15368 :  call xmpi_barrier(chebfi%spacecom)
     532        15368 :  call timab(tim_barrier,2,tsec)
     533              : 
     534              : !********************* Compute Rayleigh quotients for every band, and set lambda equal to the largest one *****
     535        15368 :  call timab(tim_RR_q, 1, tsec)
     536        15368 :  call chebfi_rayleighRitzQuotients(chebfi, maxeig, mineig, DivResults%self)
     537              : 
     538        15368 :  call xmpi_max(maxeig,maxeig_global,chebfi%spacecom,ierr)
     539        15368 :  call xmpi_min(mineig,mineig_global,chebfi%spacecom,ierr)
     540        15368 :  call timab(tim_RR_q, 2, tsec)
     541              : 
     542        15368 :  lambda_minus = maxeig_global
     543              : 
     544        15368 :  call timab(tim_oracle,1,tsec)
     545              : 
     546              :  ! 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.
     547              :  ! Also, the maximal value of ndeg_filter_max is 40.
     548        15368 :  ndeg_filter_max = cheb_oracle1(mineig_global, lambda_minus, lambda_plus, 1D-16, 40)
     549        15368 :  ndeg_filter = MIN(ndeg_filter_max,chebfi%ndeg_filter)
     550        15368 :  if (chebfi%oracle>0) then
     551         2312 :    call chebfi_set_ndeg_from_residu(chebfi,lambda_minus,lambda_plus,occ,DivResults%self,ndeg_filter_max,ndeg_filter)
     552              :  end if
     553        96712 :  ndeg_filter_bands(:) = ndeg_filter
     554              : 
     555        15368 :  call timab(tim_oracle,2,tsec)
     556              : 
     557        15368 :  center = (lambda_plus + lambda_minus)*0.5
     558        15368 :  radius = (lambda_plus - lambda_minus)*0.5
     559              : 
     560        15368 :  one_over_r = 1/radius
     561        15368 :  two_over_r = 2/radius
     562              : 
     563       129554 :  do ideg = 0, ndeg_filter - 1
     564              : 
     565       114186 :    call timab(tim_cprj,1,tsec)
     566       114186 :    call xg_nonlop_getcprj(xg_nonlop,chebfi%xAXcolsrows,chebfi%cprjX,chebfi%proj_work%self)
     567       114186 :    call timab(tim_cprj,2,tsec)
     568       114186 :    call chebfi_computeNextOrderChebfiPolynom(chebfi, ideg, center, one_over_r, two_over_r)
     569              : 
     570       114186 :    call timab(tim_swap,1,tsec)
     571       114186 :    call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, chebfi%bandpp)
     572       114186 :    call timab(tim_swap,2,tsec)
     573              : 
     574              :    !A * Psi
     575       114186 :    call timab(tim_AX_v,1,tsec)
     576       114186 :    call getAX(chebfi%xXColsRows,chebfi%xAXColsRows)
     577       114186 :    call timab(tim_AX_v,2,tsec)
     578       114186 :    call timab(tim_AX_k,1,tsec)
     579       114186 :    call xgBlock_add_diag(chebfi%xXColsRows,kin,nspinor,chebfi%xAXColsRows)
     580       114186 :    call timab(tim_AX_k,2,tsec)
     581       114186 :    call timab(tim_cprj,1,tsec)
     582       114186 :    call xg_nonlop_getcprj(xg_nonlop,chebfi%xXColsRows,chebfi%cprjX,chebfi%proj_work%self)
     583       114186 :    call timab(tim_cprj,2,tsec)
     584       114186 :    call timab(tim_AX_nl,1,tsec)
     585       114186 :    call xg_nonlop_getHX(xg_nonlop,chebfi%xAXcolsRows,chebfi%cprjX,chebfi%cprj_work%self,chebfi%proj_work%self)
     586       129554 :    call timab(tim_AX_nl,2,tsec)
     587              : 
     588              :  end do
     589              : 
     590        15368 :  call timab(tim_barrier,1,tsec)
     591        15368 :  call xmpi_barrier(chebfi%spacecom)
     592        15368 :  call timab(tim_barrier,2,tsec)
     593              : 
     594        15368 :  call timab(tim_amp_f,1,tsec)
     595        15368 :  call chebfi_ampfactor(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
     596              :  ! this results in higher condition number so avoid
     597              :  !call chebfi_ampfactorMax(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
     598        15368 :  call timab(tim_amp_f,2,tsec)
     599              : 
     600        15368 :  call xg_free(DivResults)
     601        15368 :  ABI_FREE(ndeg_filter_bands)
     602              : 
     603        15368 :  call timab(tim_transpose,1,tsec)
     604        15368 :  call xmpi_barrier(chebfi%spacecom)
     605              : 
     606        15368 :  call xgTransposer_transpose(chebfi%xgTransposerX,STATE_LINALG)
     607        15368 :  call xgTransposer_transpose(chebfi%xgTransposerAX,STATE_LINALG)
     608              : 
     609        15368 :  if (xmpi_comm_size(chebfi%spacecom) == 1) then !only one MPI proc reset buffers to right addresses (because of X-Xcolwise swaps)
     610         4216 :    call xgBlock_setBlock(chebfi%xXColsRows , chebfi%X      , spacedim, neigenpairs)
     611         4216 :    call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
     612              :  end if
     613        15368 :  call timab(tim_transpose,2,tsec)
     614              : 
     615        15368 :  call timab(tim_cprj,1,tsec)
     616        15368 :  call xg_nonlop_getcprj(xg_nonlop,chebfi%X,chebfi%cprjX,chebfi%cprj_work%self)
     617        15368 :  call timab(tim_cprj,2,tsec)
     618              :  call xg_RayleighRitz_cprj(chebfi%xg_nonlop,chebfi%X,chebfi%cprjX,chebfi%AX%self,chebfi%eigenvalues,ierr,0,&
     619        15368 :    tim_RR,ABI_GPU_DISABLED,solve_ax_bx=.true.)
     620              : 
     621        15368 :  if (chebfi%paw) then
     622        12920 :    call timab(tim_AX_nl,1,tsec)
     623              :    call xg_nonlop_getHmeSX(xg_nonlop,chebfi%X,chebfi%cprjX,chebfi%AX%self,chebfi%eigenvalues,chebfi%cprj_work%self,&
     624        12920 :    & chebfi%cprj_work2%self,no_H=.True.)
     625        12920 :    call timab(tim_AX_nl,2,tsec)
     626              :  end if
     627              : 
     628        15368 :  call timab(tim_residu, 1, tsec)
     629              : 
     630        15368 :  if (.not.chebfi%paw) then
     631         2448 :    call xgBlock_yxmax(chebfi%AX%self,chebfi%eigenvalues,chebfi%X)
     632              :  end if
     633              : 
     634        15368 :  call xgBlock_colwiseNorm2(chebfi%AX%self, residu)
     635        15368 :  call timab(tim_residu, 2, tsec)
     636              : 
     637        15368 :  call timab(tim_copy, 1, tsec)
     638        15368 :  call xgBlock_copy(chebfi%X,X0)
     639        15368 :  call timab(tim_copy, 2, tsec)
     640              : 
     641        15368 :  call xgTransposer_free(chebfi%xgTransposerX)
     642        15368 :  call xgTransposer_free(chebfi%xgTransposerAX)
     643              : 
     644        15368 :  if (.not.chebfi%paw) then
     645         2448 :    call timab(tim_enl,1,tsec)
     646         2448 :    call xg_nonlop_colwiseXHX(chebfi%xg_nonlop,chebfi%cprjX,chebfi%cprj_work%self,enl)
     647         2448 :    call timab(tim_enl,2,tsec)
     648              :  end if
     649              : 
     650        46104 : end subroutine chebfi_run_cprj
     651              : !!***
     652              : 
     653              : !----------------------------------------------------------------------
     654              : 
     655              : !!****f* m_chebfi2_cprj/chebfi_rayleighRitzQuotients
     656              : !! NAME
     657              : !! chebfi_rayleighRitzQuotients
     658              : !!
     659              : !! FUNCTION
     660              : !! Compute the Rayleigh-Ritz quotients.
     661              : !!
     662              : !! INPUTS
     663              : !!
     664              : !! OUTPUT
     665              : !!
     666              : !! SIDE EFFECTS
     667              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     668              : !!  maxeig= highest eigenvalue
     669              : !!  mineig= lowest eigenvalue
     670              : !!  DivResults= Rayleigh-Ritz quotients
     671              : !!
     672              : !! SOURCE
     673              : 
     674        15368 : subroutine chebfi_rayleighRitzQuotients(chebfi,maxeig,mineig,DivResults)
     675              : 
     676              : !Arguments ------------------------------------
     677              :  real(dp), intent(inout) :: maxeig
     678              :  real(dp), intent(inout) :: mineig
     679              :  type(chebfi_t), intent(inout) :: chebfi
     680              :  type(xgBlock_t), intent(inout) :: DivResults
     681              : 
     682              : !Local variables-------------------------------
     683              : !scalars
     684              :  type(xg_t)::Results1
     685              :  type(xg_t)::Results2
     686              :  type(xg_t)::Results_work
     687              : !arrays
     688              :  integer :: maxeig_pos(2)
     689              :  integer :: mineig_pos(2)
     690              :  integer :: space_res
     691              : 
     692              : ! *********************************************************************
     693              : 
     694        15368 :  if (space(chebfi%xXcolsRows)==SPACE_C) then
     695         9112 :    space_res = SPACE_C
     696         6256 :  else if (space(chebfi%xXcolsRows)==SPACE_CR) then
     697         6256 :    space_res = SPACE_R
     698              :  else
     699            0 :    ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
     700              :  end if
     701        15368 :  call xg_init(Results1, space_res, chebfi%bandpp, 1)
     702        15368 :  call xg_init(Results2, space_res, chebfi%bandpp, 1)
     703              : 
     704        15368 :  call xgBlock_colwiseDotProduct(chebfi%xXColsRows,chebfi%xAXColsRows,Results1%self,comm_loc=xmpi_comm_null)
     705              : 
     706        15368 :  call xgBlock_colwiseDotProduct(chebfi%xXColsRows,chebfi%xXColsRows,Results2%self,comm_loc=xmpi_comm_null)
     707        15368 :  if (chebfi%xg_nonlop%paw) then
     708        12920 :    call xg_init(Results_work, space_res, chebfi%bandpp, 1)
     709        12920 :    call xg_nonlop_colwiseXAX(chebfi%xg_nonlop,chebfi%xg_nonlop%Sij%self,chebfi%cprjX,chebfi%cprj_work%self,Results_work%self)
     710        12920 :    call xgBlock_add(Results2%self,Results_work%self)
     711        12920 :    call xg_free(Results_work)
     712              :  end if
     713              : 
     714        15368 :  call xgBlock_colwiseDivision(Results1%self, Results2%self, DivResults, maxeig, maxeig_pos, mineig, mineig_pos)
     715              : 
     716        15368 :  call xg_free(Results1)
     717        15368 :  call xg_free(Results2)
     718              : 
     719        15368 : end subroutine chebfi_rayleighRitzQuotients
     720              : !!***
     721              : 
     722              : !----------------------------------------------------------------------
     723              : 
     724              : !!****f* m_chebfi2_cprj/chebfi_computeNextOrderChebfiPolynom
     725              : !! NAME
     726              : !! chebfi_computeNextOrderChebfiPolynom
     727              : !!
     728              : !! FUNCTION
     729              : !! From P_n(B-^1.A)|X> (where P_n is the Chebyshev polynom of order n),
     730              : !!   computes P_n+1(B-^1.A)|X>
     731              : !!
     732              : !! INPUTS
     733              : !!  ideg=current degree of polynom
     734              : !!  center=filter center
     735              : !!  one_over_r,two_over_r=1/R, 2/R, R being the radius of the filter
     736              : !!  getBm1X= pointer to the function giving B^-1|X>
     737              : !!           B is typically the overlap operator S
     738              : !!
     739              : !! OUTPUT
     740              : !!
     741              : !! SIDE EFFECTS
     742              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     743              : !!
     744              : !! SOURCE
     745              : 
     746       114186 : subroutine chebfi_computeNextOrderChebfiPolynom(chebfi,ideg,center,one_over_r,two_over_r)
     747              : 
     748              : !Arguments ------------------------------------
     749              :  real(dp)       , intent(in) :: center
     750              :  integer        , intent(in) :: ideg
     751              :  real(dp)       , intent(in) :: one_over_r
     752              :  real(dp)       , intent(in) :: two_over_r
     753              :  type(chebfi_t) , intent(inout) :: chebfi
     754              : 
     755              :  !Local variables-------------------------------
     756              :  real(dp) :: tsec(2)
     757              : 
     758              :  ! *********************************************************************
     759              : 
     760       114186 :  call timab(tim_copy, 1, tsec)
     761       114186 :  call xgBlock_copy(chebfi%xAXColsRows,chebfi%X_next)
     762       114186 :  call timab(tim_copy, 2, tsec)
     763              : 
     764       114186 :  if (chebfi%paw) then
     765        94950 :    call timab(tim_invovl, 1, tsec)
     766              :    call xg_nonlop_getSm1X(chebfi%xg_nonlop,chebfi%X_next,chebfi%cprjX,&
     767        94950 :      & chebfi%cprj_work%self,chebfi%cprj_work2%self,chebfi%proj_work%self)
     768        94950 :    call timab(tim_invovl, 2, tsec)
     769              :  else
     770        19236 :    call timab(tim_copy, 1, tsec)
     771        19236 :    call xgBlock_copy(chebfi%xAXColsRows,chebfi%X_next)
     772        19236 :    call timab(tim_copy, 2, tsec)
     773              :  end if
     774              : 
     775       114186 :  call timab(tim_postinvovl, 1, tsec)
     776       114186 :  call xgBlock_scale(chebfi%xXColsRows, center, 1) !scale by center
     777              : 
     778              :  !(B-1 * A * Psi^i-1 - c * Psi^i-1)
     779       114186 :  call xgBlock_saxpy(chebfi%X_next, dble(-1.0), chebfi%xXColsRows)
     780              : 
     781              :  !Psi^i-1  = 1/c * Psi^i-1
     782       114186 :  call xgBlock_scale(chebfi%xXColsRows, 1/center, 1) !counter scale by 1/center
     783              : 
     784       114186 :  if (ideg == 0) then
     785        14984 :    call xgBlock_scale(chebfi%X_next, one_over_r, 1)
     786              :  else
     787        99202 :    call xgBlock_scale(chebfi%X_next, two_over_r, 1)
     788              : 
     789        99202 :    call xgBlock_saxpy(chebfi%X_next, dble(-1.0), chebfi%X_prev)
     790              :  end if
     791              : 
     792       114186 :  call timab(tim_postinvovl, 2, tsec)
     793              : 
     794       114186 : end subroutine chebfi_computeNextOrderChebfiPolynom
     795              : !!***
     796              : 
     797              : !----------------------------------------------------------------------
     798              : 
     799              : !!****f* m_chebfi2_cprj/chebfi_swapInnerBuffers
     800              : !! NAME
     801              : !! chebfi_swapInnerBuffers
     802              : !!
     803              : !! FUNCTION
     804              : !! Swap buffers inside a 'chebfi' datastructure.
     805              : !!
     806              : !! INPUTS
     807              : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     808              : !!  spacedim= space dimension for one vector
     809              : !!
     810              : !! OUTPUT
     811              : !!
     812              : !! SIDE EFFECTS
     813              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     814              : !!
     815              : !! SOURCE
     816              : 
     817       114186 : subroutine chebfi_swapInnerBuffers(chebfi,spacedim,neigenpairs)
     818              : 
     819              :   ! Arguments ------------------------------------
     820              :   integer        , intent(in   ) :: spacedim
     821              :   integer        , intent(in   ) :: neigenpairs
     822              :   type(chebfi_t) , intent(inout) :: chebfi
     823              : 
     824              :   ! *********************************************************************
     825              : 
     826       114186 :   call xgBlock_setBlock(chebfi%X_prev,     chebfi%X_swap,     spacedim, neigenpairs) !X_swap = X_prev
     827       114186 :   call xgBlock_setBlock(chebfi%xXColsRows, chebfi%X_prev,     spacedim, neigenpairs) !X_prev = xXColsRows
     828       114186 :   call xgBlock_setBlock(chebfi%X_next,     chebfi%xXColsRows, spacedim, neigenpairs) !xXColsRows = X_next
     829       114186 :   call xgBlock_setBlock(chebfi%X_swap,     chebfi%X_next,     spacedim, neigenpairs) !X_next = X_swap
     830              : 
     831       114186 : end subroutine chebfi_swapInnerBuffers
     832              : !!***
     833              : 
     834              : !----------------------------------------------------------------------
     835              : 
     836              : !!****f* m_chebfi2_cprj/chebfi_ampfactor
     837              : !! NAME
     838              : !! chebfi_ampfactor
     839              : !!
     840              : !! FUNCTION
     841              : !! Compute amplification factor
     842              : !!
     843              : !! INPUTS
     844              : !! eig (:,:)= eigenvalues
     845              : !! lambda_minus,lambda_plus=
     846              : !! ndeg_filter_bands(:)= degree of Chebyshev polynomial filter for each band
     847              : !!
     848              : !! OUTPUT
     849              : !!
     850              : !! SIDE EFFECTS
     851              : !!  residu<type(xgBlock_t)>= vector of residuals
     852              : !!  chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
     853              : !!
     854              : !! SOURCE
     855              : 
     856        15368 : subroutine chebfi_ampfactor(chebfi,DivResults,lambda_minus,lambda_plus,ndeg_filter_bands)
     857              : 
     858              :   ! Arguments ------------------------------------
     859              :   integer,           intent(in   ) :: ndeg_filter_bands(:)
     860              :   type(xgBlock_t),   intent(in   ) :: DivResults
     861              :   real(dp),          intent(in   ) :: lambda_minus
     862              :   real(dp),          intent(in   ) :: lambda_plus
     863              :   type(chebfi_t),    intent(inout) :: chebfi
     864              : 
     865              :   ! Local variables-------------------------------
     866              :   ! scalars
     867              :   integer         :: iband
     868              :   real(dp)        :: ampfactor
     869              :   real(dp)        :: eig_per_band
     870              :   type(xgBlock_t) :: X_part
     871              :   type(xgBlock_t) :: AX_part
     872        15368 :   real(dp),pointer :: eig(:,:)
     873              : 
     874              :   ! *********************************************************************
     875              : 
     876        15368 :   call xgBlock_reverseMap(DivResults,eig,rows=1,cols=chebfi%bandpp)
     877              : 
     878        96712 :   do iband = 1, chebfi%bandpp
     879              : 
     880        81344 :     eig_per_band = eig(1,iband)
     881              : 
     882              :     !cheb_poly1(x, n, a, b)
     883        81344 :     ampfactor = cheb_poly1(eig_per_band, ndeg_filter_bands(iband), lambda_minus, lambda_plus)
     884              : 
     885        81344 :     if(abs(ampfactor) < 1e-3) ampfactor = 1e-3 !just in case, avoid amplifying too much
     886              : 
     887        81344 :     call xgBlock_setBlock(chebfi%xXColsRows, X_part, chebfi%total_spacedim, 1, fcol=iband)
     888        81344 :     call xgBlock_setBlock(chebfi%xAXColsRows, AX_part, chebfi%total_spacedim, 1, fcol=iband)
     889              : 
     890        81344 :     call xgBlock_scale(X_part, 1/ampfactor, 1)
     891        96712 :     call xgBlock_scale(AX_part, 1/ampfactor, 1)
     892              : 
     893              :   end do
     894              : 
     895        15368 : end subroutine chebfi_ampfactor
     896              : !!***
     897              : 
     898              : subroutine chebfi_ampfactorMax(chebfi,DivResults,lambda_minus,lambda_plus,ndeg_filter_bands)
     899              : 
     900              :   ! Arguments ------------------------------------
     901              :   integer,           intent(in   ) :: ndeg_filter_bands(:)
     902              :   type(xgBlock_t),   intent(in   ) :: DivResults
     903              :   real(dp),          intent(in   ) :: lambda_minus
     904              :   real(dp),          intent(in   ) :: lambda_plus
     905              :   type(chebfi_t),    intent(inout) :: chebfi
     906              : 
     907              :   ! Local variables-------------------------------
     908              :   ! scalars
     909              :   integer         :: iband
     910              :   real(dp)        :: ampfactor
     911              :   !type(xgBlock_t) :: X_part
     912              :   !type(xgBlock_t) :: AX_part
     913              :   real(dp),pointer :: eig(:,:)
     914              : 
     915              :   ! *********************************************************************
     916              : 
     917              :   call xgBlock_reverseMap(DivResults,eig,rows=1,cols=cols(DivResults))
     918              : 
     919              :   !cheb_poly1(x, n, a, b)
     920              :   ampfactor = maxval( (/ (cheb_poly1(eig(1,iband), ndeg_filter_bands(iband), lambda_minus, lambda_plus),&
     921              :       iband=1,cols(DivResults)) /) )
     922              : 
     923              :   call xgBlock_scale(chebfi%xXColsRows, 1/ampfactor, 1)
     924              :   call xgBlock_scale(chebfi%xAXColsRows, 1/ampfactor, 1)
     925              : 
     926              : end subroutine chebfi_ampfactorMax
     927              : !!***
     928              : 
     929              : !----------------------------------------------------------------------
     930              : 
     931              : !!****f* m_chebfi2_cprj/chebfi_oracle1
     932              : !! NAME
     933              : !! chebfi_oracle1
     934              : !!
     935              : !! FUNCTION
     936              : !! Compute order of Chebyshev polynom necessary to converge to a given tol
     937              : !!
     938              : !! INPUTS
     939              : !!  xx= input variable
     940              : !!  aa= left bound of the interval
     941              : !!  bb= right bound of the interval
     942              : !!  tol= needed precision
     943              : !!  nmax= max number of iterations
     944              : !!
     945              : !! OUTPUT
     946              : !!
     947              : !! SIDE EFFECTS
     948              : !!
     949              : !! SOURCE
     950              : 
     951        22620 : function cheb_oracle1(xx,aa,bb,tol,nmax) result(nn)
     952              : 
     953              :   ! Arguments ------------------------------------
     954              :   integer              :: nn
     955              :   integer,  intent(in) :: nmax
     956              :   real(dp), intent(in) :: xx,aa,bb
     957              :   real(dp), intent(in) :: tol
     958              : 
     959              :   ! Local variables-------------------------------
     960              :   integer :: ii
     961              :   real(dp) :: yy,yim1,xred,temp
     962              : 
     963              :   ! *************************************************************************
     964              : 
     965        22620 :   xred = (xx-(aa+bb)/2)/(bb-aa)*2
     966        22620 :   yy = xred
     967        22620 :   yim1 = 1 !ONE
     968              : 
     969        22620 :   nn = nmax
     970        22620 :   if(1/(yy**2) < tol) then
     971              :     nn = 1
     972              :   else
     973       422342 :     do ii=2, nmax-1
     974       421826 :       temp = yy
     975       421826 :       yy = 2*xred*yy - yim1
     976       421826 :       yim1 = temp
     977       422342 :       if(1/(yy**2) < tol) then
     978              :         nn = ii
     979              :         exit
     980              :       end if
     981              :     end do
     982              :   end if
     983              : 
     984        22620 : end function cheb_oracle1
     985              : !!***
     986              : 
     987              : !----------------------------------------------------------------------
     988              : 
     989              : !!****f* m_chebfi2_cprj/chebfi_poly1
     990              : !! NAME
     991              : !! chebfi_poly1
     992              : !!
     993              : !! FUNCTION
     994              : !! Compute Chebyshev polynomial???
     995              : !!
     996              : !! INPUTS
     997              : !!  xx= input variable
     998              : !!  aa= left bound of the interval
     999              : !!  bb= right bound of the interval
    1000              : !!  nn=
    1001              : !!
    1002              : !! OUTPUT
    1003              : !!
    1004              : !! SIDE EFFECTS
    1005              : !!
    1006              : !! SOURCE
    1007              : 
    1008        81344 : function cheb_poly1(xx,nn,aa,bb) result(yy)
    1009              : 
    1010              :   ! Arguments ------------------------------------
    1011              :   integer,  intent(in) :: nn
    1012              :   real(dp), intent(in) :: xx, aa, bb
    1013              :   real(dp)             :: yy
    1014              : 
    1015              :   ! Local variables-------------------------------
    1016              :   integer  :: ii
    1017              :   real(dp) :: xred,yim1,temp
    1018              : 
    1019              :   ! *************************************************************************
    1020              : 
    1021        81344 :   xred = (xx-(aa+bb)/2)/(bb-aa)*2
    1022        81344 :   yy = xred
    1023        81344 :   yim1 = 1
    1024       611328 :   do ii= 2, nn
    1025       529984 :     temp = yy
    1026       529984 :     yy = 2*xred*yy - yim1
    1027       611328 :     yim1 = temp
    1028              :   end do
    1029              : 
    1030        81344 : end function cheb_poly1
    1031              : !!***
    1032              : 
    1033              : !!****f* m_chebfi2_cprj/chebfi_set_ndeg_from_residu
    1034              : !! NAME
    1035              : !! chebfi_set_ndeg_from_residu
    1036              : !!
    1037              : !! FUNCTION
    1038              : !! Compute ndeg_filter using the oracle and residuals.
    1039              : !!
    1040              : !! INPUTS
    1041              : !!
    1042              : !! OUTPUT
    1043              : !!
    1044              : !! SIDE EFFECTS
    1045              : !!
    1046              : !! SOURCE
    1047              : 
    1048         2312 : subroutine chebfi_set_ndeg_from_residu(chebfi,lambda_minus,lambda_plus,occ,DivResults,ndeg_filter_max,ndeg_filter)
    1049              : 
    1050              :  integer,intent(in) :: ndeg_filter_max
    1051              :  integer,intent(out) :: ndeg_filter
    1052              :  type(chebfi_t), intent(inout) :: chebfi
    1053              :  type(xgBlock_t), intent(in)    :: occ
    1054              :  type(xgBlock_t), intent(in)    :: DivResults
    1055              :  real(dp), intent(in) :: lambda_minus, lambda_plus
    1056              : 
    1057              :  logical :: test1,test2,test3
    1058              :  integer :: iband_tot,iband
    1059              :  integer :: bandpp,ierr,ndeg_filter_tolwfr,ndeg_filter_decrease,nbdbuf,ndeg_filter_all,shift
    1060         2312 :  integer,allocatable :: ndeg_filter_bands(:)
    1061              :  type(xgBlock_t) :: occBlock,occ_reshaped
    1062              :  type(xg_t) :: residu
    1063         2312 :  real(dp),pointer :: residu_(:,:),occ_(:,:)
    1064              :  real(dp) :: eig_iband,res_iband,occ_iband
    1065         2312 :  real(dp),pointer :: eig(:,:)
    1066              : 
    1067         2312 :  bandpp = chebfi%bandpp
    1068              : 
    1069              :  !Compute residu here for oracle, use X_next as a work space
    1070              :  ! X_next = S|Psi>
    1071         2312 :  call xgBlock_copy(chebfi%xXColsRows,chebfi%X_next)
    1072         2312 :  if (chebfi%paw) then
    1073         2312 :    call xg_nonlop_getSX(chebfi%xg_nonlop,chebfi%X_next,chebfi%cprjX,chebfi%cprj_work%self,chebfi%proj_work%self)
    1074              :  end if
    1075              :  ! X_next = - eig * S|Psi>
    1076         2312 :  call xgBlock_ymax(chebfi%X_next,DivResults,0,1)
    1077              :  ! X_next = H|Psi> - eig * S|Psi>
    1078         2312 :  call xgBlock_add(chebfi%X_next,chebfi%xAXColsRows)
    1079              :  ! resid = |X_next|^2
    1080         2312 :  call xg_init(residu,SPACE_R,bandpp,1)
    1081         2312 :  call xgBlock_colwiseNorm2(chebfi%X_next, residu%self,comm_loc=xmpi_comm_null)
    1082              : 
    1083         2312 :  occ_reshaped = occ
    1084         2312 :  shift=xmpi_comm_rank(chebfi%spacecom)*bandpp
    1085         2312 :  call xgBlock_reshape(occ_reshaped,1,chebfi%neigenpairs)
    1086         2312 :  call xgBlock_setBlock(occ_reshaped,occBlock,1,bandpp,fcol=1+shift)
    1087         2312 :  call xgBlock_reshape(occBlock,bandpp,1)
    1088         2312 :  if (chebfi%nbdbuf==-101) then
    1089          952 :    call xgBlock_apply_diag(residu%self,occBlock,1)
    1090              :  end if
    1091              : 
    1092         6936 :  ABI_MALLOC(ndeg_filter_bands,(bandpp))
    1093              : 
    1094              :  ! DivResults could be complex (with null imaginary part), so bandpp has to be in cols, not rows
    1095         2312 :  call xgBlock_reverseMap(DivResults,eig,rows=1,cols=bandpp)
    1096         2312 :  call xgBlock_reverseMap(residu%self,residu_,rows=1,cols=bandpp)
    1097         2312 :  call xgBlock_reverseMap(occBlock,occ_,rows=1,cols=bandpp)
    1098              : 
    1099         2312 :  if (chebfi%nbdbuf>0) then
    1100              :    nbdbuf = chebfi%nbdbuf
    1101          952 :  else if (chebfi%nbdbuf==-101) then
    1102          952 :    nbdbuf = 0
    1103              :  end if
    1104              : 
    1105        12104 :  do iband=1, bandpp
    1106         9792 :    eig_iband = eig(1,iband)
    1107         9792 :    res_iband = residu_(1,iband)
    1108         9792 :    occ_iband = occ_(1,iband)
    1109         9792 :    iband_tot = iband + shift
    1110         9792 :    test1 = res_iband<chebfi%tolerance ! band already converged
    1111         9792 :    test2 = iband_tot>chebfi%neigenpairs-nbdbuf ! band in the buffer
    1112         9792 :    test3 = chebfi%nbdbuf==-101.and.occ_iband<chebfi%oracle_min_occ ! occupancy is too low
    1113        12104 :    if (test1.or.test2.or.test3) then
    1114         5750 :      ndeg_filter_bands(iband) = 0
    1115              :    else
    1116              :      !ndeg_filter necessary to converge to tolerance
    1117         4042 :      ndeg_filter_tolwfr = cheb_oracle1(eig_iband, lambda_minus, lambda_plus, chebfi%tolerance / res_iband, 1000)
    1118         4042 :      if (chebfi%oracle==1) then
    1119          832 :        ndeg_filter_bands(iband) = MIN(ndeg_filter_max, ndeg_filter_tolwfr, chebfi%ndeg_filter)
    1120         3210 :      else if (chebfi%oracle==2) then
    1121              :        !ndeg_filter necessary to decrease residual by a constant factor
    1122         3210 :        ndeg_filter_decrease = cheb_oracle1(eig_iband, lambda_minus, lambda_plus, chebfi%oracle_factor, 15)
    1123         3210 :        ndeg_filter_bands(iband) = MIN(ndeg_filter_max, ndeg_filter_tolwfr, ndeg_filter_decrease)
    1124              :      else
    1125            0 :        ABI_ERROR('Wrong value for chebfi%oracle')
    1126              :      end if
    1127              :    end if
    1128              :  end do
    1129        12104 :  ndeg_filter = MAXVAL(ndeg_filter_bands)
    1130         2312 :  call xmpi_max(ndeg_filter,ndeg_filter_all,chebfi%spacecom,ierr)
    1131         2312 :  ndeg_filter=ndeg_filter_all
    1132              : 
    1133         2312 :  call xg_free(residu)
    1134         2312 :  ABI_FREE(ndeg_filter_bands)
    1135              : 
    1136         4624 : end subroutine chebfi_set_ndeg_from_residu
    1137              : !!***
    1138              : 
    1139              : !!****f* m_chebfi2/jackson_lowpass_coeffs
    1140              : !! NAME
    1141              : !! jackson_lowpass_coeffs
    1142              : !!
    1143              : !! FUNCTION
    1144              : !! Compute Jackson-damped Chebyshev coefficients for a lowpass step
    1145              : !! on interval [lambda_min, lambda_max], degree M
    1146              : 
    1147              : subroutine jackson_lowpass_coeffs(M, c)
    1148              :     implicit none
    1149              :     integer, intent(in) :: M
    1150              :     real(dp), intent(out) :: c(1:M+1)
    1151              :     integer :: k
    1152              :     real(dp) :: theta, g
    1153              : 
    1154              :     ! Chebyshev coefficients for step at left end (-1 in scaled coords)
    1155              :     theta = acos(-1.0d0)   ! step at left edge
    1156              :     c(1) = theta / Pi       ! k = 0
    1157              : 
    1158              :     do k = 1, M
    1159              :         c(k+1) = -2.0d0 / Pi * sin(k*theta) / k
    1160              :     end do
    1161              : 
    1162              :     ! Apply Jackson damping
    1163              :     do k = 0, M
    1164              :         g = ((M-k+1)*cos(Pi*k/(M+1)) + sin(Pi*k/(M+1))/tan(Pi/(M+1)))/(M+1)
    1165              :         c(k+1) = c(k+1) * g
    1166              :     end do
    1167              : 
    1168              : end subroutine jackson_lowpass_coeffs
    1169              : !!***
    1170              : 
    1171            0 : end module m_chebfi2_cprj
    1172              : !!***
        

Generated by: LCOV version 2.3-1