xref: /libCEED/rust/libceed-sys/c-src/backends/cuda-ref/ceed-cuda-ref-qfunctioncontext.c (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
30d0321e0SJeremy L Thompson //
4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
50d0321e0SJeremy L Thompson //
6*3d8e8822SJeremy 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 // * Bytes used
160d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
170d0321e0SJeremy L Thompson static inline size_t bytes(const CeedQFunctionContext ctx) {
180d0321e0SJeremy L Thompson   int ierr;
190d0321e0SJeremy L Thompson   size_t ctxsize;
200d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetContextSize(ctx, &ctxsize); CeedChkBackend(ierr);
210d0321e0SJeremy L Thompson   return ctxsize;
220d0321e0SJeremy L Thompson }
230d0321e0SJeremy L Thompson 
240d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
250d0321e0SJeremy L Thompson // Sync host to device
260d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
270d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSyncH2D_Cuda(
280d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
290d0321e0SJeremy L Thompson   int ierr;
300d0321e0SJeremy L Thompson   Ceed ceed;
310d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
320d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
330d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
340d0321e0SJeremy L Thompson 
350d0321e0SJeremy L Thompson   if (!impl->h_data)
360d0321e0SJeremy L Thompson     // LCOV_EXCL_START
370d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
380d0321e0SJeremy L Thompson                      "No valid host data to sync to device");
390d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
400d0321e0SJeremy L Thompson 
410d0321e0SJeremy L Thompson   if (impl->d_data_borrowed) {
420d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_borrowed;
430d0321e0SJeremy L Thompson   } else if (impl->d_data_owned) {
440d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
450d0321e0SJeremy L Thompson   } else {
460d0321e0SJeremy L Thompson     ierr = cudaMalloc((void **)&impl->d_data_owned, bytes(ctx));
470d0321e0SJeremy L Thompson     CeedChk_Cu(ceed, ierr);
480d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
490d0321e0SJeremy L Thompson   }
500d0321e0SJeremy L Thompson 
510d0321e0SJeremy L Thompson   ierr = cudaMemcpy(impl->d_data, impl->h_data, bytes(ctx),
520d0321e0SJeremy L Thompson                     cudaMemcpyHostToDevice); CeedChk_Cu(ceed, ierr);
530d0321e0SJeremy L Thompson 
540d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
550d0321e0SJeremy L Thompson }
560d0321e0SJeremy L Thompson 
570d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
580d0321e0SJeremy L Thompson // Sync device to host
590d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
600d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSyncD2H_Cuda(
610d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
620d0321e0SJeremy L Thompson   int ierr;
630d0321e0SJeremy L Thompson   Ceed ceed;
640d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
650d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
660d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
670d0321e0SJeremy L Thompson 
680d0321e0SJeremy L Thompson   if (!impl->d_data)
690d0321e0SJeremy L Thompson     // LCOV_EXCL_START
700d0321e0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_BACKEND,
710d0321e0SJeremy L Thompson                      "No valid device data to sync to host");
720d0321e0SJeremy L Thompson   // LCOV_EXCL_STOP
730d0321e0SJeremy L Thompson 
740d0321e0SJeremy L Thompson   if (impl->h_data_borrowed) {
750d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_borrowed;
760d0321e0SJeremy L Thompson   } else if (impl->h_data_owned) {
770d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
780d0321e0SJeremy L Thompson   } else {
790d0321e0SJeremy L Thompson     ierr = CeedMalloc(bytes(ctx), &impl->h_data_owned);
800d0321e0SJeremy L Thompson     CeedChkBackend(ierr);
810d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
820d0321e0SJeremy L Thompson   }
830d0321e0SJeremy L Thompson 
840d0321e0SJeremy L Thompson   ierr = cudaMemcpy(impl->h_data, impl->d_data, bytes(ctx),
850d0321e0SJeremy L Thompson                     cudaMemcpyDeviceToHost); CeedChk_Cu(ceed, ierr);
860d0321e0SJeremy L Thompson 
870d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
880d0321e0SJeremy L Thompson }
890d0321e0SJeremy L Thompson 
900d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
910d0321e0SJeremy L Thompson // Sync data of type
920d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
930d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSync_Cuda(
9443c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mem_type) {
9543c928f4SJeremy L Thompson   switch (mem_type) {
960d0321e0SJeremy L Thompson   case CEED_MEM_HOST: return CeedQFunctionContextSyncD2H_Cuda(ctx);
970d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE: return CeedQFunctionContextSyncH2D_Cuda(ctx);
980d0321e0SJeremy L Thompson   }
990d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
1000d0321e0SJeremy L Thompson }
1010d0321e0SJeremy L Thompson 
1020d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1030d0321e0SJeremy L Thompson // Set all pointers as invalid
1040d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1050d0321e0SJeremy L Thompson static inline int CeedQFunctionContextSetAllInvalid_Cuda(
1060d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx) {
1070d0321e0SJeremy L Thompson   int ierr;
1080d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1090d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1100d0321e0SJeremy L Thompson 
1110d0321e0SJeremy L Thompson   impl->h_data = NULL;
1120d0321e0SJeremy L Thompson   impl->d_data = NULL;
1130d0321e0SJeremy L Thompson 
1140d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1150d0321e0SJeremy L Thompson }
1160d0321e0SJeremy L Thompson 
1170d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1180d0321e0SJeremy L Thompson // Check if ctx has valid data
1190d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1200d0321e0SJeremy L Thompson static inline int CeedQFunctionContextHasValidData_Cuda(
1210d0321e0SJeremy L Thompson   const CeedQFunctionContext ctx, bool *has_valid_data) {
1220d0321e0SJeremy L Thompson   int ierr;
1230d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1240d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1250d0321e0SJeremy L Thompson 
1260d0321e0SJeremy L Thompson   *has_valid_data = !!impl->h_data || !!impl->d_data;
1270d0321e0SJeremy L Thompson 
1280d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1290d0321e0SJeremy L Thompson }
1300d0321e0SJeremy L Thompson 
1310d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1320d0321e0SJeremy L Thompson // Check if ctx has borrowed data
1330d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1340d0321e0SJeremy L Thompson static inline int CeedQFunctionContextHasBorrowedDataOfType_Cuda(
13543c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mem_type,
1360d0321e0SJeremy L Thompson   bool *has_borrowed_data_of_type) {
1370d0321e0SJeremy L Thompson   int ierr;
1380d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1390d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1400d0321e0SJeremy L Thompson 
14143c928f4SJeremy L Thompson   switch (mem_type) {
1420d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1430d0321e0SJeremy L Thompson     *has_borrowed_data_of_type = !!impl->h_data_borrowed;
1440d0321e0SJeremy L Thompson     break;
1450d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1460d0321e0SJeremy L Thompson     *has_borrowed_data_of_type = !!impl->d_data_borrowed;
1470d0321e0SJeremy L Thompson     break;
1480d0321e0SJeremy L Thompson   }
1490d0321e0SJeremy L Thompson 
1500d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1510d0321e0SJeremy L Thompson }
1520d0321e0SJeremy L Thompson 
1530d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1540d0321e0SJeremy L Thompson // Check if data of given type needs sync
1550d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1560d0321e0SJeremy L Thompson static inline int CeedQFunctionContextNeedSync_Cuda(
15743c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, CeedMemType mem_type, bool *need_sync) {
1580d0321e0SJeremy L Thompson   int ierr;
1590d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1600d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1610d0321e0SJeremy L Thompson 
1620d0321e0SJeremy L Thompson   bool has_valid_data = true;
1630d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data);
1640d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
16543c928f4SJeremy L Thompson   switch (mem_type) {
1660d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
1670d0321e0SJeremy L Thompson     *need_sync = has_valid_data && !impl->h_data;
1680d0321e0SJeremy L Thompson     break;
1690d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
1700d0321e0SJeremy L Thompson     *need_sync = has_valid_data && !impl->d_data;
1710d0321e0SJeremy L Thompson     break;
1720d0321e0SJeremy L Thompson   }
1730d0321e0SJeremy L Thompson 
1740d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1750d0321e0SJeremy L Thompson }
1760d0321e0SJeremy L Thompson 
1770d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1780d0321e0SJeremy L Thompson // Set data from host
1790d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
1800d0321e0SJeremy L Thompson static int CeedQFunctionContextSetDataHost_Cuda(const CeedQFunctionContext ctx,
18143c928f4SJeremy L Thompson     const CeedCopyMode copy_mode, void *data) {
1820d0321e0SJeremy L Thompson   int ierr;
1830d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
1840d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
1850d0321e0SJeremy L Thompson 
1860d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_data_owned); CeedChkBackend(ierr);
18743c928f4SJeremy L Thompson   switch (copy_mode) {
1880d0321e0SJeremy L Thompson   case CEED_COPY_VALUES: {
1890d0321e0SJeremy L Thompson     ierr = CeedMalloc(bytes(ctx), &impl->h_data_owned); CeedChkBackend(ierr);
1900d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
1910d0321e0SJeremy L Thompson     impl->h_data = impl->h_data_owned;
1920d0321e0SJeremy L Thompson     memcpy(impl->h_data, data, bytes(ctx));
1930d0321e0SJeremy L Thompson   } break;
1940d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
1950d0321e0SJeremy L Thompson     impl->h_data_owned = data;
1960d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
1970d0321e0SJeremy L Thompson     impl->h_data = data;
1980d0321e0SJeremy L Thompson     break;
1990d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
2000d0321e0SJeremy L Thompson     impl->h_data_borrowed = data;
2010d0321e0SJeremy L Thompson     impl->h_data = data;
2020d0321e0SJeremy L Thompson     break;
2030d0321e0SJeremy L Thompson   }
2040d0321e0SJeremy L Thompson 
2050d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2060d0321e0SJeremy L Thompson }
2070d0321e0SJeremy L Thompson 
2080d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2090d0321e0SJeremy L Thompson // Set data from device
2100d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2110d0321e0SJeremy L Thompson static int CeedQFunctionContextSetDataDevice_Cuda(
21243c928f4SJeremy L Thompson   const CeedQFunctionContext ctx, const CeedCopyMode copy_mode, void *data) {
2130d0321e0SJeremy L Thompson   int ierr;
2140d0321e0SJeremy L Thompson   Ceed ceed;
2150d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
2160d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
2170d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
2180d0321e0SJeremy L Thompson 
2190d0321e0SJeremy L Thompson   ierr = cudaFree(impl->d_data_owned); CeedChk_Cu(ceed, ierr);
2200d0321e0SJeremy L Thompson   impl->d_data_owned = NULL;
22143c928f4SJeremy L Thompson   switch (copy_mode) {
2220d0321e0SJeremy L Thompson   case CEED_COPY_VALUES:
2230d0321e0SJeremy L Thompson     ierr = cudaMalloc((void **)&impl->d_data_owned, bytes(ctx));
2240d0321e0SJeremy L Thompson     CeedChk_Cu(ceed, ierr);
2250d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
2260d0321e0SJeremy L Thompson     impl->d_data = impl->d_data_owned;
2270d0321e0SJeremy L Thompson     ierr = cudaMemcpy(impl->d_data, data, bytes(ctx),
2280d0321e0SJeremy L Thompson                       cudaMemcpyDeviceToDevice); CeedChk_Cu(ceed, ierr);
2290d0321e0SJeremy L Thompson     break;
2300d0321e0SJeremy L Thompson   case CEED_OWN_POINTER:
2310d0321e0SJeremy L Thompson     impl->d_data_owned = data;
2320d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
2330d0321e0SJeremy L Thompson     impl->d_data = data;
2340d0321e0SJeremy L Thompson     break;
2350d0321e0SJeremy L Thompson   case CEED_USE_POINTER:
2360d0321e0SJeremy L Thompson     impl->d_data_owned = NULL;
2370d0321e0SJeremy L Thompson     impl->d_data_borrowed = data;
2380d0321e0SJeremy L Thompson     impl->d_data = data;
2390d0321e0SJeremy L Thompson     break;
2400d0321e0SJeremy L Thompson   }
2410d0321e0SJeremy L Thompson 
2420d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2430d0321e0SJeremy L Thompson }
2440d0321e0SJeremy L Thompson 
2450d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2460d0321e0SJeremy L Thompson // Set the data used by a user context,
2470d0321e0SJeremy L Thompson //   freeing any previously allocated data if applicable
2480d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2490d0321e0SJeremy L Thompson static int CeedQFunctionContextSetData_Cuda(const CeedQFunctionContext ctx,
25043c928f4SJeremy L Thompson     const CeedMemType mem_type, const CeedCopyMode copy_mode, void *data) {
2510d0321e0SJeremy L Thompson   int ierr;
2520d0321e0SJeremy L Thompson   Ceed ceed;
2530d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
2540d0321e0SJeremy L Thompson 
2550d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetAllInvalid_Cuda(ctx); CeedChkBackend(ierr);
25643c928f4SJeremy L Thompson   switch (mem_type) {
2570d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
25843c928f4SJeremy L Thompson     return CeedQFunctionContextSetDataHost_Cuda(ctx, copy_mode, data);
2590d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
26043c928f4SJeremy L Thompson     return CeedQFunctionContextSetDataDevice_Cuda(ctx, copy_mode, data);
2610d0321e0SJeremy L Thompson   }
2620d0321e0SJeremy L Thompson 
2630d0321e0SJeremy L Thompson   return CEED_ERROR_UNSUPPORTED;
2640d0321e0SJeremy L Thompson }
2650d0321e0SJeremy L Thompson 
2660d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2670d0321e0SJeremy L Thompson // Take data
2680d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
2690d0321e0SJeremy L Thompson static int CeedQFunctionContextTakeData_Cuda(const CeedQFunctionContext ctx,
27043c928f4SJeremy L Thompson     const CeedMemType mem_type, void *data) {
2710d0321e0SJeremy L Thompson   int ierr;
2720d0321e0SJeremy L Thompson   Ceed ceed;
2730d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
2740d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
2750d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
2760d0321e0SJeremy L Thompson 
27743c928f4SJeremy L Thompson   // Sync data to requested mem_type
2780d0321e0SJeremy L Thompson   bool need_sync = false;
27943c928f4SJeremy L Thompson   ierr = CeedQFunctionContextNeedSync_Cuda(ctx, mem_type, &need_sync);
2800d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
2810d0321e0SJeremy L Thompson   if (need_sync) {
28243c928f4SJeremy L Thompson     ierr = CeedQFunctionContextSync_Cuda(ctx, mem_type); CeedChkBackend(ierr);
2830d0321e0SJeremy L Thompson   }
2840d0321e0SJeremy L Thompson 
2850d0321e0SJeremy L Thompson   // Update pointer
28643c928f4SJeremy L Thompson   switch (mem_type) {
2870d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
2880d0321e0SJeremy L Thompson     *(void **)data = impl->h_data_borrowed;
2890d0321e0SJeremy L Thompson     impl->h_data_borrowed = NULL;
2900d0321e0SJeremy L Thompson     impl->h_data = NULL;
2910d0321e0SJeremy L Thompson     break;
2920d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
2930d0321e0SJeremy L Thompson     *(void **)data = impl->d_data_borrowed;
2940d0321e0SJeremy L Thompson     impl->d_data_borrowed = NULL;
2950d0321e0SJeremy L Thompson     impl->d_data = NULL;
2960d0321e0SJeremy L Thompson     break;
2970d0321e0SJeremy L Thompson   }
2980d0321e0SJeremy L Thompson 
2990d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3000d0321e0SJeremy L Thompson }
3010d0321e0SJeremy L Thompson 
3020d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
30328bfd0b7SJeremy L Thompson // Core logic for GetData.
30428bfd0b7SJeremy L Thompson //   If a different memory type is most up to date, this will perform a copy
3050d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
30628bfd0b7SJeremy L Thompson static int CeedQFunctionContextGetDataCore_Cuda(const CeedQFunctionContext ctx,
30743c928f4SJeremy L Thompson     const CeedMemType mem_type, void *data) {
3080d0321e0SJeremy L Thompson   int ierr;
3090d0321e0SJeremy L Thompson   Ceed ceed;
3100d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
3110d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
3120d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
3130d0321e0SJeremy L Thompson 
31443c928f4SJeremy L Thompson   // Sync data to requested mem_type
3150d0321e0SJeremy L Thompson   bool need_sync = false;
31643c928f4SJeremy L Thompson   ierr = CeedQFunctionContextNeedSync_Cuda(ctx, mem_type, &need_sync);
3170d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
3180d0321e0SJeremy L Thompson   if (need_sync) {
31943c928f4SJeremy L Thompson     ierr = CeedQFunctionContextSync_Cuda(ctx, mem_type); CeedChkBackend(ierr);
3200d0321e0SJeremy L Thompson   }
3210d0321e0SJeremy L Thompson 
3220d0321e0SJeremy L Thompson   // Update pointer
32343c928f4SJeremy L Thompson   switch (mem_type) {
3240d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
3250d0321e0SJeremy L Thompson     *(void **)data = impl->h_data;
3260d0321e0SJeremy L Thompson     break;
3270d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
3280d0321e0SJeremy L Thompson     *(void **)data = impl->d_data;
3290d0321e0SJeremy L Thompson     break;
3300d0321e0SJeremy L Thompson   }
3310d0321e0SJeremy L Thompson 
33228bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
33328bfd0b7SJeremy L Thompson }
33428bfd0b7SJeremy L Thompson 
33528bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
33628bfd0b7SJeremy L Thompson // Get read-only access to the data
33728bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
33828bfd0b7SJeremy L Thompson static int CeedQFunctionContextGetDataRead_Cuda(const CeedQFunctionContext ctx,
33928bfd0b7SJeremy L Thompson     const CeedMemType mem_type, void *data) {
34028bfd0b7SJeremy L Thompson   return CeedQFunctionContextGetDataCore_Cuda(ctx, mem_type, data);
34128bfd0b7SJeremy L Thompson }
34228bfd0b7SJeremy L Thompson 
34328bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
34428bfd0b7SJeremy L Thompson // Get read/write access to the data
34528bfd0b7SJeremy L Thompson //------------------------------------------------------------------------------
34628bfd0b7SJeremy L Thompson static int CeedQFunctionContextGetData_Cuda(const CeedQFunctionContext ctx,
34728bfd0b7SJeremy L Thompson     const CeedMemType mem_type, void *data) {
34828bfd0b7SJeremy L Thompson   int ierr;
34928bfd0b7SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
35028bfd0b7SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
35128bfd0b7SJeremy L Thompson 
35228bfd0b7SJeremy L Thompson   ierr = CeedQFunctionContextGetDataCore_Cuda(ctx, mem_type, data);
35328bfd0b7SJeremy L Thompson   CeedChkBackend(ierr);
35428bfd0b7SJeremy L Thompson 
3550d0321e0SJeremy L Thompson   // Mark only pointer for requested memory as valid
3560d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetAllInvalid_Cuda(ctx); CeedChkBackend(ierr);
35743c928f4SJeremy L Thompson   switch (mem_type) {
3580d0321e0SJeremy L Thompson   case CEED_MEM_HOST:
3590d0321e0SJeremy L Thompson     impl->h_data = *(void **)data;
3600d0321e0SJeremy L Thompson     break;
3610d0321e0SJeremy L Thompson   case CEED_MEM_DEVICE:
3620d0321e0SJeremy L Thompson     impl->d_data = *(void **)data;
3630d0321e0SJeremy L Thompson     break;
3640d0321e0SJeremy L Thompson   }
3650d0321e0SJeremy L Thompson 
3660d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3670d0321e0SJeremy L Thompson }
3680d0321e0SJeremy L Thompson 
3690d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3700d0321e0SJeremy L Thompson // Destroy the user context
3710d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3720d0321e0SJeremy L Thompson static int CeedQFunctionContextDestroy_Cuda(const CeedQFunctionContext ctx) {
3730d0321e0SJeremy L Thompson   int ierr;
3740d0321e0SJeremy L Thompson   Ceed ceed;
3750d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
3760d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
3770d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
3780d0321e0SJeremy L Thompson 
3790d0321e0SJeremy L Thompson   ierr = cudaFree(impl->d_data_owned); CeedChk_Cu(ceed, ierr);
3800d0321e0SJeremy L Thompson   ierr = CeedFree(&impl->h_data_owned); CeedChkBackend(ierr);
3810d0321e0SJeremy L Thompson   ierr = CeedFree(&impl); CeedChkBackend(ierr);
3820d0321e0SJeremy L Thompson 
3830d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3840d0321e0SJeremy L Thompson }
3850d0321e0SJeremy L Thompson 
3860d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3870d0321e0SJeremy L Thompson // QFunctionContext Create
3880d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
3890d0321e0SJeremy L Thompson int CeedQFunctionContextCreate_Cuda(CeedQFunctionContext ctx) {
3900d0321e0SJeremy L Thompson   int ierr;
3910d0321e0SJeremy L Thompson   CeedQFunctionContext_Cuda *impl;
3920d0321e0SJeremy L Thompson   Ceed ceed;
3930d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
3940d0321e0SJeremy L Thompson 
3950d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData",
3960d0321e0SJeremy L Thompson                                 CeedQFunctionContextHasValidData_Cuda);
3970d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
3980d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx,
3990d0321e0SJeremy L Thompson                                 "HasBorrowedDataOfType",
4000d0321e0SJeremy L Thompson                                 CeedQFunctionContextHasBorrowedDataOfType_Cuda);
4010d0321e0SJeremy L Thompson   CeedChkBackend(ierr);
4020d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData",
4030d0321e0SJeremy L Thompson                                 CeedQFunctionContextSetData_Cuda); CeedChkBackend(ierr);
4040d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData",
4050d0321e0SJeremy L Thompson                                 CeedQFunctionContextTakeData_Cuda); CeedChkBackend(ierr);
4060d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData",
4070d0321e0SJeremy L Thompson                                 CeedQFunctionContextGetData_Cuda); CeedChkBackend(ierr);
40828bfd0b7SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead",
40928bfd0b7SJeremy L Thompson                                 CeedQFunctionContextGetDataRead_Cuda); CeedChkBackend(ierr);
4100d0321e0SJeremy L Thompson   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy",
4110d0321e0SJeremy L Thompson                                 CeedQFunctionContextDestroy_Cuda); CeedChkBackend(ierr);
4120d0321e0SJeremy L Thompson 
4130d0321e0SJeremy L Thompson   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
4140d0321e0SJeremy L Thompson   ierr = CeedQFunctionContextSetBackendData(ctx, impl); CeedChkBackend(ierr);
4150d0321e0SJeremy L Thompson 
4160d0321e0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4170d0321e0SJeremy L Thompson }
4180d0321e0SJeremy L Thompson //------------------------------------------------------------------------------
419