xref: /libCEED/backends/hip-ref/ceed-hip-ref-qfunctioncontext.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 <string.h>
21*0d0321e0SJeremy L Thompson #include "ceed-hip-ref.h"
22*0d0321e0SJeremy L Thompson 
23*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
24*0d0321e0SJeremy L Thompson // * Bytes used
25*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
26*0d0321e0SJeremy L Thompson static inline size_t bytes(const CeedQFunctionContext ctx) {
27*0d0321e0SJeremy L Thompson   int ierr;
28*0d0321e0SJeremy L Thompson   size_t ctxsize;
29*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetContextSize(ctx, &ctxsize); CeedChkBackend(ierr);
30*0d0321e0SJeremy L Thompson   return ctxsize;
31*0d0321e0SJeremy L Thompson }
32*0d0321e0SJeremy L Thompson 
33*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
34*0d0321e0SJeremy L Thompson // Sync host to device
35*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
36*0d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSyncH2D_Hip(
37*0d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
38*0d0321e0SJeremy L Thompson   int ierr;
39*0d0321e0SJeremy L Thompson   Ceed ceed;
40*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
41*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
42*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
43*0d0321e0SJeremy L Thompson 
44*0d0321e0SJeremy L Thompson   if (!impl->h_data)
45*0d0321e0SJeremy L Thompson     // LCOV_EXCL_START
46*0d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
47*0d0321e0SJeremy L Thompson                      "No valid host data to sync to device");
48*0d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
49*0d0321e0SJeremy L Thompson 
50*0d0321e0SJeremy L Thompson   if (impl->d_data_borrowed) {
51*0d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_borrowed;
52*0d0321e0SJeremy L Thompson   } else if (impl->d_data_owned) {
53*0d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
54*0d0321e0SJeremy L Thompson   } else {
55*0d0321e0SJeremy L Thompson     ierr = hipMalloc((void **)&impl->d_data_owned, bytes(ctx));
56*0d0321e0SJeremy L Thompson     CeedChk_Hip(ceed, ierr);
57*0d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
58*0d0321e0SJeremy L Thompson   }
59*0d0321e0SJeremy L Thompson 
60*0d0321e0SJeremy L Thompson   ierr = hipMemcpy(impl->d_data, impl->h_data, bytes(ctx),
61*0d0321e0SJeremy L Thompson                    hipMemcpyHostToDevice); CeedChk_Hip(ceed, ierr);
62*0d0321e0SJeremy L Thompson 
63*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
64*0d0321e0SJeremy L Thompson }
65*0d0321e0SJeremy L Thompson 
66*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
67*0d0321e0SJeremy L Thompson // Sync device to host
68*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
69*0d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSyncD2H_Hip(
70*0d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
71*0d0321e0SJeremy L Thompson   int ierr;
72*0d0321e0SJeremy L Thompson   Ceed ceed;
73*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
74*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
75*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
76*0d0321e0SJeremy L Thompson 
77*0d0321e0SJeremy L Thompson   if (!impl->d_data)
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_data_borrowed) {
84*0d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_borrowed;
85*0d0321e0SJeremy L Thompson   } else if (impl->h_data_owned) {
86*0d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
87*0d0321e0SJeremy L Thompson   } else {
88*0d0321e0SJeremy L Thompson     ierr = CeedMalloc(bytes(ctx), &impl->h_data_owned);
89*0d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
90*0d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
91*0d0321e0SJeremy L Thompson   }
92*0d0321e0SJeremy L Thompson 
93*0d0321e0SJeremy L Thompson   ierr = hipMemcpy(impl->h_data, impl->d_data, bytes(ctx),
94*0d0321e0SJeremy L Thompson                    hipMemcpyDeviceToHost); CeedChk_Hip(ceed, ierr);
95*0d0321e0SJeremy L Thompson 
96*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
97*0d0321e0SJeremy L Thompson }
98*0d0321e0SJeremy L Thompson 
99*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
100*0d0321e0SJeremy L Thompson // Sync data of type
101*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
102*0d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSync_Hip(const CeedQFunctionContext ctx,
103*0d0321e0SJeremy L Thompson     CeedMemType mtype) {
104*0d0321e0SJeremy L Thompson   switch (mtype) {
105*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST: return CeedQFunctionContextSyncD2H_Hip(ctx);
106*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE: return CeedQFunctionContextSyncH2D_Hip(ctx);
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 CeedQFunctionContextSetAllInvalid_Hip(
115*0d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
116*0d0321e0SJeremy L Thompson   int ierr;
117*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
118*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
119*0d0321e0SJeremy L Thompson 
120*0d0321e0SJeremy L Thompson   impl->h_data = NULL;
121*0d0321e0SJeremy L Thompson   impl->d_data = NULL;
122*0d0321e0SJeremy L Thompson 
123*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
124*0d0321e0SJeremy L Thompson }
125*0d0321e0SJeremy L Thompson 
126*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
127*0d0321e0SJeremy L Thompson // Check for valid data
128*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
129*0d0321e0SJeremy L Thompson static inline int CeedQFunctionContextHasValidData_Hip(
130*0d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx, bool *has_valid_data) {
131*0d0321e0SJeremy L Thompson   int ierr;
132*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
133*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
134*0d0321e0SJeremy L Thompson 
135*0d0321e0SJeremy L Thompson   *has_valid_data = !!impl->h_data || !!impl->d_data;
136*0d0321e0SJeremy L Thompson 
137*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
138*0d0321e0SJeremy L Thompson }
139*0d0321e0SJeremy L Thompson 
140*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
141*0d0321e0SJeremy L Thompson // Check if ctx has borrowed data
142*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
143*0d0321e0SJeremy L Thompson static inline int CeedQFunctionContextHasBorrowedDataOfType_Hip(
144*0d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mtype,
145*0d0321e0SJeremy L Thompson   bool *has_borrowed_data_of_type) {
146*0d0321e0SJeremy L Thompson   int ierr;
147*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
148*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
149*0d0321e0SJeremy L Thompson 
150*0d0321e0SJeremy L Thompson   switch (mtype) {
151*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
152*0d0321e0SJeremy L Thompson     *has_borrowed_data_of_type = !!impl->h_data_borrowed;
153*0d0321e0SJeremy L Thompson     break;
154*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
155*0d0321e0SJeremy L Thompson     *has_borrowed_data_of_type = !!impl->d_data_borrowed;
156*0d0321e0SJeremy L Thompson     break;
157*0d0321e0SJeremy L Thompson   }
158*0d0321e0SJeremy L Thompson 
159*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
160*0d0321e0SJeremy L Thompson }
161*0d0321e0SJeremy L Thompson 
162*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
163*0d0321e0SJeremy L Thompson // Check if data of given type needs sync
164*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
165*0d0321e0SJeremy L Thompson static inline int CeedQFunctionContextNeedSync_Hip(
166*0d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mtype, bool *need_sync) {
167*0d0321e0SJeremy L Thompson   int ierr;
168*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
169*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
170*0d0321e0SJeremy L Thompson 
171*0d0321e0SJeremy L Thompson   bool has_valid_data = true;
172*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextHasValidData_Hip(ctx, &has_valid_data);
173*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
174*0d0321e0SJeremy L Thompson   switch (mtype) {
175*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
176*0d0321e0SJeremy L Thompson     *need_sync = has_valid_data && !impl->h_data;
177*0d0321e0SJeremy L Thompson     break;
178*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
179*0d0321e0SJeremy L Thompson     *need_sync = has_valid_data && !impl->d_data;
180*0d0321e0SJeremy L Thompson     break;
181*0d0321e0SJeremy L Thompson   }
182*0d0321e0SJeremy L Thompson 
183*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
184*0d0321e0SJeremy L Thompson }
185*0d0321e0SJeremy L Thompson 
186*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
187*0d0321e0SJeremy L Thompson // Set data from host
188*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
189*0d0321e0SJeremy L Thompson static int CeedQFunctionContextSetDataHost_Hip(const CeedQFunctionContext ctx,
190*0d0321e0SJeremy L Thompson     const CeedCopyMode cmode, void *data) {
191*0d0321e0SJeremy L Thompson   int ierr;
192*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
193*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
194*0d0321e0SJeremy L Thompson 
195*0d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_data_owned); CeedChkBackend(ierr);
196*0d0321e0SJeremy L Thompson   switch (cmode) {
197*0d0321e0SJeremy L Thompson   case CEED_COPY_VALUES: {
198*0d0321e0SJeremy L Thompson     ierr = CeedMalloc(bytes(ctx), &impl->h_data_owned); CeedChkBackend(ierr);
199*0d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
200*0d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
201*0d0321e0SJeremy L Thompson     memcpy(impl->h_data, data, bytes(ctx));
202*0d0321e0SJeremy L Thompson   } break;
203*0d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
204*0d0321e0SJeremy L Thompson     impl->h_data_owned = data;
205*0d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
206*0d0321e0SJeremy L Thompson     impl->h_data = data;
207*0d0321e0SJeremy L Thompson     break;
208*0d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
209*0d0321e0SJeremy L Thompson     impl->h_data_borrowed = data;
210*0d0321e0SJeremy L Thompson     impl->h_data = data;
211*0d0321e0SJeremy L Thompson     break;
212*0d0321e0SJeremy L Thompson   }
213*0d0321e0SJeremy L Thompson 
214*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
215*0d0321e0SJeremy L Thompson }
216*0d0321e0SJeremy L Thompson 
217*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
218*0d0321e0SJeremy L Thompson // Set data from device
219*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
220*0d0321e0SJeremy L Thompson static int CeedQFunctionContextSetDataDevice_Hip(const CeedQFunctionContext ctx,
221*0d0321e0SJeremy L Thompson     const CeedCopyMode cmode, void *data) {
222*0d0321e0SJeremy L Thompson   int ierr;
223*0d0321e0SJeremy L Thompson   Ceed ceed;
224*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
225*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
226*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
227*0d0321e0SJeremy L Thompson 
228*0d0321e0SJeremy L Thompson   ierr = hipFree(impl->d_data_owned); CeedChk_Hip(ceed, ierr);
229*0d0321e0SJeremy L Thompson   impl->d_data_owned = NULL;
230*0d0321e0SJeremy L Thompson   switch (cmode) {
231*0d0321e0SJeremy L Thompson   case CEED_COPY_VALUES:
232*0d0321e0SJeremy L Thompson     ierr = hipMalloc((void **)&impl->d_data_owned, bytes(ctx));
233*0d0321e0SJeremy L Thompson     CeedChk_Hip(ceed, ierr);
234*0d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
235*0d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
236*0d0321e0SJeremy L Thompson     ierr = hipMemcpy(impl->d_data, data, bytes(ctx),
237*0d0321e0SJeremy L Thompson                      hipMemcpyDeviceToDevice); CeedChk_Hip(ceed, ierr);
238*0d0321e0SJeremy L Thompson     break;
239*0d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
240*0d0321e0SJeremy L Thompson     impl->d_data_owned = data;
241*0d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
242*0d0321e0SJeremy L Thompson     impl->d_data = data;
243*0d0321e0SJeremy L Thompson     break;
244*0d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
245*0d0321e0SJeremy L Thompson     impl->d_data_owned = NULL;
246*0d0321e0SJeremy L Thompson     impl->d_data_borrowed = data;
247*0d0321e0SJeremy L Thompson     impl->d_data = data;
248*0d0321e0SJeremy L Thompson     break;
249*0d0321e0SJeremy L Thompson   }
250*0d0321e0SJeremy L Thompson 
251*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
252*0d0321e0SJeremy L Thompson }
253*0d0321e0SJeremy L Thompson 
254*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
255*0d0321e0SJeremy L Thompson // Set the data used by a user context,
256*0d0321e0SJeremy L Thompson //   freeing any previously allocated data if applicable
257*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
258*0d0321e0SJeremy L Thompson static int CeedQFunctionContextSetData_Hip(const CeedQFunctionContext ctx,
259*0d0321e0SJeremy L Thompson     const CeedMemType mtype, const CeedCopyMode cmode, void *data) {
260*0d0321e0SJeremy L Thompson   int ierr;
261*0d0321e0SJeremy L Thompson   Ceed ceed;
262*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
263*0d0321e0SJeremy L Thompson 
264*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetAllInvalid_Hip(ctx); CeedChkBackend(ierr);
265*0d0321e0SJeremy L Thompson   switch (mtype) {
266*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
267*0d0321e0SJeremy L Thompson     return CeedQFunctionContextSetDataHost_Hip(ctx, cmode, data);
268*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
269*0d0321e0SJeremy L Thompson     return CeedQFunctionContextSetDataDevice_Hip(ctx, cmode, data);
270*0d0321e0SJeremy L Thompson   }
271*0d0321e0SJeremy L Thompson 
272*0d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
273*0d0321e0SJeremy L Thompson }
274*0d0321e0SJeremy L Thompson 
275*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
276*0d0321e0SJeremy L Thompson // Take data
277*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
278*0d0321e0SJeremy L Thompson static int CeedQFunctionContextTakeData_Hip(const CeedQFunctionContext ctx,
279*0d0321e0SJeremy L Thompson     const CeedMemType mtype, void *data) {
280*0d0321e0SJeremy L Thompson   int ierr;
281*0d0321e0SJeremy L Thompson   Ceed ceed;
282*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
283*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
284*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
285*0d0321e0SJeremy L Thompson 
286*0d0321e0SJeremy L Thompson   // Sync data to requested memtype
287*0d0321e0SJeremy L Thompson   bool need_sync = false;
288*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextNeedSync_Hip(ctx, mtype, &need_sync);
289*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
290*0d0321e0SJeremy L Thompson   if (need_sync) {
291*0d0321e0SJeremy L Thompson     ierr = CeedQFunctionContextSync_Hip(ctx, mtype); CeedChkBackend(ierr);
292*0d0321e0SJeremy L Thompson   }
293*0d0321e0SJeremy L Thompson 
294*0d0321e0SJeremy L Thompson   // Update pointer
295*0d0321e0SJeremy L Thompson   switch (mtype) {
296*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
297*0d0321e0SJeremy L Thompson     *(void **)data = impl->h_data_borrowed;
298*0d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
299*0d0321e0SJeremy L Thompson     impl->h_data = NULL;
300*0d0321e0SJeremy L Thompson     break;
301*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
302*0d0321e0SJeremy L Thompson     *(void **)data = impl->d_data_borrowed;
303*0d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
304*0d0321e0SJeremy L Thompson     impl->d_data = NULL;
305*0d0321e0SJeremy L Thompson     break;
306*0d0321e0SJeremy L Thompson   }
307*0d0321e0SJeremy L Thompson 
308*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
309*0d0321e0SJeremy L Thompson }
310*0d0321e0SJeremy L Thompson 
311*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
312*0d0321e0SJeremy L Thompson // Get data
313*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
314*0d0321e0SJeremy L Thompson static int CeedQFunctionContextGetData_Hip(const CeedQFunctionContext ctx,
315*0d0321e0SJeremy L Thompson     const CeedMemType mtype, void *data) {
316*0d0321e0SJeremy L Thompson   int ierr;
317*0d0321e0SJeremy L Thompson   Ceed ceed;
318*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
319*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
320*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
321*0d0321e0SJeremy L Thompson 
322*0d0321e0SJeremy L Thompson   // Sync data to requested memtype
323*0d0321e0SJeremy L Thompson   bool need_sync = false;
324*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextNeedSync_Hip(ctx, mtype, &need_sync);
325*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
326*0d0321e0SJeremy L Thompson   if (need_sync) {
327*0d0321e0SJeremy L Thompson     ierr = CeedQFunctionContextSync_Hip(ctx, mtype); CeedChkBackend(ierr);
328*0d0321e0SJeremy L Thompson   }
329*0d0321e0SJeremy L Thompson 
330*0d0321e0SJeremy L Thompson   // Sync data to requested memtype and update pointer
331*0d0321e0SJeremy L Thompson   switch (mtype) {
332*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
333*0d0321e0SJeremy L Thompson     *(void **)data = impl->h_data;
334*0d0321e0SJeremy L Thompson     break;
335*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
336*0d0321e0SJeremy L Thompson     *(void **)data = impl->d_data;
337*0d0321e0SJeremy L Thompson     break;
338*0d0321e0SJeremy L Thompson   }
339*0d0321e0SJeremy L Thompson 
340*0d0321e0SJeremy L Thompson   // Mark only pointer for requested memory as valid
341*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetAllInvalid_Hip(ctx); CeedChkBackend(ierr);
342*0d0321e0SJeremy L Thompson   switch (mtype) {
343*0d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
344*0d0321e0SJeremy L Thompson     impl->h_data = *(void **)data;
345*0d0321e0SJeremy L Thompson     break;
346*0d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
347*0d0321e0SJeremy L Thompson     impl->d_data = *(void **)data;
348*0d0321e0SJeremy L Thompson     break;
349*0d0321e0SJeremy L Thompson   }
350*0d0321e0SJeremy L Thompson 
351*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
352*0d0321e0SJeremy L Thompson }
353*0d0321e0SJeremy L Thompson 
354*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
355*0d0321e0SJeremy L Thompson // Restore data obtained using CeedQFunctionContextGetData()
356*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
357*0d0321e0SJeremy L Thompson static int CeedQFunctionContextRestoreData_Hip(const CeedQFunctionContext ctx) {
358*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
359*0d0321e0SJeremy L Thompson }
360*0d0321e0SJeremy L Thompson 
361*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
362*0d0321e0SJeremy L Thompson // Destroy the user context
363*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
364*0d0321e0SJeremy L Thompson static int CeedQFunctionContextDestroy_Hip(const CeedQFunctionContext ctx) {
365*0d0321e0SJeremy L Thompson   int ierr;
366*0d0321e0SJeremy L Thompson   Ceed ceed;
367*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
368*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
369*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
370*0d0321e0SJeremy L Thompson 
371*0d0321e0SJeremy L Thompson   ierr = hipFree(impl->d_data_owned); CeedChk_Hip(ceed, ierr);
372*0d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_data_owned); CeedChkBackend(ierr);
373*0d0321e0SJeremy L Thompson   ierr = CeedFree(&impl); CeedChkBackend(ierr);
374*0d0321e0SJeremy L Thompson 
375*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
376*0d0321e0SJeremy L Thompson }
377*0d0321e0SJeremy L Thompson 
378*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
379*0d0321e0SJeremy L Thompson // QFunctionContext Create
380*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
381*0d0321e0SJeremy L Thompson int CeedQFunctionContextCreate_Hip(CeedQFunctionContext ctx) {
382*0d0321e0SJeremy L Thompson   int ierr;
383*0d0321e0SJeremy L Thompson   CeedQFunctionContext_Hip *impl;
384*0d0321e0SJeremy L Thompson   Ceed ceed;
385*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
386*0d0321e0SJeremy L Thompson 
387*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData",
388*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextHasValidData_Hip);
389*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
390*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx,
391*0d0321e0SJeremy L Thompson                                 "HasBorrowedDataOfType",
392*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextHasBorrowedDataOfType_Hip);
393*0d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
394*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData",
395*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextSetData_Hip); CeedChkBackend(ierr);
396*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData",
397*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextTakeData_Hip); CeedChkBackend(ierr);
398*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData",
399*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextGetData_Hip); CeedChkBackend(ierr);
400*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreData",
401*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextRestoreData_Hip); CeedChkBackend(ierr);
402*0d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy",
403*0d0321e0SJeremy L Thompson                                 CeedQFunctionContextDestroy_Hip); CeedChkBackend(ierr);
404*0d0321e0SJeremy L Thompson 
405*0d0321e0SJeremy L Thompson   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
406*0d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetBackendData(ctx, impl); CeedChkBackend(ierr);
407*0d0321e0SJeremy L Thompson 
408*0d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
409*0d0321e0SJeremy L Thompson }
410*0d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
411