xref: /libCEED/rust/libceed-sys/c-src/backends/hip-ref/ceed-hip-ref-vector.c (revision 43c928f447e928df3e15bd3ef094ec32ef0950a7)
10d0321e0SJeremy L Thompson // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
20d0321e0SJeremy L Thompson // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
30d0321e0SJeremy L Thompson // All Rights reserved. See files LICENSE and NOTICE for details.
40d0321e0SJeremy L Thompson //
50d0321e0SJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software
60d0321e0SJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral
70d0321e0SJeremy L Thompson // element discretizations for exascale applications. For more information and
80d0321e0SJeremy L Thompson // source code availability see http://github.com/ceed.
90d0321e0SJeremy L Thompson //
100d0321e0SJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
110d0321e0SJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office
120d0321e0SJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for
130d0321e0SJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including
140d0321e0SJeremy L Thompson // software, applications, hardware, advanced system engineering and early
150d0321e0SJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative.
160d0321e0SJeremy L Thompson 
170d0321e0SJeremy L Thompson #include <ceed/ceed.h>
180d0321e0SJeremy L Thompson #include <ceed/backend.h>
190d0321e0SJeremy L Thompson #include <hip/hip_runtime.h>
200d0321e0SJeremy L Thompson #include <hipblas.h>
210d0321e0SJeremy L Thompson #include <math.h>
220d0321e0SJeremy L Thompson #include <string.h>
230d0321e0SJeremy L Thompson #include "ceed-hip-ref.h"
240d0321e0SJeremy L Thompson 
250d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
260d0321e0SJeremy L Thompson // * Bytes used
270d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
280d0321e0SJeremy L Thompson static inline size_t bytes(const CeedVector vec) {
290d0321e0SJeremy L Thompson   int ierr;
300d0321e0SJeremy L Thompson   CeedInt length;
310d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
320d0321e0SJeremy L Thompson   return length * sizeof(CeedScalar);
330d0321e0SJeremy L Thompson }
340d0321e0SJeremy L Thompson 
350d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
360d0321e0SJeremy L Thompson // Sync host to device
370d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
380d0321e0SJeremy L Thompson static inline int CeedVectorSyncH2D_Hip(const CeedVector vec) {
390d0321e0SJeremy L Thompson   int ierr;
400d0321e0SJeremy L Thompson   Ceed ceed;
410d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
420d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
430d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
440d0321e0SJeremy L Thompson 
450d0321e0SJeremy L Thompson   if (!impl->h_array)
460d0321e0SJeremy L Thompson     // LCOV_EXCL_START
470d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
480d0321e0SJeremy L Thompson                      "No valid host data to sync to device");
490d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
500d0321e0SJeremy L Thompson 
510d0321e0SJeremy L Thompson   if (impl->d_array_borrowed) {
520d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_borrowed;
530d0321e0SJeremy L Thompson   } else if (impl->d_array_owned) {
540d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_owned;
550d0321e0SJeremy L Thompson   } else {
560d0321e0SJeremy L Thompson     ierr = hipMalloc((void **)&impl->d_array_owned, bytes(vec));
570d0321e0SJeremy L Thompson     CeedChk_Hip(ceed, ierr);
580d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_owned;
590d0321e0SJeremy L Thompson   }
600d0321e0SJeremy L Thompson 
610d0321e0SJeremy L Thompson   ierr = hipMemcpy(impl->d_array, impl->h_array, bytes(vec),
620d0321e0SJeremy L Thompson                    hipMemcpyHostToDevice); CeedChk_Hip(ceed, ierr);
630d0321e0SJeremy L Thompson 
640d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
650d0321e0SJeremy L Thompson }
660d0321e0SJeremy L Thompson 
670d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
680d0321e0SJeremy L Thompson // Sync device to host
690d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
700d0321e0SJeremy L Thompson static inline int CeedVectorSyncD2H_Hip(const CeedVector vec) {
710d0321e0SJeremy L Thompson   int ierr;
720d0321e0SJeremy L Thompson   Ceed ceed;
730d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
740d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
750d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
760d0321e0SJeremy L Thompson 
770d0321e0SJeremy L Thompson   if (!impl->d_array)
780d0321e0SJeremy L Thompson     // LCOV_EXCL_START
790d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
800d0321e0SJeremy L Thompson                      "No valid device data to sync to host");
810d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
820d0321e0SJeremy L Thompson 
830d0321e0SJeremy L Thompson   if (impl->h_array_borrowed) {
840d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_borrowed;
850d0321e0SJeremy L Thompson   } else if (impl->h_array_owned) {
860d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_owned;
870d0321e0SJeremy L Thompson   } else {
880d0321e0SJeremy L Thompson     CeedInt length;
890d0321e0SJeremy L Thompson     ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
900d0321e0SJeremy L Thompson     ierr = CeedCalloc(length, &impl->h_array_owned); CeedChkBackend(ierr);
910d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_owned;
920d0321e0SJeremy L Thompson   }
930d0321e0SJeremy L Thompson 
940d0321e0SJeremy L Thompson   ierr = hipMemcpy(impl->h_array, impl->d_array, bytes(vec),
950d0321e0SJeremy L Thompson                    hipMemcpyDeviceToHost); CeedChk_Hip(ceed, ierr);
960d0321e0SJeremy L Thompson 
970d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
980d0321e0SJeremy L Thompson }
990d0321e0SJeremy L Thompson 
1000d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1010d0321e0SJeremy L Thompson // Sync arrays
1020d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
103*43c928f4SJeremy L Thompson static inline int CeedVectorSync_Hip(const CeedVector vec,
104*43c928f4SJeremy L Thompson                                      CeedMemType mem_type) {
105*43c928f4SJeremy L Thompson   switch (mem_type) {
1060d0321e0SJeremy L Thompson   case CEED_MEM_HOST: return CeedVectorSyncD2H_Hip(vec);
1070d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE: return CeedVectorSyncH2D_Hip(vec);
1080d0321e0SJeremy L Thompson   }
1090d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
1100d0321e0SJeremy L Thompson }
1110d0321e0SJeremy L Thompson 
1120d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1130d0321e0SJeremy L Thompson // Set all pointers as invalid
1140d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1150d0321e0SJeremy L Thompson static inline int CeedVectorSetAllInvalid_Hip(const CeedVector vec) {
1160d0321e0SJeremy L Thompson   int ierr;
1170d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
1180d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
1190d0321e0SJeremy L Thompson 
1200d0321e0SJeremy L Thompson   impl->h_array = NULL;
1210d0321e0SJeremy L Thompson   impl->d_array = NULL;
1220d0321e0SJeremy L Thompson 
1230d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1240d0321e0SJeremy L Thompson }
1250d0321e0SJeremy L Thompson 
1260d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1270d0321e0SJeremy L Thompson // Check if CeedVector has any valid pointers
1280d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1290d0321e0SJeremy L Thompson static inline int CeedVectorHasValidArray_Hip(const CeedVector vec,
1300d0321e0SJeremy L Thompson     bool *has_valid_array) {
1310d0321e0SJeremy L Thompson   int ierr;
1320d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
1330d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
1340d0321e0SJeremy L Thompson 
1350d0321e0SJeremy L Thompson   *has_valid_array = !!impl->h_array || !!impl->d_array;
1360d0321e0SJeremy L Thompson 
1370d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1380d0321e0SJeremy L Thompson }
1390d0321e0SJeremy L Thompson 
1400d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1410d0321e0SJeremy L Thompson // Check if has any array of given type
1420d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1430d0321e0SJeremy L Thompson static inline int CeedVectorHasArrayOfType_Hip(const CeedVector vec,
144*43c928f4SJeremy L Thompson     CeedMemType mem_type, bool *has_array_of_type) {
1450d0321e0SJeremy L Thompson   int ierr;
1460d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
1470d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
1480d0321e0SJeremy L Thompson 
149*43c928f4SJeremy L Thompson   switch (mem_type) {
1500d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1510d0321e0SJeremy L Thompson     *has_array_of_type = !!impl->h_array_borrowed || !!impl->h_array_owned;
1520d0321e0SJeremy L Thompson     break;
1530d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1540d0321e0SJeremy L Thompson     *has_array_of_type = !!impl->d_array_borrowed || !!impl->d_array_owned;
1550d0321e0SJeremy L Thompson     break;
1560d0321e0SJeremy L Thompson   }
1570d0321e0SJeremy L Thompson 
1580d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1590d0321e0SJeremy L Thompson }
1600d0321e0SJeremy L Thompson 
1610d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1620d0321e0SJeremy L Thompson // Check if has borrowed array of given type
1630d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1640d0321e0SJeremy L Thompson static inline int CeedVectorHasBorrowedArrayOfType_Hip(const CeedVector vec,
165*43c928f4SJeremy L Thompson     CeedMemType mem_type, bool *has_borrowed_array_of_type) {
1660d0321e0SJeremy L Thompson   int ierr;
1670d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
1680d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
1690d0321e0SJeremy L Thompson 
170*43c928f4SJeremy L Thompson   switch (mem_type) {
1710d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1720d0321e0SJeremy L Thompson     *has_borrowed_array_of_type = !!impl->h_array_borrowed;
1730d0321e0SJeremy L Thompson     break;
1740d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1750d0321e0SJeremy L Thompson     *has_borrowed_array_of_type = !!impl->d_array_borrowed;
1760d0321e0SJeremy L Thompson     break;
1770d0321e0SJeremy L Thompson   }
1780d0321e0SJeremy L Thompson 
1790d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1800d0321e0SJeremy L Thompson }
1810d0321e0SJeremy L Thompson 
1820d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1830d0321e0SJeremy L Thompson // Sync array of given type
1840d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1850d0321e0SJeremy L Thompson static inline int CeedVectorNeedSync_Hip(const CeedVector vec,
186*43c928f4SJeremy L Thompson     CeedMemType mem_type, bool *need_sync) {
1870d0321e0SJeremy L Thompson   int ierr;
1880d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
1890d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
1900d0321e0SJeremy L Thompson 
1910d0321e0SJeremy L Thompson   bool has_valid_array = false;
1920d0321e0SJeremy L Thompson   ierr = CeedVectorHasValidArray(vec, &has_valid_array); CeedChkBackend(ierr);
193*43c928f4SJeremy L Thompson   switch (mem_type) {
1940d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1950d0321e0SJeremy L Thompson     *need_sync = has_valid_array && !impl->h_array;
1960d0321e0SJeremy L Thompson     break;
1970d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1980d0321e0SJeremy L Thompson     *need_sync = has_valid_array && !impl->d_array;
1990d0321e0SJeremy L Thompson     break;
2000d0321e0SJeremy L Thompson   }
2010d0321e0SJeremy L Thompson 
2020d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2030d0321e0SJeremy L Thompson }
2040d0321e0SJeremy L Thompson 
2050d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2060d0321e0SJeremy L Thompson // Set array from host
2070d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2080d0321e0SJeremy L Thompson static int CeedVectorSetArrayHost_Hip(const CeedVector vec,
209*43c928f4SJeremy L Thompson                                       const CeedCopyMode copy_mode, CeedScalar *array) {
2100d0321e0SJeremy L Thompson   int ierr;
2110d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
2120d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
2130d0321e0SJeremy L Thompson 
214*43c928f4SJeremy L Thompson   switch (copy_mode) {
2150d0321e0SJeremy L Thompson   case CEED_COPY_VALUES: {
2160d0321e0SJeremy L Thompson     CeedInt length;
2170d0321e0SJeremy L Thompson     if (!impl->h_array_owned) {
2180d0321e0SJeremy L Thompson       ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
2190d0321e0SJeremy L Thompson       ierr = CeedMalloc(length, &impl->h_array_owned); CeedChkBackend(ierr);
2200d0321e0SJeremy L Thompson     }
2210d0321e0SJeremy L Thompson     impl->h_array_borrowed = NULL;
2220d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_owned;
2230d0321e0SJeremy L Thompson     if (array)
2240d0321e0SJeremy L Thompson       memcpy(impl->h_array, array, bytes(vec));
2250d0321e0SJeremy L Thompson   } break;
2260d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
2270d0321e0SJeremy L Thompson     ierr = CeedFree(&impl->h_array_owned); CeedChkBackend(ierr);
2280d0321e0SJeremy L Thompson     impl->h_array_owned = array;
2290d0321e0SJeremy L Thompson     impl->h_array_borrowed = NULL;
2300d0321e0SJeremy L Thompson     impl->h_array = array;
2310d0321e0SJeremy L Thompson     break;
2320d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
2330d0321e0SJeremy L Thompson     ierr = CeedFree(&impl->h_array_owned); CeedChkBackend(ierr);
2340d0321e0SJeremy L Thompson     impl->h_array_borrowed = array;
2350d0321e0SJeremy L Thompson     impl->h_array = array;
2360d0321e0SJeremy L Thompson     break;
2370d0321e0SJeremy L Thompson   }
2380d0321e0SJeremy L Thompson 
2390d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2400d0321e0SJeremy L Thompson }
2410d0321e0SJeremy L Thompson 
2420d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2430d0321e0SJeremy L Thompson // Set array from device
2440d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2450d0321e0SJeremy L Thompson static int CeedVectorSetArrayDevice_Hip(const CeedVector vec,
246*43c928f4SJeremy L Thompson                                         const CeedCopyMode copy_mode, CeedScalar *array) {
2470d0321e0SJeremy L Thompson   int ierr;
2480d0321e0SJeremy L Thompson   Ceed ceed;
2490d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
2500d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
2510d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
2520d0321e0SJeremy L Thompson 
253*43c928f4SJeremy L Thompson   switch (copy_mode) {
2540d0321e0SJeremy L Thompson   case CEED_COPY_VALUES:
2550d0321e0SJeremy L Thompson     if (!impl->d_array_owned) {
2560d0321e0SJeremy L Thompson       ierr = hipMalloc((void **)&impl->d_array_owned, bytes(vec));
2570d0321e0SJeremy L Thompson       CeedChk_Hip(ceed, ierr);
2580d0321e0SJeremy L Thompson     }
2590d0321e0SJeremy L Thompson     impl->d_array_borrowed = NULL;
2600d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_owned;
2610d0321e0SJeremy L Thompson     if (array) {
2620d0321e0SJeremy L Thompson       ierr = hipMemcpy(impl->d_array, array, bytes(vec),
2630d0321e0SJeremy L Thompson                        hipMemcpyDeviceToDevice); CeedChk_Hip(ceed, ierr);
2640d0321e0SJeremy L Thompson     }
2650d0321e0SJeremy L Thompson     break;
2660d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
2670d0321e0SJeremy L Thompson     ierr = hipFree(impl->d_array_owned); CeedChk_Hip(ceed, ierr);
2680d0321e0SJeremy L Thompson     impl->d_array_owned = array;
2690d0321e0SJeremy L Thompson     impl->d_array_borrowed = NULL;
2700d0321e0SJeremy L Thompson     impl->d_array = array;
2710d0321e0SJeremy L Thompson     break;
2720d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
2730d0321e0SJeremy L Thompson     ierr = hipFree(impl->d_array_owned); CeedChk_Hip(ceed, ierr);
2740d0321e0SJeremy L Thompson     impl->d_array_owned = NULL;
2750d0321e0SJeremy L Thompson     impl->d_array_borrowed = array;
2760d0321e0SJeremy L Thompson     impl->d_array = array;
2770d0321e0SJeremy L Thompson     break;
2780d0321e0SJeremy L Thompson   }
2790d0321e0SJeremy L Thompson 
2800d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2810d0321e0SJeremy L Thompson }
2820d0321e0SJeremy L Thompson 
2830d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2840d0321e0SJeremy L Thompson // Set the array used by a vector,
2850d0321e0SJeremy L Thompson //   freeing any previously allocated array if applicable
2860d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
287*43c928f4SJeremy L Thompson static int CeedVectorSetArray_Hip(const CeedVector vec,
288*43c928f4SJeremy L Thompson                                   const CeedMemType mem_type,
289*43c928f4SJeremy L Thompson                                   const CeedCopyMode copy_mode, CeedScalar *array) {
2900d0321e0SJeremy L Thompson   int ierr;
2910d0321e0SJeremy L Thompson   Ceed ceed;
2920d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
2930d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
2940d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
2950d0321e0SJeremy L Thompson 
2960d0321e0SJeremy L Thompson   ierr = CeedVectorSetAllInvalid_Hip(vec); CeedChkBackend(ierr);
297*43c928f4SJeremy L Thompson   switch (mem_type) {
2980d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
299*43c928f4SJeremy L Thompson     return CeedVectorSetArrayHost_Hip(vec, copy_mode, array);
3000d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
301*43c928f4SJeremy L Thompson     return CeedVectorSetArrayDevice_Hip(vec, copy_mode, array);
3020d0321e0SJeremy L Thompson   }
3030d0321e0SJeremy L Thompson 
3040d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
3050d0321e0SJeremy L Thompson }
3060d0321e0SJeremy L Thompson 
3070d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3080d0321e0SJeremy L Thompson // Set host array to value
3090d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3100d0321e0SJeremy L Thompson static int CeedHostSetValue_Hip(CeedScalar *h_array, CeedInt length,
3110d0321e0SJeremy L Thompson                                 CeedScalar val) {
3120d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
3130d0321e0SJeremy L Thompson     h_array[i] = val;
3140d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3150d0321e0SJeremy L Thompson }
3160d0321e0SJeremy L Thompson 
3170d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3180d0321e0SJeremy L Thompson // Set device array to value (impl in .hip file)
3190d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3200d0321e0SJeremy L Thompson int CeedDeviceSetValue_Hip(CeedScalar *d_array, CeedInt length, CeedScalar val);
3210d0321e0SJeremy L Thompson 
3220d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3230d0321e0SJeremy L Thompson // Set a vector to a value,
3240d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3250d0321e0SJeremy L Thompson static int CeedVectorSetValue_Hip(CeedVector vec, CeedScalar val) {
3260d0321e0SJeremy L Thompson   int ierr;
3270d0321e0SJeremy L Thompson   Ceed ceed;
3280d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
3290d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
3300d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
3310d0321e0SJeremy L Thompson   CeedInt length;
3320d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
3330d0321e0SJeremy L Thompson 
3340d0321e0SJeremy L Thompson   // Set value for synced device/host array
3350d0321e0SJeremy L Thompson   if (!impl->d_array && !impl->h_array) {
3360d0321e0SJeremy L Thompson     if (impl->d_array_borrowed) {
3370d0321e0SJeremy L Thompson       impl->d_array = impl->d_array_borrowed;
3380d0321e0SJeremy L Thompson     } else if (impl->h_array_borrowed) {
3390d0321e0SJeremy L Thompson       impl->h_array = impl->h_array_borrowed;
3400d0321e0SJeremy L Thompson     } else if (impl->d_array_owned) {
3410d0321e0SJeremy L Thompson       impl->d_array = impl->d_array_owned;
3420d0321e0SJeremy L Thompson     } else if (impl->h_array_owned) {
3430d0321e0SJeremy L Thompson       impl->h_array = impl->h_array_owned;
3440d0321e0SJeremy L Thompson     } else {
3450d0321e0SJeremy L Thompson       ierr = CeedVectorSetArray(vec, CEED_MEM_DEVICE, CEED_COPY_VALUES, NULL);
3460d0321e0SJeremy L Thompson       CeedChkBackend(ierr);
3470d0321e0SJeremy L Thompson     }
3480d0321e0SJeremy L Thompson   }
3490d0321e0SJeremy L Thompson   if (impl->d_array) {
3500d0321e0SJeremy L Thompson     ierr = CeedDeviceSetValue_Hip(impl->d_array, length, val); CeedChkBackend(ierr);
3510d0321e0SJeremy L Thompson   }
3520d0321e0SJeremy L Thompson   if (impl->h_array) {
3530d0321e0SJeremy L Thompson     ierr = CeedHostSetValue_Hip(impl->h_array, length, val); CeedChkBackend(ierr);
3540d0321e0SJeremy L Thompson   }
3550d0321e0SJeremy L Thompson 
3560d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3570d0321e0SJeremy L Thompson }
3580d0321e0SJeremy L Thompson 
3590d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3600d0321e0SJeremy L Thompson // Vector Take Array
3610d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
362*43c928f4SJeremy L Thompson static int CeedVectorTakeArray_Hip(CeedVector vec, CeedMemType mem_type,
3630d0321e0SJeremy L Thompson                                    CeedScalar **array) {
3640d0321e0SJeremy L Thompson   int ierr;
3650d0321e0SJeremy L Thompson   Ceed ceed;
3660d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
3670d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
3680d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
3690d0321e0SJeremy L Thompson 
370*43c928f4SJeremy L Thompson   // Sync array to requested mem_type
3710d0321e0SJeremy L Thompson   bool need_sync = false;
372*43c928f4SJeremy L Thompson   ierr = CeedVectorNeedSync_Hip(vec, mem_type, &need_sync); CeedChkBackend(ierr);
3730d0321e0SJeremy L Thompson   if (need_sync) {
374*43c928f4SJeremy L Thompson     ierr = CeedVectorSync_Hip(vec, mem_type); CeedChkBackend(ierr);
3750d0321e0SJeremy L Thompson   }
3760d0321e0SJeremy L Thompson 
3770d0321e0SJeremy L Thompson   // Update pointer
378*43c928f4SJeremy L Thompson   switch (mem_type) {
3790d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
3800d0321e0SJeremy L Thompson     (*array) = impl->h_array_borrowed;
3810d0321e0SJeremy L Thompson     impl->h_array_borrowed = NULL;
3820d0321e0SJeremy L Thompson     impl->h_array = NULL;
3830d0321e0SJeremy L Thompson     break;
3840d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
3850d0321e0SJeremy L Thompson     (*array) = impl->d_array_borrowed;
3860d0321e0SJeremy L Thompson     impl->d_array_borrowed = NULL;
3870d0321e0SJeremy L Thompson     impl->d_array = NULL;
3880d0321e0SJeremy L Thompson     break;
3890d0321e0SJeremy L Thompson   }
3900d0321e0SJeremy L Thompson 
3910d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3920d0321e0SJeremy L Thompson }
3930d0321e0SJeremy L Thompson 
3940d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3950d0321e0SJeremy L Thompson // Core logic for array syncronization for GetArray.
3960d0321e0SJeremy L Thompson //   If a different memory type is most up to date, this will perform a copy
3970d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3980d0321e0SJeremy L Thompson static int CeedVectorGetArrayCore_Hip(const CeedVector vec,
399*43c928f4SJeremy L Thompson                                       const CeedMemType mem_type, CeedScalar **array) {
4000d0321e0SJeremy L Thompson   int ierr;
4010d0321e0SJeremy L Thompson   Ceed ceed;
4020d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
4030d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
4040d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
4050d0321e0SJeremy L Thompson 
4060d0321e0SJeremy L Thompson   bool need_sync = false;
407*43c928f4SJeremy L Thompson   ierr = CeedVectorNeedSync_Hip(vec, mem_type, &need_sync); CeedChkBackend(ierr);
4080d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
4090d0321e0SJeremy L Thompson   if (need_sync) {
410*43c928f4SJeremy L Thompson     // Sync array to requested mem_type
411*43c928f4SJeremy L Thompson     ierr = CeedVectorSync_Hip(vec, mem_type); CeedChkBackend(ierr);
4120d0321e0SJeremy L Thompson   }
4130d0321e0SJeremy L Thompson 
4140d0321e0SJeremy L Thompson   // Update pointer
415*43c928f4SJeremy L Thompson   switch (mem_type) {
4160d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
4170d0321e0SJeremy L Thompson     *array = impl->h_array;
4180d0321e0SJeremy L Thompson     break;
4190d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
4200d0321e0SJeremy L Thompson     *array = impl->d_array;
4210d0321e0SJeremy L Thompson     break;
4220d0321e0SJeremy L Thompson   }
4230d0321e0SJeremy L Thompson 
4240d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4250d0321e0SJeremy L Thompson }
4260d0321e0SJeremy L Thompson 
4270d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
428*43c928f4SJeremy L Thompson // Get read-only access to a vector via the specified mem_type
4290d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
4300d0321e0SJeremy L Thompson static int CeedVectorGetArrayRead_Hip(const CeedVector vec,
431*43c928f4SJeremy L Thompson                                       const CeedMemType mem_type, const CeedScalar **array) {
432*43c928f4SJeremy L Thompson   return CeedVectorGetArrayCore_Hip(vec, mem_type, (CeedScalar **)array);
4330d0321e0SJeremy L Thompson }
4340d0321e0SJeremy L Thompson 
4350d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
436*43c928f4SJeremy L Thompson // Get read/write access to a vector via the specified mem_type
4370d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
438*43c928f4SJeremy L Thompson static int CeedVectorGetArray_Hip(const CeedVector vec,
439*43c928f4SJeremy L Thompson                                   const CeedMemType mem_type,
4400d0321e0SJeremy L Thompson                                   CeedScalar **array) {
4410d0321e0SJeremy L Thompson   int ierr;
4420d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
4430d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
4440d0321e0SJeremy L Thompson 
445*43c928f4SJeremy L Thompson   ierr = CeedVectorGetArrayCore_Hip(vec, mem_type, array); CeedChkBackend(ierr);
4460d0321e0SJeremy L Thompson 
4470d0321e0SJeremy L Thompson   ierr = CeedVectorSetAllInvalid_Hip(vec); CeedChkBackend(ierr);
448*43c928f4SJeremy L Thompson   switch (mem_type) {
4490d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
4500d0321e0SJeremy L Thompson     impl->h_array = *array;
4510d0321e0SJeremy L Thompson     break;
4520d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
4530d0321e0SJeremy L Thompson     impl->d_array = *array;
4540d0321e0SJeremy L Thompson     break;
4550d0321e0SJeremy L Thompson   }
4560d0321e0SJeremy L Thompson 
4570d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4580d0321e0SJeremy L Thompson }
4590d0321e0SJeremy L Thompson 
4600d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
461*43c928f4SJeremy L Thompson // Get write access to a vector via the specified mem_type
4620d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
4630d0321e0SJeremy L Thompson static int CeedVectorGetArrayWrite_Hip(const CeedVector vec,
464*43c928f4SJeremy L Thompson                                        const CeedMemType mem_type, CeedScalar **array) {
4650d0321e0SJeremy L Thompson   int ierr;
4660d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
4670d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
4680d0321e0SJeremy L Thompson 
4690d0321e0SJeremy L Thompson   bool has_array_of_type = true;
470*43c928f4SJeremy L Thompson   ierr = CeedVectorHasArrayOfType_Hip(vec, mem_type, &has_array_of_type);
4710d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
4720d0321e0SJeremy L Thompson   if (!has_array_of_type) {
4730d0321e0SJeremy L Thompson     // Allocate if array is not yet allocated
474*43c928f4SJeremy L Thompson     ierr = CeedVectorSetArray(vec, mem_type, CEED_COPY_VALUES, NULL);
4750d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
4760d0321e0SJeremy L Thompson   } else {
4770d0321e0SJeremy L Thompson     // Select dirty array
478*43c928f4SJeremy L Thompson     switch (mem_type) {
4790d0321e0SJeremy L Thompson     case CEED_MEM_HOST:
4800d0321e0SJeremy L Thompson       if (impl->h_array_borrowed)
4810d0321e0SJeremy L Thompson         impl->h_array = impl->h_array_borrowed;
4820d0321e0SJeremy L Thompson       else
4830d0321e0SJeremy L Thompson         impl->h_array = impl->h_array_owned;
4840d0321e0SJeremy L Thompson       break;
4850d0321e0SJeremy L Thompson     case CEED_MEM_DEVICE:
4860d0321e0SJeremy L Thompson       if (impl->d_array_borrowed)
4870d0321e0SJeremy L Thompson         impl->d_array = impl->d_array_borrowed;
4880d0321e0SJeremy L Thompson       else
4890d0321e0SJeremy L Thompson         impl->d_array = impl->d_array_owned;
4900d0321e0SJeremy L Thompson     }
4910d0321e0SJeremy L Thompson   }
4920d0321e0SJeremy L Thompson 
493*43c928f4SJeremy L Thompson   return CeedVectorGetArray_Hip(vec, mem_type, array);
4940d0321e0SJeremy L Thompson }
4950d0321e0SJeremy L Thompson 
4960d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
4970d0321e0SJeremy L Thompson // Restore an array obtained using CeedVectorGetArrayRead()
4980d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
4990d0321e0SJeremy L Thompson static int CeedVectorRestoreArrayRead_Hip(const CeedVector vec) {
5000d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5010d0321e0SJeremy L Thompson }
5020d0321e0SJeremy L Thompson 
5030d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5040d0321e0SJeremy L Thompson // Restore an array obtained using CeedVectorGetArray()
5050d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5060d0321e0SJeremy L Thompson static int CeedVectorRestoreArray_Hip(const CeedVector vec) {
5070d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5080d0321e0SJeremy L Thompson }
5090d0321e0SJeremy L Thompson 
5100d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5110d0321e0SJeremy L Thompson // Get the norm of a CeedVector
5120d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5130d0321e0SJeremy L Thompson static int CeedVectorNorm_Hip(CeedVector vec, CeedNormType type,
5140d0321e0SJeremy L Thompson                               CeedScalar *norm) {
5150d0321e0SJeremy L Thompson   int ierr;
5160d0321e0SJeremy L Thompson   Ceed ceed;
5170d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
5180d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
5190d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
5200d0321e0SJeremy L Thompson   CeedInt length;
5210d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
5220d0321e0SJeremy L Thompson   hipblasHandle_t handle;
5230d0321e0SJeremy L Thompson   ierr = CeedHipGetHipblasHandle(ceed, &handle); CeedChkBackend(ierr);
5240d0321e0SJeremy L Thompson 
5250d0321e0SJeremy L Thompson   // Compute norm
5260d0321e0SJeremy L Thompson   const CeedScalar *d_array;
5270d0321e0SJeremy L Thompson   ierr = CeedVectorGetArrayRead(vec, CEED_MEM_DEVICE, &d_array);
5280d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
5290d0321e0SJeremy L Thompson   switch (type) {
5300d0321e0SJeremy L Thompson   case CEED_NORM_1: {
5310d0321e0SJeremy L Thompson     if (CEED_SCALAR_TYPE == CEED_SCALAR_FP32) {
5320d0321e0SJeremy L Thompson       ierr = hipblasSasum(handle, length, (float *) d_array, 1, (float *) norm);
5330d0321e0SJeremy L Thompson     } else {
5340d0321e0SJeremy L Thompson       ierr = hipblasDasum(handle, length, (double *) d_array, 1, (double *) norm);
5350d0321e0SJeremy L Thompson     }
5360d0321e0SJeremy L Thompson     CeedChk_Hipblas(ceed, ierr);
5370d0321e0SJeremy L Thompson     break;
5380d0321e0SJeremy L Thompson   }
5390d0321e0SJeremy L Thompson   case CEED_NORM_2: {
5400d0321e0SJeremy L Thompson     if (CEED_SCALAR_TYPE == CEED_SCALAR_FP32) {
5410d0321e0SJeremy L Thompson       ierr = hipblasSnrm2(handle, length, (float *) d_array, 1, (float *) norm);
5420d0321e0SJeremy L Thompson     } else {
5430d0321e0SJeremy L Thompson       ierr = hipblasDnrm2(handle, length, (double *) d_array, 1, (double *) norm);
5440d0321e0SJeremy L Thompson     }
5450d0321e0SJeremy L Thompson     CeedChk_Hipblas(ceed, ierr);
5460d0321e0SJeremy L Thompson     break;
5470d0321e0SJeremy L Thompson   }
5480d0321e0SJeremy L Thompson   case CEED_NORM_MAX: {
5490d0321e0SJeremy L Thompson     CeedInt indx;
5500d0321e0SJeremy L Thompson     if (CEED_SCALAR_TYPE == CEED_SCALAR_FP32) {
5510d0321e0SJeremy L Thompson       ierr = hipblasIsamax(handle, length, (float *) d_array, 1, &indx);
5520d0321e0SJeremy L Thompson     } else {
5530d0321e0SJeremy L Thompson       ierr = hipblasIdamax(handle, length, (double *) d_array, 1, &indx);
5540d0321e0SJeremy L Thompson     }
5550d0321e0SJeremy L Thompson     CeedChk_Hipblas(ceed, ierr);
5560d0321e0SJeremy L Thompson     CeedScalar normNoAbs;
5570d0321e0SJeremy L Thompson     ierr = hipMemcpy(&normNoAbs, impl->d_array+indx-1, sizeof(CeedScalar),
5580d0321e0SJeremy L Thompson                      hipMemcpyDeviceToHost); CeedChk_Hip(ceed, ierr);
5590d0321e0SJeremy L Thompson     *norm = fabs(normNoAbs);
5600d0321e0SJeremy L Thompson     break;
5610d0321e0SJeremy L Thompson   }
5620d0321e0SJeremy L Thompson   }
5630d0321e0SJeremy L Thompson   ierr = CeedVectorRestoreArrayRead(vec, &d_array); CeedChkBackend(ierr);
5640d0321e0SJeremy L Thompson 
5650d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5660d0321e0SJeremy L Thompson }
5670d0321e0SJeremy L Thompson 
5680d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5690d0321e0SJeremy L Thompson // Take reciprocal of a vector on host
5700d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5710d0321e0SJeremy L Thompson static int CeedHostReciprocal_Hip(CeedScalar *h_array, CeedInt length) {
5720d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
5730d0321e0SJeremy L Thompson     if (fabs(h_array[i]) > CEED_EPSILON)
5740d0321e0SJeremy L Thompson       h_array[i] = 1./h_array[i];
5750d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5760d0321e0SJeremy L Thompson }
5770d0321e0SJeremy L Thompson 
5780d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5790d0321e0SJeremy L Thompson // Take reciprocal of a vector on device (impl in .cu file)
5800d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5810d0321e0SJeremy L Thompson int CeedDeviceReciprocal_Hip(CeedScalar *d_array, CeedInt length);
5820d0321e0SJeremy L Thompson 
5830d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5840d0321e0SJeremy L Thompson // Take reciprocal of a vector
5850d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
5860d0321e0SJeremy L Thompson static int CeedVectorReciprocal_Hip(CeedVector vec) {
5870d0321e0SJeremy L Thompson   int ierr;
5880d0321e0SJeremy L Thompson   Ceed ceed;
5890d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
5900d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
5910d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
5920d0321e0SJeremy L Thompson   CeedInt length;
5930d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
5940d0321e0SJeremy L Thompson 
5950d0321e0SJeremy L Thompson   // Set value for synced device/host array
5960d0321e0SJeremy L Thompson   if (impl->d_array) {
5970d0321e0SJeremy L Thompson     ierr = CeedDeviceReciprocal_Hip(impl->d_array, length); CeedChkBackend(ierr);
5980d0321e0SJeremy L Thompson   }
5990d0321e0SJeremy L Thompson   if (impl->h_array) {
6000d0321e0SJeremy L Thompson     ierr = CeedHostReciprocal_Hip(impl->h_array, length); CeedChkBackend(ierr);
6010d0321e0SJeremy L Thompson   }
6020d0321e0SJeremy L Thompson 
6030d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6040d0321e0SJeremy L Thompson }
6050d0321e0SJeremy L Thompson 
6060d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6070d0321e0SJeremy L Thompson // Compute x = alpha x on the host
6080d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6090d0321e0SJeremy L Thompson static int CeedHostScale_Hip(CeedScalar *x_array, CeedScalar alpha,
6100d0321e0SJeremy L Thompson                              CeedInt length) {
6110d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
6120d0321e0SJeremy L Thompson     x_array[i] *= alpha;
6130d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6140d0321e0SJeremy L Thompson }
6150d0321e0SJeremy L Thompson 
6160d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6170d0321e0SJeremy L Thompson // Compute x = alpha x on device (impl in .cu file)
6180d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6190d0321e0SJeremy L Thompson int CeedDeviceScale_Hip(CeedScalar *x_array, CeedScalar alpha,
6200d0321e0SJeremy L Thompson                         CeedInt length);
6210d0321e0SJeremy L Thompson 
6220d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6230d0321e0SJeremy L Thompson // Compute x = alpha x
6240d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6250d0321e0SJeremy L Thompson static int CeedVectorScale_Hip(CeedVector x, CeedScalar alpha) {
6260d0321e0SJeremy L Thompson   int ierr;
6270d0321e0SJeremy L Thompson   Ceed ceed;
6280d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(x, &ceed); CeedChkBackend(ierr);
6290d0321e0SJeremy L Thompson   CeedVector_Hip *x_impl;
6300d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(x, &x_impl); CeedChkBackend(ierr);
6310d0321e0SJeremy L Thompson   CeedInt length;
6320d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(x, &length); CeedChkBackend(ierr);
6330d0321e0SJeremy L Thompson 
6340d0321e0SJeremy L Thompson   // Set value for synced device/host array
6350d0321e0SJeremy L Thompson   if (x_impl->d_array) {
6360d0321e0SJeremy L Thompson     ierr = CeedDeviceScale_Hip(x_impl->d_array, alpha, length);
6370d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
6380d0321e0SJeremy L Thompson   }
6390d0321e0SJeremy L Thompson   if (x_impl->h_array) {
6400d0321e0SJeremy L Thompson     ierr = CeedHostScale_Hip(x_impl->h_array, alpha, length); CeedChkBackend(ierr);
6410d0321e0SJeremy L Thompson   }
6420d0321e0SJeremy L Thompson 
6430d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6440d0321e0SJeremy L Thompson }
6450d0321e0SJeremy L Thompson 
6460d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6470d0321e0SJeremy L Thompson // Compute y = alpha x + y on the host
6480d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6490d0321e0SJeremy L Thompson static int CeedHostAXPY_Hip(CeedScalar *y_array, CeedScalar alpha,
6500d0321e0SJeremy L Thompson                             CeedScalar *x_array, CeedInt length) {
6510d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
6520d0321e0SJeremy L Thompson     y_array[i] += alpha * x_array[i];
6530d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6540d0321e0SJeremy L Thompson }
6550d0321e0SJeremy L Thompson 
6560d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6570d0321e0SJeremy L Thompson // Compute y = alpha x + y on device (impl in .cu file)
6580d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6590d0321e0SJeremy L Thompson int CeedDeviceAXPY_Hip(CeedScalar *y_array, CeedScalar alpha,
6600d0321e0SJeremy L Thompson                        CeedScalar *x_array, CeedInt length);
6610d0321e0SJeremy L Thompson 
6620d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6630d0321e0SJeremy L Thompson // Compute y = alpha x + y
6640d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6650d0321e0SJeremy L Thompson static int CeedVectorAXPY_Hip(CeedVector y, CeedScalar alpha, CeedVector x) {
6660d0321e0SJeremy L Thompson   int ierr;
6670d0321e0SJeremy L Thompson   Ceed ceed;
6680d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(y, &ceed); CeedChkBackend(ierr);
6690d0321e0SJeremy L Thompson   CeedVector_Hip *y_impl, *x_impl;
6700d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(y, &y_impl); CeedChkBackend(ierr);
6710d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(x, &x_impl); CeedChkBackend(ierr);
6720d0321e0SJeremy L Thompson   CeedInt length;
6730d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(y, &length); CeedChkBackend(ierr);
6740d0321e0SJeremy L Thompson 
6750d0321e0SJeremy L Thompson   // Set value for synced device/host array
6760d0321e0SJeremy L Thompson   if (y_impl->d_array) {
6770d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_DEVICE); CeedChkBackend(ierr);
6780d0321e0SJeremy L Thompson     ierr = CeedDeviceAXPY_Hip(y_impl->d_array, alpha, x_impl->d_array, length);
6790d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
6800d0321e0SJeremy L Thompson   }
6810d0321e0SJeremy L Thompson   if (y_impl->h_array) {
6820d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_HOST); CeedChkBackend(ierr);
6830d0321e0SJeremy L Thompson     ierr = CeedHostAXPY_Hip(y_impl->h_array, alpha, x_impl->h_array, length);
6840d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
6850d0321e0SJeremy L Thompson   }
6860d0321e0SJeremy L Thompson 
6870d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6880d0321e0SJeremy L Thompson }
6890d0321e0SJeremy L Thompson 
6900d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6910d0321e0SJeremy L Thompson // Compute the pointwise multiplication w = x .* y on the host
6920d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
6930d0321e0SJeremy L Thompson static int CeedHostPointwiseMult_Hip(CeedScalar *w_array, CeedScalar *x_array,
6940d0321e0SJeremy L Thompson                                      CeedScalar *y_array, CeedInt length) {
6950d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
6960d0321e0SJeremy L Thompson     w_array[i] = x_array[i] * y_array[i];
6970d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6980d0321e0SJeremy L Thompson }
6990d0321e0SJeremy L Thompson 
7000d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7010d0321e0SJeremy L Thompson // Compute the pointwise multiplication w = x .* y on device (impl in .cu file)
7020d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7030d0321e0SJeremy L Thompson int CeedDevicePointwiseMult_Hip(CeedScalar *w_array, CeedScalar *x_array,
7040d0321e0SJeremy L Thompson                                 CeedScalar *y_array, CeedInt length);
7050d0321e0SJeremy L Thompson 
7060d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7070d0321e0SJeremy L Thompson // Compute the pointwise multiplication w = x .* y
7080d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7090d0321e0SJeremy L Thompson static int CeedVectorPointwiseMult_Hip(CeedVector w, CeedVector x,
7100d0321e0SJeremy L Thompson                                        CeedVector y) {
7110d0321e0SJeremy L Thompson   int ierr;
7120d0321e0SJeremy L Thompson   Ceed ceed;
7130d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(w, &ceed); CeedChkBackend(ierr);
7140d0321e0SJeremy L Thompson   CeedVector_Hip *w_impl, *x_impl, *y_impl;
7150d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(w, &w_impl); CeedChkBackend(ierr);
7160d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(x, &x_impl); CeedChkBackend(ierr);
7170d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(y, &y_impl); CeedChkBackend(ierr);
7180d0321e0SJeremy L Thompson   CeedInt length;
7190d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(w, &length); CeedChkBackend(ierr);
7200d0321e0SJeremy L Thompson 
7210d0321e0SJeremy L Thompson   // Set value for synced device/host array
7220d0321e0SJeremy L Thompson   if (!w_impl->d_array && !w_impl->h_array) {
7230d0321e0SJeremy L Thompson     ierr = CeedVectorSetValue(w, 0.0); CeedChkBackend(ierr);
7240d0321e0SJeremy L Thompson   }
7250d0321e0SJeremy L Thompson   if (w_impl->d_array) {
7260d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_DEVICE); CeedChkBackend(ierr);
7270d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(y, CEED_MEM_DEVICE); CeedChkBackend(ierr);
7280d0321e0SJeremy L Thompson     ierr = CeedDevicePointwiseMult_Hip(w_impl->d_array, x_impl->d_array,
7290d0321e0SJeremy L Thompson                                        y_impl->d_array, length);
7300d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
7310d0321e0SJeremy L Thompson   }
7320d0321e0SJeremy L Thompson   if (w_impl->h_array) {
7330d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_HOST); CeedChkBackend(ierr);
7340d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(y, CEED_MEM_HOST); CeedChkBackend(ierr);
7350d0321e0SJeremy L Thompson     ierr = CeedHostPointwiseMult_Hip(w_impl->h_array, x_impl->h_array,
7360d0321e0SJeremy L Thompson                                      y_impl->h_array, length);
7370d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
7380d0321e0SJeremy L Thompson   }
7390d0321e0SJeremy L Thompson 
7400d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7410d0321e0SJeremy L Thompson }
7420d0321e0SJeremy L Thompson 
7430d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7440d0321e0SJeremy L Thompson // Destroy the vector
7450d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7460d0321e0SJeremy L Thompson static int CeedVectorDestroy_Hip(const CeedVector vec) {
7470d0321e0SJeremy L Thompson   int ierr;
7480d0321e0SJeremy L Thompson   Ceed ceed;
7490d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
7500d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
7510d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
7520d0321e0SJeremy L Thompson 
7530d0321e0SJeremy L Thompson   ierr = hipFree(impl->d_array_owned); CeedChk_Hip(ceed, ierr);
7540d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_array_owned); CeedChkBackend(ierr);
7550d0321e0SJeremy L Thompson   ierr = CeedFree(&impl); CeedChkBackend(ierr);
7560d0321e0SJeremy L Thompson 
7570d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7580d0321e0SJeremy L Thompson }
7590d0321e0SJeremy L Thompson 
7600d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7610d0321e0SJeremy L Thompson // Create a vector of the specified length (does not allocate memory)
7620d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
7630d0321e0SJeremy L Thompson int CeedVectorCreate_Hip(CeedInt n, CeedVector vec) {
7640d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
7650d0321e0SJeremy L Thompson   int ierr;
7660d0321e0SJeremy L Thompson   Ceed ceed;
7670d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
7680d0321e0SJeremy L Thompson 
7690d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray",
7700d0321e0SJeremy L Thompson                                 CeedVectorHasValidArray_Hip); CeedChkBackend(ierr);
7710d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType",
7720d0321e0SJeremy L Thompson                                 CeedVectorHasBorrowedArrayOfType_Hip);
7730d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
7740d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "SetArray",
7750d0321e0SJeremy L Thompson                                 CeedVectorSetArray_Hip); CeedChkBackend(ierr);
7760d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray",
7770d0321e0SJeremy L Thompson                                 CeedVectorTakeArray_Hip); CeedChkBackend(ierr);
7780d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "SetValue",
7790d0321e0SJeremy L Thompson                                 (int (*)())(CeedVectorSetValue_Hip)); CeedChkBackend(ierr);
7800d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "GetArray",
7810d0321e0SJeremy L Thompson                                 CeedVectorGetArray_Hip); CeedChkBackend(ierr);
7820d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead",
7830d0321e0SJeremy L Thompson                                 CeedVectorGetArrayRead_Hip); CeedChkBackend(ierr);
7840d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite",
7850d0321e0SJeremy L Thompson                                 CeedVectorGetArrayWrite_Hip); CeedChkBackend(ierr);
7860d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray",
7870d0321e0SJeremy L Thompson                                 CeedVectorRestoreArray_Hip); CeedChkBackend(ierr);
7880d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead",
7890d0321e0SJeremy L Thompson                                 CeedVectorRestoreArrayRead_Hip); CeedChkBackend(ierr);
7900d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Norm",
7910d0321e0SJeremy L Thompson                                 CeedVectorNorm_Hip); CeedChkBackend(ierr);
7920d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Reciprocal",
7930d0321e0SJeremy L Thompson                                 CeedVectorReciprocal_Hip); CeedChkBackend(ierr);
7940d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Scale",
7950d0321e0SJeremy L Thompson                                 (int (*)())(CeedVectorScale_Hip)); CeedChkBackend(ierr);
7960d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "AXPY",
7970d0321e0SJeremy L Thompson                                 (int (*)())(CeedVectorAXPY_Hip)); CeedChkBackend(ierr);
7980d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "PointwiseMult",
7990d0321e0SJeremy L Thompson                                 CeedVectorPointwiseMult_Hip); CeedChkBackend(ierr);
8000d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Destroy",
8010d0321e0SJeremy L Thompson                                 CeedVectorDestroy_Hip); CeedChkBackend(ierr);
8020d0321e0SJeremy L Thompson 
8030d0321e0SJeremy L Thompson   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
8040d0321e0SJeremy L Thompson   ierr = CeedVectorSetData(vec, impl); CeedChkBackend(ierr);
8050d0321e0SJeremy L Thompson 
8060d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8070d0321e0SJeremy L Thompson }
808