LCOV - code coverage report
Current view: top level - src/45_xgTools - m_xg.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 54.1 % 1944 1051
Test Date: 2026-09-21 19:39:32 Functions: 59.3 % 108 64

            Line data    Source code
       1              : !!****m* ABINIT/m_xgTools
       2              : !! NAME
       3              : !!  m_xgTools
       4              : !!
       5              : !! FUNCTION
       6              : !! This is a module to manage and help developer with 2D arrays for low level routines.
       7              : !! Particularly, it manages memory for allocations and deallocations (see xg_routines),
       8              : !! It handles MPI, complex and real values (*8 kind only) automatically.
       9              : !! It is also possible to build sub-block of an array and work on it very easily (see xgBlock_routines)
      10              : !! Several routines are also available for performing blas/lapack which again
      11              : !! manage the type and MPI (and openmp if needed)
      12              : !! Almost all routines are timed by abinit timers
      13              : !! This is a starting point and has to be improved/developed
      14              : !! An example of how to use those types and routines can be found in
      15              : !! 30_diago/m_lobpcg2.F90. This is a full rewrite of LOBPCG algorithm which uses
      16              : !! only these types to perfom calculations.
      17              : !!
      18              : !! COPYRIGHT
      19              : !!  Copyright (C) 2016-2026 ABINIT group (J. Bieder, MS, L. Baguet, IML)
      20              : !!  This file is distributed under the terms of the
      21              : !!  GNU General Public License, see ~abinit/COPYING
      22              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      23              : !!
      24              : !! NOTES
      25              : !!
      26              : !! SOURCE
      27              : 
      28              : #if defined HAVE_CONFIG_H
      29              : #include "config.h"
      30              : #endif
      31              : 
      32              : #include "abi_common.h"
      33              : 
      34              : module m_xg
      35              : 
      36              :   use, intrinsic :: iso_c_binding, only: c_loc, c_double, c_double_complex, c_int32_t, c_size_t, c_ptr
      37              : 
      38              :   USE_MPI
      39              :   use m_errors
      40              :   use m_abicore
      41              :   use defs_basis
      42              :   use m_time, only : timab
      43              :   use m_xmpi
      44              :   use m_xomp
      45              :   use m_gputk
      46              :   use m_abi_linalg
      47              :   use m_hide_blas, only : xdotc
      48              : 
      49              : #if defined(HAVE_GPU)
      50              :   use m_gpu_toolbox
      51              : #endif
      52              : 
      53              : #if defined(HAVE_KOKKOS)
      54              :   use m_xg_kokkos
      55              : #endif
      56              : 
      57              : #if defined HAVE_YAKL
      58              :  use gator_mod
      59              : #endif
      60              : 
      61              :   implicit none
      62              : 
      63              :   private
      64              : 
      65              :   integer, parameter, public :: SPACE_R =  1
      66              :   integer, parameter, public :: SPACE_C =  2
      67              :   integer, parameter, public :: SPACE_CR = 3
      68              : 
      69              :   integer, parameter, public :: SMALL2BIG =  1
      70              :   integer, parameter, public :: BIG2SMALL = -1
      71              : 
      72              :   integer, parameter, public :: COLS2ROWS =  1
      73              :   integer, parameter, public :: ROWS2COLS = -1
      74              : 
      75              :   integer, parameter :: tim_gemm_blas  = 1670
      76              :   integer, parameter :: tim_trsm       = 1671
      77              :   integer, parameter :: tim_potrf      = 1672
      78              :   integer, parameter :: tim_zero       = 1673
      79              :   integer, parameter :: tim_zero_im_g0 = 1674
      80              : !  integer, parameter :: tim_set        = 1673
      81              : !  integer, parameter :: tim_get        = 1674
      82              :   integer, parameter :: tim_heev       = 1675
      83              :   integer, parameter :: tim_heevd      = 1676
      84              :   integer, parameter :: tim_hpev       = 1677
      85              :   integer, parameter :: tim_hpevd      = 1678
      86              :   integer, parameter :: tim_hegv       = 1679
      87              :   integer, parameter :: tim_hegvx      = 1680
      88              :   integer, parameter :: tim_hegvd      = 1681
      89              :   integer, parameter :: tim_hpgv       = 1682
      90              :   integer, parameter :: tim_hpgvx      = 1683
      91              :   integer, parameter :: tim_hpgvd      = 1684
      92              :   integer, parameter :: tim_copy       = 1685
      93              :   integer, parameter :: tim_cshift     = 1686
      94              :   integer, parameter :: tim_pack       = 1687
      95              :   integer, parameter :: tim_gemm_mpi   = 1688
      96              :   integer, parameter :: tim_apply_diag = 1689
      97              :   integer, parameter :: tim_invertri   = 1696
      98              : 
      99              :   integer, parameter :: tim_scale       = 2000
     100              :   integer, parameter :: tim_colw_dot    = 2001
     101              :   integer, parameter :: tim_colw_mul    = 2002
     102              :   integer, parameter :: tim_colw_cymax  = 2003
     103              :   integer, parameter :: tim_colw_div    = 2004
     104              :   integer, parameter :: tim_colw_norm2  = 2005
     105              :   integer, parameter :: tim_saxpy       = 2006
     106              :   integer, parameter :: tim_minmax      = 2007
     107              :   integer, parameter :: tim_partialcopy = 2008
     108              :   integer, parameter :: tim_gemmcyclic  = 2009
     109              :   integer, parameter :: tim_yxmax       = 2010
     110              :   integer, parameter :: tim_ymax        = 2011
     111              :   integer, parameter :: tim_add         = 2012
     112              :   integer, parameter :: tim_add_diag    = 2013
     113              :   integer, parameter :: tim_invert      = 2014
     114              :   integer, parameter :: tim_invert_sy   = 2015
     115              :   integer, parameter :: tim_dot         = 2016
     116              : 
     117              :   integer, save, private :: lrwork = 0
     118              :   integer, save, private :: lcwork = 0
     119              :   integer, save, private :: liwork = 0
     120              :   integer,                        allocatable, save, private :: iwork(:)
     121              :   real(kind=c_double),            allocatable, save, private :: rwork(:)
     122              :   complex(kind=c_double_complex), allocatable, save, private :: cwork(:)
     123              : 
     124              :   type, public :: xgBlock_t
     125              :     integer, private :: space
     126              :     integer, private :: rows
     127              :     integer, private :: LDim
     128              :     integer, private :: cols
     129              :     integer, private :: me_g0
     130              :     character, public :: trans
     131              :     character, public :: normal
     132              :     integer, private :: spacedim_comm
     133              :     integer, private :: gpu_option
     134              :     real(kind=c_double)            , ABI_CONTIGUOUS pointer, private :: vecR(:,:) => null()
     135              :     complex(kind=c_double_complex) , ABI_CONTIGUOUS pointer, private :: vecC(:,:) => null()
     136              :   end type xgBlock_t
     137              : 
     138              :   type, public :: xg_t
     139              :     integer, private :: space
     140              :     integer, private :: rows
     141              :     integer, private :: cols
     142              :     integer, private :: me_g0
     143              :     character, public :: trans
     144              :     character, public :: normal
     145              :     integer, private :: spacedim_comm
     146              :     !FIXME Settle this
     147              :     real(kind=c_double)            , ABI_CONTIGUOUS pointer, private :: vecR(:,:) => null()
     148              :     complex(kind=c_double_complex) , ABI_CONTIGUOUS pointer, private :: vecC(:,:) => null()
     149              :     integer, private :: gpu_option
     150              :     type(xgBlock_t), public :: self
     151              :   end type xg_t
     152              : 
     153              :   interface xgBlock_gemm
     154              :     module procedure xgBlock_gemmR
     155              :     module procedure xgBlock_gemmC
     156              :   end interface xgBlock_gemm
     157              : 
     158              :   interface xgBlock_saxpy
     159              :     module procedure xgBlock_saxpyR
     160              :     module procedure xgBlock_saxpyC
     161              :   end interface xgBlock_saxpy
     162              : 
     163              :   interface xgBlock_dot
     164              :     module procedure xgBlock_dotC
     165              :   end interface xgBlock_dot
     166              : 
     167              :   interface xgBlock_colwiseMul
     168              :     module procedure xgBlock_colwiseMulR
     169              :     module procedure xgBlock_colwiseMulC
     170              :   end interface xgBlock_colwiseMul
     171              : 
     172              :   interface xgBlock_trsm
     173              :     module procedure xgBlock_trsmR
     174              :     module procedure xgBlock_trsmC
     175              :   end interface xgBlock_trsm
     176              : 
     177              :   interface xgBlock_scale
     178              :     module procedure xgBlock_scaleR
     179              :     module procedure xgBlock_scaleC
     180              :   end interface xgBlock_scale
     181              : 
     182              :   interface xgBlock_reverseMap
     183              :     module procedure xgBlock_reverseMapR
     184              :     module procedure xgBlock_reverseMapC
     185              :   end interface xgBlock_reverseMap
     186              : 
     187              :   interface xgBlock_reverseMap_1d
     188              :     module procedure xgBlock_reverseMap_1dR
     189              :     module procedure xgBlock_reverseMap_1dC
     190              :   end interface xgBlock_reverseMap_1d
     191              : 
     192              :   interface checkResize
     193              :     module procedure checkResizeI
     194              :     module procedure checkResizeR
     195              :     module procedure checkResizeC
     196              :   end interface checkResize
     197              : 
     198              :   public :: space
     199              :   public :: cols
     200              :   public :: rows
     201              :   public :: comm
     202              :   public :: gpu_option
     203              :   public :: me_g0
     204              :   public :: xgBlock_setComm
     205              :   private :: getClocR
     206              :   private :: getClocC
     207              :   private :: checkResize
     208              : 
     209              :   public :: xg_init ! IL-10/03/25: on GPU- Contains OMP call to free/allocate memory on GPU
     210              :   public :: xg_set ! LB-06/03/24: Be careful, this routine is not used (so not tested)
     211              :   public :: xg_get ! LB-06/03/24: Be careful, this routine is not used (so not tested)
     212              :   public :: xg_setBlock
     213              :   public :: xg_free
     214              : 
     215              :   public :: xg_associated
     216              : 
     217              :   public :: xgBlock_setBlock
     218              :   public :: xgBlock_set ! LB-06/03/24: Be careful, this routine is not used (so not tested)
     219              :   public :: xgBlock_map ! IL-10/03/25: on GPU- Contains safe OMP call with target presence check
     220              :   public :: xgBlock_map_1d
     221              :   public :: xgBlock_reverseMap
     222              :   public :: xgBlock_reverseMap_1d
     223              :   public :: xgBlock_prefetch_async
     224              :   public :: xgBlock_get ! LB-06/03/24: Be careful, this routine is not used (so not tested)
     225              :   public :: xgBlock_copy ! IL-10/03/25: on GPU- Contains hidden one-way OMP calls (implicit H2D or D2H)
     226              :   public :: xgBlock_colwiseSwap
     227              :   public :: xgBlock_partialcopy
     228              :   public :: xgBlock_permuteCols
     229              :   public :: xgBlock_hermitian_pd_cond ! computes condition number of Hermitian positive definite
     230              :   public :: xgBlock_spd_cond ! condition matrix for symmetric positive definite
     231              :   public :: xgBlock_pack
     232              :   public :: xgBlock_getSize
     233              :   public :: xgBlock_get_gpu_option
     234              :   public :: xgBlock_get_communicator
     235              : 
     236              :   public :: xgBlock_check
     237              :   public :: xgBlock_check_gpu_option
     238              : 
     239              :   public :: xgBlock_potrf
     240              :   public :: xgBlock_trsm
     241              : 
     242              :   public :: xgBlock_heev
     243              :   public :: xgBlock_heevd
     244              : 
     245              :   public :: xgBlock_hpev
     246              :   public :: xgBlock_hpevd
     247              : 
     248              :   public :: xgBlock_hegv
     249              :   public :: xgBlock_hegvx
     250              :   public :: xgBlock_hegvd
     251              : 
     252              :   public :: xgBlock_hpgv
     253              :   public :: xgBlock_hpgvx
     254              :   public :: xgBlock_hpgvd
     255              : 
     256              :   public :: xgBlock_gemm
     257              :   public :: xgBlock_trmmR
     258              :   public :: xgBlock_add
     259              :   public :: xgBlock_cshift
     260              :   public :: xgBlock_colwiseNorm2
     261              :   public :: xgBlock_colwiseDotProduct
     262              :   public :: xgBlock_colwiseDivision
     263              :   public :: xgBlock_ymax
     264              :   public :: xgBlock_yxmax
     265              :   public :: xgBlock_colwiseCymax
     266              :   public :: xgBlock_saxpy
     267              :   public :: xgBlock_dot
     268              :   public :: xgBlock_colwiseMul
     269              :   public :: xgBlock_scale
     270              :   public :: xgBlock_transpose
     271              :   public :: xgBlock_r2c
     272              :   public :: xgBlock_c2r
     273              : 
     274              :   public :: xgBlock_apply_diag
     275              :   public :: xgBlock_add_diag
     276              : 
     277              :   public :: xgBlock_mpi_sum
     278              :   public :: xgBlock_mpi_send
     279              :   public :: xgBlock_mpi_isend
     280              :   public :: xgBlock_mpi_recv
     281              :   public :: xgBlock_gemm_mpi_cyclic_permutation
     282              : 
     283              :   public :: xgBlock_invert
     284              :   public :: xgBlock_invert_sy
     285              :   public :: xgBlock_invert_tri
     286              :   public :: xgBlock_yxpa
     287              : 
     288              :   public :: xgBlock_zero
     289              :   public :: xgBlock_zerotri
     290              :   public :: xgBlock_zero_im_g0
     291              :   public :: xgBlock_one
     292              :   public :: xgBlock_ones
     293              :   public :: xgBlock_diagonal
     294              :   public :: xgBlock_diagonalOnly
     295              : 
     296              :   public :: xgBlock_colwiseRandom
     297              :   public :: xgBlock_colwiseRandomGaussian
     298              :   public :: xgBlock_colwiseRandomRademacher
     299              :   public :: xgBlock_randomSketching
     300              : 
     301              :   public :: xgBlock_minmax
     302              :   public :: xgBlock_average
     303              :   public :: xgBlock_deviation
     304              : 
     305              :   public :: xgBlock_reshape
     306              :   public :: xgBlock_reshape_spinor
     307              :   public :: xgBlock_free_reshape
     308              :   public :: xgBlock_print
     309              :   public :: xgBlock_getid
     310              :   public :: xgBlock_get_im_g0
     311              :   public :: xgBlock_copy_from_gpu ! TODO IL-10/03/25: on GPU- Contains unsafe OMP call to copy memory from GPU
     312              :   public :: xgBlock_copy_to_gpu ! TODO IL-10/03/25: on GPU- Contains unsafe OMP call to copy memory to GPU
     313              :   public :: xg_finalize
     314              : 
     315              : contains
     316              :   !!***
     317              : 
     318              :   !!****f* m_xg/checkResizeI
     319              :   !!
     320              :   !! NAME
     321              :   !! checkResizeI
     322              : 
     323       818027 :   subroutine checkResizeI(array,current_dim,asked_dim)
     324              : 
     325              :     integer, allocatable, intent(inout) :: array(:)
     326              :     integer, intent(inout)  :: current_dim
     327              :     integer, intent(in   )  :: asked_dim
     328              : 
     329       818027 :     if ( current_dim < asked_dim  ) then
     330         1822 :       current_dim = asked_dim
     331         1822 :       if ( allocated(array) ) then
     332         1186 :         ABI_FREE(array)
     333              :       end if
     334         5466 :       ABI_MALLOC(array,(asked_dim))
     335              :     end if
     336              : 
     337       818027 :   end subroutine checkResizeI
     338              :   !!***
     339              : 
     340              :   !!****f* m_xg/checkResizeR
     341              :   !!
     342              :   !! NAME
     343              :   !! checkResizeR
     344              : 
     345       818027 :   subroutine checkResizeR(array,current_dim,asked_dim)
     346              : 
     347              :     double precision, allocatable, intent(inout) :: array(:)
     348              :     integer, intent(inout) :: current_dim
     349              :     integer, intent(in   ) :: asked_dim
     350              : 
     351       818027 :     if ( current_dim < asked_dim  ) then
     352         1822 :       current_dim = asked_dim
     353         1822 :       if ( allocated(array) ) then
     354         1186 :         ABI_FREE(array)
     355              :       end if
     356         5466 :       ABI_MALLOC(array,(asked_dim))
     357              :     end if
     358              : 
     359       818027 :   end subroutine checkResizeR
     360              :   !!***
     361              : 
     362              :   !!****f* m_xg/checkResizeC
     363              :   !!
     364              :   !! NAME
     365              :   !! checkResizeC
     366              : 
     367       713741 :   subroutine checkResizeC(array,current_dim,asked_dim)
     368              : 
     369              :     complex(kind=8), allocatable, intent(inout) :: array(:)
     370              :     integer, intent(inout)  :: current_dim
     371              :     integer, intent(in   )  :: asked_dim
     372              : 
     373              : 
     374       713741 :     if ( current_dim < asked_dim  ) then
     375         1903 :       current_dim = asked_dim
     376         1903 :       if ( allocated(array) ) then
     377         1431 :         ABI_FREE(array)
     378              :       end if
     379         5709 :       ABI_MALLOC(array,(asked_dim))
     380              :     end if
     381              : 
     382       713741 :   end subroutine checkResizeC
     383              :   !!***
     384              : 
     385              :   !!****f* m_xg/getClocR
     386              :   !!
     387              :   !! NAME
     388              :   !! getClocR
     389              : 
     390     22010863 :   function getClocR(rows,cols,array) result(cptr)
     391              :     use, intrinsic :: iso_c_binding
     392              :     integer, intent(in) :: rows
     393              :     integer, intent(in) :: cols
     394              :     double precision, target, intent(in) :: array(rows,cols)
     395              :     type(c_ptr) :: cptr
     396     22010863 :     cptr = c_loc(array)
     397              :   end function getClocR
     398              :   !!***
     399              : 
     400              :   !!****f* m_xg/getClocC
     401              :   !!
     402              :   !! NAME
     403              :   !! getClocC
     404              : 
     405     36101266 :   function getClocC(rows,cols,array) result(cptr)
     406              :     use, intrinsic :: iso_c_binding
     407              :     integer, intent(in) :: rows
     408              :     integer, intent(in) :: cols
     409              :     complex(kind=8), target, intent(in) :: array(rows,cols)
     410              :     type(c_ptr) :: cptr
     411     36101266 :     cptr = c_loc(array)
     412              :   end function getClocC
     413              :   !!***
     414              : 
     415              :   !!****f* m_xg/xg_init
     416              :   !!
     417              :   !! NAME
     418              :   !! xg_init
     419              : 
     420      9978918 :   subroutine xg_init(xg, space, rows, cols, comm, me_g0, gpu_option)
     421              : 
     422              :     type(xg_t), target, intent(inout) :: xg
     423              :     integer   , intent(in   ) :: space
     424              :     integer   , intent(in   ) :: rows
     425              :     integer   , intent(in   ) :: cols
     426              :     integer   , optional, intent(in) :: comm, me_g0, gpu_option
     427              :     integer                   :: l_gpu_option,fact
     428              : #if defined HAVE_GPU
     429              :     integer(kind=c_int32_t), parameter :: izero = 0
     430              : #endif
     431              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD && !defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
     432              :     complex(dp), pointer :: xg__vecC(:,:)
     433              :     real(dp), pointer :: xg__vecR(:,:)
     434              : #endif
     435              : 
     436      9978918 :     if ( rows < 1 ) then
     437            0 :       ABI_ERROR("rows < 1 ")
     438              :     endif
     439      9978918 :     if ( cols < 1 ) then
     440            0 :       ABI_ERROR("cols < 1 ")
     441              :     end if
     442              : 
     443              :     ! if optional parameter is present, use it
     444              :     ! else use default value, i.e. don't use GPU
     445      9978918 :     l_gpu_option = ABI_GPU_DISABLED
     446      9978918 :     if (present(gpu_option)) then
     447      3502992 :       l_gpu_option = gpu_option
     448              :     end if
     449              : 
     450      9978918 :     fact = 1 ; if (space==SPACE_CR) fact = 2
     451              : 
     452      9978918 :     if (l_gpu_option==ABI_GPU_KOKKOS) then
     453              : #if defined HAVE_GPU && defined HAVE_YAKL
     454              :       select case (space)
     455              :       case (SPACE_R,SPACE_CR)
     456              :         if ( associated(xg%vecR) ) then
     457              :           ABI_FREE_MANAGED(xg%vecR)
     458              :         end if
     459              :         ABI_MALLOC_MANAGED_BOUNDS(xg%vecR,(/fact*rows,cols/), (/1,1/))
     460              :         xg%trans = 't'
     461              :       case (SPACE_C)
     462              :         if ( associated(xg%vecC) ) then
     463              :           ABI_FREE_MANAGED(xg%vecC)
     464              :         end if
     465              :         ABI_MALLOC_MANAGED_BOUNDS(xg%vecC,(/rows,cols/), (/1,1/))
     466              :         xg%trans = 'c'
     467              :       case default
     468              :         ABI_ERROR("Invalid space")
     469              :       end select
     470              : #endif
     471              : 
     472      9978918 :     else if (l_gpu_option==ABI_GPU_OPENMP) then
     473              : 
     474              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
     475              :       select case (space)
     476              : 
     477              :       case (SPACE_R,SPACE_CR)
     478              :         if ( associated(xg%vecR) ) then
     479              :           !$OMP TARGET EXIT DATA MAP(delete:xg%vecR)
     480              :           ABI_FREE(xg%vecR)
     481              :         end if
     482              :         ABI_MALLOC(xg%vecR,(1:fact*rows,1:cols))
     483              :         xg%trans = 't'
     484              : #if defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
     485              :         !$OMP TARGET ENTER DATA MAP(alloc:xg%vecR)
     486              : #else
     487              : !FIXME For several compilers, OMP doesn't work correctly with structured types, so use pointers
     488              :         xg__vecR => xg%vecR
     489              :         !$OMP TARGET ENTER DATA MAP(alloc:xg__vecR)
     490              : #endif
     491              : 
     492              :       case (SPACE_C)
     493              :         if ( associated(xg%vecC) ) then
     494              :           !$OMP TARGET EXIT DATA MAP(delete:xg%vecC)
     495              :           ABI_FREE(xg%vecC)
     496              :         end if
     497              :         ABI_MALLOC(xg%vecC,(1:rows,1:cols))
     498              :         xg%trans = 'c'
     499              : #if defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
     500              :         !$OMP TARGET ENTER DATA MAP(alloc:xg%vecC)
     501              : #else
     502              : !FIXME For several compilers, OMP doesn't work correctly with structured types, so use pointers
     503              :         xg__vecC => xg%vecC
     504              :         !$OMP TARGET ENTER DATA MAP(alloc:xg__vecC)
     505              : #endif
     506              : 
     507              :       case default
     508              :         ABI_ERROR("Invalid space")
     509              :       end select
     510              : #endif
     511              : 
     512      9978918 :     else if ( l_gpu_option==ABI_GPU_DISABLED .or. l_gpu_option==ABI_GPU_LEGACY ) then
     513              : 
     514      3007497 :       select case (space)
     515              :       case (SPACE_R,SPACE_CR)
     516      3007497 :         if ( associated(xg%vecR) ) then
     517         2146 :           ABI_FREE(xg%vecR)
     518              :         end if
     519     12029988 :         ABI_MALLOC(xg%vecR,(1:fact*rows,1:cols))
     520      3007497 :         xg%trans = 't'
     521              :       case (SPACE_C)
     522      6971421 :         if ( associated(xg%vecC) ) then
     523         1478 :           ABI_FREE(xg%vecC)
     524              :         end if
     525     27885684 :         ABI_MALLOC(xg%vecC,(1:rows,1:cols))
     526      6971421 :         xg%trans = 'c'
     527              :       case default
     528      9978918 :         ABI_ERROR("Invalid space")
     529              :       end select
     530              : 
     531              :     else
     532            0 :         ABI_ERROR("Invalid gpu_option")
     533              :     end if
     534              : 
     535      9978918 :     xg%space = space
     536      9978918 :     xg%normal = 'n'
     537      9978918 :     xg%cols = cols
     538      9978918 :     xg%rows = rows
     539      9978918 :     xg%spacedim_comm = xmpi_comm_null
     540      9978918 :     xg%gpu_option = l_gpu_option
     541      9978918 :     xg%me_g0 = -1
     542              : 
     543      9978918 :     if ( present(comm) ) xg%spacedim_comm = comm
     544      9978918 :     if ( present(me_g0) ) then
     545      1212692 :       if (me_g0/=-1.and.me_g0/=0.and.me_g0/=1) then
     546            0 :         ABI_ERROR('Bad value of me_g0 in xg_init')
     547              :       else
     548      1212692 :         xg%me_g0 = me_g0
     549              :       end if
     550              :     end if
     551              : 
     552      9978918 :     call xg_setBlock(xg,xg%self,rows,cols)
     553      9978918 :     call xgBlock_zero(xg%self)
     554              : 
     555      9978918 :   end subroutine xg_init
     556              :   !!***
     557              : 
     558              :   !LB-06/03/24: Be careful, xg_set is not used anywhere in the code, so not tested...
     559              :   !!****f* m_xg/xg_set
     560              :   !!
     561              :   !! NAME
     562              :   !! xg_set
     563              : 
     564            0 :   subroutine xg_set(xg,array,shift_col,rows)
     565              : 
     566              :     type(xg_t), target, intent(inout) :: xg
     567              :     double precision, intent(in) :: array(:,:)
     568              :     integer, intent(in) :: shift_col
     569              :     integer, intent(in) :: rows
     570              :     integer :: cols
     571              :     integer :: col
     572              : !    double precision :: tsec(2)
     573              : 
     574              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
     575              :     complex(dp), pointer :: xg__vecC(:,:)
     576              :     real(dp), pointer :: xg__vecR(:,:)
     577              : #endif
     578              : 
     579              : !    call timab(tim_set,1,tsec)
     580              : 
     581            0 :     if ( size(array,dim=1) /= 2 ) then
     582            0 :       ABI_ERROR("First dim must be 2")
     583              :     end if
     584              : 
     585            0 :     cols = size(array,dim=2)/rows
     586            0 :     if ( shift_col+cols > xg%cols ) then
     587            0 :       ABI_WARNING("Ignore some columns, input array to large")
     588              :     endif
     589              : 
     590            0 :     if(xg%gpu_option == ABI_GPU_OPENMP) then
     591              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
     592              :       select case (xg%space)
     593              :       case (SPACE_R)
     594              :         xg__vecR => xg%vecR
     595              :         do col = 1, min(cols,xg%cols-shift_col)
     596              :           xg%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     597              :         end do
     598              :         !$OMP TARGET UPDATE TO(xg__vecR)
     599              :       case (SPACE_CR)
     600              :         xg__vecR => xg%vecR
     601              :         if ( xg%rows /= 2*rows ) then
     602              :           ABI_ERROR("Bad number of rows")
     603              :         end if
     604              : 
     605              :         do col = 1, min(cols,xg%cols-shift_col)
     606              :           xg%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     607              :           xg%vecR(rows+1:2*rows,shift_col+col) = array(2,(col-1)*rows+1:col*rows)
     608              :         end do
     609              :         !$OMP TARGET UPDATE TO(xg__vecR)
     610              :       case (SPACE_C)
     611              :         xg__vecC => xg%vecC
     612              :         do col = 1, min(cols,xg%cols-shift_col)
     613              :           xg%vecC(1:rows,shift_col+col) = dcmplx(array(1,(col-1)*rows+1:col*rows), &
     614              :             array(2,(col-1)*rows+1:col*rows))
     615              :         end do
     616              :         !$OMP TARGET UPDATE TO(xg__vecC)
     617              :       end select
     618              : #endif
     619              :     else
     620            0 :       select case (xg%space)
     621              :       case (SPACE_R)
     622            0 :         do col = 1, min(cols,xg%cols-shift_col)
     623            0 :           xg%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     624              :         end do
     625              :       case (SPACE_CR)
     626            0 :         if ( xg%rows /= 2*rows ) then
     627            0 :           ABI_ERROR("Bad number of rows")
     628              :         end if
     629              : 
     630            0 :         do col = 1, min(cols,xg%cols-shift_col)
     631            0 :           xg%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     632            0 :           xg%vecR(rows+1:2*rows,shift_col+col) = array(2,(col-1)*rows+1:col*rows)
     633              :         end do
     634              :       case (SPACE_C)
     635            0 :         do col = 1, min(cols,xg%cols-shift_col)
     636              :           xg%vecC(1:rows,shift_col+col) = dcmplx(array(1,(col-1)*rows+1:col*rows), &
     637            0 :             array(2,(col-1)*rows+1:col*rows))
     638              :         end do
     639              :       end select
     640              :     end if
     641              : 
     642              : !    call timab(tim_set,2,tsec)
     643              : 
     644            0 :   end subroutine xg_set
     645              :   !!***
     646              : 
     647              :   !LB-06/03/24: Be careful, xgBlock_set is not used anywhere in the code, so not tested...
     648              :   !!****f* m_xg/xgBlock_set
     649              :   !!
     650              :   !! NAME
     651              :   !! xgBlock_set
     652              : 
     653            0 :   subroutine xgBlock_set(xgBlock,array,shift_col,rows)
     654              : 
     655              :     type(xgBlock_t), intent(inout) :: xgBlock
     656              :     double precision, intent(in) :: array(:,:)
     657              :     integer, intent(in) :: shift_col
     658              :     integer, intent(in) :: rows
     659              :     integer :: cols
     660              :     integer :: col
     661              : !    double precision :: tsec(2)
     662              : 
     663              : !    call timab(tim_set,1,tsec)
     664              : 
     665            0 :     if ( size(array,dim=1) /= 2 ) then
     666            0 :       ABI_ERROR("First dim must be 2")
     667              :     end if
     668              : 
     669            0 :     cols = size(array,dim=2)/rows
     670            0 :     if ( shift_col+cols > xgBlock%cols ) then
     671            0 :       ABI_WARNING("Block Ignore some columns, input array to large")
     672              :     endif
     673              : 
     674            0 :     if(xgBlock%gpu_option==ABI_GPU_OPENMP) then
     675              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
     676              :       select case (xgBlock%space)
     677              :       case (SPACE_R)
     678              :         call xgBlock_copy_from_gpu(xgBlock)
     679              :         do col = 1, min(cols,xgBlock%cols-shift_col)
     680              :           xgBlock%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     681              :         end do
     682              :         call xgBlock_copy_to_gpu(xgBlock)
     683              :       case (SPACE_CR)
     684              :         if ( xgBlock%rows /= 2*rows ) then
     685              :           ABI_ERROR("Bad number of rows")
     686              :         end if
     687              : 
     688              :         call xgBlock_copy_from_gpu(xgBlock)
     689              :         do col = 1, min(cols,xgBlock%cols-shift_col)
     690              :           xgBlock%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     691              :           xgBlock%vecR(rows+1:2*rows,shift_col+col) = array(2,(col-1)*rows+1:col*rows)
     692              :         end do
     693              :         call xgBlock_copy_to_gpu(xgBlock)
     694              :       case (SPACE_C)
     695              :         call xgBlock_copy_from_gpu(xgBlock)
     696              :         do col = 1, min(cols,xgBlock%cols-shift_col)
     697              :           xgBlock%vecC(1:rows,shift_col+col) = dcmplx(array(1,(col-1)*rows+1:col*rows), &
     698              :             array(2,(col-1)*rows+1:col*rows))
     699              :         end do
     700              :         call xgBlock_copy_to_gpu(xgBlock)
     701              :       end select
     702              : #endif
     703              :     else
     704            0 :       select case (xgBlock%space)
     705              :       case (SPACE_R)
     706            0 :         do col = 1, min(cols,xgBlock%cols-shift_col)
     707            0 :           xgBlock%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     708              :         end do
     709              :       case (SPACE_CR)
     710            0 :         if ( xgBlock%rows /= 2*rows ) then
     711            0 :           ABI_ERROR("Bad number of rows")
     712              :         end if
     713              : 
     714            0 :         do col = 1, min(cols,xgBlock%cols-shift_col)
     715            0 :           xgBlock%vecR(1:rows,shift_col+col) = array(1,(col-1)*rows+1:col*rows)
     716            0 :           xgBlock%vecR(rows+1:2*rows,shift_col+col) = array(2,(col-1)*rows+1:col*rows)
     717              :         end do
     718              :       case (SPACE_C)
     719            0 :         do col = 1, min(cols,xgBlock%cols-shift_col)
     720              :           xgBlock%vecC(1:rows,shift_col+col) = dcmplx(array(1,(col-1)*rows+1:col*rows), &
     721            0 :             array(2,(col-1)*rows+1:col*rows))
     722              :         end do
     723              :       end select
     724              :     end if
     725              : 
     726              : !    call timab(tim_set,2,tsec)
     727              : 
     728            0 :   end subroutine xgBlock_set
     729              :   !!***
     730              : 
     731              :   !!****f* m_xg/xgBlock_map
     732              :   !!
     733              :   !! NAME
     734              :   !! xgBlock_map
     735              : 
     736       500526 :   subroutine xgBlock_map(xgBlock,array,space,rows,cols,comm,me_g0,gpu_option)
     737              :     use, intrinsic :: iso_c_binding
     738              :     type(xgBlock_t) , intent(inout) :: xgBlock
     739              :     double precision, target, intent(in) :: array(:,:)
     740              :     integer   , intent(in   ) :: space
     741              :     integer   , intent(in   ) :: rows
     742              :     integer   , intent(in   ) :: cols
     743              :     integer   , optional, intent(in) :: comm
     744              :     integer   , optional, intent(in) :: me_g0
     745              :     integer   , optional, intent(in) :: gpu_option
     746              :     integer :: fullsize,fact
     747              :     type(c_ptr) :: cptr
     748              : 
     749      1501578 :     fullsize = size(array)
     750       500526 :     fact = 1 ; if (space==SPACE_CR) fact = 2
     751       344921 :     select case (space)
     752              :     case ( SPACE_R,SPACE_CR )
     753       344921 :       if ( fullsize < fact*cols*rows .or. mod(fullsize,fact*rows) /= 0) then
     754            0 :         ABI_ERROR("Bad size for real array")
     755              :       end if
     756       344921 :       cptr = getClocR(size(array,dim=1),size(array,dim=2),array)
     757      1034763 :       call c_f_pointer(cptr,xgBlock%vecR,(/ fact*rows, cols /))
     758       344921 :       xgBlock%trans = 't'
     759              :     case ( SPACE_C )
     760       155605 :       if ( fullsize/2 < cols*rows .or. mod(fullsize/2,rows) /= 0) then
     761            0 :         ABI_ERROR("Bad size for complex array")
     762              :       end if
     763       155605 :       cptr = getClocR(size(array,dim=1),size(array,dim=2),array)
     764       466815 :       call c_f_pointer(cptr,xgBlock%vecC,(/ rows, cols /))
     765              : 
     766       155605 :       xgBlock%trans = 'c'
     767              :     case default
     768       500526 :       ABI_ERROR('Bad space in xgBlock_map')
     769              :     end select
     770              : 
     771       500526 :     xgBlock%space = space
     772       500526 :     xgBlock%rows = rows
     773       500526 :     xgBlock%LDim = rows
     774       500526 :     xgBlock%cols = cols
     775       500526 :     xgBlock%normal = 'n'
     776       500526 :     xgBlock%spacedim_comm = xmpi_comm_null
     777       500526 :     xgBlock%me_g0 = -1
     778       500526 :     xgBlock%gpu_option = ABI_GPU_DISABLED
     779              : 
     780       500526 :     if ( present(comm) ) xgBlock%spacedim_comm = comm
     781              : 
     782       500526 :     if ( present(me_g0) ) then
     783       481077 :       if (me_g0/=-1.and.me_g0/=0.and.me_g0/=1) then
     784            0 :         ABI_ERROR('Bad value of me_g0 in xg_init')
     785              :       else
     786       481077 :         xgBlock%me_g0 = me_g0
     787              :       end if
     788              :     end if
     789              : 
     790       500526 :     if ( present(gpu_option) ) xgBlock%gpu_option = gpu_option
     791              : #if defined(DEBUG_VERBOSE) && defined(HAVE_OPENMP_OFFLOAD)
     792              :     if ( xgBlock%gpu_option == ABI_GPU_OPENMP ) then
     793              :       ABI_CHECK(xomp_target_is_present(c_loc(array)), "Mapped array isn't... mapped with OpenMP")
     794              :     end if
     795              : #endif
     796              :     if ( xgBlock%gpu_option /= ABI_GPU_DISABLED .and. xgBlock%gpu_option /= ABI_GPU_LEGACY .and. &
     797       500526 :          xgBlock%gpu_option /= ABI_GPU_OPENMP   .and. xgBlock%gpu_option /= ABI_GPU_KOKKOS ) then
     798            0 :        ABI_ERROR('Bad GPU option in xgBlock_map')
     799              :     end if
     800              : 
     801       500526 :   end subroutine xgBlock_map
     802              :   !!***
     803              : 
     804              :   !!****f* m_xg/xgBlock_map_1d
     805              :   !!
     806              :   !! NAME
     807              :   !! xgBlock_map_1d
     808              : 
     809       250516 :     subroutine xgBlock_map_1d(xgBlock,array,space,rows,comm,me_g0,gpu_option)
     810              :       use iso_c_binding
     811              :       type(xgBlock_t) , intent(inout) :: xgBlock
     812              :       double precision, intent(in), target :: array(:)
     813              :       integer   , intent(in   ) :: space
     814              :       integer   , intent(in   ) :: rows
     815              :       integer   , optional, intent(in) :: comm
     816              :       integer   , optional, intent(in) :: me_g0
     817              :       integer   , optional, intent(in) :: gpu_option
     818              : 
     819              :       integer :: comm_,me_g0_,gpu_option_
     820              :       type(c_ptr) :: cptr
     821              :       real(dp), pointer :: array_ptr(:,:) => NULL()
     822              : 
     823              :       ! Trick the with C to change rank of arrays (:) to (:,:)
     824       250516 :       cptr = c_loc(array)
     825       751548 :       call c_f_pointer(cptr,array_ptr,(/ rows,1 /))
     826              : 
     827       250516 :       comm_ =xmpi_comm_null
     828       250516 :       if (present(comm)) then
     829            0 :         comm_=comm
     830              :       end if
     831              : 
     832       250516 :       me_g0_=-1
     833       250516 :       if (present(me_g0)) then
     834            0 :         me_g0_=me_g0
     835              :       end if
     836              : 
     837       250516 :       gpu_option_=ABI_GPU_DISABLED
     838       250516 :       if (present(gpu_option)) then
     839       142764 :         gpu_option_=gpu_option
     840              :       end if
     841              : 
     842       250516 :       call xgBlock_map(xgBlock,array_ptr,space,rows,1,comm=comm_,me_g0=me_g0_,gpu_option=gpu_option_)
     843              : 
     844       250516 :     end subroutine xgBlock_map_1d
     845              :   !!***
     846              : 
     847              :   !!****f* m_xg/xgBlock_reverseMapR
     848              :   !!
     849              :   !! NAME
     850              :   !! xgBlock_reverseMapR
     851              : 
     852     19963500 :   subroutine xgBlock_reverseMapR(xgBlock,array,rows,cols)
     853              :     use, intrinsic :: iso_c_binding
     854              :     type(xgBlock_t) , intent(in) :: xgBlock
     855              :     double precision, pointer, intent(inout) :: array(:,:)
     856              :     integer,optional,intent(in) :: rows
     857              :     integer,optional,intent(in) :: cols
     858              :     type(c_ptr) :: cptr
     859              : 
     860              :     integer :: rows_,cols_,fact
     861              : 
     862     19963500 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
     863              : 
     864     19963500 :     rows_ = fact*xgBlock%ldim
     865     19963500 :     cols_ = xgBlock%cols
     866     19963500 :     if (present(rows)) rows_=fact*rows
     867     19963500 :     if (present(cols)) cols_=cols
     868              : 
     869      8076317 :     select case (xgBlock%space)
     870              :     case ( SPACE_R,SPACE_CR )
     871      8076317 :       if ( xgBlock%cols*fact*xgBlock%Ldim < cols_*rows_ ) then
     872            0 :         write(std_out,*) xgBlock%cols,xgBlock%Ldim,cols,rows
     873            0 :         write(std_out,*) xgBlock%cols*xgBlock%Ldim,cols*rows
     874            0 :         ABI_ERROR("Bad reverseMapping")
     875              :       end if
     876      8076317 :       cptr = getClocR(fact*xgBlock%Ldim,xgBlock%cols,xgBlock%vecR(:,:))
     877     24228951 :       call c_f_pointer(cptr,array,(/ rows_, cols_ /))
     878              :     case ( SPACE_C )
     879     11887183 :       if ( xgBlock%cols*xgBlock%Ldim < cols_*rows_ ) then
     880            0 :         ABI_ERROR("Bad complex reverseMapping")
     881              :       end if
     882     11887183 :       cptr = getClocC(xgBlock%Ldim,xgBlock%cols,xgBlock%vecC(:,:))
     883     55625049 :       call c_f_pointer(cptr,array,(/ 2*rows_, cols_ /))
     884              :     end select
     885              : 
     886     19963500 :   end subroutine xgBlock_reverseMapR
     887              :   !!***
     888              : 
     889              :   !!****f* m_xg/xgBlock_reverseMap_1dR
     890              :   !!
     891              :   !! NAME
     892              :   !! xgBlock_reverseMap_1dR
     893              : 
     894       917815 :   subroutine xgBlock_reverseMap_1dR(xgBlock,array,array_dim)
     895              :     use, intrinsic :: iso_c_binding
     896              :     type(xgBlock_t) , intent(in) :: xgBlock
     897              :     double precision, pointer, intent(inout) :: array(:)
     898              :     integer,optional,intent(in) :: array_dim
     899              :     type(c_ptr) :: cptr
     900              : 
     901              :     integer :: dim_,fact
     902              : 
     903       917815 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
     904              : 
     905       917815 :     dim_ = fact*xgBlock%ldim*xgBlock%cols
     906       917815 :     if (present(array_dim)) dim_=fact*array_dim
     907              : 
     908       917815 :     select case (xgBlock%space)
     909              :     case ( SPACE_R,SPACE_CR )
     910       917815 :       if ( xgBlock%cols*fact*xgBlock%Ldim < dim_ ) then
     911            0 :         write(std_out,*) xgBlock%cols,xgBlock%Ldim,dim_
     912            0 :         write(std_out,*) xgBlock%cols*xgBlock%Ldim,dim_
     913            0 :         ABI_ERROR("Bad reverseMapping")
     914              :       end if
     915       917815 :       cptr = getClocR(fact*xgBlock%Ldim,xgBlock%cols,xgBlock%vecR(:,:))
     916      1835630 :       call c_f_pointer(cptr,array,(/ dim_ /))
     917              :     case ( SPACE_C )
     918            0 :       if ( xgBlock%cols*xgBlock%Ldim < dim_ ) then
     919            0 :         ABI_ERROR("Bad complex reverseMapping")
     920              :       end if
     921            0 :       cptr = getClocC(xgBlock%Ldim,xgBlock%cols,xgBlock%vecC(:,:))
     922       917815 :       call c_f_pointer(cptr,array,(/ 2*dim_ /))
     923              :     end select
     924              : 
     925       917815 :   end subroutine xgBlock_reverseMap_1dR
     926              :   !!***
     927              : 
     928              :   !!****f* m_xg/xgBlock_reverseMapC
     929              :   !!
     930              :   !! NAME
     931              :   !! xgBlock_reverseMapC
     932              : 
     933       864200 :   subroutine xgBlock_reverseMapC(xgBlock,array,rows,cols)
     934              :     use, intrinsic :: iso_c_binding
     935              :     type(xgBlock_t) , intent(in) :: xgBlock
     936              :     complex(dp), pointer, intent(inout) :: array(:,:)
     937              :     integer,optional,intent(in) :: rows
     938              :     integer,optional,intent(in) :: cols
     939              :     type(c_ptr) :: cptr
     940              : 
     941              :     integer :: rows_,cols_
     942              : 
     943       864200 :     if (xgBlock%space/=SPACE_C) then
     944            0 :       ABI_ERROR('space(xgBlock) should be SPACE_C')
     945              :     end if
     946       864200 :     rows_ = xgBlock%ldim
     947       864200 :     cols_ = xgBlock%cols
     948       864200 :     if (present(rows)) rows_=rows
     949       864200 :     if (present(cols)) cols_=cols
     950              : 
     951       864200 :     if ( xgBlock%cols*xgBlock%Ldim < cols_*rows_ ) then
     952            0 :       ABI_ERROR("Bad complex reverseMapping")
     953              :     end if
     954       864200 :     cptr = getClocC(xgBlock%Ldim,xgBlock%cols,xgBlock%vecC(:,:))
     955      2592600 :     call c_f_pointer(cptr,array,(/ rows_, cols_ /))
     956              : 
     957       864200 :   end subroutine xgBlock_reverseMapC
     958              :   !!***
     959              : 
     960              :   !!****f* m_xg/xgBlock_reverseMap_1dC
     961              :   !!
     962              :   !! NAME
     963              :   !! xgBlock_reverseMap_1dC
     964              : 
     965            0 :   subroutine xgBlock_reverseMap_1dC(xgBlock,array,array_dim)
     966              :     use, intrinsic :: iso_c_binding
     967              :     type(xgBlock_t) , intent(in) :: xgBlock
     968              :     complex(dp), pointer, intent(inout) :: array(:)
     969              :     integer,optional,intent(in) :: array_dim
     970              :     type(c_ptr) :: cptr
     971              : 
     972              :     integer :: dim_
     973              : 
     974            0 :     if (xgBlock%space/=SPACE_C) then
     975            0 :       ABI_ERROR('space(xgBlock) should be SPACE_C')
     976              :     end if
     977            0 :     dim_ = xgBlock%ldim*xgBlock%cols
     978            0 :     if (present(array_dim)) dim_=array_dim
     979              : 
     980            0 :     if ( xgBlock%cols*xgBlock%Ldim < dim_ ) then
     981            0 :       ABI_ERROR("Bad complex reverseMapping")
     982              :     end if
     983            0 :     cptr = getClocC(xgBlock%Ldim,xgBlock%cols,xgBlock%vecC(:,:))
     984            0 :     call c_f_pointer(cptr,array,(/ dim_ /))
     985              : 
     986            0 :   end subroutine xgBlock_reverseMap_1dC
     987              :   !!***
     988              : 
     989              :   !!****f* m_xg/xgBlock_prefetch_async
     990              :   !!
     991              :   !! Help the compiler to upload / dowload data to/from GPU memory
     992              :   !!
     993              :   !! if deviceId is CPU_DEVICE_ID (= -1, defined in 17_gpu_toolbox/m_gpu_toolbox.F90)
     994              :   !! then data is prefetch on host, else it is prefetch to GPU memory
     995              :   !!
     996              :   !! NAME
     997              :   !! xgBlock_prefetch_async
     998              : 
     999            0 :   subroutine xgBlock_prefetch_async(xgBlock, deviceId)
    1000              :     use iso_c_binding
    1001              :     type(xgBlock_t) ,             intent(inout) :: xgBlock
    1002              :     integer(C_INT32_T), optional, intent(in)    :: deviceId
    1003              : 
    1004              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_YAKL)
    1005              : 
    1006              :     real(dp), pointer                           :: array(:,:)
    1007              :     integer                                     :: blockdim
    1008              :     integer                                     :: spacedim
    1009              :     integer                                     :: ldim
    1010              :     integer(C_SIZE_T)                           :: byte_count
    1011              : 
    1012              :     ! get the array pointer underneath the xgBlock
    1013              :     call xgBlock_getSize(xgBlock,spacedim,blockdim,ldim)
    1014              :     call xgBlock_reverseMap(xgBlock,array,1,spacedim*blockdim)
    1015              : 
    1016              :     select case (xgBlock%space)
    1017              :     case ( SPACE_R )
    1018              :       byte_count = ldim*blockdim*dp
    1019              :     case ( SPACE_CR )
    1020              :       byte_count = 2*ldim*blockdim*dp
    1021              :     case ( SPACE_C )
    1022              :       byte_count = ldim*blockdim*2*dp ! Note the factor 2, needed here!
    1023              :     end select
    1024              : 
    1025              :     ! now we can call the memory prefetch
    1026              :     if (present(deviceId)) then
    1027              :       call gpu_data_prefetch_async(c_loc(array), byte_count , deviceId)
    1028              :     else
    1029              :       call gpu_data_prefetch_async(c_loc(array), byte_count)
    1030              :     end if
    1031              : 
    1032              : #else
    1033              :     ABI_UNUSED(deviceId)
    1034            0 :     ABI_UNUSED_A(xgBlock)
    1035              : #endif
    1036              : 
    1037            0 :   end subroutine xgBlock_prefetch_async
    1038              :   !!***
    1039              : 
    1040              :   !LB-06/03/24: Be careful, xg_get is not used anywhere in the code, so not tested...
    1041              :   !!****f* m_xg/xg_get
    1042              :   !!
    1043              :   !! NAME
    1044              :   !! xg_get
    1045              : 
    1046            0 :   subroutine xg_get(xg,array,shift_col,rows)
    1047              : 
    1048              :     type(xg_t), intent(inout) :: xg
    1049              :     double precision, intent(out) :: array(:,:)
    1050              :     integer, intent(in) :: shift_col
    1051              :     integer, intent(in) :: rows
    1052              :     integer :: cols
    1053              :     integer :: col
    1054              : !    double precision :: tsec(2)
    1055              : 
    1056              : !    call timab(tim_get,1,tsec)
    1057              : 
    1058            0 :     if ( size(array,dim=1) /= 2 ) then
    1059            0 :       ABI_ERROR("First dim must be 2")
    1060              :     end if
    1061              : 
    1062            0 :     cols = size(array,dim=2)/rows
    1063            0 :     if ( shift_col+cols > xg%cols ) then
    1064            0 :       ABI_WARNING("Ignore some columns, input array to large")
    1065              :     endif
    1066              : 
    1067            0 :     select case (xg%space)
    1068              :     case (SPACE_R)
    1069              :       !!$OMP TARGET UPDATE FROM(xg%vecR)
    1070            0 :       do col = 1, min(cols,xg%cols-shift_col)
    1071            0 :         array(1,(col-1)*rows+1:col*rows) = xg%vecR(1:rows,shift_col+col)
    1072              :       end do
    1073              :     case (SPACE_CR)
    1074            0 :       if ( xg%rows /= 2*rows ) then
    1075            0 :         ABI_ERROR("Bad number of rows")
    1076              :       end if
    1077              : 
    1078              :       !!$OMP TARGET UPDATE FROM(xg%vecR)
    1079            0 :       do col = 1, min(cols,xg%cols-shift_col)
    1080            0 :         array(1,(col-1)*rows+1:col*rows) = xg%vecR(1:rows,shift_col+col)
    1081            0 :         array(2,(col-1)*rows+1:col*rows) = xg%vecR(rows+1:2*rows,shift_col+col)
    1082              :       end do
    1083              :     case (SPACE_C)
    1084              :       !!$OMP TARGET UPDATE FROM(xg%vecC)
    1085            0 :       do col = 1, min(cols,xg%cols-shift_col)
    1086            0 :         array(1,(col-1)*rows+1:col*rows) = dble(xg%vecC(1:rows,shift_col+col))
    1087            0 :         array(2,(col-1)*rows+1:col*rows) = aimag(xg%vecC(1:rows,shift_col+col))
    1088              :       end do
    1089              :     end select
    1090              : 
    1091              : !    call timab(tim_get,2,tsec)
    1092              : 
    1093            0 :   end subroutine xg_get
    1094              :   !!***
    1095              : 
    1096              :   !LB-06/03/24: Be careful, xgBlock_get is not used anywhere in the code, so not tested...
    1097              :   !!****f* m_xg/xgBlock_get
    1098              :   !!
    1099              :   !! NAME
    1100              :   !! xgBlock_get
    1101              : 
    1102            0 :   subroutine xgBlock_get(xgBlock,array,shift_col,rows)
    1103              : 
    1104              :     type(xgBlock_t), intent(in   ) :: xgBlock
    1105              :     double precision, intent(out) :: array(:,:)
    1106              :     integer, intent(in) :: shift_col
    1107              :     integer, intent(in) :: rows
    1108              :     integer :: cols
    1109              :     integer :: col
    1110              : !    double precision :: tsec(2)
    1111              : 
    1112              : !    call timab(tim_get,1,tsec)
    1113              : 
    1114            0 :     if ( size(array,dim=1) /= 2 ) then
    1115            0 :       ABI_ERROR("First dim must be 2")
    1116              :     end if
    1117              : 
    1118            0 :     cols = size(array,dim=2)/rows
    1119            0 :     if ( shift_col+cols > xgBlock%cols ) then
    1120            0 :       ABI_ERROR("Ignore some columns, input array to large")
    1121              :     endif
    1122              : 
    1123            0 :     select case (xgBlock%space)
    1124              :     case (SPACE_R)
    1125            0 :       do col = 1, min(cols,xgBlock%cols-shift_col)
    1126            0 :         array(1,(col-1)*rows+1:col*rows) = xgBlock%vecR(1:rows,shift_col+col)
    1127              :       end do
    1128              :     case (SPACE_CR)
    1129            0 :       if ( xgBlock%rows /= 2*rows ) then
    1130            0 :         ABI_ERROR("Bad number of rows")
    1131              :       end if
    1132              : 
    1133            0 :       do col = 1, min(cols,xgBlock%cols-shift_col)
    1134            0 :         array(1,(col-1)*rows+1:col*rows) = xgBlock%vecR(1:rows,shift_col+col)
    1135            0 :         array(2,(col-1)*rows+1:col*rows) = xgBlock%vecR(rows+1:2*rows,shift_col+col)
    1136              :       end do
    1137              :     case (SPACE_C)
    1138            0 :       do col = 1, min(cols,xgBlock%cols-shift_col)
    1139            0 :         array(1,(col-1)*rows+1:col*rows) = dble(xgBlock%vecC(1:rows,shift_col+col))
    1140            0 :         array(2,(col-1)*rows+1:col*rows) = aimag(xgBlock%vecC(1:rows,shift_col+col))
    1141              :       end do
    1142              :     end select
    1143              : 
    1144              : !    call timab(tim_get,2,tsec)
    1145              : 
    1146            0 :   end subroutine xgBlock_get
    1147              :   !!***
    1148              : 
    1149              :   !!****f* m_xg/xg_setBlock
    1150              :   !!
    1151              :   !! NAME
    1152              :   !! xg_setBlock
    1153              : 
    1154     22602077 :   subroutine xg_setBlock(xg, Xgblock, rows, cols, fcol)
    1155              :     use, intrinsic :: iso_c_binding
    1156              :     type(xg_t), intent(inout) :: xg
    1157              :     type(xgBlock_t), intent(inout) :: xgBlock
    1158              :     integer, intent(in) :: rows
    1159              :     integer, intent(in) :: cols
    1160              :     integer, optional, intent(in) :: fcol
    1161              :     type(c_ptr) :: cptr
    1162              :     integer :: fcol_,fact
    1163              : 
    1164     22602077 :     fcol_=1
    1165     22602077 :     if (present(fcol)) fcol_=fcol
    1166              : 
    1167     22602077 :     if ( (fcol_+cols-1 ) > xg%cols ) then
    1168            0 :       ABI_ERROR("Too many columns")
    1169              :     endif
    1170     22602077 :     if ( rows > xg%rows ) then
    1171            0 :       ABI_ERROR("Too many rows")
    1172              :     end if
    1173              : 
    1174     22602077 :     xgBlock%space = xg%space
    1175     22602077 :     xgBlock%rows = rows
    1176     22602077 :     xgBlock%LDim = xg%rows
    1177     22602077 :     xgBlock%cols = cols
    1178     22602077 :     xgBlock%trans = xg%trans
    1179     22602077 :     xgBlock%normal = xg%normal
    1180     22602077 :     xgBlock%spacedim_comm= xg%spacedim_comm
    1181     22602077 :     xgBlock%me_g0 = xg%me_g0
    1182     22602077 :     xgBlock%gpu_option = xg%gpu_option
    1183              : 
    1184     22602077 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    1185      6729370 :     select case(xgBlock%space)
    1186              :     case (SPACE_R,SPACE_CR)
    1187      6729370 :       cptr = getClocR(xg%rows,xg%cols,xg%vecR(:,fcol_:fcol_+cols-1))
    1188     20188110 :       call c_f_pointer(cptr,xgBlock%vecR,(/ fact*xgBlock%LDim,cols /))
    1189              :     case(SPACE_C)
    1190     15872707 :       cptr = getClocC(xg%rows,xg%cols,xg%vecC(:,fcol_:fcol_+cols-1))
    1191     70220198 :       call c_f_pointer(cptr,xgBlock%vecC,(/ xgBlock%LDim,cols /))
    1192              :     end select
    1193              : 
    1194     22602077 :   end subroutine xg_setBlock
    1195              :   !!***
    1196              : 
    1197              :   !!****f* m_xg/xgBlock_setBlock
    1198              :   !!
    1199              :   !! NAME
    1200              :   !! xgBlock_setBlock
    1201              : 
    1202     11468551 :   subroutine xgBlock_setBlock(xgBlockA,xgBlockB, rows, cols, fcol)
    1203              :     use, intrinsic :: iso_c_binding
    1204              :     type(xgBlock_t), intent(in   ) :: xgBlockA
    1205              :     type(xgBlock_t), intent(inout) :: xgBlockB
    1206              :     integer, intent(in) :: rows
    1207              :     integer, intent(in) :: cols
    1208              :     integer,optional,intent(in) :: fcol
    1209              :     type(c_ptr) :: cptr
    1210              :     integer :: fcol_,fact
    1211              : 
    1212     11468551 :     fcol_=1
    1213     11468551 :     if (present(fcol)) fcol_=fcol
    1214              : 
    1215     11468551 :     if ( (fcol_+cols-1 ) > xgblockA%cols ) then
    1216            0 :       ABI_ERROR("Too many columns")
    1217              :     endif
    1218     11468551 :     if ( rows > xgblockA%rows ) then
    1219            0 :       ABI_ERROR("Too many rows")
    1220              :     end if
    1221              : 
    1222     11468551 :     xgBlockB%space = xgBlockA%space
    1223     11468551 :     xgBlockB%rows = rows
    1224     11468551 :     xgBlockB%LDim = xgBlockA%LDim
    1225     11468551 :     xgBlockB%cols = cols
    1226     11468551 :     xgBlockB%trans = xgBlockA%trans
    1227     11468551 :     xgBlockB%normal = xgBlockA%normal
    1228     11468551 :     xgBlockB%spacedim_comm= xgBlockA%spacedim_comm
    1229     11468551 :     xgBlockB%me_g0 = xgBlockA%me_g0
    1230     11468551 :     xgBlockB%gpu_option= xgBlockA%gpu_option
    1231              : 
    1232     11468551 :     fact = 1 ; if (xgBlockA%space==SPACE_CR) fact = 2
    1233      5147463 :     select case(xgBlockA%space)
    1234              :     case (SPACE_R,SPACE_CR)
    1235      5147463 :       cptr = getClocR(xgBlockA%LDim,xgBlockA%cols,xgBlockA%vecR(:,fcol_:fcol_+cols-1))
    1236     15442389 :       call c_f_pointer(cptr,xgBlockB%vecR,(/ fact*xgBlockB%LDim,cols /))
    1237              :     case(SPACE_C)
    1238      6321088 :       cptr = getClocC(xgBlockA%LDim,xgBlockA%cols,xgBlockA%vecC(:,fcol_:fcol_+cols-1))
    1239     30431815 :       call c_f_pointer(cptr,xgBlockB%vecC,(/ xgBlockB%LDim,cols /))
    1240              :     end select
    1241              : 
    1242     11468551 :   end subroutine xgBlock_setBlock
    1243              :   !!***
    1244              : 
    1245              :   !!****f* m_xg/xg_free
    1246              :   !!
    1247              :   !! NAME
    1248              :   !! xg_free
    1249              : 
    1250     11233210 :   subroutine xg_free(xg)
    1251              : 
    1252              :     type(xg_t),target, intent(inout) :: xg
    1253              : 
    1254              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    1255              :     complex(dp), pointer :: xg__vecC(:,:)
    1256              :     real(dp), pointer :: xg__vecR(:,:)
    1257              : #endif
    1258              : 
    1259     11233210 :     if(xg%gpu_option==ABI_GPU_KOKKOS) then
    1260              : #if defined HAVE_GPU && defined HAVE_YAKL
    1261              :       if ( associated(xg%vecR) ) then
    1262              :         ABI_FREE_MANAGED(xg%vecR)
    1263              :       end if
    1264              :       if ( associated(xg%vecC) ) then
    1265              :         ABI_FREE_MANAGED(xg%vecC)
    1266              :       end if
    1267              : #endif
    1268              : 
    1269              :     else
    1270              :       if(xg%gpu_option==ABI_GPU_OPENMP) then
    1271              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    1272              :         if ( associated(xg%vecR) ) then
    1273              :           xg__vecR => xg%vecR
    1274              :           !$OMP TARGET EXIT DATA MAP(delete:xg__vecR)
    1275              :         end if
    1276              :         if ( associated(xg%vecC) ) then
    1277              :           xg__vecC => xg%vecC
    1278              :           !$OMP TARGET EXIT DATA MAP(delete:xg__vecC)
    1279              :         end if
    1280              : #endif
    1281              :       end if
    1282     11230526 :       if ( associated(xg%vecR) ) then
    1283      3005351 :         ABI_FREE(xg%vecR)
    1284              :       end if
    1285     11230526 :       if ( associated(xg%vecC) ) then
    1286      6969943 :         ABI_FREE(xg%vecC)
    1287              :       end if
    1288              : 
    1289              :     end if
    1290              : 
    1291     11233210 :   end subroutine xg_free
    1292              :   !!***
    1293              : 
    1294              :   !!****f* m_xg/space
    1295              :   !!
    1296              :   !! NAME
    1297              :   !! space
    1298              : 
    1299     11902826 :   function space(xgBlock)
    1300              : 
    1301              :     type(xgBlock_t), intent(in) :: xgBlock
    1302              :     integer :: space
    1303     11907196 :     space = xgBlock%space
    1304      8113604 :   end function space
    1305              :   !!***
    1306              : 
    1307              :   !!****f* m_xg/comm
    1308              :   !!
    1309              :   !! NAME
    1310              :   !! comm
    1311              : 
    1312      7339029 :   function comm(xgBlock)
    1313              :     type(xgBlock_t), intent(in) :: xgBlock
    1314              :     integer :: comm
    1315      7339029 :     comm = xgBlock%spacedim_comm
    1316      5666872 :   end function comm
    1317              :   !!***
    1318              : 
    1319              :   !!****f* m_xg/me_g0
    1320              :   !!
    1321              :   !! NAME
    1322              :   !! me_g0
    1323              : 
    1324      1262563 :   function me_g0(xgBlock)
    1325              :     type(xgBlock_t), intent(in) :: xgBlock
    1326              :     integer :: me_g0
    1327      1262563 :     me_g0 = xgBlock%me_g0
    1328      1262563 :   end function me_g0
    1329              :   !!***
    1330              : 
    1331              :   !!****f* m_xg/gpu_option
    1332              :   !!
    1333              :   !! NAME
    1334              :   !! gpu_option
    1335              : 
    1336            0 :   function gpu_option(xgBlock)
    1337              :     type(xgBlock_t), intent(in) :: xgBlock
    1338              :     integer :: gpu_option
    1339            0 :     gpu_option = xgBlock%gpu_option
    1340            0 :   end function gpu_option
    1341              :   !!***
    1342              : 
    1343              :   !!****f* m_xg/setComm
    1344              :   !!
    1345              :   !! NAME
    1346              :   !! setComm
    1347              : 
    1348        46026 :   subroutine xgBlock_setComm(xgBlock,comm)
    1349              : 
    1350              :     type(xgBlock_t), intent(inout) :: xgBlock
    1351              :     integer :: comm
    1352        46026 :     xgBlock%spacedim_comm = comm
    1353              : 
    1354        46026 :   end subroutine xgBlock_setComm
    1355              :   !!***
    1356              : 
    1357              :   !!****f* m_xg/cols
    1358              :   !!
    1359              :   !! NAME
    1360              :   !! cols
    1361              : 
    1362     16344486 :   function cols(xgBlock)
    1363              : 
    1364              :     type(xgBlock_t), intent(in) :: xgBlock
    1365              :     integer :: cols
    1366     16344486 :     cols = xgBlock%cols
    1367     12829179 :   end function cols
    1368              :   !!***
    1369              : 
    1370              :   !!****f* m_xg/rows
    1371              :   !!
    1372              :   !! NAME
    1373              :   !! rows
    1374              : 
    1375     11974076 :   function rows(xgBlock)
    1376              :     type(xgBlock_t), intent(in) :: xgBlock
    1377              :     integer :: rows
    1378     11974076 :     rows = xgBlock%rows
    1379              :     !LB-31/05/24 : this warning is too verbose when activated... (even with correct coding!)
    1380              :     !if ( rows /= xgBlock%ldim ) then
    1381              :     !  ABI_WARNING("rows/ldim ! Be very careful at what you are doing")
    1382              :     !end if
    1383      8458769 :   end function rows
    1384              :   !!***
    1385              : 
    1386              :   !!****f* m_xg/xgBlock_copy
    1387              :   !!
    1388              :   !! NAME
    1389              :   !! xgBlock_copy
    1390              : 
    1391      6649858 :   subroutine xgBlock_copy(xgBlockA, xgBlockB, inc1, inc2)
    1392              : 
    1393              :     type(xgBlock_t),   intent(in   ) :: xgBlockA
    1394              :     type(xgBlock_t),   intent(inout) :: xgBlockB
    1395              :     integer, optional, intent(in   ) :: inc1
    1396              :     integer, optional, intent(in   ) :: inc2
    1397              : 
    1398              :     integer :: incx
    1399              :     integer :: incy
    1400              : 
    1401              :     integer :: size1
    1402              :     integer :: size2
    1403              :     integer :: size
    1404              :     double precision :: tsec(2)
    1405              :     integer :: l_gpu_option
    1406              : 
    1407              : #if defined HAVE_OPENMP_OFFLOAD && !defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
    1408              : !FIXME For several compilers, OMP doesn't work correctly with structured types, so use pointers
    1409              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecC(:,:),xgBlockB__vecC(:,:)
    1410              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecR(:,:),xgBlockB__vecR(:,:)
    1411              : #endif
    1412              : 
    1413      6649858 :     call timab(tim_copy,1,tsec)
    1414              : 
    1415      6649858 :     if (xgBlockA%gpu_option==xgBlockB%gpu_option) then
    1416              :       l_gpu_option = xgBlockA%gpu_option
    1417              :     else if ((xgBlockA%gpu_option==ABI_GPU_DISABLED.and.xgBlockB%gpu_option==ABI_GPU_LEGACY) &
    1418            0 :        .or.  (xgBlockA%gpu_option==ABI_GPU_LEGACY  .and.xgBlockB%gpu_option==ABI_GPU_DISABLED)) then
    1419              :       l_gpu_option = ABI_GPU_DISABLED
    1420            0 :     else if (xgBlockA%gpu_option==ABI_GPU_DISABLED.and.xgBlockB%gpu_option==ABI_GPU_OPENMP) then
    1421              :       l_gpu_option = ABI_GPU_DISABLED
    1422              :       call xgBlock_copy_from_gpu(xgBlockB)
    1423            0 :     else if (xgBlockB%gpu_option==ABI_GPU_DISABLED.and.xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    1424              :       l_gpu_option = ABI_GPU_DISABLED
    1425              :       call xgBlock_copy_from_gpu(xgBlockA)
    1426              :     else
    1427            0 :       ABI_ERROR('xgA%gpu_option/=xgB%gpu_option is possible only with ABI_GPU_OPENMP, ABI_GPU_LEGACY or ABI_GPU_DISABLED')
    1428              :     end if
    1429              : 
    1430      6649858 :     incx = 1; if ( present(inc1) ) incx = inc1
    1431      6649858 :     incy = 1; if ( present(inc2) ) incy = inc2
    1432              : 
    1433      6649858 :     if ( xgBlockA%space /= xgBlockB%space ) then
    1434            0 :       ABI_ERROR("Not same space")
    1435              :     end if
    1436              :     !if ( xgBlockA%LDim*xgBlockA%cols/incx /= xgBlockB%LDim*xgBlockB%cols/incy ) then
    1437              :     !  ABI_ERROR("Number of element different")
    1438              :     !end if
    1439              : 
    1440      6649858 :     size1 = xgBlockA%LDim*xgBlockA%cols/incx ; if ( size1 * incx < xgBlockA%LDim*xgBlockA%cols ) size1 = size1+1
    1441      6649858 :     size2 = xgBlockB%LDim*xgBlockB%cols/incy ; if ( size2 * incy < xgBlockB%LDim*xgBlockB%cols ) size2 = size2+1
    1442      6649858 :     size = min(size1,size2)
    1443      6649858 :     if (xgBlockA%space==SPACE_CR) then
    1444       674637 :       size = 2*size
    1445              :     end if
    1446              : 
    1447      6649858 :     xgBlockB%me_g0 = xgBlockA%me_g0
    1448              : 
    1449      6649858 :     if (l_gpu_option==ABI_GPU_KOKKOS .or. l_gpu_option==ABI_GPU_OPENMP) then
    1450              : #if defined HAVE_KOKKOS || defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
    1451              :       select case(xgBlockA%space)
    1452              :       case (SPACE_R,SPACE_CR)
    1453              :         call abi_gpu_xcopy(1, size, xgBlockA%vecR, incx, xgBlockB%vecR, incy)
    1454              :       case(SPACE_C)
    1455              :         call abi_gpu_xcopy(2, size, xgBlockA%vecC, incx, xgBlockB%vecC, incy)
    1456              :       end select
    1457              : #elif defined HAVE_OPENMP_OFFLOAD
    1458              : !FIXME For several compilers, OMP doesn't work correctly with structured types, so use pointers
    1459              :       select case(xgBlockA%space)
    1460              :       case (SPACE_R,SPACE_CR)
    1461              :         xgBlockA__vecR => xgBlockA%vecR
    1462              :         xgBlockB__vecR => xgBlockB%vecR
    1463              :         !$OMP TARGET DATA USE_DEVICE_ADDR(xgBlockA__vecR,xgBlockB__vecR)
    1464              :         call abi_gpu_xcopy(1, size, c_loc(xgBlockA__vecR), incx, c_loc(xgBlockB__vecR), incy)
    1465              :         !$OMP END TARGET DATA
    1466              :       case(SPACE_C)
    1467              :         xgBlockA__vecC => xgBlockA%vecC
    1468              :         xgBlockB__vecC => xgBlockB%vecC
    1469              :         !$OMP TARGET DATA USE_DEVICE_ADDR(xgBlockA__vecC,xgBlockB__vecC)
    1470              :         call abi_gpu_xcopy(2, size, c_loc(xgBlockA__vecC), incx, c_loc(xgBlockB__vecC), incy)
    1471              :         !$OMP END TARGET DATA
    1472              :       end select
    1473              : #endif
    1474              :     else
    1475              : 
    1476      1892808 :       select case(xgBlockA%space)
    1477              :       case (SPACE_R,SPACE_CR)
    1478      1892808 :         call dcopy(size,xgBlockA%vecR,incx,xgBlockB%vecR,incy)
    1479              :       case(SPACE_C)
    1480      6649858 :         call zcopy(size,xgBlockA%vecC,incx,xgBlockB%vecC,incy)
    1481              :       end select
    1482              : 
    1483              :     end if
    1484              : 
    1485      6649858 :     call timab(tim_copy,2,tsec)
    1486              : 
    1487      6649858 :   end subroutine xgBlock_copy
    1488              :   !!***
    1489              : 
    1490              :   !!****f* m_xg/xgBlock_colwiseSwap
    1491              :   !!
    1492              :   !! NAME
    1493              :   !! xgBlock_colwiseSwap
    1494              : 
    1495            0 :   subroutine xgBlock_colwiseSwap(xgBlock, j, k, tmp)
    1496              : 
    1497              :       implicit none
    1498              : 
    1499              :       type(xgBlock_t), intent(inout) :: xgBlock
    1500              :       integer, intent(in) :: j, k
    1501              :       type(xgBlock_t), intent(inout) :: tmp
    1502              : 
    1503              :       type(xgBlock_t) :: col_j, col_k
    1504              : 
    1505            0 :       if (j == k) return
    1506              : 
    1507            0 :       call xgBlock_setBlock(xgBlock, col_j, xgBlock%rows, 1, j)
    1508            0 :       call xgBlock_setBlock(xgBlock, col_k, xgBlock%rows, 1, k)
    1509              : 
    1510            0 :       call xgBlock_copy(col_j, tmp)
    1511            0 :       call xgBlock_copy(col_k, col_j)
    1512            0 :       call xgBlock_copy(tmp,   col_k)
    1513              : 
    1514            0 :   end subroutine xgBlock_colwiseSwap
    1515              :   !!***
    1516              : 
    1517              : !!****f* m_xg/xgBlock_partialcopy
    1518              : !!
    1519              : !! NAME
    1520              : !! xgBlock_partialcopy
    1521              : 
    1522     10314608 :   subroutine xgBlock_partialcopy(xgBlock_in, xgBlock_out, shift_row, shift_col, option)
    1523              : 
    1524              :     type(xgBlock_t), intent(in   ) :: xgBlock_in
    1525              :     type(xgBlock_t), intent(inout) :: xgBlock_out
    1526              :     integer,intent(in) :: shift_row,shift_col
    1527              :     integer,intent(in) :: option
    1528              : 
    1529              :     integer :: icol,ncols_small,ncols_big
    1530              :     integer :: nrows_small,nrows_big
    1531              :     integer :: shift_col_big,end_row,max_col
    1532              :     double precision :: tsec(2)
    1533              : 
    1534     10314608 :     call timab(tim_partialcopy,1,tsec)
    1535              : 
    1536     10314608 :     if (xgBlock_in%gpu_option/=ABI_GPU_DISABLED) then
    1537            0 :       ABI_ERROR('Not implemented for GPU')
    1538              :     end if
    1539     10314608 :     call xgBlock_check_gpu_option(xgBlock_in,xgBlock_out)
    1540              : 
    1541     10314608 :     if (option==SMALL2BIG) then
    1542      4846372 :       ncols_big   = xgBlock_out%cols
    1543      4846372 :       nrows_big   = xgBlock_out%rows
    1544      4846372 :       ncols_small = xgBlock_in%cols
    1545      4846372 :       nrows_small = xgBlock_in%rows
    1546      5468236 :     else if (option==BIG2SMALL) then
    1547      5468236 :       ncols_big   = xgBlock_in%cols
    1548      5468236 :       nrows_big   = xgBlock_in%rows
    1549      5468236 :       ncols_small = xgBlock_out%cols
    1550      5468236 :       nrows_small = xgBlock_out%rows
    1551              :     else
    1552            0 :       ABI_ERROR('Bad option')
    1553              :     end if
    1554     10314608 :     if (xgBlock_in%space/=xgBlock_out%space) then
    1555            0 :       ABI_ERROR('xgBlockA%space/=xgBlockB%space')
    1556              :     end if
    1557     10314608 :     if (ncols_small>ncols_big) then
    1558            0 :       ABI_ERROR('ncols_small>ncols_big')
    1559              :     end if
    1560     10314608 :     if (nrows_small>nrows_big) then
    1561            0 :       ABI_ERROR('nrows_small>nrows_big')
    1562              :     end if
    1563     10314608 :     if (shift_row<0) then
    1564            0 :       ABI_ERROR('start_row<0')
    1565              :     end if
    1566     10314608 :     if (shift_col<0) then
    1567            0 :       ABI_ERROR('start_col<0')
    1568              :     end if
    1569              : 
    1570     10314608 :     end_row = shift_row + nrows_small
    1571     10314608 :     if (end_row>nrows_big) then
    1572            0 :       ABI_ERROR('end_row>nrows_big')
    1573              :     end if
    1574              : 
    1575     10314608 :     max_col = shift_col + ncols_small
    1576     10314608 :     if (max_col>ncols_big) then
    1577            0 :       ABI_ERROR('max_col>nrows_big')
    1578              :     end if
    1579              : 
    1580     10314608 :     if (option==SMALL2BIG) then ! copy small matrix into the big one
    1581      4846372 :       select case(xgBlock_in%space)
    1582              :       case (SPACE_R)
    1583      4975136 :         do icol=1,ncols_small
    1584      2524560 :           shift_col_big = shift_col + (icol-1)
    1585      7797808 :           xgBlock_out%vecR(1+shift_row:end_row,1+shift_col_big) = xgBlock_in%vecR(1:nrows_small,icol)
    1586              :         end do
    1587              :       case (SPACE_CR)
    1588      1396560 :         do icol=1,ncols_small
    1589      1117248 :           shift_col_big = shift_col + (icol-1)
    1590     43450416 :           xgBlock_out%vecR(1+2*shift_row:2*end_row,1+shift_col_big) = xgBlock_in%vecR(1:2*nrows_small,icol)
    1591              :         end do
    1592              :       case(SPACE_C)
    1593     10674988 :         do icol=1,ncols_small
    1594      3712132 :           shift_col_big = shift_col + (icol-1)
    1595     74427844 :           xgBlock_out%vecC(1+shift_row:end_row,1+shift_col_big) = xgBlock_in%vecC(1:nrows_small,icol)
    1596              :         end do
    1597              :       end select
    1598      5468236 :     else if (option==BIG2SMALL) then ! copy a part of the big matrix in the small one
    1599      5468236 :       select case(xgBlock_in%space)
    1600              :       case (SPACE_R)
    1601      4966272 :         do icol=1,ncols_small
    1602      2533184 :           shift_col_big = shift_col + (icol-1)
    1603      7902016 :           xgBlock_out%vecR(1:nrows_small,icol) = xgBlock_in%vecR(1+shift_row:end_row,1+shift_col_big)
    1604              :         end do
    1605              :       case (SPACE_CR)
    1606       609456 :         if (shift_row>0) xgBlock_out%me_g0 = 0
    1607      3047280 :         do icol=1,ncols_small
    1608      2437824 :           shift_col_big = shift_col + (icol-1)
    1609     93934800 :           xgBlock_out%vecR(1:2*nrows_small,icol) = xgBlock_in%vecR(1+2*shift_row:2*end_row,1+shift_col_big)
    1610              :         end do
    1611              :       case(SPACE_C)
    1612     13432580 :         do icol=1,ncols_small
    1613      5538652 :           shift_col_big = shift_col + (icol-1)
    1614    142557884 :           xgBlock_out%vecC(1:nrows_small,icol) = xgBlock_in%vecC(1+shift_row:end_row,1+shift_col_big)
    1615              :         end do
    1616              :       end select
    1617              :     else
    1618            0 :       ABI_ERROR('Bad option')
    1619              :     end if
    1620              : 
    1621     10314608 :     call timab(tim_partialcopy,2,tsec)
    1622              : 
    1623     10314608 :   end subroutine xgBlock_partialcopy
    1624              : !!***
    1625              : 
    1626              : !!****f* m_xg/xgBlock_permuteCols
    1627              : !!
    1628              : !! NAME
    1629              : !! xgBlock_permuteCols
    1630              : !!
    1631              : !! FUNCTION
    1632              : !! Sequential in-place permute columns of xgBlock according to index permutation pcol.
    1633              : !! Performs the swap M(i,j) = M(i,perm(j)) for j=1,m using LAPACK.
    1634              : !! Checks memory location before applying LAPACK on CPU /!\
    1635              : !! Warning: implicit GPU transfer to place on CPU.
    1636              : !!
    1637            0 :   subroutine xgBlock_permuteCols(xgBlock, rows, cols, pcol)
    1638              : 
    1639              :     type(xgBlock_t), intent(inout) :: xgBlock
    1640              :     integer        , intent(in) :: rows,cols
    1641              :     integer        , intent(in) :: pcol(cols)
    1642              : 
    1643              :     logical :: forwrd = .true.
    1644              : 
    1645              :     ! Size check
    1646            0 :     if (size(pcol,dim=1)/=cols) then
    1647            0 :         ABI_ERROR("Permutation size must be equal to number of columns")
    1648              :     end if
    1649              : 
    1650              :     ! Device to host transfer
    1651              :     if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    1652              :         call xgBlock_copy_from_gpu(xgBlock)
    1653              :     end if
    1654              : 
    1655              :     ! LAPACK calls
    1656            0 :     select case(xgBlock%space)
    1657              :     case (SPACE_R)
    1658            0 :         call dlapmt(forwrd, rows, cols, xgBlock%vecR, xgBlock%LDim, pcol)
    1659              :     case (SPACE_CR)
    1660            0 :         call dlapmt(forwrd, 2*rows, cols, xgBlock%vecR, xgBlock%LDim, pcol)
    1661              :     case (SPACE_C)
    1662            0 :         call zlapmt(forwrd, rows, cols, xgBlock%vecC, xgBlock%LDim, pcol)
    1663              :     end select
    1664              : 
    1665              :     ! Update GPU with modified CPU memory
    1666              :     if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    1667              :         call xgBlock_copy_to_gpu(xgBlock)
    1668              :     end if
    1669              : 
    1670            0 :   end subroutine xgBlock_permuteCols
    1671              : !!***
    1672              : 
    1673              :   !!****f* m_xg/xgBlock_hermitian_pd_cond
    1674              :   !!
    1675              :   !! NAME
    1676              :   !! xgBlock_hermitian_pf_cond
    1677              :   !!
    1678              :   !! FUNCTION
    1679              :   !! Condition number with 2-norm.
    1680              :   !! kappa2(A)
    1681              :   !!
    1682              :   !! Convention:
    1683              :   !! for compatibility with xg_RayleighRitz_cprj,
    1684              :   !! xgBlock stores the upper triangle of matrix
    1685              :   !! uplo = 'u'
    1686              : 
    1687            0 :   subroutine xgBlock_hermitian_pd_cond(xgBlock, n, cond2)
    1688              : 
    1689              :       implicit none
    1690              :       type(xgBlock_t), intent(in) :: xgBlock
    1691              :       integer, intent(in) :: n
    1692              :       real(dp), intent(inout) :: cond2
    1693              : 
    1694            0 :       complex(dpc) :: vecC(n,n)
    1695            0 :       real(dp) :: w(n)
    1696            0 :       complex(dp) :: work(2*n)
    1697            0 :       real(dp) :: rwork(3*n-2)
    1698              :       integer :: info
    1699              :       external :: zheev
    1700              : 
    1701              :       ! IML debug
    1702              :       !write(901,*) 'space B', xgBlock%space
    1703              : 
    1704              :       !# Validation
    1705              :       ! Fill Hermitian SPD matrix (upper triangle only)
    1706              :       !vecC(1,1) = (4.0_dp, 0.0_dp)
    1707              :       !vecC(1,2) = (1.0_dp, 0.5_dp)
    1708              :       !vecC(2,1) = dconjg(vecC(1,2))
    1709              :       !vecC(2,2) = (3.0_dp, 0.0_dp)
    1710              :       !#
    1711              :       ! comment following line
    1712              : 
    1713              :       ! Copy input since LAPACK overwrites matrix
    1714            0 :       vecC(1:n,1:n) = xgBlock%vecC(1:n,1:n)
    1715              : 
    1716              :       ! IML debug
    1717              :       ! Objects are independent(check)
    1718              :       !write(901,*) 'temp', vecC(1,11)
    1719              :       !write(901,*) 'ref', xgBlock%vecC(1,11)
    1720              :       !vecC(1,11) = 2222
    1721              :       !write(901,*) 'new temp', vecC(1,11)
    1722              :       !write(901,*) 'new ref', xgBlock%vecC(1,11)
    1723              :       !flush(901)
    1724              : 
    1725            0 :       call zheev('N','U', n, vecC, n, w, work, size(work), rwork, info)
    1726            0 :       cond2 = maxval(w) / minval(w)
    1727              : 
    1728              :       ! IML debug
    1729              :       !write(901,*) 'eigenval(=singval)='
    1730              :       !write(901,*) w
    1731              :       !flush(901)
    1732              : 
    1733            0 :   end subroutine xgBlock_hermitian_pd_cond
    1734              :   !!***
    1735              : 
    1736            0 :   subroutine xgBlock_spd_cond(xgBlock, n, cond2)
    1737              : 
    1738              :       implicit none
    1739              :       type(xgBlock_t), intent(in) :: xgBlock
    1740              :       integer, intent(in) :: n
    1741              :       real(dp), intent(inout) :: cond2
    1742              : 
    1743            0 :       real(dp) :: vecR(n,n)
    1744            0 :       real(dp) :: w(n)
    1745            0 :       real(dp) :: rwork(8*n)
    1746              :       integer :: info
    1747              :       external :: dsyev
    1748              : 
    1749            0 :       vecR(1:n,1:n) = xgBlock%vecR(1:n,1:n)
    1750            0 :       call dsyev('N','U', n, vecR, n, w, rwork, 8*n, info)
    1751            0 :       cond2 = abs(maxval(w) / minval(w))
    1752              : 
    1753            0 :   end subroutine xgBlock_spd_cond
    1754              : 
    1755              :   !!****f* m_xg/xgBlock_pack
    1756              :   !!
    1757              :   !! NAME
    1758              :   !! xgBlock_pack
    1759              : 
    1760            0 :   subroutine xgBlock_pack(xgBlockA,xgBlockB,uplo)
    1761              :     use, intrinsic :: iso_c_binding
    1762              :     type(xgBlock_t), intent(inout) :: xgBlockA
    1763              :     type(xgBlock_t), intent(inout) :: xgBlockB
    1764              :     character, intent(in) :: uplo
    1765              :     integer :: j
    1766              :     integer :: i
    1767              :     integer :: col
    1768              :     type(c_ptr) :: cptr
    1769            0 :     double precision, pointer :: subR(:)
    1770            0 :     complex(kind=8), pointer :: subC(:)
    1771              :     double precision :: tsec(2)
    1772              : 
    1773            0 :     call timab(tim_pack,1,tsec)
    1774            0 :     if ( xgBlockA%space /= xgBlockB%space ) then
    1775            0 :       ABI_ERROR("Both blocks must be the same space")
    1776              :     end if
    1777              : 
    1778            0 :     if ( xgBlockA%Ldim /= xgBlockA%rows ) then
    1779            0 :       ABI_ERROR("Cannot pack when ldim /= rows")
    1780              :     end if
    1781              : 
    1782            0 :     if ( xgBlockA%Ldim /= xgBlockA%cols ) then
    1783            0 :       ABI_ERROR("Cannot pack when cols /= rows")
    1784              :     end if
    1785              : 
    1786            0 :     if ( xgBlockA%rows*(xgBlockA%rows+1)/2 > xgBlockB%Ldim*xgBlockB%cols ) then
    1787            0 :       ABI_ERROR("Not enought memory in destination")
    1788              :     end if
    1789              : 
    1790              :     ! make a fake pointer to pack in a 1-D array instead of 2
    1791              :     ! This allows to directly use the lapack conventions of transformation
    1792            0 :     select case(xgBlockA%space)
    1793              :     case (SPACE_R,SPACE_CR)
    1794            0 :       cptr = getClocR(xgBlockB%Ldim,xgBlockB%cols,xgBlockB%vecR(:,:))
    1795            0 :       call c_f_pointer(cptr,subR,(/ (xgBlockB%cols*(xgBlockB%cols+1))/2 /))
    1796              :     case (SPACE_C)
    1797            0 :       cptr = getClocC(xgBlockB%Ldim,xgBlockB%cols,xgBlockB%vecC(:,:))
    1798            0 :       call c_f_pointer(cptr,subC,(/ (xgBlockB%cols*(xgBlockB%cols+1))/2 /))
    1799              :     end select
    1800              : 
    1801            0 :     select case(uplo)
    1802              :     case ('u','U')
    1803            0 :       select case(xgBlockA%space)
    1804              :       case (SPACE_R,SPACE_CR)
    1805            0 :         do j = 1, xgBlockA%cols
    1806            0 :           col = (j*(j-1))/2
    1807            0 :           do i = 1, j
    1808            0 :             subR(i+col) = xgBlockA%vecR(i,j)
    1809              :           end do
    1810              :         end do
    1811              :       case (SPACE_C)
    1812            0 :         do j = 1, xgBlockA%cols
    1813            0 :           col = (j*(j-1))/2
    1814            0 :           do i = 1, j
    1815            0 :             subC(i+col) = xgBlockA%vecC(i,j)
    1816              :           end do
    1817              :         end do
    1818              :       end select
    1819              : 
    1820              :     case ('l','L')
    1821            0 :       select case(xgBlockA%space)
    1822              :       case (SPACE_R,SPACE_CR)
    1823            0 :         do j = 1, xgBlockA%cols
    1824            0 :           col = ((2*xgBlockA%cols-j)*(j-1))/2
    1825            0 :           do i = j, xgBlockA%cols
    1826            0 :             subR(i+col) = xgBlockA%vecR(i,j)
    1827              :           end do
    1828              :         end do
    1829              :       case (SPACE_C)
    1830            0 :         do j = 1, xgBlockA%cols
    1831            0 :           col = ((2*xgBlockA%cols-j)*(j-1))/2
    1832            0 :           do i = j, xgBlockA%cols
    1833            0 :             subC(i+col) = xgBlockA%vecC(i,j)
    1834              :           end do
    1835              :         end do
    1836              :       end select
    1837              :     case default
    1838            0 :       ABI_ERROR("Error for packing matrix")
    1839              :     end select
    1840            0 :     call timab(tim_pack,2,tsec)
    1841              : 
    1842            0 :   end subroutine xgBlock_pack
    1843              :   !!***
    1844              : 
    1845              :   !!****f* m_xg/xgBlock_gemmR
    1846              :   !!
    1847              :   !! NAME
    1848              :   !! xgBlock_gemmR
    1849              : 
    1850     17424340 :   subroutine xgBlock_gemmR(transa, transb, alpha, xgBlockA, xgBlockB, beta, xgBlockW, comm, timing)
    1851              : 
    1852              :     character,        intent(in   )           :: transa
    1853              :     character,        intent(in   )           :: transb
    1854              :     double precision, intent(in   )           :: alpha
    1855              :     type(xgBlock_t),  intent(in   )           :: xgBlockA
    1856              :     type(xgBlock_t),  intent(in   )           :: xgBlockB
    1857              :     double precision, intent(in   )           :: beta
    1858              :     type(xgBlock_t),  intent(inout)           :: xgBlockW
    1859              :     integer,optional, intent(in)              :: comm
    1860              :     logical,optional, intent(in)              :: timing
    1861              : 
    1862              :     real(dp)      :: alpha_
    1863              :     complex(dp)   :: calpha
    1864              :     complex(dp)   :: cbeta
    1865              :     character(kind=1) :: transa_,transb_
    1866              :     integer           :: K
    1867              :     double precision  :: tsec(2)
    1868              :     logical :: timing_
    1869              : 
    1870              : 
    1871     17424340 :     timing_ = .true.
    1872     17424340 :     if (present(timing)) then
    1873      3527492 :       timing_ = timing
    1874              :     end if
    1875     17424340 :     if (timing_) call timab(tim_gemm_blas,1,tsec)
    1876              : 
    1877     17424340 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    1878     17424340 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    1879              : 
    1880     17424340 :     if (transa /= 'n' .and. transa /= 't') then
    1881            0 :       ABI_ERROR("transa should be 'n' or 't'")
    1882              :     end if
    1883     17424340 :     if (transb /= 'n' .and. transb /= 't') then
    1884            0 :       ABI_ERROR("transb should be 'n' or 't'")
    1885              :     end if
    1886              : 
    1887     17424340 :     if ( transa == 'n' ) then
    1888     10007234 :       K = xgBlockA%cols
    1889     10007234 :       if ( xgBlockA%rows /= xgBlockW%rows ) then
    1890            0 :         ABI_ERROR("rows(A)/=rows(W)")
    1891              :       end if
    1892              :     else
    1893      7417106 :       K = xgBlockA%rows
    1894      7417106 :       if ( xgBlockA%cols /= xgBlockW%rows ) then
    1895            0 :         ABI_ERROR("cols(A)/=rows(W)")
    1896              :       end if
    1897              :     end if
    1898     17424340 :     if ( transb == 'n' ) then
    1899     17424340 :       if ( xgBlockB%cols /= xgBlockW%cols ) then
    1900            0 :         ABI_ERROR("cols(B)/=cols(W)")
    1901              :       end if
    1902              :     else
    1903            0 :       if ( xgBlockB%rows /= xgBlockW%cols ) then
    1904            0 :         ABI_ERROR("rows(B)/=cols(W)")
    1905              :       end if
    1906              :     end if
    1907              : 
    1908     17424340 :     calpha = dcmplx(alpha,0.d0)
    1909     17424340 :     cbeta  = dcmplx(beta, 0.d0)
    1910              : 
    1911     17424340 :     if ( xgBlockA%space == xgBlockB%space ) then
    1912              : 
    1913     16491411 :       if ( xgBlockA%space /= SPACE_CR .and. xgBlockW%space /= xgBlockA%space ) then
    1914            0 :         ABI_ERROR("Not same space for A and W")
    1915              :       end if
    1916     16491411 :       if ( xgBlockA%space == SPACE_CR ) then
    1917      1149452 :         if ( transa/= 't' .or. transb /='n' ) then
    1918            0 :           ABI_ERROR("if space(A)==SPACE_CR, transa shoulbe 't' and transb shoulb 'n'")
    1919              :         end if
    1920      1149452 :         if ( xgBlockW%space /= SPACE_R) then
    1921            0 :           ABI_ERROR("space(W) should be SPACE_R")
    1922              :         end if
    1923      1149452 :         if (xgBlockA%me_g0<0) then
    1924            0 :           ABI_ERROR("xgBlockA me_g0 is not initialized")
    1925              :         end if
    1926      1149452 :         if (xgBlockB%me_g0<0) then
    1927            0 :           ABI_ERROR("xgBlockB me_g0 is not initialized")
    1928              :         end if
    1929      1149452 :         if (xgBlockA%me_g0/=xgBlockB%me_g0) then
    1930            0 :           ABI_ERROR("xgBlockA and xgBlockB should have same me_g0")
    1931              :         end if
    1932              :       end if
    1933              :       ! CALL GEMM
    1934     18882578 :       select case(xgBlockA%space)
    1935              :       case (SPACE_R)
    1936              :         call abi_xgemm(transa, transb, xgBlockW%rows, xgBlockW%cols, K, &
    1937              :         &    calpha, &
    1938              :         &    xgBlockA%vecR, xgBlockA%LDim, &
    1939              :         &    xgBlockB%vecR, xgBlockB%LDim, &
    1940              :         &    cbeta, &
    1941              :         &    xgBlockW%vecR, xgBlockW%LDim, &
    1942      2391167 :         &    x_cplx=1, gpu_option=xgBlockA%gpu_option)
    1943              : 
    1944              :       case (SPACE_CR)
    1945      1149452 :         calpha = dcmplx(2*alpha,0.d0)
    1946      1149452 :         alpha_ = 2.0d0 * alpha
    1947              :         call abi_xgemm(transa, transb, xgBlockW%rows, xgBlockW%cols, 2*K, &
    1948              :         &    calpha, &
    1949              :         &    xgBlockA%vecR, 2*xgBlockA%LDim, &
    1950              :         &    xgBlockB%vecR, 2*xgBlockB%LDim, &
    1951              :         &    cbeta, &
    1952              :         &    xgBlockW%vecR, xgBlockW%LDim, &
    1953      1149452 :         &    x_cplx=1, gpu_option=xgBlockA%gpu_option)
    1954      1149452 :         if (xgBlockA%me_g0 == 1) then
    1955        85243 :           calpha = dcmplx(-2*alpha,0.d0)
    1956              :           call abi_xgemm(transa, transb, xgBlockW%rows, xgBlockW%cols, 2, &
    1957              :           &    calpha, &
    1958              :           &    xgBlockA%vecR, 2*xgBlockA%LDim, &
    1959              :           &    xgBlockB%vecR, 2*xgBlockB%LDim, &
    1960              :           &    cone, &
    1961              :           &    xgBlockW%vecR, xgBlockW%LDim, &
    1962        85243 :           &    x_cplx=1, gpu_option=xgBlockA%gpu_option)
    1963        85243 :           calpha = dcmplx(alpha,0.d0)
    1964              :           call abi_xgemm(transa, transb, xgBlockW%rows, xgBlockW%cols, 1, &
    1965              :           &    calpha, &
    1966              :           &    xgBlockA%vecR, 2*xgBlockA%LDim, &
    1967              :           &    xgBlockB%vecR, 2*xgBlockB%LDim, &
    1968              :           &    cone, &
    1969              :           &    xgBlockW%vecR, xgBlockW%LDim, &
    1970        85243 :           &    x_cplx=1, gpu_option=xgBlockA%gpu_option)
    1971              :         end if
    1972              : 
    1973              :       case(SPACE_C)
    1974              : 
    1975     12950792 :         transa_=transa
    1976     12950792 :         if (transa=='t') transa_ = 'c'
    1977     12950792 :         transb_=transb
    1978     12950792 :         if (transb=='t') transb_ = 'c'
    1979              : 
    1980              :         call abi_xgemm(transa_, transb_, xgBlockW%rows, xgBlockW%cols, K, &
    1981              :         &    calpha, &
    1982              :         &    xgBlockA%vecC, xgBlockA%LDim, &
    1983              :         &    xgBlockB%vecC, xgBlockB%LDim, &
    1984              :         &    cbeta, &
    1985              :         &    xgBlockW%vecC, xgBlockW%LDim, &
    1986     29442203 :         &    gpu_option=xgBlockA%gpu_option)
    1987              : 
    1988              :       end select
    1989              : 
    1990              :     else ! not same space for A and B
    1991              : 
    1992       932929 :       if (xgBlockA%space==SPACE_CR.and.xgBlockB%space==SPACE_R) then
    1993       932929 :         if (transa/='n'.or.transb/='n') then
    1994            0 :           ABI_ERROR('Not implemented')
    1995              :         end if
    1996       932929 :         if (xgBlockW%space/=SPACE_CR) then
    1997            0 :           ABI_ERROR('space(W) should be SPACE_CR')
    1998              :         end if
    1999              :         call abi_xgemm(transa, transb, 2*xgBlockW%rows, xgBlockW%cols,K, &
    2000              :         &    calpha, &
    2001              :         &    xgBlockA%vecR, 2*xgBlockA%LDim, &
    2002              :         &    xgBlockB%vecR, xgBlockB%LDim, &
    2003              :         &    cbeta, &
    2004              :         &    xgBlockW%vecR,2*xgBlockW%LDim, &
    2005       932929 :         &    x_cplx=1, gpu_option=xgBlockA%gpu_option)
    2006              :       else
    2007            0 :         ABI_ERROR('Not implemented')
    2008              :       end if
    2009              : 
    2010              :     end if
    2011              : 
    2012     17424340 :     if (timing_) call timab(tim_gemm_blas,2,tsec)
    2013              :     ! END CALL GEMM
    2014              : 
    2015              :     ! MPI SUM
    2016     17424340 :     if ( present(comm) ) then
    2017      5035990 :       if (timing_) call timab(tim_gemm_mpi,1,tsec)
    2018      5035990 :       call xgBlock_mpi_sum(xgBlockW,comm=comm)
    2019      5035990 :       if (timing_) call timab(tim_gemm_mpi,2,tsec)
    2020              :     end if
    2021              : 
    2022     17424340 :   end subroutine xgBlock_gemmR
    2023              :   !!***
    2024              : 
    2025              :   !!****f* m_xg/xgBlock_gemmC
    2026              :   !!
    2027              :   !! NAME
    2028              :   !! xgBlock_gemmC
    2029              : 
    2030            0 :   subroutine xgBlock_gemmC(transa, transb, alpha, xgBlockA, xgBlockB, beta, xgBlockW, comm, timing)
    2031              : 
    2032              :     character,       intent(in   ) :: transa
    2033              :     character,       intent(in   ) :: transb
    2034              :     complex(kind=8), intent(in   ) :: alpha
    2035              :     type(xgBlock_t), intent(in   ) :: xgBlockA
    2036              :     type(xgBlock_t), intent(in   ) :: xgBlockB
    2037              :     complex(kind=8), intent(in   ) :: beta
    2038              :     type(xgBlock_t), intent(inout) :: xgBlockW
    2039              :     integer,optional,intent(in)    :: comm
    2040              :     logical,optional,intent(in)    :: timing
    2041              : 
    2042              :     integer          :: K
    2043              :     double precision :: tsec(2)
    2044              :     character(kind=1) :: transa_,transb_
    2045              :     logical :: timing_
    2046              : 
    2047            0 :     timing_ = .true.
    2048            0 :     if (present(timing)) then
    2049            0 :       timing_ = timing
    2050              :     end if
    2051            0 :     if (timing_) call timab(tim_gemm_blas,1,tsec)
    2052              : 
    2053            0 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    2054            0 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    2055              : 
    2056            0 :     if ( xgBlockA%space /= xgBlockB%space .or. xgBlockB%space /= xgBlockW%space ) then
    2057            0 :       ABI_ERROR("Not same space")
    2058              :     end if
    2059            0 :     if ( xgBlockA%space /= SPACE_C ) then
    2060            0 :       ABI_ERROR("Not correct space")
    2061              :     end if
    2062              : 
    2063            0 :     if (transa /= 'n' .and. transa /= 't') then
    2064            0 :       ABI_ERROR("transa should be 'n' or 't'")
    2065              :     end if
    2066            0 :     if (transb /= 'n' .and. transb /= 't') then
    2067            0 :       ABI_ERROR("transb should be 'n' or 't'")
    2068              :     end if
    2069              : 
    2070            0 :     if ( transa == 'n' ) then
    2071            0 :       K = xgBlockA%cols
    2072              :     else
    2073            0 :       K = xgBlockA%rows
    2074              :     end if
    2075              : 
    2076            0 :     transa_=transa
    2077            0 :     if (transa=='t') transa_ = 'c'
    2078            0 :     transb_=transb
    2079            0 :     if (transb=='t') transb_ = 'c'
    2080              : 
    2081              :     ! CALL GEMM
    2082              :     call abi_xgemm(transa_, transb_, xgBlockW%rows, xgBlockW%cols, K, &
    2083              :     &    alpha, &
    2084              :     &    xgBlockA%vecC, xgBlockA%LDim, &
    2085              :     &    xgBlockB%vecC, xgBlockB%LDim, &
    2086              :     &    beta, &
    2087              :     &    xgBlockW%vecC, xgBlockW%LDim, &
    2088            0 :     &    gpu_option=xgBlockA%gpu_option)
    2089              :     ! END CALL GEMM
    2090            0 :     if (timing_) call timab(tim_gemm_blas,2,tsec)
    2091              : 
    2092              :     ! MPI SUM
    2093            0 :     if ( present(comm) ) then
    2094            0 :       if (timing_) call timab(tim_gemm_mpi,1,tsec)
    2095            0 :       call xgBlock_mpi_sum(xgBlockW,comm=comm)
    2096            0 :       if (timing_) call timab(tim_gemm_mpi,2,tsec)
    2097              :     end if
    2098              : 
    2099            0 :   end subroutine xgBlock_gemmC
    2100              :   !!***
    2101              : 
    2102              : !!****f* m_xg/xgBlock_trmmR
    2103              : !!
    2104              : !! NAME
    2105              : !! xgBlock_trmmR
    2106              : 
    2107            0 :   subroutine xgBlock_trmmR(side, uplo, transa, diag, alpha, xgBlockA, xgBlockB)
    2108              : 
    2109              :     character, intent(in) :: transa,side,uplo,diag
    2110              :     double precision, intent(in) :: alpha
    2111              :     type(xgBlock_t), intent(in) :: xgBlockA
    2112              :     type(xgBlock_t), intent(inout) :: xgBlockB
    2113              : 
    2114              :     complex(kind=8) :: calpha
    2115              : 
    2116            0 :     if (xgBlockA%gpu_option/=ABI_GPU_DISABLED) then
    2117            0 :       ABI_ERROR('Not implemented for GPU')
    2118              :     end if
    2119            0 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    2120              : 
    2121            0 :     if ( xgBlockA%space /= xgBlockB%space .or. xgBlockB%space /= xgBlockB%space ) then
    2122            0 :       ABI_ERROR("Not same space")
    2123              :     end if
    2124              : 
    2125            0 :     select case(xgBlockA%space)
    2126              :     case (SPACE_R)
    2127              :       call dtrmm(side,uplo,transa,diag,transa,xgBlockB%rows,xgBlockB%cols,&
    2128              :         alpha,xgBlockA%vecR, xgBlockA%LDim, &
    2129            0 :         xgBlockB%vecR, xgBlockB%LDim)
    2130              :     case (SPACE_CR)
    2131            0 :       ABI_ERROR("Not implemented")
    2132              :       !call dtrmm(side,uplo,transa,diag,transa,xgBlockB%rows,xgBlockB%cols,&
    2133              :       !  alpha,xgBlockA%vecR, xgBlockA%LDim, &
    2134              :       !  xgBlockB%vecR, xgBlockB%LDim)
    2135              :     case(SPACE_C)
    2136            0 :       calpha = dcmplx(alpha,0.d0)
    2137              :       call ztrmm(side,uplo,transa,diag,transa,xgBlockB%rows,xgBlockB%cols,&
    2138              :         calpha,xgBlockA%vecC, xgBlockA%LDim, &
    2139            0 :         xgBlockB%vecC, xgBlockB%LDim)
    2140              :     end select
    2141              : 
    2142            0 :   end subroutine xgBlock_trmmR
    2143              : !!***
    2144              : 
    2145              :   !!****f* m_xg/xgBlock_potrf
    2146              :   !!
    2147              :   !! NAME
    2148              :   !! xgBlock_potrf
    2149              : 
    2150       793643 :   subroutine xgBlock_potrf(xgBlock,uplo,info)
    2151              : 
    2152              :     type(xgBlock_t), intent(inout) :: xgBlock
    2153              :     character      , intent(in   ) :: uplo
    2154              :     integer        , intent(  out) :: info
    2155              :     double precision :: tsec(2)
    2156              : 
    2157       793643 :     call timab(tim_potrf,1,tsec)
    2158              : 
    2159       793643 :     if ( xgBlock%rows /= xgBlock%cols ) then
    2160            0 :       ABI_ERROR("Matrix should be a square matrixx")
    2161              :     endif
    2162              : 
    2163       888699 :     select case(xgBlock%space)
    2164              :     case (SPACE_R)
    2165              :       call abi_xpotrf(uplo,xgBlock%rows,xgBlock%vecR,xgBlock%LDim,info, &
    2166        95056 :         x_cplx=1,gpu_option=xgBlock%gpu_option)
    2167              :     case (SPACE_C)
    2168              :       call abi_xpotrf(uplo,xgBlock%rows,xgBlock%vecC,xgBlock%LDim,info, &
    2169       698587 :         gpu_option=xgBlock%gpu_option)
    2170              :     case (SPACE_CR)
    2171       793643 :       ABI_ERROR('Not implemented for SPACE_CR')
    2172              :     end select
    2173              : 
    2174       793643 :     if(xgBlock%gpu_option==ABI_GPU_KOKKOS) call gpu_device_synchronize()
    2175              : 
    2176       793643 :     call timab(tim_potrf,2,tsec)
    2177              : 
    2178       793643 :   end subroutine xgBlock_potrf
    2179              :   !!***
    2180              : 
    2181              :   !!****f* m_xg/xgBlock_heev
    2182              :   !!
    2183              :   !! NAME
    2184              :   !! xgBlock_heev
    2185              : 
    2186              : 
    2187              :   !===================================================
    2188              :   != Hermitian Full Matrix diago
    2189              :   !===================================================
    2190            0 :   subroutine xgBlock_heev(jobz,uplo,xgBlockA,xgBlockW,info)
    2191              : 
    2192              :     character       , intent(in   ) :: jobz
    2193              :     character       , intent(in   ) :: uplo
    2194              :     type(xgBlock_t) , intent(inout) :: xgBlockA
    2195              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2196              :     integer         , intent(  out) :: info
    2197              :     double precision :: tsec(2)
    2198              : 
    2199            0 :     call timab(tim_heev,1,tsec)
    2200              : 
    2201            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2202            0 :       ABI_ERROR("Block3 must be real")
    2203              :     end if
    2204              : 
    2205            0 :     select case(xgBlockA%space)
    2206              : 
    2207              :     case (SPACE_R)
    2208            0 :       call checkResize(rwork,lrwork,8*xgBlockA%rows)
    2209              : 
    2210              :       call dsyev(jobz,uplo,xgBlockA%cols, &
    2211              :         xgBlockA%vecR,xgBlockA%LDim, &
    2212              :         xgBlockW%vecR, &
    2213            0 :         rwork, lrwork,info)
    2214              : 
    2215              : 
    2216              :     case (SPACE_C)
    2217            0 :       call checkResize(rwork,lrwork,3*xgBlockA%cols-2)
    2218            0 :       call checkResize(cwork,lcwork,lrwork)
    2219              : 
    2220              :       call zheev(jobz,uplo,xgBlockA%cols, &
    2221              :         xgBlockA%vecC,xgBlockA%LDim, &
    2222              :         xgBlockW%vecR, &
    2223            0 :         cwork, lrwork, rwork, info)
    2224              : 
    2225              :     case (SPACE_CR)
    2226            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2227              : 
    2228              :     end select
    2229              : 
    2230            0 :     if ( rwork(1) > lrwork ) then
    2231              :       !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2232            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2233              :     end if
    2234              : 
    2235            0 :     call timab(tim_heev,2,tsec)
    2236              : 
    2237            0 :   end subroutine xgBlock_heev
    2238              :   !!***
    2239              : 
    2240              :   !!****f* m_xg/xgBlock_heevd
    2241              :   !!
    2242              :   !! NAME
    2243              :   !! xgBlock_heevd
    2244              : 
    2245       178137 :   subroutine xgBlock_heevd(jobz, uplo, xgBlockA, xgBlockW, info)
    2246              : 
    2247              :     character       , intent(in   ) :: jobz
    2248              :     character       , intent(in   ) :: uplo
    2249              :     type(xgBlock_t) , intent(inout) :: xgBlockA
    2250              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2251              :     integer         , intent(  out) :: info
    2252              :     double precision :: tsec(2)
    2253              : 
    2254       178137 :     call timab(tim_heevd,1,tsec)
    2255              : 
    2256       178137 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    2257              : 
    2258       178137 :     if ( xgBlockW%space /= SPACE_R ) then
    2259            0 :       ABI_ERROR("Block3 must be real")
    2260              :     end if
    2261              : 
    2262       178137 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS .or. xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    2263            0 :       select case(xgBlockA%space)
    2264              : 
    2265              :       case (SPACE_R)
    2266              :         call abi_xheevd(jobz, uplo, xgBlockA%cols, &
    2267              :             xgBlockA%vecR, xgBlockA%LDim, &
    2268              :             xgBlockW%vecR, info, &
    2269            0 :             x_cplx=1, gpu_option=xgBlockA%gpu_option)
    2270              : 
    2271              :       case (SPACE_C)
    2272              :         call abi_xheevd(jobz, uplo, xgBlockA%cols, &
    2273              :             xgBlockA%vecC, xgBlockA%LDim, &
    2274              :             xgBlockW%vecR, info, &
    2275            0 :             gpu_option=xgBlockA%gpu_option)
    2276              : 
    2277              :       case (SPACE_CR)
    2278            0 :         ABI_ERROR('Not implemented for SPACE_CR')
    2279              : 
    2280              :       end select
    2281              : 
    2282            0 :       if(xgBlockA%gpu_option==ABI_GPU_KOKKOS) call gpu_device_synchronize()
    2283              : 
    2284              :     else
    2285              : 
    2286       178137 :       call checkResize(iwork,liwork,5*xgBlockA%rows+3)
    2287              : 
    2288       202885 :       select case(xgBlockA%space)
    2289              : 
    2290              :       case (SPACE_R)
    2291        24748 :         call checkResize(rwork,lrwork,2*xgBlockA%rows*xgBlockA%rows+6*xgBlockA%rows+1)
    2292              : 
    2293              :         call dsyevd(jobz,uplo,xgBlockA%cols, &
    2294              :           xgBlockA%vecR,xgBlockA%LDim, &
    2295              :         xgBlockW%vecR, rwork, lrwork, &
    2296        24748 :         iwork, liwork,info)
    2297              : 
    2298              :       case (SPACE_C)
    2299       153389 :         call checkResize(cwork,lcwork,xgBlockA%rows*xgBlockA%rows+2*xgBlockA%rows)
    2300       153389 :         call checkResize(rwork,lrwork,2*xgBlockA%rows*xgBlockA%rows+5*xgBlockA%rows+1)
    2301              : 
    2302              :         call zheevd(jobz,uplo,xgBlockA%cols, &
    2303              :           xgBlockA%vecC,xgBlockA%LDim, &
    2304              :         xgBlockW%vecR, &
    2305       153389 :         cwork, lcwork, rwork, lrwork, iwork, liwork, info)
    2306              : 
    2307       153389 :         if ( int(cwork(1)) > lcwork ) then
    2308              :           !write(std_out,*) "Allocate work from", int(lcwork), "to", int(cwork(1))
    2309          295 :           call checkResize(cwork,lcwork,int(cwork(1)))
    2310              :         end if
    2311              : 
    2312              :       case (SPACE_CR)
    2313       178137 :         ABI_ERROR('Not implemented for SPACE_CR')
    2314              : 
    2315              :       end select
    2316              : 
    2317       178137 :       if ( rwork(1) > lrwork ) then
    2318              :         !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2319            0 :         call checkResize(rwork,lrwork,int(rwork(1)))
    2320              :       end if
    2321              : 
    2322       178137 :       if ( iwork(1) > liwork ) then
    2323              :         !write(std_out,*) "Allocate work from", liwork, "to", int(iwork(1))
    2324            0 :         call checkResize(iwork,liwork,int(iwork(1)))
    2325              :       end if
    2326              : 
    2327              :     end if
    2328              : 
    2329              : 
    2330       178137 :     call timab(tim_heevd,2,tsec)
    2331              : 
    2332       178137 :   end subroutine xgBlock_heevd
    2333              :   !!***
    2334              : 
    2335              :   !!****f* m_xg/xgBlock_hpev
    2336              :   !!
    2337              :   !! NAME
    2338              :   !! xgBlock_hpev
    2339              : 
    2340              :   !===================================================
    2341              :   != Hermitian Packed Matrix diago
    2342              :   !===================================================
    2343            0 :   subroutine xgBlock_hpev(jobz,uplo,xgBlockAP,xgBlockW,xgBlockZ,info)
    2344              : 
    2345              :     character       , intent(in   ) :: jobz
    2346              :     character       , intent(in   ) :: uplo
    2347              :     type(xgBlock_t) , intent(inout) :: xgBlockAP
    2348              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2349              :     type(xgBlock_t) , intent(inout) :: xgBlockZ
    2350              :     integer         , intent(  out) :: info
    2351              :     double precision :: tsec(2)
    2352              : 
    2353            0 :     call timab(tim_hpev,1,tsec)
    2354              : 
    2355            0 :     if ( xgBlockAP%space /= xgBlockZ%space ) then
    2356            0 :       ABI_ERROR("Not same space")
    2357              :     end if
    2358              : 
    2359            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2360            0 :       ABI_ERROR("Block3 must be real")
    2361              :     end if
    2362              : 
    2363            0 :     select case(xgBlockAP%space)
    2364              : 
    2365              :     case (SPACE_R)
    2366            0 :       call checkResize(rwork,lrwork,3*xgBlockZ%cols)
    2367              : 
    2368              :       call dspev(jobz,uplo,xgBlockZ%cols, &
    2369              :         xgBlockAP%vecR, xgBlockW%vecR, xgBlockZ%vecR, xgBlockZ%Ldim, &
    2370            0 :         rwork, info)
    2371              : 
    2372              : 
    2373              :     case (SPACE_C)
    2374            0 :       call checkResize(cwork,lcwork,2*xgBlockZ%cols-1)
    2375            0 :       call checkResize(rwork,lrwork,3*xgBlockZ%cols-2)
    2376              : 
    2377              :       call zhpev(jobz,uplo,xgBlockZ%cols, &
    2378              :         xgBlockAP%vecC, xgBlockW%vecR, xgBlockZ%vecC, xgBlockZ%Ldim, &
    2379            0 :         cwork, rwork, info)
    2380              : 
    2381            0 :       if ( int(cwork(1)) > lcwork ) then
    2382              :         !write(std_out,*) "Allocate cwork from", lcwork, "to", int(cwork(1))
    2383            0 :         call checkResize(cwork,lcwork,int(cwork(1)))
    2384              :       end if
    2385              : 
    2386              :     case (SPACE_CR)
    2387            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2388              : 
    2389              :     end select
    2390              : 
    2391            0 :     if ( rwork(1) > lrwork ) then
    2392              :       !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2393            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2394              :     end if
    2395              : 
    2396            0 :     call timab(tim_hpev,2,tsec)
    2397              : 
    2398            0 :   end subroutine xgBlock_hpev
    2399              :   !!***
    2400              : 
    2401              :   !!****f* m_xg/xgBlock_hpevd
    2402              :   !!
    2403              :   !! NAME
    2404              :   !! xgBlock_hpevd
    2405              : 
    2406            0 :   subroutine xgBlock_hpevd(jobz,uplo,xgBlockAP,xgBlockW,xgBlockZ,info)
    2407              : 
    2408              :     character       , intent(in   ) :: jobz
    2409              :     character       , intent(in   ) :: uplo
    2410              :     type(xgBlock_t) , intent(inout) :: xgBlockAP
    2411              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2412              :     type(xgBlock_t) , intent(inout) :: xgBlockZ
    2413              :     integer         , intent(  out) :: info
    2414              :     double precision :: tsec(2)
    2415              : 
    2416            0 :     call timab(tim_hpevd,1,tsec)
    2417              : 
    2418            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2419            0 :       ABI_ERROR("Block3 must be real")
    2420              :     end if
    2421              : 
    2422            0 :     if ( xgBlockAP%space /= xgBlockZ%space ) then
    2423            0 :       ABI_ERROR("Block 1 and 3 must have the same space")
    2424              :     end if
    2425              : 
    2426            0 :     call checkResize(iwork,liwork,5*xgBlockZ%rows+3)
    2427            0 :     select case(xgBlockAP%space)
    2428              : 
    2429              :     case (SPACE_R)
    2430            0 :       call checkResize(rwork,lrwork,xgBlockZ%rows*xgBlockZ%rows+6*xgBlockZ%rows+1)
    2431              : 
    2432              :       call dspevd(jobz,uplo,xgBlockZ%cols, &
    2433              :         xgBlockAP%vecR, xgBlockW%vecR, xgBlockZ%vecR, xgBlockZ%Ldim, &
    2434            0 :         rwork, lrwork, iwork, liwork,info)
    2435              : 
    2436              : 
    2437              :     case (SPACE_C)
    2438            0 :       call checkResize(cwork,lcwork,2*xgBlockZ%rows)
    2439            0 :       call checkResize(rwork,lrwork,2*xgBlockZ%rows*xgBlockZ%rows+5*xgBlockZ%rows+1)
    2440              : 
    2441              :       call zhpevd(jobz,uplo,xgBlockZ%cols, &
    2442              :         xgBlockAP%vecC, xgBlockW%vecR, xgBlockZ%vecC, xgBlockZ%Ldim, &
    2443            0 :         cwork, lcwork, rwork, lrwork, iwork, liwork, info)
    2444              : 
    2445            0 :       if ( int(cwork(1)) > lcwork ) then
    2446              :         !write(std_out,*) "Allocate work from", lcwork, "to", int(cwork(1))
    2447            0 :         call checkResize(cwork,lcwork,int(cwork(1)))
    2448              :       end if
    2449              : 
    2450              :     case (SPACE_CR)
    2451            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2452              : 
    2453              :     end select
    2454              : 
    2455            0 :     if ( int(rwork(1)) > lrwork ) then
    2456              :       !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2457            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2458              :     end if
    2459              : 
    2460            0 :     if ( iwork(1) > liwork ) then
    2461              :       !write(std_out,*) "Allocate work from", liwork, "to", int(iwork(1))
    2462            0 :       call checkResize(iwork,liwork,int(iwork(1)))
    2463              :     end if
    2464              : 
    2465            0 :     call timab(tim_hpevd,2,tsec)
    2466              : 
    2467            0 :   end subroutine xgBlock_hpevd
    2468              :   !!***
    2469              : 
    2470              :   !!****f* m_xg/xgBlock_hgev
    2471              :   !!
    2472              :   !! NAME
    2473              :   !! xgBlock_hgev
    2474              : 
    2475              :   !===================================================
    2476              :   != Hermitian Full Generalized Matrix diago
    2477              :   !===================================================
    2478              : 
    2479            0 :   subroutine xgBlock_hegv(itype, jobz, uplo, xgBlockA, xgBlockB, xgBlockW, info)
    2480              : 
    2481              :     integer         , intent(in   ) :: itype
    2482              :     character       , intent(in   ) :: jobz
    2483              :     character       , intent(in   ) :: uplo
    2484              :     type(xgBlock_t) , intent(inout) :: xgBlockA
    2485              :     type(xgBlock_t) , intent(inout) :: xgBlockB
    2486              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2487              :     integer         , intent(  out) :: info
    2488              :     double precision :: tsec(2)
    2489              : 
    2490            0 :     call timab(tim_hegv,1,tsec)
    2491              : 
    2492            0 :     if ( xgBlockA%space /= xgBlockB%space ) then
    2493            0 :       ABI_ERROR("Not same space")
    2494              :     end if
    2495            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2496            0 :       ABI_ERROR("Block3 must be real")
    2497              :     end if
    2498              : 
    2499            0 :     select case(xgBlockA%space)
    2500              : 
    2501              :     case (SPACE_R)
    2502            0 :       call checkResize(rwork,lrwork,2*xgBlockA%rows*xgBlockA%rows+6*xgBlockA%rows+1)
    2503              : 
    2504              :       call dsygv(itype, jobz, uplo, xgBlockA%rows, xgBlockA%vecR, xgBlockA%ldim, &
    2505            0 :         xgBlockB%vecR, xgBlockB%ldim, xgBlockW%vecR, rwork, lrwork, info)
    2506              : 
    2507              :     case (SPACE_C)
    2508              : 
    2509            0 :       call checkResize(cwork,lcwork,2*xgBlockA%rows-1)
    2510            0 :       call checkResize(rwork,lrwork,3*xgBlockA%rows-2)
    2511              : 
    2512              :       call zhegv(itype, jobz, uplo, xgBlockA%rows, xgBlockA%vecC, xgBlockA%ldim,&
    2513              :         xgBlockB%vecC, xgBlockB%ldim, xgBlockW%vecR, cwork, lcwork, &
    2514            0 :         rwork, info)
    2515              : 
    2516            0 :       if ( int(cwork(1)) > lcwork ) then
    2517              :         !write(std_out,*) "Allocate work from", lcwork, "to", int(cwork(1))
    2518            0 :         call checkResize(cwork,lcwork,int(cwork(1)))
    2519              :       end if
    2520              : 
    2521              :     case (SPACE_CR)
    2522            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2523              : 
    2524              :     end select
    2525              : 
    2526            0 :     if ( rwork(1) > lrwork ) then
    2527              :       !write(std_out,*) "Allocate rwork from", lrwork, "to", int(rwork(1))
    2528            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2529              :     end if
    2530              : 
    2531            0 :     call timab(tim_hegv,2,tsec)
    2532              : 
    2533            0 :   end subroutine xgBlock_hegv
    2534              :   !!***
    2535              : 
    2536              :   !!****f* m_xg/xgBlock_hegvx
    2537              :   !!
    2538              :   !! NAME
    2539              :   !! xgBlock_hegvx
    2540              : 
    2541            0 :   subroutine xgBlock_hegvx(itype,jobz,range,uplo,xgBlockA,xgBlockB,vl,vu,il,iu,abstol,xgBlockW,xgBlockZ,info)
    2542              : 
    2543              :     integer         , intent(in   ) :: itype
    2544              :     character       , intent(in   ) :: jobz
    2545              :     character       , intent(in   ) :: range
    2546              :     character       , intent(in   ) :: uplo
    2547              :     type(xgBlock_t) , intent(inout) :: xgBlockA
    2548              :     type(xgBlock_t) , intent(inout) :: xgBlockB
    2549              :     double precision, intent(in   ) :: vl
    2550              :     double precision, intent(in   ) :: vu
    2551              :     integer         , intent(in   ) :: il
    2552              :     integer         , intent(in   ) :: iu
    2553              :     double precision, intent(in   ) :: abstol
    2554              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2555              :     type(xgBlock_t) , intent(inout) :: xgBlockZ
    2556              :     integer         , intent(  out) :: info
    2557              :     integer :: neigen
    2558            0 :     integer, allocatable :: ifail(:)
    2559              :     double precision :: tsec(2)
    2560              : 
    2561            0 :     call timab(tim_hegvx,1,tsec)
    2562              : 
    2563            0 :     if ( xgBlockA%space /= xgBlockB%space .or. xgBlockA%space /= xgBlockZ%space ) then
    2564            0 :       ABI_ERROR("Not same space")
    2565              :     end if
    2566            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2567            0 :       ABI_ERROR("Block3 must be real")
    2568              :     end if
    2569              : 
    2570            0 :     call checkResize(iwork,liwork,5*xgBlockA%rows)
    2571              : 
    2572            0 :     ABI_MALLOC(ifail,(xgBlockA%rows))
    2573            0 :     ifail = 0
    2574              : 
    2575            0 :     select case(xgBlockA%space)
    2576              : 
    2577              :     case (SPACE_R)
    2578            0 :       call checkResize(rwork,lrwork,8*xgBlockA%rows)
    2579              : 
    2580              :       call dsygvx(itype,jobz,range,uplo,xgBlockA%rows, &
    2581              :         xgBlockA%vecR,xgBlockA%LDim,xgBlockB%vecR,xgBlockB%LDim, &
    2582              :         vl,vu,il,iu,abstol,&
    2583              :         neigen,xgBlockW%vecR, xgBlockZ%vecR, xgBlockZ%LDim, &
    2584            0 :         rwork, lrwork,iwork,ifail,info)
    2585              : 
    2586              :     case (SPACE_C)
    2587            0 :       call checkResize(rwork,lrwork,7*xgBlockA%rows)
    2588            0 :       call checkResize(cwork,lcwork,lrwork)
    2589              : 
    2590              :       call zhegvx(itype,jobz,range,uplo,xgBlockA%rows, &
    2591              :         xgBlockA%vecC,xgBlockA%LDim,xgBlockB%vecC,xgBlockB%LDim, &
    2592              :         vl,vu,il,iu,abstol,&
    2593              :         neigen,xgBlockW%vecR, xgBlockZ%vecC, xgBlockZ%LDim, &
    2594            0 :         cwork, lcwork, rwork, iwork,ifail,info)
    2595              : 
    2596              :     case (SPACE_CR)
    2597            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2598              : 
    2599              :     end select
    2600            0 :     ABI_FREE(ifail)
    2601              : 
    2602            0 :     if ( rwork(1) > lrwork ) then
    2603              :       !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2604            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2605              :     end if
    2606              : 
    2607              : 
    2608            0 :     call timab(tim_hegvx,2,tsec)
    2609              : 
    2610            0 :   end subroutine xgBlock_hegvx
    2611              :   !!***
    2612              : 
    2613              :   !!****f* m_xg/xgBlock_hegvd
    2614              :   !!
    2615              :   !! NAME
    2616              :   !! xgBlock_hegvd
    2617              : 
    2618       639890 :   subroutine xgBlock_hegvd(itype, jobz, uplo, xgBlockA, xgBlockB, xgBlockW, info)
    2619              : 
    2620              :     integer         , intent(in   ) :: itype
    2621              :     character       , intent(in   ) :: jobz
    2622              :     character       , intent(in   ) :: uplo
    2623              :     type(xgBlock_t) , intent(inout) :: xgBlockA
    2624              :     type(xgBlock_t) , intent(inout) :: xgBlockB
    2625              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2626              :     integer         , intent(  out) :: info
    2627              : 
    2628              :     double precision :: tsec(2)
    2629              : 
    2630              : 
    2631       639890 :     call timab(tim_hegvd,1,tsec)
    2632              : 
    2633       639890 :     if ( xgBlockA%space /= xgBlockB%space ) then
    2634            0 :       ABI_ERROR("Not same space")
    2635              :     end if
    2636       639890 :     if ( xgBlockW%space /= SPACE_R ) then
    2637            0 :       ABI_ERROR("Block3 must be real")
    2638              :     end if
    2639              : 
    2640       639890 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    2641       639890 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    2642              : 
    2643       639890 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS .or. xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    2644              : 
    2645            0 :       select case(xgBlockA%space)
    2646              : 
    2647              :       case (SPACE_R)
    2648              :         call abi_xhegvd(itype, jobz, uplo, xgBlockA%rows, &
    2649              :             xgBlockA%vecR, xgBlockA%ldim, &
    2650              :             xgBlockB%vecR, xgBlockB%ldim, &
    2651              :             xgBlockW%vecR, info, &
    2652            0 :             x_cplx=1, gpu_option=xgBlockA%gpu_option)
    2653              : 
    2654              :       case (SPACE_C)
    2655              :         call abi_xhegvd(itype, jobz, uplo, xgBlockA%rows, &
    2656              :             xgBlockA%vecC, xgBlockA%ldim, &
    2657              :             xgBlockB%vecC, xgBlockB%ldim, &
    2658              :             xgBlockW%vecR, info, &
    2659            0 :             gpu_option=xgBlockA%gpu_option)
    2660              : 
    2661              :       case (SPACE_CR)
    2662            0 :         ABI_ERROR('Not implemented for SPACE_CR')
    2663              : 
    2664              :       end select
    2665              : 
    2666            0 :       if(xgBlockA%gpu_option==ABI_GPU_KOKKOS) call gpu_device_synchronize()
    2667              : 
    2668              :     else
    2669              : 
    2670       639890 :       call checkResize(iwork,liwork,5*xgBlockA%rows+3)
    2671              : 
    2672       719990 :       select case(xgBlockA%space)
    2673              : 
    2674              :       case (SPACE_R)
    2675              : 
    2676        80100 :         call checkResize(rwork,lrwork,2*xgBlockA%rows*xgBlockA%rows+6*xgBlockA%rows+1)
    2677              : 
    2678              :         call dsygvd(itype, jobz, uplo, xgBlockA%rows, xgBlockA%vecR, xgBlockA%ldim, &
    2679        80100 :           xgBlockB%vecR, xgBlockB%ldim, xgBlockW%vecR, rwork, lrwork, iwork, liwork, info)
    2680              : 
    2681              :       case (SPACE_C)
    2682              : 
    2683       559790 :         call checkResize(cwork,lcwork,xgBlockA%rows*xgBlockA%rows+2*xgBlockA%rows)
    2684       559790 :         call checkResize(rwork,lrwork,2*(xgBlockA%rows*xgBlockA%rows)+5*xgBlockA%rows+1)
    2685              : 
    2686              :         call zhegvd(itype, jobz, uplo, xgBlockA%rows, xgBlockA%vecC, xgBlockA%ldim,&
    2687              :           xgBlockB%vecC, xgBlockB%ldim, xgBlockW%vecR, cwork, lcwork, &
    2688       559790 :           rwork, lrwork, iwork, liwork, info)
    2689              : 
    2690       559790 :         if ( int(cwork(1)) > lcwork ) then
    2691              :           !write(std_out,*) "Allocate work from", lcwork, "to", int(cwork(1))
    2692          267 :           call checkResize(cwork,lcwork,int(cwork(1)))
    2693              :         end if
    2694              : 
    2695              :       case (SPACE_CR)
    2696       639890 :         ABI_ERROR('Not implemented for SPACE_CR')
    2697              : 
    2698              :       end select
    2699              : 
    2700       639890 :       if ( rwork(1) > lrwork ) then
    2701              :         !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2702            0 :         call checkResize(rwork,lrwork,int(rwork(1)))
    2703              :       end if
    2704              : 
    2705              : 
    2706       639890 :       if ( iwork(1) > liwork ) then
    2707              :         !write(std_out,*) "Allocate work from", liwork, "to", int(iwork(1))
    2708            0 :         call checkResize(iwork,liwork,int(iwork(1)))
    2709              :       end if
    2710              : 
    2711              :     end if
    2712              : 
    2713       639890 :     call timab(tim_hegvd,2,tsec)
    2714              : 
    2715       639890 :   end subroutine xgBlock_hegvd
    2716              :   !!***
    2717              : 
    2718              :   !!****f* m_xg/xgBlock_hpgv
    2719              :   !!
    2720              :   !! NAME
    2721              :   !! xgBlock_hpgv
    2722              : 
    2723              :   !===================================================
    2724              :   != Hermitian Full Generalized Matrix diago
    2725              :   !===================================================
    2726              : 
    2727            0 :   subroutine xgBlock_hpgv(itype, jobz, uplo, xgBlockAP, xgBlockBP, xgBlockW, xgBlockZ,info)
    2728              : 
    2729              :     integer         , intent(in   ) :: itype
    2730              :     character       , intent(in   ) :: jobz
    2731              :     character       , intent(in   ) :: uplo
    2732              :     type(xgBlock_t) , intent(inout) :: xgBlockAP
    2733              :     type(xgBlock_t) , intent(inout) :: xgBlockBP
    2734              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2735              :     type(xgBlock_t) , intent(inout) :: xgBlockZ
    2736              :     integer         , intent(  out) :: info
    2737              :     double precision :: tsec(2)
    2738              : 
    2739            0 :     call timab(tim_hpgv,1,tsec)
    2740              : 
    2741            0 :     if ( xgBlockAP%space /= xgBlockBP%space ) then
    2742            0 :       ABI_ERROR("Not same space")
    2743              :     end if
    2744              : 
    2745            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2746            0 :       ABI_ERROR("Block3 must be real")
    2747              :     end if
    2748              : 
    2749            0 :     select case(xgBlockAP%space)
    2750              : 
    2751              :     case (SPACE_R)
    2752            0 :       call checkResize(rwork,lrwork,3*xgBlockZ%rows)
    2753              : 
    2754              :       call dspgv(itype, jobz, uplo, xgBlockZ%rows, xgBlockAP%vecR, xgBlockBP%vecR, &
    2755            0 :         xgBlockW%vecR, xgBlockZ%vecR, xgBlockZ%Ldim, rwork, info)
    2756              : 
    2757              :     case (SPACE_C)
    2758              : 
    2759            0 :       call checkResize(cwork,lcwork,2*xgBlockZ%rows-1)
    2760            0 :       call checkResize(rwork,lrwork,3*xgBlockZ%rows-2)
    2761              : 
    2762              :       call zhpgv(itype, jobz, uplo, xgBlockAP%rows, xgBlockAP%vecC, xgBlockBP%vecC, &
    2763            0 :         xgBlockW%vecR, xgBlockZ%vecC, xgBlockZ%Ldim, cwork, rwork, info)
    2764              : 
    2765            0 :       if ( int(cwork(1)) > lcwork ) then
    2766              :         !write(std_out,*) "Allocate work from", lcwork, "to", int(cwork(1))
    2767            0 :         call checkResize(cwork,lcwork,int(cwork(1)))
    2768              :       end if
    2769              : 
    2770              :     case (SPACE_CR)
    2771            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2772              : 
    2773              :     end select
    2774              : 
    2775            0 :     if ( rwork(1) > lrwork ) then
    2776              :       !write(std_out,*) "Allocate rwork from", lrwork, "to", int(rwork(1))
    2777            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2778              :     end if
    2779              : 
    2780            0 :     call timab(tim_hpgv,2,tsec)
    2781              : 
    2782            0 :   end subroutine xgBlock_hpgv
    2783              :   !!***
    2784              : 
    2785              :   !!****f* m_xg/xgBlock_hpgvx
    2786              :   !!
    2787              :   !! NAME
    2788              :   !! xgBlock_hpgvx
    2789              : 
    2790            0 :   subroutine xgBlock_hpgvx(itype,jobz,range,uplo,xgBlockAP,xgBlockBP,vl,vu,il,iu,abstol,xgBlockW,xgBlockZ,info)
    2791              : 
    2792              :     integer         , intent(in   ) :: itype
    2793              :     character       , intent(in   ) :: jobz
    2794              :     character       , intent(in   ) :: range
    2795              :     character       , intent(in   ) :: uplo
    2796              :     type(xgBlock_t) , intent(inout) :: xgBlockAP
    2797              :     type(xgBlock_t) , intent(inout) :: xgBlockBP
    2798              :     double precision, intent(in   ) :: vl
    2799              :     double precision, intent(in   ) :: vu
    2800              :     integer         , intent(in   ) :: il
    2801              :     integer         , intent(in   ) :: iu
    2802              :     double precision, intent(in   ) :: abstol
    2803              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2804              :     type(xgBlock_t) , intent(inout) :: xgBlockZ
    2805              :     integer         , intent(  out) :: info
    2806              :     integer :: neigen
    2807            0 :     integer, allocatable :: ifail(:)
    2808              :     double precision :: tsec(2)
    2809              : 
    2810            0 :     call timab(tim_hpgvx,1,tsec)
    2811              : 
    2812            0 :     if ( xgBlockAP%space /= xgBlockBP%space .or. xgBlockAP%space /= xgBlockZ%space ) then
    2813            0 :       ABI_ERROR("Not same space")
    2814              :     end if
    2815            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2816            0 :       ABI_ERROR("Block3 must be real")
    2817              :     end if
    2818              : 
    2819            0 :     call checkResize(iwork,liwork,5*xgBlockZ%rows)
    2820              : 
    2821            0 :     ABI_MALLOC(ifail,(xgBlockZ%rows))
    2822            0 :     ifail = 0
    2823              : 
    2824            0 :     select case(xgBlockAP%space)
    2825              : 
    2826              :     case (SPACE_R)
    2827            0 :       call checkResize(rwork,lrwork,8*xgBlockZ%rows)
    2828              : 
    2829              :       call dspgvx(itype,jobz,range,uplo,xgBlockZ%rows, &
    2830              :         xgBlockAP%vecR,xgBlockBP%vecR, &
    2831              :         vl,vu,il,iu,abstol,&
    2832              :         neigen,xgBlockW%vecR, xgBlockZ%vecR, xgBlockZ%LDim, &
    2833            0 :         rwork, iwork, ifail, info)
    2834              : 
    2835              :     case (SPACE_C)
    2836            0 :       call checkResize(rwork,lrwork,7*xgBlockAP%rows)
    2837            0 :       call checkResize(cwork,lcwork,2*xgBlockZ%rows)
    2838              : 
    2839              :       call zhpgvx(itype,jobz,range,uplo,xgBlockZ%rows, &
    2840              :         xgBlockAP%vecC,xgBlockBP%vecC, &
    2841              :         vl,vu,il,iu,abstol,&
    2842              :         neigen,xgBlockW%vecR, xgBlockZ%vecC, xgBlockZ%LDim, &
    2843            0 :         cwork, rwork, iwork, ifail, info)
    2844              : 
    2845              :     case (SPACE_CR)
    2846            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2847              : 
    2848              :     end select
    2849            0 :     ABI_FREE(ifail)
    2850              : 
    2851            0 :     if ( rwork(1) > lrwork ) then
    2852              :       !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2853            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2854              :     end if
    2855              : 
    2856              : 
    2857            0 :     call timab(tim_hpgvx,2,tsec)
    2858              : 
    2859            0 :   end subroutine xgBlock_hpgvx
    2860              :   !!***
    2861              : 
    2862              :   !!****f* m_xg/xgBlock_hpgvd
    2863              :   !!
    2864              :   !! NAME
    2865              :   !! xgBlock_hpgvd
    2866              : 
    2867            0 :   subroutine xgBlock_hpgvd(itype, jobz, uplo, xgBlockAP, xgBlockBP, xgBlockW, xgBlockZ, info)
    2868              : 
    2869              :     integer         , intent(in   ) :: itype
    2870              :     character       , intent(in   ) :: jobz
    2871              :     character       , intent(in   ) :: uplo
    2872              :     type(xgBlock_t) , intent(inout) :: xgBlockAP
    2873              :     type(xgBlock_t) , intent(inout) :: xgBlockBP
    2874              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    2875              :     type(xgBlock_t) , intent(inout) :: xgBlockZ
    2876              :     integer         , intent(  out) :: info
    2877              :     double precision :: tsec(2)
    2878              : 
    2879            0 :     call timab(tim_hpgvd,1,tsec)
    2880              : 
    2881            0 :     if ( xgBlockAP%space /= xgBlockBP%space ) then
    2882            0 :       ABI_ERROR("Not same space")
    2883              :     end if
    2884            0 :     if ( xgBlockW%space /= SPACE_R ) then
    2885            0 :       ABI_ERROR("Block3 must be real")
    2886              :     end if
    2887              : 
    2888            0 :     call checkResize(iwork,liwork,5*xgBlockZ%rows+3)
    2889              : 
    2890            0 :     select case(xgBlockAP%space)
    2891              : 
    2892              :     case (SPACE_R)
    2893            0 :       call checkResize(rwork,lrwork,2*xgBlockZ%rows*xgBlockZ%rows+6*xgBlockZ%rows+1)
    2894              : 
    2895              :       call dspgvd(itype, jobz, uplo, xgBlockZ%rows, xgBlockAP%vecR, xgBlockBP%vecR, &
    2896              :         xgBlockW%vecR, xgBlockZ%vecR, xgBlockZ%Ldim, &
    2897            0 :         rwork, lrwork, iwork, liwork, info)
    2898              : 
    2899              :     case (SPACE_C)
    2900              : 
    2901            0 :       call checkResize(cwork,lcwork,2*xgBlockZ%rows)
    2902            0 :       call checkResize(rwork,lrwork,2*(xgBlockZ%rows*xgBlockZ%rows)+5*xgBlockZ%rows+1)
    2903              : 
    2904              :       call zhpgvd(itype, jobz, uplo, xgBlockZ%rows, xgBlockAP%vecC, xgBlockBP%vecC, &
    2905              :         xgBlockW%vecR, xgBlockZ%vecC, xgBlockZ%Ldim, &
    2906            0 :         cwork, lcwork, rwork, lrwork, iwork, liwork, info)
    2907              : 
    2908            0 :       if ( int(cwork(1)) > lcwork ) then
    2909              :         !write(std_out,*) "Allocate work from", lcwork, "to", int(cwork(1))
    2910            0 :         call checkResize(cwork,lcwork,int(cwork(1)))
    2911              :       end if
    2912              : 
    2913              :     case (SPACE_CR)
    2914            0 :       ABI_ERROR('Not implemented for SPACE_CR')
    2915              : 
    2916              :     end select
    2917              : 
    2918            0 :     if ( rwork(1) > lrwork ) then
    2919              :       !write(std_out,*) "Allocate work from", lrwork, "to", int(rwork(1))
    2920            0 :       call checkResize(rwork,lrwork,int(rwork(1)))
    2921              :     end if
    2922              : 
    2923            0 :     if ( iwork(1) > liwork ) then
    2924              :       !write(std_out,*) "Allocate work from", liwork, "to", int(iwork(1))
    2925            0 :       call checkResize(iwork,liwork,int(iwork(1)))
    2926              :     end if
    2927              : 
    2928            0 :     call timab(tim_hpgvd,2,tsec)
    2929              : 
    2930            0 :   end subroutine xgBlock_hpgvd
    2931              :   !!***
    2932              : 
    2933              :   !!****f* m_xg/xgBlock_trsmR
    2934              :   !!
    2935              :   !! NAME
    2936              :   !! xgBlock_trsmR
    2937              : 
    2938      2329823 :   subroutine xgBlock_trsmR(side,uplo,transa,diag,alpha,xgBlockA,xgBlockB)
    2939              : 
    2940              :     character       , intent(in   ) :: side
    2941              :     character       , intent(in   ) :: uplo
    2942              :     character       , intent(in   ) :: transa
    2943              :     character       , intent(in   ) :: diag
    2944              :     double precision, intent(in   ) :: alpha
    2945              :     type(xgBlock_t) , intent(inout) :: xgBlockA
    2946              :     type(xgBlock_t) , intent(inout) :: xgBlockB
    2947              :     complex(kind=8) :: calpha
    2948              :     double precision :: tsec(2)
    2949              :     integer :: fact
    2950              : 
    2951      2329823 :     call timab(tim_trsm,1,tsec)
    2952      2329823 :     if ( xgBlockB%space/=SPACE_CR ) then
    2953      2082924 :       if ( xgBlockA%space /= xgBlockB%space ) then
    2954            0 :         ABI_ERROR("Not same space")
    2955              :       end if
    2956              :     else
    2957       246899 :       if ( xgBlockA%space /= SPACE_R ) then
    2958            0 :         ABI_ERROR("If space(B)=SPACE_CR, space(A) should be space(R)")
    2959              :       end if
    2960              :     end if
    2961              : 
    2962      2329823 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    2963              : 
    2964      2329823 :     fact = 1 ; if (xgBlockB%space==SPACE_CR) fact = 2
    2965              : 
    2966      2584011 :     select case(xgBlockA%space)
    2967              :     case (SPACE_R,SPACE_CR)
    2968              :       call abi_xtrsm(side,uplo,transa,diag,fact*xgBlockB%rows,xgBlockB%cols, &
    2969              :         alpha,xgBlockA%vecR,xgBlockA%LDim,xgBlockB%vecR,fact*xgBlockB%LDim, &
    2970       254188 :         gpu_option=xgBlockA%gpu_option)
    2971              :     case (SPACE_C)
    2972      2075635 :       calpha = dcmplx(alpha,0.d0)
    2973              :       call abi_xtrsm(side,uplo,transa,diag,xgBlockB%rows,xgBlockB%cols, &
    2974              :         calpha,xgBlockA%vecC,xgBlockA%LDim,xgBlockB%vecC,xgBlockB%LDim, &
    2975      2329823 :         gpu_option=xgBlockA%gpu_option)
    2976              :     end select
    2977              : 
    2978      2329823 :     call timab(tim_trsm,2,tsec)
    2979              : 
    2980      2329823 :   end subroutine xgBlock_trsmR
    2981              :   !!***
    2982              : 
    2983              :   !!****f* m_xg/xgBlock_trsmC
    2984              :   !!
    2985              :   !! NAME
    2986              :   !! xgBlock_trsmC
    2987              : 
    2988            0 :   subroutine xgBlock_trsmC(side,uplo,transa,diag,alpha, xgBlockA,xgBlockB)
    2989              : 
    2990              :     character      , intent(in   ) :: side
    2991              :     character      , intent(in   ) :: uplo
    2992              :     character      , intent(in   ) :: transa
    2993              :     character      , intent(in   ) :: diag
    2994              :     complex(kind=8), intent(in   ) :: alpha
    2995              :     type(xgBlock_t), intent(inout) :: xgBlockA
    2996              :     type(xgBlock_t), intent(inout) :: xgBlockB
    2997              :     double precision :: tsec(2)
    2998              : 
    2999            0 :     call timab(tim_trsm,1,tsec)
    3000              : 
    3001            0 :     if ( xgBlockA%space /= xgBlockB%space .or. xgBlockA%space /= SPACE_C) then
    3002            0 :       ABI_ERROR("Space should be SPACE_C for xgBlockA and xgBlockB")
    3003              :     end if
    3004              : 
    3005            0 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    3006              : 
    3007              :     call abi_xtrsm(side,uplo,transa,diag,xgBlockB%rows,xgBlockB%cols, &
    3008              :       alpha,xgBlockA%vecC,xgBlockA%LDim,xgBlockB%vecC,xgBlockB%LDim, &
    3009            0 :       gpu_option=xgBlockA%gpu_option)
    3010              : 
    3011            0 :     call timab(tim_trsm,2,tsec)
    3012              : 
    3013            0 :   end subroutine xgBlock_trsmC
    3014              :   !!***
    3015              : 
    3016              :   !!****f* m_xg/xgBlock_ymax
    3017              :   !!
    3018              :   !! NAME
    3019              :   !! xgBlock_ymax
    3020              :   !!
    3021              :   !! FUNCTION
    3022              :   !! TODO IL-10/03/2025 Be careful, GPU version not tested
    3023              : 
    3024        96999 :   subroutine xgBlock_ymax(xgBlockA, da, shift, nblocks)
    3025              : 
    3026              :     type(xgBlock_t), intent(inout) :: xgBlockA
    3027              :     type(xgBlock_t), intent(in   ) :: da
    3028              :     integer, intent(in) :: shift,nblocks
    3029              : 
    3030              :     integer :: iblock,ncols,irow,nrows,fact
    3031              :     double precision :: tsec(2)
    3032              : 
    3033              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3034              :     complex(dpc), ABI_CONTIGUOUS pointer :: xgBlockA__vecC(:,:),da__vecC(:,:)
    3035              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecR(:,:),da__vecR(:,:)
    3036              : #endif
    3037              : 
    3038        96999 :     call timab(tim_ymax,1,tsec)
    3039              : 
    3040        96999 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS) then
    3041            0 :       ABI_ERROR('Not implemented for GPU Kokkos')
    3042              :     end if
    3043        96999 :     call xgBlock_check_gpu_option(xgBlockA,da)
    3044              : 
    3045        96999 :     nrows = xgBlockA%rows
    3046        96999 :     ncols = xgBlockA%cols
    3047              : 
    3048        96999 :     if ( da%rows /= nblocks*ncols ) then
    3049            0 :       ABI_ERROR("rows(da)/=nblocks*ncols")
    3050              :     end if
    3051        96999 :     if ( shift<0 ) then
    3052            0 :       ABI_ERROR("shift<0")
    3053              :     end if
    3054        96999 :     if ( shift+ncols > da%rows ) then
    3055            0 :       ABI_ERROR("shift+xgBlockA%cols > da%rows")
    3056              :     end if
    3057              : 
    3058        96999 :     fact = 1 ; if (xgBlockA%space==SPACE_CR) fact = 2
    3059              : 
    3060        96999 :     if (xgBlockA%gpu_option==ABI_GPU_DISABLED) then
    3061              : 
    3062        96999 :         if (space(da)==SPACE_R) then
    3063              :             select case(xgBlockA%space)
    3064              :             case (SPACE_R,SPACE_CR)
    3065              :                 !$omp parallel do collapse(2) shared(da,xgBlockA) private(irow,iblock)
    3066       104707 :                 do iblock = 1, ncols
    3067      1520227 :                     do irow = 1, fact*nrows
    3068      1483840 :                         xgBlockA%vecR(irow,iblock) = - da%vecR(iblock+shift,1) * xgBlockA%vecR(irow,iblock)
    3069              :                     end do
    3070              :                 end do
    3071              :                 !$omp end parallel do
    3072              :             case (SPACE_C)
    3073              :                 !$omp parallel do collapse(2) shared(da,xgBlockA) private(irow,iblock)
    3074       301893 :                 do iblock = 1, ncols
    3075      4026656 :                     do irow = 1, nrows
    3076      3970414 :                         xgBlockA%vecC(irow,iblock) = - da%vecR(iblock+shift,1) * xgBlockA%vecC(irow,iblock)
    3077              :                     end do
    3078              :                 end do
    3079              :                 !$omp end parallel do
    3080              :             end select
    3081         4370 :         else if (space(da)==SPACE_C) then
    3082         4370 :             if (xgBlockA%space/=SPACE_C) then
    3083            0 :                 ABI_ERROR('If space(da)=SPACE_C, space(xgBlockA) has to be SPACE_C')
    3084              :             end if
    3085              :             !$omp parallel do collapse(2) shared(da,xgBlockA) private(irow,iblock)
    3086        22930 :             do iblock = 1, ncols
    3087      7402994 :                 do irow = 1, nrows
    3088      7398624 :                     xgBlockA%vecC(irow,iblock) = - da%vecC(iblock+shift,1) * xgBlockA%vecC(irow,iblock)
    3089              :                 end do
    3090              :             end do
    3091              :             !$omp end parallel do
    3092              :         else
    3093            0 :             ABI_ERROR('Only SPACE_R or SPACE_C (for da) are implemented.')
    3094              :         end if
    3095              : 
    3096              :     else if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    3097              : 
    3098              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3099              : 
    3100              :         if (space(da)==SPACE_R) then
    3101              :             select case(xgBlockA%space)
    3102              :             case (SPACE_R,SPACE_CR)
    3103              :                 xgBlockA__vecR => xgBlockA%vecR
    3104              :                 da__vecR => da%vecR
    3105              :                 !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    3106              :                 !$OMP& MAP(to:xgBlockA__vecR,da__vecR)
    3107              :                 do iblock = 1, ncols
    3108              :                     do irow = 1, fact*nrows
    3109              :                         xgBlockA__vecR(irow,iblock) = - da__vecR(iblock+shift,1) * xgBlockA__vecR(irow,iblock)
    3110              :                     end do
    3111              :                 end do
    3112              :             case (SPACE_C)
    3113              :                 xgBlockA__vecC => xgBlockA%vecC
    3114              :                 da__vecR => da%vecR
    3115              :                 !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    3116              :                 !$OMP& MAP(to:xgBlockA__vecC,da__vecR)
    3117              :                 do iblock = 1, ncols
    3118              :                     do irow = 1, nrows
    3119              :                         xgBlockA__vecC(irow,iblock) = - da__vecR(iblock+shift,1) * xgBlockA__vecC(irow,iblock)
    3120              :                     end do
    3121              :                 end do
    3122              :             end select
    3123              :         else if (space(da)==SPACE_C) then
    3124              :             if (xgBlockA%space/=SPACE_C) then
    3125              :                 ABI_ERROR('If space(da)=SPACE_C, space(xgBlockA) has to be SPACE_C')
    3126              :             end if
    3127              :             xgBlockA__vecC => xgBlockA%vecC
    3128              :             da__vecC => da%vecC
    3129              :             !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    3130              :             !$OMP& MAP(to:xgBlockA__vecC,da__vecC)
    3131              :             do iblock = 1, ncols
    3132              :                 do irow = 1, nrows
    3133              :                     xgBlockA__vecC(irow,iblock) = - da__vecC(iblock+shift,1) * xgBlockA__vecC(irow,iblock)
    3134              :                 end do
    3135              :             end do
    3136              :         else
    3137              :             ABI_ERROR('Only SPACE_R or SPACE_C (for da) are implemented.')
    3138              :         end if
    3139              : 
    3140              : #endif
    3141              : 
    3142              :     end if
    3143              : 
    3144        96999 :     call timab(tim_ymax,2,tsec)
    3145              : 
    3146        96999 :   end subroutine xgBlock_ymax
    3147              :   !!***
    3148              : 
    3149              :   !!****f* m_xg/xgBlock_colwiseCymax
    3150              :   !!
    3151              :   !! NAME
    3152              :   !! xgBlock_colwiseCymax
    3153              : 
    3154       705748 :   subroutine xgBlock_colwiseCymax(xgBlockA, da, xgBlockB, xgBlockW)
    3155              : 
    3156              :     type(xgBlock_t), intent(inout) :: xgBlockA
    3157              :     type(xgBlock_t), intent(in   ) :: da
    3158              :     type(xgBlock_t), intent(in   ) :: xgBlockB
    3159              :     type(xgBlock_t), intent(in   ) :: xgBlockW
    3160              : 
    3161              :     integer :: iblock,fact,rows,cols,jblock
    3162              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3163              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecC(:,:),xgBlockB__vecC(:,:),xgBlockW__vecC(:,:)
    3164              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecR(:,:),xgBlockB__vecR(:,:),xgBlockW__vecR(:,:),da__vecR(:,:)
    3165              : #endif
    3166              :     double precision :: tsec(2)
    3167              : 
    3168       705748 :     call timab(tim_colw_cymax,1,tsec)
    3169              : 
    3170       705748 :     if ( xgBlockA%space /= xgBlockB%space .or. xgBlockA%space /= xgBlockW%space ) then
    3171            0 :       ABI_ERROR("Must be same space for caxmy")
    3172              :     end if
    3173       705748 :     if ( xgBlockA%LDim /= xgBlockB%LDim .or. xgBlockA%LDim /= xgBlockW%LDim) then
    3174            0 :       ABI_ERROR("Must have same LDim for caxmy")
    3175              :     end if
    3176       705748 :     if ( xgBlockA%cols /= xgBlockB%cols .or. xgBlockA%cols /= xgBlockW%cols ) then
    3177            0 :       ABI_ERROR("Must have same cols for caxmy")
    3178              :     end if
    3179       705748 :     if ( da%rows /= xgBlockA%cols ) then
    3180            0 :       ABI_ERROR("Must have same cols for caxmy")
    3181              :     end if
    3182              : 
    3183       705748 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    3184       705748 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    3185       705748 :     call xgBlock_check_gpu_option(xgBlockA,da)
    3186              : 
    3187       705748 :     fact = 1 ; if (xgBlockA%space==SPACE_CR) fact = 2
    3188              : 
    3189       705748 :     rows = fact*xgBlockA%rows; cols = xgBlockA%cols
    3190              : 
    3191       705748 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS) then
    3192              : 
    3193              : #if defined HAVE_GPU && defined HAVE_KOKKOS
    3194              : 
    3195              :       select case(xgBlockA%space)
    3196              :       case (SPACE_R,SPACE_CR)
    3197              :         call compute_colwiseCymax_scalar(c_loc(xgBlockA%vecR), c_loc(da%vecR), c_loc(xgBlockB%vecR), &
    3198              :           &                              c_loc(xgBlockW%vecR), fact*xgBlockA%rows, xgBlockA%cols, fact*xgBlockA%ldim)
    3199              :       case (SPACE_C)
    3200              :         call compute_colwiseCymax_cplx  (c_loc(xgBlockA%vecC), c_loc(da%vecR), c_loc(xgBlockB%vecC), &
    3201              :           &                              c_loc(xgBlockW%vecC), xgBlockA%rows, xgBlockA%cols, xgBlockA%ldim)
    3202              :       end select
    3203              : 
    3204              : #endif
    3205              : 
    3206       705748 :     else if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    3207              : 
    3208              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3209              : 
    3210              :       select case(xgBlockA%space)
    3211              :       case (SPACE_R,SPACE_CR)
    3212              :         xgBlockA__vecR => xgBlockA%vecR
    3213              :         xgBlockB__vecR => xgBlockB%vecR
    3214              :         xgBlockW__vecR => xgBlockW%vecR
    3215              :         da__vecR => da%vecR
    3216              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    3217              :         !$OMP& MAP(to:xgBlockA__vecR,xgBlockB__vecR,xgBlockW__vecR,da__vecR)
    3218              :         do iblock = 1, cols
    3219              :           do jblock = 1, rows
    3220              :             xgBlockA__vecR(jblock,iblock) = - da__vecR(iblock,1) * xgBlockB__vecR(jblock,iblock) &
    3221              :                 + xgBlockW__vecR(jblock,iblock)
    3222              :           end do
    3223              :         end do
    3224              :       case (SPACE_C)
    3225              :         xgBlockA__vecC => xgBlockA%vecC
    3226              :         xgBlockB__vecC => xgBlockB%vecC
    3227              :         xgBlockW__vecC => xgBlockW%vecC
    3228              :         da__vecR => da%vecR
    3229              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) &
    3230              :         !$OMP& MAP(to:xgBlockA__vecC,xgBlockB__vecC,xgBlockW__vecC,da__vecR)
    3231              :         do iblock = 1, cols
    3232              :           do jblock = 1, rows
    3233              :             xgBlockA__vecC(jblock,iblock) = - da__vecR(iblock,1) * xgBlockB__vecC(jblock,iblock) &
    3234              :                 + xgBlockW__vecC(jblock,iblock)
    3235              :           end do
    3236              :         end do
    3237              :       end select
    3238              : 
    3239              : #endif
    3240              : 
    3241              :     else
    3242              : 
    3243              :       select case(xgBlockA%space)
    3244              :       case (SPACE_R,SPACE_CR)
    3245              :         !$omp parallel do collapse(2) shared(da,xgBlockB,xgBlockW,xgBlockA) private(iblock,jblock)
    3246       570925 :         do iblock = 1, cols
    3247    283069893 :           do jblock = 1, rows
    3248    283011874 :             xgBlockA%vecR(jblock,iblock) = - da%vecR(iblock,1) * xgBlockB%vecR(jblock,iblock) + xgBlockW%vecR(jblock,iblock)
    3249              :           end do
    3250              :         end do
    3251              :         !$omp end parallel do
    3252              :       case (SPACE_C)
    3253              :         !$omp parallel do collapse(2) shared(da,xgBlockB,xgBlockW,xgBlockA) private(iblock,jblock)
    3254      2738231 :         do iblock = 1, cols
    3255    201864931 :           do jblock = 1, rows
    3256    201217202 :             xgBlockA%vecC(jblock,iblock) = - da%vecR(iblock,1) * xgBlockB%vecC(jblock,iblock) + xgBlockW%vecC(jblock,iblock)
    3257              :           end do
    3258              :         end do
    3259              :         !$omp end parallel do
    3260              :       end select
    3261              : 
    3262              :     end if
    3263              : 
    3264       705748 :     call timab(tim_colw_cymax,2,tsec)
    3265              : 
    3266       705748 :   end subroutine xgBlock_colwiseCymax
    3267              :   !!***
    3268              : 
    3269              : !!****f* m_xg/xgBlock_yxmax
    3270              : !!
    3271              : !! NAME
    3272              : !! xgBlock_yxmax
    3273              : 
    3274        90464 :   subroutine xgBlock_yxmax(xgBlockA, da, xgBlockB)
    3275              : 
    3276              :     type(xgBlock_t), intent(inout) :: xgBlockA
    3277              :     type(xgBlock_t), intent(in   ) :: da
    3278              :     type(xgBlock_t), intent(in   ) :: xgBlockB
    3279              : 
    3280              :     integer :: iblock,irow,cols,rows,fact
    3281              :     double precision :: tsec(2)
    3282              : 
    3283        90464 :     call timab(tim_yxmax,1,tsec)
    3284              : 
    3285        90464 :     if (xgBlockA%gpu_option/=ABI_GPU_DISABLED) then
    3286            0 :       ABI_ERROR('Not implemented for GPU')
    3287              :     end if
    3288        90464 :     call xgBlock_check_gpu_option(xgBlockA,da)
    3289        90464 :     call xgBlock_check_gpu_option(xgBlockA,da)
    3290              : 
    3291        90464 :     if ( xgBlockA%space /= xgBlockB%space ) then
    3292            0 :       ABI_ERROR("Must be same space for ymax")
    3293              :     end if
    3294        90464 :     if ( xgBlockA%rows /= xgBlockB%rows ) then
    3295            0 :       ABI_ERROR("Must have same rows for ymax")
    3296              :     end if
    3297        90464 :     if ( xgBlockA%cols /= xgBlockB%cols ) then
    3298            0 :       ABI_ERROR("Must have same cols for ymax")
    3299              :     end if
    3300        90464 :     if ( da%rows /= xgBlockA%cols ) then
    3301            0 :       ABI_ERROR("Must have same cols for ymax")
    3302              :     end if
    3303              : 
    3304        90464 :     cols = xgBlockA%cols
    3305        90464 :     rows = xgBlockA%rows
    3306        90464 :     fact = 1 ; if (xgBlockA%space==SPACE_CR) fact = 2
    3307              : 
    3308              :     select case(xgBlockA%space)
    3309              :     case (SPACE_R,SPACE_CR)
    3310              :       !$omp parallel do collapse(2) shared(da,xgBlockB,xgBlockA) private(iblock,irow)
    3311       263955 :       do iblock = 1, cols
    3312     12989715 :         do irow = 1, fact*rows
    3313     12947298 :           xgBlockA%vecR(irow,iblock) = xgBlockA%vecR(irow,iblock) - da%vecR(iblock,1) * xgBlockB%vecR(irow,iblock)
    3314              :         end do
    3315              :       end do
    3316              :       !$omp end parallel do
    3317              :     case (SPACE_C)
    3318              :       !$omp parallel do collapse(2) shared(da,xgBlockB,xgBlockA) private(iblock,irow)
    3319       363771 :       do iblock = 1, cols
    3320     30600575 :         do irow = 1, rows
    3321     30552528 :           xgBlockA%vecC(irow,iblock) = xgBlockA%vecC(irow,iblock) - da%vecR(iblock,1) * xgBlockB%vecC(irow,iblock)
    3322              :         end do
    3323              :       end do
    3324              :       !$omp end parallel do
    3325              :     end select
    3326              : 
    3327        90464 :     call timab(tim_yxmax,2,tsec)
    3328              : 
    3329        90464 :   end subroutine xgBlock_yxmax
    3330              : !!***
    3331              : 
    3332              :   !!****f* m_xg/xgBlock_apply_diag
    3333              :   !!
    3334              :   !! NAME
    3335              :   !! xgBlock_apply_diag
    3336              : 
    3337       917767 :   subroutine xgBlock_apply_diag(X, diag, nspinor, Y)
    3338              : 
    3339              :     type(xgBlock_t) , intent(inout) :: X
    3340              :     type(xgBlock_t) , intent(in)    :: diag
    3341              :     integer,          intent(in)    :: nspinor
    3342              :     type(xgBlock_t) , optional, intent(inout) :: Y
    3343              : 
    3344              :     type(xgBlock_t) :: X_spinor, Y_spinor
    3345       917767 :     real(dp)    , pointer :: array(:)
    3346       917767 :     complex(dp), pointer :: arrayc(:)
    3347              :     double precision :: tsec(2)
    3348              : 
    3349       917767 :     call timab(tim_apply_diag,1,tsec)
    3350              : 
    3351       917767 :     if (X%rows/=nspinor*diag%rows) then
    3352            0 :       ABI_ERROR('xgBlock%rows/=nspinor*xgBlock_diag%rows')
    3353              :     end if
    3354       917767 :     if (diag%cols/=1) then
    3355            0 :       ABI_ERROR('diag should have one column')
    3356              :     end if
    3357       917767 :     if (diag%space/=SPACE_R.and.diag%space/=SPACE_C) then
    3358            0 :       ABI_ERROR('space(diag) should be SPACE_C or SPACE_R')
    3359              :     end if
    3360       917767 :     if (X%space==SPACE_R) then
    3361       122043 :       if (diag%space/=SPACE_R) then
    3362            0 :         ABI_ERROR('If space(X)==SPACE_R, space(diag) should be SPACE_R')
    3363              :       end if
    3364              :     end if
    3365              : 
    3366       917767 :     if (present(Y)) then
    3367       144043 :       call xgBlock_check(Y,X)
    3368       144043 :       call xgBlock_copy(X,Y)
    3369       144043 :       call xgBlock_reshape_spinor(Y,Y_spinor,nspinor,ROWS2COLS)
    3370              :     else
    3371       773724 :       call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
    3372       773724 :       Y_spinor = X_spinor
    3373              :     end if
    3374              : 
    3375       917767 :     if (space(diag)==SPACE_R) then
    3376       917767 :       call xgBlock_reverseMap_1dR(diag,array,array_dim=diag%rows)
    3377       917767 :       call xgBlock_colwiseMulR(Y_spinor,array)
    3378            0 :     else if (space(diag)==SPACE_C) then
    3379            0 :       call xgBlock_reverseMap_1dC(diag,arrayc,array_dim=diag%rows)
    3380            0 :       call xgBlock_colwiseMulC(Y_spinor,arrayc)
    3381              :     end if
    3382              : 
    3383       917767 :     call timab(tim_apply_diag,2,tsec)
    3384              : 
    3385       917767 :   end subroutine xgBlock_apply_diag
    3386              :   !!***
    3387              : 
    3388              : !****f* m_xg/xgBlock_add_diag
    3389              : !
    3390              : ! NAME
    3391              : ! xgBlock_add_diag
    3392              : 
    3393       204650 :   subroutine xgBlock_add_diag(X, diag, nspinor, Y)
    3394              : 
    3395              :     type(xgBlock_t) , intent(in)    :: X
    3396              :     type(xgBlock_t) , intent(in)    :: diag
    3397              :     integer,          intent(in)    :: nspinor
    3398              :     type(xgBlock_t) , intent(inout) :: Y
    3399              : 
    3400              :     integer :: iblock,irow,rows,cols
    3401              :     type(xgBlock_t) :: X_spinor, Y_spinor
    3402              :     double precision :: tsec(2)
    3403              : 
    3404       204650 :     call timab(tim_add_diag,1,tsec)
    3405              : 
    3406       204650 :     if (X%gpu_option/=ABI_GPU_DISABLED) then
    3407            0 :       ABI_ERROR('Not implemented for GPU')
    3408              :     end if
    3409       204650 :     call xgBlock_check_gpu_option(X,diag)
    3410       204650 :     call xgBlock_check_gpu_option(X,Y)
    3411              : 
    3412       204650 :     if (X%rows/=nspinor*diag%rows) then
    3413            0 :       ABI_ERROR('xgBlock%rows/=nspinor*xgBlock_diag%rows')
    3414              :     end if
    3415       204650 :     if (diag%cols/=1) then
    3416            0 :       ABI_ERROR('xgBlock_diag should have one column')
    3417              :     end if
    3418       204650 :     if (diag%space==SPACE_CR) then
    3419            0 :       ABI_ERROR('space(diag) should be SPACE_C or SPACE_R')
    3420              :     end if
    3421       204650 :     if (X%space==SPACE_R) then
    3422            0 :       if (diag%space/=SPACE_R) then
    3423            0 :         ABI_ERROR('If space(X)==SPACE_R, space(diag) should be SPACE_R')
    3424              :       end if
    3425              :     end if
    3426              : 
    3427       204650 :     call xgBlock_check(Y,X)
    3428              : 
    3429       204650 :     call xgBlock_reshape_spinor(X,X_spinor,nspinor,ROWS2COLS)
    3430       204650 :     call xgBlock_reshape_spinor(Y,Y_spinor,nspinor,ROWS2COLS)
    3431              : 
    3432       204650 :     rows = X_spinor%rows
    3433       204650 :     cols = X_spinor%cols
    3434              : 
    3435       204650 :     select case(X%space)
    3436              :     case (SPACE_R)
    3437              :       !$omp parallel do collapse(2) shared(X_spinor,Y_spinor,diag) private(iblock,irow)
    3438            0 :       do iblock = 1, cols
    3439            0 :         do irow=1,rows
    3440              :           Y_spinor%vecR(irow,iblock) = Y_spinor%vecR(irow,iblock) &
    3441            0 :             & + X_spinor%vecR(irow,iblock) * diag%vecR(irow,1)
    3442              :         end do
    3443              :       end do
    3444              :     case (SPACE_CR)
    3445        91520 :       if (diag%space==SPACE_R) then
    3446              :         !$omp parallel do collapse(2) shared(X_spinor,Y_spinor,diag) private(iblock,irow)
    3447       491850 :         do iblock = 1, cols
    3448     24392946 :           do irow=1,rows
    3449              :             Y_spinor%vecR(2*irow-1,iblock) = Y_spinor%vecR(2*irow-1,iblock) &
    3450     23901096 :               & + X_spinor%vecR(2*irow-1,iblock) * diag%vecR(irow,1)
    3451              :             Y_spinor%vecR(2*irow  ,iblock) = Y_spinor%vecR(2*irow  ,iblock) &
    3452     24301426 :               & + X_spinor%vecR(2*irow  ,iblock) * diag%vecR(irow,1)
    3453              :           end do
    3454              :         end do
    3455              :       else
    3456            0 :         ABI_ERROR('Not implemented')
    3457              :       end if
    3458              :     case (SPACE_C)
    3459       204650 :       if (diag%space==SPACE_C) then
    3460              :         !$omp parallel do collapse(2) shared(X_spinor,Y_spinor,diag) private(iblock,irow)
    3461            0 :         do iblock = 1, cols
    3462            0 :           do irow=1,rows
    3463              :             Y_spinor%vecC(irow,iblock) = Y_spinor%vecC(irow,iblock) &
    3464            0 :               & + X_spinor%vecC(irow,iblock) * diag%vecC(irow,1)
    3465              :           end do
    3466              :         end do
    3467       113130 :       else if (diag%space==SPACE_R) then
    3468              :         !$omp parallel do collapse(2) shared(X_spinor,Y_spinor,diag) private(iblock,irow)
    3469       888922 :         do iblock = 1, cols
    3470    100807590 :           do irow=1,rows
    3471              :             Y_spinor%vecC(irow,iblock) = Y_spinor%vecC(irow,iblock) &
    3472    100694460 :               & + X_spinor%vecC(irow,iblock) * diag%vecR(irow,1)
    3473              :           end do
    3474              :         end do
    3475              :       else
    3476            0 :         ABI_ERROR('Not implemented')
    3477              :       end if
    3478              :     end select
    3479              : 
    3480       204650 :     call timab(tim_add_diag,2,tsec)
    3481              : 
    3482       204650 :   end subroutine xgBlock_add_diag
    3483              : !!***
    3484              : 
    3485              :   !!****f* m_xg/xgBlock_mpi_sum
    3486              :   !!
    3487              :   !! NAME
    3488              :   !! xgBlock_mpi_sum
    3489              : 
    3490      5771418 :   subroutine xgBlock_mpi_sum(xgBlock,comm)
    3491              : 
    3492              :     type(xgBlock_t) , intent(inout) :: xgBlock
    3493              :     integer,intent(in),optional :: comm
    3494              : 
    3495              :     integer :: ierr,comm_
    3496              : 
    3497      5771418 :     if (.not.present(comm)) then
    3498            0 :       comm_ = xgBlock%spacedim_comm
    3499              :     else
    3500      5771418 :       comm_ = comm
    3501              :     end if
    3502              : 
    3503      5771418 :     if ( xmpi_comm_size(comm_) > 1) then
    3504      5249270 :       if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    3505              :         ! CPU waits for GPU to finish before doing MPI communications
    3506            0 :         call gpu_device_synchronize()
    3507              :       end if
    3508              : 
    3509      6090714 :       select case(xgBlock%space)
    3510              : 
    3511              :         case (SPACE_R,SPACE_CR)
    3512       841444 :           call xmpi_sum(xgBlock%vecR,comm_,ierr,use_omp_map=(xgBlock%gpu_option==ABI_GPU_OPENMP))
    3513              :         case (SPACE_C)
    3514      5249270 :           call xmpi_sum(xgBlock%vecC,comm_,ierr,use_omp_map=(xgBlock%gpu_option==ABI_GPU_OPENMP))
    3515              :       end select
    3516              :     end if ! xmpi_comm_size>1
    3517              : 
    3518      5771418 :   end subroutine xgBlock_mpi_sum
    3519              :   !!***
    3520              : 
    3521              :   !!****f* m_xg/xgBlock_mpi_send
    3522              :   !!
    3523              :   !! NAME
    3524              :   !! xgBlock_mpi_send
    3525              : 
    3526            0 :   subroutine xgBlock_mpi_send(xgBlock,dest,tag,comm)
    3527              : 
    3528              :     type(xgBlock_t) , intent(in) :: xgBlock
    3529              :     integer,intent(in) :: dest,tag
    3530              :     integer,intent(in),optional :: comm
    3531              : 
    3532              :     integer :: ierr,comm_
    3533            0 :     real(dp), pointer :: vec(:,:)
    3534              : 
    3535            0 :     if (xgBlock%gpu_option/=ABI_GPU_DISABLED) then
    3536            0 :       ABI_ERROR('Not implemented for GPU')
    3537              :     end if
    3538              : 
    3539            0 :     if (.not.present(comm)) then
    3540            0 :       comm_ = xgBlock%spacedim_comm
    3541              :     else
    3542            0 :       comm_ = comm
    3543              :     end if
    3544              : 
    3545            0 :     call xgBlock_reverseMap(xgBlock,vec)
    3546            0 :     call xmpi_send(vec,dest,tag,comm_,ierr)
    3547              : 
    3548            0 :   end subroutine xgBlock_mpi_send
    3549              :   !!***
    3550              : 
    3551              :   !!****f* m_xg/xgBlock_mpi_isend
    3552              :   !!
    3553              :   !! NAME
    3554              :   !! xgBlock_mpi_isend
    3555              : 
    3556      3135276 :   subroutine xgBlock_mpi_isend(xgBlock,dest,tag,request,comm)
    3557              : 
    3558              :     type(xgBlock_t) , intent(in) :: xgBlock
    3559              :     integer,intent(in) :: dest,tag
    3560              :     integer,intent(inout) :: request
    3561              :     integer,intent(in),optional :: comm
    3562              : 
    3563              :     integer :: ierr,comm_
    3564      1567638 :     real(dp), pointer :: vec(:,:)
    3565              : 
    3566      1567638 :     if (xgBlock%gpu_option/=ABI_GPU_DISABLED) then
    3567            0 :       ABI_ERROR('Not implemented for GPU')
    3568              :     end if
    3569              : 
    3570      1567638 :     if (.not.present(comm)) then
    3571       950822 :       comm_ = xgBlock%spacedim_comm
    3572              :     else
    3573       616816 :       comm_ = comm
    3574              :     end if
    3575              : 
    3576      1567638 :     call xgBlock_reverseMap(xgBlock,vec)
    3577      1567638 :     call xmpi_isend(vec,dest,tag,comm_,request,ierr)
    3578              : 
    3579      1567638 :   end subroutine xgBlock_mpi_isend
    3580              :   !!***
    3581              : 
    3582              :   !!****f* m_xg/xgBlock_mpi_recv
    3583              :   !!
    3584              :   !! NAME
    3585              :   !! xgBlock_mpi_recv
    3586              : 
    3587      3135276 :   subroutine xgBlock_mpi_recv(xgBlock,source,tag,comm)
    3588              : 
    3589              :     type(xgBlock_t) , intent(inout) :: xgBlock
    3590              :     integer,intent(in) :: source,tag
    3591              :     integer,intent(in),optional :: comm
    3592              : 
    3593              :     integer :: ierr,comm_
    3594      1567638 :     real(dp), pointer :: vec(:,:)
    3595              : 
    3596      1567638 :     if (xgBlock%gpu_option/=ABI_GPU_DISABLED) then
    3597            0 :       ABI_ERROR('Not implemented for GPU')
    3598              :     end if
    3599              : 
    3600      1567638 :     if (.not.present(comm)) then
    3601       950822 :       comm_ = xgBlock%spacedim_comm
    3602              :     else
    3603       616816 :       comm_ = comm
    3604              :     end if
    3605              : 
    3606      1567638 :     call xgBlock_reverseMap(xgBlock,vec)
    3607      1567638 :     call xmpi_recv(vec,source,tag,comm_,ierr)
    3608              : 
    3609      1567638 :   end subroutine xgBlock_mpi_recv
    3610              :   !!***
    3611              : 
    3612              :   !!****f* m_xg/xgBlock_gemm_mpi_cyclic_permutation
    3613              :   !!
    3614              :   !! NAME
    3615              :   !! xgBlock_gemm_mpi_cyclic_permutation
    3616              : 
    3617       214911 :   subroutine xgBlock_gemm_mpi_cyclic_permutation(xgBlockA,xgBlockB,xgBlockW,me_comm,blocksize,comm)
    3618              : 
    3619              :     type(xgBlock_t) , intent(in)    :: xgBlockA,xgBlockB
    3620              :     type(xgBlock_t) , intent(inout) :: xgBlockW
    3621              :     integer,intent(in) :: me_comm
    3622              :     integer,intent(in),optional :: blocksize,comm
    3623              : 
    3624              :     logical :: multiblock
    3625              :     integer :: ierr,blocksize_,comm_,source,dest,tag,request
    3626              :     integer :: iblock_left,iblock_right,iblock_mpi,nblocks_mpi,nblocks_left,nblocks_right
    3627              :     integer :: shift_col,shift_row,shift_col_mpi,shift_row_mpi
    3628              :     double precision :: tsec(2)
    3629              :     type(xg_t) :: xg_mpi_work
    3630              :     type(xg_t) :: subB,subB_mpi
    3631              : 
    3632       214911 :     call timab(tim_gemmcyclic,1,tsec)
    3633              : 
    3634       214911 :     if (xgBlockA%gpu_option/=ABI_GPU_DISABLED) then
    3635            0 :       ABI_ERROR('Not implemented for GPU')
    3636              :     end if
    3637       214911 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    3638       214911 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    3639              : 
    3640       214911 :     if (.not.present(comm)) then
    3641            0 :       comm_ = xgBlockA%spacedim_comm
    3642              :     else
    3643       214911 :       comm_ = comm
    3644              :     end if
    3645              : 
    3646       214911 :     nblocks_mpi = xmpi_comm_size(comm_)
    3647              : 
    3648       214911 :     if (xgBlockA%rows/=xgBlockW%rows) then
    3649            0 :       ABI_ERROR('rows(xgBlockA)/=rows(xgBlockW)')
    3650              :     end if
    3651       214911 :     if (xgBlockB%rows/=nblocks_mpi*xgBlockA%cols) then
    3652            0 :       ABI_ERROR('rows(xgBlockB)/=nblocks_mpi*cols(xgBlockA)')
    3653              :     end if
    3654       214911 :     if (xgBlockB%cols/=nblocks_mpi*xgBlockW%cols) then
    3655            0 :       ABI_ERROR('cols(xgBlockB)/=nblocks_mpi*cols(xgBlockW)')
    3656              :     end if
    3657              : 
    3658       214911 :     blocksize_ = xgBlockA%cols
    3659       214911 :     if (present(blocksize)) then
    3660       214911 :       if (mod(xgBlockA%cols,blocksize)/=0) then
    3661            0 :         ABI_ERROR('invalid blocksize')
    3662              :       end if
    3663       214911 :       if (mod(xgBlockB%cols/nblocks_mpi,blocksize)/=0) then
    3664            0 :         ABI_ERROR('invalid blocksize')
    3665              :       end if
    3666       214911 :       blocksize_ = blocksize
    3667              :     end if
    3668              : 
    3669       214911 :     if (nblocks_mpi==1) then
    3670              : 
    3671              :       ! If only one mpi process, use timing from gemm routine
    3672        35023 :       call timab(tim_gemmcyclic,2,tsec)
    3673        35023 :       call xgBlock_gemm('n','n',1.0d0,xgBlockA,xgBlockB,1.d0,xgBlockW)
    3674        35023 :       call timab(tim_gemmcyclic,1,tsec)
    3675              : 
    3676              :     else
    3677              : 
    3678       179888 :       nblocks_left  = xgBlockA%cols / blocksize_
    3679       179888 :       nblocks_right = xgBlockB%cols / (blocksize_*nblocks_mpi)
    3680       179888 :       multiblock = .false.
    3681       179888 :       if (nblocks_left>1.or.nblocks_right>1) then
    3682        78170 :         multiblock = .true.
    3683              :       end if
    3684              : 
    3685       179888 :       call xg_init(xg_mpi_work,xgBlockA%space,xgBlockA%rows,xgBlockA%cols,xmpi_comm_null)
    3686       179888 :       call xg_init(subB_mpi,xgBlockB%space,xgBlockB%rows/nblocks_mpi,xgBlockB%cols/nblocks_mpi,xmpi_comm_null)
    3687       179888 :       if (multiblock) then
    3688        78170 :         call xg_init(subB,xgBlockB%space,blocksize_,blocksize_,xmpi_comm_null)
    3689              :       end if
    3690              : 
    3691       865616 :       do iblock_mpi=1,nblocks_mpi
    3692              : 
    3693       685728 :         shift_row_mpi = mod((iblock_mpi-1)+me_comm,nblocks_mpi) * blocksize_
    3694       685728 :         shift_col_mpi = me_comm * blocksize_
    3695       685728 :         if (.not.multiblock) then
    3696       387420 :           call xgBlock_partialcopy(xgBlockB,subB_mpi%self,shift_row_mpi,shift_col_mpi,BIG2SMALL)
    3697              :         else
    3698       857388 :           do iblock_right=1,nblocks_right
    3699      2387556 :             do iblock_left=1,nblocks_left
    3700      1530168 :               shift_row = shift_row_mpi + (iblock_left-1) * blocksize_*nblocks_mpi
    3701      1530168 :               shift_col = shift_col_mpi + (iblock_right-1) * blocksize_*nblocks_mpi
    3702      1530168 :               call xgBlock_partialcopy(xgBlockB,subB%self,shift_row,shift_col,BIG2SMALL)
    3703      1530168 :               shift_row = (iblock_left-1) * blocksize_
    3704      1530168 :               shift_col = (iblock_right-1) * blocksize_
    3705      2089248 :               call xgBlock_partialcopy(subB%self,subB_mpi%self,shift_row,shift_col,SMALL2BIG)
    3706              :             end do
    3707              :           end do
    3708              :         end if
    3709              : 
    3710       685728 :         if (iblock_mpi==1) then
    3711       179888 :           call xgBlock_gemm('n','n',1.0d0,xgBlockA,subB_mpi%self,1.d0,xgBlockW,timing=.false.)
    3712              :         else
    3713       505840 :           tag = iblock_mpi
    3714       505840 :           dest = mod(me_comm-(iblock_mpi-1),nblocks_mpi)
    3715       505840 :           if (dest<0) dest=dest+nblocks_mpi
    3716       505840 :           call xgBlock_mpi_isend(xgBlockA,dest,tag,request,comm=comm_)
    3717       505840 :           source = mod(me_comm+(iblock_mpi-1),nblocks_mpi)
    3718       505840 :           call xgBlock_mpi_recv(xg_mpi_work%self,source,tag,comm=comm_)
    3719       505840 :           call xgBlock_gemm('n','n',1.0d0,xg_mpi_work%self,subB_mpi%self,1.d0,xgBlockW,timing=.false.)
    3720              :         end if
    3721              : 
    3722       865616 :         if (iblock_mpi>1) call xmpi_wait(request,ierr)
    3723              : 
    3724              :       end do
    3725              : 
    3726       179888 :       call xg_free(xg_mpi_work)
    3727       179888 :       call xg_free(subB_mpi)
    3728       179888 :       if (multiblock) then
    3729        78170 :         call xg_free(subB)
    3730              :       end if
    3731              : 
    3732              :     end if
    3733              : 
    3734       214911 :     call timab(tim_gemmcyclic,2,tsec)
    3735              : 
    3736       214911 :   end subroutine xgBlock_gemm_mpi_cyclic_permutation
    3737              :   !!***
    3738              : 
    3739              :   !!****f* m_xg/xgBlock_colwiseMulR
    3740              :   !!
    3741              :   !! NAME
    3742              :   !! xgBlock_colwiseMulR
    3743              : 
    3744       917767 :   subroutine xgBlock_colwiseMulR(xgBlock, vec)
    3745              : 
    3746              :     type(xgBlock_t) , intent(inout)           :: xgBlock
    3747              :     double precision, intent(in   ), target   :: vec(:)
    3748              : 
    3749              :     integer :: rows
    3750              :     integer :: iblock,irow
    3751              : 
    3752              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3753              :     integer :: cols
    3754              :     logical :: map_vec
    3755              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    3756              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:)
    3757              : #endif
    3758              :     double precision :: tsec(2)
    3759              : 
    3760       917767 :     call timab(tim_colw_mul,1,tsec)
    3761              : 
    3762       917767 :     rows = size(vec,dim=1)
    3763              : 
    3764       917767 :     if (xgBlock%rows/=rows) then
    3765            0 :       ABI_ERROR('dim(vec)/=xgBlock%rows')
    3766              :     end if
    3767              : 
    3768       917767 :     if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    3769              : 
    3770              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS) && defined(HAVE_YAKL)
    3771              : 
    3772              :       select case(xgBlock%space)
    3773              :       case (SPACE_R)
    3774              :         call compute_colwiseMul_scalar_scalar(c_loc(xgBlock%vecR), c_loc(vec), &
    3775              :           &                                   0, xgBlock%rows, xgBlock%cols, &
    3776              :           &                                   xgBlock%ldim, rows)
    3777              :       case (SPACE_CR)
    3778              :          ABI_ERROR('Not implemented')
    3779              :       case (SPACE_C)
    3780              :         call compute_colwiseMul_cplx_scalar(c_loc(xgBlock%vecC), c_loc(vec), &
    3781              :           &                                 0, xgBlock%rows, xgBlock%cols, &
    3782              :           &                                 xgBlock%ldim, rows)
    3783              :       end select
    3784              : 
    3785              : #endif
    3786              : 
    3787       917767 :     else if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    3788              : 
    3789              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3790              : 
    3791              :       map_vec=.not. xomp_target_is_present(c_loc(vec))
    3792              :       !$OMP TARGET ENTER DATA MAP(to:vec) IF(map_vec)
    3793              :       cols=xgBlock%cols
    3794              :       select case(xgBlock%space)
    3795              :       case (SPACE_R)
    3796              :         xgBlock__vecR => xgBlock%vecR
    3797              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlock__vecR) MAP(to:vec) PRIVATE(iblock,irow)
    3798              :         do iblock = 1, cols
    3799              :           do irow = 1, rows
    3800              :             xgBlock__vecR(irow,iblock) = xgBlock__vecR(irow,iblock) * vec(irow)
    3801              :           end do
    3802              :         end do
    3803              :       case (SPACE_CR)
    3804              :         xgBlock__vecR => xgBlock%vecR
    3805              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlock__vecR) MAP(to:vec) PRIVATE(iblock,irow)
    3806              :         do iblock = 1, cols
    3807              :           do irow = 1, rows
    3808              :             xgBlock__vecR(2*irow-1,iblock) = xgBlock__vecR(2*irow-1,iblock) * vec(irow)
    3809              :             xgBlock__vecR(2*irow  ,iblock) = xgBlock__vecR(2*irow  ,iblock) * vec(irow)
    3810              :           end do
    3811              :         end do
    3812              :       case (SPACE_C)
    3813              :         xgBlock__vecC => xgBlock%vecC
    3814              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlock__vecC) MAP(to:vec) PRIVATE(iblock,irow)
    3815              :         do iblock = 1, cols
    3816              :           do irow = 1, rows
    3817              :             xgBlock__vecC(irow,iblock) = xgBlock__vecC(irow,iblock) * vec(irow)
    3818              :           end do
    3819              :         end do
    3820              :       end select
    3821              :       !$OMP TARGET EXIT DATA MAP(delete:vec) IF(map_vec)
    3822              : #endif
    3823              : 
    3824              :     else
    3825              : 
    3826      1039810 :       select case(xgBlock%space)
    3827              :       case (SPACE_R)
    3828              :         !$omp parallel do collapse(2) shared(xgBlock,vec) private(iblock,irow)
    3829       427750 :         do iblock = 1, xgBlock%cols
    3830      9972634 :           do irow = 1, rows
    3831      9850591 :             xgBlock%vecR(irow,iblock) = xgBlock%vecR(irow,iblock) * vec(irow)
    3832              :           end do
    3833              :         end do
    3834              :       case (SPACE_CR)
    3835              :         !$omp parallel do collapse(2) shared(xgBlock,vec) private(iblock,irow)
    3836       694528 :         do iblock = 1, xgBlock%cols
    3837    144975980 :           do irow = 1, rows
    3838    144281452 :             xgBlock%vecR(2*irow-1,iblock) = xgBlock%vecR(2*irow-1,iblock) * vec(irow)
    3839    144885336 :             xgBlock%vecR(2*irow  ,iblock) = xgBlock%vecR(2*irow  ,iblock) * vec(irow)
    3840              :           end do
    3841              :         end do
    3842              :       case (SPACE_C)
    3843              :         !$omp parallel do collapse(2) shared(xgBlock,vec) private(iblock,irow)
    3844      2726033 :         do iblock = 1, xgBlock%cols
    3845    221157902 :           do irow = 1, rows
    3846    220452822 :             xgBlock%vecC(irow,iblock) = xgBlock%vecC(irow,iblock) * vec(irow)
    3847              :           end do
    3848              :         end do
    3849              :       end select
    3850              : 
    3851              :     end if
    3852              : 
    3853       917767 :     call timab(tim_colw_mul,2,tsec)
    3854              : 
    3855       917767 :   end subroutine xgBlock_colwiseMulR
    3856              :   !!***
    3857              : 
    3858              :   !!****f* m_xg/xgBlock_colwiseMulC
    3859              :   !!
    3860              :   !! NAME
    3861              :   !! xgBlock_colwiseMulC
    3862              : 
    3863            0 :   subroutine xgBlock_colwiseMulC(xgBlock, vec)
    3864              : 
    3865              :     type(xgBlock_t), intent(inout)           :: xgBlock
    3866              :     complex(kind=8), intent(in   ), target   :: vec(:)
    3867              : 
    3868              :     integer :: rows
    3869              :     integer :: iblock,irow
    3870              : 
    3871              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3872              :     integer :: cols
    3873              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    3874              : #endif
    3875              :     double precision :: tsec(2)
    3876              : 
    3877            0 :     call timab(tim_colw_mul,1,tsec)
    3878              : 
    3879              :     ABI_UNUSED((/irow/)) ! Use in OpenMP GPU
    3880            0 :     rows = size(vec,dim=1)
    3881              : 
    3882            0 :     if (xgBlock%rows/=rows) then
    3883            0 :       ABI_ERROR('dim(vec)/=xgBlock%rows')
    3884              :     end if
    3885              : 
    3886            0 :     if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    3887              : 
    3888              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS) && defined(HAVE_YAKL)
    3889              : 
    3890              :       select case(xgBlock%space)
    3891              :       case (SPACE_R,SPACE_CR)
    3892              :         ABI_ERROR("Error colwiseMulC")
    3893              :       case (SPACE_C)
    3894              :         call compute_colwiseMul_cplx_cplx(c_loc(xgBlock%vecC), c_loc(vec), &
    3895              :           &                               0, xgBlock%rows, xgBlock%cols, &
    3896              :           &                               xgBlock%ldim, rows)
    3897              :       end select
    3898              : 
    3899              : #endif
    3900              : 
    3901            0 :     else if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    3902              : 
    3903              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    3904              : 
    3905              :       select case(xgBlock%space)
    3906              :       case (SPACE_R,SPACE_CR)
    3907              :         ABI_ERROR("Error colwiseMulC")
    3908              :       case (SPACE_C)
    3909              :         cols = xgBlock%cols
    3910              :         xgBlock__vecC => xgBlock%vecC
    3911              :         !$OMP TARGET ENTER DATA MAP(to:vec)
    3912              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlock__vecC) MAP(to:vec) PRIVATE(iblock,irow)
    3913              :         do iblock = 1, cols
    3914              :           do irow = 1, rows
    3915              :             xgBlock__vecC(irow,iblock) = xgBlock__vecC(irow,iblock) * vec(irow)
    3916              :           end do
    3917              :         end do
    3918              :       end select
    3919              :       !$OMP TARGET EXIT DATA MAP(delete:vec)
    3920              : 
    3921              : #endif
    3922              : 
    3923              :     else
    3924              : 
    3925            0 :       select case(xgBlock%space)
    3926              :       case (SPACE_R,SPACE_CR)
    3927            0 :         ABI_ERROR("Error colwiseMulC")
    3928              :       case (SPACE_C)
    3929              :         !$omp parallel do collapse(2) shared(xgBlock,vec) private(iblock,irow)
    3930            0 :         do iblock = 1, xgBlock%cols
    3931            0 :           do irow=1, rows
    3932            0 :             xgBlock%vecC(irow,iblock) = xgBlock%vecC(irow,iblock) * vec(irow)
    3933              :           end do
    3934              :         end do
    3935              :       end select
    3936              : 
    3937              :     end if
    3938              : 
    3939            0 :     call timab(tim_colw_mul,2,tsec)
    3940              : 
    3941            0 :   end subroutine xgBlock_colwiseMulC
    3942              :   !!***
    3943              : 
    3944              :   !!****f* m_xg/xgBlock_saxpyR
    3945              :   !!
    3946              :   !! NAME
    3947              :   !! xgBlock_saxpyR
    3948              : 
    3949      1086257 :   subroutine xgBlock_saxpyR(xgBlock1, da, xgBlock2)
    3950              : 
    3951              :     type(xgBlock_t),  intent(inout) :: xgBlock1
    3952              :     double precision, intent(in   ) :: da
    3953              :     type(xgBlock_t),  intent(in   ) :: xgBlock2
    3954              : 
    3955              :     integer :: fact
    3956              :     complex(dp) :: da_cplx
    3957              :     double precision :: tsec(2)
    3958              : 
    3959      1086257 :     call timab(tim_saxpy,1,tsec)
    3960              : 
    3961      1086257 :     da_cplx = dcmplx(da,0.0_dp)
    3962              : 
    3963      1086257 :     if ( xgBlock1%space /= xgBlock2%space ) then
    3964            0 :       ABI_ERROR("Must be same space for saxpy")
    3965              :     end if
    3966      1086257 :     if ( xgBlock1%LDim /= xgBlock2%LDim ) then
    3967            0 :       ABI_ERROR("Must have same LDim for saxpy")
    3968              :     end if
    3969      1086257 :     if ( xgBlock1%cols /= xgBlock2%cols ) then
    3970            0 :       ABI_ERROR("Must have same cols for saxpy")
    3971              :     end if
    3972              : 
    3973      1086257 :     call xgBlock_check_gpu_option(xgBlock1,xgBlock2)
    3974              : 
    3975      1086257 :     fact = 1 ; if (xgBlock1%space==SPACE_CR) fact = 2
    3976              : 
    3977       412274 :     select case(xgBlock1%space)
    3978              :     case (SPACE_R,SPACE_CR)
    3979              :       call abi_xaxpy(xgBlock1%cols*fact*xgBlock1%LDim, da_cplx, xgBlock2%vecR, 1, xgBlock1%vecR, 1, &
    3980       412274 :           x_cplx=1, gpu_option=xgBlock1%gpu_option)
    3981              :     case (SPACE_C)
    3982              :       call abi_xaxpy(xgBlock1%cols*xgBlock1%LDim, da_cplx, xgBlock2%vecC, 1, xgBlock1%vecC, 1, &
    3983      1086257 :           gpu_option=xgBlock1%gpu_option)
    3984              :     end select
    3985              : 
    3986      1086257 :     call timab(tim_saxpy,2,tsec)
    3987              : 
    3988      1086257 :   end subroutine xgBlock_saxpyR
    3989              :   !!***
    3990              : 
    3991              :   !!****f* m_xg/xgBlock_saxpyC
    3992              :   !!
    3993              :   !! NAME
    3994              :   !! xgBlock_saxpyC
    3995              : 
    3996            0 :   subroutine xgBlock_saxpyC(xgBlock1, da, xgBlock2)
    3997              : 
    3998              :     type(xgBlock_t), intent(inout) :: xgBlock1
    3999              :     double complex,  intent(in   ) :: da
    4000              :     type(xgBlock_t), intent(in   ) :: xgBlock2
    4001              : 
    4002              : #if defined HAVE_OPENMP_OFFLOAD && !defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
    4003              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock1__vecC(:,:),xgBlock2__vecC(:,:)
    4004              : #endif
    4005              :     double precision :: tsec(2)
    4006              : 
    4007            0 :     call timab(tim_saxpy,1,tsec)
    4008              : 
    4009            0 :     if ( xgBlock1%space /= xgBlock2%space ) then
    4010            0 :       ABI_ERROR("Must be same space for Saxpy")
    4011              :     end if
    4012            0 :     if ( xgBlock1%LDim /= xgBlock2%LDim ) then
    4013            0 :       ABI_ERROR("Must have same LDim for Saxpy")
    4014              :     end if
    4015            0 :     if ( xgBlock1%cols /= xgBlock2%cols ) then
    4016            0 :       ABI_ERROR("Must have same cols for Saxpy")
    4017              :     end if
    4018            0 :     if ( xgBlock1%space /= SPACE_C ) then
    4019            0 :       ABI_ERROR("Not correct space")
    4020              :     end if
    4021              : 
    4022            0 :     call xgBlock_check_gpu_option(xgBlock1,xgBlock2)
    4023              : 
    4024              :     call abi_xaxpy(xgBlock1%cols*xgBlock1%LDim, da, xgBlock2%vecC, 1, xgBlock1%vecC, 1, &
    4025            0 :         gpu_option=xgBlock1%gpu_option)
    4026              : 
    4027            0 :     call timab(tim_saxpy,2,tsec)
    4028              : 
    4029            0 :   end subroutine xgBlock_saxpyC
    4030              :   !!***
    4031              : 
    4032              :   !!****f* m_xg/xgBlock_dotC
    4033              :   !!
    4034              :   !! NAME
    4035              :   !! xgBlock_dotC
    4036              : 
    4037          198 :   subroutine xgBlock_dotC(xgBlock1, xgBlock2, xgBlock_out)
    4038              : 
    4039              :     type(xgBlock_t), intent(in  ) :: xgBlock1
    4040              :     type(xgBlock_t), intent(in  ) :: xgBlock2
    4041              :     type(xgBlock_t),  intent(inout ) :: xgBlock_out
    4042              :     double complex,external :: zdotc !conjugated dot product, not working on macos
    4043              : 
    4044              : #if defined HAVE_OPENMP_OFFLOAD && !defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
    4045              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock1__vecC(:,:),xgBlock2__vecC(:,:)
    4046              : #endif
    4047              :     double precision :: tsec(2)
    4048              : 
    4049          198 :     call timab(tim_dot,1,tsec)
    4050              : 
    4051          198 :     if ( xgBlock1%space /= xgBlock2%space ) then
    4052            0 :         ABI_ERROR("Must be same space for dot")
    4053              :     end if
    4054          198 :     if ( xgBlock1%LDim /= xgBlock2%LDim ) then
    4055            0 :         ABI_ERROR("Must have same LDim for dot")
    4056              :     end if
    4057          198 :     if ( xgBlock1%cols /= xgBlock2%cols ) then
    4058            0 :         ABI_ERROR("Must have same cols for dot")
    4059              :     end if
    4060          198 :     if ( xgBlock1%space /= SPACE_C .or. xgBlock_out%space /= SPACE_C) then
    4061            0 :       ABI_ERROR("Not correct space")
    4062              :     end if
    4063              : 
    4064          198 :     call xgBlock_check_gpu_option(xgBlock1,xgBlock2)
    4065          198 :     call xgBlock_check_gpu_option(xgBlock2,xgBlock_out)
    4066              : 
    4067          198 :     if (xgBlock1%gpu_option==ABI_GPU_KOKKOS .or. xgBlock2%gpu_option==ABI_GPU_OPENMP) then
    4068              : #if defined HAVE_KOKKOS || defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
    4069              :       ! /IML\ will fix later compilation bug
    4070              :       ABI_ERROR("not implemented")
    4071              :       !call abi_gpu_xdot(2, xgBlock1%cols*xgBlock1%LDim, xgBlock_out%vecC, xgBlock1%vecC, 1, xgBlock2%vecC, 1)
    4072              : #elif defined HAVE_OPENMP_OFFLOAD
    4073              : !FIXME For several compilers, OMP doesn't work correctly with structured types, so use pointers
    4074              :       xgBlock1__vecC => xgBlock1%vecC
    4075              :       xgBlock2__vecC => xgBlock2%vecC
    4076              :       !$OMP TARGET DATA USE_DEVICE_ADDR(xgBlock1__vecC,xgBlock2__vecC)
    4077              :       ! /IML\ will fix later compilation bug
    4078              :       ABI_ERROR("not implemented")
    4079              :       !call abi_gpu_xdot(2, xgBlock1%cols*xgBlock1%LDim, xgBlock_out%vecC, c_loc(xgBlock1__vecC),1,c_loc(xgBlock2__vecC),1)
    4080              :       !$OMP END TARGET DATA
    4081              : #endif
    4082              : 
    4083              :     else
    4084          792 :       xgBlock_out%vecC = zdotc(xgBlock1%cols*xgBlock1%LDim, xgBlock1%vecC, 1, xgBlock2%vecC, 1)
    4085              :     end if
    4086              : 
    4087          198 :     call timab(tim_dot,2,tsec)
    4088              : 
    4089          198 :   end subroutine xgBlock_dotC
    4090              :   !!***
    4091              : 
    4092              :   !!****f* m_xg/xgBlock_add
    4093              :   !!
    4094              :   !! NAME
    4095              :   !! xgBlock_add
    4096              : 
    4097      2148380 :   subroutine xgBlock_add(xgBlockA, xgBlockB)
    4098              : 
    4099              :     type(xgBlock_t), intent(inout) :: xgBlockA
    4100              :     type(xgBlock_t), intent(inout) :: xgBlockB
    4101              :     integer :: col
    4102              :     integer :: row
    4103              :     integer :: fact
    4104              :     integer :: rows,cols
    4105              : 
    4106              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    4107              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecR(:,:), xgBlockB__vecR(:,:)
    4108              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecC(:,:), xgBlockB__vecC(:,:)
    4109              : #endif
    4110              :     double precision :: tsec(2)
    4111              : 
    4112      2148380 :     call timab(tim_add,1,tsec)
    4113              : 
    4114      2148380 :     if ( xgBlockA%space /= xgBlockB%space ) then
    4115            0 :       ABI_ERROR("Must be same space for add")
    4116              :     end if
    4117      2148380 :     if ( xgBlockA%rows /= xgBlockB%rows ) then
    4118            0 :       ABI_ERROR("Must have same LDim for add")
    4119              :     end if
    4120      2148380 :     if ( xgBlockA%cols /= xgBlockB%cols ) then
    4121            0 :       ABI_ERROR("Must have same cols for add")
    4122              :     end if
    4123              : 
    4124      2148380 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    4125              : 
    4126      2148380 :     fact = 1 ; if (xgBlockA%space==SPACE_CR) fact = 2
    4127      2148380 :     rows=fact*xgBlockB%rows
    4128      2148380 :     cols=xgBlockB%cols
    4129              : 
    4130      2148380 :     if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    4131              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    4132              :       select case(xgBlockA%space)
    4133              :       case (SPACE_R,SPACE_CR)
    4134              :         xgBlockA__vecR => xgBlockA%vecR
    4135              :         xgBlockB__vecR => xgBlockB%vecR
    4136              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlockA__vecR,xgBlockB__vecR)
    4137              :         do col = 1, cols
    4138              :           do row = 1, rows
    4139              :             xgBlockA__vecR(row,col) = xgBlockA__vecR(row,col) + xgBlockB__vecR(row,col)
    4140              :           end do
    4141              :         end do
    4142              :         !call daxpy(xgBlockA%cols*xgBlockA%LDim,1.d0,xgBlockB%vecR,1,xgBlockA%vecR1)
    4143              :       case (SPACE_C)
    4144              :         xgBlockA__vecC => xgBlockA%vecC
    4145              :         xgBlockB__vecC => xgBlockB%vecC
    4146              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlockA__vecC,xgBlockB__vecC)
    4147              :         do col = 1, cols
    4148              :           do row = 1, rows
    4149              :             xgBlockA__vecC(row,col) = xgBlockA__vecC(row,col) + xgBlockB__vecC(row,col)
    4150              :           end do
    4151              :         end do
    4152              :         !call zaxpy(xgBlockA%cols*xgBlockA%LDim,1.d0,xgBlockB%vecR,1,xgBlockA%vecR1)
    4153              :       end select
    4154              : #endif
    4155              :     else
    4156              :       select case(xgBlockA%space)
    4157              :       case (SPACE_R,SPACE_CR)
    4158              :         !$omp parallel do collapse(2) shared(xgBlockA,xgBlockB) private(col,row)
    4159      2556988 :         do col = 1, cols
    4160    696784742 :           do row = 1, rows
    4161    696413818 :             xgBlockA%vecR(row,col) = xgBlockA%vecR(row,col) + xgBlockB%vecR(row,col)
    4162              :           end do
    4163              :         end do
    4164              :         !call daxpy(xgBlockA%cols*xgBlockA%LDim,1.d0,xgBlockB%vecR,1,xgBlockA%vecR1)
    4165              :       case (SPACE_C)
    4166              :         !$omp parallel do collapse(2) shared(xgBlockA,xgBlockB) private(col,row)
    4167      8069284 :         do col = 1, cols
    4168    524300312 :           do row = 1, rows
    4169    522522856 :             xgBlockA%vecC(row,col) = xgBlockA%vecC(row,col) + xgBlockB%vecC(row,col)
    4170              :           end do
    4171              :         end do
    4172              :         !call zaxpy(xgBlockA%cols*xgBlockA%LDim,1.d0,xgBlockB%vecR,1,xgBlockA%vecR1)
    4173              :       end select
    4174              :     end if
    4175              : 
    4176      2148380 :     call timab(tim_add,2,tsec)
    4177              : 
    4178      2148380 :   end subroutine xgBlock_add
    4179              :   !!***
    4180              : 
    4181              :   !!****f* m_xg/xgBlock_cshift
    4182              :   !!
    4183              :   !! NAME
    4184              :   !! xgBlock_cshift
    4185              : 
    4186       615498 :   subroutine xgBlock_cshift(xgBlock,nshift,shiftdim)
    4187              : 
    4188              :     type(xgBlock_t), intent(inout) :: xgBlock
    4189              :     integer        , intent(in   ) :: nshift
    4190              :     integer        , intent(in   ) :: shiftdim
    4191              :     double precision :: tsec(2)
    4192              : 
    4193       615498 :     call timab(tim_cshift,1,tsec)
    4194       685806 :     select case(xgBlock%space)
    4195              :     case (SPACE_R)
    4196     42800784 :       xgBlock%vecR(:,:) = cshift(xgBlock%vecR(:,:),nshift,dim=shiftdim) ! Bottom 2*blockdim lines are now at the top
    4197              :     case (SPACE_C)
    4198     21260784 :       xgBlock%vecC(:,:) = cshift(xgBlock%vecC(:,:),nshift,dim=shiftdim) ! Bottom 2*blockdim lines are now at the top
    4199              :     case (SPACE_CR)
    4200       615498 :       ABI_ERROR('Not implemented')
    4201              :     end select
    4202       615498 :     call timab(tim_cshift,2,tsec)
    4203              : 
    4204       615498 :   end subroutine xgBlock_cshift
    4205              :   !!***
    4206              : 
    4207              :   !!****f* m_xg/xgBlock_colwiseNorm2
    4208              :   !!
    4209              :   !! NAME
    4210              :   !! xgBlock_colwiseNorm2
    4211              : 
    4212      1603853 :   subroutine xgBlock_colwiseNorm2(xgBlock, dot, max_val, max_elt, min_val, min_elt, comm_loc)
    4213              : 
    4214              :     type(xgBlock_t) , intent(in   ) :: xgBlock
    4215              :     type(xgBlock_t) , intent(inout) :: dot
    4216              :     double precision, intent(  out), optional :: max_val
    4217              :     integer         , intent(  out), optional :: max_elt
    4218              :     double precision, intent(  out), optional :: min_val
    4219              :     integer         , intent(  out), optional :: min_elt
    4220              :     integer         , intent(in   ), optional :: comm_loc
    4221              : 
    4222              :     integer :: icol, ierr, fact, comm_
    4223              :     double precision,external :: ddot
    4224              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    4225              :     integer :: cols,rows
    4226              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    4227              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:),dot__vecR(:,:)
    4228              : #endif
    4229              : 
    4230              : #if (defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD) || defined FC_CRAY
    4231              :     integer :: ii
    4232              :     double precision :: tmp
    4233              : #endif
    4234              :     double precision :: tsec(2)
    4235              : 
    4236      1603853 :     call timab(tim_colw_norm2,1,tsec)
    4237              : 
    4238      1603853 :     if ( dot%space /= SPACE_R ) then
    4239            0 :       ABI_ERROR("space(dot) should be SPACE_R")
    4240              :     end if
    4241      1603853 :     if ( dot%cols /= 1 ) then
    4242            0 :       ABI_ERROR("cols(dot) should be 1")
    4243              :     end if
    4244      1603853 :     if ( dot%rows /= xgBlock%cols ) then
    4245            0 :       ABI_ERROR("rows(dot) should be cols(xgBlock)")
    4246              :     end if
    4247      1603853 :     comm_=comm(xgBlock)
    4248      1603853 :     if (present(comm_loc)) then
    4249         4660 :       comm_ = comm_loc
    4250              :     end if
    4251              : 
    4252      1603853 :     if (xgBlock%space==SPACE_CR.and.xgBlock%me_g0<0) then
    4253            0 :       ABI_ERROR("xgBlock me_g0 is not initialized")
    4254              :     end if
    4255      1603853 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    4256              : 
    4257      1603853 :     if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    4258              : 
    4259              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS) && defined(HAVE_YAKL)
    4260              : 
    4261              :       select case(xgBlock%space)
    4262              :       case(SPACE_R,SPACE_CR)
    4263              :         if (xgBlock%space==SPACE_CR) then
    4264              :           ABI_ERROR('Not implemented for GPU with KOKKOS')
    4265              :         end if
    4266              :         call computeBatchedDotProduct_scalar(c_loc(xgBlock%vecR), c_loc(xgBlock%vecR), &
    4267              :           & c_loc(dot%vecR), fact*xgBlock%rows, xgBlock%cols, fact*xgBlock%ldim)
    4268              : 
    4269              :       case(SPACE_C)
    4270              :         call computeBatchedDotProduct_cplx_scalar(c_loc(xgBlock%vecC), c_loc(xgBlock%vecC), &
    4271              :           & c_loc(dot%vecR), xgBlock%rows, xgBlock%cols, xgBlock%ldim)
    4272              : 
    4273              :       end select
    4274              :       call xmpi_sum(dot%vecR,comm_,ierr)
    4275              : 
    4276              :       ! do reductions
    4277              :       if ( present(max_val) ) then
    4278              :         call computeMax_scalar(c_loc(dot%vecR(1,1)), xgBlock%cols, max_val)
    4279              :       end if
    4280              :       if ( present(min_val) ) then
    4281              :         call computeMin_scalar(c_loc(dot%vecR(1,1)), xgBlock%cols, min_val)
    4282              :       end if
    4283              :       if ( present(max_elt) ) then
    4284              :         call computeMaxloc_scalar(c_loc(dot%vecR(1,1)), xgBlock%cols, max_elt)
    4285              :       end if
    4286              :       if ( present(min_elt) ) then
    4287              :         call computeMinloc_scalar(c_loc(dot%vecR(1,1)), xgBlock%cols, min_elt)
    4288              :       end if
    4289              : 
    4290              : #else
    4291              :       ! we shouldn't be here, it means gpu_option was wrongly set to 1 in
    4292              :       ! input parameter file
    4293              : #endif
    4294              : 
    4295      1603853 :     else if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    4296              : 
    4297              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    4298              : 
    4299              :       cols=xgBlock%cols
    4300              :       rows=fact*xgBlock%rows
    4301              :       dot__vecR => dot%vecR
    4302              :       select case(xgBlock%space)
    4303              :       case(SPACE_R,SPACE_CR)
    4304              :         xgBlock__vecR => xgBlock%vecR
    4305              :         !$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecR,xgBlock__vecR) PRIVATE(icol,tmp)
    4306              :         do icol = 1, cols
    4307              :           tmp=0
    4308              :           !$OMP PARALLEL DO REDUCTION(+:tmp) PRIVATE(ii)
    4309              :           do ii = 1,rows
    4310              :             tmp = tmp + fact*xgBlock__vecR(ii,icol)*xgBlock__vecR(ii,icol)
    4311              :           end do
    4312              :           dot__vecR(icol,1)=tmp
    4313              :         end do
    4314              :         if (xgBlock%me_g0==1) then
    4315              :           !$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecR,xgBlock__vecR) PRIVATE(icol)
    4316              :           do icol = 1, cols
    4317              :             dot__vecR(icol,1) = dot__vecR(icol,1) - xgBlock__vecR(1,icol)*xgBlock__vecR(1,icol) &
    4318              : &                                                 - xgBlock__vecR(2,icol)*xgBlock__vecR(2,icol)
    4319              :           end do
    4320              :         end if
    4321              :       case(SPACE_C)
    4322              :         xgBlock__vecC => xgBlock%vecC
    4323              :         !$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecR,xgBlock__vecC) PRIVATE(icol,tmp)
    4324              :         do icol = 1, cols
    4325              :           tmp=0
    4326              :           !$OMP PARALLEL DO REDUCTION(+:tmp) PRIVATE(ii)
    4327              :           do ii = 1,rows
    4328              :             tmp = tmp + dconjg(xgBlock__vecC(ii,icol))*xgBlock__vecC(ii,icol)
    4329              :           end do
    4330              :           dot__vecR(icol,1)=tmp
    4331              :         end do
    4332              :       end select
    4333              :       !FIXME This should happen inplace ideally
    4334              :       !$OMP TARGET UPDATE FROM(dot__vecR)
    4335              :       call xmpi_sum(dot%vecR,comm_,icol)
    4336              :       !$OMP TARGET UPDATE TO(dot__vecR)
    4337              : 
    4338              :       ! do reductions
    4339              :       if ( present(max_val) ) then
    4340              :         max_val = maxval(dot%vecR(1:xgBlock%cols,1))
    4341              :       end if
    4342              :       if ( present(min_val) ) then
    4343              :         min_val = minval(dot%vecR(1:xgBlock%cols,1))
    4344              :       end if
    4345              :       if ( present(max_elt) ) then
    4346              :         max_elt = maxloc(dot%vecR(1:xgBlock%cols,1),dim=1)
    4347              :       end if
    4348              :       if ( present(min_elt) ) then
    4349              :         min_elt = minloc(dot%vecR(1:xgBlock%cols,1),dim=1)
    4350              :       end if
    4351              : 
    4352              : #endif
    4353              : 
    4354              :     else
    4355              : 
    4356       381659 :       select case(xgBlock%space)
    4357              :       case(SPACE_R,SPACE_CR)
    4358              :         !$omp parallel do shared(dot,xgBlock)
    4359      2485231 :         do icol = 1, xgBlock%cols
    4360      2485231 :           dot%vecR(icol,1) = fact*ddot(fact*xgBlock%rows,xgBlock%vecR(:,icol),1,xgBlock%vecR(:,icol),1)
    4361              :         end do
    4362              :         !$omp end parallel do
    4363       381659 :         if (xgBlock%me_g0==1) then
    4364              :           !$omp parallel do shared(dot,xgBlock)
    4365       179617 :           do icol = 1, xgBlock%cols
    4366       179617 :             dot%vecR(icol,1) = dot%vecR(icol,1) - ddot(2,xgBlock%vecR(:,icol),1,xgBlock%vecR(:,icol),1)
    4367              :           end do
    4368              :           !$omp end parallel do
    4369              :         end if
    4370              :       case(SPACE_C)
    4371              : #if defined(FC_CRAY)
    4372              : !FIXME zdotc call goes wrong with NVHPC (NVHPC 22.11, MKL 22.3) or CRAY
    4373              :         !$omp parallel do private(ii,tmp)
    4374              :         do icol = 1, xgBlock%cols
    4375              :           tmp=0
    4376              :           do ii = 1, xgBlock%rows
    4377              :             tmp = tmp + dconjg(xgBlock%vecC(ii,icol))*xgBlock%vecC(ii,icol)
    4378              :           end do
    4379              :           dot%vecR(icol,1)=tmp
    4380              :         end do
    4381              :         !$omp end parallel do
    4382              : #else
    4383              :         !$omp parallel do shared(dot,xgBlock)
    4384      7471871 :         do icol = 1, xgBlock%cols
    4385              :           ! Instead of calling a complex function to get only the real part of the
    4386              :           ! result
    4387              :           !dot%vecR(icol,1) = dble(zdotc(xgBlock%rows,xgBlock%vecC(:,icol),1,xgBlock%vecC(:,icol),1))
    4388              :           ! Directely call a real function which gives what we want.
    4389      7090212 :           dot%vecR(icol,1) = ddot(2*xgBlock%rows,xgBlock%vecC(:,icol),1,xgBlock%vecC(:,icol),1)
    4390              :         end do
    4391              :         !$omp end parallel do
    4392              : #endif
    4393              :       end select
    4394      1603853 :       call xmpi_sum(dot%vecR,comm_,ierr)
    4395              : 
    4396      1603853 :       if ( present(max_val) ) then
    4397      7203198 :         max_val = maxval(dot%vecR(1:xgBlock%cols,1))
    4398              :       end if
    4399      1603853 :       if ( present(min_val) ) then
    4400            0 :         min_val = minval(dot%vecR(1:xgBlock%cols,1))
    4401              :       end if
    4402      1603853 :       if ( present(max_elt) ) then
    4403            0 :         max_elt = maxloc(dot%vecR(1:xgBlock%cols,1),dim=1)
    4404              :       end if
    4405      1603853 :       if ( present(min_elt) ) then
    4406            0 :         min_elt = minloc(dot%vecR(1:xgBlock%cols,1),dim=1)
    4407              :       end if
    4408              : 
    4409              :     end if ! if gpu_option==ABI_GPU_KOKKOS
    4410              : 
    4411      1603853 :     call timab(tim_colw_norm2,2,tsec)
    4412              : 
    4413      1603853 :   end subroutine xgBlock_colwiseNorm2
    4414              :   !!***
    4415              : 
    4416              :   !!****f* m_xg/xgBlock_colwiseDotProduct
    4417              :   !!
    4418              :   !! NAME
    4419              :   !! xgBlock_colwiseDotProduct
    4420              : 
    4421        67224 :   subroutine xgBlock_colwiseDotProduct(xgBlockA,xgBlockB,dot,max_val,max_elt,min_val,min_elt,comm_loc)
    4422              : 
    4423              :     type(xgBlock_t)  , intent(in   ) :: xgBlockA
    4424              :     type(xgBlock_t)  , intent(in   ) :: xgBlockB
    4425              :     type(xgBlock_t)  , intent(inout) :: dot
    4426              :     integer, intent(in), optional :: comm_loc
    4427              :     double precision , intent(  out), optional :: max_val
    4428              :     integer          , intent(  out), optional :: max_elt
    4429              :     double precision , intent(  out), optional :: min_val
    4430              :     integer          , intent(  out), optional :: min_elt
    4431              :     integer :: icol,fact,comm_
    4432              :     double precision,external :: ddot
    4433              :     !double complex,external :: zdotc !conjugated dot product, not working on macos
    4434              : 
    4435              : #if (defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD) || defined(FC_NVHPC) || defined(FC_CRAY)
    4436              :     integer :: rows,cols,ii,me_g0
    4437              :     double precision :: tmp
    4438              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecC(:,:),xgBlockB__vecC(:,:),dot__vecC(:,:)
    4439              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecR(:,:),xgBlockB__vecR(:,:),dot__vecR(:,:)
    4440              : #endif
    4441              :     double precision :: tsec(2)
    4442              : 
    4443        67224 :     call timab(tim_colw_dot,1,tsec)
    4444              : 
    4445        67224 :     call xgBlock_check(xgBlockA,xgBlockB)
    4446              : 
    4447        67224 :     comm_=comm(xgBlockA)
    4448        67224 :     if (present(comm_loc)) then
    4449        66144 :       comm_ = comm_loc
    4450              :     else
    4451         1080 :       if (comm(xgBlockA)/=comm(xgBlockB)) then
    4452            0 :         ABI_ERROR('xgBlockA and xgBlockB should have the same comm')
    4453              :       end if
    4454              :     end if
    4455        67224 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    4456        67224 :     call xgBlock_check_gpu_option(xgBlockA,dot)
    4457              : 
    4458        67224 :     if (xgBlockA%space/=SPACE_CR) then
    4459        47640 :       if (dot%space/=xgBlockA%space) then
    4460            0 :         ABI_ERROR('xgBlockA and dot should have the same space')
    4461              :       end if
    4462              :     else ! space(A) = space(B) = SPACE_CR
    4463        19584 :       if (xgBlockA%me_g0<0) then
    4464            0 :         ABI_ERROR("xgBlockA me_g0 is not initialized")
    4465              :       end if
    4466        19584 :       if (xgBlockB%me_g0<0) then
    4467            0 :         ABI_ERROR("xgBlockB me_g0 is not initialized")
    4468              :       end if
    4469        19584 :       if (xgBlockA%me_g0/=xgBlockB%me_g0) then
    4470            0 :         ABI_ERROR('xgBlockA and xgBlockB should have the same me_g0')
    4471              :       end if
    4472        19584 :       if (dot%space/=SPACE_R) then
    4473            0 :         ABI_ERROR('if space(A)=SPACE_CR, space(dot) should be SPACE_R')
    4474              :       end if
    4475              :     end if
    4476        67224 :     if ( dot%cols /= 1 ) then
    4477            0 :       ABI_ERROR("cols(dot) should be 1")
    4478              :     end if
    4479        67224 :     if ( dot%rows /= xgBlockA%cols ) then
    4480            0 :       ABI_ERROR("rows(dot) should be cols(xgBlockA)")
    4481              :     end if
    4482              : 
    4483        67224 :     fact = 1 ; if (xgBlockA%space==SPACE_CR) fact = 2
    4484              : 
    4485        67224 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS) then
    4486              : 
    4487              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS) && defined(HAVE_YAKL)
    4488              : 
    4489              :       select case(xgBlockA%space)
    4490              :       case(SPACE_R,SPACE_CR)
    4491              :         if (xgBlockA%space==SPACE_CR) then
    4492              :           ABI_ERROR('Not implemented for GPU with KOKKOS')
    4493              :         end if
    4494              :         call computeBatchedDotProduct_scalar(c_loc(xgBlockA%vecR), c_loc(xgBlockB%vecR), &
    4495              :           & c_loc(dot%vecR), xgBlockA%rows, xgBlockA%cols, xgBlockA%ldim)
    4496              : 
    4497              :         ! do reductions
    4498              :         if ( present(max_val) ) then
    4499              :           call computeMax_scalar(c_loc(dot%vecR(1,1)), xgBlockA%cols, max_val)
    4500              :         end if
    4501              :         if ( present(min_val) ) then
    4502              :           call computeMin_scalar(c_loc(dot%vecR(1,1)), xgBlockA%cols, min_val)
    4503              :         end if
    4504              :         if ( present(max_elt) ) then
    4505              :           call computeMaxloc_scalar(c_loc(dot%vecR(1,1)), xgBlockA%cols, max_elt)
    4506              :         end if
    4507              :         if ( present(min_elt) ) then
    4508              :           call computeMinloc_scalar(c_loc(dot%vecR(1,1)), xgBlockA%cols, min_elt)
    4509              :         end if
    4510              : 
    4511              :       case(SPACE_C)
    4512              :         call computeBatchedDotProduct_cplx(c_loc(xgBlockA%vecC), c_loc(xgBlockB%vecC), &
    4513              :           & c_loc(dot%vecC), xgBlockA%rows, xgBlockA%cols, xgBlockA%ldim)
    4514              : 
    4515              :         ! do reductions
    4516              :         if ( present(max_val) ) then
    4517              :           call computeMax_complex(c_loc(dot%vecC(1,1)), xgBlockA%cols, max_val)
    4518              :         end if
    4519              :         if ( present(min_val) ) then
    4520              :           call computeMin_complex(c_loc(dot%vecC(1,1)), xgBlockA%cols, min_val)
    4521              :         end if
    4522              :         if ( present(max_elt) ) then
    4523              :           call computeMaxloc_complex(c_loc(dot%vecC(1,1)), xgBlockA%cols, max_elt)
    4524              :         end if
    4525              :         if ( present(min_elt) ) then
    4526              :           call computeMinloc_scalar(c_loc(dot%vecC(1,1)), xgBlockA%cols, min_elt)
    4527              : 
    4528              :         end if
    4529              : 
    4530              :       end select
    4531              : 
    4532              : #else
    4533              :       ! we shouldn't be here, it means gpu_option was wrongly set to 1 in
    4534              :       ! input parameter file
    4535              : #endif
    4536              : 
    4537        67224 :     else if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    4538              : 
    4539              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    4540              :       rows = xgBlockA%rows; cols = xgBlockA%cols
    4541              :       select case(xgBlockA%space)
    4542              :       case(SPACE_R,SPACE_CR)
    4543              :         xgBlockA__vecR => xgBlockA%vecR
    4544              :         xgBlockB__vecR => xgBlockB%vecR
    4545              :         dot__vecR => dot%vecR
    4546              :         me_g0 = xgBlockA%me_g0
    4547              : #if defined FC_NVHPC
    4548              :         !$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecR,xgBlockA__vecR,xgBlockB__vecR) PRIVATE(icol,tmp)
    4549              :         do icol = 1, cols
    4550              :           tmp=0
    4551              :           !$OMP PARALLEL DO REDUCTION(+:tmp) PRIVATE(ii)
    4552              :           do ii = 1, fact*rows
    4553              :             tmp = tmp + fact*xgBlockA__vecR(ii,icol)*xgBlockB__vecR(ii,icol)
    4554              :           end do
    4555              :           dot__vecR(icol,1)=tmp
    4556              :         end do
    4557              :         if (me_g0==1) then
    4558              :           !$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecR,xgBlockA__vecR,xgBlockB__vecR) PRIVATE(icol)
    4559              :           do icol = 1, cols
    4560              :             dot__vecR(icol,1) = dot__vecR(icol,1) - xgBlockA__vecR(1,icol)*xgBlockB__vecR(1,icol)
    4561              :           end do
    4562              :         end if
    4563              :         !$OMP TARGET UPDATE FROM(dot__vecR)
    4564              : #else
    4565              : !FIXME For several compilers, this section doesnt work properly
    4566              :         !$OMP TARGET UPDATE FROM(dot__vecR,xgBlockA__vecR,xgBlockB__vecR)
    4567              :         !!$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecR,xgBlockA__vecR,xgBlockB__vecR) PRIVATE(icol,tmp)
    4568              :         do icol = 1, cols
    4569              :           tmp=0
    4570              :           !!$OMP PARALLEL DO REDUCTION(+:tmp) PRIVATE(ii)
    4571              :           do ii = 1, fact*rows
    4572              :             tmp = tmp + fact*xgBlockA__vecR(ii,icol)*xgBlockB__vecR(ii,icol)
    4573              :           end do
    4574              :           dot__vecR(icol,1)=tmp
    4575              :         end do
    4576              :         if (me_g0==1) then
    4577              :           do icol = 1, cols
    4578              :             dot__vecR(icol,1) = dot__vecR(icol,1) - xgBlockA__vecR(1,icol)*xgBlockB__vecR(1,icol)
    4579              :           end do
    4580              :         end if
    4581              :         !$OMP TARGET UPDATE TO(dot__vecR)
    4582              : #endif
    4583              : 
    4584              :         !TODO Port this to GPU (reductions)
    4585              :         if ( present(max_val) ) then
    4586              :           max_val = maxval(dot%vecR(1:xgBlockA%cols,1))
    4587              :         end if
    4588              :         if ( present(min_val) ) then
    4589              :           min_val = minval(dot%vecR(1:xgBlockA%cols,1))
    4590              :         end if
    4591              :         if ( present(max_elt) ) then
    4592              :           max_elt = maxloc(dot%vecR(1:xgBlockA%cols,1),dim=1)
    4593              :         end if
    4594              :         if ( present(min_elt) ) then
    4595              :           min_elt = minloc(dot%vecR(1:xgBlockA%cols,1),dim=1)
    4596              :         end if
    4597              : 
    4598              :       case(SPACE_C)
    4599              :         xgBlockA__vecC => xgBlockA%vecC
    4600              :         xgBlockB__vecC => xgBlockB%vecC
    4601              :         dot__vecC => dot%vecC
    4602              : #if defined FC_NVHPC
    4603              :         !$OMP TARGET TEAMS DISTRIBUTE MAP(to:dot__vecC,xgBlockA__vecC,xgBlockB__vecC) PRIVATE(icol,tmp)
    4604              :         do icol = 1, cols
    4605              :           tmp=0
    4606              :           !$OMP PARALLEL DO REDUCTION(+:tmp) PRIVATE(ii)
    4607              :           do ii = 1, rows
    4608              :             tmp = tmp + dconjg(xgBlockA__vecC(ii,icol))*xgBlockB__vecC(ii,icol)
    4609              :           end do
    4610              :           dot__vecC(icol,1)=tmp
    4611              :         end do
    4612              :         !$OMP TARGET UPDATE FROM(dot__vecC)
    4613              : #else
    4614              : !FIXME For several compilers, this section doesnt work properly
    4615              :         !$OMP TARGET UPDATE FROM(xgBlockA__vecC,xgBlockB__vecC)
    4616              :         do icol = 1, cols
    4617              :           tmp=0
    4618              :           !$OMP PARALLEL DO REDUCTION(+:tmp) PRIVATE(ii)
    4619              :           do ii = 1, rows
    4620              :             tmp = tmp + dconjg(xgBlockA__vecC(ii,icol))*xgBlockB__vecC(ii,icol)
    4621              :           end do
    4622              :           dot__vecC(icol,1)=tmp
    4623              :         end do
    4624              :         !$OMP TARGET UPDATE TO(dot__vecC)
    4625              : #endif
    4626              : 
    4627              :         !TODO Port this to GPU (reductions)
    4628              :         if ( present(max_val) ) then
    4629              :           max_val = maxval(dble(dot%vecC(1:xgBlockA%cols,1)))
    4630              :         end if
    4631              :         if ( present(min_val) ) then
    4632              :           min_val = minval(dble(dot%vecC(1:xgBlockA%cols,1)))
    4633              :         end if
    4634              :         if ( present(max_elt) ) then
    4635              :           max_elt = maxloc(dble(dot%vecC(1:xgBlockA%cols,1)),dim=1)
    4636              :         end if
    4637              :         if ( present(min_elt) ) then
    4638              :           min_elt = minloc(dble(dot%vecC(1:xgBlockA%cols,1)),dim=1)
    4639              :         end if
    4640              : 
    4641              :       end select
    4642              : 
    4643              : #endif
    4644              : 
    4645              :     else
    4646              : 
    4647        26929 :       select case(xgBlockA%space)
    4648              :       case(SPACE_R,SPACE_CR)
    4649              :         !$omp parallel do shared(dot,xgBlockA,xgBlockB)
    4650       153493 :         do icol = 1, xgBlockA%cols
    4651       153493 :           dot%vecR(icol,1) = fact*ddot(fact*xgBlockA%rows,xgBlockA%vecR(:,icol),1,xgBlockB%vecR(:,icol),1)
    4652              :         end do
    4653              :         !$omp end parallel do
    4654        26929 :         if (xgBlockA%me_g0==1) then
    4655              :           !$omp parallel do shared(dot,xgBlockA,xgBlockB) &
    4656              :           !$omp& schedule(static)
    4657        13872 :           do icol = 1, xgBlockA%cols
    4658        13872 :             dot%vecR(icol,1) = dot%vecR(icol,1) - ddot(2,xgBlockA%vecR(:,icol),1,xgBlockB%vecR(:,icol),1)
    4659              :           end do
    4660              :           !$omp end parallel do
    4661              :         end if
    4662              : 
    4663        26929 :         if ( present(max_val) ) then
    4664            0 :           max_val = maxval(dot%vecR(1:xgBlockA%cols,1))
    4665              :         end if
    4666        26929 :         if ( present(min_val) ) then
    4667            0 :           min_val = minval(dot%vecR(1:xgBlockA%cols,1))
    4668              :         end if
    4669        26929 :         if ( present(max_elt) ) then
    4670            0 :           max_elt = maxloc(dot%vecR(1:xgBlockA%cols,1),dim=1)
    4671              :         end if
    4672        26929 :         if ( present(min_elt) ) then
    4673            0 :           min_elt = minloc(dot%vecR(1:xgBlockA%cols,1),dim=1)
    4674              :         end if
    4675              : 
    4676              :       case(SPACE_C)
    4677              : #if defined(FC_NVHPC) || defined(FC_CRAY)
    4678              : !FIXME zdotc call goes wrong with NVHPC (NVHPC 22.11, MKL 22.3) or CRAY
    4679              :         !$omp parallel do private(ii,tmp) shared(dot,xgBlockA,xgBlockB)
    4680              :         do icol = 1, xgBlockA%cols
    4681              :           tmp=0
    4682              :           do ii = 1, xgBlockA%rows
    4683              :             tmp = tmp + dconjg(xgBlockA%vecC(ii,icol))*xgBlockB%vecC(ii,icol)
    4684              :           end do
    4685              :           dot%vecC(icol,1)=tmp
    4686              :         end do
    4687              :         !$omp end parallel do
    4688              : #else
    4689              :         !$omp parallel do shared(dot,xgBlockA,xgBlockB)
    4690       258927 :         do icol = 1, xgBlockA%cols
    4691       258927 :           dot%vecC(icol,1) = xdotc(xgBlockA%rows,xgBlockA%vecC(:,icol),1,xgBlockB%vecC(:,icol),1)
    4692              :         end do
    4693              :         !$omp end parallel do
    4694              : #endif
    4695              : 
    4696        40295 :         if ( present(max_val) ) then
    4697            0 :           max_val = maxval(dble(dot%vecC(1:xgBlockA%cols,1)))
    4698              :         end if
    4699        40295 :         if ( present(min_val) ) then
    4700            0 :           min_val = minval(dble(dot%vecC(1:xgBlockA%cols,1)))
    4701              :         end if
    4702        40295 :         if ( present(max_elt) ) then
    4703            0 :           max_elt = maxloc(dble(dot%vecC(1:xgBlockA%cols,1)),dim=1)
    4704              :         end if
    4705       107519 :         if ( present(min_elt) ) then
    4706            0 :           min_elt = minloc(dble(dot%vecC(1:xgBlockA%cols,1)),dim=1)
    4707              :         end if
    4708              : 
    4709              :       end select
    4710              : 
    4711              :     end if ! gpu_option
    4712              : 
    4713        67224 :     call xgBlock_mpi_sum(dot,comm=comm_)
    4714              : 
    4715        67224 :     call timab(tim_colw_dot,2,tsec)
    4716              : 
    4717        67224 :   end subroutine xgBlock_colwiseDotProduct
    4718              :   !!***
    4719              : 
    4720              :   !!****f* m_xg/xgBlock_colwiseDivision
    4721              :   !!
    4722              :   !! NAME
    4723              :   !! xgBlock_colwiseDivision
    4724              : 
    4725        24432 :   subroutine xgBlock_colwiseDivision(xgBlockA, xgBlockB, divResult, &
    4726              :     & max_val, max_elt, min_val, min_elt)
    4727              : 
    4728              :     type(xgBlock_t) ,      intent(in   )           :: xgBlockA
    4729              :     type(xgBlock_t) ,      intent(in   )           :: xgBlockB
    4730              :     type(xgBlock_t) ,      intent(inout)           :: divResult
    4731              :     double precision,      intent(inout), optional :: max_val
    4732              :     integer, dimension(2), intent(inout), optional, target :: max_elt
    4733              :     double precision,      intent(inout), optional :: min_val
    4734              :     integer, dimension(2), intent(inout), optional, target :: min_elt
    4735              : 
    4736              :     integer :: irow,icol,rows,cols
    4737              : 
    4738              : #if defined HAVE_GPU
    4739              :     ! TODO: evaluate if total_size should be a 64 bit integer, i.e.
    4740              :     ! does spacedim * neigenpairs be larger than 2^31 = 2. 10^9
    4741              :     integer(kind=c_int32_t)  :: total_size
    4742              : #if defined HAVE_OPENMP_OFFLOAD
    4743              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecC(:,:),xgBlockB__vecC(:,:),divResult__vecC(:,:)
    4744              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlockA__vecR(:,:),xgBlockB__vecR(:,:),divResult__vecR(:,:)
    4745              : #endif
    4746              : #endif
    4747              :     double precision :: tsec(2)
    4748              : 
    4749        24432 :     call timab(tim_colw_div,1,tsec)
    4750              : 
    4751        24432 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    4752        24432 :     call xgBlock_check_gpu_option(xgBlockA,divResult)
    4753              : 
    4754        24432 :     rows = xgBlockA%rows; cols = xgBlockA%cols
    4755              : 
    4756        24432 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS) then
    4757              : 
    4758              : #if defined(HAVE_GPU_CUDA) && defined(HAVE_KOKKOS) && defined(HAVE_YAKL)
    4759              : 
    4760              :       total_size = xgBlockA%rows * xgBlockA%cols
    4761              : 
    4762              :       select case(xgBlockA%space)
    4763              :       case(SPACE_R)
    4764              :         call computeColwiseDivision_scalar(c_loc(xgBlockA%vecR(1,1)), &
    4765              :           &                                c_loc(xgBlockB%vecR(1,1)), &
    4766              :           &                                total_size,                &
    4767              :           &                                c_loc(divResult%vecR(1,1)))
    4768              : 
    4769              :         ! do reductions
    4770              :         if ( present(max_val) ) then
    4771              :           call computeMax_scalar(c_loc(divResult%vecR(1,1)), total_size, max_val)
    4772              :         end if
    4773              :         if ( present(min_val) ) then
    4774              :           call computeMin_scalar(c_loc(divResult%vecR(1,1)), total_size, min_val)
    4775              :         end if
    4776              :         if ( present(max_elt) ) then
    4777              :           call computeMaxloc_scalar_2d(c_loc(divResult%vecR(1,1)), xgBlockA%rows, xgBlockA%cols, c_loc(max_elt))
    4778              :         end if
    4779              :         if ( present(min_elt) ) then
    4780              :           call computeMinloc_scalar_2d(c_loc(divResult%vecR(1,1)), xgBlockA%rows, xgBlockA%cols, c_loc(min_elt))
    4781              :         end if
    4782              : 
    4783              :       case(SPACE_C)
    4784              :         call computeColwiseDivision_complex(c_loc(xgBlockA%vecC(1,1)), &
    4785              :           &                                 c_loc(xgBlockB%vecC(1,1)), &
    4786              :           &                                 total_size,                &
    4787              :           &                                 c_loc(divResult%vecC(1,1)))
    4788              : 
    4789              :         if ( present(max_val) ) then
    4790              :           call computeMax_complex(c_loc(divResult%vecC(1,1)), total_size, max_val)
    4791              :         end if
    4792              :         if ( present(min_val) ) then
    4793              :           call computeMin_complex(c_loc(divResult%vecC(1,1)), total_size, min_val)
    4794              :         end if
    4795              :         if ( present(max_elt) ) then
    4796              :           call computeMaxloc_complex_2d(c_loc(divResult%vecC(1,1)), xgBlockA%rows, xgBlockA%cols, c_loc(max_elt))
    4797              :         end if
    4798              :         if ( present(min_elt) ) then
    4799              :           call computeMinloc_complex_2d(c_loc(divResult%vecC(1,1)), xgBlockA%rows, xgBlockA%cols, c_loc(min_elt))
    4800              :         end if
    4801              :       case(SPACE_CR)
    4802              :         ABI_ERROR('Not implemented for SPACE_CR')
    4803              :       end select
    4804              : 
    4805              : #else
    4806              :       ! we shouldn't be here, it means gpu_option was wrongly set to 1 in
    4807              :       ! input parameter file
    4808              : #endif
    4809              : 
    4810        24432 :     else if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    4811              : 
    4812              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    4813              : 
    4814              :       total_size = xgBlockA%rows * xgBlockA%cols
    4815              :       select case(xgBlockA%space)
    4816              :       case(SPACE_R)
    4817              :         xgBlockA__vecR => xgBlockA%vecR
    4818              :         xgBlockB__vecR => xgBlockB%vecR
    4819              :         divResult__vecR => divResult%vecR
    4820              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlockA__vecR,xgBlockB__vecR,divResult__vecR)
    4821              :         do irow = 1, rows
    4822              :           do icol = 1, cols
    4823              :             divResult__vecR(irow,icol) = xgBlockA__vecR(irow,icol)/xgBlockB__vecR(irow,icol)
    4824              :           end do
    4825              :         end do
    4826              :         !FIXME Port this on GPU to avoid copy below ?
    4827              :         !$OMP TARGET UPDATE FROM(divResult__vecR)
    4828              :         if ( present(max_val) ) then
    4829              :           max_val = maxval(dble(divResult%vecR))
    4830              :         end if
    4831              :         if ( present(min_val) ) then
    4832              :           min_val = minval(dble(divResult%vecR))
    4833              :         end if
    4834              :         if ( present(max_elt) ) then
    4835              :           max_elt = maxloc(dble(divResult%vecR(1:xgBlockA%rows,1:xgBlockA%cols)))
    4836              :         end if
    4837              :         if ( present(min_elt) ) then
    4838              :           min_elt = minloc(dble(divResult%vecR(1:xgBlockA%rows,1:xgBlockA%cols)))
    4839              :         end if
    4840              : 
    4841              :       case(SPACE_C)
    4842              :         xgBlockA__vecC => xgBlockA%vecC
    4843              :         xgBlockB__vecC => xgBlockB%vecC
    4844              :         divResult__vecC => divResult%vecC
    4845              : #if !defined FC_LLVM
    4846              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlockA__vecC,xgBlockB__vecC,divResult__vecC)
    4847              :         do irow = 1, rows
    4848              :           do icol = 1, cols
    4849              :             divResult__vecC(irow,icol) = xgBlockA__vecC(irow,icol)/xgBlockB__vecC(irow,icol)
    4850              :           end do
    4851              :         end do
    4852              :         !FIXME Port this on GPU to avoid copy below ?
    4853              :         !$OMP TARGET UPDATE FROM(divResult__vecC)
    4854              : #else
    4855              :         !FIXME LLVM AOMP 16 doesn't support complex division inside OpenMP !?
    4856              :         !$OMP TARGET UPDATE FROM(xgBlockA__vecC,xgBlockB__vecC)
    4857              :         do irow = 1, rows
    4858              :           do icol = 1, cols
    4859              :             divResult__vecC(irow,icol) = xgBlockA__vecC(irow,icol)/xgBlockB__vecC(irow,icol)
    4860              :           end do
    4861              :         end do
    4862              :         !$OMP TARGET UPDATE TO(divResult__vecC)
    4863              : #endif
    4864              :         if ( present(max_val) ) then
    4865              :           max_val = maxval(dble(divResult%vecC))
    4866              :         end if
    4867              :         if ( present(min_val) ) then
    4868              :           min_val = minval(dble(divResult%vecC))
    4869              :         end if
    4870              :         if ( present(max_elt) ) then
    4871              :           max_elt = maxloc(dble(divResult%vecC(1:xgBlockA%rows,1:xgBlockA%cols)))
    4872              :         end if
    4873              :         if ( present(min_elt) ) then
    4874              :           min_elt = minloc(dble(divResult%vecC(1:xgBlockA%rows,1:xgBlockA%cols)))
    4875              :         end if
    4876              :       case(SPACE_CR)
    4877              :         ABI_ERROR('Not implemented for SPACE_CR')
    4878              :       end select
    4879              : 
    4880              : #endif
    4881              : 
    4882              :     else
    4883              : 
    4884        24432 :       select case(xgBlockA%space)
    4885              :       case(SPACE_R)
    4886              :         !$omp parallel do collapse(2) shared(divResult,xgBlockA,xgBlockB) private(icol,irow)
    4887        19620 :         do icol = 1, cols
    4888        66468 :           do irow = 1, rows
    4889        56658 :             divResult%vecR(irow,icol) = xgBlockA%vecR(irow,icol)/xgBlockB%vecR(irow,icol)
    4890              :           end do
    4891              :         end do
    4892              :         !$omp end parallel do
    4893              : 
    4894         9810 :         if ( present(max_val) ) then
    4895        65280 :           max_val = maxval(dble(divResult%vecR))
    4896              :         end if
    4897         9810 :         if ( present(min_val) ) then
    4898        65280 :           min_val = minval(dble(divResult%vecR))
    4899              :         end if
    4900         9810 :         if ( present(max_elt) ) then
    4901        65280 :           max_elt = maxloc(dble(divResult%vecR(1:xgBlockA%rows,1:xgBlockA%cols)))
    4902              :         end if
    4903         9810 :         if ( present(min_elt) ) then
    4904        65280 :           min_elt = minloc(dble(divResult%vecR(1:xgBlockA%rows,1:xgBlockA%cols)))
    4905              :         end if
    4906              : 
    4907              :       case(SPACE_C)
    4908              : 
    4909              :         !$omp parallel do collapse(2) shared(divResult,xgBlockA,xgBlockB) private(icol,irow)
    4910        37240 :         do icol = 1, cols
    4911     32118536 :           do irow = 1, rows
    4912     32103914 :             divResult%vecC(irow,icol) = xgBlockA%vecC(irow,icol)/xgBlockB%vecC(irow,icol)
    4913              :           end do
    4914              :         end do
    4915              :         !$omp end parallel do
    4916              : 
    4917        14622 :         if ( present(max_val) ) then
    4918       109344 :           max_val = maxval(dble(divResult%vecC))
    4919              :         end if
    4920        14622 :         if ( present(min_val) ) then
    4921       109344 :           min_val = minval(dble(divResult%vecC))
    4922              :         end if
    4923        14622 :         if ( present(max_elt) ) then
    4924       109344 :           max_elt = maxloc(dble(divResult%vecC(1:xgBlockA%rows,1:xgBlockA%cols)))
    4925              :         end if
    4926        14622 :         if ( present(min_elt) ) then
    4927       109344 :           min_elt = minloc(dble(divResult%vecC(1:xgBlockA%rows,1:xgBlockA%cols)))
    4928              :         end if
    4929              :       case(SPACE_CR)
    4930        24432 :         ABI_ERROR('Not implemented for SPACE_CR')
    4931              :       end select
    4932              : 
    4933              :     end if ! gpu_option
    4934              : 
    4935        24432 :     call timab(tim_colw_div,2,tsec)
    4936              : 
    4937        24432 :   end subroutine xgBlock_colwiseDivision
    4938              :   !!***
    4939              : 
    4940              :   !!****f* m_xg/xgBlock_scaleR
    4941              :   !!
    4942              :   !! NAME
    4943              :   !! xgBlock_scaleR
    4944              : 
    4945      1538561 :   subroutine xgBlock_scaleR(xgBlock, val, inc)
    4946              : 
    4947              :     type(xgBlock_t) , intent(inout)           :: xgBlock
    4948              :     double precision, intent(in   )           :: val
    4949              :     integer         , intent(in   )           :: inc
    4950              : 
    4951              :     integer      :: i,fact
    4952              :     complex(dp) :: valc
    4953              : 
    4954              :     double precision :: tsec(2)
    4955              : 
    4956      1538561 :     call timab(tim_scale,1,tsec)
    4957              : 
    4958      1538561 :     valc = dcmplx(val,0.0_dp)
    4959              : 
    4960      1538561 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    4961              : 
    4962      1538561 :     if ( xgBlock%ldim .eq. xgBlock%rows ) then
    4963       584452 :       select case(xgBlock%space)
    4964              :       case (SPACE_R,SPACE_CR)
    4965              :         call abi_xscal(fact*xgBlock%ldim*xgBlock%cols/inc, val, xgBlock%vecR, inc, &
    4966       584452 :             gpu_option=xgBlock%gpu_option)
    4967              :       case (SPACE_C)
    4968              :         call abi_xscal(xgBlock%ldim*xgBlock%cols/inc, valc, xgBlock%vecC, inc, &
    4969      1538561 :             gpu_option=xgBlock%gpu_option)
    4970              :       end select
    4971              :     else
    4972              :       !FIXME Do loop that calls scal on each column sequentially, might be improved
    4973            0 :       select case(xgBlock%space)
    4974              :       case (SPACE_R,SPACE_CR)
    4975            0 :         do i=1,xgBlock%cols
    4976              :           call abi_xscal(fact*xgBlock%rows/inc, val, xgBlock%vecR(:,i), inc, &
    4977            0 :               gpu_option=xgBlock%gpu_option)
    4978              :         end do
    4979              :       case (SPACE_C)
    4980            0 :         do i=1,xgBlock%cols
    4981              :           call abi_xscal(xgBlock%rows/inc, valc, xgBlock%vecC(:,i), inc, &
    4982            0 :               gpu_option=xgBlock%gpu_option)
    4983              :         end do
    4984              :       end select
    4985              :     end if
    4986              : 
    4987      1538561 :     call timab(tim_scale,2,tsec)
    4988              : 
    4989      1538561 :   end subroutine xgBlock_scaleR
    4990              :   !!***
    4991              : 
    4992              :   !!****f* m_xg/xgBlock_scaleC
    4993              :   !!
    4994              :   !! NAME
    4995              :   !! xgBlock_scaleC
    4996              : 
    4997            0 :   subroutine xgBlock_scaleC(xgBlock, val, inc)
    4998              : 
    4999              :     type(xgBlock_t), intent(inout)           :: xgBlock
    5000              :     complex(kind=8), intent(in   )           :: val
    5001              :     integer        , intent(in   )           :: inc
    5002              : 
    5003              :     integer :: i
    5004              :     double precision :: tsec(2)
    5005              : 
    5006            0 :     call timab(tim_scale,1,tsec)
    5007              : 
    5008            0 :     if ( xgBlock%ldim .eq. xgBlock%rows ) then
    5009            0 :       select case(xgBlock%space)
    5010              :       case (SPACE_R,SPACE_CR)
    5011            0 :         ABI_ERROR("Scaling real vector with a complex not possible")
    5012              :       case (SPACE_C)
    5013              :         call abi_xscal(xgBlock%ldim*xgBlock%cols/inc, val, xgBlock%vecC, inc, &
    5014            0 :             gpu_option=xgBlock%gpu_option)
    5015              :       end select
    5016              :     else
    5017              :       ! TODO: evaluate if it is really necessary to deal with this case on GPU
    5018            0 :       if (xgBlock%gpu_option/=ABI_GPU_DISABLED) then
    5019            0 :         ABI_BUG("Scaling a xgBlock when xgBlock%ldim != xgBlock%rows is not implemented for GPU. FIX ME if needed.")
    5020              :       end if
    5021            0 :       select case(xgBlock%space)
    5022              :       case (SPACE_R,SPACE_CR)
    5023            0 :         ABI_ERROR("Scaling real vector with a complex not possible")
    5024              :       case (SPACE_C)
    5025            0 :         do i=1,xgBlock%cols
    5026            0 :           call abi_xscal(xgBlock%rows/inc, val, xgBlock%vecC(:,i), inc)
    5027              :         end do
    5028              :       end select
    5029              :     end if
    5030              : 
    5031            0 :     call timab(tim_scale,2,tsec)
    5032              : 
    5033            0 :   end subroutine xgBlock_scaleC
    5034              :   !!***
    5035              : 
    5036              :   !!****f* m_xg/xgBlock_transpose
    5037              :   !!
    5038              :   !! NAME
    5039              :   !! xgBlock_transpose
    5040              : 
    5041            0 :   subroutine xgBlock_transpose(xgBlockI,xgBlockO)
    5042              : 
    5043              :     type(xgBlock_t) , intent(inout) :: xgBlockI,xgBlockO
    5044              :     integer :: nrows,ncols
    5045              : 
    5046            0 :     if (xgBlockI%gpu_option/=ABI_GPU_DISABLED) then
    5047            0 :       ABI_ERROR('Not implemented for GPU')
    5048              :     end if
    5049            0 :     call xgBlock_check_gpu_option(xgBlockI,xgBlockO)
    5050              : 
    5051            0 :     nrows = xgBlockI%rows
    5052            0 :     ncols = xgBlockI%cols
    5053            0 :     if (nrows/=xgBlockO%cols) then
    5054            0 :       ABI_ERROR('nrowsI/=ncolsO')
    5055              :     end if
    5056            0 :     if (ncols/=xgBlockO%rows) then
    5057            0 :       ABI_ERROR('ncolsI/=nrowsO')
    5058              :     end if
    5059              : 
    5060            0 :     select case(xgBlockI%space)
    5061              :     case (SPACE_R)
    5062            0 :       xgBlockO%vecR = TRANSPOSE(xgBlockI%vecR)
    5063              :     case (SPACE_CR)
    5064            0 :       ABI_ERROR("Not implemented")
    5065              :     case (SPACE_C)
    5066            0 :       xgBlockO%vecC = TRANSPOSE(CONJG(xgBlockI%vecC))
    5067              :     end select
    5068              : 
    5069            0 :   end subroutine xgBlock_transpose
    5070              :   !!***
    5071              : 
    5072              :   !!****f* m_xg/xgBlock_r2c
    5073              :   !!
    5074              :   !! NAME
    5075              :   !! xgBlock_r2c
    5076              : 
    5077       693206 :   subroutine xgBlock_r2c(xgBlockR,xgBlockC,nspinor)
    5078              : 
    5079              :     integer         , intent(in) :: nspinor
    5080              :     type(xgBlock_t) , intent(in) :: xgBlockR
    5081              :     type(xgBlock_t) , intent(inout) :: xgBlockC
    5082              :     integer :: nrows,ncols,col
    5083       693206 :     double precision,allocatable :: zeros(:)
    5084              : 
    5085       693206 :     if (xgBlockR%gpu_option/=ABI_GPU_DISABLED) then
    5086            0 :       ABI_ERROR('Not implemented for GPU')
    5087              :     end if
    5088       693206 :     call xgBlock_check_gpu_option(xgBlockR,xgBlockC)
    5089              : 
    5090       693206 :     if (space(xgBlockR)/=SPACE_R) then
    5091            0 :       ABI_ERROR('space(xgBlockR)/=SPACE_R')
    5092              :     end if
    5093       693206 :     if (space(xgBlockC)/=SPACE_C .and. space(xgBLockC)/=SPACE_CR) then
    5094            0 :       ABI_ERROR('space(xgBlockC)/=SPACE_C')
    5095              :     end if
    5096       693206 :     if (space(xgBlockC)==SPACE_CR .and. nspinor/=1) then
    5097            0 :       ABI_ERROR('This should not happen')
    5098              :     end if
    5099              : 
    5100       693206 :     nrows = xgBlockR%rows
    5101       693206 :     ncols = xgBlockR%cols
    5102       693206 :     if (nspinor*nrows/=xgBlockC%rows) then
    5103            0 :       ABI_ERROR('nspinor*nrowsR/=nrowsC')
    5104              :     end if
    5105       693206 :     if (nspinor*ncols/=xgBlockC%cols) then
    5106            0 :       ABI_ERROR('nspinor*ncolsR/=ncolsC')
    5107              :     end if
    5108              : 
    5109       693206 :     if (space(xgBlockC)==SPACE_C) then
    5110      2079618 :       ABI_MALLOC(zeros,(nrows))
    5111      6889934 :       zeros=zero
    5112      6889934 :       do col = 1,ncols
    5113     67489992 :         xgBlockC%vecC(1:nrows,col) = dcmplx(xgBlockR%vecR(1:nrows,col),zeros)
    5114      6889934 :         if (nspinor==2) then
    5115     22317948 :           xgBlockC%vecC(1+nrows:2*nrows,col      ) = dcmplx(zeros,zeros)
    5116     22317948 :           xgBlockC%vecC(1      :  nrows,col+ncols) = dcmplx(zeros,zeros)
    5117     22317948 :           xgBlockC%vecC(1+nrows:2*nrows,col+ncols) = dcmplx(xgBlockR%vecR(1:nrows,col),zeros)
    5118              :         end if
    5119              :       end do
    5120       693206 :       ABI_FREE(zeros)
    5121              :     else ! space(C)==SPACE_CR
    5122            0 :       do col = 1,ncols
    5123            0 :         xgBlockC%vecR(1:2*nrows-1:2,col) = xgBlockR%vecR(1:nrows,col)
    5124            0 :         xgBlockC%vecR(2:2*nrows  :2,col) = zero
    5125              :       end do
    5126              :     end if
    5127              : 
    5128       693206 :   end subroutine xgBlock_r2c
    5129              :   !!***
    5130              : 
    5131              :   !!****f* m_xg/xgBlock_c2r
    5132              :   !!
    5133              :   !! NAME
    5134              :   !! xgBlock_c2r
    5135              : 
    5136          544 :   subroutine xgBlock_c2r(xgBlockC,xgBlockR)
    5137              : 
    5138              :     type(xgBlock_t) , intent(in) :: xgBlockC
    5139              :     type(xgBlock_t) , intent(inout) :: xgBlockR
    5140              :     integer :: nrows,ncols,col
    5141              : 
    5142          544 :     if (xgBlockR%gpu_option/=ABI_GPU_DISABLED) then
    5143            0 :       ABI_ERROR('Not implemented for GPU')
    5144              :     end if
    5145          544 :     call xgBlock_check_gpu_option(xgBlockR,xgBlockC)
    5146              : 
    5147          544 :     if (space(xgBlockR)/=SPACE_R) then
    5148            0 :       ABI_ERROR('space(xgBlockR)/=SPACE_R')
    5149              :     end if
    5150          544 :     if (space(xgBlockC)/=SPACE_C .and. space(xgBLockC)/=SPACE_CR) then
    5151            0 :       ABI_ERROR('space(xgBlockC)/=SPACE_C')
    5152              :     end if
    5153              : 
    5154          544 :     nrows = xgBlockR%rows
    5155          544 :     ncols = xgBlockR%cols
    5156          544 :     if (nrows/=xgBlockC%rows) then
    5157            0 :       ABI_ERROR('nrowsR/=nrowsC')
    5158              :     end if
    5159          544 :     if (ncols/=xgBlockC%cols) then
    5160            0 :       ABI_ERROR('ncolsR/=ncolsC')
    5161              :     end if
    5162              : 
    5163          544 :     if (space(xgBlockC)==SPACE_C) then
    5164         1088 :       do col = 1,ncols
    5165         5440 :         xgBlockR%vecR(1:nrows,col) = dble(xgBlockC%vecC(1:nrows,col))
    5166              :       end do
    5167              :     else ! space(C)==SPACE_CR
    5168            0 :       do col = 1,ncols
    5169            0 :         xgBlockR%vecR(1:nrows,col) = xgBlockC%vecR(1:2*nrows-1:2,col)
    5170              :       end do
    5171              :     end if
    5172              : 
    5173          544 :   end subroutine xgBlock_c2r
    5174              :   !!***
    5175              : 
    5176              :   !!****f* m_xg/xgBlock_getSize
    5177              :   !!
    5178              :   !! NAME
    5179              :   !! xgBlock_getSize
    5180              : 
    5181      6495448 :   subroutine xgBlock_getSize(xgBlock, rows, cols, ldim)
    5182              : 
    5183              :     type(xgBlock_t)  , intent(in   ) :: xgBlock
    5184              :     integer          , intent(  out) :: rows
    5185              :     integer          , intent(  out) :: cols
    5186              :     integer, optional, intent(  out) :: ldim
    5187              : 
    5188      6495448 :     rows = xgBlock%rows
    5189      6495448 :     cols = xgBlock%cols
    5190              : 
    5191      6493701 :     if (present(ldim)) then
    5192            0 :       ldim = xgBlock%ldim
    5193              :     end if
    5194              : 
    5195      6493701 :   end subroutine xgBlock_getSize
    5196              :   !!***
    5197              : 
    5198              :   !!****f* m_xg/xgBlock_get_gpu_option
    5199              :   !!
    5200              :   !! NAME
    5201              :   !! xgBlock_get_gpu_option
    5202              :   !!
    5203              :   !! FUNCTION
    5204              :   !! Getter routine for private variable of xgBlock type
    5205              : 
    5206            0 :   subroutine xgBlock_get_gpu_option(xgBlock, gpu_option)
    5207              : 
    5208              :     type(xgBlock_t)  , intent(in   ) :: xgBlock
    5209              :     integer          , intent(  out) :: gpu_option
    5210              : 
    5211            0 :     gpu_option = xgBlock%gpu_option
    5212              : 
    5213            0 :   end subroutine xgBlock_get_gpu_option
    5214              :   !!***
    5215              : 
    5216              :   !!****f* m_xg/xgBlock_get_communicator
    5217              :   !!
    5218              :   !! NAME
    5219              :   !! xgBlock_get_communicator
    5220              :   !!
    5221              :   !! FUNCTION
    5222              :   !! Getter routine for private variable of xgBlock type
    5223              : 
    5224            0 :   subroutine xgBlock_get_communicator(xgBlock, comm)
    5225              : 
    5226              :     type(xgBlock_t)  , intent(in   ) :: xgBlock
    5227              :     integer          , intent(  out) :: comm
    5228              : 
    5229            0 :     comm = xgBlock%spacedim_comm
    5230              : 
    5231            0 :   end subroutine xgBlock_get_communicator
    5232              :   !!***
    5233              : 
    5234              :   !!****f* m_xg/xgBlock_check
    5235              :   !!
    5236              :   !! NAME
    5237              :   !! xgBlock_check
    5238              : 
    5239     13145970 :   subroutine xgBlock_check(X, Y, fact_col)
    5240              : 
    5241              :     type(xgBlock_t) , intent(in) :: X
    5242              :     type(xgBlock_t) , intent(in) :: Y
    5243              :     integer,optional, intent(in) :: fact_col
    5244              : 
    5245              :     integer :: fact_col_
    5246              : 
    5247     13145970 :     fact_col_ = 1
    5248     13145970 :     if (present(fact_col)) then
    5249      2876146 :       fact_col_ = fact_col
    5250              :     end if
    5251     13145970 :     if (X%space/=Y%space) then
    5252            0 :       ABI_ERROR('X%space/=Y%space')
    5253              :     end if
    5254     13145970 :     if (X%rows/=Y%rows) then
    5255            0 :         ABI_ERROR('X%rows/=Y%rows')
    5256              :     end if
    5257     13145970 :     if (fact_col_*X%cols/=Y%cols) then
    5258            0 :       ABI_ERROR('X%cols/=Y%cols')
    5259              :     end if
    5260              : 
    5261     13145970 :   end subroutine xgBlock_check
    5262              :   !!***
    5263              : 
    5264              :   !!****f* m_xg/xgBlock_check_gpu_option
    5265              :   !!
    5266              :   !! NAME
    5267              :   !! xgBlock_check_gpu_option
    5268              : 
    5269     56997530 :   subroutine xgBlock_check_gpu_option(X, Y)
    5270              : 
    5271              :     type(xgBlock_t) , intent(in) :: X
    5272              :     type(xgBlock_t) , intent(in) :: Y
    5273              : 
    5274     56997530 :     if (X%gpu_option/=Y%gpu_option) then
    5275            0 :       ABI_ERROR('X%gpu_option /= Y%gpu_option')
    5276              :     end if
    5277              : 
    5278     56997530 :   end subroutine xgBlock_check_gpu_option
    5279              :   !!***
    5280              : 
    5281              :   !!****f* m_xg/xgBlock_copy_to_gpu
    5282              :   !!
    5283              :   !! NAME
    5284              :   !! xgBlock_copy_to_gpu
    5285              : 
    5286            0 :   subroutine xgBlock_copy_to_gpu(xgBlock)
    5287              :     type(xgBlock_t), target, intent(in   ) :: xgBlock
    5288              : #if defined(HAVE_GPU) && defined(HAVE_OPENMP_OFFLOAD)
    5289              :     integer(c_size_t) :: size
    5290              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    5291              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:)
    5292              : 
    5293              :     select case(xgBlock%space)
    5294              :     case (SPACE_R,SPACE_CR)
    5295              :       xgBlock__vecR => xgBlock%vecR
    5296              :       !$OMP TARGET UPDATE TO(xgBlock__vecR)
    5297              :     case (SPACE_C)
    5298              :       xgBlock__vecC => xgBlock%vecC
    5299              :       !$OMP TARGET UPDATE TO(xgBlock__vecC)
    5300              :     end select
    5301              : #else
    5302       105746 :     ABI_UNUSED_A(xgBlock)
    5303              : #endif
    5304              : 
    5305            0 :   end subroutine xgBlock_copy_to_gpu
    5306              :   !!***
    5307              : 
    5308              :   !!****f* m_xg/xgBlock_copy_from_gpu
    5309              :   !!
    5310              :   !! NAME
    5311              :   !! xgBlock_copy_from_gpu
    5312              : 
    5313            0 :   subroutine xgBlock_copy_from_gpu(xgBlock)
    5314              :     type(xgBlock_t), target, intent(in   ) :: xgBlock
    5315              : #if defined(HAVE_GPU) && defined(HAVE_OPENMP_OFFLOAD)
    5316              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    5317              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:)
    5318              : 
    5319              :     select case(xgBlock%space)
    5320              :     case (SPACE_R,SPACE_CR)
    5321              :       xgBlock__vecR => xgBlock%vecR
    5322              :       !$OMP TARGET UPDATE FROM(xgBlock__vecR)
    5323              :     case (SPACE_C)
    5324              :       xgBlock__vecC => xgBlock%vecC
    5325              :       !$OMP TARGET UPDATE FROM(xgBlock__vecC)
    5326              :     end select
    5327              : #else
    5328            0 :     ABI_UNUSED_A(xgBlock)
    5329              : #endif
    5330              : 
    5331            0 :   end subroutine xgBlock_copy_from_gpu
    5332              :   !!***
    5333              : 
    5334              :   !!****f* m_xg/xgBlock_reshape
    5335              :   !!
    5336              :   !! NAME
    5337              :   !! xgBlock_reshape
    5338              : 
    5339       819248 :   subroutine xgBlock_reshape(xgBlock,newrows,newcols)
    5340              :     use, intrinsic :: iso_c_binding
    5341              :     type(xgBlock_t), intent(inout) :: xgBlock
    5342              :     integer        , intent(in   ) :: newrows
    5343              :     integer        , intent(in   ) :: newcols
    5344              :     integer :: fact,newshape(2)
    5345              :     type(c_ptr) :: cptr
    5346              : 
    5347       819248 :     if ( xgBlock%rows*xgBlock%cols /= newrows*newcols ) then
    5348            0 :       write(std_out,*) "xgBlock%rows", xgBlock%rows
    5349            0 :       write(std_out,*) "xgBlock%cols", xgBlock%cols
    5350            0 :       write(std_out,*) "newrows", newrows
    5351            0 :       write(std_out,*) "newcols", newcols
    5352            0 :       write(std_out,*) "xgBlock%rows*xgBlock%cols", xgBlock%rows*xgBlock%cols
    5353            0 :       write(std_out,*) "newrows*newcols", newrows*newcols
    5354            0 :       ABI_ERROR("Bad shape")
    5355              :     end if
    5356              : 
    5357              :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    5358              : 
    5359       819248 :     xgBlock%LDim = newrows+( (xgBlock%LDim-xgBlock%rows)* xgBlock%cols)/newcols
    5360       819248 :     xgBlock%rows = newrows
    5361       819248 :     xgBlock%cols = newcols
    5362       819248 :     newshape(1) = newrows
    5363       819248 :     newshape(2) = newcols
    5364      1001528 :     select case(xgBlock%space)
    5365              :     case (SPACE_R,SPACE_CR)
    5366       182280 :       cptr = getClocR(fact*xgBlock%LDim,xgBlock%cols,xgBlock%vecR)
    5367       546840 :       call c_f_pointer(cptr,xgBlock%vecR,newshape)
    5368              :     case (SPACE_C)
    5369       636968 :       cptr = getClocC(xgBlock%LDim,xgBlock%cols,xgBlock%vecC)
    5370      2730152 :       call c_f_pointer(cptr,xgBlock%vecC,newshape)
    5371              :     end select
    5372              : 
    5373       819248 :   end subroutine xgBlock_reshape
    5374              :   !!***
    5375              : 
    5376              :   !!****f* m_xg/xgBlock_reshape_spinor
    5377              :   !!
    5378              :   !! NAME
    5379              :   !! xgBlock_reshape_spinor
    5380              : 
    5381      3513353 :   subroutine xgBlock_reshape_spinor(xgBlock,xgBlock_spinor,nspinor,option)
    5382              :     use iso_c_binding
    5383              :     integer, intent(in   ) :: nspinor,option
    5384              :     type(xgBlock_t), intent(in   ) :: xgBlock
    5385              :     type(xgBlock_t), intent(inout) :: xgBlock_spinor
    5386              : 
    5387              :     integer :: nrows,ncols
    5388              : 
    5389      3513353 :     if (nspinor/=1.and.nspinor/=2) then
    5390            0 :       ABI_ERROR('It should not happen : nspinor must be 1 or 2')
    5391              :     end if
    5392      3513353 :     if (xgBlock%space==SPACE_CR.and.nspinor==2) then
    5393            0 :       ABI_ERROR('It should not happen : space_CR cannot be used with nspinor=2')
    5394              :     end if
    5395              : 
    5396      3513353 :     nrows = rows(xgBlock)
    5397      3513353 :     ncols = cols(xgBlock)
    5398              : 
    5399      3513353 :     if (option==COLS2ROWS) then
    5400      1487706 :       if (modulo(ncols,nspinor)/=0) then
    5401            0 :         ABI_ERROR('nspinor should divide the number of cols')
    5402              :       end if
    5403      1487706 :       call xgBlock_setBlock(xgBlock,xgBlock_spinor,nrows,ncols)
    5404      1487706 :       if (nspinor>1) call xgBlock_reshape(xgBlock_spinor,nrows*nspinor,ncols/nspinor)
    5405      2025647 :     else if (option==ROWS2COLS) then
    5406      2025647 :       if (modulo(nrows,nspinor)/=0) then
    5407            0 :         ABI_ERROR('nspinor should divide the number of rows')
    5408              :       end if
    5409      2025647 :       call xgBlock_setBlock(xgBlock,xgBlock_spinor,nrows,ncols)
    5410      2025647 :       if (nspinor>1) call xgBlock_reshape(xgBlock_spinor,nrows/nspinor,ncols*nspinor)
    5411              :     else
    5412            0 :       ABI_ERROR('bad option value')
    5413              :     end if
    5414              : 
    5415      3513353 :   end subroutine xgBlock_reshape_spinor
    5416              :   !!***
    5417              : 
    5418              :   !!****f* m_xg/xgBlock_free_reshape
    5419              :   !!
    5420              :   !! NAME
    5421              :   !! xgBlock_free_reshape
    5422       976212 :   subroutine xgBlock_free_reshape(xgBlock,newrows,newcols,newldim,new_me_g0)
    5423              :     use iso_c_binding
    5424              :     type(xgBlock_t) , intent(inout) :: xgBlock
    5425              :     integer         , intent(in   ) :: newrows,newcols
    5426              :     integer,optional, intent(in   ) :: newldim
    5427              :     integer,optional, intent(in   ) :: new_me_g0
    5428              : 
    5429              :     integer :: newshape(2)
    5430              :     type(c_ptr) :: cptr
    5431              : 
    5432       976212 :     if (newrows<1.or.newcols<1) then
    5433            0 :       ABI_ERROR("Bad new shape")
    5434              :     end if
    5435              : 
    5436       976212 :     if ( xgBLock%Ldim*xgBlock%cols < newrows*newcols ) then
    5437            0 :       write(std_out,*) "xgBLock%rows", xgBLock%rows
    5438            0 :       write(std_out,*) "xgBlock%cols", xgBlock%cols
    5439            0 :       write(std_out,*) "newrows", newrows
    5440            0 :       write(std_out,*) "newcols", newcols
    5441            0 :       write(std_out,*) "xgBLock%rows*xgBlock%cols", xgBLock%rows*xgBlock%cols
    5442            0 :       write(std_out,*) "newrows*newcols", newrows*newcols
    5443            0 :       ABI_ERROR("Bad shape (ldim*cols<newrows*newcols")
    5444              :     end if
    5445              : 
    5446       976212 :     xgBlock%LDim = newrows
    5447       976212 :     if (present(newldim)) then
    5448            0 :       if (newldim<newrows) then
    5449            0 :         ABI_ERROR("newldim<newrows")
    5450              :       end if
    5451            0 :       if ( xgBLock%Ldim*xgBlock%cols < newldim*newcols ) then
    5452            0 :         ABI_ERROR("Bad shape (ldim*cols<newldim*newcols")
    5453              :       end if
    5454            0 :       xgBlock%LDim = newldim
    5455              :     end if
    5456       976212 :     xgBlock%rows = newrows
    5457       976212 :     xgBlock%cols = newcols
    5458       976212 :     newshape(1)  = newrows
    5459       976212 :     newshape(2)  = newcols
    5460       976212 :     select case(xgBLock%space)
    5461              :     case (SPACE_R)
    5462            0 :       cptr = getClocR(xgBlock%LDim,xgBlock%cols,xgBlock%vecR)
    5463            0 :       call c_f_pointer(cptr,xgBlock%vecR,newshape)
    5464              :     case (SPACE_CR)
    5465       457092 :       cptr = getClocR(2*xgBlock%LDim,xgBlock%cols,xgBlock%vecR)
    5466       457092 :       newshape(1) = 2*newshape(1)
    5467      1371276 :       call c_f_pointer(cptr,xgBlock%vecR,newshape)
    5468       457092 :       if (present(new_me_g0)) then
    5469       247608 :         xgBlock%me_g0=new_me_g0
    5470              :       end if
    5471              :     case (SPACE_C)
    5472       519120 :       cptr = getClocC(xgBlock%LDim,xgBlock%cols,xgBlock%vecC)
    5473      2533572 :       call c_f_pointer(cptr,xgBlock%vecC,newshape)
    5474              :     end select
    5475       976212 :   end subroutine xgBlock_free_reshape
    5476              :   !!***
    5477              : 
    5478              :   !!****f* m_xg/xgBlock_zero
    5479              :   !!
    5480              :   !! NAME
    5481              :   !! xgBlock_zero
    5482              : 
    5483     11725363 :   subroutine xgBlock_zero(xgBlock)
    5484              : 
    5485              :     type(xgBlock_t), intent(inout) :: xgBlock
    5486              : 
    5487              :     integer :: i,fact
    5488              : #if defined HAVE_GPU
    5489              :     integer(C_SIZE_T) :: byte_count
    5490              : #endif
    5491              : 
    5492              : #if defined HAVE_OPENMP_OFFLOAD && !defined HAVE_OPENMP_OFFLOAD_DATASTRUCTURE
    5493              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    5494              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:)
    5495              :     integer :: rows,cols,iblock,jblock
    5496              : #endif
    5497              :     double precision :: tsec(2)
    5498              : 
    5499     11725363 :     call timab(tim_zero,1,tsec)
    5500              : 
    5501     11725363 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    5502              : 
    5503     11725363 :     if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    5504              : 
    5505              : #if defined HAVE_GPU && defined HAVE_KOKKOS
    5506              :       select case(xgBlock%space)
    5507              :       case (SPACE_R,SPACE_CR)
    5508              :         byte_count = fact * xgBlock%ldim * xgBlock%cols * dp
    5509              :         call gpu_memset(c_loc(xgBlock%vecR), 0, byte_count)
    5510              :       case (SPACE_C)
    5511              :         byte_count = xgBlock%ldim * xgBlock%cols * 2 * dp ! Note the factor 2, needed here!
    5512              :         call gpu_memset(c_loc(xgBlock%vecC), 0, byte_count)
    5513              :       end select
    5514              : #endif
    5515              : 
    5516     11725363 :     else if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    5517              : 
    5518              : #if defined HAVE_OPENMP_OFFLOAD
    5519              :       select case(xgBlock%space)
    5520              :       case (SPACE_R,SPACE_CR)
    5521              :         call gpu_set_to_zero(xgBlock%vecR, int(fact, c_size_t) * xgBlock%ldim * xgBlock%cols)
    5522              :       case (SPACE_C)
    5523              :         call gpu_set_to_zero_complex(xgBlock%vecC, int(xgBlock%ldim, c_size_t) * xgBlock%cols)
    5524              :       end select
    5525              : #endif
    5526              : 
    5527              :     else
    5528              : 
    5529     15398816 :       select case(xgBlock%space)
    5530              :       case (SPACE_R,SPACE_CR)
    5531              :         !$omp parallel do
    5532     20588007 :         do i = 1, xgBlock%cols
    5533   1592517743 :           xgBlock%vecR(:,i) = 0.d0
    5534              :         end do
    5535              :       case (SPACE_C)
    5536              :         !$omp parallel do
    5537     52842739 :         do i = 1, xgBlock%cols
    5538   1315086475 :           xgBlock%vecC(:,i) = dcmplx(0.d0)
    5539              :         end do
    5540              :       end select
    5541              :     end if
    5542              : 
    5543     11725363 :     call timab(tim_zero,2,tsec)
    5544              : 
    5545     11725363 :   end subroutine xgBlock_zero
    5546              :   !!***
    5547              : 
    5548              :   !!****f* m_xg/xgBlock_ones
    5549              :   !!
    5550              :   !! NAME
    5551              :   !! xgBlock_ones
    5552              : 
    5553            0 :   subroutine xgBlock_ones(xgBlock)
    5554              : 
    5555              :     type(xgBlock_t), intent(inout) :: xgBlock
    5556              : 
    5557              :     integer :: i,fact
    5558              : #if defined HAVE_GPU
    5559              :     integer(C_SIZE_T) :: byte_count
    5560              : #endif
    5561              : 
    5562              : #if defined HAVE_OPENMP_OFFLOAD
    5563              :     complex(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecC(:,:)
    5564              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:)
    5565              :     integer :: rows,cols,iblock,jblock
    5566              : #endif
    5567              : 
    5568            0 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    5569              : 
    5570            0 :     if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    5571              : 
    5572              : #if defined HAVE_OPENMP_OFFLOAD
    5573              :       rows = xgBlock%rows; cols = xgBlock%cols
    5574              :       select case(xgBlock%space)
    5575              :       case (SPACE_R,SPACE_CR)
    5576              :         xgBlock__vecR => xgBlock%vecR
    5577              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlock__vecR)
    5578              :         do iblock = 1, cols
    5579              :           do jblock = 1, fact * rows
    5580              :             xgBlock__vecR(jblock,iblock) = 1.d0
    5581              :           end do
    5582              :         end do
    5583              :       case (SPACE_C)
    5584              :         xgBlock__vecC => xgBlock%vecC
    5585              :         !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO COLLAPSE(2) MAP(to:xgBlock__vecC)
    5586              :         do iblock = 1, cols
    5587              :           do jblock = 1, fact * rows
    5588              :             xgBlock__vecC(jblock,iblock) = dcmplx(1.d0,0)
    5589              :           end do
    5590              :         end do
    5591              :       end select
    5592              : #endif
    5593              : 
    5594              :     else
    5595              : 
    5596            0 :       select case(xgBlock%space)
    5597              :       case (SPACE_R,SPACE_CR)
    5598              :         !$omp parallel do
    5599            0 :         do i = 1, xgBlock%cols
    5600            0 :           xgBlock%vecR(:,i) = 1.d0
    5601              :         end do
    5602              :       case (SPACE_C)
    5603              :         !$omp parallel do
    5604            0 :         do i = 1, xgBlock%cols
    5605            0 :           xgBlock%vecC(:,i) = dcmplx(1.d0)
    5606              :         end do
    5607              :       end select
    5608              :     end if
    5609              : 
    5610            0 :   end subroutine xgBlock_ones
    5611              :   !!***
    5612              : 
    5613              :   !!****f* m_xg/xgBlock_zerotri
    5614              :   !!
    5615              :   !! NAME
    5616              :   !! xgBlock_zerotri
    5617              : 
    5618        51082 :   subroutine xgBlock_zerotri(xgBlockA,uplo)
    5619              :     use iso_c_binding
    5620              :     type(xgBlock_t), intent(inout) :: xgBlockA
    5621              :     character, intent(in) :: uplo
    5622              :     integer :: j
    5623              :     integer :: i
    5624              :     integer :: nn
    5625              :     integer :: col
    5626              : 
    5627        51082 :     nn = xgBlockA%cols
    5628        51082 :     if (xgBlockA%rows/=nn) then
    5629            0 :       ABI_ERROR('rows should be equal to cols!')
    5630              :     end if
    5631              : 
    5632        51082 :     if (xgBlockA%gpu_option==ABI_GPU_KOKKOS) then
    5633            0 :       ABI_ERROR('Not implemented for GPU Kokkos')
    5634              :     end if
    5635              :     if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    5636              :       call xgBlock_copy_from_gpu(xgBlockA) !FIXME Avoid that transfer
    5637              :     end if
    5638              : 
    5639        51082 :     select case(uplo)
    5640              :     case ('u','U')
    5641        51082 :       select case(xgBlockA%space)
    5642              :       case (SPACE_R)
    5643       341204 :         do j = 1, nn
    5644       310224 :           col = (j*(j-1))/2
    5645      1940556 :           do i = j+1,nn
    5646      1909576 :             xgBlockA%vecR(i,j) = zero
    5647              :           end do
    5648              :         end do
    5649              :       case (SPACE_CR)
    5650            0 :         ABI_ERROR("Not implemented")
    5651              :       case (SPACE_C)
    5652       248528 :         do j = 1, nn
    5653       177344 :           col = (j*(j-1))/2
    5654      1070446 :           do i = j+1,nn
    5655      1050344 :             xgBlockA%vecC(i,j) = czero
    5656              :           end do
    5657              :         end do
    5658              :       end select
    5659              : 
    5660              :     case ('l','L')
    5661            0 :       select case(xgBlockA%space)
    5662              :       case (SPACE_R)
    5663            0 :         do j = 1, nn
    5664            0 :           col = ((2*xgBlockA%cols-j)*(j-1))/2
    5665            0 :           do i = 1, j-1
    5666            0 :             xgBlockA%vecR(i,j) = zero
    5667              :           end do
    5668              :         end do
    5669              :       case (SPACE_CR)
    5670            0 :         ABI_ERROR("Not implemented")
    5671              :       case (SPACE_C)
    5672            0 :         do j = 1, nn
    5673            0 :           col = ((2*xgBlockA%cols-j)*(j-1))/2
    5674            0 :           do i = 1, j-1
    5675            0 :             xgBlockA%vecC(i,j) = czero
    5676              :           end do
    5677              :         end do
    5678              :       end select
    5679              :     case default
    5680        51082 :       ABI_ERROR("Error for zerotri")
    5681              :     end select
    5682              : 
    5683              :     if (xgBlockA%gpu_option==ABI_GPU_OPENMP) then
    5684              :       call xgBlock_copy_to_gpu(xgBlockA) !FIXME Avoid that transfer
    5685              :     end if
    5686              : 
    5687        51082 :   end subroutine xgBlock_zerotri
    5688              :   !!***
    5689              : 
    5690              :   !!****f* m_xg/xgBlock_zero_im_g0
    5691              :   !!
    5692              :   !! NAME
    5693              :   !! xgBlock_zero_im_g0
    5694              : 
    5695      7890750 :   subroutine xgBlock_zero_im_g0(xgBlock)
    5696              : 
    5697              :     type(xgBlock_t), intent(inout) :: xgBlock
    5698              : 
    5699              :     integer :: ii,cols
    5700              : 
    5701              : #if defined HAVE_OPENMP_OFFLOAD
    5702              :     real(dp), ABI_CONTIGUOUS pointer :: xgBlock__vecR(:,:)
    5703              : #endif
    5704              :     double precision :: tsec(2)
    5705              : 
    5706      7890750 :     call timab(tim_zero_im_g0,1,tsec)
    5707      7890750 :     if (xgBlock%space==SPACE_CR) then
    5708              : 
    5709       714691 :       cols = xgBlock%cols
    5710              : 
    5711       714691 :       if (xgBlock%me_g0<0) then
    5712            0 :         ABI_ERROR("xgBlock me_g0 is not initialized")
    5713       714691 :       else if (xgBlock%me_g0==1) then
    5714              : 
    5715       117942 :         if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    5716              : 
    5717            0 :           ABI_ERROR('Not implemented')
    5718              : 
    5719       117942 :         else if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    5720              : 
    5721              : #if defined HAVE_OPENMP_OFFLOAD
    5722              :           xgBlock__vecR => xgBlock%vecR
    5723              :           !$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO MAP(to:xgBlock__vecR)
    5724              :           do ii = 1, cols
    5725              :             xgBlock__vecR(2,ii) = zero
    5726              :           end do
    5727              : #endif
    5728              : 
    5729              :         else
    5730              : 
    5731              :           !$omp parallel do
    5732      2714188 :           do ii = 1, cols
    5733      2714188 :             xgBlock%vecR(2,ii) = zero
    5734              :           end do
    5735              : 
    5736              :         end if ! gpu_option
    5737              : 
    5738              :       end if ! me_g0>=0
    5739              :     end if ! SPACE_CR
    5740      7890750 :     call timab(tim_zero_im_g0,2,tsec)
    5741              : 
    5742      7890750 :   end subroutine xgBlock_zero_im_g0
    5743              :   !!***
    5744              : 
    5745              :   !!****f* m_xg/xgBlock_invert
    5746              :   !!
    5747              :   !! NAME
    5748              :   !! xgBlock_invert
    5749              : 
    5750            0 :   subroutine xgBlock_invert(xgBlockA,xgBlockW,xg_input)
    5751              : 
    5752              :     type(xgBlock_t), intent(inout) :: xgBlockA,xgblockW
    5753              :     type(xgBlock_t), optional,intent(in) :: xg_input
    5754              : 
    5755              :     integer :: nn,nrows,info,ldim
    5756            0 :     integer,allocatable :: ipiv(:)
    5757              :     double precision :: tsec(2)
    5758              : 
    5759            0 :     call timab(tim_invert,1,tsec)
    5760              : 
    5761            0 :     if (xgBlockA%gpu_option/=ABI_GPU_DISABLED) then
    5762            0 :       ABI_ERROR('Not implemented for GPU')
    5763              :     end if
    5764            0 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    5765            0 :     if (present(xg_input)) then
    5766            0 :       call xgBlock_check_gpu_option(xgBlockA,xg_input)
    5767              :     end if
    5768              : 
    5769            0 :     call xgBlock_getsize(xgBlockA,nrows,nn,ldim=ldim)
    5770            0 :     if (nrows/=nn) then
    5771            0 :       ABI_ERROR('nrows/=ncols')
    5772              :     end if
    5773            0 :     if (cols(xgBlockW)/=nn) then
    5774            0 :       ABI_ERROR('cols(xgBlockW)/=ncols')
    5775              :     end if
    5776            0 :     if (rows(xgBlockW)/=nn) then
    5777            0 :       ABI_ERROR('rows(xgBlockW)/=nrows')
    5778              :     end if
    5779              : 
    5780            0 :     if (present(xg_input)) then
    5781            0 :       if (cols(xg_input)/=nn) then
    5782            0 :         ABI_ERROR('cols(xgBlockB)/=ncols')
    5783              :       end if
    5784            0 :       if (rows(xg_input)/=nn) then
    5785            0 :         ABI_ERROR('rows(xgBlockB)/=nrows')
    5786              :       end if
    5787            0 :       call xgBlock_copy(xg_input,xgBlockA)
    5788              :     end if
    5789              : 
    5790            0 :     ABI_MALLOC(ipiv,(nn))
    5791              : 
    5792            0 :     select case(xgBlockA%space)
    5793              :     case (SPACE_R)
    5794            0 :       call DGETRF(nn,nn,xgBlockA%vecR,ldim,ipiv,info)
    5795            0 :       if (info==0) then
    5796            0 :         call DGETRI(nn,xgBlockA%vecR,ldim,ipiv,xgBlockW%vecR,nn,info)
    5797              :       else
    5798            0 :         ABI_ERROR('info/=0 : something bad happened in xgetrf')
    5799              :       end if
    5800              :     case (SPACE_CR)
    5801            0 :       ABI_ERROR("Not implemented")
    5802              :       !call DGETRF(nn,nn,xgBlockA%vecR,ldim,ipiv,info)
    5803              :       !if (info==0) then
    5804              :       !  call DGETRI(nn,xgBlockA%vecR,ldim,ipiv,xgBlockW%vecR,nn,info)
    5805              :       !else
    5806              :       !  ABI_ERROR('info/=0 : something bad happened in xgetrf')
    5807              :       !end if
    5808              :     case (SPACE_C)
    5809            0 :       call ZGETRF(nn,nn,xgBlockA%vecC,ldim,ipiv,info)
    5810            0 :       if (info==0) then
    5811            0 :         call ZGETRI(nn,xgBlockA%vecC,ldim,ipiv,xgBlockW%vecC,nn,info)
    5812              :       else
    5813            0 :         ABI_ERROR('info/=0 : something bad happened in xgetrf')
    5814              :       end if
    5815              :     end select
    5816              : 
    5817            0 :     ABI_FREE(ipiv)
    5818              : 
    5819            0 :     if (info/=0) then
    5820            0 :       ABI_ERROR('info/=0 : something bad happened in xgetri')
    5821              :     end if
    5822              : 
    5823            0 :     call timab(tim_invert,2,tsec)
    5824              : 
    5825            0 :   end subroutine xgBlock_invert
    5826              :   !!***
    5827              : 
    5828              :   !!****f* m_xg/xgBlock_invert_sy
    5829              :   !!
    5830              :   !! NAME
    5831              :   !! xgBlock_invert_sy
    5832              : 
    5833         1747 :   subroutine xgBlock_invert_sy(xgBlockA,xgBlockW,xg_input)
    5834              : 
    5835              :     type(xgBlock_t), intent(inout)       :: xgBlockA,xgblockW
    5836              :     type(xgBlock_t), optional,intent(in) :: xg_input
    5837              : 
    5838              :     integer :: nn,nrows,ldim,info
    5839              :     integer :: ii,jj
    5840         1747 :     integer,allocatable :: ipiv(:)
    5841              :     double precision :: tsec(2)
    5842              : 
    5843         1747 :     call timab(tim_invert_sy,1,tsec)
    5844              : 
    5845         1747 :     if (xgBlockA%gpu_option/=ABI_GPU_DISABLED) then
    5846            0 :       ABI_ERROR('Not implemented for GPU')
    5847              :     end if
    5848         1747 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockW)
    5849         1747 :     if (present(xg_input)) then
    5850          207 :       call xgBlock_check_gpu_option(xgBlockA,xg_input)
    5851              :     end if
    5852              : 
    5853         1747 :     call xgBlock_getsize(xgBlockA,nrows,nn,ldim=ldim)
    5854         1747 :     if (nrows/=nn) then
    5855            0 :       ABI_ERROR('nrows/=ncols')
    5856              :     end if
    5857         1747 :     if (cols(xgBlockW)/=nn) then
    5858            0 :       ABI_ERROR('cols(xgBlockW)/=ncols')
    5859              :     end if
    5860         1747 :     if (rows(xgBlockW)/=nn) then
    5861            0 :       ABI_ERROR('rows(xgBlockW)/=nrows')
    5862              :     end if
    5863              : 
    5864         1747 :     if (present(xg_input)) then
    5865          207 :       if (cols(xg_input)/=nn) then
    5866            0 :         ABI_ERROR('cols(xg_input)/=ncols')
    5867              :       end if
    5868          207 :       if (rows(xg_input)/=nn) then
    5869            0 :         ABI_ERROR('rows(xg_input)/=nrows')
    5870              :       end if
    5871          207 :       call xgBlock_copy(xg_input,xgBlockA)
    5872              :     end if
    5873              : 
    5874         5241 :     ABI_MALLOC(ipiv,(nn))
    5875              : 
    5876         2450 :     select case(xgBlockA%space)
    5877              :     case (SPACE_R)
    5878          703 :       call DSYTRF('U',nn,xgBlockA%vecR,ldim,ipiv,xgBlockW%vecR,nn,info)
    5879          703 :       if (info==0) then
    5880          703 :         call DSYTRI('U',nn,xgBlockA%vecR,ldim,ipiv,xgBlockW%vecR,info)
    5881          703 :         if (info/=0) then
    5882            0 :           ABI_ERROR('info/=0 : something bad happened in dsytri')
    5883              :         end if
    5884              :       else
    5885            0 :         ABI_ERROR('info/=0 : something bad happened in dsytrf')
    5886              :       end if
    5887              :       ! complete the matrix
    5888         6377 :       do ii=1, nn
    5889        26686 :         do jj=1, ii-1
    5890        25983 :            xgBlockA%vecR(ii,jj) = xgBlockA%vecR(jj,ii)
    5891              :         end do
    5892              :       end do
    5893              :     case (SPACE_CR)
    5894            0 :       ABI_ERROR("Not implemented")
    5895              :     case (SPACE_C)
    5896         1044 :       call ZHETRF('U',nn,xgBlockA%vecC,ldim,ipiv,xgBlockW%vecC,nn,info)
    5897         1044 :       if (info==0) then
    5898         1044 :         call ZHETRI('U',nn,xgBlockA%vecC,ldim,ipiv,xgBlockW%vecC,info)
    5899         1044 :         if (info/=0) then
    5900            0 :           ABI_ERROR('info/=0 : something bad happened in zhetri')
    5901              :         end if
    5902              :       else
    5903            0 :         ABI_ERROR('info/=0 : something bad happened in zhetrf')
    5904              :       end if
    5905              :       ! complete the matrix
    5906        11163 :       do ii=1, nn
    5907        38898 :         do jj=1, ii-1
    5908        37854 :            xgBlockA%vecC(ii,jj) = CONJG(xgBlockA%vecC(jj,ii))
    5909              :         end do
    5910              :       end do
    5911              :     end select
    5912              : 
    5913         1747 :     ABI_FREE(ipiv)
    5914              : 
    5915         1747 :     call timab(tim_invert_sy,2,tsec)
    5916              : 
    5917         1747 :   end subroutine xgBlock_invert_sy
    5918              :   !!***
    5919              : 
    5920              :   !!****f* m_xg/xgBlock_invert_tri
    5921              :   !!
    5922              :   !! NAME
    5923              :   !! xgBlock_invert_tri
    5924              : 
    5925        51082 :   subroutine xgBlock_invert_tri(uplo,diag,xgBlock)
    5926              : 
    5927              :     type(xgBlock_t), intent(inout) :: xgBlock
    5928              :     character, intent(in) :: uplo,diag
    5929              : 
    5930              :     integer :: info
    5931              :     double precision :: tsec(2)
    5932              : 
    5933        51082 :     call timab(tim_invertri,1,tsec)
    5934              : 
    5935        51082 :     if (xgBlock%rows/=xgBlock%cols) then
    5936            0 :       ABI_ERROR('nrows/=ncols')
    5937              :     end if
    5938              : 
    5939        51082 :     if (xgBlock%gpu_option==ABI_GPU_KOKKOS) then
    5940            0 :       ABI_ERROR('Not implemented for GPU Kokkos')
    5941              :     end if
    5942              :     if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    5943              :       call xgBlock_copy_from_gpu(xgBlock) !FIXME Avoid that transfer
    5944              :     end if
    5945              : 
    5946        82062 :     select case(xgBlock%space)
    5947              :     case (SPACE_R)
    5948        30980 :       call DTRTRI(uplo,diag,xgBlock%rows,xgBlock%vecR,xgBlock%LDim,info)
    5949              :     case (SPACE_CR)
    5950            0 :       ABI_ERROR("Not implemented")
    5951              :     case (SPACE_C)
    5952        51082 :       call ZTRTRI(uplo,diag,xgBlock%rows,xgBlock%vecC,xgBlock%LDim,info)
    5953              :     end select
    5954              : 
    5955              :     if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    5956              :       call xgBlock_copy_to_gpu(xgBlock) !FIXME Avoid that transfer
    5957              :     end if
    5958              : 
    5959        51082 :     if (info/=0) then
    5960            0 :       ABI_ERROR('info/=0 : something bad happened in xtrtri')
    5961              :     end if
    5962              : 
    5963        51082 :     call timab(tim_invertri,2,tsec)
    5964              : 
    5965        51082 :   end subroutine xgBlock_invert_tri
    5966              :   !!***
    5967              : 
    5968              :   !!****f* m_xg/xgBlock_yxpa
    5969              :   !!
    5970              :   !! NAME
    5971              :   !! xgBlock_yxpa
    5972              : 
    5973            0 :   subroutine xgBlock_yxpa(xgBlockA,xgBlockB,aa)
    5974              : 
    5975              :     double precision,intent(in) :: aa
    5976              :     type(xgBlock_t), intent(in) :: xgBlockA
    5977              :     type(xgBlock_t), intent(inout) :: xgBlockB
    5978              : 
    5979              :     integer :: nrows
    5980              : 
    5981            0 :     if (xgBlockA%gpu_option/=ABI_GPU_DISABLED) then
    5982            0 :       ABI_ERROR('Not implemented for GPU')
    5983              :     end if
    5984            0 :     call xgBlock_check_gpu_option(xgBlockA,xgBlockB)
    5985              : 
    5986            0 :     nrows = rows(xgBlockA)
    5987              : 
    5988            0 :     select case(xgBlockA%space)
    5989              :     case (SPACE_R)
    5990            0 :       xgBlockB%vecR(1:nrows,:) = xgBlockA%vecR(1:nrows,:) + aa
    5991              :     case (SPACE_CR)
    5992            0 :       xgBlockB%vecR(1:2*nrows,:) = xgBlockA%vecR(1:2*nrows,:) + aa
    5993              :     case (SPACE_C)
    5994            0 :       xgBlockB%vecC(1:nrows,:) = xgBlockA%vecC(1:nrows,:) + aa*(1.0d0,1.0d0)
    5995              :     end select
    5996              : 
    5997            0 :   end subroutine xgBlock_yxpa
    5998              :   !!***
    5999              : 
    6000              :   !!****f* m_xg/xgBlock_one
    6001              :   !!
    6002              :   !! NAME
    6003              :   !! xgBlock_one
    6004              : 
    6005            0 :   subroutine xgBlock_one(xgBlock)
    6006              : 
    6007              :     type(xgBlock_t), intent(inout) :: xgBlock
    6008              :     integer :: i
    6009              : 
    6010            0 :     select case(xgBlock%space)
    6011              :     case (SPACE_R)
    6012              :       !$omp parallel do
    6013            0 :       do i = 1, min(xgBlock%rows,xgBlock%cols)
    6014            0 :         xgBlock%vecR(i,i) = 1.d0
    6015              :       end do
    6016              :     case (SPACE_CR)
    6017              :       !$omp parallel do
    6018            0 :       do i = 1, min(2*xgBlock%rows,xgBlock%cols)
    6019            0 :         xgBlock%vecR(2*i-1,i) = 1.d0
    6020              :       end do
    6021              :     case (SPACE_C)
    6022              :       !$omp parallel do
    6023            0 :       do i = 1, min(xgBlock%rows,xgBlock%cols)
    6024            0 :         xgBlock%vecC(i,i) = dcmplx(1.d0)
    6025              :       end do
    6026              :     end select
    6027              : 
    6028            0 :   end subroutine xgBlock_one
    6029              :   !!***
    6030              : 
    6031              :   !!****f* m_xg/xgBlock_colwiseRandom
    6032              :   !!
    6033              :   !! NAME
    6034              :   !! xgBlock_colwiseRandom
    6035              : 
    6036           18 :   subroutine xgBlock_colwiseRandom(xgBlock, my_rank, jcol)
    6037              : 
    6038              :     type(xgBlock_t), intent(inout) :: xgBlock
    6039              :     integer, intent(in) :: my_rank ! mpi-parallel safe seed
    6040              :     integer, intent(in) :: jcol
    6041              : 
    6042              :     type(xgBlock_t) :: xgBlock_part
    6043              :     real(dp) :: re, reim(2)
    6044              :     real(dp) :: norm2_vec
    6045              :     integer :: tid, seed_size, i, n, fact
    6046           18 :     integer, allocatable :: seed(:)
    6047              :     complex(kind=c_double_complex), ABI_CONTIGUOUS pointer :: vecC(:) => null()
    6048              :     real(kind=c_double), ABI_CONTIGUOUS pointer:: vecR(:) => null()
    6049              : 
    6050           18 :     if (jcol > xgBlock%cols) then
    6051            0 :         ABI_ERROR('given column is out of block')
    6052              :     end if
    6053              : 
    6054           18 :     tid = 0
    6055           18 :     n = xgBlock%rows
    6056           18 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    6057              : 
    6058           18 :     if (xgBlock%gpu_option == ABI_GPU_OPENMP) then
    6059            0 :         call xgBlock_setBlock(xgBlock, xgBlock_part, n, 1, fcol=jcol)
    6060            0 :         call xgBlock_copy_from_gpu(xgBlock_part)
    6061              :     end if
    6062              : 
    6063              :     ! Each thread each MPI process maintains its own seed
    6064           18 :     select case(xgBlock%space)
    6065              :     case (SPACE_R,SPACE_CR)
    6066            0 :         vecR => xgBlock%vecR(1:fact*n,jcol) ! contiguous in memory
    6067              :         !$omp parallel default(none) &
    6068              :         !$omp private(tid, seed, re, i, seed_size) &
    6069              :         !$omp shared(vecR, my_rank, n)
    6070            0 :             call random_seed(size=seed_size)
    6071            0 :             ABI_MALLOC(seed, (seed_size))
    6072            0 :             tid = xomp_get_thread_num()
    6073            0 :             seed = 123456 + 1000*my_rank + 97*tid + (/ (i, i=1,seed_size) /)
    6074            0 :             call random_seed(put=seed)
    6075              :             ! Avoid multiple threads modify the same RNG state race condition
    6076              :             ! execute each iteration i by exactly one thread
    6077              :             !$omp do
    6078            0 :             do i=1,n
    6079            0 :                 call random_number(re)
    6080            0 :                 vecR(i) = merge(1.d0, -1.d0, re>=0.5d0)
    6081              :             end do
    6082              :             !$omp end do
    6083            0 :             ABI_FREE(seed)
    6084              :         !$omp end parallel
    6085              :     case (SPACE_C)
    6086           18 :         vecC => xgBlock%vecC(:,jcol) ! contiguous in memory
    6087              :         !$omp parallel default(none) &
    6088              :         !$omp private(tid, seed, reim, i, seed_size) &
    6089              :         !$omp shared(vecC, my_rank, n)
    6090           18 :             call random_seed(size=seed_size)
    6091           54 :             ABI_MALLOC(seed, (seed_size))
    6092           18 :             tid = xomp_get_thread_num()
    6093          612 :             seed = 123456 + 1000*my_rank + 97*tid + (/ (i, i=1,seed_size) /)
    6094           18 :             call random_seed(put=seed)
    6095              :             !$omp do
    6096        69984 :             do i=1,n
    6097        69966 :                 call random_number(reim)
    6098        69984 :                 vecC(i) = dcmplx(reim(1)-0.5_dp, reim(2)-0.5_dp) ! zero mean
    6099              :             end do
    6100              :             !$omp end do
    6101           18 :             ABI_FREE(seed)
    6102              :         !$omp end parallel
    6103        69984 :         norm2_vec = sum(conjg(vecC)*vecC)
    6104        70002 :         vecC = vecC / sqrt(real(norm2_vec, dp))
    6105              :     end select
    6106              : 
    6107              :     if (xgBlock%gpu_option == ABI_GPU_OPENMP) then
    6108              :         call xgBlock_copy_to_gpu(xgBlock_part)
    6109              :     end if
    6110              : 
    6111           36 :   end subroutine xgBlock_colwiseRandom
    6112              :   !!***
    6113              : 
    6114              :   !!****f* m_xg/xgBlock_colwiseRandomGaussian
    6115              :   !!
    6116              :   !! NAME
    6117              :   !! xgBlock_colwiseRandomGaussian
    6118              : 
    6119         3474 :   subroutine xgBlock_colwiseRandomGaussian(xgBlock, my_rank, jcol)
    6120              : 
    6121              :     type(xgBlock_t), intent(inout) :: xgBlock
    6122              :     integer, intent(in) :: my_rank ! mpi-parallel safe seed
    6123              :     integer, intent(in) :: jcol
    6124              : 
    6125              :     type(xgBlock_t) :: xgBlock_part
    6126              :     real(dp) :: u1, u2, r, theta
    6127              :     complex(dp) :: z
    6128              :     integer :: tid, seed_size, i, n
    6129         3474 :     integer, allocatable :: seed(:)
    6130              :     complex(kind=c_double_complex), ABI_CONTIGUOUS pointer :: vecC(:) => null()
    6131              : 
    6132         3474 :     if (jcol > xgBlock%cols) then
    6133            0 :         ABI_ERROR('given column is out of block')
    6134              :     end if
    6135              : 
    6136         3474 :     tid = 0
    6137         3474 :     n = xgBlock%rows
    6138              : 
    6139         3474 :     if (xgBlock%gpu_option == ABI_GPU_OPENMP) then
    6140            0 :         call xgBlock_setBlock(xgBlock, xgBlock_part, n, 1, fcol=jcol)
    6141            0 :         call xgBlock_copy_from_gpu(xgBlock_part)
    6142              :     end if
    6143              : 
    6144              :     ! Each thread each MPI process maintains its own seed
    6145         3474 :     select case(xgBlock%space)
    6146              :     case (SPACE_R)
    6147            0 :         ABI_ERROR('Not implemented for SPACE_R')
    6148              :     case (SPACE_C)
    6149         3474 :         vecC => xgBlock%vecC(:,jcol) ! contiguous in memory
    6150              :         !$omp parallel default(none) &
    6151              :         !$omp private(tid, seed, u1, u2, r, theta, z, i, seed_size) &
    6152              :         !$omp shared(vecC, my_rank, n)
    6153         3474 :             call random_seed(size=seed_size)
    6154        10422 :             ABI_MALLOC(seed, (seed_size))
    6155         3474 :             tid = xomp_get_thread_num()
    6156       118116 :             seed = 123456 + 1000*my_rank + 97*tid + (/ (i, i=1,seed_size) /)
    6157         3474 :             call random_seed(put=seed)
    6158              :             !$omp do
    6159       670482 :             do i=1,n
    6160       667008 :                 call random_number(u1)
    6161       667008 :                 call random_number(u2)
    6162       667008 :                 if (u1 == 0.0d0) u1 = 1.0e-12
    6163       667008 :                 r = sqrt(-2.d0 * log(u1))
    6164       667008 :                 theta = 2.d0 * PI * u2
    6165       667008 :                 z = (r*cos(theta)+(0.d0,1.d0)*r*sin(theta))/sqrt(2.d0)
    6166       670482 :                 vecC(i) = dcmplx(real(z), aimag(z)) ! zero mean
    6167              :             end do
    6168              :             !$omp end do
    6169         3474 :             ABI_FREE(seed)
    6170              :         !$omp end parallel
    6171              :     case (SPACE_CR)
    6172         3474 :         ABI_ERROR('Not implemented for SPACE_CR')
    6173              :     end select
    6174              : 
    6175              :     if (xgBlock%gpu_option == ABI_GPU_OPENMP) then
    6176              :         call xgBlock_copy_to_gpu(xgBlock_part)
    6177              :     end if
    6178              : 
    6179         6948 :   end subroutine xgBlock_colwiseRandomGaussian
    6180              :   !!***
    6181              : 
    6182              :   !!****f* m_xg/xgBlock_colwiseRandomRademacher
    6183              :   !!
    6184              :   !! NAME
    6185              :   !! xgBlock_colwiseRandomRademacher
    6186              :   !!
    6187              :   !! FUNCTION
    6188              :   !! Every entry has |z_j| = 1 and E[z_j] = 0
    6189              : 
    6190           90 :   subroutine xgBlock_colwiseRandomRademacher(xgBlock, my_rank, jcol)
    6191              : 
    6192              :     type(xgBlock_t), intent(inout) :: xgBlock
    6193              :     integer, intent(in) :: my_rank ! mpi-parallel safe seed
    6194              :     integer, intent(in) :: jcol
    6195              : 
    6196              :     type(xgBlock_t) :: xgBlock_part
    6197              :     real(dp) :: u
    6198              :     complex(dp) :: meanz
    6199              :     real(dp)    :: norm2_, variance
    6200              :     integer :: tid, seed_size, i, n, k, fact
    6201           90 :     integer, allocatable :: seed(:)
    6202              :     complex(kind=c_double_complex), ABI_CONTIGUOUS pointer :: vecC(:) => null()
    6203              :     real(kind=c_double)            , ABI_CONTIGUOUS pointer :: vecR(:) => null()
    6204              : 
    6205           90 :     if (jcol > xgBlock%cols) then
    6206            0 :         ABI_ERROR('given column is out of block')
    6207              :     end if
    6208              : 
    6209           90 :     tid = 0
    6210              :     fact = 1
    6211           90 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    6212              : 
    6213           90 :     n = fact*xgBlock%rows
    6214              : 
    6215           90 :     if (xgBlock%gpu_option == ABI_GPU_OPENMP) then
    6216            0 :         call xgBlock_setBlock(xgBlock, xgBlock_part, n, 1, fcol=jcol)
    6217            0 :         call xgBlock_copy_from_gpu(xgBlock_part)
    6218              :     end if
    6219              : 
    6220              :     ! Each thread each MPI process maintains its own seed
    6221           90 :     select case(xgBlock%space)
    6222              :     case (SPACE_R)
    6223            0 :         ABI_ERROR('Not implemented for SPACE_R')
    6224              :     case (SPACE_C)
    6225           90 :         vecC => xgBlock%vecC(:,jcol) ! contiguous in memory
    6226              :         !$omp parallel default(none) &
    6227              :         !$omp private(tid, seed, u, k, i, seed_size) &
    6228              :         !$omp shared(vecC, my_rank, n)
    6229           90 :             call random_seed(size=seed_size)
    6230          270 :             ABI_MALLOC(seed, (seed_size))
    6231           90 :             tid = xomp_get_thread_num()
    6232         3060 :             seed = 123456 + 1000*my_rank + 97*tid + (/ (i, i=1,seed_size) /)
    6233           90 :             call random_seed(put=seed)
    6234              :             !$omp do
    6235       349920 :             do i=1,n
    6236       349830 :                 call random_number(u)
    6237       349830 :                 k = int(4.0d0 * u)   ! 0,1,2,3
    6238       349920 :                 vecC(i) = exp(dcmplx(0.0d0, 1.0d0) * (0.5d0 * PI * k))
    6239              :             end do
    6240              :             !$omp end do
    6241           90 :             ABI_FREE(seed)
    6242              :         !$omp end parallel
    6243           90 :         meanz = sum(vecC) / dcmplx(n,0.0d0)
    6244              :         norm2_ = sum(abs(vecC)**2) / n
    6245            0 :         variance = norm2_ - abs(meanz)**2
    6246              :         ! IML debug
    6247              :         !write(901,*) "mean = ", meanz
    6248              :         !write(901,*) "E|z|^2 = ", norm2_
    6249              :         !write(901,*) "variance = ", variance
    6250              :         !flush(901)
    6251              :     case (SPACE_CR)
    6252            0 :         vecR => xgBlock%vecR(1:fact*xgBlock%rows,jcol) ! contiguous in memory
    6253              :         !$omp parallel default(none) &
    6254              :         !$omp private(tid, seed, u, k, i, seed_size) &
    6255              :         !$omp shared(vecR, my_rank, n)
    6256            0 :             call random_seed(size=seed_size)
    6257            0 :             ABI_MALLOC(seed, (seed_size))
    6258            0 :             tid = xomp_get_thread_num()
    6259            0 :             seed = 123456 + 1000*my_rank + 97*tid + (/ (i, i=1,seed_size) /)
    6260            0 :             call random_seed(put=seed)
    6261              :             !$omp do
    6262            0 :             do i=1,n
    6263            0 :                 call random_number(u)
    6264            0 :                 vecR(i) = merge(1.d0, -1.d0, u>=0.5d0)
    6265              :             end do
    6266              :             !$omp end do
    6267           90 :             ABI_FREE(seed)
    6268              :         !$omp end parallel
    6269              :     end select
    6270              : 
    6271              :     if (xgBlock%gpu_option == ABI_GPU_OPENMP) then
    6272              :         call xgBlock_copy_to_gpu(xgBlock_part)
    6273              :     end if
    6274              : 
    6275          180 :   end subroutine xgBlock_colwiseRandomRademacher
    6276              :   !!***
    6277              : 
    6278              :   !!****f* m_xg/xgBlock_randomSketching
    6279              :   !!
    6280              :   !! NAME
    6281              :   !! xgBlock_randomSketching
    6282              :   !!
    6283              : 
    6284           36 :   subroutine xgBlock_randomSketching(X, X_sketch, k_sketch)
    6285              : 
    6286              :     implicit none
    6287              : 
    6288              :     type(xgBlock_t), intent(in) :: X
    6289              :     type(xgBlock_t), intent(inout) :: X_sketch
    6290              :     integer, intent(in) :: k_sketch
    6291              : 
    6292              :     integer :: k
    6293              :     integer :: rank
    6294              :     integer :: spacecom, space
    6295              :     integer :: ncols, nrows
    6296              :     integer :: gpu_option
    6297              :     type(xg_t) :: Omega
    6298              :     !type(xgBlock_t) :: q
    6299              : 
    6300              :   ! *********************************************************************
    6301              : 
    6302           36 :     space = X%space
    6303           36 :     ncols = X%cols
    6304           36 :     nrows = X%rows
    6305           36 :     gpu_option = X%gpu_option
    6306           36 :     spacecom = X%spacedim_comm
    6307              : 
    6308           36 :     if (k_sketch > ncols) then
    6309            0 :         ABI_ERROR("sketching dimension cannot be more than initial one")
    6310              :     end if
    6311              : 
    6312              :     ! Each MPI has the same sketch matrix
    6313           36 :     call xg_init(Omega, space, ncols, k_sketch, xmpi_comm_null, gpu_option=gpu_option)
    6314              : 
    6315           36 :     rank = xmpi_comm_rank(spacecom)
    6316              : 
    6317         3510 :     do k = 1, k_sketch
    6318              :         ! seed depends on column index
    6319              :         ! rank * offset + k, with offset > ncols to avoid overlap between columns across ranks
    6320         3510 :         call xgBlock_colwiseRandomGaussian(Omega%self, rank*(k_sketch+10)+k, k)
    6321              : 
    6322              :         ! test
    6323              :         ! q = random column vector
    6324              :         !call xgBlock_setBlock(Omega%self, q, ncols, 1, fcol=k)
    6325              :         !write(std_out,*) 'Random id=', xgBlock_getid(q)
    6326              :         !flush(std_out)
    6327              :     end do
    6328              : 
    6329              :     ! Compute X * Omega
    6330           36 :     call xgBlock_gemm('n','n',1.0d0,X,Omega%self,0.d0,X_sketch,comm=xmpi_comm_null)
    6331              :     !call xgBlock_copy(Omega%self, X_sketch)
    6332              : 
    6333           36 :     call xg_free(Omega)
    6334              : 
    6335           36 :   end subroutine xgBlock_randomSketching
    6336              :   !!***
    6337              : 
    6338              :   !!****f* m_xg/xgBlock_diagonal
    6339              :   !!
    6340              :   !! NAME
    6341              :   !! xgBlock_diagonal
    6342              : 
    6343            0 :   subroutine xgBlock_diagonal(xgBlock,diag)
    6344              : 
    6345              :     type(xgBlock_t), intent(inout) :: xgBlock
    6346              :     type(xgBlock_t), intent(in   ) :: diag
    6347              :     integer :: i
    6348              : 
    6349            0 :     if ( diag%cols /= 1 .or. diag%rows/= min(xgBlock%rows,xgBlock%cols) ) then
    6350            0 :       ABI_ERROR("Bad diagonal")
    6351              :     end if
    6352              : 
    6353            0 :     select case(xgBlock%space)
    6354              :     case (SPACE_R)
    6355            0 :       select case(diag%space)
    6356              :       case (SPACE_R)
    6357              :         !$omp parallel do
    6358            0 :         do i = 1, min(xgBlock%rows,xgBlock%cols)
    6359            0 :           xgBlock%vecR(i,i) = diag%vecR(i,1)
    6360              :         end do
    6361              :       case (SPACE_CR)
    6362            0 :           ABI_ERROR('Not implemented for SPACE_CR')
    6363              :       case (SPACE_C)
    6364              :         !$omp parallel do
    6365            0 :         do i = 1, min(xgBlock%rows,xgBlock%cols)
    6366            0 :           xgBlock%vecR(i,i) = dble(diag%vecC(i,1))
    6367              :         end do
    6368              :       end select
    6369              :     case (SPACE_CR)
    6370            0 :         ABI_ERROR('Not implemented for SPACE_CR')
    6371              :     case (SPACE_C)
    6372            0 :       select case(diag%space)
    6373              :       case (SPACE_R)
    6374              :         !$omp parallel do
    6375            0 :         do i = 1, min(xgBlock%rows,xgBlock%cols)
    6376            0 :           xgBlock%vecC(i,i) = dcmplx(diag%vecR(i,1))
    6377              :         end do
    6378              :       case (SPACE_CR)
    6379            0 :           ABI_ERROR('Not implemented for SPACE_CR')
    6380              :       case (SPACE_C)
    6381              :         !$omp parallel do
    6382            0 :         do i = 1, min(xgBlock%rows,xgBlock%cols)
    6383            0 :           xgBlock%vecC(i,i) = diag%vecR(i,1)
    6384              :         end do
    6385              :       end select
    6386              :     end select
    6387              : 
    6388            0 :   end subroutine xgBlock_diagonal
    6389              :   !!***
    6390              : 
    6391              :   !!****f* m_xg/xgBlock_diagonalOnly
    6392              :   !!
    6393              :   !! NAME
    6394              :   !! xgBlock_diagonalOnly
    6395              : 
    6396            0 :   subroutine xgBlock_diagonalOnly(xgBlock)
    6397              : 
    6398              :     type(xgBlock_t) , intent(inout) :: xgBlock
    6399              :     type(xg_t) :: diag
    6400              :     integer :: i
    6401              : 
    6402            0 :     if ( xgBlock%rows /= xgBlock%cols) then
    6403            0 :       ABI_ERROR("Bad xgBlock shape")
    6404              :     end if
    6405              : 
    6406            0 :     call xg_init(diag,space(xgBlock),xgBlock%rows,1,xgBlock%spacedim_comm)
    6407            0 :     select case(xgBlock%space)
    6408              :     case (SPACE_R)
    6409              :       !$omp parallel do
    6410            0 :       do i = 1, xgBlock%cols
    6411            0 :         diag%vecR(i,1) = xgBlock%vecR(i,i)
    6412              :       end do
    6413              :     case (SPACE_CR)
    6414            0 :         ABI_ERROR('Not implemented for SPACE_CR')
    6415              :     case (SPACE_C)
    6416              :       !$omp parallel do
    6417            0 :       do i = 1, xgBlock%cols
    6418            0 :         diag%vecC(i,1) = xgBlock%vecC(i,i)
    6419              :       end do
    6420              :     end select
    6421            0 :     call xgBlock_zero(xgBlock)
    6422            0 :     call xgBlock_diagonal(xgBlock,diag%self)
    6423            0 :     call xg_free(diag)
    6424              : 
    6425            0 :   end subroutine xgBlock_diagonalOnly
    6426              :   !!***
    6427              : 
    6428              :   !!****f* m_xg/xgBlock_minmax
    6429              :   !!
    6430              :   !! NAME
    6431              :   !! xgBlock_minmax
    6432              : 
    6433       758687 :   subroutine xgBlock_minmax(xgBlock,minimum,maximum,row_bound)
    6434              : 
    6435              :     type(XgBlock_t) , intent(in)  :: xgBlock
    6436              :     double precision, intent(out) :: minimum,maximum
    6437              :     integer,optional, intent(in)  :: row_bound
    6438              : 
    6439              :     integer :: row_bound_,fact
    6440              :     double precision :: tsec(2)
    6441              : 
    6442       758687 :     call timab(tim_minmax,1,tsec)
    6443              : 
    6444       758687 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    6445              : 
    6446       758687 :     row_bound_ = fact*xgBlock%rows
    6447       758687 :     if (present(row_bound)) then
    6448        28390 :       if (row_bound<1.or.row_bound>fact*xgBlock%rows) then
    6449            0 :         ABI_ERROR('Bad row_bound')
    6450              :       else
    6451        28390 :         row_bound_ = fact*row_bound
    6452              :       end if
    6453              :     end if
    6454              : 
    6455      1517374 :     select case(xgBlock%space)
    6456              :     case (SPACE_R,SPACE_CR)
    6457      3450569 :       minimum = minval(xgBlock%vecR(:row_bound_,:))
    6458      3450569 :       maximum = maxval(xgBlock%vecR(:row_bound_,:))
    6459              :     case (SPACE_C)
    6460            0 :       minimum = minval(abs(xgBlock%vecC(:row_bound_,:)))
    6461       758687 :       maximum = maxval(abs(xgBlock%vecC(:row_bound_,:)))
    6462              :     end select
    6463              : 
    6464       758687 :     call timab(tim_minmax,2,tsec)
    6465              : 
    6466       758687 :   end subroutine xgBlock_minmax
    6467              :   !!***
    6468              : 
    6469              :   !!****f* m_xg/xgBlock_average
    6470              :   !!
    6471              :   !! NAME
    6472              :   !! xgBlock_average
    6473              : 
    6474            0 :   subroutine xgBlock_average(xgBlock,average)
    6475              : 
    6476              :     type(XgBlock_t) , intent(in)  :: xgBlock
    6477              :     double precision, intent(out) :: average
    6478              :     complex(kind=8) :: averageC
    6479              :     integer :: i,fact
    6480              : 
    6481            0 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    6482              : 
    6483            0 :     select case(xgBlock%space)
    6484              :     case (SPACE_R,SPACE_CR)
    6485            0 :       average = 0.d0
    6486            0 :       do i = 1, xgBlock%cols
    6487            0 :         average = average + sum(xgBlock%vecR(1:fact*xgBlock%rows,i))
    6488              :       end do
    6489            0 :       average = average / dble(xgBlock%cols*xgBlock%rows)
    6490              :     case (SPACE_C)
    6491            0 :       averageC = dcmplx(0.d0,0.d0)
    6492            0 :       do i = 1, xgBlock%cols
    6493            0 :         averageC = averageC + sum(xgBlock%vecC(1:xgBlock%rows,i))
    6494              :       end do
    6495            0 :       averageC = averageC / dble(xgBlock%cols*xgBlock%rows)
    6496            0 :       average = dble(averageC)
    6497              :     end select
    6498              : 
    6499            0 :   end subroutine xgBlock_average
    6500              :   !!***
    6501              : 
    6502              :   !!****f* m_xg/xgBlock_deviation
    6503              :   !!
    6504              :   !! NAME
    6505              :   !! xgBlock_deviation
    6506              : 
    6507            0 :   subroutine xgBlock_deviation(xgBlock,deviation)
    6508              : 
    6509              :     type(XgBlock_t) , intent(in)  :: xgBlock
    6510              :     double precision, intent(out) :: deviation
    6511              :     complex(kind=8) :: deviationC
    6512              :     double precision :: average
    6513              :     integer :: i,fact
    6514              : 
    6515            0 :     fact = 1 ; if (xgBlock%space==SPACE_CR) fact = 2
    6516              : 
    6517            0 :     call xgBlock_average(xgBlock,average)
    6518            0 :     select case(xgBlock%space)
    6519              :     case (SPACE_R,SPACE_CR)
    6520            0 :       deviation = 0.d0
    6521            0 :       do i = 1, xgBlock%cols
    6522            0 :         deviation = deviation + sum((xgBlock%vecR(1:fact*xgBlock%rows,i)-average)*(xgBlock%vecR(1:fact*xgBlock%rows,i)-average))
    6523              :       end do
    6524            0 :       deviation = sqrt( deviation / dble(xgBlock%cols*xgBlock%rows) )
    6525              :     case (SPACE_C)
    6526            0 :       deviationC = dcmplx(0.d0,0.d0)
    6527            0 :       do i = 1, xgBlock%cols
    6528            0 :         deviationC = deviationC + sum((xgBlock%vecC(1:xgBlock%rows,i)-average)*(xgBlock%vecC(1:xgBlock%rows,i)-average))
    6529              :       end do
    6530            0 :       deviationC = deviationC / dble(xgBlock%cols*xgBlock%rows)
    6531            0 :       deviation = abs(deviationC)
    6532              :     end select
    6533            0 :   end subroutine xgBlock_deviation
    6534              :   !!***
    6535              : 
    6536              :   !!****f* m_xg/xgBlock_print
    6537              :   !!
    6538              :   !! NAME
    6539              :   !! xgBlock_print
    6540              : 
    6541            0 :   subroutine xgBlock_print(xgBlock,outunit)
    6542              : 
    6543              :     type(xgBlock_t), intent(in) :: xgBlock
    6544              :     integer, intent(in) :: outunit
    6545              :     integer :: i, j
    6546              :     character(len=4) :: ccols
    6547              :     character(len=50) :: fstring
    6548            0 :     real(dp), allocatable :: vecR_tmp(:)
    6549              : 
    6550              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    6551              :     complex(dp), pointer :: xgBlock__vecC(:,:)
    6552              :     real(dp), pointer :: xgBlock__vecR(:,:)
    6553              : #endif
    6554              : 
    6555            0 :     select case(xgBlock%space)
    6556              :     case (SPACE_R)
    6557              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    6558              :       if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    6559              :         xgBlock__vecR => xgBlock%vecR
    6560              :         !$OMP TARGET UPDATE FROM(xgBlock__vecR)
    6561              :       end if
    6562              : #endif
    6563            0 :       write(ccols,'(i4)') xgBlock%cols
    6564              :       !fstring = '(1x,'//trim(adjustl(ccols))//'ES22.14)'
    6565            0 :       fstring = '(1x,'//trim(adjustl(ccols))//'f24.14)'
    6566            0 :       do i = 1, xgBlock%rows
    6567            0 :         write(outunit,fstring) (/ (xgBlock%vecR(i,j), j = 1, xgBlock%cols) /)
    6568              :       end do
    6569              :     case (SPACE_CR)
    6570              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    6571              :       if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    6572              :         xgBlock__vecR => xgBlock%vecR
    6573              :         !$OMP TARGET UPDATE FROM(xgBlock__vecR)
    6574              :       end if
    6575              : #endif
    6576            0 :       ABI_MALLOC(vecR_tmp,(2*xgBlock%cols))
    6577            0 :       write(ccols,'(i4)') 2*xgBlock%cols
    6578              :       !fstring = '(1x,2(1x,'//trim(adjustl(ccols))//'ES22.14))'
    6579            0 :       fstring = '(1x,2(1x,'//trim(adjustl(ccols))//'f24.14))'
    6580            0 :       do i = 1, xgBlock%rows
    6581            0 :         do j = 1, xgBlock%cols
    6582            0 :            vecR_tmp(2*j-1) = xgBlock%vecR(2*i-1,j)
    6583            0 :            vecR_tmp(2*j  ) = xgBlock%vecR(2*i  ,j)
    6584              :         end do
    6585            0 :         write(outunit,fstring) (/ (vecR_tmp(j), j = 1, 2*xgBlock%cols) /)
    6586              :       end do
    6587            0 :       ABI_FREE(vecR_tmp)
    6588              :     case (SPACE_C)
    6589              : #if defined HAVE_GPU && defined HAVE_OPENMP_OFFLOAD
    6590              :       if (xgBlock%gpu_option==ABI_GPU_OPENMP) then
    6591              :         xgBlock__vecC => xgBlock%vecC
    6592              :         !$OMP TARGET UPDATE FROM(xgBlock__vecC)
    6593              :       end if
    6594              : #endif
    6595            0 :       write(ccols,'(i4)') xgBlock%cols
    6596              :       !fstring = '(1x,2(1x,'//trim(adjustl(ccols))//'ES22.14))'
    6597            0 :       fstring = '(1x,2(1x,'//trim(adjustl(ccols))//'f24.14))'
    6598            0 :       do i = 1, xgBlock%rows
    6599            0 :         write(outunit,fstring) (/ (xgBlock%vecC(i,j), j = 1, xgBlock%cols) /)
    6600              :       end do
    6601              :     end select
    6602            0 :   end subroutine xgBlock_print
    6603              :   !!***
    6604              : 
    6605              :   !!****f* m_xg/xgBlock_getid
    6606              :   !!
    6607              :   !! NAME
    6608              :   !! xgBlock_getid
    6609              : 
    6610           18 :   function xgBlock_getid(xgBlock,comm) result (id)
    6611              : 
    6612              :     type(xgBlock_t), intent(in) :: xgBlock
    6613              :     integer, intent(in),optional :: comm
    6614              : 
    6615              :     real(dp) :: id
    6616              :     integer :: ierr,comm_
    6617              : 
    6618              :     if (xgBlock%gpu_option/=ABI_GPU_DISABLED) then
    6619              :       call xgBlock_copy_from_gpu(xgBlock)
    6620              :     end if
    6621           18 :     select case(xgBlock%space)
    6622              :       case (SPACE_R)
    6623            0 :         id = sum(abs(xgBlock%vecR(:,:)))
    6624              :       case (SPACE_CR)
    6625            0 :         if (xgBlock%me_g0<0) then
    6626            0 :           ABI_ERROR("xgBlock me_g0 is not initialized")
    6627              :         end if
    6628            0 :         id = 2*sum(abs(xgBlock%vecR(:,:)))
    6629            0 :         if (xgBlock%me_g0==1) then
    6630            0 :           id = id - sum(abs(xgBlock%vecR(1,:)))
    6631              :         end if
    6632              :       case (SPACE_C)
    6633      9009276 :         id = sum(abs(dble(xgBlock%vecC(:,:))))+sum(abs(dimag(xgBlock%vecC(:,:))))
    6634              :     end select
    6635           18 :     comm_=xgBlock%spacedim_comm
    6636           18 :     if (present(comm)) then
    6637            0 :       comm_=comm
    6638              :     end if
    6639           18 :     if (xmpi_comm_size(comm_)>1) call xmpi_sum(id,comm_,ierr)
    6640              : 
    6641           18 :   end function xgBlock_getid
    6642              :   !!***
    6643              : 
    6644              :   !!****f* m_xg/xgBlock_get_im_g0
    6645              :   !!
    6646              :   !! NAME
    6647              :   !! xgBlock_get_im_g0
    6648              : 
    6649            0 :   function xgBlock_get_im_g0(xgBlock,comm) result (im_g0)
    6650              : 
    6651              :     type(xgBlock_t), intent(in) :: xgBlock
    6652              :     integer, intent(in),optional :: comm
    6653              : 
    6654              :     real(dp) :: im_g0
    6655              :     integer :: ierr,comm_
    6656              : 
    6657              :     if (xgBlock%gpu_option/=ABI_GPU_DISABLED) then
    6658              :       call xgBlock_copy_from_gpu(xgBlock)
    6659              :     end if
    6660            0 :     select case(xgBlock%space)
    6661              :       case (SPACE_R)
    6662            0 :         im_g0 = zero
    6663              :       case (SPACE_CR)
    6664            0 :         if (xgBlock%me_g0<0) then
    6665            0 :           ABI_ERROR("xgBlock me_g0 is not initialized")
    6666              :         end if
    6667            0 :         im_g0 = zero
    6668            0 :         if (xgBlock%me_g0==1) then
    6669            0 :           im_g0 = im_g0 + sum(abs(xgBlock%vecR(2,:)))
    6670              :         end if
    6671              :       case (SPACE_C)
    6672            0 :         im_g0 = zero
    6673              :     end select
    6674            0 :     comm_=xgBlock%spacedim_comm
    6675            0 :     if (present(comm)) then
    6676            0 :       comm_=comm
    6677              :     end if
    6678            0 :     if (xmpi_comm_size(comm_)>1) call xmpi_sum(im_g0,comm_,ierr)
    6679              : 
    6680            0 :   end function xgBlock_get_im_g0
    6681              :   !!***
    6682              : 
    6683              :   !!****f* m_xg/xg_finalize
    6684              :   !!
    6685              :   !! NAME
    6686              :   !! xg_finalize
    6687              : 
    6688         5285 :   subroutine xg_finalize()
    6689              : 
    6690         5285 :     if ( allocated(iwork) ) then
    6691          636 :       ABI_FREE(iwork)
    6692              :     end if
    6693         5285 :     if ( allocated(rwork) ) then
    6694          636 :       ABI_FREE(rwork)
    6695              :     end if
    6696         5285 :     if ( allocated(cwork) ) then
    6697          472 :       ABI_FREE(cwork)
    6698              :     end if
    6699              : 
    6700         5285 :     liwork = 0
    6701         5285 :     lrwork = 0
    6702         5285 :     lcwork = 0
    6703              : 
    6704         5285 :   end subroutine xg_finalize
    6705              :   !!***
    6706              : 
    6707              :   !!****f* m_xg/xg_associated
    6708              :   !!
    6709              :   !! NAME
    6710              :   !! xg_associated
    6711              : 
    6712            0 :   function xg_associated(xgB) result (tf)
    6713              : 
    6714              :     type(xgBlock_t), intent(inout) :: xgB
    6715              :     logical :: tf
    6716              : 
    6717              :     if ( associated(xgB%vecR) ) then
    6718              :       tf = .TRUE.
    6719              :     end if
    6720              : 
    6721            0 :     if ( associated(xgB%vecC) ) then
    6722            0 :       tf = .FALSE.
    6723              :     end if
    6724              : 
    6725            0 :   end function xg_associated
    6726              :   !!***
    6727              : 
    6728            0 : end module m_xg
    6729              : !!***
        

Generated by: LCOV version 2.3-1