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-11-11 19:49:02 Functions: 73.3 % 15 11
Branches: 58.9 % 158 93

             Branch data     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