xref: /libCEED/rust/libceed-sys/c-src/backends/hip-ref/ceed-hip-ref-vector.c (revision 0d0321e0e600f17fbb9528732fcb5c1d5c63fc0f)
1*0d0321e0SJeremy L Thompson // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
2*0d0321e0SJeremy L Thompson // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
3*0d0321e0SJeremy L Thompson // All Rights reserved. See files LICENSE and NOTICE for details.
4*0d0321e0SJeremy L Thompson //
5*0d0321e0SJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software
6*0d0321e0SJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral
7*0d0321e0SJeremy L Thompson // element discretizations for exascale applications. For more information and
8*0d0321e0SJeremy L Thompson // source code availability see http://github.com/ceed.
9*0d0321e0SJeremy L Thompson //
10*0d0321e0SJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*0d0321e0SJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office
12*0d0321e0SJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for
13*0d0321e0SJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including
14*0d0321e0SJeremy L Thompson // software, applications, hardware, advanced system engineering and early
15*0d0321e0SJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative.
16*0d0321e0SJeremy L Thompson 
17*0d0321e0SJeremy L Thompson #include <ceed/ceed.h>
18*0d0321e0SJeremy L Thompson #include <ceed/backend.h>
19*0d0321e0SJeremy L Thompson #include <hip/hip_runtime.h>
20*0d0321e0SJeremy L Thompson #include <hipblas.h>
21*0d0321e0SJeremy L Thompson #include <math.h>
22*0d0321e0SJeremy L Thompson #include <string.h>
23*0d0321e0SJeremy L Thompson #include "ceed-hip-ref.h"
24*0d0321e0SJeremy L Thompson 
25*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
26*0d0321e0SJeremy L Thompson // * Bytes used
27*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
28*0d0321e0SJeremy L Thompson static inline size_t bytes(const CeedVector vec) {
29*0d0321e0SJeremy L Thompson   int ierr;
30*0d0321e0SJeremy L Thompson   CeedInt length;
31*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
32*0d0321e0SJeremy L Thompson   return length * sizeof(CeedScalar);
33*0d0321e0SJeremy L Thompson }
34*0d0321e0SJeremy L Thompson 
35*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
36*0d0321e0SJeremy L Thompson // Sync host to device
37*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
38*0d0321e0SJeremy L Thompson static inline int CeedVectorSyncH2D_Hip(const CeedVector vec) {
39*0d0321e0SJeremy L Thompson   int ierr;
40*0d0321e0SJeremy L Thompson   Ceed ceed;
41*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
42*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
43*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
44*0d0321e0SJeremy L Thompson 
45*0d0321e0SJeremy L Thompson   if (!impl->h_array)
46*0d0321e0SJeremy L Thompson     // LCOV_EXCL_START
47*0d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
48*0d0321e0SJeremy L Thompson                      "No valid host data to sync to device");
49*0d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
50*0d0321e0SJeremy L Thompson 
51*0d0321e0SJeremy L Thompson   if (impl->d_array_borrowed) {
52*0d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_borrowed;
53*0d0321e0SJeremy L Thompson   } else if (impl->d_array_owned) {
54*0d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_owned;
55*0d0321e0SJeremy L Thompson   } else {
56*0d0321e0SJeremy L Thompson     ierr = hipMalloc((void **)&impl->d_array_owned, bytes(vec));
57*0d0321e0SJeremy L Thompson     CeedChk_Hip(ceed, ierr);
58*0d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_owned;
59*0d0321e0SJeremy L Thompson   }
60*0d0321e0SJeremy L Thompson 
61*0d0321e0SJeremy L Thompson   ierr = hipMemcpy(impl->d_array, impl->h_array, bytes(vec),
62*0d0321e0SJeremy L Thompson                    hipMemcpyHostToDevice); CeedChk_Hip(ceed, ierr);
63*0d0321e0SJeremy L Thompson 
64*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
65*0d0321e0SJeremy L Thompson }
66*0d0321e0SJeremy L Thompson 
67*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
68*0d0321e0SJeremy L Thompson // Sync device to host
69*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
70*0d0321e0SJeremy L Thompson static inline int CeedVectorSyncD2H_Hip(const CeedVector vec) {
71*0d0321e0SJeremy L Thompson   int ierr;
72*0d0321e0SJeremy L Thompson   Ceed ceed;
73*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
74*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
75*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
76*0d0321e0SJeremy L Thompson 
77*0d0321e0SJeremy L Thompson   if (!impl->d_array)
78*0d0321e0SJeremy L Thompson     // LCOV_EXCL_START
79*0d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
80*0d0321e0SJeremy L Thompson                      "No valid device data to sync to host");
81*0d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
82*0d0321e0SJeremy L Thompson 
83*0d0321e0SJeremy L Thompson   if (impl->h_array_borrowed) {
84*0d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_borrowed;
85*0d0321e0SJeremy L Thompson   } else if (impl->h_array_owned) {
86*0d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_owned;
87*0d0321e0SJeremy L Thompson   } else {
88*0d0321e0SJeremy L Thompson     CeedInt length;
89*0d0321e0SJeremy L Thompson     ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
90*0d0321e0SJeremy L Thompson     ierr = CeedCalloc(length, &impl->h_array_owned); CeedChkBackend(ierr);
91*0d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_owned;
92*0d0321e0SJeremy L Thompson   }
93*0d0321e0SJeremy L Thompson 
94*0d0321e0SJeremy L Thompson   ierr = hipMemcpy(impl->h_array, impl->d_array, bytes(vec),
95*0d0321e0SJeremy L Thompson                    hipMemcpyDeviceToHost); CeedChk_Hip(ceed, ierr);
96*0d0321e0SJeremy L Thompson 
97*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
98*0d0321e0SJeremy L Thompson }
99*0d0321e0SJeremy L Thompson 
100*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
101*0d0321e0SJeremy L Thompson // Sync arrays
102*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
103*0d0321e0SJeremy L Thompson static inline int CeedVectorSync_Hip(const CeedVector vec, CeedMemType mtype) {
104*0d0321e0SJeremy L Thompson   switch (mtype) {
105*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST: return CeedVectorSyncD2H_Hip(vec);
106*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE: return CeedVectorSyncH2D_Hip(vec);
107*0d0321e0SJeremy L Thompson   }
108*0d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
109*0d0321e0SJeremy L Thompson }
110*0d0321e0SJeremy L Thompson 
111*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
112*0d0321e0SJeremy L Thompson // Set all pointers as invalid
113*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
114*0d0321e0SJeremy L Thompson static inline int CeedVectorSetAllInvalid_Hip(const CeedVector vec) {
115*0d0321e0SJeremy L Thompson   int ierr;
116*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
117*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
118*0d0321e0SJeremy L Thompson 
119*0d0321e0SJeremy L Thompson   impl->h_array = NULL;
120*0d0321e0SJeremy L Thompson   impl->d_array = NULL;
121*0d0321e0SJeremy L Thompson 
122*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
123*0d0321e0SJeremy L Thompson }
124*0d0321e0SJeremy L Thompson 
125*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
126*0d0321e0SJeremy L Thompson // Check if CeedVector has any valid pointers
127*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
128*0d0321e0SJeremy L Thompson static inline int CeedVectorHasValidArray_Hip(const CeedVector vec,
129*0d0321e0SJeremy L Thompson     bool *has_valid_array) {
130*0d0321e0SJeremy L Thompson   int ierr;
131*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
132*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
133*0d0321e0SJeremy L Thompson 
134*0d0321e0SJeremy L Thompson   *has_valid_array = !!impl->h_array || !!impl->d_array;
135*0d0321e0SJeremy L Thompson 
136*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
137*0d0321e0SJeremy L Thompson }
138*0d0321e0SJeremy L Thompson 
139*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
140*0d0321e0SJeremy L Thompson // Check if has any array of given type
141*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
142*0d0321e0SJeremy L Thompson static inline int CeedVectorHasArrayOfType_Hip(const CeedVector vec,
143*0d0321e0SJeremy L Thompson     CeedMemType mtype, bool *has_array_of_type) {
144*0d0321e0SJeremy L Thompson   int ierr;
145*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
146*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
147*0d0321e0SJeremy L Thompson 
148*0d0321e0SJeremy L Thompson   switch (mtype) {
149*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
150*0d0321e0SJeremy L Thompson     *has_array_of_type = !!impl->h_array_borrowed || !!impl->h_array_owned;
151*0d0321e0SJeremy L Thompson     break;
152*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
153*0d0321e0SJeremy L Thompson     *has_array_of_type = !!impl->d_array_borrowed || !!impl->d_array_owned;
154*0d0321e0SJeremy L Thompson     break;
155*0d0321e0SJeremy L Thompson   }
156*0d0321e0SJeremy L Thompson 
157*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
158*0d0321e0SJeremy L Thompson }
159*0d0321e0SJeremy L Thompson 
160*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
161*0d0321e0SJeremy L Thompson // Check if has borrowed array of given type
162*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
163*0d0321e0SJeremy L Thompson static inline int CeedVectorHasBorrowedArrayOfType_Hip(const CeedVector vec,
164*0d0321e0SJeremy L Thompson     CeedMemType mtype, bool *has_borrowed_array_of_type) {
165*0d0321e0SJeremy L Thompson   int ierr;
166*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
167*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
168*0d0321e0SJeremy L Thompson 
169*0d0321e0SJeremy L Thompson   switch (mtype) {
170*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
171*0d0321e0SJeremy L Thompson     *has_borrowed_array_of_type = !!impl->h_array_borrowed;
172*0d0321e0SJeremy L Thompson     break;
173*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
174*0d0321e0SJeremy L Thompson     *has_borrowed_array_of_type = !!impl->d_array_borrowed;
175*0d0321e0SJeremy L Thompson     break;
176*0d0321e0SJeremy L Thompson   }
177*0d0321e0SJeremy L Thompson 
178*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
179*0d0321e0SJeremy L Thompson }
180*0d0321e0SJeremy L Thompson 
181*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
182*0d0321e0SJeremy L Thompson // Sync array of given type
183*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
184*0d0321e0SJeremy L Thompson static inline int CeedVectorNeedSync_Hip(const CeedVector vec,
185*0d0321e0SJeremy L Thompson     CeedMemType mtype, bool *need_sync) {
186*0d0321e0SJeremy L Thompson   int ierr;
187*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
188*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
189*0d0321e0SJeremy L Thompson 
190*0d0321e0SJeremy L Thompson   bool has_valid_array = false;
191*0d0321e0SJeremy L Thompson   ierr = CeedVectorHasValidArray(vec, &has_valid_array); CeedChkBackend(ierr);
192*0d0321e0SJeremy L Thompson   switch (mtype) {
193*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
194*0d0321e0SJeremy L Thompson     *need_sync = has_valid_array && !impl->h_array;
195*0d0321e0SJeremy L Thompson     break;
196*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
197*0d0321e0SJeremy L Thompson     *need_sync = has_valid_array && !impl->d_array;
198*0d0321e0SJeremy L Thompson     break;
199*0d0321e0SJeremy L Thompson   }
200*0d0321e0SJeremy L Thompson 
201*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
202*0d0321e0SJeremy L Thompson }
203*0d0321e0SJeremy L Thompson 
204*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
205*0d0321e0SJeremy L Thompson // Set array from host
206*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
207*0d0321e0SJeremy L Thompson static int CeedVectorSetArrayHost_Hip(const CeedVector vec,
208*0d0321e0SJeremy L Thompson                                       const CeedCopyMode cmode, CeedScalar *array) {
209*0d0321e0SJeremy L Thompson   int ierr;
210*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
211*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
212*0d0321e0SJeremy L Thompson 
213*0d0321e0SJeremy L Thompson   switch (cmode) {
214*0d0321e0SJeremy L Thompson   case CEED_COPY_VALUES: {
215*0d0321e0SJeremy L Thompson     CeedInt length;
216*0d0321e0SJeremy L Thompson     if (!impl->h_array_owned) {
217*0d0321e0SJeremy L Thompson       ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
218*0d0321e0SJeremy L Thompson       ierr = CeedMalloc(length, &impl->h_array_owned); CeedChkBackend(ierr);
219*0d0321e0SJeremy L Thompson     }
220*0d0321e0SJeremy L Thompson     impl->h_array_borrowed = NULL;
221*0d0321e0SJeremy L Thompson     impl->h_array = impl->h_array_owned;
222*0d0321e0SJeremy L Thompson     if (array)
223*0d0321e0SJeremy L Thompson       memcpy(impl->h_array, array, bytes(vec));
224*0d0321e0SJeremy L Thompson   } break;
225*0d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
226*0d0321e0SJeremy L Thompson     ierr = CeedFree(&impl->h_array_owned); CeedChkBackend(ierr);
227*0d0321e0SJeremy L Thompson     impl->h_array_owned = array;
228*0d0321e0SJeremy L Thompson     impl->h_array_borrowed = NULL;
229*0d0321e0SJeremy L Thompson     impl->h_array = array;
230*0d0321e0SJeremy L Thompson     break;
231*0d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
232*0d0321e0SJeremy L Thompson     ierr = CeedFree(&impl->h_array_owned); CeedChkBackend(ierr);
233*0d0321e0SJeremy L Thompson     impl->h_array_borrowed = array;
234*0d0321e0SJeremy L Thompson     impl->h_array = array;
235*0d0321e0SJeremy L Thompson     break;
236*0d0321e0SJeremy L Thompson   }
237*0d0321e0SJeremy L Thompson 
238*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
239*0d0321e0SJeremy L Thompson }
240*0d0321e0SJeremy L Thompson 
241*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
242*0d0321e0SJeremy L Thompson // Set array from device
243*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
244*0d0321e0SJeremy L Thompson static int CeedVectorSetArrayDevice_Hip(const CeedVector vec,
245*0d0321e0SJeremy L Thompson                                         const CeedCopyMode cmode, CeedScalar *array) {
246*0d0321e0SJeremy L Thompson   int ierr;
247*0d0321e0SJeremy L Thompson   Ceed ceed;
248*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
249*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
250*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
251*0d0321e0SJeremy L Thompson 
252*0d0321e0SJeremy L Thompson   switch (cmode) {
253*0d0321e0SJeremy L Thompson   case CEED_COPY_VALUES:
254*0d0321e0SJeremy L Thompson     if (!impl->d_array_owned) {
255*0d0321e0SJeremy L Thompson       ierr = hipMalloc((void **)&impl->d_array_owned, bytes(vec));
256*0d0321e0SJeremy L Thompson       CeedChk_Hip(ceed, ierr);
257*0d0321e0SJeremy L Thompson     }
258*0d0321e0SJeremy L Thompson     impl->d_array_borrowed = NULL;
259*0d0321e0SJeremy L Thompson     impl->d_array = impl->d_array_owned;
260*0d0321e0SJeremy L Thompson     if (array) {
261*0d0321e0SJeremy L Thompson       ierr = hipMemcpy(impl->d_array, array, bytes(vec),
262*0d0321e0SJeremy L Thompson                        hipMemcpyDeviceToDevice); CeedChk_Hip(ceed, ierr);
263*0d0321e0SJeremy L Thompson     }
264*0d0321e0SJeremy L Thompson     break;
265*0d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
266*0d0321e0SJeremy L Thompson     ierr = hipFree(impl->d_array_owned); CeedChk_Hip(ceed, ierr);
267*0d0321e0SJeremy L Thompson     impl->d_array_owned = array;
268*0d0321e0SJeremy L Thompson     impl->d_array_borrowed = NULL;
269*0d0321e0SJeremy L Thompson     impl->d_array = array;
270*0d0321e0SJeremy L Thompson     break;
271*0d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
272*0d0321e0SJeremy L Thompson     ierr = hipFree(impl->d_array_owned); CeedChk_Hip(ceed, ierr);
273*0d0321e0SJeremy L Thompson     impl->d_array_owned = NULL;
274*0d0321e0SJeremy L Thompson     impl->d_array_borrowed = array;
275*0d0321e0SJeremy L Thompson     impl->d_array = array;
276*0d0321e0SJeremy L Thompson     break;
277*0d0321e0SJeremy L Thompson   }
278*0d0321e0SJeremy L Thompson 
279*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
280*0d0321e0SJeremy L Thompson }
281*0d0321e0SJeremy L Thompson 
282*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
283*0d0321e0SJeremy L Thompson // Set the array used by a vector,
284*0d0321e0SJeremy L Thompson //   freeing any previously allocated array if applicable
285*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
286*0d0321e0SJeremy L Thompson static int CeedVectorSetArray_Hip(const CeedVector vec, const CeedMemType mtype,
287*0d0321e0SJeremy L Thompson                                   const CeedCopyMode cmode, CeedScalar *array) {
288*0d0321e0SJeremy L Thompson   int ierr;
289*0d0321e0SJeremy L Thompson   Ceed ceed;
290*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
291*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
292*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
293*0d0321e0SJeremy L Thompson 
294*0d0321e0SJeremy L Thompson   ierr = CeedVectorSetAllInvalid_Hip(vec); CeedChkBackend(ierr);
295*0d0321e0SJeremy L Thompson   switch (mtype) {
296*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
297*0d0321e0SJeremy L Thompson     return CeedVectorSetArrayHost_Hip(vec, cmode, array);
298*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
299*0d0321e0SJeremy L Thompson     return CeedVectorSetArrayDevice_Hip(vec, cmode, array);
300*0d0321e0SJeremy L Thompson   }
301*0d0321e0SJeremy L Thompson 
302*0d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
303*0d0321e0SJeremy L Thompson }
304*0d0321e0SJeremy L Thompson 
305*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
306*0d0321e0SJeremy L Thompson // Set host array to value
307*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
308*0d0321e0SJeremy L Thompson static int CeedHostSetValue_Hip(CeedScalar *h_array, CeedInt length,
309*0d0321e0SJeremy L Thompson                                 CeedScalar val) {
310*0d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
311*0d0321e0SJeremy L Thompson     h_array[i] = val;
312*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
313*0d0321e0SJeremy L Thompson }
314*0d0321e0SJeremy L Thompson 
315*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
316*0d0321e0SJeremy L Thompson // Set device array to value (impl in .hip file)
317*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
318*0d0321e0SJeremy L Thompson int CeedDeviceSetValue_Hip(CeedScalar *d_array, CeedInt length, CeedScalar val);
319*0d0321e0SJeremy L Thompson 
320*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
321*0d0321e0SJeremy L Thompson // Set a vector to a value,
322*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
323*0d0321e0SJeremy L Thompson static int CeedVectorSetValue_Hip(CeedVector vec, CeedScalar val) {
324*0d0321e0SJeremy L Thompson   int ierr;
325*0d0321e0SJeremy L Thompson   Ceed ceed;
326*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
327*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
328*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
329*0d0321e0SJeremy L Thompson   CeedInt length;
330*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
331*0d0321e0SJeremy L Thompson 
332*0d0321e0SJeremy L Thompson   // Set value for synced device/host array
333*0d0321e0SJeremy L Thompson   if (!impl->d_array && !impl->h_array) {
334*0d0321e0SJeremy L Thompson     if (impl->d_array_borrowed) {
335*0d0321e0SJeremy L Thompson       impl->d_array = impl->d_array_borrowed;
336*0d0321e0SJeremy L Thompson     } else if (impl->h_array_borrowed) {
337*0d0321e0SJeremy L Thompson       impl->h_array = impl->h_array_borrowed;
338*0d0321e0SJeremy L Thompson     } else if (impl->d_array_owned) {
339*0d0321e0SJeremy L Thompson       impl->d_array = impl->d_array_owned;
340*0d0321e0SJeremy L Thompson     } else if (impl->h_array_owned) {
341*0d0321e0SJeremy L Thompson       impl->h_array = impl->h_array_owned;
342*0d0321e0SJeremy L Thompson     } else {
343*0d0321e0SJeremy L Thompson       ierr = CeedVectorSetArray(vec, CEED_MEM_DEVICE, CEED_COPY_VALUES, NULL);
344*0d0321e0SJeremy L Thompson       CeedChkBackend(ierr);
345*0d0321e0SJeremy L Thompson     }
346*0d0321e0SJeremy L Thompson   }
347*0d0321e0SJeremy L Thompson   if (impl->d_array) {
348*0d0321e0SJeremy L Thompson     ierr = CeedDeviceSetValue_Hip(impl->d_array, length, val); CeedChkBackend(ierr);
349*0d0321e0SJeremy L Thompson   }
350*0d0321e0SJeremy L Thompson   if (impl->h_array) {
351*0d0321e0SJeremy L Thompson     ierr = CeedHostSetValue_Hip(impl->h_array, length, val); CeedChkBackend(ierr);
352*0d0321e0SJeremy L Thompson   }
353*0d0321e0SJeremy L Thompson 
354*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
355*0d0321e0SJeremy L Thompson }
356*0d0321e0SJeremy L Thompson 
357*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
358*0d0321e0SJeremy L Thompson // Vector Take Array
359*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
360*0d0321e0SJeremy L Thompson static int CeedVectorTakeArray_Hip(CeedVector vec, CeedMemType mtype,
361*0d0321e0SJeremy L Thompson                                    CeedScalar **array) {
362*0d0321e0SJeremy L Thompson   int ierr;
363*0d0321e0SJeremy L Thompson   Ceed ceed;
364*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
365*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
366*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
367*0d0321e0SJeremy L Thompson 
368*0d0321e0SJeremy L Thompson   // Sync array to requested memtype
369*0d0321e0SJeremy L Thompson   bool need_sync = false;
370*0d0321e0SJeremy L Thompson   ierr = CeedVectorNeedSync_Hip(vec, mtype, &need_sync); CeedChkBackend(ierr);
371*0d0321e0SJeremy L Thompson   if (need_sync) {
372*0d0321e0SJeremy L Thompson     ierr = CeedVectorSync_Hip(vec, mtype); CeedChkBackend(ierr);
373*0d0321e0SJeremy L Thompson   }
374*0d0321e0SJeremy L Thompson 
375*0d0321e0SJeremy L Thompson   // Update pointer
376*0d0321e0SJeremy L Thompson   switch (mtype) {
377*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
378*0d0321e0SJeremy L Thompson     (*array) = impl->h_array_borrowed;
379*0d0321e0SJeremy L Thompson     impl->h_array_borrowed = NULL;
380*0d0321e0SJeremy L Thompson     impl->h_array = NULL;
381*0d0321e0SJeremy L Thompson     break;
382*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
383*0d0321e0SJeremy L Thompson     (*array) = impl->d_array_borrowed;
384*0d0321e0SJeremy L Thompson     impl->d_array_borrowed = NULL;
385*0d0321e0SJeremy L Thompson     impl->d_array = NULL;
386*0d0321e0SJeremy L Thompson     break;
387*0d0321e0SJeremy L Thompson   }
388*0d0321e0SJeremy L Thompson 
389*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
390*0d0321e0SJeremy L Thompson }
391*0d0321e0SJeremy L Thompson 
392*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
393*0d0321e0SJeremy L Thompson // Core logic for array syncronization for GetArray.
394*0d0321e0SJeremy L Thompson //   If a different memory type is most up to date, this will perform a copy
395*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
396*0d0321e0SJeremy L Thompson static int CeedVectorGetArrayCore_Hip(const CeedVector vec,
397*0d0321e0SJeremy L Thompson                                       const CeedMemType mtype, CeedScalar **array) {
398*0d0321e0SJeremy L Thompson   int ierr;
399*0d0321e0SJeremy L Thompson   Ceed ceed;
400*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
401*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
402*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
403*0d0321e0SJeremy L Thompson 
404*0d0321e0SJeremy L Thompson   bool need_sync = false;
405*0d0321e0SJeremy L Thompson   ierr = CeedVectorNeedSync_Hip(vec, mtype, &need_sync); CeedChkBackend(ierr);
406*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
407*0d0321e0SJeremy L Thompson   if (need_sync) {
408*0d0321e0SJeremy L Thompson     // Sync array to requested memtype
409*0d0321e0SJeremy L Thompson     ierr = CeedVectorSync_Hip(vec, mtype); CeedChkBackend(ierr);
410*0d0321e0SJeremy L Thompson   }
411*0d0321e0SJeremy L Thompson 
412*0d0321e0SJeremy L Thompson   // Update pointer
413*0d0321e0SJeremy L Thompson   switch (mtype) {
414*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
415*0d0321e0SJeremy L Thompson     *array = impl->h_array;
416*0d0321e0SJeremy L Thompson     break;
417*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
418*0d0321e0SJeremy L Thompson     *array = impl->d_array;
419*0d0321e0SJeremy L Thompson     break;
420*0d0321e0SJeremy L Thompson   }
421*0d0321e0SJeremy L Thompson 
422*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
423*0d0321e0SJeremy L Thompson }
424*0d0321e0SJeremy L Thompson 
425*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
426*0d0321e0SJeremy L Thompson // Get read-only access to a vector via the specified mtype
427*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
428*0d0321e0SJeremy L Thompson static int CeedVectorGetArrayRead_Hip(const CeedVector vec,
429*0d0321e0SJeremy L Thompson                                       const CeedMemType mtype, const CeedScalar **array) {
430*0d0321e0SJeremy L Thompson   return CeedVectorGetArrayCore_Hip(vec, mtype, (CeedScalar **)array);
431*0d0321e0SJeremy L Thompson }
432*0d0321e0SJeremy L Thompson 
433*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
434*0d0321e0SJeremy L Thompson // Get read/write access to a vector via the specified mtype
435*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
436*0d0321e0SJeremy L Thompson static int CeedVectorGetArray_Hip(const CeedVector vec, const CeedMemType mtype,
437*0d0321e0SJeremy L Thompson                                   CeedScalar **array) {
438*0d0321e0SJeremy L Thompson   int ierr;
439*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
440*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
441*0d0321e0SJeremy L Thompson 
442*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetArrayCore_Hip(vec, mtype, array); CeedChkBackend(ierr);
443*0d0321e0SJeremy L Thompson 
444*0d0321e0SJeremy L Thompson   ierr = CeedVectorSetAllInvalid_Hip(vec); CeedChkBackend(ierr);
445*0d0321e0SJeremy L Thompson   switch (mtype) {
446*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
447*0d0321e0SJeremy L Thompson     impl->h_array = *array;
448*0d0321e0SJeremy L Thompson     break;
449*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
450*0d0321e0SJeremy L Thompson     impl->d_array = *array;
451*0d0321e0SJeremy L Thompson     break;
452*0d0321e0SJeremy L Thompson   }
453*0d0321e0SJeremy L Thompson 
454*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
455*0d0321e0SJeremy L Thompson }
456*0d0321e0SJeremy L Thompson 
457*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
458*0d0321e0SJeremy L Thompson // Get write access to a vector via the specified mtype
459*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
460*0d0321e0SJeremy L Thompson static int CeedVectorGetArrayWrite_Hip(const CeedVector vec,
461*0d0321e0SJeremy L Thompson                                        const CeedMemType mtype, CeedScalar **array) {
462*0d0321e0SJeremy L Thompson   int ierr;
463*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
464*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
465*0d0321e0SJeremy L Thompson 
466*0d0321e0SJeremy L Thompson   bool has_array_of_type = true;
467*0d0321e0SJeremy L Thompson   ierr = CeedVectorHasArrayOfType_Hip(vec, mtype, &has_array_of_type);
468*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
469*0d0321e0SJeremy L Thompson   if (!has_array_of_type) {
470*0d0321e0SJeremy L Thompson     // Allocate if array is not yet allocated
471*0d0321e0SJeremy L Thompson     ierr = CeedVectorSetArray(vec, mtype, CEED_COPY_VALUES, NULL);
472*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
473*0d0321e0SJeremy L Thompson   } else {
474*0d0321e0SJeremy L Thompson     // Select dirty array
475*0d0321e0SJeremy L Thompson     switch (mtype) {
476*0d0321e0SJeremy L Thompson     case CEED_MEM_HOST:
477*0d0321e0SJeremy L Thompson       if (impl->h_array_borrowed)
478*0d0321e0SJeremy L Thompson         impl->h_array = impl->h_array_borrowed;
479*0d0321e0SJeremy L Thompson       else
480*0d0321e0SJeremy L Thompson         impl->h_array = impl->h_array_owned;
481*0d0321e0SJeremy L Thompson       break;
482*0d0321e0SJeremy L Thompson     case CEED_MEM_DEVICE:
483*0d0321e0SJeremy L Thompson       if (impl->d_array_borrowed)
484*0d0321e0SJeremy L Thompson         impl->d_array = impl->d_array_borrowed;
485*0d0321e0SJeremy L Thompson       else
486*0d0321e0SJeremy L Thompson         impl->d_array = impl->d_array_owned;
487*0d0321e0SJeremy L Thompson     }
488*0d0321e0SJeremy L Thompson   }
489*0d0321e0SJeremy L Thompson 
490*0d0321e0SJeremy L Thompson   return CeedVectorGetArray_Hip(vec, mtype, array);
491*0d0321e0SJeremy L Thompson }
492*0d0321e0SJeremy L Thompson 
493*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
494*0d0321e0SJeremy L Thompson // Restore an array obtained using CeedVectorGetArrayRead()
495*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
496*0d0321e0SJeremy L Thompson static int CeedVectorRestoreArrayRead_Hip(const CeedVector vec) {
497*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
498*0d0321e0SJeremy L Thompson }
499*0d0321e0SJeremy L Thompson 
500*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
501*0d0321e0SJeremy L Thompson // Restore an array obtained using CeedVectorGetArray()
502*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
503*0d0321e0SJeremy L Thompson static int CeedVectorRestoreArray_Hip(const CeedVector vec) {
504*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
505*0d0321e0SJeremy L Thompson }
506*0d0321e0SJeremy L Thompson 
507*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
508*0d0321e0SJeremy L Thompson // Get the norm of a CeedVector
509*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
510*0d0321e0SJeremy L Thompson static int CeedVectorNorm_Hip(CeedVector vec, CeedNormType type,
511*0d0321e0SJeremy L Thompson                               CeedScalar *norm) {
512*0d0321e0SJeremy L Thompson   int ierr;
513*0d0321e0SJeremy L Thompson   Ceed ceed;
514*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
515*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
516*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
517*0d0321e0SJeremy L Thompson   CeedInt length;
518*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
519*0d0321e0SJeremy L Thompson   hipblasHandle_t handle;
520*0d0321e0SJeremy L Thompson   ierr = CeedHipGetHipblasHandle(ceed, &handle); CeedChkBackend(ierr);
521*0d0321e0SJeremy L Thompson 
522*0d0321e0SJeremy L Thompson   // Compute norm
523*0d0321e0SJeremy L Thompson   const CeedScalar *d_array;
524*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetArrayRead(vec, CEED_MEM_DEVICE, &d_array);
525*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
526*0d0321e0SJeremy L Thompson   switch (type) {
527*0d0321e0SJeremy L Thompson   case CEED_NORM_1: {
528*0d0321e0SJeremy L Thompson     if (CEED_SCALAR_TYPE == CEED_SCALAR_FP32) {
529*0d0321e0SJeremy L Thompson       ierr = hipblasSasum(handle, length, (float *) d_array, 1, (float *) norm);
530*0d0321e0SJeremy L Thompson     } else {
531*0d0321e0SJeremy L Thompson       ierr = hipblasDasum(handle, length, (double *) d_array, 1, (double *) norm);
532*0d0321e0SJeremy L Thompson     }
533*0d0321e0SJeremy L Thompson     CeedChk_Hipblas(ceed, ierr);
534*0d0321e0SJeremy L Thompson     break;
535*0d0321e0SJeremy L Thompson   }
536*0d0321e0SJeremy L Thompson   case CEED_NORM_2: {
537*0d0321e0SJeremy L Thompson     if (CEED_SCALAR_TYPE == CEED_SCALAR_FP32) {
538*0d0321e0SJeremy L Thompson       ierr = hipblasSnrm2(handle, length, (float *) d_array, 1, (float *) norm);
539*0d0321e0SJeremy L Thompson     } else {
540*0d0321e0SJeremy L Thompson       ierr = hipblasDnrm2(handle, length, (double *) d_array, 1, (double *) norm);
541*0d0321e0SJeremy L Thompson     }
542*0d0321e0SJeremy L Thompson     CeedChk_Hipblas(ceed, ierr);
543*0d0321e0SJeremy L Thompson     break;
544*0d0321e0SJeremy L Thompson   }
545*0d0321e0SJeremy L Thompson   case CEED_NORM_MAX: {
546*0d0321e0SJeremy L Thompson     CeedInt indx;
547*0d0321e0SJeremy L Thompson     if (CEED_SCALAR_TYPE == CEED_SCALAR_FP32) {
548*0d0321e0SJeremy L Thompson       ierr = hipblasIsamax(handle, length, (float *) d_array, 1, &indx);
549*0d0321e0SJeremy L Thompson     } else {
550*0d0321e0SJeremy L Thompson       ierr = hipblasIdamax(handle, length, (double *) d_array, 1, &indx);
551*0d0321e0SJeremy L Thompson     }
552*0d0321e0SJeremy L Thompson     CeedChk_Hipblas(ceed, ierr);
553*0d0321e0SJeremy L Thompson     CeedScalar normNoAbs;
554*0d0321e0SJeremy L Thompson     ierr = hipMemcpy(&normNoAbs, impl->d_array+indx-1, sizeof(CeedScalar),
555*0d0321e0SJeremy L Thompson                      hipMemcpyDeviceToHost); CeedChk_Hip(ceed, ierr);
556*0d0321e0SJeremy L Thompson     *norm = fabs(normNoAbs);
557*0d0321e0SJeremy L Thompson     break;
558*0d0321e0SJeremy L Thompson   }
559*0d0321e0SJeremy L Thompson   }
560*0d0321e0SJeremy L Thompson   ierr = CeedVectorRestoreArrayRead(vec, &d_array); CeedChkBackend(ierr);
561*0d0321e0SJeremy L Thompson 
562*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
563*0d0321e0SJeremy L Thompson }
564*0d0321e0SJeremy L Thompson 
565*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
566*0d0321e0SJeremy L Thompson // Take reciprocal of a vector on host
567*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
568*0d0321e0SJeremy L Thompson static int CeedHostReciprocal_Hip(CeedScalar *h_array, CeedInt length) {
569*0d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
570*0d0321e0SJeremy L Thompson     if (fabs(h_array[i]) > CEED_EPSILON)
571*0d0321e0SJeremy L Thompson       h_array[i] = 1./h_array[i];
572*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
573*0d0321e0SJeremy L Thompson }
574*0d0321e0SJeremy L Thompson 
575*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
576*0d0321e0SJeremy L Thompson // Take reciprocal of a vector on device (impl in .cu file)
577*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
578*0d0321e0SJeremy L Thompson int CeedDeviceReciprocal_Hip(CeedScalar *d_array, CeedInt length);
579*0d0321e0SJeremy L Thompson 
580*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
581*0d0321e0SJeremy L Thompson // Take reciprocal of a vector
582*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
583*0d0321e0SJeremy L Thompson static int CeedVectorReciprocal_Hip(CeedVector vec) {
584*0d0321e0SJeremy L Thompson   int ierr;
585*0d0321e0SJeremy L Thompson   Ceed ceed;
586*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
587*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
588*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
589*0d0321e0SJeremy L Thompson   CeedInt length;
590*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(vec, &length); CeedChkBackend(ierr);
591*0d0321e0SJeremy L Thompson 
592*0d0321e0SJeremy L Thompson   // Set value for synced device/host array
593*0d0321e0SJeremy L Thompson   if (impl->d_array) {
594*0d0321e0SJeremy L Thompson     ierr = CeedDeviceReciprocal_Hip(impl->d_array, length); CeedChkBackend(ierr);
595*0d0321e0SJeremy L Thompson   }
596*0d0321e0SJeremy L Thompson   if (impl->h_array) {
597*0d0321e0SJeremy L Thompson     ierr = CeedHostReciprocal_Hip(impl->h_array, length); CeedChkBackend(ierr);
598*0d0321e0SJeremy L Thompson   }
599*0d0321e0SJeremy L Thompson 
600*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
601*0d0321e0SJeremy L Thompson }
602*0d0321e0SJeremy L Thompson 
603*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
604*0d0321e0SJeremy L Thompson // Compute x = alpha x on the host
605*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
606*0d0321e0SJeremy L Thompson static int CeedHostScale_Hip(CeedScalar *x_array, CeedScalar alpha,
607*0d0321e0SJeremy L Thompson                              CeedInt length) {
608*0d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
609*0d0321e0SJeremy L Thompson     x_array[i] *= alpha;
610*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
611*0d0321e0SJeremy L Thompson }
612*0d0321e0SJeremy L Thompson 
613*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
614*0d0321e0SJeremy L Thompson // Compute x = alpha x on device (impl in .cu file)
615*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
616*0d0321e0SJeremy L Thompson int CeedDeviceScale_Hip(CeedScalar *x_array, CeedScalar alpha,
617*0d0321e0SJeremy L Thompson                         CeedInt length);
618*0d0321e0SJeremy L Thompson 
619*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
620*0d0321e0SJeremy L Thompson // Compute x = alpha x
621*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
622*0d0321e0SJeremy L Thompson static int CeedVectorScale_Hip(CeedVector x, CeedScalar alpha) {
623*0d0321e0SJeremy L Thompson   int ierr;
624*0d0321e0SJeremy L Thompson   Ceed ceed;
625*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(x, &ceed); CeedChkBackend(ierr);
626*0d0321e0SJeremy L Thompson   CeedVector_Hip *x_impl;
627*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(x, &x_impl); CeedChkBackend(ierr);
628*0d0321e0SJeremy L Thompson   CeedInt length;
629*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(x, &length); CeedChkBackend(ierr);
630*0d0321e0SJeremy L Thompson 
631*0d0321e0SJeremy L Thompson   // Set value for synced device/host array
632*0d0321e0SJeremy L Thompson   if (x_impl->d_array) {
633*0d0321e0SJeremy L Thompson     ierr = CeedDeviceScale_Hip(x_impl->d_array, alpha, length);
634*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
635*0d0321e0SJeremy L Thompson   }
636*0d0321e0SJeremy L Thompson   if (x_impl->h_array) {
637*0d0321e0SJeremy L Thompson     ierr = CeedHostScale_Hip(x_impl->h_array, alpha, length); CeedChkBackend(ierr);
638*0d0321e0SJeremy L Thompson   }
639*0d0321e0SJeremy L Thompson 
640*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
641*0d0321e0SJeremy L Thompson }
642*0d0321e0SJeremy L Thompson 
643*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
644*0d0321e0SJeremy L Thompson // Compute y = alpha x + y on the host
645*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
646*0d0321e0SJeremy L Thompson static int CeedHostAXPY_Hip(CeedScalar *y_array, CeedScalar alpha,
647*0d0321e0SJeremy L Thompson                             CeedScalar *x_array, CeedInt length) {
648*0d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
649*0d0321e0SJeremy L Thompson     y_array[i] += alpha * x_array[i];
650*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
651*0d0321e0SJeremy L Thompson }
652*0d0321e0SJeremy L Thompson 
653*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
654*0d0321e0SJeremy L Thompson // Compute y = alpha x + y on device (impl in .cu file)
655*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
656*0d0321e0SJeremy L Thompson int CeedDeviceAXPY_Hip(CeedScalar *y_array, CeedScalar alpha,
657*0d0321e0SJeremy L Thompson                        CeedScalar *x_array, CeedInt length);
658*0d0321e0SJeremy L Thompson 
659*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
660*0d0321e0SJeremy L Thompson // Compute y = alpha x + y
661*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
662*0d0321e0SJeremy L Thompson static int CeedVectorAXPY_Hip(CeedVector y, CeedScalar alpha, CeedVector x) {
663*0d0321e0SJeremy L Thompson   int ierr;
664*0d0321e0SJeremy L Thompson   Ceed ceed;
665*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(y, &ceed); CeedChkBackend(ierr);
666*0d0321e0SJeremy L Thompson   CeedVector_Hip *y_impl, *x_impl;
667*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(y, &y_impl); CeedChkBackend(ierr);
668*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(x, &x_impl); CeedChkBackend(ierr);
669*0d0321e0SJeremy L Thompson   CeedInt length;
670*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(y, &length); CeedChkBackend(ierr);
671*0d0321e0SJeremy L Thompson 
672*0d0321e0SJeremy L Thompson   // Set value for synced device/host array
673*0d0321e0SJeremy L Thompson   if (y_impl->d_array) {
674*0d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_DEVICE); CeedChkBackend(ierr);
675*0d0321e0SJeremy L Thompson     ierr = CeedDeviceAXPY_Hip(y_impl->d_array, alpha, x_impl->d_array, length);
676*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
677*0d0321e0SJeremy L Thompson   }
678*0d0321e0SJeremy L Thompson   if (y_impl->h_array) {
679*0d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_HOST); CeedChkBackend(ierr);
680*0d0321e0SJeremy L Thompson     ierr = CeedHostAXPY_Hip(y_impl->h_array, alpha, x_impl->h_array, length);
681*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
682*0d0321e0SJeremy L Thompson   }
683*0d0321e0SJeremy L Thompson 
684*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
685*0d0321e0SJeremy L Thompson }
686*0d0321e0SJeremy L Thompson 
687*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
688*0d0321e0SJeremy L Thompson // Compute the pointwise multiplication w = x .* y on the host
689*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
690*0d0321e0SJeremy L Thompson static int CeedHostPointwiseMult_Hip(CeedScalar *w_array, CeedScalar *x_array,
691*0d0321e0SJeremy L Thompson                                      CeedScalar *y_array, CeedInt length) {
692*0d0321e0SJeremy L Thompson   for (int i = 0; i < length; i++)
693*0d0321e0SJeremy L Thompson     w_array[i] = x_array[i] * y_array[i];
694*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
695*0d0321e0SJeremy L Thompson }
696*0d0321e0SJeremy L Thompson 
697*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
698*0d0321e0SJeremy L Thompson // Compute the pointwise multiplication w = x .* y on device (impl in .cu file)
699*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
700*0d0321e0SJeremy L Thompson int CeedDevicePointwiseMult_Hip(CeedScalar *w_array, CeedScalar *x_array,
701*0d0321e0SJeremy L Thompson                                 CeedScalar *y_array, CeedInt length);
702*0d0321e0SJeremy L Thompson 
703*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
704*0d0321e0SJeremy L Thompson // Compute the pointwise multiplication w = x .* y
705*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
706*0d0321e0SJeremy L Thompson static int CeedVectorPointwiseMult_Hip(CeedVector w, CeedVector x,
707*0d0321e0SJeremy L Thompson                                        CeedVector y) {
708*0d0321e0SJeremy L Thompson   int ierr;
709*0d0321e0SJeremy L Thompson   Ceed ceed;
710*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(w, &ceed); CeedChkBackend(ierr);
711*0d0321e0SJeremy L Thompson   CeedVector_Hip *w_impl, *x_impl, *y_impl;
712*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(w, &w_impl); CeedChkBackend(ierr);
713*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(x, &x_impl); CeedChkBackend(ierr);
714*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(y, &y_impl); CeedChkBackend(ierr);
715*0d0321e0SJeremy L Thompson   CeedInt length;
716*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetLength(w, &length); CeedChkBackend(ierr);
717*0d0321e0SJeremy L Thompson 
718*0d0321e0SJeremy L Thompson   // Set value for synced device/host array
719*0d0321e0SJeremy L Thompson   if (!w_impl->d_array && !w_impl->h_array) {
720*0d0321e0SJeremy L Thompson     ierr = CeedVectorSetValue(w, 0.0); CeedChkBackend(ierr);
721*0d0321e0SJeremy L Thompson   }
722*0d0321e0SJeremy L Thompson   if (w_impl->d_array) {
723*0d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_DEVICE); CeedChkBackend(ierr);
724*0d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(y, CEED_MEM_DEVICE); CeedChkBackend(ierr);
725*0d0321e0SJeremy L Thompson     ierr = CeedDevicePointwiseMult_Hip(w_impl->d_array, x_impl->d_array,
726*0d0321e0SJeremy L Thompson                                        y_impl->d_array, length);
727*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
728*0d0321e0SJeremy L Thompson   }
729*0d0321e0SJeremy L Thompson   if (w_impl->h_array) {
730*0d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(x, CEED_MEM_HOST); CeedChkBackend(ierr);
731*0d0321e0SJeremy L Thompson     ierr = CeedVectorSyncArray(y, CEED_MEM_HOST); CeedChkBackend(ierr);
732*0d0321e0SJeremy L Thompson     ierr = CeedHostPointwiseMult_Hip(w_impl->h_array, x_impl->h_array,
733*0d0321e0SJeremy L Thompson                                      y_impl->h_array, length);
734*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
735*0d0321e0SJeremy L Thompson   }
736*0d0321e0SJeremy L Thompson 
737*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
738*0d0321e0SJeremy L Thompson }
739*0d0321e0SJeremy L Thompson 
740*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
741*0d0321e0SJeremy L Thompson // Destroy the vector
742*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
743*0d0321e0SJeremy L Thompson static int CeedVectorDestroy_Hip(const CeedVector vec) {
744*0d0321e0SJeremy L Thompson   int ierr;
745*0d0321e0SJeremy L Thompson   Ceed ceed;
746*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
747*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
748*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetData(vec, &impl); CeedChkBackend(ierr);
749*0d0321e0SJeremy L Thompson 
750*0d0321e0SJeremy L Thompson   ierr = hipFree(impl->d_array_owned); CeedChk_Hip(ceed, ierr);
751*0d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_array_owned); CeedChkBackend(ierr);
752*0d0321e0SJeremy L Thompson   ierr = CeedFree(&impl); CeedChkBackend(ierr);
753*0d0321e0SJeremy L Thompson 
754*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
755*0d0321e0SJeremy L Thompson }
756*0d0321e0SJeremy L Thompson 
757*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
758*0d0321e0SJeremy L Thompson // Create a vector of the specified length (does not allocate memory)
759*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
760*0d0321e0SJeremy L Thompson int CeedVectorCreate_Hip(CeedInt n, CeedVector vec) {
761*0d0321e0SJeremy L Thompson   CeedVector_Hip *impl;
762*0d0321e0SJeremy L Thompson   int ierr;
763*0d0321e0SJeremy L Thompson   Ceed ceed;
764*0d0321e0SJeremy L Thompson   ierr = CeedVectorGetCeed(vec, &ceed); CeedChkBackend(ierr);
765*0d0321e0SJeremy L Thompson 
766*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray",
767*0d0321e0SJeremy L Thompson                                 CeedVectorHasValidArray_Hip); CeedChkBackend(ierr);
768*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType",
769*0d0321e0SJeremy L Thompson                                 CeedVectorHasBorrowedArrayOfType_Hip);
770*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
771*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "SetArray",
772*0d0321e0SJeremy L Thompson                                 CeedVectorSetArray_Hip); CeedChkBackend(ierr);
773*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray",
774*0d0321e0SJeremy L Thompson                                 CeedVectorTakeArray_Hip); CeedChkBackend(ierr);
775*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "SetValue",
776*0d0321e0SJeremy L Thompson                                 (int (*)())(CeedVectorSetValue_Hip)); CeedChkBackend(ierr);
777*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "GetArray",
778*0d0321e0SJeremy L Thompson                                 CeedVectorGetArray_Hip); CeedChkBackend(ierr);
779*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead",
780*0d0321e0SJeremy L Thompson                                 CeedVectorGetArrayRead_Hip); CeedChkBackend(ierr);
781*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite",
782*0d0321e0SJeremy L Thompson                                 CeedVectorGetArrayWrite_Hip); CeedChkBackend(ierr);
783*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray",
784*0d0321e0SJeremy L Thompson                                 CeedVectorRestoreArray_Hip); CeedChkBackend(ierr);
785*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead",
786*0d0321e0SJeremy L Thompson                                 CeedVectorRestoreArrayRead_Hip); CeedChkBackend(ierr);
787*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Norm",
788*0d0321e0SJeremy L Thompson                                 CeedVectorNorm_Hip); CeedChkBackend(ierr);
789*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Reciprocal",
790*0d0321e0SJeremy L Thompson                                 CeedVectorReciprocal_Hip); CeedChkBackend(ierr);
791*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Scale",
792*0d0321e0SJeremy L Thompson                                 (int (*)())(CeedVectorScale_Hip)); CeedChkBackend(ierr);
793*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "AXPY",
794*0d0321e0SJeremy L Thompson                                 (int (*)())(CeedVectorAXPY_Hip)); CeedChkBackend(ierr);
795*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "PointwiseMult",
796*0d0321e0SJeremy L Thompson                                 CeedVectorPointwiseMult_Hip); CeedChkBackend(ierr);
797*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "Vector", vec, "Destroy",
798*0d0321e0SJeremy L Thompson                                 CeedVectorDestroy_Hip); CeedChkBackend(ierr);
799*0d0321e0SJeremy L Thompson 
800*0d0321e0SJeremy L Thompson   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
801*0d0321e0SJeremy L Thompson   ierr = CeedVectorSetData(vec, impl); CeedChkBackend(ierr);
802*0d0321e0SJeremy L Thompson 
803*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
804*0d0321e0SJeremy L Thompson }
805