LCOV - code coverage report
Current view: top level - src/48_diago - m_slice.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.5 % 306 283
Test Date: 2026-11-08 04:19:34 Functions: 80.0 % 10 8
Branches: 53.3 % 272 145

             Branch data     Line data    Source code
       1                 :             : !!****f* ABINIT/m_slice
       2                 :             : !! NAME
       3                 :             : !! m_slice
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module contains the types and routines used to apply the Spectrum Slicing
       7                 :             : !! method. It mainly defines 'slice' datatypes and associated methods.
       8                 :             : !!
       9                 :             : !! Main features:
      10                 :             : !! - uses 'xgTools' implementation for matrix data structure.
      11                 :             : !! - adopts 'chebfi' functionalities for most matrix calculations.
      12                 :             : !! - uses polynomial filtering, Chebyshev lowpass, next Chebyshev-Jackson.
      13                 :             : !! - uses scheduler and resource allocator for slice tasks.
      14                 :             : !! - uses logic for asynchronous slice memory avoiding race condition in read/write.
      15                 :             : !! - applies Rayleigh-Ritz for individual slices in parallel or sequentially.
      16                 :             : !!
      17                 :             : !! NOTES
      18                 :             : !! Dependence with other modules and hierarchy in this directory:
      19                 :             : !!   m_slice uses:
      20                 :             : !!      |- m_polynomial_filter | various math compute routines
      21                 :             : !!      |- m_trace_estimation  | various math compute routines
      22                 :             : !!      |- m_chebfi2           ! the Chebyshev recursion
      23                 :             : !!      |- m_slice_task        | Low-level
      24                 :             : !!
      25                 :             : !! COPYRIGHT
      26                 :             : !! Copyright (C) 2018-2026 ABINIT group (IML)
      27                 :             : !! This file is distributed under the terms of the
      28                 :             : !! gnu general public license, see ~abinit/COPYING
      29                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      30                 :             : !! for the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      31                 :             : !!
      32                 :             : !! SOURCE
      33                 :             : 
      34                 :             : #if defined HAVE_CONFIG_H
      35                 :             : #include "config.h"
      36                 :             : #endif
      37                 :             : 
      38                 :             : #include "abi_common.h"
      39                 :             : 
      40                 :             : ! nvtx related macro definition
      41                 :             : #include "nvtx_macros.h"
      42                 :             : 
      43                 :             : module m_slice
      44                 :             : 
      45                 :             :     use defs_basis
      46                 :             :     use defs_abitypes
      47                 :             :     use m_abicore
      48                 :             :     use m_errors
      49                 :             :     use m_time, only : timab
      50                 :             :     use m_sort, only: sort_dp
      51                 :             : 
      52                 :             :     use m_cgtools
      53                 :             :     use m_xg
      54                 :             :     use m_xgTransposer
      55                 :             :     use m_xg_ortho_RR
      56                 :             :     use m_chebfi2
      57                 :             : 
      58                 :             :     use m_trace_estimation
      59                 :             :     use m_slice_task
      60                 :             :     use m_polynomial_filter
      61                 :             : 
      62                 :             :     use m_xmpi
      63                 :             :     use m_xomp
      64                 :             : #ifdef HAVE_OPENMP
      65                 :             :     use omp_lib
      66                 :             : #endif
      67                 :             : 
      68                 :             : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
      69                 :             :     use m_gpu_toolbox, only : CPU_DEVICE_ID, gpu_device_synchronize
      70                 :             : #endif
      71                 :             : 
      72                 :             : #if defined(HAVE_GPU_MARKERS)
      73                 :             :     use m_nvtx_data
      74                 :             : #endif
      75                 :             : 
      76                 :             :     implicit none
      77                 :             : 
      78                 :             :     private
      79                 :             : 
      80                 :             :     ! Spectral interval decomposition strategy (spectral_cut input variable)
      81                 :             :     ! todo delete this obsolete
      82                 :             :     !---------------------------------------------------
      83                 :             :     integer, parameter :: DIVIDE_INTERVAL_WIDTH    = 0
      84                 :             :     integer, parameter :: DIVIDE_NUMBER_OF_VECTORS = 1
      85                 :             :     integer, parameter :: DIVIDE_SPECTRAL_GAPS     = 2
      86                 :             : 
      87                 :             :     ! Load balance criteria for fair resource allocation (paral_slice input variable)
      88                 :             :     ! todo should be either 0 or 1
      89                 :             :     !---------------------------------------------------
      90                 :             :     integer, parameter :: FAIR_BANDPP      = 1          ! bandpp (unweigted)
      91                 :             :     integer, parameter :: FAIR_BANDPP_WDEG = 2          ! bandpp weighted by degree
      92                 :             :     integer, parameter :: EVEN_SLICES      = 3          ! all slices have the same num of procs
      93                 :             :     integer, parameter :: SEQUENTIAL_SLICE = 4          ! sequential slice treatment
      94                 :             : 
      95                 :             :     integer, parameter :: ENABLE_PARAL  = 0
      96                 :             :     integer, parameter :: DISABLE_PARAL = 1
      97                 :             : 
      98                 :             :     ! Timers
      99                 :             :     !---------------------------------------------------
     100                 :             :     integer, parameter :: tim_swap        = 1761
     101                 :             :     integer, parameter :: tim_RR_q        = 1759
     102                 :             :     integer, parameter :: tim_barrier     = 1764
     103                 :             :     integer, parameter :: tim_copy        = 1765
     104                 :             :     integer, parameter :: tim_Bortho_X    = 1641
     105                 :             :     integer, parameter :: tim_getAX_BX    = 1754
     106                 :             :     integer, parameter :: tim_invovl      = 1755
     107                 :             :     integer, parameter :: tim_slice_sched = 2161
     108                 :             :     integer, parameter :: tim_slice_1     = 2162
     109                 :             :     integer, parameter :: tim_slice_2     = 2163
     110                 :             :     integer, parameter :: tim_slice_3     = 2164
     111                 :             :     integer, parameter :: tim_slice_X     = 2165
     112                 :             :     integer, parameter :: tim_lanczos     = 2167
     113                 :             :     integer, parameter :: tim_trace       = 2168
     114                 :             : 
     115                 :             :     ! Public 'slice' datatype
     116                 :             :     !-------------------------------------------------
     117                 :             :     type, public :: slice_t
     118                 :             : 
     119                 :             :         ! MPI-related common to all-slice phase
     120                 :             :         integer :: nproc                                ! number of available processes
     121                 :             :         integer :: comm_rows                            ! xmpi_comm_self ...
     122                 :             :         integer :: comm_cols                            ! same as spacecom
     123                 :             :         integer :: spacecom                             ! same as comm_cols
     124                 :             :         integer :: bandpp                               ! nb of bands per process in colsrows representation
     125                 :             :         integer :: me_g0                                ! 1 if this processors treats G=0, 0 otherwise
     126                 :             :         integer :: me_g0_fft                            ! 1 if this processors treats G=0 in FFT, 0 otherwise
     127                 :             : 
     128                 :             :         ! Eigenpair parameters
     129                 :             :         integer :: neigenpairs                          ! total number of bands (=number of eigenpairs)
     130                 :             :         integer :: total_spacedim                       ! total number of plane-waves
     131                 :             :         integer :: spacedim                             ! nb of plane-waves per process in linalg representation
     132                 :             :         integer :: nslice                               ! number of spectral slices
     133                 :             :         integer :: space                                ! real or complex eigenvectors
     134                 :             :         integer :: nbdbuf                               ! fixme for the moment not clear if useful
     135                 :             : 
     136                 :             :         ! GPU-related
     137                 :             :         integer :: gpu_kokkos_nthrd
     138                 :             :         integer :: gpu_thread_limit
     139                 :             : 
     140                 :             :         ! Various options
     141                 :             :         integer :: gpu_option                           ! enable GPU
     142                 :             :         integer :: paral_kgb                            ! enable parallel (k-points, G basis, bands)
     143                 :             :         integer :: paral_slice                          ! how to allocate resources for parallel slices
     144                 :             :         integer :: spectral_cut                         ! how to decompose spectrum into slices
     145                 :             : 
     146                 :             :         ! Various model parameters
     147                 :             :         logical :: paw                                  ! use PAW or not
     148                 :             :         integer :: ndeg_filter                          ! lowpass degree of polynomial filter
     149                 :             :         real(dp) :: tolerance                           ! tolerance on the residu to stop the minimization
     150                 :             :         real(dp) :: ramp                                ! bandpass filter tolerance
     151                 :             :         real(dp) :: ecut                                ! Ecut Fermi level
     152                 :             :         real(dp) :: mineig                              ! slightly larger than mineig_global
     153                 :             :         real(dp) :: mineig_global                       ! guaranteed lower spectral bound
     154                 :             :         real(dp) :: maxeig_global                       ! guaranteed upper spectral bound
     155                 :             : 
     156                 :             :         ! Arrays related to polynomial filtering
     157                 :             :         integer, allocatable :: neigen_per_slice(:)     ! total number of eigenpairs per slice
     158                 :             :         integer, allocatable :: poly_degrees(:)         ! polynomial filter degrees per slice
     159                 :             :         real(dp), allocatable :: low_bounds(:)          ! lower bounds in spectral partition (disjoint)
     160                 :             :         real(dp), allocatable :: upp_bounds(:)          ! upper bounds in spectral partition (disjoint)
     161                 :             : 
     162                 :             :     end type slice_t
     163                 :             : 
     164                 :             :     ! Public methods associated to 'slice' datatype
     165                 :             :     !-------------------------------------------------
     166                 :             :     public :: slice_init                                ! initialize slice datatype object
     167                 :             :     public :: slice_free                                ! free slice datatype object
     168                 :             :     public :: slice_run                                 ! run Spectrum Slicing for active slice task
     169                 :             : 
     170                 :             :     CONTAINS
     171                 :             : !=====================================================================
     172                 :             : !!***
     173                 :             : 
     174                 :             : !!****f* m_slice/slice_init
     175                 :             : !! NAME
     176                 :             : !! slice_init
     177                 :             : !!
     178                 :             : !! FUNCTION
     179                 :             : !! Initialize a 'slice' datastructure.
     180                 :             : !!
     181                 :             : !! INPUTS
     182                 :             : !!  nslice= number of spectral slices
     183                 :             : !!  neigenpairs= number of requested eigenvectors/eigenvalues
     184                 :             : !!  spacedim= space dimension for one vector
     185                 :             : !!  tolerance= tolerance criterion on the residu to stop the minimization
     186                 :             : !!  ecut= plane-wave cut-off energy
     187                 :             : !!  paral_kgb= flag controlling (k,g,bands) parallelization
     188                 :             : !!  bandpp= number of 'bands' handled by a processor
     189                 :             : !!  ndeg_filter= polynomial degree of the polynomial filter (.i.e. number of H applications)
     190                 :             : !!  is_lowpass= flag. True: use lowpass Chebyshev, false: use bandpass Heaviside expanded on Chebyshev
     191                 :             : !!  space= defines in which space we are (columns, rows, etc.)
     192                 :             : !!  eigenProblem= type of eigenpb: 1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
     193                 :             : !!  spacecom= MPI communicator
     194                 :             : !!  me_g0= 1 if this processors treats G=0, 0 otherwise
     195                 :             : !!  me_g0_ftt= 1 if this processors treats G=0 in FFT, 0 otherwise
     196                 :             : !!  paw= flag. TRUE if current calculation ses the PAW approach
     197                 :             : !!  comm_rows= "rows" communicator
     198                 :             : !!  comm_cols= "cols" communicator
     199                 :             : !!  gpu_option= flag. Enable GPU if true
     200                 :             : !!  gpu_kokkos_nthrd= number of OpenMP offloaded threads used
     201                 :             : !!  gpu_thread_limit= maximum number of OpenMP offloaded threads
     202                 :             : !!
     203                 :             : !! SOURCE
     204                 :             : 
     205                 :          18 : subroutine slice_init(slice,nslice,neigenpairs,spacedim,tolerance,paral_kgb,&
     206                 :             :         paral_slice,ndeg_filter,nbdbuf,ramp,ecut,bandpp,space,spacecom,me_g0,me_g0_fft,&
     207                 :             :         paw,comm_rows,comm_cols,spectral_cut,gpu_option,gpu_kokkos_nthrd,gpu_thread_limit)
     208                 :             : 
     209                 :             :     implicit none
     210                 :             : 
     211                 :             :     ! Arguments ------------------------------------
     212                 :             :     integer      , intent(in   ) :: bandpp
     213                 :             :     integer      , intent(in   ) :: nslice
     214                 :             :     integer      , intent(in   ) :: me_g0
     215                 :             :     integer      , intent(in   ) :: me_g0_fft
     216                 :             :     integer      , intent(in   ) :: neigenpairs
     217                 :             :     integer      , intent(in   ) :: comm_rows
     218                 :             :     integer      , intent(in   ) :: comm_cols
     219                 :             :     integer      , intent(in   ) :: paral_kgb
     220                 :             :     integer      , intent(in   ) :: paral_slice
     221                 :             :     integer      , intent(in   ) :: space
     222                 :             :     integer      , intent(in   ) :: spacecom
     223                 :             :     integer      , intent(in   ) :: spacedim
     224                 :             :     integer      , intent(in   ) :: ndeg_filter
     225                 :             :     integer      , intent(in   ) :: nbdbuf
     226                 :             :     integer      , intent(in   ) :: spectral_cut
     227                 :             :     integer      , intent(in   ) :: gpu_option
     228                 :             :     logical      , intent(in   ) :: paw
     229                 :             :     real(dp)     , intent(in   ) :: ramp
     230                 :             :     real(dp)     , intent(in   ) :: tolerance
     231                 :             :     real(dp)     , intent(in   ) :: ecut
     232                 :             :     type(slice_t), intent(inout) :: slice
     233                 :             :     integer      , intent(in   ), optional :: gpu_kokkos_nthrd
     234                 :             :     integer      , intent(in   ), optional :: gpu_thread_limit
     235                 :             : 
     236                 :             :     ! Local variables --------------------------------
     237                 :             :     integer :: total_spacedim, ierr
     238                 :             :     !logical :: on_host, on_device
     239                 :             : 
     240                 :             :     ! *********************************************************************
     241                 :             : 
     242                 :          18 :     slice%bandpp        = bandpp
     243                 :          18 :     slice%nslice        = nslice
     244                 :          18 :     slice%me_g0         = me_g0
     245                 :          18 :     slice%me_g0_fft     = me_g0_fft
     246                 :          18 :     slice%neigenpairs   = neigenpairs
     247                 :          18 :     slice%comm_rows     = comm_rows
     248                 :          18 :     slice%comm_cols     = comm_cols
     249                 :          18 :     slice%paral_kgb     = paral_kgb
     250                 :          18 :     slice%paral_slice   = paral_slice
     251                 :          18 :     slice%space         = space
     252                 :          18 :     slice%spacecom      = spacecom
     253                 :          18 :     slice%spacedim      = spacedim
     254                 :          18 :     slice%ndeg_filter   = ndeg_filter
     255                 :          18 :     slice%nbdbuf        = nbdbuf
     256                 :          18 :     slice%spectral_cut  = spectral_cut
     257                 :          18 :     slice%gpu_option    = gpu_option
     258                 :          18 :     slice%paw           = paw
     259                 :          18 :     slice%ramp          = ramp
     260                 :          18 :     slice%tolerance     = tolerance
     261                 :          18 :     slice%ecut          = ecut
     262                 :             : 
     263                 :          18 :     slice%gpu_kokkos_nthrd = 1
     264         [ +  - ]:          18 :     if (present(gpu_kokkos_nthrd)) then
     265                 :          18 :         slice%gpu_kokkos_nthrd = gpu_kokkos_nthrd
     266                 :             :     end if
     267                 :          18 :     slice%gpu_thread_limit = 0
     268         [ +  - ]:          18 :     if (present(gpu_thread_limit)) then
     269                 :          18 :         slice%gpu_thread_limit = gpu_thread_limit
     270                 :             :     end if
     271                 :             : 
     272                 :             :     ! Total number of rows (used in colsrows representation)
     273         [ +  + ]:          18 :     if (paral_kgb==0) then
     274                 :           2 :         slice%total_spacedim = spacedim
     275                 :             :     else
     276                 :          16 :         total_spacedim = spacedim
     277                 :          16 :         call xmpi_sum(total_spacedim, spacecom, ierr)
     278                 :          16 :         slice%total_spacedim = total_spacedim
     279                 :             :     end if
     280                 :             : 
     281                 :             :     ! Total number of processes
     282                 :          18 :     slice%nproc = xmpi_comm_size(spacecom)
     283                 :             : 
     284                 :             :     ! Arrays
     285                 :          18 :     call slice_allocateAll(slice)
     286                 :             : 
     287                 :          18 : end subroutine slice_init
     288                 :             : !!***
     289                 :             : 
     290                 :             : !----------------------------------------------------------------------
     291                 :             : 
     292                 :             : !!****f* m_slice/slice_allocateAll
     293                 :             : !! name
     294                 :             : !! slice_allocateAll
     295                 :             : 
     296                 :          18 : subroutine slice_allocateAll(slice)
     297                 :             : 
     298                 :             :     implicit none
     299                 :             :     type(slice_t), intent(inout) :: slice
     300                 :             : 
     301                 :             :     ! *********************************************************************
     302                 :             : 
     303                 :          18 :     call slice_free(slice)
     304                 :             : 
     305   [ +  -  -  +  :          54 :     ABI_MALLOC_IFNOT(slice%neigen_per_slice, (slice%nslice))
          +  -  +  -  +  
          -  -  +  -  +  
                   -  + ]
     306   [ +  -  -  +  :          54 :     ABI_MALLOC_IFNOT(slice%poly_degrees, (slice%nslice))
          +  -  +  -  +  
          -  -  +  -  +  
                   -  + ]
     307   [ +  -  -  +  :          54 :     ABI_MALLOC_IFNOT(slice%low_bounds, (slice%nslice))
          +  -  +  -  +  
          -  -  +  -  +  
                   -  + ]
     308   [ +  -  -  +  :          54 :     ABI_MALLOC_IFNOT(slice%upp_bounds, (slice%nslice))
          +  -  +  -  +  
          -  -  +  -  +  
                   -  + ]
     309                 :             : 
     310                 :          18 : end subroutine slice_allocateAll
     311                 :             : !!***
     312                 :             : 
     313                 :             : !----------------------------------------------------------------------
     314                 :             : 
     315                 :             : !!****f* m_slice/slice_free
     316                 :             : !! name
     317                 :             : !! slice_free
     318                 :             : 
     319                 :          36 : subroutine slice_free(slice)
     320                 :             : 
     321                 :             :     implicit none
     322                 :             :     type(slice_t), intent(inout) :: slice
     323                 :             : 
     324                 :             :     ! *********************************************************************
     325                 :             : 
     326         [ +  + ]:          36 :     ABI_SFREE(slice%neigen_per_slice)
     327         [ +  + ]:          36 :     ABI_SFREE(slice%poly_degrees)
     328         [ +  + ]:          36 :     ABI_SFREE(slice%low_bounds)
     329         [ +  + ]:          36 :     ABI_SFREE(slice%upp_bounds)
     330                 :             : 
     331                 :          36 : end subroutine slice_free
     332                 :             : !!***
     333                 :             : 
     334                 :             : !----------------------------------------------------------------------
     335                 :             : 
     336                 :             : !!****f* m_slice/slice_run
     337                 :             : !! NAME
     338                 :             : !! slice_run
     339                 :             : !!
     340                 :             : !! FUNCTION
     341                 :             : !! Run Spectrum slicing on a given set of active vectors.
     342                 :             : !! Computation uses marked resources for current task **only**.
     343                 :             : !!
     344                 :             : !! INPUTS
     345                 :             : !! X0=           size (spacedim, neigenpairs)
     346                 :             : !! eigen,residu= size (neigenpairs, 1) (column vectors)
     347                 :             : !! getAX_BX= pointer to the function giving A|X> and B|X>
     348                 :             : !!           A is typically the Hamiltonian H, and B the overlap operator S
     349                 :             : !! getBm1X= pointer to the function giving B^-1|X>
     350                 :             : !!          B is typically the overlap operator S
     351                 :             : !! nspinor= number of spinorial components of the wavefunctions
     352                 :             : !!
     353                 :             : !! SIDE EFFECTS
     354                 :             : !! slice <type(slice_t)>= memory workspace used for Spectrum slicing
     355                 :             : !!
     356                 :             : !! SOURCE
     357                 :             : 
     358                 :          18 : subroutine slice_run(slice, X0, getAX_BX, getBm1X, eigen, residu, nspinor)
     359                 :             : 
     360                 :             :     implicit none
     361                 :             : 
     362                 :             :     ! Arguments
     363                 :             :     type(slice_t), target, intent(inout) :: slice
     364                 :             :     type(xgBlock_t), intent(inout) :: X0     ! size (spacedim, neigenpairs)
     365                 :             :     type(xgBlock_t), intent(inout) :: eigen  ! size (neigenpairs,1)
     366                 :             :     type(xgBlock_t), intent(inout) :: residu ! size (neigenpairs,1)
     367                 :             :     integer, intent(in) :: nspinor
     368                 :             :     interface
     369                 :             :         subroutine getAX_BX(X,AX,BX)
     370                 :             :             use m_xg, only : xgBlock_t
     371                 :             :             type(xgBlock_t), intent(inout) :: X
     372                 :             :             type(xgBlock_t), intent(inout) :: AX
     373                 :             :             type(xgBlock_t), intent(inout) :: BX
     374                 :             :         end subroutine getAX_BX
     375                 :             :     end interface
     376                 :             :     interface
     377                 :             :         subroutine getBm1X(X,Bm1X)
     378                 :             :             use m_xg, only : xgBlock_t
     379                 :             :             type(xgBlock_t), intent(inout) :: X
     380                 :             :             type(xgBlock_t), intent(inout) :: Bm1X
     381                 :             :         end subroutine getBm1X
     382                 :             :     end interface
     383                 :             : 
     384                 :             :     ! Local scalars
     385                 :             :     integer :: tim_slice_me
     386                 :             :     integer :: nrows, ncols
     387                 :             :     integer :: space_res
     388                 :             :     !integer :: neigenpairs, bandpp, ndeg_filter
     389                 :             :     integer :: neigenpairs_ext
     390                 :             :     integer :: p_offset, ndeg_filter_max
     391                 :             :     !integer :: ierr
     392                 :             :     !real(dp) :: theta
     393                 :             :     real(dp) :: safe, tol ! for slice selection window
     394                 :             :     !logical :: is_lowpass, on_host, on_device ! todo use slice%..
     395                 :             :     ! ----> variables for logic of slice solver
     396                 :             :     type(matrixInfo_t) :: matrixInfo
     397                 :             :     type(xg_t) :: DivResults
     398                 :          18 :     type(activeTask_t) :: task
     399                 :          18 :     type(taskScheduler_t) :: scheduler
     400                 :          18 :     type(asyncMemory_t) :: asyncMemory
     401                 :             :     ! <-----
     402                 :             :     ! Arrays
     403                 :             :     !real(dp) :: tsec(2)
     404                 :          18 :     real(dp), allocatable :: moments(:)
     405                 :          18 :     logical, allocatable, target :: mapper(:,:)
     406                 :             : 
     407                 :             :     ! *********************************************************************
     408                 :             : 
     409                 :             :     tim_slice_me = tim_slice_X
     410                 :             :     select case(task%me_id_slice)
     411                 :             :     case(1)
     412                 :             :         tim_slice_me = tim_slice_1
     413                 :             :     case(2)
     414                 :             :         tim_slice_me = tim_slice_2
     415                 :             :     case(3)
     416                 :             :         tim_slice_me = tim_slice_3
     417                 :             :     end select
     418                 :             : 
     419                 :          18 :     nrows = slice%spacedim
     420                 :          18 :     ncols = slice%neigenpairs
     421                 :             :     if (slice%paral_kgb==1) then ! colsrows distribution
     422                 :             :         nrows = slice%total_spacedim
     423                 :             :         ncols = slice%bandpp
     424                 :             :     end if
     425                 :             : 
     426                 :          18 :     if (slice%space==SPACE_C) then
     427                 :          18 :         space_res = SPACE_C
     428         [ #  # ]:           0 :     else if (slice%space==SPACE_CR) then
     429                 :           0 :         space_res = SPACE_R
     430                 :             :     else
     431                 :           0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
     432                 :             :     end if
     433                 :             : 
     434                 :          18 :     call xg_init(DivResults, space_res, slice%neigenpairs, 1, gpu_option=slice%gpu_option)
     435                 :             : 
     436                 :             :     call init_matrixInfo(matrixInfo, slice%comm_rows, slice%comm_cols, slice%spacecom, &
     437                 :             :         slice%neigenpairs,slice%total_spacedim, slice%spacedim, slice%space, &
     438                 :             :         slice%gpu_kokkos_nthrd, slice%gpu_thread_limit,slice%gpu_option, slice%paral_kgb, &
     439                 :          18 :         slice%me_g0, slice%me_g0_fft, nspinor)
     440                 :             : 
     441                 :          18 :     write(std_out,*) 'in slice_run'
     442                 :          18 :     write(std_out,*) 'array of eigenvalues', rows(eigen), cols(eigen)
     443                 :          18 :     flush(std_out)
     444                 :             : 
     445                 :             :     ! ============================= Prepare spectral slices =====================================
     446                 :             : 
     447                 :             :     !call timab(tim_slice_sched,1,tsec) ! fixme those timers
     448                 :             :     !ABI_NVTX_START_RANGE(NVTX_SLICE_SCHEDULE) ! fixme those markers
     449                 :             : 
     450                 :          18 :     ndeg_filter_max = 10 ! todo IML autotune based on the presence of oscillations
     451         [ -  + ]:          18 :     ABI_MALLOC(moments, (ndeg_filter_max+1))
     452                 :             : 
     453                 :             :     !ABI_NVTX_START_RANGE(NVTX_SLICE_RRQ)
     454                 :             :     call slice_getSpectralInfo(slice, X0, matrixInfo, moments, DivResults%self, residu, &
     455                 :          18 :         getAX_BX, getBm1X)
     456                 :             :     !ABI_NVTX_END_RANGE()
     457                 :             : 
     458                 :             :     !ABI_NVTX_END_RANGE()
     459                 :             :     !call timab(tim_slice_sched,2,tsec)
     460                 :             : 
     461                 :          18 :     call slice_splitSpectrum(slice, moments)
     462         [ -  + ]:          18 :     ABI_FREE(moments)
     463                 :             : 
     464                 :             :     ! Attribute column vectors of X0 to slices using query results
     465   [ -  +  +  -  :          72 :     ABI_MALLOC(mapper, (slice%neigenpairs, slice%nslice))
          -  +  +  -  +  
          -  +  -  -  +  
             -  +  -  + ]
     466   [ +  +  +  + ]:        6966 :     mapper = .false.
     467                 :          18 :     write(std_out,*) 'tolerance in residual window=', slice%tolerance
     468                 :          18 :     flush(std_out)
     469                 :             : 
     470                 :          18 :     safe = 2.d0
     471                 :          18 :     tol = 1e-2 ! slice%tolerance
     472                 :          18 :     call slice_applySelectionWindow(slice, mapper, DivResults%self, residu, tol, safe)
     473                 :             : 
     474                 :          18 :     write(std_out,*) 'created the following map slices to cols='
     475                 :          18 :     write(std_out,*) mapper(1,:)
     476                 :          18 :     flush(std_out)
     477                 :             : 
     478                 :             :     ! Include m+p where p offset 10%
     479                 :          18 :     p_offset = 0.1d0
     480                 :          18 :     slice%neigen_per_slice = ceiling(slice%neigen_per_slice*(1.d0+p_offset))
     481         [ +  + ]:          54 :     neigenpairs_ext = sum(slice%neigen_per_slice)
     482                 :             : 
     483                 :          18 :     write(std_out,*) 'allocating async memory of size', neigenpairs_ext
     484                 :          18 :     flush(std_out)
     485                 :             : 
     486                 :             :     ! Allocate extended buffer in Linalg representation. Notice spacecom communicator (global)
     487                 :          18 :     call slice_task_allocAsyncMemory(asyncMemory, matrixInfo, neigenpairs_ext)
     488                 :             : 
     489                 :             :     ! Init extended buffer with vectors from X or random vectors. This part also uses global comm.
     490                 :          18 :     call slice_task_copyToAsyncMemory(asyncMemory, X0, matrixInfo, mapper, slice%neigen_per_slice)
     491                 :             : 
     492                 :          18 :     write(std_out,*) 'getid after init', xgBlock_getid(asyncMemory%XextLinalg)
     493                 :          18 :     flush(std_out)
     494                 :             : 
     495                 :             :     ! =========================== MPI distribution for slices ==================================
     496                 :             : 
     497                 :             :     ! MPI phase I: Compute 'process-to-slice(task)' distribution according to paral options
     498                 :             :     call slice_task_initSchedule(scheduler, slice%nslice, slice%nproc, slice%neigen_per_slice,&
     499                 :          18 :         slice%paral_kgb, slice%paral_slice)
     500                 :             :     ! /IML\ in here there should be some per-rank parameter called slice%neigen_per_slice
     501                 :             :     ! that is updated along slice iterations
     502                 :             :     ! also nslice should be rank-wise as well
     503                 :             : 
     504                 :          18 :     call slice_task_printSchedule(scheduler, std_out)
     505                 :             : 
     506                 :             :     ! MPI phase II: Compute 'slice columns(load)-to-process' distribution for next task
     507                 :             :     ! and apply schedule to distribute the async memory to processes
     508                 :          18 :     call slice_task_initNextTask(scheduler, task, matrixInfo)
     509                 :          18 :     call slice_task_enableAsync(asyncMemory, task, matrixInfo)
     510                 :             : 
     511                 :             :     !!! ^------- start region containing data on slice only --------^
     512                 :             : 
     513                 :             :     ! ============================ Active task execution =======================================
     514                 :             : 
     515                 :             :     ! IML is here
     516                 :             :     ! pass explicit slice parameters such as degree, lowb, uppb
     517                 :             :     ! call slice_task_runActiveTask(task...)
     518                 :             : 
     519                 :             :     ! if (paral_slice==yes) then
     520                 :             :     !! exit
     521                 :             :     !! otherwise, update slice%neigen_per_slice etc
     522                 :             : 
     523                 :             :     !
     524                 :             : !    call timab(tim_slice_me,1,tsec)
     525                 :             : !
     526                 :             : !    if (slice%paral_kgb==0 .or. slice%paral_slice==DISABLE_PARAL) then
     527                 :             : !        ! execute active tasks sequentially
     528                 :             : !
     529                 :             : !        do islice=1, nslice
     530                 :             : !            if (task%active(islice)) then                   ! <--- normally it should not be that different..
     531                 :             : !            call schedule_next_task(schedule, neigenpairs)
     532                 :             : !            call init_active_memory(asyncMemory, task, X0, p)
     533                 :             : !            call execute_active_task(task)
     534                 :             : !            call mask_active_task(task, tol) ! mask extendedMem
     535                 :             : !        end do
     536                 :             : !
     537                 :             : !    else
     538                 :             : !        ! execute active tasks in parallel
     539                 :             : !
     540                 :             : !        call init_active_memory(asyncMemory, task, X0, p)
     541                 :             : !        call execute_active_task(task)
     542                 :             : !        call mask_active_task(task, tol) ! mask extendedMem
     543                 :             : !
     544                 :             : !    end if
     545                 :             : !
     546                 :             : !    ! Copy to spectrum memory only when active tasks have finished
     547                 :             : !    call compress_extended_memory(work) ! extendendMem -> spectrumMem
     548                 :             : !
     549                 :             : !
     550                 :             : !    call free_schedule(schedule)
     551                 :             : !
     552                 :             : !
     553                 :             : !
     554                 :             : !    ! Free temporary memory
     555                 :             : !    call chebfi_free(chebfi)
     556                 :             : !    ABI_SFREE(nrowsLinalg)
     557                 :             : !
     558                 :             : !    ! Timer is BEFORE the barrier !!
     559                 :             : !    call timab(tim_slice_me,2,tsec)
     560                 :             : !
     561         [ -  + ]:          18 :     ABI_FREE(mapper)
     562                 :          18 :     call xg_free(DivResults)
     563                 :          18 :     call slice_task_freeAsyncMemory(asyncMemory)
     564                 :          18 :     call slice_task_freeSchedule(scheduler)
     565                 :          18 :     call slice_task_freeActiveTask(task)
     566                 :             : 
     567   [ +  -  -  +  :          36 : end subroutine slice_run
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                      + ]
     568                 :             : !!***
     569                 :             : 
     570                 :             : !----------------------------------------------------------------------
     571                 :             : 
     572                 :             : !!****f* m_slice/slice_getSpectralInfo
     573                 :             : !! NAME
     574                 :             : !! slice_getSpectralInfo
     575                 :             : !!
     576                 :             : !! FUNCTION
     577                 :             : !! Approximate eigenvalue spectrum and query input X for Ritz values and residuals.
     578                 :             : !! This is a Hamiltonian-application-based approximation.
     579                 :             : !! Inner calculations use colsrows representation to apply the Hamiltonian.
     580                 :             : !!
     581                 :             : !! INPUTS
     582                 :             : !! X        =eigenvector guess
     583                 :             : !! getAX_BX =Hamiltonian application
     584                 :             : !!
     585                 :             : !! SOURCE
     586                 :             : 
     587         [ -  + ]:          18 : subroutine slice_getSpectralInfo(slice, X, matrixInfo, moments, eigen, resid, getAX_BX, getBm1X)
     588                 :             : 
     589                 :             :     implicit none
     590                 :             : 
     591                 :             :     ! Arguments
     592                 :             :     type(slice_t), intent(inout) :: slice
     593                 :             :     type(xgBlock_t), intent(inout) :: X
     594                 :             :     type(matrixInfo_t), intent(in) :: matrixInfo
     595                 :             :     real(dp), intent(inout) :: moments(:)
     596                 :             :     type(xgBlock_t), intent(inout) :: eigen
     597                 :             :     type(xgBlock_t), intent(inout) :: resid
     598                 :             :     interface
     599                 :             :         subroutine getAX_BX(X,AX,BX)
     600                 :             :             use m_xg, only : xgBlock_t
     601                 :             :             type(xgBlock_t), intent(inout) :: X
     602                 :             :             type(xgBlock_t), intent(inout) :: AX
     603                 :             :             type(xgBlock_t), intent(inout) :: BX
     604                 :             :         end subroutine getAX_BX
     605                 :             :     end interface
     606                 :             :     interface
     607                 :             :         subroutine getBm1X(X,Bm1X)
     608                 :             :             use m_xg, only : xgBlock_t
     609                 :             :             type(xgBlock_t), intent(inout) :: X
     610                 :             :             type(xgBlock_t), intent(inout) :: Bm1X
     611                 :             :         end subroutine getBm1X
     612                 :             :     end interface
     613                 :             : 
     614                 :             :     ! Local variables
     615                 :             :     ! Scalars
     616                 :             :     integer :: spacedim, tot_spacedim, nspinor
     617                 :             :     integer :: ndeg_filter_max, neigenpairs
     618                 :             :     integer :: ierr
     619                 :             :     !integer :: ideg
     620                 :             :     integer :: kmax
     621                 :             :     integer :: m_probe
     622                 :             :     integer :: my_shift, my_rank
     623                 :             :     integer :: space, spacecom, gpu_option
     624                 :             :     !integer :: k_sketch
     625                 :             :     real(dp) :: lambda_min, res_norm
     626                 :             :     !real(dp) :: center, radius
     627                 :             :     real(dp) :: lowb!, mineig, maxeig
     628                 :             :     real(dp) :: lanczos_lowb, lanczos_lowb_global
     629                 :             :     ! Derived types
     630                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     631                 :             :     integer :: me_g0
     632                 :             :     type(xg_t) :: W_dummy
     633                 :             :     integer :: work_size
     634                 :             : #endif
     635                 :             :     !type(xg_t) :: BX
     636                 :             :     type(xgBlock_t) :: xXColsRows
     637                 :             :     type(xgBlock_t) :: eigen_me, resid_me
     638                 :          18 :     type(xgTransposer_t) :: xgTransposerX
     639                 :             :     ! Arrays
     640                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     641                 :             :     real(dp) :: tsec(2)
     642                 :             : #endif
     643                 :             :     ! *********************************************************************
     644                 :             : 
     645                 :          18 :     neigenpairs = slice%neigenpairs
     646                 :          18 :     tot_spacedim = slice%total_spacedim
     647                 :          18 :     spacedim = slice%spacedim
     648                 :          18 :     gpu_option = slice%gpu_option
     649                 :          18 :     spacecom = slice%spacecom
     650                 :          18 :     space = slice%space
     651                 :          18 :     nspinor = matrixInfo%nspinor
     652                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     653                 :             :     me_g0 = slice%me_g0
     654                 :             :     if (slice%paral_kgb==1) then
     655                 :             :         me_g0 = slice%me_g0_fft
     656                 :             :     end if
     657                 :             : #endif
     658                 :             : 
     659                 :             :     ! ============== Transpose ==============
     660                 :          18 :     if (slice%paral_kgb==1) then
     661                 :             : 
     662                 :             :         ! Allocate memory for X in colsrows representation
     663                 :             :         call xgTransposer_constructor(xgTransposerX, X, xXColsRows, nspinor, STATE_LINALG,&
     664                 :             :             TRANS_ALL2ALL, slice%comm_rows, slice%comm_cols, 0, 0, slice%me_g0_fft,&
     665                 :          16 :             gpu_option=slice%gpu_option, gpu_thread_limit=slice%gpu_thread_limit)
     666                 :             : 
     667                 :          16 :         xgTransposerX%gpu_kokkos_nthrd  = slice%gpu_kokkos_nthrd
     668                 :             : 
     669                 :             :         !call xmpi_barrier(slice%spacecom)
     670                 :             :         ABI_NVTX_START_RANGE(NVTX_SLICE_TRANSPOSE)
     671                 :          16 :         call xgTransposer_transpose(xgTransposerX, STATE_COLSROWS)
     672                 :             :         ABI_NVTX_END_RANGE()
     673                 :             : 
     674                 :             :     else
     675                 :             : 
     676                 :             :         ! Use colsrows notion instead of X notion
     677                 :           2 :         call xgBlock_setBlock(X, xXColsRows, spacedim, neigenpairs)
     678                 :             : 
     679                 :             :     end if
     680                 :             : 
     681                 :             :     ! Prevent invovl error
     682                 :             :     ! dummy invovl calculation to allocate buffers of full size
     683                 :             :     ! Workaround: getBm1X error related to invovl allocated buffers.
     684                 :             :     ! With this setup we allocate large then use 1 in Lanczos.
     685                 :             :     ! The inverse is not possible with current implementation. This order allows to avoid
     686                 :             :     ! make_invovl for 1 vector then make_invovl for nband vectors.
     687                 :             : #ifdef HAVE_OPENMP_OFFLOAD
     688                 :             :     if (slice%paw) then
     689                 :             :         work_size = slice%neigenpairs ! fixme will complain
     690                 :             :         call xg_init(W_dummy, slice%space, tot_spacedim, work_size, xmpi_comm_null, &
     691                 :             :             me_g0=me_g0, gpu_option=slice%gpu_option)
     692                 :             :         call timab(tim_invovl, 1, tsec)
     693                 :             :         ABI_NVTX_START_RANGE(NVTX_CHEBFI2_GET_BM1X)
     694                 :             :         call getBm1X(W_dummy%self, W_dummy%self)
     695                 :             :         ABI_NVTX_END_RANGE()
     696                 :             :         call timab(tim_invovl, 2, tsec)
     697                 :             :         call xg_free(W_dummy)
     698                 :             :     end if
     699                 :             : #endif
     700                 :             : 
     701                 :          18 :     kmax = 30
     702                 :          18 :     call computeBLanczos(matrixInfo, slice%paw, getAX_BX, getBm1X, kmax, lambda_min, res_norm)
     703                 :             : 
     704                 :          18 :     lanczos_lowb = lambda_min - res_norm
     705                 :          18 :     call xmpi_min(lanczos_lowb,lanczos_lowb_global,slice%spacecom,ierr)
     706                 :          18 :     lowb = lanczos_lowb_global
     707                 :             : 
     708                 :          18 :     write(std_out,*) 'Lanczos lambda_min=', lambda_min
     709                 :          18 :     write(std_out,*) 'Lanczos res_norm  =', res_norm
     710                 :          18 :     write(std_out,*) 'Lanczos guarantee =', lanczos_lowb
     711                 :          18 :     write(std_out,*) 'Lanczos guarantee(global) =', lanczos_lowb_global
     712                 :          18 :     flush(std_out)
     713                 :             : 
     714                 :             :     ! Perform sensitivity study of trace estimation for these parameters
     715                 :             :     ! Keep m_probe small allows to reduce noise
     716                 :          18 :     m_probe = 5
     717                 :          18 :     ndeg_filter_max = size(moments) - 1
     718                 :          18 :     write(std_out,*) 'Here I compute Stochastic Trace Estimation'
     719                 :          18 :     write(std_out,*) 'm_probe=    ', m_probe
     720                 :          18 :     write(std_out,*) 'ndeg_filter=', ndeg_filter_max
     721                 :          18 :     flush(std_out)
     722                 :             : 
     723                 :             :     call computeTraceEstimation(matrixInfo, slice%ecut, slice%paw, slice%tolerance, &
     724                 :          18 :         getAX_BX, getBm1X, ndeg_filter_max, m_probe, lanczos_lowb_global, moments)
     725                 :             : 
     726                 :             :     ! Define working spectrum to be splitted to slices
     727                 :          18 :     slice%mineig = lanczos_lowb
     728                 :          18 :     slice%mineig_global = lanczos_lowb_global
     729                 :          18 :     slice%maxeig_global = slice%ecut
     730                 :             : 
     731                 :          18 :     write(std_out,*) 'STE exited'
     732                 :          18 :     flush(std_out)
     733                 :             : 
     734                 :             :     ! Compute Rayleigh quotients (colsrows distribution) ! fixme timers
     735                 :             :     !ABI_NVTX_START_RANGE(NVTX_CHEBFI2_RRQ)
     736                 :             :     !call timab(tim_RR_q, 1, tsec)
     737                 :             : 
     738         [ +  + ]:          18 :     if (slice%paral_kgb==1) then
     739                 :          16 :         my_rank = xmpi_comm_rank(slice%spacecom)
     740                 :          16 :         my_shift = my_rank * slice%bandpp
     741                 :          16 :         call xgBlock_reshape(eigen, 1, slice%neigenpairs)
     742                 :          16 :         call xgBlock_reshape(resid, 1, slice%neigenpairs)
     743                 :          16 :         call xgBlock_setBlock(eigen, eigen_me, 1, slice%bandpp, fcol=my_shift+1)
     744                 :          16 :         call xgBlock_setBlock(resid, resid_me, 1, slice%bandpp, fcol=my_shift+1)
     745                 :          16 :         call xgBlock_reshape(eigen, slice%neigenpairs, 1)
     746                 :          16 :         call xgBlock_reshape(resid, slice%neigenpairs, 1)
     747                 :          16 :         call xgBlock_reshape(eigen_me, slice%bandpp, 1)
     748                 :          16 :         call xgBlock_reshape(resid_me, slice%bandpp, 1)
     749                 :             :     else
     750                 :           2 :         call xgBlock_setBlock(eigen, eigen_me, rows(eigen), 1)
     751                 :           2 :         call xgBlock_setBlock(resid, resid_me, rows(resid), 1)
     752                 :             :     end if
     753                 :             : 
     754                 :          18 :     call slice_queryCandidates(slice, xXColsRows, eigen_me, resid_me, getAX_BX)
     755                 :             :     !call timab(tim_RR_q, 2, tsec)
     756                 :             :     !ABI_NVTX_END_RANGE()
     757                 :             : 
     758                 :          18 :     call xgBlock_mpi_sum(eigen, comm=slice%spacecom)
     759                 :          18 :     call xgBlock_mpi_sum(resid, comm=slice%spacecom)
     760                 :             : 
     761                 :             :     ! ============== Transpose ==============
     762         [ +  + ]:          18 :     if (slice%paral_kgb == 1) then
     763                 :          16 :         call xmpi_barrier(slice%spacecom)
     764                 :             :         ABI_NVTX_START_RANGE(NVTX_SLICE_TRANSPOSE)
     765                 :          16 :         call xgTransposer_transpose(xgTransposerX, STATE_LINALG)
     766                 :             :         ABI_NVTX_END_RANGE()
     767                 :             : 
     768                 :             :         ! reset buffers to right address
     769         [ -  + ]:          16 :         if (xmpi_comm_size(slice%spacecom) == 1) then
     770                 :           0 :             call xgBlock_setBlock(xXColsRows, X, spacedim, neigenpairs)
     771                 :             :         end if
     772                 :             :     else
     773                 :           2 :         call xgBlock_setBlock(xXColsRows, X, spacedim, neigenpairs)
     774                 :             :     end if
     775                 :             : 
     776         [ +  + ]:          18 :     if (slice%paral_kgb == 1) then
     777                 :          16 :         call xgTransposer_free(xgTransposerX)
     778                 :             :     end if
     779                 :             : 
     780   [ +  +  -  + ]:          36 : end subroutine slice_getSpectralInfo
     781                 :             : !!***
     782                 :             : 
     783                 :             : !----------------------------------------------------------------------
     784                 :             : 
     785                 :             : !!****f* m_slice/slice_queryCandidates
     786                 :             : !! NAME
     787                 :             : !! slice_queryCandidates
     788                 :             : !!
     789                 :             : !! FUNCTION
     790                 :             : !! Compute Rayleigh-Ritz quotients and residuals in colsrows MPI representation.
     791                 :             : !! Return bandpp indicators per MPI process.
     792                 :             : !! These two indicators are useful to rank candidates per slices.
     793                 :             : !!
     794                 :             : !! SOURCE
     795                 :             : 
     796                 :          18 : subroutine slice_queryCandidates(slice, xXColsRows, eigen, resid, getAX_BX)
     797                 :             : 
     798                 :             :     implicit none
     799                 :             : 
     800                 :             :     !Arguments ------------------------------------
     801                 :             :     type(slice_t), intent(inout) :: slice
     802                 :             :     type(xgBlock_t), intent(inout) :: xXColsRows
     803                 :             :     type(xgBlock_t), intent(inout) :: eigen
     804                 :             :     type(xgBlock_t), intent(inout) :: resid
     805                 :             :     interface
     806                 :             :         subroutine getAX_BX(X,AX,BX)
     807                 :             :             use m_xg, only : xgBlock_t
     808                 :             :             type(xgBlock_t), intent(inout) :: X
     809                 :             :             type(xgBlock_t), intent(inout) :: AX
     810                 :             :             type(xgBlock_t), intent(inout) :: BX
     811                 :             :         end subroutine getAX_BX
     812                 :             :     end interface
     813                 :             : 
     814                 :             :     !Local variables-------------------------------
     815                 :             :     type(xg_t) :: XAB
     816                 :             :     type(xg_t) :: Results1
     817                 :             :     type(xg_t) :: Results2
     818                 :             :     type(xg_t) :: norml
     819                 :             :     type(xgBlock_t) :: xAXColsRows
     820                 :             :     type(xgBlock_t) :: xBXColsRows
     821                 :             :     type(xgBlock_t) :: xRXColsRows
     822                 :             :     integer :: space_res
     823                 :             :     integer :: me_g0, nrows, ncols, gpu_option
     824                 :             :     real(dp) :: tsec(2)
     825                 :             : 
     826                 :             :     ! *********************************************************************
     827                 :             : 
     828                 :          18 :     if (slice%space==SPACE_C) then
     829                 :          18 :         space_res = SPACE_C
     830         [ #  # ]:           0 :     else if (slice%space==SPACE_CR) then
     831                 :           0 :         space_res = SPACE_R
     832                 :             :     else
     833                 :           0 :         ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
     834                 :             :     end if
     835                 :             : 
     836                 :          18 :     ncols = slice%bandpp
     837                 :          18 :     nrows = rows(xXColsRows)
     838                 :          18 :     me_g0 = slice%me_g0
     839                 :          18 :     gpu_option = slice%gpu_option
     840         [ +  + ]:          18 :     if (slice%paral_kgb==1) then
     841                 :             :         ncols = slice%bandpp
     842                 :          16 :         nrows = slice%total_spacedim
     843                 :          16 :         me_g0 = slice%me_g0_fft
     844                 :             :     end if
     845                 :          18 :     call xg_init(Results1, space_res, ncols, 1, gpu_option=slice%gpu_option)
     846                 :          18 :     call xg_init(Results2, space_res, ncols, 1, gpu_option=slice%gpu_option)
     847                 :          18 :     call xg_init(norml, SPACE_R, slice%bandpp, 1)
     848                 :             : 
     849                 :          18 :     call xg_init(XAB,slice%space,nrows,3*ncols,slice%spacecom,me_g0=me_g0,gpu_option=gpu_option)
     850                 :          18 :     call xg_setBlock(XAB, xAXColsRows, nrows, ncols)
     851                 :          18 :     call xg_setBlock(XAB, xBXColsRows, nrows, ncols, fcol=ncols+1)
     852                 :          18 :     call xg_setBlock(XAB, xRXColsRows, nrows, ncols, fcol=2*ncols+1)
     853                 :             : 
     854                 :             :     ! Compute A*Psi
     855                 :          18 :     call timab(tim_getAX_BX,1,tsec)
     856                 :             :     ABI_NVTX_START_RANGE(NVTX_SLICE_GET_AX_BX)
     857                 :          18 :     call getAX_BX(xXColsRows, xAXColsRows, xBXColsRows)
     858                 :          18 :     call xgBlock_zero_im_g0(xAXColsRows)
     859                 :          18 :     call xgBlock_zero_im_g0(xBXColsRows)
     860                 :             :     ABI_NVTX_END_RANGE()
     861                 :          18 :     call timab(tim_getAX_BX,2,tsec)
     862                 :             : 
     863                 :             :     ! <Psi|H|Psi>
     864                 :          18 :     call xgBlock_colwiseDotProduct(xXColsRows, xAXColsRows, Results1%self, comm_loc=xmpi_comm_null)
     865                 :             : 
     866                 :             :     ! <Psi|S|Psi>
     867                 :          18 :     call xgBlock_colwiseDotProduct(xXColsRows, xBXColsRows, Results2%self, comm_loc=xmpi_comm_null)
     868                 :             : 
     869                 :             :     ! eig = <Psi|H|Psi> / <Psi|S|Psi>
     870                 :          18 :     call xgBlock_colwiseDivision(Results1%self, Results2%self, eigen)
     871                 :             : 
     872                 :             :     ! xRXColsRows = S|Psi>
     873                 :          18 :     call xgBlock_copy(xBXColsRows,xRXColsRows)
     874                 :             :     ! xRXColsRows = - eigen * S|Psi>
     875                 :          18 :     call xgBlock_ymax(xRXColsRows,eigen,0,1)
     876                 :             :     ! norml = |eigen*S|Psi>|^2
     877                 :          18 :     call xgBlock_colwiseNorm2(xBXColsRows, norml%self, comm_loc=xmpi_comm_null)
     878                 :             :     ! xRXColsRows = H|Psi> - eigen * S|Psi>
     879                 :          18 :     call xgBlock_add(xRXColsRows,xAXColsRows)
     880                 :             :     ! resid = |xRXColsRows|^2
     881                 :          18 :     call xgBlock_colwiseNorm2(xRXColsRows, resid, comm_loc=xmpi_comm_null)
     882                 :             : 
     883                 :             :     ! compute relative resid=resid/(|eigen|*|BX|)^2
     884                 :             :     ! scales with the eigenvalue
     885                 :          18 :     call xgBlock_colwiseDivision(resid, norml%self, resid)
     886                 :             : 
     887                 :          18 :     call xg_free(Results1)
     888                 :          18 :     call xg_free(Results2)
     889                 :          18 :     call xg_free(XAB)
     890                 :          18 :     call xg_free(norml)
     891                 :             : 
     892         [ +  - ]:          18 : end subroutine slice_queryCandidates
     893                 :             : !!***
     894                 :             : 
     895                 :             : !----------------------------------------------------------------------
     896                 :             : 
     897                 :             : !!****f* m_slice/slice_unitTest
     898                 :             : !! NAME
     899                 :             : !! slice_unitTest
     900                 :             : !!
     901                 :             : !! FUNCTION
     902                 :             : !! Given a set of vectors X computes the columnwise norm squared, on:
     903                 :             : !! - CPU sequential,
     904                 :             : !! - CPU MPI,
     905                 :             : !! - GPU sequential (if GPU available),
     906                 :             : !! - GPU MPI (if GPU available).
     907                 :             : !! Checks that all four are the same.
     908                 :             : !!
     909                 :             : !! SOURCE
     910                 :             : 
     911                 :             : function slice_unitTest(X) result(ierr)
     912                 :             : 
     913                 :             :     implicit none
     914                 :             : 
     915                 :             :     !Arguments ------------------------------------
     916                 :             :     type(xgBlock_t), intent(in) :: X
     917                 :             :     integer                     :: ierr
     918                 :             : 
     919                 :             :     !Local variables-------------------------------
     920                 :             :     integer :: nrows,ncols
     921                 :             :     integer :: comm
     922                 :             :     integer :: gpu_option
     923                 :             :     real(dp) :: id_cpu, id_from_gpu, id_to_gpu
     924                 :             : 
     925                 :             :     ! *********************************************************************
     926                 :             : 
     927                 :             :     ! Get nrows, nrcols, gpu_option of X
     928                 :             :     call xgBlock_getSize(X,nrows,ncols)
     929                 :             :     call xgBlock_get_gpu_option(X,gpu_option)
     930                 :             :     call xgBlock_get_communicator(X,comm)
     931                 :             :     ! above this is just comm(X)
     932                 :             :     write(std_out,*) '<--*--> Start unitary test for matrix'
     933                 :             :     write(std_out,*) 'nrows       =', nrows
     934                 :             :     write(std_out,*) 'ncols       =', ncols
     935                 :             :     write(std_out,*) 'gpu_option  =', gpu_option
     936                 :             :     write(std_out,*) 'communicator=', comm
     937                 :             : 
     938                 :             :     id_cpu = -1.0d0
     939                 :             :     id_from_gpu = -1.0d0
     940                 :             :     id_to_gpu = -1.0d0
     941                 :             : 
     942                 :             :     if (gpu_option==ABI_GPU_DISABLED) then
     943                 :             :         id_cpu = xgBlock_getid(X, comm)
     944                 :             :         write(std_out,*) 'id_cpu     =', id_cpu
     945                 :             :     end if
     946                 :             : 
     947                 :             : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
     948                 :             :     if (gpu_option/=ABI_GPU_DISABLED) then
     949                 :             :         call xgBlock_copy_from_gpu(X)
     950                 :             :         id_from_gpu = xgBlock_getid(X, comm)
     951                 :             :         call xgBlock_copy_to_gpu(X)
     952                 :             :         write(std_out,*) 'id_from_gpu=', id_from_gpu
     953                 :             :     else
     954                 :             :         call xgBlock_copy_to_gpu(X)
     955                 :             :         call xgBlock_copy_from_gpu(X)
     956                 :             :         id_to_gpu = xgBlock_getid(X, comm)
     957                 :             :         call xgBlock_copy_to_gpu(X)
     958                 :             :         call xgBlock_copy_from_gpu(X)
     959                 :             :         write(std_out,*) 'id_to_gpu  =', id_to_gpu
     960                 :             :     end if
     961                 :             : #endif
     962                 :             : 
     963                 :             :     ! TODO getid on xmpi_comm_null
     964                 :             :     ! then sum across comm
     965                 :             :     ! should give the same as
     966                 :             :     ! getid on comm
     967                 :             :     ! this is useful for MPI
     968                 :             : 
     969                 :             :     ierr = 0
     970                 :             :     if (id_cpu < 0) ierr = -1
     971                 :             :     if (id_from_gpu < 0) ierr = -1
     972                 :             :     if (id_to_gpu < 0) ierr = -1
     973                 :             : 
     974                 :             : end function slice_unitTest
     975                 :             : !!***
     976                 :             : 
     977                 :             : !----------------------------------------------------------------------
     978                 :             : 
     979                 :             : !!****f* m_slice/slice_splitSpectrum
     980                 :             : !! NAME
     981                 :             : !! slice_splitSpectrum
     982                 :             : !!
     983                 :             : !! FUNCTION
     984                 :             : !! Split working spectrum [a,b) mapped to [-1,1) with center and radius.
     985                 :             : !!
     986                 :             : !! INPUT
     987                 :             : !! a= slice%mineig_global
     988                 :             : !! b= slice%maxeig_global
     989                 :             : !!
     990                 :             : !! SIDE EFFECTS
     991                 :             : !! slice%low_bounds
     992                 :             : !! slice%upp_bounds
     993                 :             : !! slice%neigen_per_slice
     994                 :             : !!
     995                 :             : !! SOURCE
     996                 :             : 
     997         [ -  + ]:          18 :   subroutine slice_splitSpectrum(slice, moments)
     998                 :             : 
     999                 :             :       implicit none
    1000                 :             : 
    1001                 :             :       ! Arguments ------------------------------------
    1002                 :             :       type(slice_t), intent(inout) :: slice
    1003                 :             :       real(dp), intent(inout) :: moments(:)
    1004                 :             : 
    1005                 :             :       ! Local variables --------------------------------
    1006                 :             :       integer :: uppb_loc, ib
    1007                 :             :       integer :: ngrid_fine, ngrid_coarse
    1008                 :             :       integer :: half_index, i_left, i_right
    1009                 :             :       integer :: i_split, num_moments
    1010                 :             :       logical :: gap_left, gap_right
    1011                 :             :       real(dp) :: a, b
    1012                 :             :       real(dp) :: center, radius
    1013                 :             :       real(dp) :: step_fine, step_coarse
    1014                 :             :       real(dp) :: partial_mass, half_mass
    1015                 :             :       real(dp) :: b_scaled
    1016                 :             :       real(dp) :: mass_left, mass_right
    1017                 :             :       real(dp) :: lambda_plus_wanted
    1018                 :          18 :       real(dp), allocatable :: cumm_eigen_count(:)
    1019                 :          18 :       real(dp), allocatable :: bgrid_fine(:)
    1020                 :          18 :       real(dp), allocatable :: bgrid_coarse(:)
    1021                 :          18 :       real(dp), allocatable :: work(:)
    1022                 :             :       character(len=500) :: msg
    1023                 :             : 
    1024                 :             :     ! *********************************************************************
    1025                 :             : 
    1026         [ -  + ]:          18 :       if (slice%nslice/=2) then
    1027                 :           0 :           ABI_ERROR("spectral bidirectional split not yet implemented for 3 slices")
    1028                 :             :       end if
    1029                 :             : 
    1030                 :          18 :       ngrid_coarse = 10 ! coarse, just to find uppb, hardcoded
    1031                 :          18 :       ngrid_fine = 30 ! used for cumulative eigenvalue count, hardcoded
    1032                 :             : 
    1033                 :          18 :       a = slice%mineig_global
    1034                 :          18 :       b = slice%maxeig_global
    1035                 :             : 
    1036                 :          18 :       num_moments = size(moments)
    1037   [ -  +  +  -  :          54 :       ABI_MALLOC(work, (num_moments))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
    1038         [ -  + ]:          18 :       ABI_MALLOC(bgrid_coarse, (ngrid_coarse))
    1039         [ -  + ]:          18 :       ABI_MALLOC(bgrid_fine, (ngrid_fine))
    1040         [ -  + ]:          18 :       ABI_MALLOC(cumm_eigen_count, (ngrid_fine))
    1041                 :             : 
    1042                 :          18 :       center = (a + b) / 2.d0
    1043                 :          18 :       radius = (b - a) / 2.d0
    1044                 :             : 
    1045                 :             :       ! #########################################
    1046                 :             :       ! ########## Coarse resolution ############
    1047                 :             :       ! #########################################
    1048                 :             : 
    1049                 :             :       ! scan with lowpass
    1050                 :             :       ! first pass uppb is actually unknown
    1051                 :          18 :       step_coarse = (b - a) / (ngrid_coarse - 1)
    1052   [ +  -  +  +  :         594 :       bgrid_coarse = (/ ( a + (ib-1)*step_coarse, ib=1,ngrid_coarse ) /)
          +  -  +  +  +  
          -  -  +  -  -  
                   +  + ]
    1053                 :          18 :       uppb_loc = -1
    1054         [ +  - ]:          36 :       do ib=1, ngrid_coarse
    1055                 :          36 :           b_scaled = (bgrid_coarse(ib) - center) / radius
    1056                 :          36 :           partial_mass = get_eigenvalue_count(b_scaled, moments, work)
    1057                 :             : 
    1058                 :          36 :           write(std_out,*) ib, 'scan: <=', bgrid_coarse(ib), 'mass=', partial_mass
    1059                 :          36 :           flush(std_out)
    1060                 :             : 
    1061         [ +  + ]:          36 :           if (partial_mass > slice%neigenpairs) then
    1062                 :             :               uppb_loc = ib
    1063                 :             :               exit
    1064                 :             :           end if
    1065                 :             : 
    1066                 :             :       end do
    1067                 :             : 
    1068                 :          18 :       lambda_plus_wanted = (bgrid_coarse(uppb_loc-1) + bgrid_coarse(uppb_loc)) / 2.d0
    1069                 :          18 :       write(std_out,*) 'found upp bound in', lambda_plus_wanted
    1070                 :          18 :       write(std_out,*) 'estimated mass=', get_eigenvalue_count((lambda_plus_wanted-center)/radius, moments, work)
    1071                 :          18 :       write(std_out,*) 'starting adaptive refinement ..'
    1072                 :          18 :       flush(std_out)
    1073                 :             : 
    1074                 :             :       ! #########################################
    1075                 :             :       ! ########### Fine resolution #############
    1076                 :             :       ! #########################################
    1077                 :             : 
    1078                 :             :       ! Now compute eigenvalue count
    1079                 :          18 :       step_fine = (lambda_plus_wanted - a) / (ngrid_fine - 1)
    1080   [ +  -  +  +  :        1674 :       bgrid_fine = (/ (a + (ib-1)*step_fine, ib=1,ngrid_fine) /)
          +  -  +  +  +  
          -  -  +  -  -  
                   +  + ]
    1081         [ +  + ]:         558 :       do ib=1, ngrid_fine
    1082                 :         540 :           b_scaled = (bgrid_fine(ib) - center) / radius
    1083                 :         540 :           partial_mass = get_eigenvalue_count(b_scaled, moments, work)
    1084                 :         540 :           cumm_eigen_count(ib) = partial_mass
    1085   [ -  +  -  - ]:         540 :           if (partial_mass < 0.d0 .and. abs(partial_mass) > 1.d0) then
    1086                 :           0 :               write(msg,'(a)') "fine resolution for eigenvalue count failed due to oscillations. ",&
    1087                 :           0 :                   "Reduce ndeg_filter_max (hard-coded) as a solution"
    1088                 :           0 :               ABI_ERROR(msg)
    1089                 :             :           end if
    1090                 :         558 :           write(std_out,*) ib, 'scan: <=', bgrid_fine(ib), 'mass=', partial_mass
    1091                 :             :       end do
    1092                 :             :       !! todo if not found then add points in the fine grid...
    1093                 :             : 
    1094                 :             :       ! Prepare: detect gap existence in the interior of slice
    1095                 :             :       ! define value of smallest_gap
    1096                 :             :       ! todo
    1097                 :             : 
    1098                 :             :       ! step 1 cut in half balanced mass
    1099                 :          18 :       half_mass = cumm_eigen_count(ngrid_fine)/2.d0
    1100   [ +  -  +  -  :         576 :       half_index = minloc(abs(half_mass - cumm_eigen_count), dim=1)
             +  +  +  + ]
    1101                 :             :       ! step 2 adjust so that it is on constant mass (predicts gap)
    1102                 :             :       ! bidirectional search left and right
    1103                 :          18 :       write(std_out,*) 'bidirectional search from index=', half_index
    1104                 :          18 :       write(std_out,*) 'half mass=', half_mass
    1105                 :          18 :       flush(std_out)
    1106                 :          18 :       i_left = half_index
    1107                 :          18 :       i_right = half_index
    1108                 :          18 :       gap_left = .false.
    1109                 :          18 :       gap_right = .false.
    1110   [ +  +  -  + ]:          36 :       do while((.not.gap_right .and. .not.gap_left) .and. (i_left >= 2 .and. i_right <=ngrid_fine-1))
    1111                 :             :           ! this is if gap exists. If it does not exist.. must minimize using smallest_gap
    1112                 :          18 :           gap_left = abs(cumm_eigen_count(i_left) - cumm_eigen_count(i_left-1)) < 1e-4
    1113                 :          18 :           gap_right = abs(cumm_eigen_count(i_right) - cumm_eigen_count(i_right+1)) < 1e-4
    1114                 :          18 :           i_left = i_left - 1
    1115                 :          18 :           i_right = i_right + 1
    1116                 :             :       end do
    1117         [ +  - ]:          18 :       if (gap_right) then
    1118                 :          18 :           i_split = i_right
    1119                 :             :       end if
    1120         [ -  + ]:          18 :       if (gap_left) then
    1121                 :           0 :           i_split = i_left
    1122                 :             :       end if
    1123         [ -  + ]:          18 :       if (.not.gap_right .and. .not.gap_left) then
    1124                 :             :           ! todo treat this case
    1125                 :           0 :           ABI_ERROR("spectrum has no gap..")
    1126                 :             :       end if
    1127                 :          18 :       mass_left = get_eigenvalue_count((bgrid_fine(i_split)-center)/radius,moments,work)
    1128                 :          18 :       mass_right = slice%neigenpairs - mass_left
    1129                 :          18 :       write(std_out,*) 'i_split val=', i_split, bgrid_fine(i_split)
    1130                 :          18 :       write(std_out,*) 'mass left=', mass_left
    1131                 :          18 :       write(std_out,*) 'mass right=', mass_right
    1132                 :          18 :       flush(std_out)
    1133                 :             : 
    1134                 :             :       ! Store results into the slice
    1135         [ +  - ]:          18 :       slice%neigen_per_slice(1) = ceiling(mass_left)
    1136         [ +  - ]:          18 :       slice%neigen_per_slice(2) = ceiling(mass_right)
    1137                 :             : 
    1138                 :          18 :       slice%low_bounds(1) = slice%mineig
    1139                 :          18 :       slice%low_bounds(2) = bgrid_fine(i_split)
    1140                 :             : 
    1141                 :          18 :       slice%upp_bounds(1) = bgrid_fine(i_split)
    1142                 :          18 :       slice%upp_bounds(2) = bgrid_fine(ngrid_fine)
    1143                 :             : 
    1144                 :          18 :       ABI_FREE(bgrid_fine)
    1145                 :          18 :       ABI_FREE(bgrid_coarse)
    1146                 :          18 :       ABI_FREE(cumm_eigen_count)
    1147         [ -  + ]:          18 :       ABI_FREE(work)
    1148                 :             : 
    1149                 :          18 :   end subroutine slice_splitSpectrum
    1150                 :             : !!***
    1151                 :             : 
    1152                 :             : !----------------------------------------------------------------------
    1153                 :             : 
    1154                 :             : !!****f* m_slice/slice_applySelectionWindow
    1155                 :             : !! NAME
    1156                 :             : !! slice_applySelectionWindow
    1157                 :             : !!
    1158                 :             : !! FUNCTION
    1159                 :             : !! Input: k=m+p ou m la masse et p oversampling parameter
    1160                 :             : !! step 1) calculer les valeurs de Ritz
    1161                 :             : !! step 2) calculer les residus
    1162                 :             : !! step 3) mettre les valeurs de Ritz dans part_low_bounds, part_upp_bounds sous condition que res<tol
    1163                 :             : !! step 4) sinon faire un sketch de taille K du reste
    1164                 :             : !!
    1165                 :             : !! INPUT
    1166                 :             : !! safe is between 2 and 10
    1167                 :             : !!
    1168                 :             : !! OUTPUT
    1169                 :             : !! mapper contains the column indices per slice (allowing repetitions)
    1170                 :             : !!
    1171                 :             : !! SOURCE
    1172                 :             : 
    1173         [ -  + ]:          18 :   subroutine slice_applySelectionWindow(slice, mapper, eigen, resid, tol, safe)
    1174                 :             : 
    1175                 :             :     implicit none
    1176                 :             : 
    1177                 :             :     type(slice_t), intent(inout) :: slice
    1178                 :             :     logical, intent(inout) :: mapper(:,:)
    1179                 :             :     type(xgBlock_t), intent(inout) :: eigen
    1180                 :             :     type(xgBlock_t), intent(inout) :: resid
    1181                 :             :     real(dp), intent(in) :: tol
    1182                 :             :     real(dp), intent(in) :: safe
    1183                 :             : 
    1184                 :             :     integer :: nband, iband, islice, m, k_kept
    1185                 :             :     real(dp) :: uppb, lowb, uppb_plus, lowb_minus
    1186                 :             :     real(dp) :: theta, relaxf, relres
    1187                 :             :     real(dp), pointer :: resid_vals(:,:) => null()
    1188                 :             :     complex(dp), pointer :: thetas(:,:) => null()
    1189                 :             : 
    1190                 :             :   ! *********************************************************************
    1191                 :             : 
    1192                 :          18 :     nband = slice%neigenpairs
    1193                 :             : 
    1194                 :          18 :     call xgBlock_reverseMap(eigen, thetas, rows=nband, cols=1)
    1195                 :          18 :     call xgBlock_reverseMap(resid, resid_vals, rows=nband, cols=1)
    1196                 :             : 
    1197                 :             :     ! apply selection window per slice
    1198         [ +  + ]:          54 :     do islice=1,slice%nslice
    1199                 :          36 :         m = slice%neigen_per_slice(islice)
    1200                 :          36 :         lowb = slice%low_bounds(islice)
    1201                 :          36 :         uppb = slice%upp_bounds(islice)
    1202                 :          36 :         write(std_out,*) islice, 'slice bounds', lowb, uppb
    1203                 :             : 
    1204                 :             :         ! keep candidates in expanded interval
    1205                 :          36 :         k_kept = 0
    1206         [ +  + ]:        6948 :         do iband=1, nband
    1207                 :        6912 :             relres = resid_vals(iband, 1)
    1208         [ -  + ]:        6948 :             if (relres < tol) then
    1209                 :             :                 ! Soft selection:
    1210                 :             :                 ! relaxed bounds for converged eigenpairs near boundaries
    1211                 :           0 :                 relaxf = safe * relres
    1212                 :           0 :                 lowb_minus = lowb - relaxf
    1213                 :           0 :                 uppb_plus = uppb + relaxf
    1214                 :           0 :                 theta = real(thetas(iband, 1))
    1215                 :           0 :                 write(std_out,*) iband, 'theta=', theta, 'resid=', relres
    1216                 :           0 :                 flush(std_out)
    1217                 :             : 
    1218                 :             :                 ! accept if lambda in relaxed interval
    1219   [ #  #  #  # ]:           0 :                 if (theta < uppb_plus .and. theta > lowb_minus) then
    1220                 :           0 :                     k_kept = k_kept + 1
    1221                 :           0 :                     mapper(iband, islice) = .true.
    1222                 :             :                 end if
    1223                 :             :             end if
    1224                 :             :         end do
    1225                 :             : 
    1226                 :             :         ! todo m not set must modify computeTraceEstimation and separate the split spectrum from that
    1227                 :             :         ! because split spectrum will store info on slice object that is invisible from trace
    1228                 :          36 :         write(std_out,*) 'selection window kept', k_kept, 'for eigendimension', m
    1229                 :          54 :         flush(std_out)
    1230                 :             :     end do
    1231                 :             : 
    1232                 :          18 :   end subroutine slice_applySelectionWindow
    1233                 :             : !!***
    1234                 :             : 
    1235   [ #  #  #  #  :           0 : end module m_slice
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    1236                 :             : !!***
        

Generated by: LCOV version 2.3-1