LCOV - code coverage report
Current view: top level - src/48_diago - m_lobpcg2_cprj.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.8 % 405 319
Test Date: 2026-09-20 18:56:22 Functions: 69.2 % 13 9

            Line data    Source code
       1              : 
       2              : #if defined HAVE_CONFIG_H
       3              : #include "config.h"
       4              : #endif
       5              : 
       6              : #include "abi_common.h"
       7              : 
       8              : module m_lobpcg2_cprj
       9              : 
      10              :   use defs_basis
      11              :   use m_xg
      12              :   use m_xg_nonlop
      13              :   use m_xg_ortho_RR
      14              :   use m_xgTransposer
      15              :   use m_xgScalapack
      16              :   use defs_basis
      17              :   use m_abicore
      18              :   use m_errors
      19              :   use m_xomp
      20              : #ifdef HAVE_OPENMP
      21              :   use omp_lib
      22              : #endif
      23              : 
      24              :   use m_xmpi
      25              :   use m_time, only : timab
      26              : 
      27              :   implicit none
      28              : 
      29              :   private
      30              : 
      31              :   integer, parameter :: tim_init     = 2040
      32              :   integer, parameter :: tim_free     = 2041
      33              :   integer, parameter :: tim_cprj     = 2043
      34              :   integer, parameter :: tim_ortho    = 2044
      35              :   integer, parameter :: tim_transpose = 2039
      36              :   integer, parameter :: tim_maxres   = 2046
      37              :   integer, parameter :: tim_ax_k     = 2048
      38              :   integer, parameter :: tim_ax_v     = 2049
      39              :   integer, parameter :: tim_ax_nl    = 2050
      40              :   integer, parameter :: tim_pcond    = 2047
      41              : 
      42              :   integer, parameter :: tim_Bortho_X    = 2031
      43              :   integer, parameter :: tim_Bortho_XW   = 2032
      44              :   integer, parameter :: tim_Bortho_XWP  = 2033
      45              :   integer, parameter :: tim_Bortho_Xall = 2034
      46              :   integer, parameter :: tim_RR_X        = 2035
      47              :   integer, parameter :: tim_RR_XW       = 2036
      48              :   integer, parameter :: tim_RR_XWP      = 2037
      49              :   integer, parameter :: tim_RR_Xall     = 2038
      50              : 
      51              :   integer, parameter :: tim_copy     = 2042
      52              :   integer, parameter :: tim_nbdbuf   = 2045
      53              : 
      54              :   integer, parameter :: tim_enl = 2051
      55              : 
      56              :   type, public :: lobpcg_t
      57              :     logical :: is_nested                     ! For OpenMP nested region
      58              :     integer :: spacedim                      ! Space dimension for one vector (WFs)
      59              :     integer :: space                         ! Space type for one vector
      60              :     integer :: space_cprj                    ! Space type for one projector
      61              :     integer :: cprjdim                       ! Space dimension for one vector (cprj)
      62              :     integer :: neigenpairs                   ! Number of eigen values/vectors we want
      63              :     integer :: nblock                        ! Number of block in the space of dim spacedim
      64              :     integer :: blockdim                      ! Number of vectors in one block
      65              :     integer :: blockdim_cprj                 ! Number of vectors in one block (for cprj array)
      66              :     integer :: nline                         ! Number of line to perform
      67              :     integer :: spacecom                      ! Communicator for MPI
      68              :     integer :: paral_kgb                     ! paral_kgb formalism or not
      69              :     integer :: comm_rows                     ! communicator for rows
      70              :     integer :: comm_cols                     ! communicator for cols
      71              :     integer :: me_g0
      72              :     integer :: me_g0_fft
      73              :     double precision :: tolerance            ! Tolerance on the residu to stop the minimization
      74              :     integer :: prtvol
      75              :     type(xg_nonlop_t) :: xg_nonlop ! contains data for nonlocal operations
      76              :     type(xgBlock_t) :: AllX0 ! Block of initial and final solution.
      77              :     type(xgBlock_t) :: AllcprjX0 ! Block of initial and final solution.
      78              :     type(xgBlock_t) :: X0
      79              :     type(xgBlock_t) :: cprjX0
      80              :                                              ! Dim is (cplx*spacedim,neigenpair)
      81              :     !double precision, allocatable :: eig(:)  ! Actual eigen values
      82              : 
      83              :     ! Some denomination here
      84              :     ! X, W, P are the shifts where their block vectors starts.
      85              :     ! X is the current block we are solving
      86              :     ! W is the residu of the pencil A-lambda*B ie W=A*X-lambdaB*X
      87              :     ! P correspond to X_{iline} - X_{iline-1}
      88              :     ! if prefixed by A (AX, AW, AP) it means the result of A*X (A*W, A*P ! respectively)
      89              :     ! Idem for B (BX, BW, BP) which is the result of B*X (B*W, B*P)
      90              :     ! An extend to this is AXWP which is the vector [AX,AW,AP]
      91              :     ! and BXWP which is [BX,BW,BP] columnwise
      92              :     ! Now we only allocate the triple XWP matrix and each individual X, W and P
      93              :     ! Example : XWP=[x1,x2,x3,w1,w2,w3,p1,p2,p3] X points to the indice of x1-1, W points to w1-1 and
      94              :     ! P to p1-1
      95              :     type(xg_t) :: XWP
      96              :     type(xg_t) :: AXWP
      97              :     type(xg_t) :: cprjXWP
      98              : 
      99              :     type(xg_t) :: cprj_work
     100              :     type(xg_t) :: cprj_work2
     101              : 
     102              :     type(xgBlock_t) :: XColsRows
     103              :     type(xgBlock_t) :: AXColsRows
     104              : 
     105              :     type(xgTransposer_t) :: xgTransposerX
     106              :     type(xgTransposer_t) :: xgTransposerAX
     107              : 
     108              :     type(xgBlock_t) :: WColsRows
     109              :     type(xgBlock_t) :: AWColsRows
     110              : 
     111              :     type(xgTransposer_t) :: xgTransposerW
     112              :     type(xgTransposer_t) :: xgTransposerAW
     113              : 
     114              :     type(xgBlock_t) :: X ! Shift to apply to start reading the X values
     115              :     type(xgBlock_t) :: W ! Shift to apply to start reading the W values
     116              :     type(xgBlock_t) :: P ! Shift to apply to start reading the P values
     117              :     type(xgBlock_t) :: XW ! Shift to apply to start reading the P values
     118              :     type(xgBlock_t) :: WP ! Shift to apply to start reading the P values
     119              : 
     120              :     type(xgBlock_t) :: AX ! Shift to apply to start reading the X values
     121              :     type(xgBlock_t) :: AW ! Shift to apply to start reading the W values
     122              :     type(xgBlock_t) :: AP ! Shift to apply to start reading the P values
     123              :     type(xgBlock_t) :: AXW ! Shift to apply to start reading the P values
     124              :     type(xgBlock_t) :: AWP ! Shift to apply to start reading the P values
     125              : 
     126              :     type(xgBlock_t) :: cprjX ! Shift to apply to start reading the X values
     127              :     type(xgBlock_t) :: cprjW ! Shift to apply to start reading the W values
     128              :     type(xgBlock_t) :: cprjP ! Shift to apply to start reading the P values
     129              :     type(xgBlock_t) :: cprjXW ! Shift to apply to start reading the P values
     130              :     type(xgBlock_t) :: cprjWP ! Shift to apply to start reading the P values
     131              : 
     132              :     type(xg_t) :: AllAX0
     133              : 
     134              :     type(xgBlock_t) :: AllX0ColsRows
     135              :     type(xgBlock_t) :: AllAX0ColsRows
     136              : 
     137              :     type(xgTransposer_t) :: xgTransposerAllX0
     138              :     type(xgTransposer_t) :: xgTransposerAllAX0
     139              : 
     140              :   end type lobpcg_t
     141              : 
     142              :   public :: lobpcg_init
     143              :   public :: lobpcg_memInfo
     144              :   public :: lobpcg_run_cprj
     145              :   public :: lobpcg_free
     146              : 
     147              :   contains
     148              : 
     149              : 
     150         4036 :   subroutine lobpcg_init(lobpcg, bandpp, neigenpairs, spacedim, cprjdim, blockdim, tolerance, nline, &
     151              : &      space, space_cprj, spacecom, paral_kgb, xg_nonlop, comm_rows, comm_cols, me_g0, me_g0_fft)
     152              : 
     153              :     type(lobpcg_t)   , intent(inout) :: lobpcg
     154              :     type(xg_nonlop_t), intent(in   ) :: xg_nonlop
     155              :     integer          , intent(in   ) :: neigenpairs
     156              :     integer          , intent(in   ) :: spacedim
     157              :     integer          , intent(in   ) :: cprjdim
     158              :     integer          , intent(in   ) :: blockdim
     159              :     integer          , intent(in   ) :: bandpp
     160              :     double precision , intent(in   ) :: tolerance
     161              :     integer          , intent(in   ) :: nline
     162              :     integer          , intent(in   ) :: comm_rows,comm_cols
     163              :     integer          , intent(in   ) :: space
     164              :     integer          , intent(in   ) :: space_cprj
     165              :     integer          , intent(in   ) :: spacecom
     166              :     integer          , intent(in   ) :: paral_kgb
     167              :     integer          , intent(in   ) :: me_g0
     168              :     integer          , intent(in   ) :: me_g0_fft
     169              :     double precision :: tsec(2)
     170              : 
     171         4036 :     call timab(tim_init,1,tsec)
     172         4036 :     lobpcg%neigenpairs   = neigenpairs
     173         4036 :     lobpcg%spacedim      = spacedim
     174         4036 :     lobpcg%space         = space
     175         4036 :     lobpcg%space_cprj    = space_cprj
     176         4036 :     lobpcg%cprjdim       = cprjdim
     177         4036 :     lobpcg%nblock        = neigenpairs / blockdim
     178         4036 :     lobpcg%blockdim      = blockdim
     179         4036 :     lobpcg%blockdim_cprj = bandpp*xg_nonlop%nspinor
     180         4036 :     if (tolerance > 0.0) then
     181            0 :       lobpcg%tolerance   = tolerance
     182              :     else
     183         4036 :       lobpcg%tolerance   = 1e-20
     184              :     end if
     185         4036 :     lobpcg%nline         = nline
     186         4036 :     lobpcg%spacecom      = spacecom
     187         4036 :     lobpcg%paral_kgb     = paral_kgb
     188         4036 :     lobpcg%comm_rows     = comm_rows
     189         4036 :     lobpcg%comm_cols     = comm_cols
     190         4036 :     lobpcg%xg_nonlop     = xg_nonlop
     191         4036 :     lobpcg%me_g0         = me_g0
     192         4036 :     lobpcg%me_g0_fft     = me_g0_fft
     193              : 
     194         4036 :     call lobpcg_allocateAll(lobpcg)
     195         4036 :     call timab(tim_init,2,tsec)
     196              : 
     197         4036 :   end subroutine lobpcg_init
     198              : 
     199              : 
     200         4036 :   subroutine lobpcg_allocateAll(lobpcg)
     201              : 
     202              :     type(lobpcg_t)  , intent(inout) :: lobpcg
     203              :     integer :: spacedim
     204              :     integer :: cprjdim
     205              :     integer :: blockdim
     206              :     integer :: blockdim_cprj
     207              : 
     208         4036 :     spacedim = lobpcg%spacedim
     209         4036 :     blockdim = lobpcg%blockdim
     210              : 
     211         4036 :     cprjdim       = lobpcg%cprjdim
     212         4036 :     blockdim_cprj = lobpcg%blockdim_cprj
     213              : 
     214         4036 :     call lobpcg_free(lobpcg) ! Make sure everything is not allocated and
     215              :     ! pointer point to null()
     216              : 
     217         4036 :     call xg_init(lobpcg%XWP,lobpcg%space,spacedim,3*blockdim,lobpcg%spacecom,me_g0=lobpcg%me_g0)
     218         4036 :     call xg_setBlock(lobpcg%XWP,lobpcg%X,spacedim,blockdim)
     219         4036 :     call xg_setBlock(lobpcg%XWP,lobpcg%W,spacedim,blockdim,fcol=blockdim+1)
     220         4036 :     call xg_setBlock(lobpcg%XWP,lobpcg%P,spacedim,blockdim,fcol=2*blockdim+1)
     221         4036 :     call xg_setBlock(lobpcg%XWP,lobpcg%XW,spacedim,2*blockdim)
     222         4036 :     call xg_setBlock(lobpcg%XWP,lobpcg%WP,spacedim,2*blockdim,fcol=blockdim+1)
     223              : 
     224         4036 :     call xg_init(lobpcg%AXWP,lobpcg%space,spacedim,3*blockdim,lobpcg%spacecom,me_g0=lobpcg%me_g0)
     225         4036 :     call xg_setBlock(lobpcg%AXWP,lobpcg%AX,spacedim,blockdim)
     226         4036 :     call xg_setBlock(lobpcg%AXWP,lobpcg%AW,spacedim,blockdim,fcol=blockdim+1)
     227         4036 :     call xg_setBlock(lobpcg%AXWP,lobpcg%AP,spacedim,blockdim,fcol=2*blockdim+1)
     228         4036 :     call xg_setBlock(lobpcg%AXWP,lobpcg%AXW,spacedim,2*blockdim)
     229         4036 :     call xg_setBlock(lobpcg%AXWP,lobpcg%AWP,spacedim,2*blockdim,fcol=blockdim+1)
     230              : 
     231         4036 :     call xg_init(lobpcg%cprjXWP,lobpcg%space_cprj,cprjdim,3*blockdim_cprj,lobpcg%spacecom)
     232         4036 :     call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjX, cprjdim,  blockdim_cprj)
     233         4036 :     call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjW, cprjdim,  blockdim_cprj,fcol=   blockdim_cprj+1)
     234         4036 :     call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjP, cprjdim,  blockdim_cprj,fcol= 2*blockdim_cprj+1)
     235         4036 :     call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjXW,cprjdim,2*blockdim_cprj)
     236         4036 :     call xg_setBlock(lobpcg%cprjXWP,lobpcg%cprjWP,cprjdim,2*blockdim_cprj,fcol=   blockdim_cprj+1)
     237              : 
     238         4036 :     call xg_init(lobpcg%cprj_work ,lobpcg%space_cprj,cprjdim,blockdim_cprj,lobpcg%spacecom)
     239         4036 :     call xg_init(lobpcg%cprj_work2,lobpcg%space_cprj,cprjdim,blockdim_cprj,lobpcg%spacecom)
     240              : 
     241         4036 :     if ( lobpcg%nblock /= 1 ) then
     242         4004 :       call xg_init(lobpcg%AllAX0,lobpcg%space,spacedim,lobpcg%neigenpairs,lobpcg%spacecom,me_g0=lobpcg%me_g0)
     243              :     else
     244           32 :       lobpcg%AllAX0%self = lobpcg%AX
     245              :     end if
     246              : 
     247         4036 :   end subroutine lobpcg_allocateAll
     248              : 
     249              : 
     250            0 :   function lobpcg_memInfo(neigenpairs, spacedim, blockdim, space) result(arraymem)
     251              : 
     252              :     integer         , intent(in   ) :: neigenpairs
     253              :     integer         , intent(in   ) :: spacedim
     254              :     integer         , intent(in   ) :: blockdim
     255              :     integer         , intent(in   ) :: space
     256              :     double precision :: memXWP
     257              :     double precision :: memAXWP
     258              :     double precision :: memBXWP
     259              :     double precision :: memAllBX0
     260              :     double precision :: memAllAX0
     261              :     double precision :: memeigenvalues3N
     262              :     double precision :: membufferOrtho
     263              :     double precision :: membufferBOrtho
     264              :     double precision :: memsubA
     265              :     double precision :: memsubB
     266              :     double precision :: memsubBtmp
     267              :     double precision :: memvec
     268              :     double precision :: memRR
     269              :     double precision :: maxmemTmp
     270              :     double precision :: cplx
     271              :     integer :: nblock
     272              :     double precision :: arraymem(2)
     273              : 
     274            0 :     cplx = 1 ; if ( space == SPACE_C ) cplx = 2
     275            0 :     nblock = neigenpairs/blockdim
     276              : 
     277              :     ! Permanent in lobpcg
     278            0 :     memXWP  = cplx* kind(1.d0) * spacedim * 3*blockdim
     279            0 :     memAXWP = cplx* kind(1.d0) * spacedim * 3*blockdim
     280            0 :     memBXWP = cplx* kind(1.d0) * spacedim * 3*blockdim
     281            0 :     if ( nblock > 1 ) then
     282            0 :       memAllAX0 = cplx * kind(1.d0) * spacedim * 3*blockdim
     283            0 :       memAllBX0 = cplx * kind(1.d0) * spacedim * 3*blockdim
     284            0 :       membufferOrtho = cplx * kind(1.d0) * blockdim * (nblock-1) * blockdim
     285              :     else
     286              :       memAllAX0 = 0
     287              :       memAllBX0 = 0
     288              :       membufferOrtho = 0
     289              :     endif
     290            0 :     memeigenvalues3N = kind(1.d0) * 3*blockdim
     291              : 
     292              :     ! Temporary arrays
     293            0 :     membufferBOrtho = cplx * kind(1.d0) * 2*blockdim * 2*blockdim ! For the moment being, only Bortho with X or WP at the same time
     294            0 :     memsubA = cplx * kind(1.d0) * 3*blockdim * 3*blockdim
     295            0 :     memsubB = cplx * kind(1.d0) * 3*blockdim * 3*blockdim
     296            0 :     memsubBtmp = cplx * kind(1.d0) * spacedim * blockdim
     297            0 :     memvec = cplx * kind(1.d0) * 3*blockdim * blockdim
     298            0 :     memRR = max(memsubA+memsubB+memvec,memsubBtmp+memvec)
     299              : 
     300            0 :     maxmemTmp = max( membufferBOrtho,memRR,membufferOrtho )
     301              : 
     302            0 :     arraymem(1) = memXWP+memAXWP+memBXWP+memAllAX0+memAllBX0+memeigenvalues3N
     303            0 :     arraymem(2) = maxmemTmp
     304              : 
     305            0 :   end function lobpcg_memInfo
     306              : 
     307              : 
     308        12108 :   subroutine lobpcg_run_cprj(lobpcg, X0, cprjX0, getAX, kin, pcond, eigen, occ, residu, enl, prtvol, nspinor, &
     309              :       isppol, ikpt, inonsc, istep, nbdbuf)
     310              : 
     311              :     type(lobpcg_t) , intent(inout) :: lobpcg
     312              :     type(xgBlock_t), intent(inout) :: X0      ! Full initial vectors
     313              :     type(xgBlock_t), intent(inout) :: cprjX0  ! Full initial cprj
     314              :     type(xgBlock_t), intent(inout) :: eigen   ! Full initial eigen values
     315              :     type(xgBlock_t), intent(inout) :: occ
     316              :     type(xgBlock_t), intent(inout) :: residu
     317              :     type(xgBlock_t), intent(inout) :: enl
     318              :     type(xgBlock_t), intent(in   ) :: kin
     319              :     type(xgBlock_t), intent(in   ) :: pcond
     320              :     integer        , intent(in   ) :: prtvol
     321              :     integer        , intent(in   ) :: nspinor
     322              :     integer        , intent(in   ) :: isppol,ikpt,inonsc,istep,nbdbuf
     323              : 
     324              :     type(xg_t) :: eigenvalues3N   ! eigen values for Rayleight-Ritz
     325              :     type(xg_t) :: residu_eff
     326              :     type(xgBlock_t) :: eigenvaluesN   ! eigen values for Rayleight-Ritz
     327              :     type(xgBlock_t) :: eigenvalues2N   ! eigen values for Rayleight-Ritz
     328              :     logical :: skip,compute_residu
     329              :     integer :: blockdim, blockdim3, blockdim2, blockdim_cprj
     330              :     integer :: spacedim
     331              :     integer :: iblock, nblock
     332              :     integer :: iline, nline
     333              :     integer :: rows_tmp, cols_tmp, nband_eff, iband_min, iband_max
     334              :     integer,parameter :: gpu_option=ABI_GPU_DISABLED
     335              :     type(xgBlock_t) :: eigenBlock   !
     336              :     type(xgBlock_t) :: residuBlock,occBlock
     337              :     type(xg_t):: cprj_work_all
     338              :     double precision :: maxResidu, minResidu, dummy
     339              :     double precision :: dlamch,tolerance
     340              :     integer :: ierr = 0
     341              :     integer :: nrestart
     342              :     double precision :: tsec(2)
     343              :     character(len=500) :: msg
     344              : 
     345              :     interface
     346              :       subroutine getAX(X,AX)
     347              :         use m_xg, only : xgBlock_t
     348              :         type(xgBlock_t), intent(inout) :: X
     349              :         type(xgBlock_t), intent(inout) :: AX
     350              :       end subroutine getAX
     351              :     end interface
     352              : 
     353         4036 :     lobpcg%prtvol = prtvol
     354              : 
     355         8072 :     tolerance=2*dlamch('E')
     356              : 
     357         4036 :     blockdim = lobpcg%blockdim
     358         4036 :     blockdim2 = 2*blockdim
     359         4036 :     blockdim3 = 3*blockdim
     360         4036 :     blockdim_cprj = lobpcg%blockdim_cprj
     361         4036 :     spacedim = lobpcg%spacedim
     362              : 
     363         4036 :     nblock = lobpcg%nblock
     364         4036 :     nline = lobpcg%nline
     365              : 
     366         4036 :     if (nbdbuf>0) then
     367         4036 :        nband_eff = lobpcg%neigenpairs - nbdbuf
     368              :     else
     369            0 :        nband_eff = lobpcg%neigenpairs
     370              :     end if
     371              : 
     372         4036 :     call xgBlock_getSize(eigen,rows_tmp, cols_tmp)
     373         4036 :     if ( rows_tmp /= lobpcg%neigenpairs .and. cols_tmp /= 1 ) then
     374            0 :       ABI_ERROR("Error eigen size")
     375              :     endif
     376         4036 :     call xgBlock_getSize(X0,rows_tmp, cols_tmp)
     377         4036 :     if ( rows_tmp /= lobpcg%spacedim ) then
     378            0 :       ABI_ERROR("Error X0 spacedim")
     379              :     endif
     380         4036 :     if ( cols_tmp /= lobpcg%neigenpairs ) then
     381            0 :       ABI_ERROR("Error X0 npairs")
     382              :     endif
     383              : 
     384         4036 :     if (isppol==1.and.ikpt==1.and.inonsc==1.and.istep==1) then
     385           42 :       write(msg,'(a,es16.6)') ' lobpcg%tolerance(tolwfr_diago)=',lobpcg%tolerance
     386           42 :       call wrtout(std_out,msg,'COLL')
     387              :     end if
     388              : 
     389         4036 :     call xg_init(eigenvalues3N,SPACE_R,blockdim3,1)
     390         4036 :     call xg_setBlock(eigenvalues3N,eigenvaluesN,blockdim,1)
     391         4036 :     call xg_setBlock(eigenvalues3N,eigenvalues2N,blockdim2,1)
     392              : 
     393         4036 :     call xgBlock_reshape(eigen,blockdim,nblock)
     394         4036 :     call xgBlock_reshape(residu,blockdim,nblock)
     395         4036 :     call xgBlock_reshape(occ,blockdim,nblock)
     396              : 
     397         4036 :     lobpcg%AllX0     = X0
     398         4036 :     lobpcg%AllcprjX0 = cprjX0
     399              : 
     400         4036 :     call xg_init(residu_eff,SPACE_R,blockdim,1,gpu_option=ABI_GPU_DISABLED)
     401              : 
     402         4036 :     if ( lobpcg%paral_kgb == 1 ) then
     403         2684 :       call timab(tim_transpose,1,tsec)
     404              :       call xgTransposer_constructor(lobpcg%xgTransposerX,lobpcg%X,lobpcg%XColsRows,nspinor,&
     405         2684 :         STATE_LINALG,TRANS_ALL2ALL,lobpcg%comm_rows,lobpcg%comm_cols,0,0,lobpcg%me_g0_fft)
     406              :       call xgTransposer_copyConstructor(lobpcg%xgTransposerAX,lobpcg%xgTransposerX,&
     407         2684 :         lobpcg%AX,lobpcg%AXColsRows,STATE_LINALG)
     408              :       call xgTransposer_copyConstructor(lobpcg%xgTransposerW,lobpcg%xgTransposerX,&
     409         2684 :         lobpcg%W,lobpcg%WColsRows,STATE_LINALG)
     410              :       call xgTransposer_copyConstructor(lobpcg%xgTransposerAW,lobpcg%xgTransposerX,&
     411         2684 :         lobpcg%AW,lobpcg%AWColsRows,STATE_LINALG)
     412         2684 :       call timab(tim_transpose,2,tsec)
     413              :     else
     414         1352 :       call xgBlock_setBlock(lobpcg%X, lobpcg%XColsRows, spacedim, blockdim)
     415         1352 :       call xgBlock_setBlock(lobpcg%AX, lobpcg%AXColsRows, spacedim, blockdim)
     416         1352 :       call xgBlock_setBlock(lobpcg%W, lobpcg%WColsRows, spacedim, blockdim)
     417         1352 :       call xgBlock_setBlock(lobpcg%AW, lobpcg%AWColsRows, spacedim, blockdim)
     418              :     end if
     419              : 
     420              :     !! Start big loop over blocks
     421        20628 :     do iblock = 1, nblock
     422        16592 :       nrestart = 0
     423              : 
     424        16592 :       call lobpcg_getX0(lobpcg,iblock)
     425        16592 :       call xgBlock_setBlock(residu,residuBlock,blockdim,1,fcol=iblock)
     426        16592 :       call xgBlock_setBlock(occ,   occBlock,   blockdim,1,fcol=iblock)
     427              : 
     428        16592 :       call timab(tim_cprj,1,tsec)
     429        16592 :       call xg_nonlop_getcprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%cprj_work%self)
     430        16592 :       call timab(tim_cprj,2,tsec)
     431              : 
     432        16592 :       if ( iblock > 1 ) then
     433        12556 :         call lobpcg_setPreviousX0(lobpcg,iblock)
     434              :         ! Orthogonalize current iblock X block With Respect To previous Blocks in B-basis
     435        12556 :         call lobpcg_orthoXwrtBlocks(lobpcg,lobpcg%X,lobpcg%cprjX,iblock,lobpcg%cprj_work%self)
     436              :       end if
     437              : 
     438        16592 :       if (lobpcg%paral_kgb == 1) then
     439        11184 :         call timab(tim_transpose,1,tsec)
     440        11184 :         call xgTransposer_transpose(lobpcg%xgTransposerX,STATE_COLSROWS)
     441        11184 :         lobpcg%xgTransposerAX%state=STATE_COLSROWS
     442        11184 :         call timab(tim_transpose,2,tsec)
     443              :       end if
     444              : 
     445              :       ! Initialize some quantitites (AX)
     446        16592 :       call timab(tim_ax_v,1,tsec)
     447        16592 :       call getAX(lobpcg%XColsRows,lobpcg%AXColsRows)
     448        16592 :       call xgBlock_zero_im_g0(lobpcg%AXColsRows)
     449        16592 :       call timab(tim_ax_v,2,tsec)
     450        16592 :       if (lobpcg%paral_kgb == 1) then
     451        11184 :         call timab(tim_transpose,1,tsec)
     452        11184 :         lobpcg%xgTransposerX%state=STATE_LINALG
     453        11184 :         call xgTransposer_transpose(lobpcg%xgTransposerAX,STATE_LINALG)
     454        11184 :         call timab(tim_transpose,2,tsec)
     455              :       end if
     456              : 
     457        16592 :       call timab(tim_ax_k,1,tsec)
     458        16592 :       call xgBlock_add_diag(lobpcg%X,kin,nspinor,lobpcg%AX)
     459        16592 :       call timab(tim_ax_k,2,tsec)
     460              : 
     461              :       ! B-orthonormalize X, BX and AX
     462        16592 :       call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,ierr,tim_Bortho_X,gpu_option,AX=lobpcg%AX)
     463              : 
     464              :       ! Do first RR on X to get the first eigen values
     465              :       call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
     466        16592 :         & lobpcg%prtvol,tim_RR_X,gpu_option,add_Anl=.True.)
     467              : 
     468        16592 :       compute_residu = .true.
     469              : 
     470        75096 :       do iline = 1, nline
     471              : 
     472        67717 :         if ( ierr /= 0 ) then
     473              :           !ABI_COMMENT("Consider using more bands and nbdbuf if necessary.")
     474            0 :           ierr = 0
     475              :         end if
     476              : 
     477              :         ! Compute AX-Lambda*BX
     478        67717 :         call timab(tim_copy,1,tsec)
     479        67717 :         call xgBlock_copy(lobpcg%AX,lobpcg%W)
     480        67717 :         call timab(tim_copy,2,tsec)
     481              :         ! Add the non-local part: (A_nl - Lambda*B)X
     482        67717 :         call timab(tim_ax_nl,1,tsec)
     483        67717 :         if (lobpcg%xg_nonlop%paw) then
     484              :           call xg_nonlop_getHmeSX(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%W,eigenvaluesN,&
     485        55920 :             lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
     486              :         else
     487              :           call xg_nonlop_getHX(lobpcg%xg_nonlop,lobpcg%W,lobpcg%cprjX,&
     488        11797 :             lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
     489        11797 :           call xgBlock_yxmax(lobpcg%W,eigenvaluesN,lobpcg%X)
     490              :         end if
     491        67717 :         call timab(tim_ax_nl,2,tsec)
     492              : 
     493              :         ! Compute residu norm here !
     494        67717 :         call timab(tim_maxres,1,tsec)
     495        67717 :         call xgBlock_colwiseNorm2(lobpcg%W,residuBlock)
     496        67717 :         call timab(tim_maxres,2,tsec)
     497              : 
     498              :         ! Apply preconditioner
     499        67717 :         call timab(tim_pcond,1,tsec)
     500        67717 :         call xgBlock_apply_diag(lobpcg%W,pcond,nspinor)
     501        67717 :         call timab(tim_pcond,2,tsec)
     502              : 
     503        67717 :         call timab(tim_nbdbuf,1,tsec)
     504        67717 :         if (nbdbuf>=0) then
     505              :           ! There is a transfer from GPU to CPU in this copy
     506        67717 :           call xgBlock_copy(residuBlock,residu_eff%self)
     507        67717 :           iband_min = 1 + blockdim*(iblock-1)
     508        67717 :           iband_max = blockdim*iblock
     509        67717 :           if (iband_max<=nband_eff) then ! all bands of this block are below nband_eff
     510        57269 :             call xgBlock_minmax(residu_eff%self,minResidu,maxResidu)
     511        10448 :           else if (iband_min<=nband_eff) then ! some bands of this block are below nband_eff
     512         3120 :             call xgBlock_minmax(residu_eff%self,minResidu,maxResidu,row_bound=(nband_eff-iband_min+1))
     513              :           else ! all bands of this block are above nband_eff
     514         7328 :             minResidu = 0.0
     515         7328 :             maxResidu = 0.0
     516              :           end if
     517            0 :         else if (nbdbuf==-101) then
     518            0 :           call xgBlock_minmax(residuBlock,minResidu,dummy) ! Get minimum of true residuals
     519              :           ! Compute effective residuals : res_eff = res * occ
     520            0 :           call xgBlock_apply_diag(residuBlock,occBlock,1,Y=residu_eff%self)
     521            0 :           call xgBlock_minmax(residu_eff%self,dummy,maxResidu) ! Get maximum of effective residuals
     522              :         else
     523            0 :           ABI_ERROR('Bad value of nbdbuf')
     524              :         end if
     525        67717 :         call timab(tim_nbdbuf,2,tsec)
     526        67717 :         if ( maxResidu < lobpcg%tolerance ) then
     527              :           compute_residu = .false.
     528              :           exit
     529              :         end if
     530              : 
     531        58504 :         call timab(tim_cprj,1,tsec)
     532        58504 :         call xg_nonlop_getcprj(lobpcg%xg_nonlop,lobpcg%W,lobpcg%cprjW,lobpcg%cprj_work%self)
     533        58504 :         call timab(tim_cprj,2,tsec)
     534              : 
     535              :         ! Orthonormalize with respect to previous blocks
     536        58504 :         if ( iblock > 1 ) then
     537        32398 :           call lobpcg_orthoXwrtBlocks(lobpcg,lobpcg%W,lobpcg%cprjW,iblock,lobpcg%cprj_work%self)
     538              :         end if
     539              : 
     540        58504 :         if (lobpcg%paral_kgb == 1) then
     541        37406 :           call timab(tim_transpose,1,tsec)
     542        37406 :           call xgTransposer_transpose(lobpcg%xgTransposerW,STATE_COLSROWS)
     543        37406 :           lobpcg%xgTransposerAW%state=STATE_COLSROWS
     544        37406 :           call timab(tim_transpose,2,tsec)
     545              :         end if
     546              :         ! Apply A and B on W
     547        58504 :         call timab(tim_ax_v,1,tsec)
     548        58504 :         call getAX(lobpcg%WColsRows,lobpcg%AWColsRows)
     549        58504 :         call xgBlock_zero_im_g0(lobpcg%AWColsRows)
     550        58504 :         call timab(tim_ax_v,2,tsec)
     551        58504 :         if (lobpcg%paral_kgb == 1) then
     552        37406 :           call timab(tim_transpose,1,tsec)
     553        37406 :           lobpcg%xgTransposerW%state=STATE_LINALG
     554        37406 :           call xgTransposer_transpose(lobpcg%xgTransposerAW,STATE_LINALG)
     555        37406 :           call timab(tim_transpose,2,tsec)
     556              :         end if
     557              : 
     558        58504 :         call timab(tim_ax_k,1,tsec)
     559        58504 :         call xgBlock_add_diag(lobpcg%W,kin,nspinor,lobpcg%AW)
     560        58504 :         call timab(tim_ax_k,2,tsec)
     561              : 
     562              :         ! DO RR in the correct subspace
     563              :         ! if residu starts to be too small, there is an accumulation error in
     564              :         ! P with values such as 1e-29 that make the eigenvectors diverge
     565        65883 :         if ( iline == 1 .or. minResidu < 1e-27) then
     566              :           ! Do RR on XW to get the eigen vectors
     567              :           call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%XW,lobpcg%cprjXW,&
     568         8938 :             & ierr,tim_Bortho_XW,gpu_option,AX=lobpcg%AXW,blockdim_cprj=blockdim_cprj)
     569         8938 :           call xgBlock_zero(lobpcg%P)
     570         8938 :           call xgBlock_zero(lobpcg%AP)
     571         8938 :           call xgBlock_zero(lobpcg%cprjP)
     572         8938 :           if ( ierr /= 0 ) then
     573            0 :             ABI_COMMENT("B-orthonormalization (XW) did not work.")
     574              :           end if
     575              :           call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
     576              :            & lobpcg%prtvol,tim_RR_XW,gpu_option,tolerance=tolerance,&
     577              :            & XW=lobpcg%XW,W=lobpcg%W,cprjXW=lobpcg%cprjXW,cprjW=lobpcg%cprjW,AW=lobpcg%AW,&
     578              :            & P=lobpcg%P,cprjP=lobpcg%cprjP,AP=lobpcg%AP,WP=lobpcg%WP,cprjWP=lobpcg%cprjWP,&
     579         8938 :            & AWP=lobpcg%AWP,blockdim_cprj=blockdim_cprj,add_Anl=.True.)
     580         8938 :           if ( ierr /= 0 ) then
     581            0 :             ABI_WARNING("RayleighRitz (XW) did not work, but continue anyway.")
     582              :             exit
     583              :           end if
     584              :         else
     585              :           ! B-orthonormalize P, BP
     586              :           call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%XWP%self,lobpcg%cprjXWP%self,&
     587        49566 :             & ierr,tim_Bortho_XWP,gpu_option,AX=lobpcg%AXWP%self,blockdim_cprj=blockdim_cprj)
     588              :           ! Do RR on XWP to get the eigen vectors
     589        49566 :           if ( ierr == 0 ) then
     590              :             call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
     591              :              & lobpcg%prtvol,tim_RR_XWP,gpu_option,tolerance=tolerance,&
     592              :              & XW=lobpcg%XW,W=lobpcg%W,cprjXW=lobpcg%cprjXW,cprjW=lobpcg%cprjW,AW=lobpcg%AW,&
     593              :              & P=lobpcg%P,cprjP=lobpcg%cprjP,AP=lobpcg%AP,WP=lobpcg%WP,cprjWP=lobpcg%cprjWP,&
     594        49566 :              & AWP=lobpcg%AWP,XWP=lobpcg%XWP%self,cprjXWP=lobpcg%cprjXWP%self,blockdim_cprj=blockdim_cprj,add_Anl=.True.)
     595        49566 :              if ( ierr /= 0 ) then
     596            0 :                ABI_WARNING("RayleighRitz (XWP) did not work, but continue anyway.")
     597              :                exit
     598              :              end if
     599              :           else
     600            0 :             ABI_COMMENT("B-orthonormalization (XWP) did not work, try on XW.")
     601              :             call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,lobpcg%XW,lobpcg%cprjXW,&
     602            0 :               & ierr,tim_Bortho_XW,gpu_option,AX=lobpcg%AXW,blockdim_cprj=blockdim_cprj)
     603            0 :             if ( ierr /= 0 ) then
     604            0 :               ABI_COMMENT("B-orthonormalization (XW) did not work.")
     605              :             end if
     606            0 :             call xgBlock_zero(lobpcg%P)
     607            0 :             call xgBlock_zero(lobpcg%AP)
     608            0 :             call xgBlock_zero(lobpcg%cprjP)
     609            0 :             nrestart = nrestart + 1
     610              :             call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%AX,eigenvaluesN,ierr,&
     611              :              & lobpcg%prtvol,tim_RR_XW,gpu_option,tolerance=tolerance,&
     612              :              & XW=lobpcg%XW,W=lobpcg%W,cprjXW=lobpcg%cprjXW,cprjW=lobpcg%cprjW,AW=lobpcg%AW,&
     613              :              & P=lobpcg%P,cprjP=lobpcg%cprjP,AP=lobpcg%AP,WP=lobpcg%WP,cprjWP=lobpcg%cprjWP,&
     614            0 :              & AWP=lobpcg%AWP,blockdim_cprj=blockdim_cprj,add_Anl=.True.)
     615            0 :              if ( ierr /= 0 ) then
     616            0 :                ABI_WARNING("RayleighRitz (XW) did not work, but continue anyway.")
     617              :                exit
     618              :              end if
     619              :             end if
     620              :         end if
     621              : 
     622              :       end do
     623              : 
     624        16592 :       if ( compute_residu ) then
     625              :         ! Recompute AX-Lambda*BX for the last time
     626         7379 :         call timab(tim_copy,1,tsec)
     627         7379 :         call xgBlock_copy(lobpcg%AX,lobpcg%W)
     628         7379 :         call timab(tim_copy,2,tsec)
     629         7379 :         call timab(tim_ax_nl,1,tsec)
     630         7379 :         if (lobpcg%xg_nonlop%paw) then
     631              :           call xg_nonlop_getHmeSX(lobpcg%xg_nonlop,lobpcg%X,lobpcg%cprjX,lobpcg%W,eigenvaluesN,&
     632         6305 :             lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
     633              :         else
     634              :           call xg_nonlop_getHX(lobpcg%xg_nonlop,lobpcg%W,lobpcg%cprjX,&
     635         1074 :             lobpcg%cprj_work%self,lobpcg%cprj_work2%self)
     636         1074 :           call xgBlock_yxmax(lobpcg%W,eigenvaluesN,lobpcg%X)
     637              :         end if
     638         7379 :         call timab(tim_ax_nl,2,tsec)
     639              :         ! Recompute residu norm here !
     640         7379 :         call timab(tim_maxres,1,tsec)
     641         7379 :         call xgBlock_colwiseNorm2(lobpcg%W,residuBlock)
     642         7379 :         call timab(tim_maxres,2,tsec)
     643              :         ! Apply preconditioner
     644         7379 :         call timab(tim_pcond,1,tsec)
     645         7379 :         call xgBlock_apply_diag(lobpcg%W,pcond,nspinor)
     646         7379 :         call timab(tim_pcond,2,tsec)
     647              : 
     648         7379 :         call timab(tim_nbdbuf,1,tsec)
     649         7379 :         if (nbdbuf>=0) then
     650         7379 :           call xgBlock_copy(residuBlock,residu_eff%self)
     651         7379 :           iband_min = 1 + blockdim*(iblock-1)
     652         7379 :           iband_max = blockdim*iblock
     653         7379 :           if (iband_max<=nband_eff) then ! all bands of this block are below nband_eff
     654         6871 :             call xgBlock_minmax(residu_eff%self,minResidu,maxResidu)
     655          508 :           else if (iband_min<=nband_eff) then ! some bands of this block are below nband_eff
     656          508 :             call xgBlock_minmax(residu_eff%self,minResidu,maxResidu,row_bound=(nband_eff-iband_min+1))
     657              :           else ! all bands of this block are above nband_eff
     658            0 :             minResidu = 0.0
     659            0 :             maxResidu = 0.0
     660              :           end if
     661            0 :         else if (nbdbuf==-101) then
     662            0 :           call xgBlock_minmax(residuBlock,minResidu,dummy) ! Get minimum of true residuals
     663              :           ! Compute effective residuals : res_eff = res * occ
     664            0 :           call xgBlock_apply_diag(residuBlock,occBlock,1,Y=residu_eff%self)
     665            0 :           call xgBlock_minmax(residu_eff%self,dummy,maxResidu) ! Get maximum of effective residuals
     666              :         else
     667            0 :           ABI_ERROR('Bad value of nbdbuf')
     668              :         end if
     669         7379 :         call timab(tim_nbdbuf,2,tsec)
     670              :       end if
     671              : 
     672        16592 :       if (prtvol==5.and.xmpi_comm_rank(lobpcg%spacecom)==0) then
     673            0 :         write(msg,'(6(a,i4),2(a,es16.6))') 'lobpcg | istep=',istep,'| isppol=',isppol,'| ikpt=',ikpt,&
     674            0 :           & '| inonsc=',inonsc,'| iblock=',iblock,'| nline_done=',iline-1,'| minRes=',minResidu,'| maxRes=',maxResidu
     675            0 :         call wrtout(std_out,msg,'PERS')
     676              :       end if
     677              : 
     678              :       ! Save eigenvalues
     679        16592 :       call timab(tim_copy,1,tsec)
     680        16592 :       call xgBlock_setBlock(eigen,eigenBlock,blockdim,1,fcol=iblock)
     681        16592 :       call xgBlock_copy(eigenvaluesN,eigenBlock)
     682        16592 :       call timab(tim_copy,2,tsec)
     683              : 
     684              :       ! Save new X in X0
     685        16592 :       call lobpcg_setX0(lobpcg,iblock)
     686              : 
     687              :       ! Copy previous BX into BX0 for previous block
     688        20628 :       if ( nblock > 1 ) then
     689        16560 :         call lobpcg_transferAX_BX(lobpcg,iblock)
     690              :       end if
     691              : 
     692              :     end do !! End iblock loop
     693              : 
     694         4036 :     call xgBlock_reshape(eigen,blockdim*nblock,1)
     695         4036 :     call xgBlock_reshape(residu,blockdim*nblock,1)
     696         4036 :     call xgBlock_reshape(occ,blockdim*nblock,1)
     697              : 
     698         4036 :     call xg_free(eigenvalues3N)
     699         4036 :     call xg_free(residu_eff)
     700              : 
     701         4036 :     skip = .false.
     702         4036 :     if ( ierr /= 0 ) then
     703            0 :       ABI_COMMENT("Some errors happened, so H|Psi> and S|Psi> are computed before leaving")
     704            0 :       if ( lobpcg%paral_kgb == 1 ) then
     705              :         call xgTransposer_constructor(lobpcg%xgTransposerAllX0,lobpcg%AllX0,lobpcg%AllX0ColsRows,nspinor,&
     706            0 :           STATE_LINALG,TRANS_ALL2ALL,lobpcg%comm_rows,lobpcg%comm_cols,0,0,lobpcg%me_g0_fft)
     707              :         call xgTransposer_copyConstructor(lobpcg%xgTransposerAllAX0,lobpcg%xgTransposerAllX0,&
     708            0 :           lobpcg%AllAX0%self,lobpcg%AllAX0ColsRows,STATE_LINALG)
     709              :       else
     710            0 :         call xgBlock_setBlock(lobpcg%AllX0      , lobpcg%AllX0ColsRows , spacedim, lobpcg%neigenpairs)
     711            0 :         call xgBlock_setBlock(lobpcg%AllAX0%self, lobpcg%AllAX0ColsRows, spacedim, lobpcg%neigenpairs)
     712              :       end if
     713            0 :       if (lobpcg%paral_kgb == 1) then
     714            0 :         call timab(tim_transpose,1,tsec)
     715            0 :         call xgTransposer_transpose(lobpcg%xgTransposerAllX0,STATE_COLSROWS)
     716            0 :         lobpcg%xgTransposerAllAX0%state=STATE_COLSROWS
     717            0 :         call timab(tim_transpose,2,tsec)
     718              :       end if
     719            0 :       call timab(tim_ax_v,1,tsec)
     720            0 :       call getAX(lobpcg%AllX0ColsRows,lobpcg%AllAX0ColsRows)
     721            0 :       call xgBlock_zero_im_g0(lobpcg%AllAX0ColsRows)
     722            0 :       call timab(tim_ax_v,2,tsec)
     723            0 :       if (lobpcg%paral_kgb == 1) then
     724            0 :         call timab(tim_transpose,1,tsec)
     725            0 :         call xgTransposer_transpose(lobpcg%xgTransposerAllX0,STATE_LINALG)
     726            0 :         call xgTransposer_transpose(lobpcg%xgTransposerAllAX0,STATE_LINALG)
     727            0 :         call timab(tim_transpose,2,tsec)
     728              :       end if
     729              : 
     730            0 :       call timab(tim_ax_k,1,tsec)
     731            0 :       call xgBlock_add_diag(lobpcg%AllX0,kin,nspinor,lobpcg%AllAX0%self)
     732            0 :       call timab(tim_ax_k,2,tsec)
     733              : 
     734            0 :       call xgTransposer_free(lobpcg%xgTransposerAllX0)
     735            0 :       call xgTransposer_free(lobpcg%xgTransposerAllAX0)
     736              :       skip = .true.
     737              :     end if
     738              : 
     739              :     if (.not.skip) then
     740              : 
     741         4036 :       if ( nblock > 1 ) then
     742         4004 :         call timab(tim_cprj,1,tsec)
     743         4004 :         call xg_init(cprj_work_all,space(cprjX0),rows(cprjX0),cols(cprjX0),comm(cprjX0))
     744              :         ! cprj computation could be avoided, with MPI comm instead
     745         4004 :         call xg_nonlop_getcprj(lobpcg%xg_nonlop,X0,cprjX0,cprj_work_all%self)
     746         4004 :         call xg_free(cprj_work_all)
     747         4004 :         call timab(tim_cprj,2,tsec)
     748              :         call xg_Borthonormalize_cprj(lobpcg%xg_nonlop,X0,cprjX0,&
     749         4004 :           & ierr,tim_Bortho_Xall,gpu_option,AX=lobpcg%AllAX0%self)
     750              :         call xg_RayleighRitz_cprj(lobpcg%xg_nonlop,X0,cprjX0,lobpcg%AllAX0%self,eigen,ierr,&
     751         4004 :           & lobpcg%prtvol,tim_RR_Xall,gpu_option,add_Anl=.True.)
     752              :       end if
     753              : 
     754              :     end if
     755              : 
     756         4036 :     if ( lobpcg%paral_kgb == 1 ) then
     757         2684 :       call xgTransposer_free(lobpcg%xgTransposerX)
     758         2684 :       call xgTransposer_free(lobpcg%xgTransposerAX)
     759         2684 :       call xgTransposer_free(lobpcg%xgTransposerW)
     760         2684 :       call xgTransposer_free(lobpcg%xgTransposerAW)
     761              :     end if
     762              : 
     763         4036 :     if (.not.lobpcg%xg_nonlop%paw) then
     764          816 :       call timab(tim_enl,1,tsec)
     765          816 :       call xg_init(cprj_work_all,space(cprjX0),rows(cprjX0),cols(cprjX0),comm(cprjX0))
     766          816 :       call xg_nonlop_colwiseXHX(lobpcg%xg_nonlop,cprjX0,cprj_work_all%self,enl)
     767          816 :       call xg_free(cprj_work_all)
     768          816 :       call timab(tim_enl,2,tsec)
     769              :     end if
     770              : 
     771         4036 :   end subroutine lobpcg_run_cprj
     772              : 
     773        16592 :   subroutine lobpcg_getX0(lobpcg,iblock)
     774              : 
     775              :     type(lobpcg_t) , intent(inout)  :: lobpcg
     776              :     integer        , intent(in   )  :: iblock
     777              :     type(xgBlock_t) :: Xtmp,cprjXtmp
     778              :     integer :: blockdim
     779              :     integer :: spacedim
     780              :     integer :: cprjdim
     781              :     integer :: blockdim_cprj
     782              :     double precision :: tsec(2)
     783              : 
     784        16592 :     call timab(tim_copy,1,tsec)
     785              : 
     786        16592 :     blockdim = lobpcg%blockdim
     787        16592 :     spacedim = lobpcg%spacedim
     788              : 
     789        16592 :     cprjdim       = lobpcg%cprjdim
     790        16592 :     blockdim_cprj = lobpcg%blockdim_cprj
     791              : 
     792        16592 :     call xgBlock_setBlock(lobpcg%AllX0,Xtmp,spacedim,blockdim,fcol=(iblock-1)*blockdim+1)
     793        16592 :     call xgBlock_copy(Xtmp,lobpcg%X)
     794              : 
     795        16592 :     call xgBlock_setBlock(lobpcg%AllcprjX0,cprjXtmp,cprjdim,blockdim_cprj,fcol=(iblock-1)*blockdim_cprj+1)
     796        16592 :     call xgBlock_copy(cprjXtmp,lobpcg%cprjX)
     797              : 
     798        16592 :     call timab(tim_copy,2,tsec)
     799              : 
     800        16592 :   end subroutine lobpcg_getX0
     801              : 
     802              : 
     803        12556 :   subroutine lobpcg_setPreviousX0(lobpcg,iblock)
     804              : 
     805              :     type(lobpcg_t) , intent(inout) :: lobpcg
     806              :     integer        , intent(in   ) :: iblock
     807              : 
     808        12556 :     if (iblock<2) then
     809            0 :       ABI_ERROR("iblock<2")
     810              :     end if
     811        12556 :     call xgBlock_setBlock(lobpcg%AllX0    ,lobpcg%X0    ,lobpcg%spacedim,(iblock-1)*lobpcg%blockdim)
     812        12556 :     call xgBlock_setBlock(lobpcg%AllcprjX0,lobpcg%cprjX0,lobpcg%cprjdim ,(iblock-1)*lobpcg%blockdim_cprj)
     813        12556 :   end subroutine lobpcg_setPreviousX0
     814              : 
     815        44954 :   subroutine lobpcg_orthoXwrtBlocks(lobpcg,var,cprjvar,iblock,cprj_work)
     816              : 
     817              :     type(lobpcg_t) , intent(inout) :: lobpcg
     818              :     type(xgBlock_t), intent(inout) :: var
     819              :     type(xgBlock_t), intent(inout) :: cprjvar
     820              :     type(xgBlock_t), intent(inout) :: cprj_work
     821              :     integer        , intent(in   ) :: iblock
     822              :     integer :: previousBlock
     823              :     integer :: blockdim
     824              :     integer :: spacedim
     825              :     integer :: space_buf
     826              :     integer :: nspinor,cprjdim
     827              :     type(xg_t) :: buffer
     828              :     double precision :: tsec(2)
     829              :     type(xgBlock_t) :: cprjX0_spinor,cprj_work_spinor
     830              : 
     831        44954 :     call timab(tim_ortho,1,tsec)
     832              : 
     833        44954 :     if (iblock<2) then
     834            0 :       ABI_ERROR("iblock<2")
     835              :     end if
     836              : 
     837        44954 :     if (cols(cprjvar)/=cols(cprj_work)) then
     838            0 :       ABI_ERROR("cprjvar and cprj_work should have same number of columns")
     839              :     end if
     840        44954 :     blockdim = lobpcg%blockdim
     841        44954 :     spacedim = lobpcg%spacedim
     842        44954 :     previousBlock = (iblock-1)*lobpcg%blockdim
     843              : 
     844        44954 :     cprjdim = lobpcg%xg_nonlop%cprjdim
     845        44954 :     nspinor = lobpcg%xg_nonlop%nspinor
     846              : 
     847        44954 :     space_buf = space(var)
     848        44954 :     if (space(var)==SPACE_CR) then
     849        20858 :       space_buf = SPACE_R
     850              :     end if
     851        44954 :     call xg_init(buffer,space_buf,previousBlock,blockdim,lobpcg%spacecom)
     852              : 
     853              :     ! buffer = X0^T*X
     854        44954 :     call xgBlock_gemm('t','n',1.0d0,lobpcg%X0,var,0.d0,buffer%self,comm=lobpcg%spacecom)
     855              : 
     856              :     ! Add the nonlocal part if paw
     857        44954 :     if (lobpcg%xg_nonlop%paw) then
     858        37654 :       call xg_nonlop_getXSY(lobpcg%xg_nonlop,lobpcg%cprjX0,cprjvar,cprj_work,buffer%self)
     859              :     end if
     860              : 
     861              :     ! sum all process contribution
     862              :     ! X = - X0*(BX0^T*X) + X
     863        44954 :     call xgBlock_gemm('n','n',-1.0d0,lobpcg%X0,buffer%self,1.0d0,var)
     864              : 
     865        44954 :     call xgBlock_zero(cprj_work)
     866        44954 :     call xgBlock_reshape_spinor(cprj_work,cprj_work_spinor,nspinor,COLS2ROWS)
     867        44954 :     call xgBlock_reshape_spinor(lobpcg%cprjX0,cprjX0_spinor,nspinor,COLS2ROWS)
     868              :     call xgBlock_gemm_mpi_cyclic_permutation(cprjX0_spinor,buffer%self,cprj_work_spinor,&
     869        44954 :       & lobpcg%xg_nonlop%me_band,blocksize=lobpcg%blockdim_cprj/nspinor,comm=lobpcg%xg_nonlop%comm_band)
     870        44954 :     call xgBlock_saxpy(cprjvar,-1.0d0,cprj_work)
     871              : 
     872        44954 :     call xg_free(buffer)
     873              : 
     874        44954 :     call timab(tim_ortho,2,tsec)
     875              : 
     876        44954 :   end subroutine lobpcg_orthoXwrtBlocks
     877              : 
     878        16592 :   subroutine lobpcg_setX0(lobpcg,iblock)
     879              : 
     880              :     type(lobpcg_t)  , intent(inout) :: lobpcg
     881              :     integer         , intent(in   ) :: iblock
     882              :     type(xgBlock_t) :: Xtmp,cprjXtmp
     883              :     integer :: blockdim
     884              :     integer :: spacedim
     885              :     integer :: cprjdim
     886              :     integer :: blockdim_cprj
     887              :     double precision :: tsec(2)
     888              : 
     889        16592 :     call timab(tim_copy,1,tsec)
     890        16592 :     blockdim = lobpcg%blockdim
     891        16592 :     spacedim = lobpcg%spacedim
     892              : 
     893        16592 :     cprjdim       = lobpcg%cprjdim
     894        16592 :     blockdim_cprj = lobpcg%blockdim_cprj
     895              : 
     896              :     !X0(:,(iblock-1)*blockdim+1:iblock*blockdim) = lobpcg%XWP(:,lobpcg%X+1:lobpcg%X+blockdim)
     897        16592 :     call xgBlock_setBlock(lobpcg%AllX0,Xtmp,spacedim,blockdim,fcol=(iblock-1)*blockdim+1)
     898        16592 :     call xgBlock_copy(lobpcg%X,Xtmp)
     899              : 
     900        16592 :     call xgBlock_setBlock(lobpcg%AllcprjX0,cprjXtmp,cprjdim,blockdim_cprj,fcol=(iblock-1)*blockdim_cprj+1)
     901        16592 :     call xgBlock_copy(lobpcg%cprjX,cprjXtmp)
     902        16592 :     call timab(tim_copy,2,tsec)
     903              : 
     904        16592 :   end subroutine lobpcg_setX0
     905              : 
     906        16560 :   subroutine lobpcg_transferAX_BX(lobpcg,iblock)
     907              : 
     908              :     type(lobpcg_t), intent(inout) :: lobpcg
     909              :     integer       , intent(in   ) :: iblock
     910              :     type(xgBlock_t) :: CXtmp
     911              :     integer :: firstcol
     912              :     double precision :: tsec(2)
     913              : 
     914        16560 :     call timab(tim_copy,1,tsec)
     915              : 
     916        16560 :     if (iblock<1) then
     917            0 :       ABI_ERROR("iblock<1")
     918              :     end if
     919              : 
     920              :     ! iblock goes from 1 to nblock-1 included
     921        16560 :     firstcol = (iblock-1)*lobpcg%blockdim+1  ! Start of each block
     922              : 
     923              :     ! AX
     924        16560 :     call xg_setBlock(lobpcg%AllAX0,CXtmp,lobpcg%spacedim,lobpcg%blockdim,fcol=firstcol)
     925        16560 :     call xgBlock_copy(lobpcg%AX,CXtmp)
     926              : 
     927        16560 :     call timab(tim_copy,2,tsec)
     928              : 
     929        16560 :   end subroutine lobpcg_transferAX_BX
     930              : 
     931         8072 :   subroutine lobpcg_free(lobpcg)
     932              : 
     933              :     type(lobpcg_t), intent(inout) :: lobpcg
     934              : 
     935         8072 :     call xg_free(lobpcg%XWP)
     936         8072 :     call xg_free(lobpcg%AXWP)
     937         8072 :     call xg_free(lobpcg%cprjXWP)
     938         8072 :     call xg_free(lobpcg%cprj_work)
     939         8072 :     call xg_free(lobpcg%cprj_work2)
     940         8072 :     call xg_free(lobpcg%AllAX0)
     941              : 
     942         8072 :   end subroutine lobpcg_free
     943              : 
     944            0 : end module m_lobpcg2_cprj
     945              : !!***
        

Generated by: LCOV version 2.3-1