xref: /libCEED/backends/cuda-ref/ceed-cuda-ref-qfunctioncontext.c (revision 52b3e6a738faffda5b45f08b3021a8d767a770af)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
30d0321e0SJeremy L Thompson //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
50d0321e0SJeremy L Thompson //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
70d0321e0SJeremy L Thompson 
80d0321e0SJeremy L Thompson #include <ceed/ceed.h>
90d0321e0SJeremy L Thompson #include <ceed/backend.h>
100d0321e0SJeremy L Thompson #include <cuda_runtime.h>
110d0321e0SJeremy L Thompson #include <string.h>
120d0321e0SJeremy L Thompson #include "ceed-cuda-ref.h"
130d0321e0SJeremy L Thompson 
140d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
150d0321e0SJeremy L Thompson // Sync host to device
160d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
170d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSyncH2D_Cuda(
180d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
190d0321e0SJeremy L Thompson   int ierr;
200d0321e0SJeremy L Thompson   Ceed ceed;
210d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
220d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
230d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
240d0321e0SJeremy L Thompson 
250d0321e0SJeremy L Thompson   if (!impl->h_data)
260d0321e0SJeremy L Thompson     // LCOV_EXCL_START
270d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
280d0321e0SJeremy L Thompson                      "No valid host data to sync to device");
290d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
300d0321e0SJeremy L Thompson 
31539ec17dSJeremy L Thompson   size_t ctxsize;
32539ec17dSJeremy L Thompson   ierr = CeedQFunctionContextGetContextSize(ctx, &ctxsize); CeedChkBackend(ierr);
33539ec17dSJeremy L Thompson 
340d0321e0SJeremy L Thompson   if (impl->d_data_borrowed) {
350d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_borrowed;
360d0321e0SJeremy L Thompson   } else if (impl->d_data_owned) {
370d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
380d0321e0SJeremy L Thompson   } else {
39539ec17dSJeremy L Thompson     ierr = cudaMalloc((void **)&impl->d_data_owned, ctxsize);
400d0321e0SJeremy L Thompson     CeedChk_Cu(ceed, ierr);
410d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
420d0321e0SJeremy L Thompson   }
430d0321e0SJeremy L Thompson 
44539ec17dSJeremy L Thompson   ierr = cudaMemcpy(impl->d_data, impl->h_data, ctxsize,
450d0321e0SJeremy L Thompson                     cudaMemcpyHostToDevice); CeedChk_Cu(ceed, ierr);
460d0321e0SJeremy L Thompson 
470d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
480d0321e0SJeremy L Thompson }
490d0321e0SJeremy L Thompson 
500d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
510d0321e0SJeremy L Thompson // Sync device to host
520d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
530d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSyncD2H_Cuda(
540d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
550d0321e0SJeremy L Thompson   int ierr;
560d0321e0SJeremy L Thompson   Ceed ceed;
570d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
580d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
590d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
600d0321e0SJeremy L Thompson 
610d0321e0SJeremy L Thompson   if (!impl->d_data)
620d0321e0SJeremy L Thompson     // LCOV_EXCL_START
630d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
640d0321e0SJeremy L Thompson                      "No valid device data to sync to host");
650d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
660d0321e0SJeremy L Thompson 
67539ec17dSJeremy L Thompson   size_t ctxsize;
68539ec17dSJeremy L Thompson   ierr = CeedQFunctionContextGetContextSize(ctx, &ctxsize); CeedChkBackend(ierr);
69539ec17dSJeremy L Thompson 
700d0321e0SJeremy L Thompson   if (impl->h_data_borrowed) {
710d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_borrowed;
720d0321e0SJeremy L Thompson   } else if (impl->h_data_owned) {
730d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
740d0321e0SJeremy L Thompson   } else {
75c470c2d9Snbeams     ierr = CeedMallocArray(1, ctxsize, &impl->h_data_owned);
760d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
770d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
780d0321e0SJeremy L Thompson   }
790d0321e0SJeremy L Thompson 
80539ec17dSJeremy L Thompson   ierr = cudaMemcpy(impl->h_data, impl->d_data, ctxsize,
810d0321e0SJeremy L Thompson                     cudaMemcpyDeviceToHost); CeedChk_Cu(ceed, ierr);
820d0321e0SJeremy L Thompson 
830d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
840d0321e0SJeremy L Thompson }
850d0321e0SJeremy L Thompson 
860d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
870d0321e0SJeremy L Thompson // Sync data of type
880d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
890d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSync_Cuda(
9043c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mem_type) {
9143c928f4SJeremy L Thompson   switch (mem_type) {
920d0321e0SJeremy L Thompson   case CEED_MEM_HOST: return CeedQFunctionContextSyncD2H_Cuda(ctx);
930d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE: return CeedQFunctionContextSyncH2D_Cuda(ctx);
940d0321e0SJeremy L Thompson   }
950d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
960d0321e0SJeremy L Thompson }
970d0321e0SJeremy L Thompson 
980d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
990d0321e0SJeremy L Thompson // Set all pointers as invalid
1000d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1010d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSetAllInvalid_Cuda(
1020d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
1030d0321e0SJeremy L Thompson   int ierr;
1040d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1050d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1060d0321e0SJeremy L Thompson 
1070d0321e0SJeremy L Thompson   impl->h_data = NULL;
1080d0321e0SJeremy L Thompson   impl->d_data = NULL;
1090d0321e0SJeremy L Thompson 
1100d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1110d0321e0SJeremy L Thompson }
1120d0321e0SJeremy L Thompson 
1130d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1140d0321e0SJeremy L Thompson // Check if ctx has valid data
1150d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1160d0321e0SJeremy L Thompson static inline int CeedQFunctionContextHasValidData_Cuda(
1170d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx, bool *has_valid_data) {
1180d0321e0SJeremy L Thompson   int ierr;
1190d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1200d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1210d0321e0SJeremy L Thompson 
122*52b3e6a7SJed Brown   *has_valid_data = impl && (!!impl->h_data || !!impl->d_data);
1230d0321e0SJeremy L Thompson 
1240d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1250d0321e0SJeremy L Thompson }
1260d0321e0SJeremy L Thompson 
1270d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1280d0321e0SJeremy L Thompson // Check if ctx has borrowed data
1290d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1300d0321e0SJeremy L Thompson static inline int CeedQFunctionContextHasBorrowedDataOfType_Cuda(
13143c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mem_type,
1320d0321e0SJeremy L Thompson   bool *has_borrowed_data_of_type) {
1330d0321e0SJeremy L Thompson   int ierr;
1340d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1350d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1360d0321e0SJeremy L Thompson 
13743c928f4SJeremy L Thompson   switch (mem_type) {
1380d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1390d0321e0SJeremy L Thompson     *has_borrowed_data_of_type = !!impl->h_data_borrowed;
1400d0321e0SJeremy L Thompson     break;
1410d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1420d0321e0SJeremy L Thompson     *has_borrowed_data_of_type = !!impl->d_data_borrowed;
1430d0321e0SJeremy L Thompson     break;
1440d0321e0SJeremy L Thompson   }
1450d0321e0SJeremy L Thompson 
1460d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1470d0321e0SJeremy L Thompson }
1480d0321e0SJeremy L Thompson 
1490d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1500d0321e0SJeremy L Thompson // Check if data of given type needs sync
1510d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1520d0321e0SJeremy L Thompson static inline int CeedQFunctionContextNeedSync_Cuda(
15343c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mem_type, bool *need_sync) {
1540d0321e0SJeremy L Thompson   int ierr;
1550d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1560d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1570d0321e0SJeremy L Thompson 
1580d0321e0SJeremy L Thompson   bool has_valid_data = true;
1590d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data);
1600d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
16143c928f4SJeremy L Thompson   switch (mem_type) {
1620d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1630d0321e0SJeremy L Thompson     *need_sync = has_valid_data && !impl->h_data;
1640d0321e0SJeremy L Thompson     break;
1650d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1660d0321e0SJeremy L Thompson     *need_sync = has_valid_data && !impl->d_data;
1670d0321e0SJeremy L Thompson     break;
1680d0321e0SJeremy L Thompson   }
1690d0321e0SJeremy L Thompson 
1700d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1710d0321e0SJeremy L Thompson }
1720d0321e0SJeremy L Thompson 
1730d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1740d0321e0SJeremy L Thompson // Set data from host
1750d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1760d0321e0SJeremy L Thompson static int CeedQFunctionContextSetDataHost_Cuda(const CeedQFunctionContext ctx,
17743c928f4SJeremy L Thompson     const CeedCopyMode copy_mode, void *data) {
1780d0321e0SJeremy L Thompson   int ierr;
1790d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1800d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1810d0321e0SJeremy L Thompson 
1820d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_data_owned); CeedChkBackend(ierr);
18343c928f4SJeremy L Thompson   switch (copy_mode) {
1840d0321e0SJeremy L Thompson   case CEED_COPY_VALUES: {
185539ec17dSJeremy L Thompson     size_t ctxsize;
186539ec17dSJeremy L Thompson     ierr = CeedQFunctionContextGetContextSize(ctx, &ctxsize); CeedChkBackend(ierr);
187c470c2d9Snbeams     ierr = CeedMallocArray(1, ctxsize, &impl->h_data_owned);
188c470c2d9Snbeams     CeedChkBackend(ierr);
1890d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
1900d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
191539ec17dSJeremy L Thompson     memcpy(impl->h_data, data, ctxsize);
1920d0321e0SJeremy L Thompson   } break;
1930d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
1940d0321e0SJeremy L Thompson     impl->h_data_owned = data;
1950d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
1960d0321e0SJeremy L Thompson     impl->h_data = data;
1970d0321e0SJeremy L Thompson     break;
1980d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
1990d0321e0SJeremy L Thompson     impl->h_data_borrowed = data;
2000d0321e0SJeremy L Thompson     impl->h_data = data;
2010d0321e0SJeremy L Thompson     break;
2020d0321e0SJeremy L Thompson   }
2030d0321e0SJeremy L Thompson 
2040d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2050d0321e0SJeremy L Thompson }
2060d0321e0SJeremy L Thompson 
2070d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2080d0321e0SJeremy L Thompson // Set data from device
2090d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2100d0321e0SJeremy L Thompson static int CeedQFunctionContextSetDataDevice_Cuda(
21143c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, const CeedCopyMode copy_mode, void *data) {
2120d0321e0SJeremy L Thompson   int ierr;
2130d0321e0SJeremy L Thompson   Ceed ceed;
2140d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
2150d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
2160d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
2170d0321e0SJeremy L Thompson 
2180d0321e0SJeremy L Thompson   ierr = cudaFree(impl->d_data_owned); CeedChk_Cu(ceed, ierr);
2190d0321e0SJeremy L Thompson   impl->d_data_owned = NULL;
22043c928f4SJeremy L Thompson   switch (copy_mode) {
221539ec17dSJeremy L Thompson   case CEED_COPY_VALUES: {
222539ec17dSJeremy L Thompson     size_t ctxsize;
223539ec17dSJeremy L Thompson     ierr = CeedQFunctionContextGetContextSize(ctx, &ctxsize); CeedChkBackend(ierr);
224539ec17dSJeremy L Thompson     ierr = cudaMalloc((void **)&impl->d_data_owned, ctxsize);
2250d0321e0SJeremy L Thompson     CeedChk_Cu(ceed, ierr);
2260d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
2270d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
228539ec17dSJeremy L Thompson     ierr = cudaMemcpy(impl->d_data, data, ctxsize,
2290d0321e0SJeremy L Thompson                       cudaMemcpyDeviceToDevice); CeedChk_Cu(ceed, ierr);
230539ec17dSJeremy L Thompson   } break;
2310d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
2320d0321e0SJeremy L Thompson     impl->d_data_owned = data;
2330d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
2340d0321e0SJeremy L Thompson     impl->d_data = data;
2350d0321e0SJeremy L Thompson     break;
2360d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
2370d0321e0SJeremy L Thompson     impl->d_data_owned = NULL;
2380d0321e0SJeremy L Thompson     impl->d_data_borrowed = data;
2390d0321e0SJeremy L Thompson     impl->d_data = data;
2400d0321e0SJeremy L Thompson     break;
2410d0321e0SJeremy L Thompson   }
2420d0321e0SJeremy L Thompson 
2430d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2440d0321e0SJeremy L Thompson }
2450d0321e0SJeremy L Thompson 
2460d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2470d0321e0SJeremy L Thompson // Set the data used by a user context,
2480d0321e0SJeremy L Thompson //   freeing any previously allocated data if applicable
2490d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2500d0321e0SJeremy L Thompson static int CeedQFunctionContextSetData_Cuda(const CeedQFunctionContext ctx,
25143c928f4SJeremy L Thompson     const CeedMemType mem_type, const CeedCopyMode copy_mode, void *data) {
2520d0321e0SJeremy L Thompson   int ierr;
2530d0321e0SJeremy L Thompson   Ceed ceed;
2540d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
2550d0321e0SJeremy L Thompson 
2560d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetAllInvalid_Cuda(ctx); CeedChkBackend(ierr);
25743c928f4SJeremy L Thompson   switch (mem_type) {
2580d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
25943c928f4SJeremy L Thompson     return CeedQFunctionContextSetDataHost_Cuda(ctx, copy_mode, data);
2600d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
26143c928f4SJeremy L Thompson     return CeedQFunctionContextSetDataDevice_Cuda(ctx, copy_mode, data);
2620d0321e0SJeremy L Thompson   }
2630d0321e0SJeremy L Thompson 
2640d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
2650d0321e0SJeremy L Thompson }
2660d0321e0SJeremy L Thompson 
2670d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2680d0321e0SJeremy L Thompson // Take data
2690d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2700d0321e0SJeremy L Thompson static int CeedQFunctionContextTakeData_Cuda(const CeedQFunctionContext ctx,
27143c928f4SJeremy L Thompson     const CeedMemType mem_type, void *data) {
2720d0321e0SJeremy L Thompson   int ierr;
2730d0321e0SJeremy L Thompson   Ceed ceed;
2740d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
2750d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
2760d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
2770d0321e0SJeremy L Thompson 
27843c928f4SJeremy L Thompson   // Sync data to requested mem_type
2790d0321e0SJeremy L Thompson   bool need_sync = false;
28043c928f4SJeremy L Thompson   ierr = CeedQFunctionContextNeedSync_Cuda(ctx, mem_type, &need_sync);
2810d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
2820d0321e0SJeremy L Thompson   if (need_sync) {
28343c928f4SJeremy L Thompson     ierr = CeedQFunctionContextSync_Cuda(ctx, mem_type); CeedChkBackend(ierr);
2840d0321e0SJeremy L Thompson   }
2850d0321e0SJeremy L Thompson 
2860d0321e0SJeremy L Thompson   // Update pointer
28743c928f4SJeremy L Thompson   switch (mem_type) {
2880d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
2890d0321e0SJeremy L Thompson     *(void **)data = impl->h_data_borrowed;
2900d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
2910d0321e0SJeremy L Thompson     impl->h_data = NULL;
2920d0321e0SJeremy L Thompson     break;
2930d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
2940d0321e0SJeremy L Thompson     *(void **)data = impl->d_data_borrowed;
2950d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
2960d0321e0SJeremy L Thompson     impl->d_data = NULL;
2970d0321e0SJeremy L Thompson     break;
2980d0321e0SJeremy L Thompson   }
2990d0321e0SJeremy L Thompson 
3000d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3010d0321e0SJeremy L Thompson }
3020d0321e0SJeremy L Thompson 
3030d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
30428bfd0b7SJeremy L Thompson // Core logic for GetData.
30528bfd0b7SJeremy L Thompson //   If a different memory type is most up to date, this will perform a copy
3060d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
30728bfd0b7SJeremy L Thompson static int CeedQFunctionContextGetDataCore_Cuda(const CeedQFunctionContext ctx,
30843c928f4SJeremy L Thompson     const CeedMemType mem_type, void *data) {
3090d0321e0SJeremy L Thompson   int ierr;
3100d0321e0SJeremy L Thompson   Ceed ceed;
3110d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
3120d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
3130d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
3140d0321e0SJeremy L Thompson 
31543c928f4SJeremy L Thompson   // Sync data to requested mem_type
3160d0321e0SJeremy L Thompson   bool need_sync = false;
31743c928f4SJeremy L Thompson   ierr = CeedQFunctionContextNeedSync_Cuda(ctx, mem_type, &need_sync);
3180d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
3190d0321e0SJeremy L Thompson   if (need_sync) {
32043c928f4SJeremy L Thompson     ierr = CeedQFunctionContextSync_Cuda(ctx, mem_type); CeedChkBackend(ierr);
3210d0321e0SJeremy L Thompson   }
3220d0321e0SJeremy L Thompson 
3230d0321e0SJeremy L Thompson   // Update pointer
32443c928f4SJeremy L Thompson   switch (mem_type) {
3250d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
3260d0321e0SJeremy L Thompson     *(void **)data = impl->h_data;
3270d0321e0SJeremy L Thompson     break;
3280d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
3290d0321e0SJeremy L Thompson     *(void **)data = impl->d_data;
3300d0321e0SJeremy L Thompson     break;
3310d0321e0SJeremy L Thompson   }
3320d0321e0SJeremy L Thompson 
33328bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
33428bfd0b7SJeremy L Thompson }
33528bfd0b7SJeremy L Thompson 
33628bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
33728bfd0b7SJeremy L Thompson // Get read-only access to the data
33828bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
33928bfd0b7SJeremy L Thompson static int CeedQFunctionContextGetDataRead_Cuda(const CeedQFunctionContext ctx,
34028bfd0b7SJeremy L Thompson     const CeedMemType mem_type, void *data) {
34128bfd0b7SJeremy L Thompson   return CeedQFunctionContextGetDataCore_Cuda(ctx, mem_type, data);
34228bfd0b7SJeremy L Thompson }
34328bfd0b7SJeremy L Thompson 
34428bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
34528bfd0b7SJeremy L Thompson // Get read/write access to the data
34628bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
34728bfd0b7SJeremy L Thompson static int CeedQFunctionContextGetData_Cuda(const CeedQFunctionContext ctx,
34828bfd0b7SJeremy L Thompson     const CeedMemType mem_type, void *data) {
34928bfd0b7SJeremy L Thompson   int ierr;
35028bfd0b7SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
35128bfd0b7SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
35228bfd0b7SJeremy L Thompson 
35328bfd0b7SJeremy L Thompson   ierr = CeedQFunctionContextGetDataCore_Cuda(ctx, mem_type, data);
35428bfd0b7SJeremy L Thompson   CeedChkBackend(ierr);
35528bfd0b7SJeremy L Thompson 
3560d0321e0SJeremy L Thompson   // Mark only pointer for requested memory as valid
3570d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetAllInvalid_Cuda(ctx); CeedChkBackend(ierr);
35843c928f4SJeremy L Thompson   switch (mem_type) {
3590d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
3600d0321e0SJeremy L Thompson     impl->h_data = *(void **)data;
3610d0321e0SJeremy L Thompson     break;
3620d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
3630d0321e0SJeremy L Thompson     impl->d_data = *(void **)data;
3640d0321e0SJeremy L Thompson     break;
3650d0321e0SJeremy L Thompson   }
3660d0321e0SJeremy L Thompson 
3670d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3680d0321e0SJeremy L Thompson }
3690d0321e0SJeremy L Thompson 
3700d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3710d0321e0SJeremy L Thompson // Destroy the user context
3720d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3730d0321e0SJeremy L Thompson static int CeedQFunctionContextDestroy_Cuda(const CeedQFunctionContext ctx) {
3740d0321e0SJeremy L Thompson   int ierr;
3750d0321e0SJeremy L Thompson   Ceed ceed;
3760d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
3770d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
3780d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
3790d0321e0SJeremy L Thompson 
3800d0321e0SJeremy L Thompson   ierr = cudaFree(impl->d_data_owned); CeedChk_Cu(ceed, ierr);
3810d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_data_owned); CeedChkBackend(ierr);
3820d0321e0SJeremy L Thompson   ierr = CeedFree(&impl); CeedChkBackend(ierr);
3830d0321e0SJeremy L Thompson 
3840d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3850d0321e0SJeremy L Thompson }
3860d0321e0SJeremy L Thompson 
3870d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3880d0321e0SJeremy L Thompson // QFunctionContext Create
3890d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3900d0321e0SJeremy L Thompson int CeedQFunctionContextCreate_Cuda(CeedQFunctionContext ctx) {
3910d0321e0SJeremy L Thompson   int ierr;
3920d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
3930d0321e0SJeremy L Thompson   Ceed ceed;
3940d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
3950d0321e0SJeremy L Thompson 
3960d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData",
3970d0321e0SJeremy L Thompson                                 CeedQFunctionContextHasValidData_Cuda);
3980d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
3990d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx,
4000d0321e0SJeremy L Thompson                                 "HasBorrowedDataOfType",
4010d0321e0SJeremy L Thompson                                 CeedQFunctionContextHasBorrowedDataOfType_Cuda);
4020d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
4030d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData",
4040d0321e0SJeremy L Thompson                                 CeedQFunctionContextSetData_Cuda); CeedChkBackend(ierr);
4050d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData",
4060d0321e0SJeremy L Thompson                                 CeedQFunctionContextTakeData_Cuda); CeedChkBackend(ierr);
4070d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData",
4080d0321e0SJeremy L Thompson                                 CeedQFunctionContextGetData_Cuda); CeedChkBackend(ierr);
40928bfd0b7SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead",
41028bfd0b7SJeremy L Thompson                                 CeedQFunctionContextGetDataRead_Cuda); CeedChkBackend(ierr);
4110d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy",
4120d0321e0SJeremy L Thompson                                 CeedQFunctionContextDestroy_Cuda); CeedChkBackend(ierr);
4130d0321e0SJeremy L Thompson 
4140d0321e0SJeremy L Thompson   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
4150d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetBackendData(ctx, impl); CeedChkBackend(ierr);
4160d0321e0SJeremy L Thompson 
4170d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4180d0321e0SJeremy L Thompson }
4190d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
420