LCOV - code coverage report
Current view: top level - shared/common/src/28_numeric_noabirule - abi_gpu_linalg.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 437 0
Test Date: 2026-09-20 18:56:22 Functions: 0.0 % 69 0

            Line data    Source code
       1              : !{\src2tex{textfont=tt}}
       2              : !!****m* ABINIT/m_abi_gpu_linalg
       3              : !! NAME
       4              : !!  m_abi_gpu_linalg
       5              : !!
       6              : !! FUNCTION
       7              : !!  Interfaces of GPU subroutines wrapper
       8              : !!
       9              : !! COPYRIGHT
      10              : !!  Copyright (C) 2011-2026 ABINIT group (FDahm)
      11              : !!  This file is distributed under the terms of the
      12              : !!  GNU General Public License, see ~abinit/COPYING
      13              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14              : !!
      15              : !! NOTES
      16              : !!  This is an include file.
      17              : !!
      18              : !! SOURCE
      19              : 
      20              : !!***
      21              : 
      22              : #ifndef HAVE_GPU
      23              : 
      24              : !!****f* m_abi_gpu_linalg/gpu_linalg_init
      25              : !! NAME
      26              : !!  gpu_linalg_init
      27              : !!
      28              : !! FUNCTION
      29              : !!  initialisation of linalg environnement on GPU
      30              : !!
      31              : !! INPUTS
      32              : !!
      33              : !! OUTPUT
      34              : !!
      35              : !! SIDE EFFECTS
      36              : !!   WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
      37              : !!   the correct one is in 17_gpu_toolbox/gpu_linalg.cu
      38              : !!
      39              : !! SOURCE
      40              : 
      41            0 : subroutine gpu_linalg_init()
      42              : 
      43              : 
      44            0 : end subroutine gpu_linalg_init
      45              : !!***
      46              : 
      47              : !!****f* m_abi_gpu_linalg/gpu_linalg_shutdown
      48              : !! NAME
      49              : !!  gpu_linalg_shutdown
      50              : !!
      51              : !! FUNCTION
      52              : !!  close linalg environnement on GPU
      53              : !!
      54              : !! INPUTS
      55              : !!
      56              : !! OUTPUT
      57              : !!
      58              : !! SIDE EFFECTS
      59              : !!   WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
      60              : !!   the correct one is in 17_gpu_toolbox/gpu_linalg.cu
      61              : !!
      62              : !! SOURCE
      63            0 : subroutine gpu_linalg_shutdown()
      64              : 
      65            0 : end subroutine gpu_linalg_shutdown
      66              : !!***
      67              : 
      68              : !!****f* m_abi_gpu_linalg/gpu_xgemm
      69              : !! NAME
      70              : !!  gpu_xgemm
      71              : !!
      72              : !! FUNCTION
      73              : !!  Compute a scalar-matrix-matrix product and return a scalar-matrix product on GPU
      74              : !!  c = alpha * op(a) * op(b) + beta * c
      75              : !!
      76              : !! INPUTS
      77              : !!  cplx  = 1 if real 2 if complex
      78              : !!  transa= from of op(a) to be used in the matrix multiplication
      79              : !!  transb= from of op(b) to be used in the matrix multiplication
      80              : !!  m     = number of rows of the matrix op(a) and of the matrix c
      81              : !!  n     = number of rows of the matrix op(b) and the number of columns of the matrix c
      82              : !!  k     = number of columns of the matrix op(a) and the number of rows of the matrix op(b)
      83              : !!  alpha = alpha scalar coefficient for matrix op(a)
      84              : !!  a_gpu = pointer to gpu memory location of  matrix a
      85              : !!  lda   = first dimension of a
      86              : !!  b_gpu = pointer to gpu memory location of  matrix b
      87              : !!  ldb   = first dimension of b
      88              : !!  beta  = beta scalar coefficient for matrix c
      89              : !!  c_gpu = pointer to gpu memory location of  matrix c
      90              : !!  ldc   = first dimension of c
      91              : !!
      92              : !! OUTPUT
      93              : !!  c     = c matrix
      94              : !!
      95              : !! SIDE EFFECTS
      96              : !!   WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
      97              : !!   the correct one is in 17_gpu_toolbox/gpu_linalg.cu
      98              : !!
      99              : !! SOURCE
     100              : 
     101            0 : subroutine gpu_xgemm(cplx,transa,transb,m,n,k,alpha,a_gpu,lda,b_gpu,ldb,beta,c_gpu,ldc)
     102              : 
     103              : !Arguments ------------------------------------
     104              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     105              :  complex(dp),intent(in) :: alpha,beta
     106              :  character(len=1),intent(in) :: transa,transb
     107              :  type(c_ptr),intent(in) :: a_gpu,b_gpu
     108              :  type(c_ptr),intent(inout) :: c_gpu
     109              : !Local variables ------------------------------
     110              :  type(c_ptr) :: cptr
     111              : ! *********************************************************************
     112              : 
     113              :  if (.false.) then
     114              :    cptr=a_gpu;cptr=b_gpu;cptr=c_gpu
     115              :    write(std_out,*) transa,transb,cplx,lda,ldb,ldc,m,n,k,alpha,beta
     116              :  end if
     117              : 
     118            0 : end subroutine gpu_xgemm
     119              : !!***
     120              : 
     121              : !!****f* m_abi_gpu_linalg/gpu_xtrsm
     122              : !! NAME
     123              : !!  gpu_xtrsm
     124              : !!
     125              : !! FUNCTION
     126              : !! Solves a matrix equation (one matrix operand is triangular) on GPU.
     127              : !! The xtrsm routines solve one of the following matrix equations
     128              : !! op(a)*x = alpha*b
     129              : !! or
     130              : !! x*op(a) = alpha*b,
     131              : !!
     132              : !! INPUTS
     133              : !! cplx= 1 if real 2 if complex
     134              : !! side= Specifies whether op(a) appears on the left or right of x for
     135              : !!      the operation to be performed as follows:
     136              : !!      L or l op(a)*x = alpha*b
     137              : !!      R or r x*op(a) = alpha*b
     138              : !! uplo= Specifies whether the matrix a is an upper or lower triangular
     139              : !!      matrix as follows:
     140              : !!      U or u Matrix a is an upper triangular matrix.
     141              : !!      L or l Matrix a is a lower triangular matrix
     142              : !! transa= Specifies the form of op(a) to be used in the matrix
     143              : !!      multiplication as follows:
     144              : !!      N or n op(a) = a
     145              : !!      T or t op(a) = a'
     146              : !!      C or c op(a) = conjg(a')
     147              : !! diag= Specifies whether or not a is unit triangular as follows:
     148              : !!      U or u Matrix a is assumed to be unit triangular.
     149              : !!      N or n Matrix a is not assumed to be unit triangular.
     150              : !! m= Specifies the number of rows of b. The value of m must be at least zero
     151              : !! n= Specifies the number of columns of b. The value of n must be at least zero
     152              : !! alpha= Specifies the scalar alpha. When alpha is zero, then a is not referenced and b
     153              : !!      need not be set before entry.
     154              : !! a_gpu = pointer to gpu memory location of  array a, DIMENSION (lda, k), where k is m when side = 'L' or 'l' and is n
     155              : !!      when side = 'R' or 'r'.
     156              : !! lda= Specifies the first dimension of a as declared in the calling
     157              : !!     (sub)program. When side = 'L' or 'l', then lda must be at least max(1,
     158              : !!      m), when side = 'R' or 'r', then lda must be at least max(1, n).
     159              : !! b_gpu = pointer to gpu memory location of  b Array, DIMENSION (ldb,n). Before entry, the leading m-by-n part of the array
     160              : !!     b must contain the right-hand side matrix b.
     161              : !! ldb= Specifies the first dimension of b as declared in the calling
     162              : !!     (sub)program. The value of ldb must be at least max(1, m).
     163              : !!
     164              : !! OUTPUT
     165              : !!  b_gpu
     166              : !!
     167              : !! SIDE EFFECTS
     168              : !!   WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
     169              : !!   the correct one is in 17_gpu_toolbox/gpu_linalg.cu
     170              : !!
     171              : !! SOURCE
     172              : 
     173            0 : subroutine gpu_xtrsm(cplx,side,uplo,transa,diag,m,n,alpha,a_gpu,lda,b_gpu,ldb)
     174              : 
     175              : ! !Arguments ------------------------------------
     176              :  integer, intent(in) :: cplx,lda,ldb,m,n
     177              :  complex(dp), intent(in) :: alpha
     178              :  character(len=1), intent(in) :: side,uplo,transa,diag
     179              :  type(c_ptr),intent(in) :: a_gpu
     180              :  type(c_ptr),intent(inout) :: b_gpu
     181              : !Local variables ------------------------------
     182              :  type(c_ptr) :: cptr
     183              : ! *********************************************************************
     184              : 
     185              :  if (.false.) then
     186              :    cptr=a_gpu;cptr=b_gpu
     187              :    write(std_out,*) side,uplo,transa,diag,cplx,lda,ldb,m,n,alpha
     188              :  end if
     189              : 
     190            0 : end subroutine gpu_xtrsm
     191              : !!***
     192              : 
     193              : !!****f* m_abi_gpu_linalg/gpu_xaxpy
     194              : !! NAME
     195              : !!  gpu_xaxpy
     196              : !!
     197              : !! FUNCTION
     198              : !!  Compute a BLAS-1 AXPY operation on GPU
     199              : !!  y = alpha * x + y
     200              : !!
     201              : !! INPUTS
     202              : !!  cplx  = 1 if real 2 if complex
     203              : !!  size  = vector size
     204              : !!  alpha = scalar complex value
     205              : !!  x_gpu = pointer to gpu memory location of array x
     206              : !! incrx  = stride between consecutive elements of x
     207              : !!  y_gpu = pointer to gpu memory location of array y
     208              : !! incry  = stride between consecutive elements of y
     209              : !!
     210              : !! SOURCE
     211            0 : subroutine gpu_xaxpy(cplx, size, alpha, x_gpu, incrx, y_gpu, incry)
     212              : 
     213              :   ! !Arguments ------------------------------------
     214              :   integer,      intent(in)    :: cplx
     215              :   integer,      intent(in)    :: size
     216              :   complex(dp), intent(in)    :: alpha
     217              :   type(c_ptr),  intent(in)    :: x_gpu
     218              :   integer,      intent(in)    :: incrx
     219              :   type(c_ptr),  intent(inout) :: y_gpu
     220              :   integer,      intent(in)    :: incry
     221              : 
     222              :   ABI_UNUSED((/cplx,size,incrx,incry/))
     223              :   ABI_UNUSED(alpha)
     224            0 :   ABI_UNUSED_A(x_gpu)
     225            0 :   ABI_UNUSED_A(y_gpu)
     226            0 : end subroutine gpu_xaxpy
     227              : !!***
     228              : 
     229              : !!****f* m_abi_gpu_linalg/gpu_xcopy
     230              : !! NAME
     231              : !!  gpu_xcopy
     232              : !!
     233              : !! FUNCTION
     234              : !!  Compute a BLAS-1 COPY operation on GPU
     235              : !!  y = x (copy x into y)
     236              : !!
     237              : !! INPUTS
     238              : !!  cplx   = 1 if real 2 if complex
     239              : !!  size   = input vector size
     240              : !!  x_gpu  = pointer to gpu memory location of array x
     241              : !!  incrx  = stride between consecutive elements of x
     242              : !!  y_gpu  = pointer to gpu memory location of array y
     243              : !!  incry  = stride between consecutive elements of y
     244              : !!
     245              : !! SOURCE
     246            0 : subroutine gpu_xcopy(cplx, size, x_gpu, incrx, y_gpu, incry)
     247              : 
     248              :   ! !Arguments ------------------------------------
     249              :   integer,      intent(in)    :: cplx
     250              :   integer,      intent(in)    :: size
     251              :   type(c_ptr),  intent(in)    :: x_gpu
     252              :   integer,      intent(in)    :: incrx
     253              :   type(c_ptr),  intent(inout) :: y_gpu
     254              :   integer,      intent(in)    :: incry
     255              : 
     256              :   ABI_UNUSED((/cplx,size,incrx,incry/))
     257            0 :   ABI_UNUSED_A(x_gpu)
     258            0 :   ABI_UNUSED_A(y_gpu)
     259            0 : end subroutine gpu_xcopy
     260              : !!***
     261              : 
     262              : !!****f* m_abi_gpu_linalg/gpu_xscal
     263              : !! NAME
     264              : !!  gpu_xscal
     265              : !!
     266              : !! FUNCTION
     267              : !!  Compute a BLAS-1 SCAL operation on GPU
     268              : !!  x = alpha * x
     269              : !!
     270              : !! INPUTS
     271              : !!  cplx   = 1 if real 2 if complex
     272              : !!  size   = vector size
     273              : !!  alpha  = scalar complex value
     274              : !!  x_gpu  = pointer to gpu memory location of array x
     275              : !!  incrx  = stride between consecutive elements of x
     276              : !!
     277              : !! SOURCE
     278            0 : subroutine gpu_xscal(cplx, size, alpha, x_gpu, incrx)
     279              : 
     280              :   ! !Arguments ------------------------------------
     281              :   integer,      intent(in)    :: cplx
     282              :   integer,      intent(in)    :: size
     283              :   complex(dp), intent(in)    :: alpha
     284              :   type(c_ptr),  intent(in)    :: x_gpu
     285              :   integer,      intent(in)    :: incrx
     286              : 
     287              :   ABI_UNUSED((/cplx,size,incrx/))
     288              :   ABI_UNUSED(alpha)
     289            0 :   ABI_UNUSED_A(x_gpu)
     290            0 : end subroutine gpu_xscal
     291              : !!***
     292              : 
     293              : !!****f* m_abi_gpu_linalg/gpu_xdot
     294              : !! NAME
     295              : !!  gpu_xdot
     296              : !!
     297              : !! FUNCTION
     298              : !!  Compute blas-3 DOT on GPU
     299              : !!  trace(X^H*Y)
     300              : !!
     301              : !! INPUTS
     302              : !!  cplx  = 1 if real 2 if complex
     303              : !!  N     = number of elements n*s
     304              : !!  X     = array (n,s)
     305              : !!  incrx = stride for X
     306              : !!  Y     = array (n,s)
     307              : !!  incry = stride for Y
     308              : !!  alpha = output pointer
     309              : !!
     310              : !! SOURCE
     311            0 : subroutine gpu_xdot(cplx, size, alpha, x_gpu, incrx, y_gpu, incry)
     312              : 
     313              :   ! !Arguments ------------------------------------
     314              :   integer,      intent(in)    :: cplx
     315              :   integer,      intent(in)    :: size
     316              :   complex(dp), intent(in)    :: alpha
     317              :   type(c_ptr),  intent(in)    :: x_gpu
     318              :   integer,      intent(in)    :: incrx
     319              :   type(c_ptr),  intent(inout) :: y_gpu
     320              :   integer,      intent(in)    :: incry
     321              : 
     322              :   ABI_UNUSED((/cplx,size,incrx,incry/))
     323              :   ABI_UNUSED(alpha)
     324            0 :   ABI_UNUSED_A(x_gpu)
     325            0 :   ABI_UNUSED_A(y_gpu)
     326            0 : end subroutine gpu_xdot
     327              : !!***
     328              : 
     329              : !!****f* m_abi_gpu_linalg/gpu_xsygvd
     330              : !! NAME
     331              : !!  gpu_xsygvd
     332              : !!
     333              : !! FUNCTION
     334              : !!  Compute a LAPACK SYGVD operation on GPU
     335              : !!  compute eigen values/vectors of a real generalized
     336              : !!  symmetric-definite eigenproblem
     337              : !!
     338              : !! See cusolver documentation
     339              : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-sygvd
     340              : !!
     341              : !! See also LAPACK doc in reference implementation:
     342              : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dsygvd.f
     343              : !!
     344              : !! INPUTS
     345              : !!  cplx  = 1 if real 2 if complex
     346              : !!  itype = integer, type of problem
     347              : !!  jobz  = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
     348              : !!  uplo  = character, 'u' or 'l'
     349              : !!  A_nrows = matrix size
     350              : !!  A_ptr = pointer to gpu memory location of matrix A
     351              : !!  lda   = leading dimension of matrix A
     352              : !!  B_ptr = pointer to gpu memory location of matrix B
     353              : !!  ldb   = leading dimension of matrix B
     354              : !!  W_ptr = pointer to gpu memory location of matrix W (output eigen values)
     355              : !!  work_ptr =
     356              : !!  lwork =
     357              : !!  devInfo  =
     358              : !!
     359              : !! SOURCE
     360            0 : subroutine gpu_xsygvd(cplx, itype, jobz, uplo, A_nrows, &
     361              :   &                   A_ptr, lda, &
     362              :   &                   B_ptr, ldb, &
     363              :   &                   W_ptr,      &
     364              :   &                   work_ptr, lwork, &
     365              :   &                   devInfo)
     366              : 
     367              :   ! Arguments ------------------------------------
     368              :   integer,         intent(in   ) :: cplx
     369              :   integer,         intent(in   ) :: itype
     370              :   character(len=1),intent(in   ) :: jobz
     371              :   character(len=1),intent(in   ) :: uplo
     372              :   integer,         intent(in   ) :: A_nrows
     373              :   type(c_ptr),     intent(in   ) :: A_ptr
     374              :   integer,         intent(in   ) :: lda
     375              :   type(c_ptr),     intent(in   ) :: B_ptr
     376              :   integer,         intent(in   ) :: ldb
     377              :   type(c_ptr),     intent(inout) :: W_ptr
     378              :   type(c_ptr),     intent(inout) :: work_ptr
     379              :   integer,         intent(in   ) :: lwork
     380              :   integer,         intent(inout) :: devInfo
     381              : 
     382              :   ABI_UNUSED((/cplx,itype,A_nrows,lda,ldb,lwork,devInfo/))
     383              :   ABI_UNUSED((/jobz,uplo/))
     384              :   ABI_UNUSED((/A_ptr,B_ptr,W_ptr,work_ptr/))
     385            0 : end subroutine gpu_xsygvd
     386              : !!***
     387              : 
     388              : !!****f* m_abi_gpu_linalg/gpu_xsygvd_bufferSize
     389              : !! NAME
     390              : !!  gpu_xsygvd_bufferSize
     391              : !!
     392              : !! FUNCTION
     393              : !!  Compute required size for auxiliary work buffer used internally by cusolver
     394              : !!  in cusolverDnDsygvd / cusolverDnZhegvd
     395              : !!
     396              : !! See cusolver documentation
     397              : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-sygvd
     398              : !!
     399              : !! INPUTS
     400              : !!  cplx  = 1 if real 2 if complex
     401              : !!  itype = integer, type of problem
     402              : !!  jobz  = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
     403              : !!  uplo  = character, 'u' or 'l'
     404              : !!  A_nrows = matrix size
     405              : !!  A_ptr = pointer to gpu memory location of matrix A
     406              : !!  lda   = leading dimension of matrix A
     407              : !!  B_ptr = pointer to gpu memory location of matrix B
     408              : !!  ldb   = leading dimension of matrix B
     409              : !!  W_ptr = pointer to gpu memory location of matrix W (output eigen values)
     410              : !!  work_ptr =
     411              : !!  lwork =
     412              : !!  devInfo  =
     413              : !!
     414              : !! SOURCE
     415            0 : subroutine gpu_xsygvd_buffersize(cplx, itype, jobz, uplo, A_nrows, &
     416              :   &                              A_ptr, lda, &
     417              :   &                              B_ptr, ldb, &
     418              :   &                              W_ptr,      &
     419              :   &                              lwork)
     420              : 
     421              :   ! Arguments ------------------------------------
     422              :   integer,         intent(in   ) :: cplx
     423              :   integer,         intent(in   ) :: itype
     424              :   character(len=1),intent(in   ) :: jobz
     425              :   character(len=1),intent(in   ) :: uplo
     426              :   integer,         intent(in   ) :: A_nrows
     427              :   type(c_ptr),     intent(in   ) :: A_ptr
     428              :   integer,         intent(in   ) :: lda
     429              :   type(c_ptr),     intent(in   ) :: B_ptr
     430              :   integer,         intent(in   ) :: ldb
     431              :   type(c_ptr),     intent(inout) :: W_ptr
     432              :   integer,         intent(in   ) :: lwork
     433              : 
     434              :   ABI_UNUSED((/cplx,itype,A_nrows,lda,ldb,lwork/))
     435              :   ABI_UNUSED((/jobz,uplo/))
     436              :   ABI_UNUSED((/A_ptr,B_ptr,W_ptr/))
     437            0 : end subroutine gpu_xsygvd_bufferSize
     438              : !!***
     439              : #endif
     440              : 
     441              : !!***
     442              : 
     443              : !!****f* m_abi_gpu_linalg/abi_gpu_xgemm
     444              : !! NAME
     445              : !!  abi_gpu_xgemm
     446              : !!
     447              : !! FUNCTION
     448              : !!  Compute a scalar-matrix-matrix product and return a scalar-matrix product on GPU
     449              : !!  c = alpha * op(a) * op(b) + beta * c
     450              : !!
     451              : !! INPUTS
     452              : !!  cplx  = 1 if real 2 if complex
     453              : !!  transa= from of op(a) to be used in the matrix multiplication
     454              : !!  transb= from of op(b) to be used in the matrix multiplication
     455              : !!  m     = number of rows of the matrix op(a) and of the matrix c
     456              : !!  n     = number of rows of the matrix op(b) and the number of columns of the matrix c
     457              : !!  k     = number of columns of the matrix op(a) and the number of rows of the matrix op(b)
     458              : !!  alpha = alpha scalar coefficient for matrix op(a)
     459              : !!  a = pointer to gpu memory location of  matrix a
     460              : !!  lda   = first dimension of a
     461              : !!  b = pointer to gpu memory location of  matrix b
     462              : !!  ldb   = first dimension of b
     463              : !!  beta  = beta scalar coefficient for matrix c
     464              : !!  c = pointer to gpu memory location of  matrix c
     465              : !!  ldc   = first dimension of c
     466              : !!
     467              : !! OUTPUT
     468              : !!  c     = c matrix
     469              : !!
     470              : !! SOURCE
     471              : 
     472            0 : subroutine abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
     473              : 
     474              : !Arguments ------------------------------------
     475              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     476              :  complex(dp),intent(in) :: alpha,beta
     477              :  character(len=1),intent(in) :: transa,transb
     478              :  type(c_ptr),intent(in) :: a,b
     479              :  type(c_ptr),intent(in) :: c
     480              : ! *********************************************************************
     481              : 
     482            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     483            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     484              :   end if
     485              : 
     486              : #ifdef HAVE_GPU
     487              :   call gpu_xgemm(cplx,transa,transb,m,n,k,alpha,&
     488              :       a,lda,b,ldb,beta,c,ldc)
     489              : 
     490              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     491              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
     492              :     ! Therefore, we issue a stream sync here to avoid
     493              :     !potential mistakes in calling context.
     494              :     call gpu_linalg_stream_synchronize()
     495              :   end if
     496              : 
     497              : #else
     498              :   ! Unused if GPU code disabled
     499              :   ABI_UNUSED((/cplx,lda,ldb,ldc,m,n,k/))
     500              :   ABI_UNUSED((/alpha,beta/))
     501              :   ABI_UNUSED((/transa,transb/))
     502              :   ABI_UNUSED((/a,b,c/))
     503              : #endif
     504              : 
     505            0 : end subroutine abi_gpu_xgemm_cptr
     506              : !!***
     507              : 
     508            0 : subroutine abi_gpu_xgemm_d(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
     509              : 
     510              : !Arguments ------------------------------------
     511              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     512              :  complex(dp),intent(in) :: alpha,beta
     513              :  character(len=1),intent(in) :: transa,transb
     514              :  real(dp),   intent(in),target :: a(*),b(*)
     515              :  real(dp),   intent(inout),target :: c(*)
     516              : ! *********************************************************************
     517              : 
     518            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     519            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     520              :   end if
     521              : 
     522            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     523              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     524              :         c_loc(a),lda,&
     525              :         c_loc(b),ldb,&
     526              :         beta,&
     527            0 :         c_loc(c),ldc)
     528            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     529              : #ifdef HAVE_OPENMP_OFFLOAD
     530              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     531              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     532              :       c_loc(a),lda,&
     533              :       c_loc(b),ldb,&
     534              :       beta,&
     535              :       c_loc(c),ldc)
     536              :     !$OMP END TARGET DATA
     537              : #endif
     538              :   else
     539            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     540              :   end if
     541              : 
     542            0 : end subroutine abi_gpu_xgemm_d
     543              : !!***
     544              : 
     545            0 : subroutine abi_gpu_xgemm_z(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
     546              : 
     547              : !Arguments ------------------------------------
     548              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     549              :  complex(dp),intent(in) :: alpha,beta
     550              :  character(len=1),intent(in) :: transa,transb
     551              :  complex(dp),intent(in),target :: a(*),b(*)
     552              :  complex(dp),intent(inout),target :: c(*)
     553              : ! *********************************************************************
     554              : 
     555            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     556            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     557              :   end if
     558              : 
     559            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     560              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     561              :         c_loc(a),lda,&
     562              :         c_loc(b),ldb,&
     563              :         beta,&
     564            0 :         c_loc(c),ldc)
     565            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     566              : #ifdef HAVE_OPENMP_OFFLOAD
     567              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     568              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     569              :       c_loc(a),lda,&
     570              :       c_loc(b),ldb,&
     571              :       beta,&
     572              :       c_loc(c),ldc)
     573              :     !$OMP END TARGET DATA
     574              : #endif
     575              :   else
     576            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     577              :   end if
     578              : 
     579            0 : end subroutine abi_gpu_xgemm_z
     580              : !!***
     581              : 
     582            0 : subroutine abi_gpu_xgemm_2d(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
     583              : 
     584              : !Arguments ------------------------------------
     585              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     586              :  complex(dp),intent(in) :: alpha,beta
     587              :  character(len=1),intent(in) :: transa,transb
     588              :  real(dp),   intent(in),target :: a(lda,*),b(ldb,*)
     589              :  real(dp),   intent(inout),target :: c(ldc,*)
     590              : ! *********************************************************************
     591              : 
     592            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     593            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     594              :   end if
     595              : 
     596            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     597              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     598              :         c_loc(a),lda,&
     599              :         c_loc(b),ldb,&
     600              :         beta,&
     601            0 :         c_loc(c),ldc)
     602            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     603              : #ifdef HAVE_OPENMP_OFFLOAD
     604              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     605              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     606              :       c_loc(a),lda,&
     607              :       c_loc(b),ldb,&
     608              :       beta,&
     609              :       c_loc(c),ldc)
     610              :     !$OMP END TARGET DATA
     611              : #endif
     612              :   else
     613            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     614              :   end if
     615              : 
     616            0 : end subroutine abi_gpu_xgemm_2d
     617              : !!***
     618              : 
     619            0 : subroutine abi_gpu_xgemm_2z(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
     620              : 
     621              : !Arguments ------------------------------------
     622              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     623              :  complex(dp),intent(in) :: alpha,beta
     624              :  character(len=1),intent(in) :: transa,transb
     625              :  complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
     626              :  complex(dp),intent(inout),target :: c(ldc,*)
     627              : ! *********************************************************************
     628              : 
     629            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     630            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     631              :   end if
     632              : 
     633            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     634              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     635              :         c_loc(a),lda,&
     636              :         c_loc(b),ldb,&
     637              :         beta,&
     638            0 :         c_loc(c),ldc)
     639            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     640              : #ifdef HAVE_OPENMP_OFFLOAD
     641              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     642              :     call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
     643              :       c_loc(a),lda,&
     644              :       c_loc(b),ldb,&
     645              :       beta,&
     646              :       c_loc(c),ldc)
     647              :     !$OMP END TARGET DATA
     648              : #endif
     649              :   else
     650            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     651              :   end if
     652              : 
     653            0 : end subroutine abi_gpu_xgemm_2z
     654              : !!***
     655              : 
     656              : !------------------------------------------------------------------------------
     657              : 
     658              : !!****f* m_abi_gpu_linalg/abi_gpu_xgemm_strided
     659              : !! NAME
     660              : !!  abi_gpu_xgemm_strided
     661              : !!
     662              : !! FUNCTION
     663              : !!  Compute a batched scalar-matrix-matrix product and return a scalar-matrix product on GPU.
     664              : !!  Meant to be used on non-contiguous matrixes with data is uniformly split in the same number of batches in each matrix.
     665              : !!  c = alpha * op(a) * op(b) + beta * c
     666              : !!
     667              : !! INPUTS
     668              : !!  cplx       = 1 if real 2 if complex
     669              : !!  transa     = from of op(a) to be used in the matrix multiplication
     670              : !!  transb     = from of op(b) to be used in the matrix multiplication
     671              : !!  m          = number of rows of the matrix op(a) and of the matrix c
     672              : !!  n          = number of rows of the matrix op(b) and the number of columns of the matrix c
     673              : !!  k          = number of columns of the matrix op(a) and the number of rows of the matrix op(b)
     674              : !!  alpha      = alpha scalar coefficient for matrix op(a)
     675              : !!  a          = pointer to gpu memory location of  matrix a
     676              : !!  lda        = first dimension of a
     677              : !!  strideC    = stride between each batch in matrix a
     678              : !!  b          = pointer to gpu memory location of  matrix b
     679              : !!  ldb        = first dimension of b
     680              : !!  strideC    = stride between each batch in matrix b
     681              : !!  beta       = beta scalar coefficient for matrix c
     682              : !!  c          = pointer to gpu memory location of  matrix c
     683              : !!  ldc        = first dimension of c
     684              : !!  strideC    = stride between each batch in matrix c
     685              : !!  batchCount = number of batches in any matrix
     686              : !!
     687              : !! OUTPUT
     688              : !!  c     = c matrix
     689              : !!
     690              : !! SOURCE
     691              : 
     692            0 : subroutine abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     693              :     a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount,async,stream_id)
     694              : 
     695              : !Arguments ------------------------------------
     696              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     697              :  integer,intent(in) :: strideA,strideB,strideC,batchCount
     698              :  logical,intent(in),optional :: async
     699              :  integer,intent(in),optional :: stream_id
     700              :  complex(dp),intent(in) :: alpha,beta
     701              :  character(len=1),intent(in) :: transa,transb
     702              :  type(c_ptr),intent(in) :: a,b
     703              :  type(c_ptr),intent(in) :: c
     704              : !Locals ---------------------------------------
     705              :  logical :: async_
     706              :  integer :: stream_id_
     707              : ! *********************************************************************
     708              : 
     709            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     710            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     711              :   end if
     712              :   async_=.false.
     713            0 :   if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) async_=.false.
     714              :   ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
     715              :   ! Therefore, we issue a stream sync here to avoid
     716              :   ! potential mistakes in calling context.
     717              :   if(present(async)) async_=async
     718            0 :   stream_id_=-1;
     719              :   if(present(stream_id)) then
     720              :     stream_id_=modulo(stream_id,32);
     721              :     async_=.true.
     722              :   end if
     723              : 
     724              : #ifdef HAVE_GPU
     725              :     call gpu_xgemm_strided_batched(cplx,transa,transb,m,n,k,alpha,&
     726              :         a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount,stream_id_)
     727              : 
     728              :   if (.not. async_) then
     729              :     call gpu_linalg_stream_synchronize()
     730              :   end if
     731              : 
     732              : #else
     733              :   ! Unused if GPU code disabled
     734              :   ABI_UNUSED((/cplx,lda,ldb,ldc,m,n,k/))
     735              :   ABI_UNUSED((/strideA,strideB,strideC,batchCount/))
     736              :   ABI_UNUSED((/alpha,beta/))
     737              :   ABI_UNUSED((/transa,transb/))
     738              :   ABI_UNUSED((/a,b,c/))
     739              : #endif
     740              : 
     741            0 : end subroutine abi_gpu_xgemm_strided_cptr
     742              : !!***
     743              : 
     744            0 : subroutine abi_gpu_xgemm_strided_d(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
     745              : 
     746              : !Arguments ------------------------------------
     747              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     748              :  integer,intent(in) :: strideA,strideB,strideC,batchCount
     749              :  complex(dp),intent(in) :: alpha,beta
     750              :  character(len=1),intent(in) :: transa,transb
     751              :  real(dp),   intent(in),target :: a(*),b(*)
     752              :  real(dp),   intent(inout),target :: c(*)
     753              : ! *********************************************************************
     754              : 
     755            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     756            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     757              :   end if
     758              : 
     759            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     760              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     761              :         c_loc(a),lda,strideA,&
     762              :         c_loc(b),ldb,strideB,&
     763              :         beta,&
     764            0 :         c_loc(c),ldc,strideC,batchCount)
     765            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     766              : #ifdef HAVE_OPENMP_OFFLOAD
     767              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     768              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     769              :         c_loc(a),lda,strideA,&
     770              :         c_loc(b),ldb,strideB,&
     771              :         beta,&
     772              :         c_loc(c),ldc,strideC,batchCount)
     773              :     !$OMP END TARGET DATA
     774              : #endif
     775              :   else
     776            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     777              :   end if
     778              : 
     779            0 : end subroutine abi_gpu_xgemm_strided_d
     780              : !!***
     781              : 
     782            0 : subroutine abi_gpu_xgemm_strided_z(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
     783              : 
     784              : !Arguments ------------------------------------
     785              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     786              :  integer,intent(in) :: strideA,strideB,strideC,batchCount
     787              :  complex(dp),intent(in) :: alpha,beta
     788              :  character(len=1),intent(in) :: transa,transb
     789              :  complex(dp),intent(in),target :: a(*),b(*)
     790              :  complex(dp),intent(inout),target :: c(*)
     791              : ! *********************************************************************
     792              : 
     793            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     794            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     795              :   end if
     796              : 
     797            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     798              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     799              :         c_loc(a),lda,strideA,&
     800              :         c_loc(b),ldb,strideB,&
     801              :         beta,&
     802            0 :         c_loc(c),ldc,strideC,batchCount)
     803            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     804              : #ifdef HAVE_OPENMP_OFFLOAD
     805              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     806              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     807              :       c_loc(a),lda,strideA,&
     808              :       c_loc(b),ldb,strideB,&
     809              :       beta,&
     810              :       c_loc(c),ldc,strideC,batchCount)
     811              :     !$OMP END TARGET DATA
     812              : #endif
     813              :   else
     814            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     815              :   end if
     816              : 
     817            0 : end subroutine abi_gpu_xgemm_strided_z
     818              : !!***
     819              : 
     820            0 : subroutine abi_gpu_xgemm_strided_2d(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
     821              : 
     822              : !Arguments ------------------------------------
     823              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     824              :  integer,intent(in) :: strideA,strideB,strideC,batchCount
     825              :  complex(dp),intent(in) :: alpha,beta
     826              :  character(len=1),intent(in) :: transa,transb
     827              :  real(dp),   intent(in),target :: a(lda,*),b(ldb,*)
     828              :  real(dp),   intent(inout),target :: c(ldc,*)
     829              : ! *********************************************************************
     830              : 
     831            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     832            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     833              :   end if
     834              : 
     835            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     836              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     837              :         c_loc(a),lda,strideA,&
     838              :         c_loc(b),ldb,strideB,&
     839              :         beta,&
     840            0 :         c_loc(c),ldc,strideC,batchCount)
     841            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     842              : #ifdef HAVE_OPENMP_OFFLOAD
     843              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     844              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     845              :       c_loc(a),lda,strideA,&
     846              :       c_loc(b),ldb,strideB,&
     847              :       beta,&
     848              :       c_loc(c),ldc,strideC,batchCount)
     849              :     !$OMP END TARGET DATA
     850              : #endif
     851              :   else
     852            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     853              :   end if
     854              : 
     855            0 : end subroutine abi_gpu_xgemm_strided_2d
     856              : !!***
     857              : 
     858            0 : subroutine abi_gpu_xgemm_strided_2z(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
     859              : 
     860              : !Arguments ------------------------------------
     861              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
     862              :  integer,intent(in) :: strideA,strideB,strideC,batchCount
     863              :  complex(dp),intent(in) :: alpha,beta
     864              :  character(len=1),intent(in) :: transa,transb
     865              :  complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
     866              :  complex(dp),intent(inout),target :: c(ldc,*)
     867              : ! *********************************************************************
     868              : 
     869            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     870            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     871              :   end if
     872              : 
     873            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     874              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     875              :         c_loc(a),lda,strideA,&
     876              :         c_loc(b),ldb,strideB,&
     877              :         beta,&
     878            0 :         c_loc(c),ldc,strideC,batchCount)
     879            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     880              : #ifdef HAVE_OPENMP_OFFLOAD
     881              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     882              :     call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
     883              :       c_loc(a),lda,strideA,&
     884              :       c_loc(b),ldb,strideB,&
     885              :       beta,&
     886              :       c_loc(c),ldc,strideC,batchCount)
     887              :     !$OMP END TARGET DATA
     888              : #endif
     889              :   else
     890            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
     891              :   end if
     892              : 
     893            0 : end subroutine abi_gpu_xgemm_strided_2z
     894              : !!***
     895              : 
     896              : !------------------------------------------------------------------------------
     897              : !!****f* m_abi_gpu_linalg/abi_gpu_xsymm
     898              : !! NAME
     899              : !!  abi_gpu_xsymm
     900              : !!
     901              : !! FUNCTION
     902              : !!  Compute a symmetric scalar-matrix-matrix product and return a scalar-matrix product on GPU
     903              : !!  c = alpha * op(a) * op(b) + beta * c    , if side == L
     904              : !!  c = alpha * op(b) * op(a) + beta * c    , if side == R
     905              : !!
     906              : !! INPUTS
     907              : !!  cplx  = 1 if real 2 if complex
     908              : !!  side  = Specifies whether op(a) appears on the left or right of x for
     909              : !!          the operation to be performed as follows:
     910              : !!              L or l op(a)*x = alpha*b
     911              : !!              R or r x*op(a) = alpha*b
     912              : !!  uplo  = Specifies whether the matrix a is an upper or lower triangular
     913              : !!          matrix as follows:
     914              : !!              U or u Matrix a is an upper triangular matrix.
     915              : !!              L or l Matrix a is a lower triangular matrix
     916              : !!  m     = number of rows of the matrix op(a) and of the matrix c
     917              : !!  n     = number of rows of the matrix op(b) and the number of columns of the matrix c
     918              : !!  alpha = alpha scalar coefficient for matrix op(a)
     919              : !!  a = pointer to gpu memory location of  matrix a
     920              : !!  lda   = first dimension of a
     921              : !!  b = pointer to gpu memory location of  matrix b
     922              : !!  ldb   = first dimension of b
     923              : !!  beta  = beta scalar coefficient for matrix c
     924              : !!  c = pointer to gpu memory location of  matrix c
     925              : !!  ldc   = first dimension of c
     926              : !!
     927              : !! OUTPUT
     928              : !!  c     = c matrix
     929              : !!
     930              : !! SOURCE
     931              : 
     932            0 : subroutine abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
     933              : 
     934              : !Arguments ------------------------------------
     935              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n
     936              :  complex(dp),intent(in) :: alpha,beta
     937              :  character(len=1),intent(in) :: side,uplo
     938              :  type(c_ptr),intent(in) :: a,b
     939              :  type(c_ptr),intent(in) :: c
     940              : ! *********************************************************************
     941              : 
     942            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     943            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     944              :   end if
     945              : 
     946              : #ifdef HAVE_GPU
     947              : 
     948              :   call gpu_xsymm(cplx,side,uplo,m,n,alpha,&
     949              :       a,lda,b,ldb,beta,c,ldc)
     950              : 
     951              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     952              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
     953              :     ! Therefore, we issue a stream sync here to avoid
     954              :     !potential mistakes in calling context.
     955              :     call gpu_linalg_stream_synchronize()
     956              :   end if
     957              : 
     958              : #else
     959              :   ! Unused if GPU code disabled
     960              :   ABI_UNUSED((/cplx,lda,ldb,ldc,m,n/))
     961              :   ABI_UNUSED((/alpha,beta/))
     962              :   ABI_UNUSED((/side,uplo/))
     963              :   ABI_UNUSED((/a,b,c/))
     964              : #endif
     965              : 
     966            0 : end subroutine abi_gpu_xsymm_cptr
     967              : !!***
     968              : 
     969            0 : subroutine abi_gpu_xsymm_d(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
     970              : 
     971              : !Arguments ------------------------------------
     972              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n
     973              :  complex(dp),intent(in) :: alpha,beta
     974              :  character(len=1),intent(in) :: side,uplo
     975              :  real(dp),   intent(in),target :: a(*),b(*)
     976              :  real(dp),   intent(inout),target :: c(*)
     977              : ! *********************************************************************
     978              : 
     979            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
     980            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
     981              :   end if
     982              : 
     983            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
     984              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
     985              :         c_loc(a),lda,&
     986              :         c_loc(b),ldb,&
     987              :         beta,&
     988            0 :         c_loc(c),ldc)
     989            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
     990              : #ifdef HAVE_OPENMP_OFFLOAD
     991              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
     992              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
     993              :       c_loc(a),lda,&
     994              :       c_loc(b),ldb,&
     995              :       beta,&
     996              :       c_loc(c),ldc)
     997              :     !$OMP END TARGET DATA
     998              : #endif
     999              :   else
    1000            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1001              :   end if
    1002              : 
    1003            0 : end subroutine abi_gpu_xsymm_d
    1004              : !!***
    1005              : 
    1006            0 : subroutine abi_gpu_xsymm_z(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1007              : 
    1008              : !Arguments ------------------------------------
    1009              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n
    1010              :  complex(dp),intent(in) :: alpha,beta
    1011              :  character(len=1),intent(in) :: side,uplo
    1012              :  complex(dp),intent(in),target :: a(*),b(*)
    1013              :  complex(dp),intent(inout),target :: c(*)
    1014              : ! *********************************************************************
    1015              : 
    1016            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1017            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1018              :   end if
    1019              : 
    1020            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1021              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
    1022              :         c_loc(a),lda,&
    1023              :         c_loc(b),ldb,&
    1024              :         beta,&
    1025            0 :         c_loc(c),ldc)
    1026            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1027              : #ifdef HAVE_OPENMP_OFFLOAD
    1028              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1029              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
    1030              :       c_loc(a),lda,&
    1031              :       c_loc(b),ldb,&
    1032              :       beta,&
    1033              :       c_loc(c),ldc)
    1034              :     !$OMP END TARGET DATA
    1035              : #endif
    1036              :   else
    1037            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1038              :   end if
    1039              : 
    1040            0 : end subroutine abi_gpu_xsymm_z
    1041              : !!***
    1042              : 
    1043            0 : subroutine abi_gpu_xsymm_2d(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1044              : 
    1045              : !Arguments ------------------------------------
    1046              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n
    1047              :  complex(dp),intent(in) :: alpha,beta
    1048              :  character(len=1),intent(in) :: side,uplo
    1049              :  real(dp),   intent(in),target :: a(lda,*),b(ldb,*)
    1050              :  real(dp),   intent(inout),target :: c(ldc,*)
    1051              : ! *********************************************************************
    1052              : 
    1053            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1054            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1055              :   end if
    1056              : 
    1057            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1058              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
    1059              :         c_loc(a),lda,&
    1060              :         c_loc(b),ldb,&
    1061              :         beta,&
    1062            0 :         c_loc(c),ldc)
    1063            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1064              : #ifdef HAVE_OPENMP_OFFLOAD
    1065              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1066              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
    1067              :       c_loc(a),lda,&
    1068              :       c_loc(b),ldb,&
    1069              :       beta,&
    1070              :       c_loc(c),ldc)
    1071              :     !$OMP END TARGET DATA
    1072              : #endif
    1073              :   else
    1074            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1075              :   end if
    1076              : 
    1077            0 : end subroutine abi_gpu_xsymm_2d
    1078              : !!***
    1079              : 
    1080            0 : subroutine abi_gpu_xsymm_2z(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1081              : 
    1082              : !Arguments ------------------------------------
    1083              :  integer,intent(in) :: cplx,lda,ldb,ldc,m,n
    1084              :  complex(dp),intent(in) :: alpha,beta
    1085              :  character(len=1),intent(in) :: side,uplo
    1086              :  complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
    1087              :  complex(dp),intent(inout),target :: c(ldc,*)
    1088              : ! *********************************************************************
    1089              : 
    1090            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1091            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1092              :   end if
    1093              : 
    1094            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1095              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
    1096              :         c_loc(a),lda,&
    1097              :         c_loc(b),ldb,&
    1098              :         beta,&
    1099            0 :         c_loc(c),ldc)
    1100            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1101              : #ifdef HAVE_OPENMP_OFFLOAD
    1102              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1103              :     call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
    1104              :       c_loc(a),lda,&
    1105              :       c_loc(b),ldb,&
    1106              :       beta,&
    1107              :       c_loc(c),ldc)
    1108              :     !$OMP END TARGET DATA
    1109              : #endif
    1110              :   else
    1111            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1112              :   end if
    1113              : 
    1114            0 : end subroutine abi_gpu_xsymm_2z
    1115              : !!***
    1116              : 
    1117              : !------------------------------------------------------------------------------
    1118              : !!****f* m_abi_gpu_linalg/abi_gpu_zhemm
    1119              : !! NAME
    1120              : !!  abi_gpu_xhemm
    1121              : !!
    1122              : !! FUNCTION
    1123              : !!  Compute a Hermitian scalar-matrix-matrix product and return a scalar-matrix product on GPU
    1124              : !!  c = alpha * op(a) * op(b) + beta * c    , if side == L
    1125              : !!  c = alpha * op(b) * op(a) + beta * c    , if side == R
    1126              : !!
    1127              : !! INPUTS
    1128              : !!  side  = Specifies whether op(a) appears on the left or right of x for
    1129              : !!          the operation to be performed as follows:
    1130              : !!              L or l op(a)*x = alpha*b
    1131              : !!              R or r x*op(a) = alpha*b
    1132              : !!  uplo  = Specifies whether the matrix a is an upper or lower triangular
    1133              : !!          matrix as follows:
    1134              : !!              U or u Matrix a is an upper triangular matrix.
    1135              : !!              L or l Matrix a is a lower triangular matrix
    1136              : !!  m     = number of rows of the matrix op(a) and of the matrix c
    1137              : !!  n     = number of rows of the matrix op(b) and the number of columns of the matrix c
    1138              : !!  alpha = alpha scalar coefficient for matrix op(a)
    1139              : !!  a_gpu = pointer to gpu memory location of  matrix a
    1140              : !!  lda   = first dimension of a
    1141              : !!  b_gpu = pointer to gpu memory location of  matrix b
    1142              : !!  ldb   = first dimension of b
    1143              : !!  beta  = beta scalar coefficient for matrix c
    1144              : !!  c_gpu = pointer to gpu memory location of  matrix c
    1145              : !!  ldc   = first dimension of c
    1146              : !!
    1147              : !! OUTPUT
    1148              : !!  c     = c matrix
    1149              : !!
    1150              : !! SOURCE
    1151              : 
    1152            0 : subroutine abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1153              : 
    1154              : !Arguments ------------------------------------
    1155              :  integer,intent(in) :: lda,ldb,ldc,m,n
    1156              :  complex(dp),intent(in) :: alpha,beta
    1157              :  character(len=1),intent(in) :: side,uplo
    1158              :  type(c_ptr),intent(in) :: a,b
    1159              :  type(c_ptr),intent(in) :: c
    1160              : ! *********************************************************************
    1161              : 
    1162            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1163            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1164              :   end if
    1165              : 
    1166              : #ifdef HAVE_GPU
    1167              : 
    1168              :   call gpu_zhemm(side,uplo,m,n,alpha,&
    1169              :       a,lda,b,ldb,beta,c,ldc)
    1170              : 
    1171              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1172              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    1173              :     ! Therefore, we issue a stream sync here to avoid
    1174              :     !potential mistakes in calling context.
    1175              :     call gpu_linalg_stream_synchronize()
    1176              :   end if
    1177              : 
    1178              : #else
    1179              :   ! Unused if GPU code disabled
    1180              :   ABI_UNUSED((/lda,ldb,ldc,m,n/))
    1181              :   ABI_UNUSED((/alpha,beta/))
    1182              :   ABI_UNUSED((/side,uplo/))
    1183              :   ABI_UNUSED((/a,b,c/))
    1184              : #endif
    1185              : 
    1186            0 : end subroutine abi_gpu_zhemm_cptr
    1187              : !!***
    1188              : 
    1189            0 : subroutine abi_gpu_zhemm_d(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1190              : 
    1191              : !Arguments ------------------------------------
    1192              :  integer,intent(in) :: lda,ldb,ldc,m,n
    1193              :  complex(dp),intent(in) :: alpha,beta
    1194              :  character(len=1),intent(in) :: side,uplo
    1195              :  real(dp),intent(in),target :: a(*),b(*)
    1196              :  real(dp),intent(inout),target :: c(*)
    1197              : ! *********************************************************************
    1198              : 
    1199            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1200            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1201              :   end if
    1202              : 
    1203            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1204              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1205              :         c_loc(a),lda,&
    1206              :         c_loc(b),ldb,&
    1207              :         beta,&
    1208            0 :         c_loc(c),ldc)
    1209            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1210              : #ifdef HAVE_OPENMP_OFFLOAD
    1211              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1212              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1213              :       c_loc(a),lda,&
    1214              :       c_loc(b),ldb,&
    1215              :       beta,&
    1216              :       c_loc(c),ldc)
    1217              :     !$OMP END TARGET DATA
    1218              : #endif
    1219              :   else
    1220            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1221              :   end if
    1222              : 
    1223            0 : end subroutine abi_gpu_zhemm_d
    1224              : !!***
    1225              : 
    1226            0 : subroutine abi_gpu_zhemm_z(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1227              : 
    1228              : !Arguments ------------------------------------
    1229              :  integer,intent(in) :: lda,ldb,ldc,m,n
    1230              :  complex(dp),intent(in) :: alpha,beta
    1231              :  character(len=1),intent(in) :: side,uplo
    1232              :  complex(dp),intent(in),target :: a(*),b(*)
    1233              :  complex(dp),intent(inout),target :: c(*)
    1234              : ! *********************************************************************
    1235              : 
    1236            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1237            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1238              :   end if
    1239              : 
    1240            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1241              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1242              :         c_loc(a),lda,&
    1243              :         c_loc(b),ldb,&
    1244              :         beta,&
    1245            0 :         c_loc(c),ldc)
    1246            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1247              : #ifdef HAVE_OPENMP_OFFLOAD
    1248              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1249              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1250              :       c_loc(a),lda,&
    1251              :       c_loc(b),ldb,&
    1252              :       beta,&
    1253              :       c_loc(c),ldc)
    1254              :     !$OMP END TARGET DATA
    1255              : #endif
    1256              :   else
    1257            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1258              :   end if
    1259              : 
    1260            0 : end subroutine abi_gpu_zhemm_z
    1261              : !!***
    1262              : 
    1263            0 : subroutine abi_gpu_zhemm_2d(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1264              : 
    1265              : !Arguments ------------------------------------
    1266              :  integer,intent(in) :: lda,ldb,ldc,m,n
    1267              :  complex(dp),intent(in) :: alpha,beta
    1268              :  character(len=1),intent(in) :: side,uplo
    1269              :  real(dp),intent(in),target :: a(lda,*),b(ldb,*)
    1270              :  real(dp),intent(inout),target :: c(ldc,*)
    1271              : ! *********************************************************************
    1272              : 
    1273            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1274            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1275              :   end if
    1276              : 
    1277            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1278              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1279              :         c_loc(a),lda,&
    1280              :         c_loc(b),ldb,&
    1281              :         beta,&
    1282            0 :         c_loc(c),ldc)
    1283            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1284              : #ifdef HAVE_OPENMP_OFFLOAD
    1285              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1286              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1287              :       c_loc(a),lda,&
    1288              :       c_loc(b),ldb,&
    1289              :       beta,&
    1290              :       c_loc(c),ldc)
    1291              :     !$OMP END TARGET DATA
    1292              : #endif
    1293              :   else
    1294            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1295              :   end if
    1296              : 
    1297            0 : end subroutine abi_gpu_zhemm_2d
    1298              : !!***
    1299              : 
    1300            0 : subroutine abi_gpu_zhemm_2z(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
    1301              : 
    1302              : !Arguments ------------------------------------
    1303              :  integer,intent(in) :: lda,ldb,ldc,m,n
    1304              :  complex(dp),intent(in) :: alpha,beta
    1305              :  character(len=1),intent(in) :: side,uplo
    1306              :  complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
    1307              :  complex(dp),intent(inout),target :: c(ldc,*)
    1308              : ! *********************************************************************
    1309              : 
    1310            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1311            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1312              :   end if
    1313              : 
    1314            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1315              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1316              :         c_loc(a),lda,&
    1317              :         c_loc(b),ldb,&
    1318              :         beta,&
    1319            0 :         c_loc(c),ldc)
    1320            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1321              : #ifdef HAVE_OPENMP_OFFLOAD
    1322              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
    1323              :     call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
    1324              :       c_loc(a),lda,&
    1325              :       c_loc(b),ldb,&
    1326              :       beta,&
    1327              :       c_loc(c),ldc)
    1328              :     !$OMP END TARGET DATA
    1329              : #endif
    1330              :   else
    1331            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1332              :   end if
    1333              : 
    1334            0 : end subroutine abi_gpu_zhemm_2z
    1335              : !!***
    1336              : 
    1337              : !------------------------------------------------------------------------------
    1338              : !!****f* m_abi_gpu_linalg/abi_gpu_xscal
    1339              : !! NAME
    1340              : !!  abi_gpu_xscal
    1341              : !!
    1342              : !! FUNCTION
    1343              : !!  Compute a BLAS-1 SCAL operation on GPU
    1344              : !!  x = alpha * x
    1345              : !!
    1346              : !! INPUTS
    1347              : !!  cplx   = 1 if real 2 if complex
    1348              : !!  size   = vector size
    1349              : !!  alpha  = scalar complex value
    1350              : !!  x_gpu  = pointer to gpu memory location of array x
    1351              : !!  incrx  = stride between consecutive elements of x
    1352              : !!
    1353              : !! SOURCE
    1354            0 : subroutine abi_gpu_xscal_cptr(cplx, size, alpha, x, incrx)
    1355              : 
    1356              :  ! !Arguments ------------------------------------
    1357              :  integer,      intent(in)    :: cplx
    1358              :  integer,      intent(in)    :: size
    1359              :  complex(dp), intent(in)    :: alpha
    1360              :  type(c_ptr),  intent(in)    :: x
    1361              :  integer,      intent(in)    :: incrx
    1362              : ! *************************************************************************
    1363              : 
    1364            0 :  if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1365            0 :    ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1366              :  end if
    1367              : 
    1368              : #ifdef HAVE_GPU
    1369              : 
    1370              :  call gpu_xscal(cplx, size, alpha, x, incrx)
    1371              : 
    1372              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1373              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    1374              :     ! Therefore, we issue a stream sync here to avoid
    1375              :     !potential mistakes in calling context.
    1376              :     call gpu_linalg_stream_synchronize()
    1377              :   end if
    1378              : 
    1379              : #else
    1380              :   ! Unused if GPU code disabled
    1381              :   ABI_UNUSED((/cplx,incrx,size/))
    1382              :   ABI_UNUSED((/alpha/))
    1383              :   ABI_UNUSED((/x/))
    1384              : #endif
    1385              : 
    1386            0 : end subroutine abi_gpu_xscal_cptr
    1387              : !!***
    1388              : 
    1389            0 : subroutine abi_gpu_xscal_d(cplx, size, alpha, x, incrx)
    1390              : 
    1391              :  ! !Arguments ------------------------------------
    1392              :  integer,      intent(in)    :: cplx
    1393              :  integer,      intent(in)    :: size
    1394              :  complex(dp), intent(in)    :: alpha
    1395              :  real(dp),     intent(inout), target :: x(*)
    1396              :  integer,      intent(in)    :: incrx
    1397              : ! *************************************************************************
    1398              : 
    1399            0 :  if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1400            0 :    ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1401              :  end if
    1402              : 
    1403            0 :  if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1404            0 :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1405            0 :  else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1406              : #ifdef HAVE_OPENMP_OFFLOAD
    1407              :    !$OMP TARGET DATA USE_DEVICE_ADDR(x)
    1408              :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1409              :    !$OMP END TARGET DATA
    1410              : #endif
    1411              :  else
    1412            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1413              :  end if
    1414              : 
    1415            0 : end subroutine abi_gpu_xscal_d
    1416              : !!***
    1417              : 
    1418            0 : subroutine abi_gpu_xscal_z(cplx, size, alpha, x, incrx)
    1419              : 
    1420              :  ! !Arguments ------------------------------------
    1421              :  integer,      intent(in)    :: cplx
    1422              :  integer,      intent(in)    :: size
    1423              :  complex(dp), intent(in)    :: alpha
    1424              :  complex(dp), intent(inout), target :: x(*)
    1425              :  integer,      intent(in)    :: incrx
    1426              : ! *************************************************************************
    1427              : 
    1428            0 :  if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1429            0 :    ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1430              :  end if
    1431              : 
    1432            0 :  if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1433            0 :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1434            0 :  else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1435              : #ifdef HAVE_OPENMP_OFFLOAD
    1436              :    !$OMP TARGET DATA USE_DEVICE_ADDR(x)
    1437              :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1438              :    !$OMP END TARGET DATA
    1439              : #endif
    1440              :  else
    1441            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1442              :  end if
    1443              : 
    1444            0 : end subroutine abi_gpu_xscal_z
    1445              : !!***
    1446              : 
    1447            0 : subroutine abi_gpu_xscal_2d(cplx, size, alpha, x, incrx)
    1448              : 
    1449              :  ! !Arguments ------------------------------------
    1450              :  integer,      intent(in)    :: cplx
    1451              :  integer,      intent(in)    :: size
    1452              :  complex(dp), intent(in)    :: alpha
    1453              :  real(dp),     intent(inout), target :: x(size,*)
    1454              :  integer,      intent(in)    :: incrx
    1455              : ! *************************************************************************
    1456              : 
    1457            0 :  if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1458            0 :    ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1459              :  end if
    1460              : 
    1461            0 :  if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1462            0 :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1463            0 :  else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1464              : #ifdef HAVE_OPENMP_OFFLOAD
    1465              :    !$OMP TARGET DATA USE_DEVICE_ADDR(x)
    1466              :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1467              :    !$OMP END TARGET DATA
    1468              : #endif
    1469              :  else
    1470            0 :    ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1471              :  end if
    1472              : 
    1473            0 : end subroutine abi_gpu_xscal_2d
    1474              : !!***
    1475              : 
    1476            0 : subroutine abi_gpu_xscal_2z(cplx, size, alpha, x, incrx)
    1477              : 
    1478              :  ! !Arguments ------------------------------------
    1479              :  integer,      intent(in)    :: cplx
    1480              :  integer,      intent(in)    :: size
    1481              :  complex(dp), intent(in)    :: alpha
    1482              :  complex(dp), intent(inout), target :: x(size,*)
    1483              :  integer,      intent(in)    :: incrx
    1484              : ! *************************************************************************
    1485              : 
    1486            0 :  if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1487            0 :    ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1488              :  end if
    1489              : 
    1490            0 :  if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1491            0 :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1492            0 :  else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1493              : #ifdef HAVE_OPENMP_OFFLOAD
    1494              :    !$OMP TARGET DATA USE_DEVICE_ADDR(x)
    1495              :    call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
    1496              :    !$OMP END TARGET DATA
    1497              : #endif
    1498              :  else
    1499            0 :    ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1500              :  end if
    1501              : 
    1502            0 : end subroutine abi_gpu_xscal_2z
    1503              : !!***
    1504              : 
    1505              : !!****f* m_abi_gpu_linalg/abi_gpu_xdot
    1506              : !! NAME
    1507              : !!  abi_gpu_xdot
    1508              : !!
    1509              : !! FUNCTION
    1510              : !!  Compute blas-3 DOT on GPU
    1511              : !!  trace(X^H*Y)
    1512              : !!
    1513              : !! INPUTS
    1514              : !!  cplx  = 1 if real 2 if complex
    1515              : !!  size  = vector size
    1516              : !!  alpha = scalar complex value
    1517              : !!  x_gpu = pointer to gpu memory location of array x
    1518              : !! incrx  = stride between consecutive elements of x
    1519              : !!  y_gpu = pointer to gpu memory location of array y
    1520              : !! incry  = stride between consecutive elements of y
    1521              : !!
    1522              : !! SOURCE
    1523            0 : subroutine abi_gpu_xdot_cptr(cplx, size, alpha, x, incrx, y, incry)
    1524              : 
    1525              :   ! !Arguments ------------------------------------
    1526              :   integer,      intent(in)    :: cplx
    1527              :   integer,      intent(in)    :: size
    1528              :   complex(dp), intent(in)    :: alpha
    1529              :   type(c_ptr),  intent(in)    :: x
    1530              :   integer,      intent(in)    :: incrx
    1531              :   type(c_ptr),  intent(in)    :: y
    1532              :   integer,      intent(in)    :: incry
    1533              : ! *************************************************************************
    1534              : 
    1535            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1536            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1537              :   end if
    1538              : 
    1539              : #ifdef HAVE_GPU
    1540              : 
    1541              :   call gpu_xdot(cplx, size, alpha, x, incrx, y, incry)
    1542              : 
    1543              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1544              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    1545              :     ! Therefore, we issue a stream sync here to avoid
    1546              :     !potential mistakes in calling context.
    1547              :     call gpu_linalg_stream_synchronize()
    1548              :   end if
    1549              : 
    1550              : #else
    1551              :   ! Unused if GPU code disabled
    1552              :   ABI_UNUSED((/cplx,incrx,incry,size/))
    1553              :   ABI_UNUSED((/alpha/))
    1554              :   ABI_UNUSED((/x,y/))
    1555              : #endif
    1556              : 
    1557            0 : end subroutine abi_gpu_xdot_cptr
    1558              : !!***
    1559              : 
    1560            0 : subroutine abi_gpu_xdot_d(cplx, size, alpha, x, incrx, y, incry)
    1561              : 
    1562              :   !Arguments ------------------------------------
    1563              :   integer,      intent(in)    :: cplx
    1564              :   integer,      intent(in)    :: size
    1565              :   complex(dp), intent(in)    :: alpha
    1566              :   real(dp),     intent(in), target    :: x(*)
    1567              :   integer,      intent(in)    :: incrx
    1568              :   real(dp),     intent(inout), target :: y(*)
    1569              :   integer,      intent(in)    :: incry
    1570              : ! *************************************************************************
    1571              : 
    1572            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1573            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1574              :   end if
    1575              : 
    1576            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1577            0 :     call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1578            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1579              : #ifdef HAVE_OPENMP_OFFLOAD
    1580              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1581              :     call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1582              :     !$OMP END TARGET DATA
    1583              : #endif
    1584              :   else
    1585            0 :     ABI_BUG("Unhandled GPU mode !")
    1586              :   end if
    1587              : 
    1588            0 : end subroutine abi_gpu_xdot_d
    1589              : !!***
    1590              : 
    1591            0 : subroutine abi_gpu_xdot_z(cplx, size, alpha, x, incrx, y, incry)
    1592              : 
    1593              :   !Arguments ------------------------------------
    1594              :   integer,      intent(in)    :: cplx
    1595              :   integer,      intent(in)    :: size
    1596              :   complex(dp), intent(in)    :: alpha
    1597              :   complex(dp), intent(in), target    :: x(*)
    1598              :   integer,      intent(in)    :: incrx
    1599              :   complex(dp), intent(inout), target :: y(*)
    1600              :   integer,      intent(in)    :: incry
    1601              : ! *************************************************************************
    1602              : 
    1603            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1604            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1605              :   end if
    1606              : 
    1607            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1608            0 :     call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1609            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1610              : #ifdef HAVE_OPENMP_OFFLOAD
    1611              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1612              :     call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1613              :     !$OMP END TARGET DATA
    1614              : #endif
    1615              :   else
    1616            0 :     ABI_BUG("Unhandled GPU mode !")
    1617              :   end if
    1618              : 
    1619            0 : end subroutine abi_gpu_xdot_z
    1620              : !!***
    1621              : 
    1622              : !!****f* m_abi_gpu_linalg/abi_gpu_xaxpy
    1623              : !! NAME
    1624              : !!  abi_gpu_xaxpy
    1625              : !!
    1626              : !! FUNCTION
    1627              : !!  Compute a BLAS-1 AXPY operation on GPU
    1628              : !!  y = alpha * x + y
    1629              : !!
    1630              : !! INPUTS
    1631              : !!  cplx  = 1 if real 2 if complex
    1632              : !!  size  = vector size
    1633              : !!  alpha = scalar complex value
    1634              : !!  x_gpu = pointer to gpu memory location of array x
    1635              : !! incrx  = stride between consecutive elements of x
    1636              : !!  y_gpu = pointer to gpu memory location of array y
    1637              : !! incry  = stride between consecutive elements of y
    1638              : !!
    1639              : !! SOURCE
    1640            0 : subroutine abi_gpu_xaxpy_cptr(cplx, size, alpha, x, incrx, y, incry)
    1641              : 
    1642              :   ! !Arguments ------------------------------------
    1643              :   integer,      intent(in)    :: cplx
    1644              :   integer,      intent(in)    :: size
    1645              :   complex(dp), intent(in)    :: alpha
    1646              :   type(c_ptr),  intent(in)    :: x
    1647              :   integer,      intent(in)    :: incrx
    1648              :   type(c_ptr),  intent(in)    :: y
    1649              :   integer,      intent(in)    :: incry
    1650              : ! *************************************************************************
    1651              : 
    1652            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1653            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1654              :   end if
    1655              : 
    1656              : #ifdef HAVE_GPU
    1657              : 
    1658              :   call gpu_xaxpy(cplx, size, alpha, x, incrx, y, incry)
    1659              : 
    1660              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1661              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    1662              :     ! Therefore, we issue a stream sync here to avoid
    1663              :     !potential mistakes in calling context.
    1664              :     call gpu_linalg_stream_synchronize()
    1665              :   end if
    1666              : 
    1667              : #else
    1668              :   ! Unused if GPU code disabled
    1669              :   ABI_UNUSED((/cplx,incrx,incry,size/))
    1670              :   ABI_UNUSED((/alpha/))
    1671              :   ABI_UNUSED((/x,y/))
    1672              : #endif
    1673              : 
    1674            0 : end subroutine abi_gpu_xaxpy_cptr
    1675              : !!***
    1676              : 
    1677            0 : subroutine abi_gpu_xaxpy_d(cplx, size, alpha, x, incrx, y, incry)
    1678              : 
    1679              :   !Arguments ------------------------------------
    1680              :   integer,      intent(in)    :: cplx
    1681              :   integer,      intent(in)    :: size
    1682              :   complex(dp), intent(in)    :: alpha
    1683              :   real(dp),     intent(in), target    :: x(*)
    1684              :   integer,      intent(in)    :: incrx
    1685              :   real(dp),     intent(inout), target :: y(*)
    1686              :   integer,      intent(in)    :: incry
    1687              : ! *************************************************************************
    1688              : 
    1689            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1690            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1691              :   end if
    1692              : 
    1693            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1694            0 :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1695            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1696              : #ifdef HAVE_OPENMP_OFFLOAD
    1697              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1698              :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1699              :     !$OMP END TARGET DATA
    1700              : #endif
    1701              :   else
    1702            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1703              :   end if
    1704              : 
    1705            0 : end subroutine abi_gpu_xaxpy_d
    1706              : !!***
    1707              : 
    1708            0 : subroutine abi_gpu_xaxpy_z(cplx, size, alpha, x, incrx, y, incry)
    1709              : 
    1710              :   !Arguments ------------------------------------
    1711              :   integer,      intent(in)    :: cplx
    1712              :   integer,      intent(in)    :: size
    1713              :   complex(dp), intent(in)    :: alpha
    1714              :   complex(dp), intent(in), target    :: x(*)
    1715              :   integer,      intent(in)    :: incrx
    1716              :   complex(dp), intent(inout), target :: y(*)
    1717              :   integer,      intent(in)    :: incry
    1718              : ! *************************************************************************
    1719              : 
    1720            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1721            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1722              :   end if
    1723              : 
    1724            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1725            0 :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1726            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1727              : #ifdef HAVE_OPENMP_OFFLOAD
    1728              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1729              :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1730              :     !$OMP END TARGET DATA
    1731              : #endif
    1732              :   else
    1733            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1734              :   end if
    1735              : 
    1736            0 : end subroutine abi_gpu_xaxpy_z
    1737              : !!***
    1738              : 
    1739            0 : subroutine abi_gpu_xaxpy_2d(cplx, size, alpha, x, incrx, y, incry)
    1740              : 
    1741              :   !Arguments ------------------------------------
    1742              :   integer,      intent(in)    :: cplx
    1743              :   integer,      intent(in)    :: size
    1744              :   complex(dp), intent(in)    :: alpha
    1745              :   real(dp),     intent(in), target    :: x(size,*)
    1746              :   integer,      intent(in)    :: incrx
    1747              :   real(dp),     intent(inout), target :: y(size,*)
    1748              :   integer,      intent(in)    :: incry
    1749              : ! *************************************************************************
    1750              : 
    1751            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1752            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1753              :   end if
    1754              : 
    1755            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1756            0 :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1757            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1758              : #ifdef HAVE_OPENMP_OFFLOAD
    1759              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1760              :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1761              :     !$OMP END TARGET DATA
    1762              : #endif
    1763              :   else
    1764            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1765              :   end if
    1766              : 
    1767            0 : end subroutine abi_gpu_xaxpy_2d
    1768              : !!***
    1769              : 
    1770            0 : subroutine abi_gpu_xaxpy_2z(cplx, size, alpha, x, incrx, y, incry)
    1771              : 
    1772              :   !Arguments ------------------------------------
    1773              :   integer,      intent(in)    :: cplx
    1774              :   integer,      intent(in)    :: size
    1775              :   complex(dp), intent(in)    :: alpha
    1776              :   complex(dp), intent(in), target    :: x(size,*)
    1777              :   integer,      intent(in)    :: incrx
    1778              :   complex(dp), intent(inout), target :: y(size,*)
    1779              :   integer,      intent(in)    :: incry
    1780              : ! *************************************************************************
    1781              : 
    1782            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1783            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1784              :   end if
    1785              : 
    1786            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1787            0 :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1788            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1789              : #ifdef HAVE_OPENMP_OFFLOAD
    1790              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1791              :     call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
    1792              :     !$OMP END TARGET DATA
    1793              : #endif
    1794              :   else
    1795            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1796              :   end if
    1797              : 
    1798            0 : end subroutine abi_gpu_xaxpy_2z
    1799              : !!***
    1800              : 
    1801              : !!****f* m_abi_gpu_linalg/abi_gpu_xcopy
    1802              : !! NAME
    1803              : !!  abi_gpu_xcopy
    1804              : !!
    1805              : !! FUNCTION
    1806              : !!  Compute a BLAS-1 COPY operation on GPU
    1807              : !!  y = x (copy x into y)
    1808              : !!
    1809              : !! INPUTS
    1810              : !!  cplx   = 1 if real 2 if complex
    1811              : !!  size   = input vector size
    1812              : !!  x      = pointer to gpu memory location of array x
    1813              : !!  incrx  = stride between consecutive elements of x
    1814              : !!  y      = pointer to gpu memory location of array y
    1815              : !!  incry  = stride between consecutive elements of y
    1816              : !!
    1817              : !! SOURCE
    1818              : 
    1819            0 : subroutine abi_gpu_xcopy_cptr(cplx, size, x, incrx, y, incry)
    1820              : 
    1821              :   ! !Arguments ------------------------------------
    1822              :   integer,      intent(in)    :: cplx
    1823              :   integer,      intent(in)    :: size
    1824              :   type(c_ptr),  intent(in)    :: x
    1825              :   integer,      intent(in)    :: incrx
    1826              :   type(c_ptr),  intent(in)    :: y
    1827              :   integer,      intent(in)    :: incry
    1828              : 
    1829              : ! *************************************************************************
    1830              : 
    1831            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1832            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1833              :   end if
    1834              : 
    1835              : #ifdef HAVE_GPU
    1836              : 
    1837              :   call gpu_xcopy(cplx, size, x, incrx, y, incry)
    1838              : 
    1839              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1840              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    1841              :     ! Therefore, we issue a stream sync here to avoid
    1842              :     !potential mistakes in calling context.
    1843              :     call gpu_linalg_stream_synchronize()
    1844              :   end if
    1845              : 
    1846              : #else
    1847              :   ! Unused if GPU code disabled
    1848              :   ABI_UNUSED((/cplx,incrx,incry,size/))
    1849              :   ABI_UNUSED((/x,y/))
    1850              : #endif
    1851              : 
    1852            0 : end subroutine abi_gpu_xcopy_cptr
    1853              : !!***
    1854              : 
    1855            0 : subroutine abi_gpu_xcopy_d(cplx, size, x, incrx, y, incry)
    1856              : 
    1857              :   ! !Arguments ------------------------------------
    1858              :   integer,      intent(in)    :: cplx
    1859              :   integer,      intent(in)    :: size
    1860              :   real(dp),     intent(in),target    :: x(*)
    1861              :   integer,      intent(in)    :: incrx
    1862              :   real(dp),     intent(inout),target :: y(*)
    1863              :   integer,      intent(in)    :: incry
    1864              : 
    1865              : ! *************************************************************************
    1866              : 
    1867            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1868            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1869              :   end if
    1870              : 
    1871            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1872            0 :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1873            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1874              : #ifdef HAVE_OPENMP_OFFLOAD
    1875              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1876              :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1877              :     !$OMP END TARGET DATA
    1878              : #endif
    1879              :   else
    1880            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1881              :   end if
    1882              : 
    1883            0 : end subroutine abi_gpu_xcopy_d
    1884              : !!***
    1885              : 
    1886            0 : subroutine abi_gpu_xcopy_z(cplx, size, x, incrx, y, incry)
    1887              : 
    1888              :   ! !Arguments ------------------------------------
    1889              :   integer,      intent(in)    :: cplx
    1890              :   integer,      intent(in)    :: size
    1891              :   complex(dp), intent(in),target    :: x(*)
    1892              :   integer,      intent(in)    :: incrx
    1893              :   complex(dp), intent(inout),target :: y(*)
    1894              :   integer,      intent(in)    :: incry
    1895              : ! *************************************************************************
    1896              : 
    1897            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1898            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1899              :   end if
    1900              : 
    1901            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1902            0 :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1903            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1904              : #ifdef HAVE_OPENMP_OFFLOAD
    1905              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1906              :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1907              :     !$OMP END TARGET DATA
    1908              : #endif
    1909              :   else
    1910            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1911              :   end if
    1912              : 
    1913            0 : end subroutine abi_gpu_xcopy_z
    1914              : !!***
    1915              : 
    1916            0 : subroutine abi_gpu_xcopy_2d(cplx, size, x, incrx, y, incry)
    1917              : 
    1918              :   ! !Arguments ------------------------------------
    1919              :   integer,      intent(in)    :: cplx
    1920              :   integer,      intent(in)    :: size
    1921              :   real(dp),     intent(in),target    :: x(size,*)
    1922              :   integer,      intent(in)    :: incrx
    1923              :   real(dp),     intent(inout),target :: y(size,*)
    1924              :   integer,      intent(in)    :: incry
    1925              : 
    1926              : ! *************************************************************************
    1927              : 
    1928            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1929            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1930              :   end if
    1931              : 
    1932            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1933            0 :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1934            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1935              : #ifdef HAVE_OPENMP_OFFLOAD
    1936              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1937              :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1938              :     !$OMP END TARGET DATA
    1939              : #endif
    1940              :   else
    1941            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1942              :   end if
    1943              : 
    1944            0 : end subroutine abi_gpu_xcopy_2d
    1945              : !!***
    1946              : 
    1947            0 : subroutine abi_gpu_xcopy_2z(cplx, size, x, incrx, y, incry)
    1948              : 
    1949              :   !Arguments ------------------------------------
    1950              :   integer,      intent(in)    :: cplx
    1951              :   integer,      intent(in)    :: size
    1952              :   complex(dp), intent(in),target    :: x(size,*)
    1953              :   integer,      intent(in)    :: incrx
    1954              :   complex(dp), intent(inout),target :: y(size,*)
    1955              :   integer,      intent(in)    :: incry
    1956              : ! *************************************************************************
    1957              : 
    1958            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    1959            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    1960              :   end if
    1961              : 
    1962            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    1963            0 :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1964            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    1965              : #ifdef HAVE_OPENMP_OFFLOAD
    1966              :     !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
    1967              :     call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
    1968              :     !$OMP END TARGET DATA
    1969              : #endif
    1970              :   else
    1971            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    1972              :   end if
    1973              : 
    1974            0 : end subroutine abi_gpu_xcopy_2z
    1975              : !!***
    1976              : 
    1977              : !!****f* m_abi_gpu_linalg/abi_gpu_xtrsm
    1978              : !! NAME
    1979              : !!  abi_gpu_xtrsm
    1980              : !!
    1981              : !! FUNCTION
    1982              : !! Solves a matrix equation (one matrix operand is triangular) on GPU.
    1983              : !! The xtrsm routines solve one of the following matrix equations
    1984              : !! op(a)*x = alpha*b
    1985              : !! or
    1986              : !! x*op(a) = alpha*b,
    1987              : !!
    1988              : !! INPUTS
    1989              : !! cplx= 1 if real 2 if complex
    1990              : !! side= Specifies whether op(a) appears on the left or right of x for
    1991              : !!      the operation to be performed as follows:
    1992              : !!      L or l op(a)*x = alpha*b
    1993              : !!      R or r x*op(a) = alpha*b
    1994              : !! uplo= Specifies whether the matrix a is an upper or lower triangular
    1995              : !!      matrix as follows:
    1996              : !!      U or u Matrix a is an upper triangular matrix.
    1997              : !!      L or l Matrix a is a lower triangular matrix
    1998              : !! transa= Specifies the form of op(a) to be used in the matrix
    1999              : !!      multiplication as follows:
    2000              : !!      N or n op(a) = a
    2001              : !!      T or t op(a) = a'
    2002              : !!      C or c op(a) = conjg(a')
    2003              : !! diag= Specifies whether or not a is unit triangular as follows:
    2004              : !!      U or u Matrix a is assumed to be unit triangular.
    2005              : !!      N or n Matrix a is not assumed to be unit triangular.
    2006              : !! m= Specifies the number of rows of b. The value of m must be at least zero
    2007              : !! n= Specifies the number of columns of b. The value of n must be at least zero
    2008              : !! alpha= Specifies the scalar alpha. When alpha is zero, then a is not referenced and b
    2009              : !!      need not be set before entry.
    2010              : !!  a = pointer to gpu memory location of  array a, DIMENSION (lda, k), where k is m when side = 'L' or 'l' and is n
    2011              : !!      when side = 'R' or 'r'.
    2012              : !! lda= Specifies the first dimension of a as declared in the calling
    2013              : !!     (sub)program. When side = 'L' or 'l', then lda must be at least max(1,
    2014              : !!      m), when side = 'R' or 'r', then lda must be at least max(1, n).
    2015              : !!  b = pointer to gpu memory location of  b Array, DIMENSION (ldb,n). Before entry, the leading m-by-n part of the array
    2016              : !!     b must contain the right-hand side matrix b.
    2017              : !! ldb= Specifies the first dimension of b as declared in the calling
    2018              : !!     (sub)program. The value of ldb must be at least max(1, m).
    2019              : !!
    2020              : !! OUTPUT
    2021              : !!  b
    2022              : !!
    2023              : !! SIDE EFFECTS
    2024              : !!   WARNING! : this routine is a dummy one when HAVE_GPU_CUDA is not enabled
    2025              : !!   the correct one is in 17_toolbox/gpu_linalg.cu
    2026              : !!
    2027              : !! SOURCE
    2028              : 
    2029            0 : subroutine abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
    2030              : 
    2031              : ! !Arguments ------------------------------------
    2032              :  integer, intent(in) :: cplx,lda,ldb,m,n
    2033              :  complex(dp), intent(in) :: alpha
    2034              :  character(len=1), intent(in) :: side,uplo,transa,diag
    2035              :  type(c_ptr),intent(in) :: a
    2036              :  type(c_ptr),intent(in) :: b
    2037              : ! *********************************************************************
    2038              : 
    2039            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2040            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2041              :   end if
    2042              : 
    2043              : #ifdef HAVE_GPU
    2044              : 
    2045              :   call gpu_xtrsm(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
    2046              : 
    2047              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2048              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    2049              :     ! Therefore, we issue a stream sync here to avoid
    2050              :     !potential mistakes in calling context.
    2051              :     call gpu_linalg_stream_synchronize()
    2052              :   end if
    2053              : 
    2054              : #else
    2055              :   ! Unused if GPU code disabled
    2056              :   ABI_UNUSED((/cplx,lda,ldb,m,n/))
    2057              :   ABI_UNUSED((/alpha/))
    2058              :   ABI_UNUSED((/side,uplo,transa,diag/))
    2059              :   ABI_UNUSED((/a,b/))
    2060              : #endif
    2061              : 
    2062            0 : end subroutine abi_gpu_xtrsm_cptr
    2063              : !!***
    2064              : 
    2065            0 : subroutine abi_gpu_xtrsm_d(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
    2066              : 
    2067              : ! !Arguments ------------------------------------
    2068              :  integer, intent(in) :: cplx,lda,ldb,m,n
    2069              :  complex(dp), intent(in) :: alpha
    2070              :  character(len=1), intent(in) :: side,uplo,transa,diag
    2071              :  real(dp),   intent(in),target :: a(*)
    2072              :  real(dp),   intent(inout),target :: b(*)
    2073              : ! *********************************************************************
    2074              : 
    2075            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2076            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2077              :   end if
    2078              : 
    2079            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2080              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2081            0 :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2082            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2083              : #ifdef HAVE_OPENMP_OFFLOAD
    2084              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
    2085              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2086              :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2087              :     !$OMP END TARGET DATA
    2088              : #endif
    2089              :   else
    2090            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2091              :   end if
    2092              : 
    2093            0 : end subroutine abi_gpu_xtrsm_d
    2094              : !!***
    2095              : 
    2096            0 : subroutine abi_gpu_xtrsm_z(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
    2097              : 
    2098              : ! !Arguments ------------------------------------
    2099              :  integer, intent(in) :: cplx,lda,ldb,m,n
    2100              :  complex(dp), intent(in) :: alpha
    2101              :  character(len=1), intent(in) :: side,uplo,transa,diag
    2102              :  complex(dp),intent(in),target :: a(*)
    2103              :  complex(dp),intent(inout),target :: b(*)
    2104              : ! *********************************************************************
    2105              : 
    2106            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2107            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2108              :   end if
    2109              : 
    2110            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2111              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2112            0 :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2113            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2114              : #ifdef HAVE_OPENMP_OFFLOAD
    2115              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
    2116              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2117              :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2118              :     !$OMP END TARGET DATA
    2119              : #endif
    2120              :   else
    2121            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2122              :   end if
    2123              : 
    2124            0 : end subroutine abi_gpu_xtrsm_z
    2125              : !!***
    2126              : 
    2127            0 : subroutine abi_gpu_xtrsm_2d(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
    2128              : 
    2129              :  !Arguments ------------------------------------
    2130              :  integer, intent(in) :: cplx,lda,ldb,m,n
    2131              :  complex(dp), intent(in) :: alpha
    2132              :  character(len=1), intent(in) :: side,uplo,transa,diag
    2133              :  real(dp),   intent(in),target :: a(lda,*)
    2134              :  real(dp),   intent(inout),target :: b(ldb,*)
    2135              : ! *********************************************************************
    2136              : 
    2137            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2138            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2139              :   end if
    2140              : 
    2141            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2142              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2143            0 :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2144            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2145              : #ifdef HAVE_OPENMP_OFFLOAD
    2146              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
    2147              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2148              :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2149              :     !$OMP END TARGET DATA
    2150              : #endif
    2151              :   else
    2152            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2153              :   end if
    2154              : 
    2155            0 : end subroutine abi_gpu_xtrsm_2d
    2156              : !!***
    2157              : 
    2158            0 : subroutine abi_gpu_xtrsm_2z(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
    2159              : 
    2160              : !Arguments ------------------------------------
    2161              :  integer, intent(in) :: cplx,lda,ldb,m,n
    2162              :  complex(dp), intent(in) :: alpha
    2163              :  character(len=1), intent(in) :: side,uplo,transa,diag
    2164              :  complex(dp),intent(in),target :: a(lda,*)
    2165              :  complex(dp),intent(inout),target :: b(ldb,*)
    2166              : ! *********************************************************************
    2167              : 
    2168            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2169            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2170              :   end if
    2171              : 
    2172            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2173              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2174            0 :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2175            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2176              : #ifdef HAVE_OPENMP_OFFLOAD
    2177              :     !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
    2178              :     call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
    2179              :       diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
    2180              :     !$OMP END TARGET DATA
    2181              : #endif
    2182              :   else
    2183            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2184              :   end if
    2185              : 
    2186            0 : end subroutine abi_gpu_xtrsm_2z
    2187              : !!***
    2188              : 
    2189              : 
    2190              : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeI
    2191              : !!
    2192              : !! NAME
    2193              : !! abi_gpu_work_resizeI
    2194              : 
    2195              : subroutine abi_gpu_work_resizeI(array,array_managed,current_dim,asked_dim)
    2196              : 
    2197              :   integer, allocatable, intent(inout) :: array(:)
    2198              :   integer(kind=c_int32_t), contiguous, pointer, intent(inout) :: array_managed(:)
    2199              :   integer, intent(inout)  :: current_dim
    2200              :   integer, intent(in   )  :: asked_dim
    2201              : ! *************************************************************************
    2202              : 
    2203              :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2204              : 
    2205              : #ifdef HAVE_YAKL
    2206              :     if ( current_dim < asked_dim  ) then
    2207              :       current_dim = asked_dim
    2208              :       if ( associated(array_managed) ) then
    2209              :         ABI_FREE_MANAGED(array_managed)
    2210              :       end if
    2211              :       ABI_MALLOC_MANAGED(array_managed,(/asked_dim/))
    2212              :     end if
    2213              : #endif
    2214              : 
    2215              :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2216              : 
    2217              : #ifdef HAVE_OPENMP_OFFLOAD
    2218              :     if ( current_dim < asked_dim  ) then
    2219              :       current_dim = asked_dim
    2220              :       if ( allocated(array) ) then
    2221              :         !$OMP TARGET EXIT DATA MAP(release:array)
    2222              :         ABI_FREE(array)
    2223              :       end if
    2224              :       ABI_MALLOC(array,(asked_dim))
    2225              :       !$OMP TARGET ENTER DATA MAP(alloc:array)
    2226              :     end if
    2227              : #endif
    2228              : 
    2229              :   else
    2230              :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2231              :   end if
    2232              : 
    2233              : #ifndef HAVE_GPU
    2234              :   ! Unused if GPU code disabled
    2235              :   ABI_UNUSED(array)
    2236              :   ABI_UNUSED(array_managed)
    2237              :   ABI_UNUSED((/current_dim,asked_dim/))
    2238              : #endif
    2239              : 
    2240              : end subroutine abi_gpu_work_resizeI
    2241              : !!***
    2242              : 
    2243              : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeR
    2244              : !!
    2245              : !! NAME
    2246              : !! abi_gpu_work_resizeR
    2247              : 
    2248              : subroutine abi_gpu_work_resizeR(array,array_managed,current_dim,asked_dim)
    2249              : 
    2250              :   double precision, allocatable, intent(inout) :: array(:)
    2251              :   real(kind=c_double), contiguous, pointer, intent(inout) :: array_managed(:)
    2252              :   integer, intent(inout) :: current_dim
    2253              :   integer, intent(in   ) :: asked_dim
    2254              : 
    2255              : ! *************************************************************************
    2256              : 
    2257              :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2258              : 
    2259              : #ifdef HAVE_YAKL
    2260              :     if ( current_dim < asked_dim  ) then
    2261              :       current_dim = asked_dim
    2262              :       if ( associated(array_managed) ) then
    2263              :         ABI_FREE_MANAGED(array_managed)
    2264              :       end if
    2265              :       ABI_MALLOC_MANAGED(array_managed,(/asked_dim/))
    2266              :     end if
    2267              : #endif
    2268              : 
    2269              :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2270              : 
    2271              : #ifdef HAVE_OPENMP_OFFLOAD
    2272              :     if ( current_dim < asked_dim  ) then
    2273              :       current_dim = asked_dim
    2274              :       if ( allocated(array) ) then
    2275              :         !$OMP TARGET EXIT DATA MAP(release:array)
    2276              :         ABI_FREE(array)
    2277              :       end if
    2278              :       ABI_MALLOC(array,(asked_dim))
    2279              :       !$OMP TARGET ENTER DATA MAP(alloc:array)
    2280              :     end if
    2281              : #endif
    2282              : 
    2283              :   else
    2284              :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2285              :   end if
    2286              : 
    2287              : #ifndef HAVE_GPU
    2288              :   ! Unused if GPU code disabled
    2289              :   ABI_UNUSED(array)
    2290              :   ABI_UNUSED(array_managed)
    2291              :   ABI_UNUSED((/current_dim,asked_dim/))
    2292              : #endif
    2293              : 
    2294              : end subroutine abi_gpu_work_resizeR
    2295              : !!***
    2296              : 
    2297              : 
    2298              : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeC
    2299              : !!
    2300              : !! NAME
    2301              : !! abi_gpu_work_resizeC
    2302              : 
    2303              : subroutine abi_gpu_work_resizeC(array,array_managed,current_dim,asked_dim)
    2304              : 
    2305              :   complex(kind=8), allocatable, intent(inout) :: array(:)
    2306              :   complex(kind=c_double_complex), contiguous, pointer, intent(inout) :: array_managed(:)
    2307              :   integer, intent(inout)  :: current_dim
    2308              :   integer, intent(in   )  :: asked_dim
    2309              : ! *************************************************************************
    2310              : 
    2311              :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2312              : 
    2313              : #ifdef HAVE_YAKL
    2314              :     if ( current_dim < asked_dim  ) then
    2315              :       current_dim = asked_dim
    2316              :       if ( associated(array_managed) ) then
    2317              :         ABI_FREE_MANAGED(array_managed)
    2318              :       end if
    2319              :       ABI_MALLOC_MANAGED(array_managed,(/asked_dim/))
    2320              :     end if
    2321              : #endif
    2322              : 
    2323              :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2324              : 
    2325              : #ifdef HAVE_OPENMP_OFFLOAD
    2326              :     if ( current_dim < asked_dim  ) then
    2327              :       current_dim = asked_dim
    2328              :       if ( allocated(array) ) then
    2329              :         !$OMP TARGET EXIT DATA MAP(release:array)
    2330              :         ABI_FREE(array)
    2331              :       end if
    2332              :       ABI_MALLOC(array,(asked_dim))
    2333              :       !$OMP TARGET ENTER DATA MAP(alloc:array)
    2334              :     end if
    2335              : #endif
    2336              : 
    2337              :   else
    2338              :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2339              :   end if
    2340              : 
    2341              : #ifndef HAVE_GPU
    2342              :   ! Unused if GPU code disabled
    2343              :   ABI_UNUSED(array)
    2344              :   ABI_UNUSED(array_managed)
    2345              :   ABI_UNUSED((/current_dim,asked_dim/))
    2346              : #endif
    2347              : 
    2348              : end subroutine abi_gpu_work_resizeC
    2349              : !!***
    2350              : 
    2351              : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeCptr
    2352              : !!
    2353              : !! NAME
    2354              : !! abi_gpu_work_resizeCptr
    2355              : 
    2356              : subroutine abi_gpu_work_resizeCptr(array,current_dim,asked_dim)
    2357              :  use, intrinsic :: iso_c_binding
    2358              : 
    2359              :   type(c_ptr), intent(inout) :: array
    2360              :   integer(c_size_t), intent(inout)  :: current_dim
    2361              :   integer(c_size_t), intent(in   )  :: asked_dim
    2362              : ! *************************************************************************
    2363              : 
    2364              :   if ( current_dim < asked_dim  ) then
    2365              :     if(current_dim /= 0) then
    2366              :       call dealloc_on_gpu(array)
    2367              :     end if
    2368              :     current_dim = asked_dim
    2369              :     call alloc_on_gpu(array, asked_dim)
    2370              :   end if
    2371              : 
    2372              : #ifndef HAVE_GPU
    2373              :   ! Unused if GPU code disabled
    2374              :   ABI_UNUSED(array)
    2375              :   ABI_UNUSED((/current_dim,asked_dim/))
    2376              : #endif
    2377              : 
    2378              : end subroutine abi_gpu_work_resizeCptr
    2379              : !!***
    2380              : 
    2381              : subroutine abi_gpu_work_finalize()
    2382              :  use, intrinsic :: iso_c_binding
    2383              : 
    2384              : #ifdef HAVE_GPU
    2385              :   !FIXME Assuming managed here ?
    2386              :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2387              : 
    2388              : #ifdef HAVE_YAKL
    2389              :     if ( associated(i_work_managed) ) then
    2390              :       ABI_FREE_MANAGED(i_work_managed)
    2391              :     end if
    2392              :     if ( associated(r_work_managed) ) then
    2393              :       ABI_FREE_MANAGED(r_work_managed)
    2394              :     end if
    2395              :     if ( associated(c_work_managed) ) then
    2396              :       ABI_FREE_MANAGED(c_work_managed)
    2397              :     end if
    2398              : #endif
    2399              : 
    2400              :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2401              : 
    2402              : #ifdef HAVE_OPENMP_OFFLOAD
    2403              :     if ( allocated(i_work) ) then
    2404              :       !$OMP TARGET EXIT DATA MAP(release:i_work)
    2405              :       ABI_FREE(i_work)
    2406              :     end if
    2407              :     if ( allocated(r_work) ) then
    2408              :       !$OMP TARGET EXIT DATA MAP(release:r_work)
    2409              :       ABI_FREE(r_work)
    2410              :     end if
    2411              :     if ( allocated(c_work) ) then
    2412              :       !$OMP TARGET EXIT DATA MAP(release:c_work)
    2413              :       ABI_FREE(c_work)
    2414              :     end if
    2415              : #endif
    2416              : 
    2417              :     if(gpu_work_len > 0) then
    2418              :       call dealloc_on_gpu(gpu_work)
    2419              :     end if
    2420              : 
    2421              :   end if
    2422              : 
    2423              :   i_work_len = 0
    2424              :   r_work_len = 0
    2425              :   c_work_len = 0
    2426              :   gpu_work_len = 0
    2427              : 
    2428              : #endif
    2429              : 
    2430              : end subroutine abi_gpu_work_finalize
    2431              : !!***
    2432              : 
    2433              : !!****f* m_abi_gpu_linalg/abi_gpu_xhegvd
    2434              : !! NAME
    2435              : !!  abi_gpu_xhegvd
    2436              : !!
    2437              : !! FUNCTION
    2438              : !!  Compute a LAPACK SYGVD operation on GPU
    2439              : !!  compute eigen values/vectors of a real generalized
    2440              : !!  symmetric-definite eigenproblem
    2441              : !!
    2442              : !! See cusolver documentation
    2443              : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-hegvd
    2444              : !!
    2445              : !! See also LAPACK doc in reference implementation:
    2446              : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dhegvd.f
    2447              : !!
    2448              : !! INPUTS
    2449              : !!  cplx  = 1 if real 2 if complex
    2450              : !!  itype = integer, type of problem
    2451              : !!  jobz  = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
    2452              : !!  uplo  = character, 'u' or 'l'
    2453              : !!  A_nrows = matrix size
    2454              : !!  A = pointer to gpu memory location of matrix A
    2455              : !!  lda   = leading dimension of matrix A
    2456              : !!  B = pointer to gpu memory location of matrix B
    2457              : !!  ldb   = leading dimension of matrix B
    2458              : !!  W = pointer to gpu memory location of matrix W (output eigen values)
    2459              : !!  devInfo  =
    2460              : !!
    2461              : !! SOURCE
    2462              : 
    2463            0 : subroutine abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, A_nrows, &
    2464              :                    A, lda, &
    2465              :                    B, ldb, &
    2466              :                    W,      &
    2467              :                    devInfo)
    2468              : 
    2469              :   ! Arguments ------------------------------------
    2470              :   integer,         intent(in   ) :: cplx
    2471              :   integer,         intent(in   ) :: itype
    2472              :   character(len=1),intent(in   ) :: jobz
    2473              :   character(len=1),intent(in   ) :: uplo
    2474              :   integer,         intent(in   ) :: A_nrows
    2475              :   type(c_ptr),     intent(in   ) :: A
    2476              :   integer,         intent(in   ) :: lda
    2477              :   type(c_ptr),     intent(in   ) :: B
    2478              :   integer,         intent(in   ) :: ldb
    2479              :   type(c_ptr),     intent(in   ) :: W
    2480              :   integer,         intent(inout) :: devInfo
    2481              : 
    2482              :   ! Local variables ------------------------------
    2483              :   integer     :: bufferSize
    2484              :   type(c_ptr) :: gpu_ptr
    2485              : ! *************************************************************************
    2486              : 
    2487            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2488            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2489              :   end if
    2490              : 
    2491              : #ifdef HAVE_GPU
    2492              : 
    2493              :   ! probe needed bufferSize
    2494              :   call gpu_xsygvd_buffersize(cplx, itype, jobz, uplo, &
    2495              :                  A_nrows, &
    2496              :                  A, lda, &
    2497              :                  B, ldb, &
    2498              :                  W, &
    2499              :                  bufferSize)
    2500              : 
    2501              :   select case(cplx)
    2502              : 
    2503              :   case (1)
    2504              :     ! resize work array if needed and retrieve work pointer to use
    2505              :     if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
    2506              :           .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2507              :       call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
    2508              :       gpu_ptr = c_loc(r_work_managed)
    2509              :     else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2510              :       !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
    2511              :       !gpu_ptr = gpu_work
    2512              :       call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
    2513              :       gpu_ptr = xomp_get_mapped_ptr(c_loc(r_work))
    2514              :     end if
    2515              : 
    2516              :   case (2)
    2517              :     ! resize work array if needed and retrieve work pointer to use
    2518              :     if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
    2519              :           .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2520              :       call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
    2521              :       gpu_ptr = c_loc(c_work_managed)
    2522              :     else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2523              :       !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(2,c_size_t)*bufferSize*dp)
    2524              :       !gpu_ptr = gpu_work
    2525              :       call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
    2526              :       gpu_ptr = xomp_get_mapped_ptr(c_loc(c_work))
    2527              :     end if
    2528              : 
    2529              :   end select
    2530              : 
    2531              :   ! and compute (finally)
    2532              :   call gpu_xsygvd(cplx, itype, jobz, uplo, &
    2533              :                  A_nrows, &
    2534              :                  A, lda, &
    2535              :                  B, ldb, &
    2536              :                  W, &
    2537              :                  gpu_ptr, bufferSize, devInfo)
    2538              : 
    2539              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2540              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    2541              :     ! Therefore, we issue a stream sync here to avoid
    2542              :     !potential mistakes in calling context.
    2543              :     call gpu_linalg_stream_synchronize()
    2544              :     !FIXME Free memory to help GPU memory constraint (temporary?)
    2545              :     call abi_gpu_work_finalize()
    2546              :   end if
    2547              : 
    2548              : #else
    2549              :   ! Unused if GPU code disabled
    2550              :   ABI_UNUSED((/cplx,itype,A_nrows,lda,ldb,devInfo,bufferSize/))
    2551              :   ABI_UNUSED((/jobz,uplo/))
    2552              :   ABI_UNUSED((/A,B,W,gpu_ptr/))
    2553              : #endif
    2554              : 
    2555            0 : end subroutine abi_gpu_xhegvd_cptr
    2556              : !!***
    2557              : 
    2558            0 : subroutine abi_gpu_xhegvd_d(cplx, itype, jobz, uplo, A_nrows, &
    2559              :                    A, lda, &
    2560              :                    B, ldb, &
    2561              :                    W,      &
    2562              :                    devInfo)
    2563              : 
    2564              :   ! Arguments ------------------------------------
    2565              :   integer,         intent(in   ) :: cplx
    2566              :   integer,         intent(in   ) :: itype
    2567              :   character(len=1),intent(in   ) :: jobz
    2568              :   character(len=1),intent(in   ) :: uplo
    2569              :   integer,         intent(in   ) :: A_nrows
    2570              :   real(dp),        intent(in   ),target :: A(*)
    2571              :   integer,         intent(in   ) :: lda
    2572              :   real(dp),        intent(in   ),target :: B(*)
    2573              :   integer,         intent(in   ) :: ldb
    2574              :   real(dp),        intent(inout),target :: W(*)
    2575              :   integer,         intent(inout) :: devInfo
    2576              : ! *************************************************************************
    2577              : 
    2578            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2579              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2580              :                  A_nrows, &
    2581              :                  c_loc(A), lda, &
    2582              :                  c_loc(B), ldb, &
    2583              :                  c_loc(W), &
    2584            0 :                  devInfo)
    2585            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2586              : #ifdef HAVE_OPENMP_OFFLOAD
    2587              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
    2588              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2589              :                  A_nrows, &
    2590              :                  c_loc(A), lda, &
    2591              :                  c_loc(B), ldb, &
    2592              :                  c_loc(W), &
    2593              :                  devInfo)
    2594              :     !$OMP END TARGET DATA
    2595              : #endif
    2596              :   else
    2597            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2598              :   end if
    2599              : 
    2600            0 : end subroutine abi_gpu_xhegvd_d
    2601              : !!***
    2602              : 
    2603            0 : subroutine abi_gpu_xhegvd_z(cplx, itype, jobz, uplo, A_nrows, &
    2604              :                    A, lda, &
    2605              :                    B, ldb, &
    2606              :                    W,      &
    2607              :                    devInfo)
    2608              : 
    2609              :   ! Arguments ------------------------------------
    2610              :   integer,         intent(in   ) :: cplx
    2611              :   integer,         intent(in   ) :: itype
    2612              :   character(len=1),intent(in   ) :: jobz
    2613              :   character(len=1),intent(in   ) :: uplo
    2614              :   integer,         intent(in   ) :: A_nrows
    2615              :   complex(dp),    intent(in   ),target :: A(*)
    2616              :   integer,         intent(in   ) :: lda
    2617              :   complex(dp),    intent(in   ),target :: B(*)
    2618              :   integer,         intent(in   ) :: ldb
    2619              :   real(dp),        intent(inout),target :: W(*)
    2620              :   integer,         intent(inout) :: devInfo
    2621              : ! *************************************************************************
    2622              : 
    2623            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2624              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2625              :                  A_nrows, &
    2626              :                  c_loc(A), lda, &
    2627              :                  c_loc(B), ldb, &
    2628              :                  c_loc(W), &
    2629            0 :                  devInfo)
    2630            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2631              : #ifdef HAVE_OPENMP_OFFLOAD
    2632              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
    2633              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2634              :                  A_nrows, &
    2635              :                  c_loc(A), lda, &
    2636              :                  c_loc(B), ldb, &
    2637              :                  c_loc(W), &
    2638              :                  devInfo)
    2639              :     !$OMP END TARGET DATA
    2640              : #endif
    2641              :   else
    2642            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2643              :   end if
    2644              : 
    2645            0 : end subroutine abi_gpu_xhegvd_z
    2646              : !!***
    2647              : 
    2648            0 : subroutine abi_gpu_xhegvd_2d(cplx, itype, jobz, uplo, A_nrows, &
    2649            0 :                    A, lda, &
    2650            0 :                    B, ldb, &
    2651            0 :                    W,      &
    2652              :                    devInfo)
    2653              : 
    2654              :   ! Arguments ------------------------------------
    2655              :   integer,         intent(in   ) :: cplx
    2656              :   integer,         intent(in   ) :: itype
    2657              :   character(len=1),intent(in   ) :: jobz
    2658              :   character(len=1),intent(in   ) :: uplo
    2659              :   integer,         intent(in   ) :: A_nrows,lda,ldb
    2660              :   real(dp),        intent(in   ),target :: A(lda,*)
    2661              :   real(dp),        intent(in   ),target :: B(ldb,*)
    2662              :   real(dp),        intent(inout),target :: W(A_nrows,*)
    2663              :   integer,         intent(inout) :: devInfo
    2664              : ! *************************************************************************
    2665              : 
    2666            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2667              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2668              :                  A_nrows, &
    2669              :                  c_loc(A), lda, &
    2670              :                  c_loc(B), ldb, &
    2671              :                  c_loc(W), &
    2672            0 :                  devInfo)
    2673            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2674              : #ifdef HAVE_OPENMP_OFFLOAD
    2675              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
    2676              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2677              :                  A_nrows, &
    2678              :                  c_loc(A), lda, &
    2679              :                  c_loc(B), ldb, &
    2680              :                  c_loc(W), &
    2681              :                  devInfo)
    2682              :     !$OMP END TARGET DATA
    2683              : #endif
    2684              :   else
    2685            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2686              :   end if
    2687              : 
    2688            0 : end subroutine abi_gpu_xhegvd_2d
    2689              : !!***
    2690              : 
    2691            0 : subroutine abi_gpu_xhegvd_2z(cplx, itype, jobz, uplo, A_nrows, &
    2692            0 :                    A, lda, &
    2693            0 :                    B, ldb, &
    2694            0 :                    W,      &
    2695              :                    devInfo)
    2696              : 
    2697              :   ! Arguments ------------------------------------
    2698              :   integer,         intent(in   ) :: cplx
    2699              :   integer,         intent(in   ) :: itype
    2700              :   character(len=1),intent(in   ) :: jobz
    2701              :   character(len=1),intent(in   ) :: uplo
    2702              :   integer,         intent(in   ) :: A_nrows,lda,ldb
    2703              :   complex(dp),    intent(in   ),target :: A(lda,*)
    2704              :   complex(dp),    intent(in   ),target :: B(ldb,*)
    2705              :   real(dp),        intent(inout),target :: W(A_nrows,*)
    2706              :   integer,         intent(inout) :: devInfo
    2707              : ! *************************************************************************
    2708              : 
    2709            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2710              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2711              :                  A_nrows, &
    2712              :                  c_loc(A), lda, &
    2713              :                  c_loc(B), ldb, &
    2714              :                  c_loc(W), &
    2715            0 :                  devInfo)
    2716            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2717              : #ifdef HAVE_OPENMP_OFFLOAD
    2718              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
    2719              :     call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
    2720              :                  A_nrows, &
    2721              :                  c_loc(A), lda, &
    2722              :                  c_loc(B), ldb, &
    2723              :                  c_loc(W), &
    2724              :                  devInfo)
    2725              :     !$OMP END TARGET DATA
    2726              : #endif
    2727              :   else
    2728            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2729              :   end if
    2730              : 
    2731            0 : end subroutine abi_gpu_xhegvd_2z
    2732              : !!***
    2733              : 
    2734              : !!****f* m_abi_gpu_linalg/abi_gpu_xheevd
    2735              : !! NAME
    2736              : !!  abi_gpu_xheevd
    2737              : !!
    2738              : !! FUNCTION
    2739              : !!  Compute a LAPACK SYEVD operation on GPU
    2740              : !!  compute eigen values/vectors of a real
    2741              : !!  symmetric-definite eigenproblem
    2742              : !!
    2743              : !! See cusolver documentation
    2744              : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-heevd
    2745              : !!
    2746              : !! See also LAPACK doc in reference implementation:
    2747              : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dheevd.f
    2748              : !!
    2749              : !! INPUTS
    2750              : !!  cplx  = 1 if real 2 if complex
    2751              : !!  jobz  = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
    2752              : !!  uplo  = character, 'u' or 'l'
    2753              : !!  A_nrows = matrix size
    2754              : !!  A = pointer to gpu memory location of matrix A
    2755              : !!  lda   = leading dimension of matrix A
    2756              : !!  W = pointer to gpu memory location of matrix W (output eigen values)
    2757              : !!  devInfo  =
    2758              : !!
    2759              : !! SOURCE
    2760              : 
    2761            0 : subroutine abi_gpu_xheevd_cptr(cplx, jobz, uplo, A_nrows, &
    2762              :                    A, lda, &
    2763              :                    W,      &
    2764              :                    devInfo)
    2765              : 
    2766              :   ! Arguments ------------------------------------
    2767              :   integer,         intent(in   ) :: cplx
    2768              :   character(len=1),intent(in   ) :: jobz
    2769              :   character(len=1),intent(in   ) :: uplo
    2770              :   integer,         intent(in   ) :: A_nrows
    2771              :   type(c_ptr),     intent(in   ) :: A
    2772              :   integer,         intent(in   ) :: lda
    2773              :   type(c_ptr),     intent(in) :: W
    2774              :   integer,         intent(inout) :: devInfo
    2775              : 
    2776              :   ! Local variables ------------------------------
    2777              :   integer     :: bufferSize
    2778              :   type(c_ptr) :: gpu_ptr
    2779              : ! *************************************************************************
    2780              : 
    2781            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    2782            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    2783              :   end if
    2784              : 
    2785              : #ifdef HAVE_GPU
    2786              : 
    2787              :   ! probe needed bufferSize
    2788              :   call gpu_xsyevd_buffersize(cplx, jobz, uplo, &
    2789              :                  A_nrows, &
    2790              :                  A, lda, &
    2791              :                  W, &
    2792              :                  bufferSize)
    2793              : 
    2794              :   select case(cplx)
    2795              : 
    2796              :   case (1)
    2797              :     ! resize work array if needed and retrieve work pointer to use
    2798              :     if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
    2799              :           .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2800              :       call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
    2801              :       gpu_ptr = c_loc(r_work_managed)
    2802              :     else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2803              :       !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
    2804              :       !gpu_ptr = gpu_work
    2805              :       call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
    2806              :       gpu_ptr = xomp_get_mapped_ptr(c_loc(r_work))
    2807              :     end if
    2808              : 
    2809              :   case (2)
    2810              :     ! resize work array if needed and retrieve work pointer to use
    2811              :     if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
    2812              :           .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2813              :       call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
    2814              :       gpu_ptr = c_loc(c_work_managed)
    2815              :     else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2816              :       !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(2,c_size_t)*bufferSize*dp)
    2817              :       !gpu_ptr = gpu_work
    2818              :       call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
    2819              :       gpu_ptr = xomp_get_mapped_ptr(c_loc(c_work))
    2820              :     end if
    2821              : 
    2822              :   end select
    2823              : 
    2824              :   ! and compute (finally)
    2825              :   call gpu_xsyevd(cplx, jobz, uplo, &
    2826              :                  A_nrows, &
    2827              :                  A, lda, &
    2828              :                  W, &
    2829              :                  gpu_ptr, bufferSize, devInfo)
    2830              : 
    2831              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2832              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    2833              :     ! Therefore, we issue a stream sync here to avoid
    2834              :     !potential mistakes in calling context.
    2835              :     call gpu_linalg_stream_synchronize()
    2836              :   end if
    2837              : 
    2838              : #else
    2839              :   ! Unused if GPU code disabled
    2840              :   ABI_UNUSED((/cplx,A_nrows,lda,devInfo,bufferSize/))
    2841              :   ABI_UNUSED((/jobz,uplo/))
    2842              :   ABI_UNUSED((/A,W,gpu_ptr/))
    2843              : #endif
    2844              : 
    2845            0 : end subroutine abi_gpu_xheevd_cptr
    2846              : !!***
    2847              : 
    2848            0 : subroutine abi_gpu_xheevd_d(cplx, jobz, uplo, A_nrows, &
    2849              :                    A, lda, &
    2850              :                    W,      &
    2851              :                    devInfo)
    2852              : 
    2853              :   ! Arguments ------------------------------------
    2854              :   integer,         intent(in   ) :: cplx
    2855              :   character(len=1),intent(in   ) :: jobz
    2856              :   character(len=1),intent(in   ) :: uplo
    2857              :   integer,         intent(in   ) :: A_nrows
    2858              :   real(dp),        intent(in   ),target :: A(*)
    2859              :   integer,         intent(in   ) :: lda
    2860              :   real(dp),        intent(inout),target :: W(*)
    2861              :   integer,         intent(inout) :: devInfo
    2862              : ! *************************************************************************
    2863              : 
    2864            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2865              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2866              :                  A_nrows, &
    2867              :                  c_loc(A), lda, &
    2868              :                  c_loc(W), &
    2869            0 :                  devInfo)
    2870            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2871              : #ifdef HAVE_OPENMP_OFFLOAD
    2872              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
    2873              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2874              :                  A_nrows, &
    2875              :                  c_loc(A), lda, &
    2876              :                  c_loc(W), &
    2877              :                  devInfo)
    2878              :     !$OMP END TARGET DATA
    2879              : #endif
    2880              :   else
    2881            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2882              :   end if
    2883              : 
    2884            0 : end subroutine abi_gpu_xheevd_d
    2885              : !!***
    2886              : 
    2887            0 : subroutine abi_gpu_xheevd_z(cplx, jobz, uplo, A_nrows, &
    2888              :                    A, lda, &
    2889              :                    W,      &
    2890              :                    devInfo)
    2891              : 
    2892              :   ! Arguments ------------------------------------
    2893              :   integer,         intent(in   ) :: cplx
    2894              :   character(len=1),intent(in   ) :: jobz
    2895              :   character(len=1),intent(in   ) :: uplo
    2896              :   integer,         intent(in   ) :: A_nrows
    2897              :   complex(dp),    intent(in   ),target :: A(*)
    2898              :   integer,         intent(in   ) :: lda
    2899              :   real(dp),        intent(inout),target :: W(*)
    2900              :   integer,         intent(inout) :: devInfo
    2901              : ! *************************************************************************
    2902              : 
    2903            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2904              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2905              :                  A_nrows, &
    2906              :                  c_loc(A), lda, &
    2907              :                  c_loc(W), &
    2908            0 :                  devInfo)
    2909            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2910              : #ifdef HAVE_OPENMP_OFFLOAD
    2911              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
    2912              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2913              :                  A_nrows, &
    2914              :                  c_loc(A), lda, &
    2915              :                  c_loc(W), &
    2916              :                  devInfo)
    2917              :     !$OMP END TARGET DATA
    2918              : #endif
    2919              :   else
    2920            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2921              :   end if
    2922              : 
    2923            0 : end subroutine abi_gpu_xheevd_z
    2924              : !!***
    2925              : 
    2926            0 : subroutine abi_gpu_xheevd_2d(cplx, jobz, uplo, A_nrows, &
    2927            0 :                    A, lda, &
    2928            0 :                    W,      &
    2929              :                    devInfo)
    2930              : 
    2931              :   ! Arguments ------------------------------------
    2932              :   integer,         intent(in   ) :: cplx
    2933              :   character(len=1),intent(in   ) :: jobz
    2934              :   character(len=1),intent(in   ) :: uplo
    2935              :   integer,         intent(in   ) :: A_nrows,lda
    2936              :   real(dp),        intent(in   ),target :: A(lda,*)
    2937              :   real(dp),        intent(inout),target :: W(A_nrows,*)
    2938              :   integer,         intent(inout) :: devInfo
    2939              : ! *************************************************************************
    2940              : 
    2941            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2942              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2943              :                  A_nrows, &
    2944              :                  c_loc(A), lda, &
    2945              :                  c_loc(W), &
    2946            0 :                  devInfo)
    2947            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2948              : #ifdef HAVE_OPENMP_OFFLOAD
    2949              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
    2950              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2951              :                  A_nrows, &
    2952              :                  c_loc(A), lda, &
    2953              :                  c_loc(W), &
    2954              :                  devInfo)
    2955              :     !$OMP END TARGET DATA
    2956              : #endif
    2957              :   else
    2958            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2959              :   end if
    2960              : 
    2961            0 : end subroutine abi_gpu_xheevd_2d
    2962              : !!***
    2963              : 
    2964            0 : subroutine abi_gpu_xheevd_2z(cplx, jobz, uplo, A_nrows, &
    2965            0 :                    A, lda, &
    2966            0 :                    W,      &
    2967              :                    devInfo)
    2968              : 
    2969              :   ! Arguments ------------------------------------
    2970              :   integer,         intent(in   ) :: cplx
    2971              :   character(len=1),intent(in   ) :: jobz
    2972              :   character(len=1),intent(in   ) :: uplo
    2973              :   integer,         intent(in   ) :: A_nrows,lda
    2974              :   complex(dp),    intent(in   ),target :: A(lda,*)
    2975              :   real(dp),        intent(inout),target :: W(A_nrows,*)
    2976              :   integer,         intent(inout) :: devInfo
    2977              : ! *************************************************************************
    2978              : 
    2979            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    2980              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2981              :                  A_nrows, &
    2982              :                  c_loc(A), lda, &
    2983              :                  c_loc(W), &
    2984            0 :                  devInfo)
    2985            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    2986              : #ifdef HAVE_OPENMP_OFFLOAD
    2987              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
    2988              :     call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
    2989              :                  A_nrows, &
    2990              :                  c_loc(A), lda, &
    2991              :                  c_loc(W), &
    2992              :                  devInfo)
    2993              :     !$OMP END TARGET DATA
    2994              : #endif
    2995              :   else
    2996            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    2997              :   end if
    2998              : 
    2999            0 : end subroutine abi_gpu_xheevd_2z
    3000              : !!***
    3001              : 
    3002              : !!****f* m_abi_gpu_linalg/abi_gpu_xpotrf
    3003              : !! NAME
    3004              : !!  abi_gpu_xpotrf
    3005              : !!
    3006              : !! FUNCTION
    3007              : !!  Compute a LAPACK SYGVD operation on GPU
    3008              : !!  compute eigen values/vectors of a real
    3009              : !!  symmetric-definite eigenproblem
    3010              : !!
    3011              : !! See cusolver documentation
    3012              : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-potrf
    3013              : !!
    3014              : !! See also LAPACK doc in reference implementation:
    3015              : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dpotrf.f
    3016              : !!
    3017              : !! INPUTS
    3018              : !!  cplx  = 1 if real 2 if complex
    3019              : !!  uplo  = character, 'u' or 'l'
    3020              : !!  A_nrows = matrix size
    3021              : !!  A = pointer to gpu memory location of matrix A
    3022              : !!  lda   = leading dimension of matrix A
    3023              : !!  devInfo  =
    3024              : !!
    3025              : !! SOURCE
    3026            0 : subroutine abi_gpu_xpotrf_cptr(cplx, uplo, A_nrows, &
    3027              :                    A, lda, &
    3028              :                    devInfo)
    3029              : 
    3030              :   ! Arguments ------------------------------------
    3031              :   integer,         intent(in   ) :: cplx
    3032              :   character(len=1),intent(in   ) :: uplo
    3033              :   integer,         intent(in   ) :: A_nrows
    3034              :   type(c_ptr),     intent(in   ) :: A
    3035              :   integer,         intent(in   ) :: lda
    3036              :   integer,         intent(inout) :: devInfo
    3037              : 
    3038              :   ! Local variables ------------------------------
    3039              :   integer     :: bufferSize
    3040              :   type(c_ptr) :: gpu_ptr
    3041              : ! *************************************************************************
    3042              : 
    3043            0 :   if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
    3044            0 :     ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
    3045              :   end if
    3046              : 
    3047              : #ifdef HAVE_GPU
    3048              : 
    3049              :   ! probe needed bufferSize
    3050              :   call gpu_xpotrf_buffersize(cplx, uplo, &
    3051              :                  A_nrows, &
    3052              :                  A, lda, &
    3053              :                  bufferSize)
    3054              : 
    3055              :   select case(cplx)
    3056              : 
    3057              :   case (1)
    3058              :     ! resize work array if needed and retrieve work pointer to use
    3059              :     if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
    3060              :           .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    3061              :       call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
    3062              :       gpu_ptr = c_loc(r_work_managed)
    3063              :     else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3064              :       !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
    3065              :       !gpu_ptr = gpu_work
    3066              :       call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
    3067              :       gpu_ptr = xomp_get_mapped_ptr(c_loc(r_work))
    3068              :     end if
    3069              : 
    3070              :   case (2)
    3071              :     ! resize work array if needed and retrieve work pointer to use
    3072              :     if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
    3073              :           .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    3074              :       call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
    3075              :       gpu_ptr = c_loc(c_work_managed)
    3076              :     else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3077              :       !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
    3078              :       !gpu_ptr = gpu_work
    3079              :       call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
    3080              :       gpu_ptr = xomp_get_mapped_ptr(c_loc(c_work))
    3081              :     end if
    3082              : 
    3083              :   end select
    3084              : 
    3085              :   ! and compute (finally)
    3086              :   call gpu_xpotrf(cplx, uplo, &
    3087              :                  A_nrows, &
    3088              :                  A, lda, &
    3089              :                  gpu_ptr, bufferSize, devInfo)
    3090              : 
    3091              :   if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3092              :     ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
    3093              :     ! Therefore, we issue a stream sync here to avoid
    3094              :     !potential mistakes in calling context.
    3095              :     call gpu_linalg_stream_synchronize()
    3096              :   end if
    3097              : 
    3098              : #else
    3099              :   ! Unused if GPU code disabled
    3100              :   ABI_UNUSED((/cplx,A_nrows,lda,devInfo,bufferSize/))
    3101              :   ABI_UNUSED((/uplo/))
    3102              :   ABI_UNUSED((/A,gpu_ptr/))
    3103              : #endif
    3104              : 
    3105            0 : end subroutine abi_gpu_xpotrf_cptr
    3106              : !!***
    3107              : 
    3108            0 : subroutine abi_gpu_xpotrf_d(cplx, uplo, A_nrows, &
    3109              :                    A, lda, &
    3110              :                    devInfo)
    3111              : 
    3112              :   ! Arguments ------------------------------------
    3113              :   integer,         intent(in   ) :: cplx
    3114              :   character(len=1),intent(in   ) :: uplo
    3115              :   integer,         intent(in   ) :: A_nrows
    3116              :   real(dp),        intent(in   ),target :: A(*)
    3117              :   integer,         intent(in   ) :: lda
    3118              :   integer,         intent(inout) :: devInfo
    3119              : ! *************************************************************************
    3120              : 
    3121            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    3122              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3123              :                  A_nrows, &
    3124              :                  c_loc(A), lda, &
    3125            0 :                  devInfo)
    3126            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3127              : #ifdef HAVE_OPENMP_OFFLOAD
    3128              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A)
    3129              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3130              :                  A_nrows, &
    3131              :                  c_loc(A), lda, &
    3132              :                  devInfo)
    3133              :     !$OMP END TARGET DATA
    3134              : #endif
    3135              :   else
    3136            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    3137              :   end if
    3138              : 
    3139            0 : end subroutine abi_gpu_xpotrf_d
    3140              : !!***
    3141              : 
    3142            0 : subroutine abi_gpu_xpotrf_z(cplx, uplo, A_nrows, &
    3143              :                    A, lda, &
    3144              :                    devInfo)
    3145              : 
    3146              :   ! Arguments ------------------------------------
    3147              :   integer,         intent(in   ) :: cplx
    3148              :   character(len=1),intent(in   ) :: uplo
    3149              :   integer,         intent(in   ) :: A_nrows
    3150              :   complex(dp),    intent(in   ),target :: A(*)
    3151              :   integer,         intent(in   ) :: lda
    3152              :   integer,         intent(inout) :: devInfo
    3153              : ! *************************************************************************
    3154              : 
    3155            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    3156              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3157              :                  A_nrows, &
    3158              :                  c_loc(A), lda, &
    3159            0 :                  devInfo)
    3160            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3161              : #ifdef HAVE_OPENMP_OFFLOAD
    3162              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A)
    3163              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3164              :                  A_nrows, &
    3165              :                  c_loc(A), lda, &
    3166              :                  devInfo)
    3167              :     !$OMP END TARGET DATA
    3168              : #endif
    3169              :   else
    3170            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    3171              :   end if
    3172              : 
    3173            0 : end subroutine abi_gpu_xpotrf_z
    3174              : !!***
    3175              : 
    3176            0 : subroutine abi_gpu_xpotrf_2d(cplx, uplo, A_nrows, &
    3177            0 :                    A, lda, &
    3178              :                    devInfo)
    3179              : 
    3180              :   ! Arguments ------------------------------------
    3181              :   integer,         intent(in   ) :: cplx
    3182              :   character(len=1),intent(in   ) :: uplo
    3183              :   integer,         intent(in   ) :: A_nrows,lda
    3184              :   real(dp),        intent(in   ),target :: A(lda,*)
    3185              :   integer,         intent(inout) :: devInfo
    3186              : ! *************************************************************************
    3187              : 
    3188            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    3189              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3190              :                  A_nrows, &
    3191              :                  c_loc(A), lda, &
    3192            0 :                  devInfo)
    3193            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3194              : #ifdef HAVE_OPENMP_OFFLOAD
    3195              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A)
    3196              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3197              :                  A_nrows, &
    3198              :                  c_loc(A), lda, &
    3199              :                  devInfo)
    3200              :     !$OMP END TARGET DATA
    3201              : #endif
    3202              :   else
    3203            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    3204              :   end if
    3205              : 
    3206            0 : end subroutine abi_gpu_xpotrf_2d
    3207              : !!***
    3208              : 
    3209            0 : subroutine abi_gpu_xpotrf_2z(cplx, uplo, A_nrows, &
    3210            0 :                    A, lda, &
    3211              :                    devInfo)
    3212              : 
    3213              :   ! Arguments ------------------------------------
    3214              :   integer,         intent(in   ) :: cplx
    3215              :   character(len=1),intent(in   ) :: uplo
    3216              :   integer,         intent(in   ) :: A_nrows,lda
    3217              :   complex(dp),    intent(in   ),target :: A(lda,*)
    3218              :   integer,         intent(inout) :: devInfo
    3219              : ! *************************************************************************
    3220              : 
    3221            0 :   if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
    3222              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3223              :                  A_nrows, &
    3224              :                  c_loc(A), lda, &
    3225            0 :                  devInfo)
    3226            0 :   else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
    3227              : #ifdef HAVE_OPENMP_OFFLOAD
    3228              :     !$OMP TARGET DATA USE_DEVICE_ADDR(A)
    3229              :     call abi_gpu_xpotrf_cptr(cplx, uplo, &
    3230              :                  A_nrows, &
    3231              :                  c_loc(A), lda, &
    3232              :                  devInfo)
    3233              :     !$OMP END TARGET DATA
    3234              : #endif
    3235              :   else
    3236            0 :     ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
    3237              :   end if
    3238              : 
    3239            0 : end subroutine abi_gpu_xpotrf_2z
    3240              : !!***
    3241              : 
    3242              : !!****f* m_abi_linalg/gpu_xorthonormalize
    3243              : !! NAME
    3244              : !!  gpu_xorthonormalize
    3245              : !!
    3246              : !! FUNCTION
    3247              : !!  This routine computes the overlap of two complex wavefunctions (for a given number of bands)
    3248              : !!  and orthonormalizes it using gpu:
    3249              : !!      - Computes the products of two rectangular matrices
    3250              : !!         containing the wavefunctions psi and S.psi (where S is the
    3251              : !!         overlap (with the PAW terms if necessary)).
    3252              : !!      - Does a Cholesky decomposition of this overlap
    3253              : !!      - rotates the initial matrix blockvectorx by the triangular matrix to
    3254              : !!         have an orthonormal set of wavefunctions
    3255              : !!
    3256              : !! INPUTS
    3257              : !!  blockvectorbx = matrix of dimension (blocksize,vectsize) as a GPU ptr
    3258              : !!                  (e.g. block of overlap*wavefunction)
    3259              : !!  blocksize     = dimension of matrices (e.g number of bands)
    3260              : !!  spaceComm     = communicator used for  MPI parallelization
    3261              : !!  vectsize      = dimension of matrices (e.g number of G vector)
    3262              : !!
    3263              : !! OUTPUT
    3264              : !!  sqgram        = Choleski decomposition of transpose(blockvector)*blockvectorx as a GPU ptr
    3265              : !!
    3266              : !! SIDE EFFECTS
    3267              : !!  blockvectorx  = on input, matrix of dimension (vectsize,blocksize) as a GPU ptr
    3268              : !!                  (e.g block of wavefunction)
    3269              : !!  blockvectorx  = on output, orthonormalized wavefunction. as a GPU ptr
    3270              : !!
    3271              : !! SOURCE
    3272              : 
    3273            0 : subroutine gpu_xorthonormalize(blockvectorx_gpu,blockvectorbx_gpu,blocksize,spaceComm,&
    3274              : &                              sqgram_gpu,vectsize,&
    3275              : &                              x_cplx,timopt,tim_xortho) ! optional arguments
    3276              : 
    3277              : !Arguments ------------------------------------
    3278              : !scalars
    3279              :  integer,intent(in) :: blocksize,spaceComm,vectsize,x_cplx
    3280              :  integer, intent(in), optional :: timopt,tim_xortho
    3281              : !arrays
    3282              :  type(c_ptr),intent(inout) :: blockvectorbx_gpu, blockvectorx_gpu, sqgram_gpu
    3283              : !Local variables-------------------------------
    3284              : #if defined HAVE_GPU
    3285              :  integer :: ierr,info
    3286              :  real(dp),    dimension(:,:),allocatable, target :: d_sqgram
    3287              :  complex(dp),dimension(:,:),allocatable, target :: z_sqgram
    3288              :  character :: tr
    3289              :  real(dp) :: tsec(2)
    3290              :  integer(c_size_t) :: size
    3291              : #else
    3292              :  type(c_ptr) :: cptr_a
    3293              : #endif
    3294              :  character(len=500) :: message
    3295              : ! *********************************************************************
    3296              : 
    3297              : #if defined HAVE_GPU
    3298              :  if (present(tim_xortho).and.present(timopt)) then
    3299              :    if(abs(timopt)==3) then
    3300              :      call timab(tim_xortho,1,tsec)
    3301              :    end if
    3302              :  end if
    3303              : 
    3304              :  if ( x_cplx == 1 ) then
    3305              :    tr='t'
    3306              :    ABI_MALLOC(d_sqgram,(blocksize,blocksize))
    3307              :  else
    3308              :    tr='c'
    3309              :    ABI_MALLOC(z_sqgram,(blocksize,blocksize))
    3310              :  end if
    3311              : 
    3312              :  call gpu_xgemm(x_cplx,tr,'n',blocksize,blocksize,vectsize, &
    3313              : & cone,blockvectorx_gpu,vectsize,blockvectorbx_gpu,vectsize,czero,sqgram_gpu,blocksize)
    3314              :  call gpu_device_synchronize()
    3315              :    size=x_cplx*dp*blocksize*blocksize
    3316              : 
    3317              :  if ( x_cplx == 1 ) then
    3318              :    call copy_from_gpu(d_sqgram, sqgram_gpu, INT(x_cplx, c_size_t)*dp*blocksize*blocksize)
    3319              :    call xmpi_sum(d_sqgram,spaceComm,ierr)
    3320              :    call abi_xpotrf('u',blocksize,d_sqgram,blocksize,info)
    3321              :    call copy_on_gpu(d_sqgram, sqgram_gpu, INT(x_cplx, c_size_t)*dp*blocksize*blocksize)
    3322              :  else
    3323              :    call copy_from_gpu(z_sqgram, sqgram_gpu, size)
    3324              :    call xmpi_sum(z_sqgram,spaceComm,ierr)
    3325              :    call abi_xpotrf('u',blocksize,z_sqgram,blocksize,info)
    3326              :    call copy_on_gpu(z_sqgram, sqgram_gpu, size)
    3327              :  end if
    3328              : 
    3329              :  if (info /= 0 ) then
    3330              :    write(message,'(a,i3)') '  xpotrf, info=',info
    3331              :    ABI_WARNING(message)
    3332              :  end if
    3333              : 
    3334              :  call gpu_xtrsm(x_cplx,'r','u','n','n',vectsize,blocksize,cone,sqgram_gpu,blocksize,&
    3335              : &               blockvectorx_gpu,vectsize)
    3336              : 
    3337              :  if(x_cplx==1) then
    3338              :    ABI_FREE(d_sqgram)
    3339              :  else
    3340              :    ABI_FREE(z_sqgram)
    3341              :  end if
    3342              :  if (present(tim_xortho).and.present(timopt)) then
    3343              :    if(abs(timopt)==3) then
    3344              :      call timab(tim_xortho,2,tsec)
    3345              :    end if
    3346              :  end if
    3347              :  return
    3348              : 
    3349              : #else
    3350            0 :  message='  This routine is not allowed when running on GPU is disabled !'
    3351            0 :  ABI_BUG(message)
    3352              :  if (.false.) then
    3353              :    write(std_out,*) blocksize,vectsize,spaceComm,x_cplx
    3354              :    if (present(timopt))  write(std_out,*) timopt
    3355              :    if (present(tim_xortho))  write(std_out,*) tim_xortho
    3356              :    cptr_a=blockvectorbx_gpu;cptr_a=blockvectorx_gpu;cptr_a=sqgram_gpu
    3357              :  end if
    3358              : #endif
    3359              : 
    3360            0 : end subroutine gpu_xorthonormalize
    3361              : !!***
        

Generated by: LCOV version 2.3-1