xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunctioncontext.c (revision 9bc663991d6482bcb1d60b1f116148f11db83fa1)
15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, 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.
3777ff853SJeremy L Thompson //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5777ff853SJeremy L Thompson //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7777ff853SJeremy L Thompson 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
1149aac155SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdint.h>
133d576824SJeremy L Thompson #include <stdio.h>
14cdf32b93SJeremy L Thompson #include <string.h>
15777ff853SJeremy L Thompson 
16777ff853SJeremy L Thompson /// @file
17777ff853SJeremy L Thompson /// Implementation of public CeedQFunctionContext interfaces
18777ff853SJeremy L Thompson 
19777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
20cdf32b93SJeremy L Thompson /// CeedQFunctionContext Library Internal Functions
21cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
22cdf32b93SJeremy L Thompson /// @addtogroup CeedQFunctionDeveloper
23cdf32b93SJeremy L Thompson /// @{
24cdf32b93SJeremy L Thompson 
25cdf32b93SJeremy L Thompson /**
26ca94c3ddSJeremy L Thompson   @brief Get index for `CeedQFunctionContext` field
27cdf32b93SJeremy L Thompson 
28ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
29ea61e9acSJeremy L Thompson   @param[in]  field_name  Name of field
30ca94c3ddSJeremy L Thompson   @param[out] field_index Index of field, or `-1` if field is not registered
31cdf32b93SJeremy L Thompson 
32cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
33cdf32b93SJeremy L Thompson 
34cdf32b93SJeremy L Thompson   @ref Developer
35cdf32b93SJeremy L Thompson **/
362b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, const char *field_name, CeedInt *field_index) {
37cdf32b93SJeremy L Thompson   *field_index = -1;
382b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
392b730f8bSJeremy L Thompson     if (!strcmp(ctx->field_labels[i]->name, field_name)) *field_index = i;
402b730f8bSJeremy L Thompson   }
41cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
42cdf32b93SJeremy L Thompson }
43cdf32b93SJeremy L Thompson 
44cdf32b93SJeremy L Thompson /**
45ca94c3ddSJeremy L Thompson   @brief Common function for registering `CeedQFunctionContext` fields
46cdf32b93SJeremy L Thompson 
47ca94c3ddSJeremy L Thompson   @param[in,out] ctx               `CeedQFunctionContext`
48ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
49ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
50ca94c3ddSJeremy L Thompson   @param[in]     field_description Description of field, or `NULL` for none
51ca94c3ddSJeremy L Thompson   @param[in]     field_type        @ref CeedContextFieldType
52ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
53cdf32b93SJeremy L Thompson 
54cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
55cdf32b93SJeremy L Thompson 
56cdf32b93SJeremy L Thompson   @ref Developer
57cdf32b93SJeremy L Thompson **/
582b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, const char *field_description,
595b6ec284SJeremy L Thompson                                         CeedContextFieldType field_type, size_t num_values) {
605b6ec284SJeremy L Thompson   size_t  field_size  = 0;
61cdf32b93SJeremy L Thompson   CeedInt field_index = -1;
621c66c397SJeremy L Thompson 
631c66c397SJeremy L Thompson   // Check for duplicate
642b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
65*9bc66399SJeremy L Thompson   CeedCheck(field_index == -1, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
66*9bc66399SJeremy L Thompson             "QFunctionContext field with name \"%s\" already registered", field_name);
67cdf32b93SJeremy L Thompson 
68cdf32b93SJeremy L Thompson   // Allocate space for field data
69cdf32b93SJeremy L Thompson   if (ctx->num_fields == 0) {
702b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(1, &ctx->field_labels));
71cdf32b93SJeremy L Thompson     ctx->max_fields = 1;
72cdf32b93SJeremy L Thompson   } else if (ctx->num_fields == ctx->max_fields) {
732b730f8bSJeremy L Thompson     CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels));
74cdf32b93SJeremy L Thompson     ctx->max_fields *= 2;
75cdf32b93SJeremy L Thompson   }
762b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields]));
77cdf32b93SJeremy L Thompson 
785b6ec284SJeremy L Thompson   // Compute field size
795b6ec284SJeremy L Thompson   switch (field_type) {
805b6ec284SJeremy L Thompson     case CEED_CONTEXT_FIELD_DOUBLE:
815b6ec284SJeremy L Thompson       field_size = sizeof(double);
825b6ec284SJeremy L Thompson       break;
835b6ec284SJeremy L Thompson     case CEED_CONTEXT_FIELD_INT32:
845b6ec284SJeremy L Thompson       field_size = sizeof(int);
855b6ec284SJeremy L Thompson       break;
865b6ec284SJeremy L Thompson     case CEED_CONTEXT_FIELD_BOOL:
875b6ec284SJeremy L Thompson       field_size = sizeof(bool);
885b6ec284SJeremy L Thompson       break;
895b6ec284SJeremy L Thompson   }
905b6ec284SJeremy L Thompson 
91cdf32b93SJeremy L Thompson   // Copy field data
922b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name));
932b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_description, (char **)&ctx->field_labels[ctx->num_fields]->description));
943668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->type       = field_type;
953668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->offset     = field_offset;
967bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->size       = field_size * num_values;
977bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->num_values = num_values;
98cdf32b93SJeremy L Thompson   ctx->num_fields++;
99cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
100cdf32b93SJeremy L Thompson }
101cdf32b93SJeremy L Thompson 
1023b190ab8SJeremy L Thompson /**
103ca94c3ddSJeremy L Thompson   @brief Destroy user data held by `CeedQFunctionContext`, using function set by @ref CeedQFunctionContextSetDataDestroy(), if applicable
1043b190ab8SJeremy L Thompson 
105ca94c3ddSJeremy L Thompson   @param[in,out] ctx `CeedQFunctionContext` to destroy user data
1063b190ab8SJeremy L Thompson 
1073b190ab8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1083b190ab8SJeremy L Thompson 
1093b190ab8SJeremy L Thompson   @ref Developer
1103b190ab8SJeremy L Thompson **/
1113b190ab8SJeremy L Thompson static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) {
1123b190ab8SJeremy L Thompson   if (ctx->DataDestroy) {
1132b730f8bSJeremy L Thompson     CeedCall(ctx->DataDestroy(ctx));
1143b190ab8SJeremy L Thompson   } else {
1153b190ab8SJeremy L Thompson     CeedMemType                         data_destroy_mem_type;
1161c66c397SJeremy L Thompson     CeedQFunctionContextDataDestroyUser data_destroy_function;
1173b190ab8SJeremy L Thompson 
1182b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function));
1193b190ab8SJeremy L Thompson     if (data_destroy_function) {
1203b190ab8SJeremy L Thompson       void *data;
1213b190ab8SJeremy L Thompson 
1222b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data));
1232b730f8bSJeremy L Thompson       CeedCall(data_destroy_function(data));
1242b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
1253b190ab8SJeremy L Thompson     }
1263b190ab8SJeremy L Thompson   }
1273b190ab8SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1283b190ab8SJeremy L Thompson }
1293b190ab8SJeremy L Thompson 
130cdf32b93SJeremy L Thompson /// @}
131cdf32b93SJeremy L Thompson 
132cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
133777ff853SJeremy L Thompson /// CeedQFunctionContext Backend API
134777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
135777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionBackend
136777ff853SJeremy L Thompson /// @{
137777ff853SJeremy L Thompson 
138777ff853SJeremy L Thompson /**
139ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedQFunctionContext`
140777ff853SJeremy L Thompson 
141ca94c3ddSJeremy L Thompson   @param[in]  ctx  `CeedQFunctionContext`
142ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store `Ceed`
143777ff853SJeremy L Thompson 
144777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
145777ff853SJeremy L Thompson 
146777ff853SJeremy L Thompson   @ref Backend
147777ff853SJeremy L Thompson **/
148777ff853SJeremy L Thompson int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) {
149*9bc66399SJeremy L Thompson   *ceed = NULL;
150*9bc66399SJeremy L Thompson   CeedCall(CeedReferenceCopy(CeedQFunctionContextReturnCeed(ctx), ceed));
151e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
152777ff853SJeremy L Thompson }
153777ff853SJeremy L Thompson 
154777ff853SJeremy L Thompson /**
1556e536b99SJeremy L Thompson   @brief Return the `Ceed` associated with a `CeedQFunctionContext`
1566e536b99SJeremy L Thompson 
1576e536b99SJeremy L Thompson   @param[in]  ctx  `CeedQFunctionContext`
1586e536b99SJeremy L Thompson 
1596e536b99SJeremy L Thompson   @return `Ceed` associated with `ctx`
1606e536b99SJeremy L Thompson 
1616e536b99SJeremy L Thompson   @ref Backend
1626e536b99SJeremy L Thompson **/
1636e536b99SJeremy L Thompson Ceed CeedQFunctionContextReturnCeed(CeedQFunctionContext ctx) { return ctx->ceed; }
1646e536b99SJeremy L Thompson 
1656e536b99SJeremy L Thompson /**
166ca94c3ddSJeremy L Thompson   @brief Check for valid data in a `CeedQFunctionContext`
1679c774eddSJeremy L Thompson 
168ca94c3ddSJeremy L Thompson   @param[in]  ctx            `CeedQFunctionContext` to check validity
1699c774eddSJeremy L Thompson   @param[out] has_valid_data Variable to store validity
1709c774eddSJeremy L Thompson 
1719c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1729c774eddSJeremy L Thompson 
1739c774eddSJeremy L Thompson   @ref Backend
1749c774eddSJeremy L Thompson **/
1752b730f8bSJeremy L Thompson int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, bool *has_valid_data) {
1766e536b99SJeremy L Thompson   CeedCheck(ctx->HasValidData, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
1776e536b99SJeremy L Thompson             "Backend does not support CeedQFunctionContextHasValidData");
1782b730f8bSJeremy L Thompson   CeedCall(ctx->HasValidData(ctx, has_valid_data));
1799c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1809c774eddSJeremy L Thompson }
1819c774eddSJeremy L Thompson 
1829c774eddSJeremy L Thompson /**
183ca94c3ddSJeremy L Thompson   @brief Check for borrowed data of a specific @ref CeedMemType in a `CeedQFunctionContext`
1849c774eddSJeremy L Thompson 
185ca94c3ddSJeremy L Thompson   @param[in]  ctx                       `CeedQFunctionContext` to check
186ea61e9acSJeremy L Thompson   @param[in]  mem_type                  Memory type to check
1879c774eddSJeremy L Thompson   @param[out] has_borrowed_data_of_type Variable to store result
1889c774eddSJeremy L Thompson 
1899c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1909c774eddSJeremy L Thompson 
1919c774eddSJeremy L Thompson   @ref Backend
1929c774eddSJeremy L Thompson **/
1932b730f8bSJeremy L Thompson int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) {
1946e536b99SJeremy L Thompson   CeedCheck(ctx->HasBorrowedDataOfType, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
1956e536b99SJeremy L Thompson             "Backend does not support CeedQFunctionContextHasBorrowedDataOfType");
1962b730f8bSJeremy L Thompson   CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type));
1979c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1989c774eddSJeremy L Thompson }
1999c774eddSJeremy L Thompson 
2009c774eddSJeremy L Thompson /**
201ca94c3ddSJeremy L Thompson   @brief Get the state of a `CeedQFunctionContext`
202777ff853SJeremy L Thompson 
203ca94c3ddSJeremy L Thompson   @param[in]  ctx   `CeedQFunctionContext` to retrieve state
204777ff853SJeremy L Thompson   @param[out] state Variable to store state
205777ff853SJeremy L Thompson 
206777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
207777ff853SJeremy L Thompson 
208777ff853SJeremy L Thompson   @ref Backend
209777ff853SJeremy L Thompson **/
210777ff853SJeremy L Thompson int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
211777ff853SJeremy L Thompson   *state = ctx->state;
212e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
213777ff853SJeremy L Thompson }
214777ff853SJeremy L Thompson 
215777ff853SJeremy L Thompson /**
216ca94c3ddSJeremy L Thompson   @brief Get backend data of a `CeedQFunctionContext`
217777ff853SJeremy L Thompson 
218ca94c3ddSJeremy L Thompson   @param[in]  ctx  `CeedQFunctionContext`
219777ff853SJeremy L Thompson   @param[out] data Variable to store data
220777ff853SJeremy L Thompson 
221777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
222777ff853SJeremy L Thompson 
223777ff853SJeremy L Thompson   @ref Backend
224777ff853SJeremy L Thompson **/
225777ff853SJeremy L Thompson int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
226777ff853SJeremy L Thompson   *(void **)data = ctx->data;
227e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
228777ff853SJeremy L Thompson }
229777ff853SJeremy L Thompson 
230777ff853SJeremy L Thompson /**
231ca94c3ddSJeremy L Thompson   @brief Set backend data of a `CeedQFunctionContext`
232777ff853SJeremy L Thompson 
233ca94c3ddSJeremy L Thompson   @param[in,out] ctx  `CeedQFunctionContext`
234ea61e9acSJeremy L Thompson   @param[in]     data Data to set
235777ff853SJeremy L Thompson 
236777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
237777ff853SJeremy L Thompson 
238777ff853SJeremy L Thompson   @ref Backend
239777ff853SJeremy L Thompson **/
240777ff853SJeremy L Thompson int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
241777ff853SJeremy L Thompson   ctx->data = data;
242e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
243777ff853SJeremy L Thompson }
244777ff853SJeremy L Thompson 
24534359f16Sjeremylt /**
246ca94c3ddSJeremy L Thompson   @brief Get label for a registered `CeedQFunctionContext` field, or `NULL` if no field has been registered with this `field_name`
247e6a0ab89SJeremy L Thompson 
248ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
249e6a0ab89SJeremy L Thompson   @param[in]  field_name  Name of field to retrieve label
250e6a0ab89SJeremy L Thompson   @param[out] field_label Variable to field label
251e6a0ab89SJeremy L Thompson 
252e6a0ab89SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
253e6a0ab89SJeremy L Thompson 
2543e1e85abSJeremy L Thompson   @ref Backend
255e6a0ab89SJeremy L Thompson **/
2562b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) {
257e6a0ab89SJeremy L Thompson   CeedInt field_index;
2581c66c397SJeremy L Thompson 
2592b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
260e6a0ab89SJeremy L Thompson 
261e6a0ab89SJeremy L Thompson   if (field_index != -1) {
262e6a0ab89SJeremy L Thompson     *field_label = ctx->field_labels[field_index];
263e6a0ab89SJeremy L Thompson   } else {
264e6a0ab89SJeremy L Thompson     *field_label = NULL;
265e6a0ab89SJeremy L Thompson   }
266e6a0ab89SJeremy L Thompson   return CEED_ERROR_SUCCESS;
267e6a0ab89SJeremy L Thompson }
268e6a0ab89SJeremy L Thompson 
269e6a0ab89SJeremy L Thompson /**
270ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field
271d8dd9a91SJeremy L Thompson 
272ca94c3ddSJeremy L Thompson   @param[in,out] ctx         `CeedQFunctionContext`
273ea61e9acSJeremy L Thompson   @param[in]     field_label Label of field to set
274ea61e9acSJeremy L Thompson   @param[in]     field_type  Type of field to set
2752788fa27SJeremy L Thompson   @param[in]     values      Value to set
276d8dd9a91SJeremy L Thompson 
277d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
278d8dd9a91SJeremy L Thompson 
2793e1e85abSJeremy L Thompson   @ref Backend
280d8dd9a91SJeremy L Thompson **/
2812788fa27SJeremy L Thompson int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) {
2821a34d7dcSJeremy L Thompson   bool  is_different;
2831c66c397SJeremy L Thompson   char *data;
2841c66c397SJeremy L Thompson 
2853668ca4bSJeremy L Thompson   // Check field type
2866e536b99SJeremy L Thompson   CeedCheck(field_label->type == field_type, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
2876574a04fSJeremy L Thompson             "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name,
2886574a04fSJeremy L Thompson             CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
289d8dd9a91SJeremy L Thompson 
2901a34d7dcSJeremy L Thompson   CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data));
2911a34d7dcSJeremy L Thompson   is_different = memcmp(&data[field_label->offset], values, field_label->size);
2921a34d7dcSJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreDataRead(ctx, &data));
2931a34d7dcSJeremy L Thompson   if (is_different) {
2942b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data));
2952788fa27SJeremy L Thompson     memcpy(&data[field_label->offset], values, field_label->size);
2962b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
2971a34d7dcSJeremy L Thompson   }
298d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
299d8dd9a91SJeremy L Thompson }
300d8dd9a91SJeremy L Thompson 
301d8dd9a91SJeremy L Thompson /**
302ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field data, read-only
3032788fa27SJeremy L Thompson 
304ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
3052788fa27SJeremy L Thompson   @param[in]  field_label Label of field to read
3062788fa27SJeremy L Thompson   @param[in]  field_type  Type of field to read
3072788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
3082788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3092788fa27SJeremy L Thompson 
3102788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3112788fa27SJeremy L Thompson 
3122788fa27SJeremy L Thompson   @ref Backend
3132788fa27SJeremy L Thompson **/
3142788fa27SJeremy L Thompson int CeedQFunctionContextGetGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type,
3152788fa27SJeremy L Thompson                                        size_t *num_values, void *values) {
3161c66c397SJeremy L Thompson   char *data;
3171c66c397SJeremy L Thompson 
3182788fa27SJeremy L Thompson   // Check field type
3196e536b99SJeremy L Thompson   CeedCheck(field_label->type == field_type, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
3206574a04fSJeremy L Thompson             "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name,
3216574a04fSJeremy L Thompson             CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
3222788fa27SJeremy L Thompson 
3232788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data));
3242788fa27SJeremy L Thompson   *(void **)values = &data[field_label->offset];
3252788fa27SJeremy L Thompson   switch (field_type) {
3262788fa27SJeremy L Thompson     case CEED_CONTEXT_FIELD_INT32:
3272788fa27SJeremy L Thompson       *num_values = field_label->size / sizeof(int);
3282788fa27SJeremy L Thompson       break;
3292788fa27SJeremy L Thompson     case CEED_CONTEXT_FIELD_DOUBLE:
3302788fa27SJeremy L Thompson       *num_values = field_label->size / sizeof(double);
3312788fa27SJeremy L Thompson       break;
3325b6ec284SJeremy L Thompson     case CEED_CONTEXT_FIELD_BOOL:
3335b6ec284SJeremy L Thompson       *num_values = field_label->size / sizeof(bool);
3345b6ec284SJeremy L Thompson       break;
3352788fa27SJeremy L Thompson   }
3362788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3372788fa27SJeremy L Thompson }
3382788fa27SJeremy L Thompson 
3392788fa27SJeremy L Thompson /**
340ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field data, read-only
3412788fa27SJeremy L Thompson 
342ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
3432788fa27SJeremy L Thompson   @param[in]  field_label Label of field to restore
3442788fa27SJeremy L Thompson   @param[in]  field_type  Type of field to restore
3452788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3462788fa27SJeremy L Thompson 
3472788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3482788fa27SJeremy L Thompson 
3492788fa27SJeremy L Thompson   @ref Backend
3502788fa27SJeremy L Thompson **/
3512788fa27SJeremy L Thompson int CeedQFunctionContextRestoreGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type,
3522788fa27SJeremy L Thompson                                            void *values) {
3532788fa27SJeremy L Thompson   // Check field type
3546e536b99SJeremy L Thompson   CeedCheck(field_label->type == field_type, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
3556574a04fSJeremy L Thompson             "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name,
3566574a04fSJeremy L Thompson             CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
3572788fa27SJeremy L Thompson 
3582788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreDataRead(ctx, values));
3592788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3602788fa27SJeremy L Thompson }
3612788fa27SJeremy L Thompson 
3622788fa27SJeremy L Thompson /**
363ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field holding double precision values
364bfacc300SJeremy L Thompson 
365ca94c3ddSJeremy L Thompson   @param[in,out] ctx         `CeedQFunctionContext`
3662788fa27SJeremy L Thompson   @param[in]     field_label Label for field to set
367ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
368bfacc300SJeremy L Thompson 
369bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
370bfacc300SJeremy L Thompson 
3713e1e85abSJeremy L Thompson   @ref Backend
372bfacc300SJeremy L Thompson **/
3732b730f8bSJeremy L Thompson int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) {
3746e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
3752b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
376bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
377bfacc300SJeremy L Thompson }
378bfacc300SJeremy L Thompson 
379bfacc300SJeremy L Thompson /**
380ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field holding double precision values, read-only
3812788fa27SJeremy L Thompson 
382ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
3832788fa27SJeremy L Thompson   @param[in]  field_label Label for field to get
3842788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
3852788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3862788fa27SJeremy L Thompson 
3872788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3882788fa27SJeremy L Thompson 
3892788fa27SJeremy L Thompson   @ref Backend
3902788fa27SJeremy L Thompson **/
3912788fa27SJeremy L Thompson int CeedQFunctionContextGetDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const double **values) {
3926e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
3932788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, num_values, values));
3942788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3952788fa27SJeremy L Thompson }
3962788fa27SJeremy L Thompson 
3972788fa27SJeremy L Thompson /**
398ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field holding double precision values, read-only
3992788fa27SJeremy L Thompson 
400ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
4012788fa27SJeremy L Thompson   @param[in]  field_label Label for field to restore
4022788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4032788fa27SJeremy L Thompson 
4042788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4052788fa27SJeremy L Thompson 
4062788fa27SJeremy L Thompson   @ref Backend
4072788fa27SJeremy L Thompson **/
4082788fa27SJeremy L Thompson int CeedQFunctionContextRestoreDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const double **values) {
4096e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4102788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
4112788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4122788fa27SJeremy L Thompson }
4132788fa27SJeremy L Thompson 
4142788fa27SJeremy L Thompson /**
415ca94c3ddSJeremy L Thompson   @brief Set CeedQFunctionContext field holding `int32` values
416bfacc300SJeremy L Thompson 
417ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
4182788fa27SJeremy L Thompson   @param[in]     field_label Label for field to set
419ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
420bfacc300SJeremy L Thompson 
421bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
422bfacc300SJeremy L Thompson 
4233e1e85abSJeremy L Thompson   @ref Backend
424bfacc300SJeremy L Thompson **/
42523dbfd29SJeremy L Thompson int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int32_t *values) {
4266e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4272b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
428bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
429bfacc300SJeremy L Thompson }
430bfacc300SJeremy L Thompson 
431bfacc300SJeremy L Thompson /**
432ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field holding `int32` values, read-only
4332788fa27SJeremy L Thompson 
434ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
4352788fa27SJeremy L Thompson   @param[in]  field_label Label for field to get
4362788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
4372788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4382788fa27SJeremy L Thompson 
4392788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4402788fa27SJeremy L Thompson 
4412788fa27SJeremy L Thompson   @ref Backend
4422788fa27SJeremy L Thompson **/
44323dbfd29SJeremy L Thompson int CeedQFunctionContextGetInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const int32_t **values) {
4446e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4452788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, num_values, values));
4462788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4472788fa27SJeremy L Thompson }
4482788fa27SJeremy L Thompson 
4492788fa27SJeremy L Thompson /**
450ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field holding `int32` values, read-only
4512788fa27SJeremy L Thompson 
452ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
4532788fa27SJeremy L Thompson   @param[in]  field_label Label for field to restore
4542788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4552788fa27SJeremy L Thompson 
4562788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4572788fa27SJeremy L Thompson 
4582788fa27SJeremy L Thompson   @ref Backend
4592788fa27SJeremy L Thompson **/
46023dbfd29SJeremy L Thompson int CeedQFunctionContextRestoreInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const int32_t **values) {
4616e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4622788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
4632788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4642788fa27SJeremy L Thompson }
4652788fa27SJeremy L Thompson 
4662788fa27SJeremy L Thompson /**
467ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field holding boolean values
4685b6ec284SJeremy L Thompson 
469ca94c3ddSJeremy L Thompson   @param[in,out] ctx         `CeedQFunctionContext`
4705b6ec284SJeremy L Thompson   @param[in]     field_label Label for field to set
4715b6ec284SJeremy L Thompson   @param[in]     values      Values to set
4725b6ec284SJeremy L Thompson 
4735b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4745b6ec284SJeremy L Thompson 
4755b6ec284SJeremy L Thompson   @ref Backend
4765b6ec284SJeremy L Thompson **/
4775b6ec284SJeremy L Thompson int CeedQFunctionContextSetBoolean(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, bool *values) {
4786e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4795b6ec284SJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_BOOL, values));
4805b6ec284SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4815b6ec284SJeremy L Thompson }
4825b6ec284SJeremy L Thompson 
4835b6ec284SJeremy L Thompson /**
484ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field holding boolean values, read-only
4855b6ec284SJeremy L Thompson 
486ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
4875b6ec284SJeremy L Thompson   @param[in]  field_label Label for field to get
4885b6ec284SJeremy L Thompson   @param[out] num_values  Number of values in the field label
4895b6ec284SJeremy L Thompson   @param[out] values      Pointer to context values
4905b6ec284SJeremy L Thompson 
4915b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4925b6ec284SJeremy L Thompson 
4935b6ec284SJeremy L Thompson   @ref Backend
4945b6ec284SJeremy L Thompson **/
4955b6ec284SJeremy L Thompson int CeedQFunctionContextGetBooleanRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const bool **values) {
4966e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4975b6ec284SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_BOOL, num_values, values));
4985b6ec284SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4995b6ec284SJeremy L Thompson }
5005b6ec284SJeremy L Thompson 
5015b6ec284SJeremy L Thompson /**
502ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field holding boolean values, read-only
5035b6ec284SJeremy L Thompson 
504ca94c3ddSJeremy L Thompson   @param[in]  ctx         `CeedQFunctionContext`
5055b6ec284SJeremy L Thompson   @param[in]  field_label Label for field to restore
5065b6ec284SJeremy L Thompson   @param[out] values      Pointer to context values
5075b6ec284SJeremy L Thompson 
5085b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5095b6ec284SJeremy L Thompson 
5105b6ec284SJeremy L Thompson   @ref Backend
5115b6ec284SJeremy L Thompson **/
5125b6ec284SJeremy L Thompson int CeedQFunctionContextRestoreBooleanRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const bool **values) {
5136e536b99SJeremy L Thompson   CeedCheck(field_label, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Invalid field label");
5145b6ec284SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_BOOL, values));
5155b6ec284SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5165b6ec284SJeremy L Thompson }
5175b6ec284SJeremy L Thompson 
5185b6ec284SJeremy L Thompson /**
519ca94c3ddSJeremy L Thompson   @brief Get additional destroy routine for `CeedQFunctionContext` user data
5202e64a2b9SJeremy L Thompson 
521ca94c3ddSJeremy L Thompson   @param[in] ctx         `CeedQFunctionContext` to get user destroy function
5222e64a2b9SJeremy L Thompson   @param[out] f_mem_type Memory type to use when passing data into `f`
5232e64a2b9SJeremy L Thompson   @param[out] f          Additional routine to use to destroy user data
5242e64a2b9SJeremy L Thompson 
5252e64a2b9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5262e64a2b9SJeremy L Thompson 
5272e64a2b9SJeremy L Thompson   @ref Backend
5282e64a2b9SJeremy L Thompson **/
5292b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) {
5302e64a2b9SJeremy L Thompson   if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type;
5312e64a2b9SJeremy L Thompson   if (f) *f = ctx->data_destroy_function;
5322e64a2b9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5332e64a2b9SJeremy L Thompson }
5342e64a2b9SJeremy L Thompson 
5352e64a2b9SJeremy L Thompson /**
536ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedQFunctionContext`
53734359f16Sjeremylt 
538ca94c3ddSJeremy L Thompson   @param[in,out] ctx `CeedQFunctionContext` to increment the reference counter
53934359f16Sjeremylt 
54034359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
54134359f16Sjeremylt 
54234359f16Sjeremylt   @ref Backend
54334359f16Sjeremylt **/
5449560d06aSjeremylt int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
54534359f16Sjeremylt   ctx->ref_count++;
54634359f16Sjeremylt   return CEED_ERROR_SUCCESS;
54734359f16Sjeremylt }
54834359f16Sjeremylt 
549777ff853SJeremy L Thompson /// @}
550777ff853SJeremy L Thompson 
551777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
552777ff853SJeremy L Thompson /// CeedQFunctionContext Public API
553777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
554777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionUser
555777ff853SJeremy L Thompson /// @{
556777ff853SJeremy L Thompson 
557777ff853SJeremy L Thompson /**
558ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunctionContext` for storing `CeedQFunctionContext` user context data
559777ff853SJeremy L Thompson 
560ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedQFunctionContext`
561ca94c3ddSJeremy L Thompson   @param[out] ctx  Address of the variable where the newly created `CeedQFunctionContext` will be stored
562777ff853SJeremy L Thompson 
563777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
564777ff853SJeremy L Thompson 
565777ff853SJeremy L Thompson   @ref User
566777ff853SJeremy L Thompson **/
567777ff853SJeremy L Thompson int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
568777ff853SJeremy L Thompson   if (!ceed->QFunctionContextCreate) {
569777ff853SJeremy L Thompson     Ceed delegate;
5706574a04fSJeremy L Thompson 
5712b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context"));
5721ef3a2a9SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedQFunctionContextCreate");
5732b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextCreate(delegate, ctx));
574*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
575e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
576777ff853SJeremy L Thompson   }
577777ff853SJeremy L Thompson 
5782b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, ctx));
579db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*ctx)->ceed));
580d1d35e2fSjeremylt   (*ctx)->ref_count = 1;
5812b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionContextCreate(*ctx));
582e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
583777ff853SJeremy L Thompson }
584777ff853SJeremy L Thompson 
585777ff853SJeremy L Thompson /**
586ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedQFunctionContext`.
5874385fb7fSSebastian Grimberg 
588ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedQFunctionContextDestroy().
589512bb800SJeremy L Thompson 
590ca94c3ddSJeremy L Thompson   Note: If the value of `*ctx_copy` passed to this function is non-`NULL`, then it is assumed that `*ctx_copy` is a pointer to a `CeedQFunctionContext`.
591ca94c3ddSJeremy L Thompson         This `CeedQFunctionContext` will be destroyed if `*ctx_copy` is the only reference to this `CeedQFunctionContext`.
5929560d06aSjeremylt 
593ea61e9acSJeremy L Thompson   @param[in]     ctx      CeedQFunctionContext to copy reference to
594ea61e9acSJeremy L Thompson   @param[in,out] ctx_copy Variable to store copied reference
5959560d06aSjeremylt 
5969560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
5979560d06aSjeremylt 
5989560d06aSjeremylt   @ref User
5999560d06aSjeremylt **/
6002b730f8bSJeremy L Thompson int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) {
6012b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextReference(ctx));
6022b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(ctx_copy));
6039560d06aSjeremylt   *ctx_copy = ctx;
6049560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6059560d06aSjeremylt }
6069560d06aSjeremylt 
6079560d06aSjeremylt /**
608ca94c3ddSJeremy L Thompson   @brief Set the data used by a `CeedQFunctionContext`, freeing any previously allocated data if applicable.
6094385fb7fSSebastian Grimberg 
610ca94c3ddSJeremy L Thompson   The backend may copy values to a different @ref CeedMemType, such as during @ref CeedQFunctionApply().
611777ff853SJeremy L Thompson   See also @ref CeedQFunctionContextTakeData().
612777ff853SJeremy L Thompson 
613ca94c3ddSJeremy L Thompson   @param[in,out] ctx       `CeedQFunctionContext`
614ea61e9acSJeremy L Thompson   @param[in]     mem_type  Memory type of the data being passed
615ea61e9acSJeremy L Thompson   @param[in]     copy_mode Copy mode for the data
616ea61e9acSJeremy L Thompson   @param[in]     size      Size of data, in bytes
617ea61e9acSJeremy L Thompson   @param[in]     data      Data to be used
618777ff853SJeremy L Thompson 
619777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
620777ff853SJeremy L Thompson 
621777ff853SJeremy L Thompson   @ref User
622777ff853SJeremy L Thompson **/
6232b730f8bSJeremy L Thompson int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) {
624*9bc66399SJeremy L Thompson   CeedCheck(ctx->SetData, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionContextSetData");
625*9bc66399SJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, CeedQFunctionContextReturnCeed(ctx), 1,
626*9bc66399SJeremy L Thompson             "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
627777ff853SJeremy L Thompson 
6282b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(ctx));
629d1d35e2fSjeremylt   ctx->ctx_size = size;
6302b730f8bSJeremy L Thompson   CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data));
631777ff853SJeremy L Thompson   ctx->state += 2;
632e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
633777ff853SJeremy L Thompson }
634777ff853SJeremy L Thompson 
635777ff853SJeremy L Thompson /**
636ca94c3ddSJeremy L Thompson   @brief Take ownership of the data in a `CeedQFunctionContext` via the specified memory type.
6374385fb7fSSebastian Grimberg 
638891038deSjeremylt   The caller is responsible for managing and freeing the memory.
639891038deSjeremylt 
640ca94c3ddSJeremy L Thompson   @param[in]  ctx      `CeedQFunctionContext` to access
641ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
642ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
643891038deSjeremylt   @param[out] data     Data on memory type mem_type
644891038deSjeremylt 
645891038deSjeremylt   @return An error code: 0 - success, otherwise - failure
646891038deSjeremylt 
647891038deSjeremylt   @ref User
648891038deSjeremylt **/
6492b730f8bSJeremy L Thompson int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
6501c66c397SJeremy L Thompson   void *temp_data      = NULL;
6511c66c397SJeremy L Thompson   bool  has_valid_data = true, has_borrowed_data_of_type = true;
6521c66c397SJeremy L Thompson 
6532b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
654*9bc66399SJeremy L Thompson   CeedCheck(has_valid_data, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data");
6559c774eddSJeremy L Thompson 
656*9bc66399SJeremy L Thompson   CeedCheck(ctx->TakeData, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionContextTakeData");
657*9bc66399SJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, CeedQFunctionContextReturnCeed(ctx), 1,
658*9bc66399SJeremy L Thompson             "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
659891038deSjeremylt 
6602b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type));
661*9bc66399SJeremy L Thompson   CeedCheck(has_borrowed_data_of_type, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_BACKEND,
6626574a04fSJeremy L Thompson             "CeedQFunctionContext has no borrowed %s data, must set data with CeedQFunctionContextSetData", CeedMemTypes[mem_type]);
6639c774eddSJeremy L Thompson 
6642b730f8bSJeremy L Thompson   CeedCall(ctx->TakeData(ctx, mem_type, &temp_data));
665891038deSjeremylt   if (data) (*(void **)data) = temp_data;
666891038deSjeremylt   return CEED_ERROR_SUCCESS;
667891038deSjeremylt }
668891038deSjeremylt 
669891038deSjeremylt /**
670ca94c3ddSJeremy L Thompson   @brief Get read/write access to a `CeedQFunctionContext` via the specified memory type.
6714385fb7fSSebastian Grimberg 
672777ff853SJeremy L Thompson   Restore access with @ref CeedQFunctionContextRestoreData().
673777ff853SJeremy L Thompson 
674ca94c3ddSJeremy L Thompson   @param[in]  ctx      `CeedQFunctionContext` to access
675ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
676ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
677d1d35e2fSjeremylt   @param[out] data     Data on memory type mem_type
678777ff853SJeremy L Thompson 
679ca94c3ddSJeremy L Thompson   @note The @ref CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory space.
680ca94c3ddSJeremy L Thompson         Pairing get/restore allows the `CeedQFunctionContext` to track access.
681777ff853SJeremy L Thompson 
682777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
683777ff853SJeremy L Thompson 
684777ff853SJeremy L Thompson   @ref User
685777ff853SJeremy L Thompson **/
6862b730f8bSJeremy L Thompson int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
6871c66c397SJeremy L Thompson   bool has_valid_data = true;
6881c66c397SJeremy L Thompson 
689*9bc66399SJeremy L Thompson   CeedCheck(ctx->GetData, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionContextGetData");
690*9bc66399SJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, CeedQFunctionContextReturnCeed(ctx), 1,
691*9bc66399SJeremy L Thompson             "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
692*9bc66399SJeremy L Thompson   CeedCheck(ctx->num_readers == 0, CeedQFunctionContextReturnCeed(ctx), 1,
693*9bc66399SJeremy L Thompson             "Cannot grant CeedQFunctionContext data access, a process has read access");
69428bfd0b7SJeremy L Thompson 
6952b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
696*9bc66399SJeremy L Thompson   CeedCheck(has_valid_data, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
6979c774eddSJeremy L Thompson 
6982b730f8bSJeremy L Thompson   CeedCall(ctx->GetData(ctx, mem_type, data));
69928bfd0b7SJeremy L Thompson   ctx->state++;
70028bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
70128bfd0b7SJeremy L Thompson }
70228bfd0b7SJeremy L Thompson 
70328bfd0b7SJeremy L Thompson /**
704ca94c3ddSJeremy L Thompson   @brief Get read only access to a `CeedQFunctionContext` via the specified memory type.
7054385fb7fSSebastian Grimberg 
70628bfd0b7SJeremy L Thompson   Restore access with @ref CeedQFunctionContextRestoreData().
70728bfd0b7SJeremy L Thompson 
708ca94c3ddSJeremy L Thompson   @param[in]  ctx      `CeedQFunctionContext` to access
709ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
710ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
71128bfd0b7SJeremy L Thompson   @param[out] data     Data on memory type mem_type
71228bfd0b7SJeremy L Thompson 
713ca94c3ddSJeremy L Thompson   @note The @ref CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired memory space.
714ca94c3ddSJeremy L Thompson         Pairing get/restore allows the `CeedQFunctionContext` to track access.
71528bfd0b7SJeremy L Thompson 
71628bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
71728bfd0b7SJeremy L Thompson 
71828bfd0b7SJeremy L Thompson   @ref User
71928bfd0b7SJeremy L Thompson **/
7202b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
7211c66c397SJeremy L Thompson   bool has_valid_data = true;
7221c66c397SJeremy L Thompson 
723*9bc66399SJeremy L Thompson   CeedCheck(ctx->GetDataRead, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_UNSUPPORTED,
724*9bc66399SJeremy L Thompson             "Backend does not support CeedQFunctionContextGetDataRead");
725*9bc66399SJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, CeedQFunctionContextReturnCeed(ctx), 1,
726*9bc66399SJeremy L Thompson             "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
72728bfd0b7SJeremy L Thompson 
7282b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
729*9bc66399SJeremy L Thompson   CeedCheck(has_valid_data, CeedQFunctionContextReturnCeed(ctx), CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
73028bfd0b7SJeremy L Thompson 
7312b730f8bSJeremy L Thompson   CeedCall(ctx->GetDataRead(ctx, mem_type, data));
73228bfd0b7SJeremy L Thompson   ctx->num_readers++;
733e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
734777ff853SJeremy L Thompson }
735777ff853SJeremy L Thompson 
736777ff853SJeremy L Thompson /**
737777ff853SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
738777ff853SJeremy L Thompson 
739ca94c3ddSJeremy L Thompson   @param[in]     ctx  `CeedQFunctionContext` to restore
740ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
741777ff853SJeremy L Thompson 
742777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
743777ff853SJeremy L Thompson 
744777ff853SJeremy L Thompson   @ref User
745777ff853SJeremy L Thompson **/
746777ff853SJeremy L Thompson int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
7476e536b99SJeremy L Thompson   CeedCheck(ctx->state % 2 == 1, CeedQFunctionContextReturnCeed(ctx), 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
748777ff853SJeremy L Thompson 
7496574a04fSJeremy L Thompson   if (ctx->RestoreData) CeedCall(ctx->RestoreData(ctx));
750777ff853SJeremy L Thompson   *(void **)data = NULL;
75128bfd0b7SJeremy L Thompson   ctx->state++;
75228bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
75328bfd0b7SJeremy L Thompson }
75428bfd0b7SJeremy L Thompson 
75528bfd0b7SJeremy L Thompson /**
75628bfd0b7SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead()
75728bfd0b7SJeremy L Thompson 
758ca94c3ddSJeremy L Thompson   @param[in]     ctx  `CeedQFunctionContext` to restore
759ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
76028bfd0b7SJeremy L Thompson 
76128bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
76228bfd0b7SJeremy L Thompson 
76328bfd0b7SJeremy L Thompson   @ref User
76428bfd0b7SJeremy L Thompson **/
76528bfd0b7SJeremy L Thompson int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) {
7666e536b99SJeremy L Thompson   CeedCheck(ctx->num_readers > 0, CeedQFunctionContextReturnCeed(ctx), 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
76728bfd0b7SJeremy L Thompson 
76875a19770SJeremy L Thompson   ctx->num_readers--;
7696574a04fSJeremy L Thompson   if (ctx->num_readers == 0 && ctx->RestoreDataRead) CeedCall(ctx->RestoreDataRead(ctx));
77028bfd0b7SJeremy L Thompson   *(void **)data = NULL;
771e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
772777ff853SJeremy L Thompson }
773777ff853SJeremy L Thompson 
774777ff853SJeremy L Thompson /**
775ca94c3ddSJeremy L Thompson   @brief Register a `CeedQFunctionContext` field holding double precision values
776cdf32b93SJeremy L Thompson 
777ca94c3ddSJeremy L Thompson   @param[in,out] ctx               `CeedQFunctionContext`
778ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
779ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
780ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
781ca94c3ddSJeremy L Thompson   @param[in]     field_description Description of field, or `NULL` for none
782cdf32b93SJeremy L Thompson 
783cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
784cdf32b93SJeremy L Thompson 
785cdf32b93SJeremy L Thompson   @ref User
786cdf32b93SJeremy L Thompson **/
7872b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
788cdf32b93SJeremy L Thompson                                        const char *field_description) {
7895b6ec284SJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, num_values);
790cdf32b93SJeremy L Thompson }
791cdf32b93SJeremy L Thompson 
792cdf32b93SJeremy L Thompson /**
793ca94c3ddSJeremy L Thompson   @brief Register a `CeedQFunctionContext` field holding `int32` values
794cdf32b93SJeremy L Thompson 
795ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
796ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
797ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
798ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
799ca94c3ddSJeremy L Thompson   @param[in]     field_description Description of field, or `NULL` for none
800cdf32b93SJeremy L Thompson 
801cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
802cdf32b93SJeremy L Thompson 
803cdf32b93SJeremy L Thompson   @ref User
804cdf32b93SJeremy L Thompson **/
8052b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
806cdf32b93SJeremy L Thompson                                       const char *field_description) {
8075b6ec284SJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, num_values);
8085b6ec284SJeremy L Thompson }
8095b6ec284SJeremy L Thompson 
8105b6ec284SJeremy L Thompson /**
811ca94c3ddSJeremy L Thompson   @brief Register a `CeedQFunctionContext` field holding boolean values
8125b6ec284SJeremy L Thompson 
813ca94c3ddSJeremy L Thompson   @param[in,out] ctx               `CeedQFunctionContext`
8145b6ec284SJeremy L Thompson   @param[in]     field_name        Name of field to register
8155b6ec284SJeremy L Thompson   @param[in]     field_offset      Offset of field to register
8165b6ec284SJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
817ca94c3ddSJeremy L Thompson   @param[in]     field_description Description of field, or `NULL` for none
8185b6ec284SJeremy L Thompson 
8195b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8205b6ec284SJeremy L Thompson 
8215b6ec284SJeremy L Thompson   @ref User
8225b6ec284SJeremy L Thompson **/
8235b6ec284SJeremy L Thompson int CeedQFunctionContextRegisterBoolean(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
8245b6ec284SJeremy L Thompson                                         const char *field_description) {
8255b6ec284SJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_BOOL, num_values);
826cdf32b93SJeremy L Thompson }
827cdf32b93SJeremy L Thompson 
828cdf32b93SJeremy L Thompson /**
829ca94c3ddSJeremy L Thompson   @brief Get labels for all registered `CeedQFunctionContext` fields
830cdf32b93SJeremy L Thompson 
831ca94c3ddSJeremy L Thompson   @param[in]  ctx          `CeedQFunctionContext`
8323668ca4bSJeremy L Thompson   @param[out] field_labels Variable to hold array of field labels
833cdf32b93SJeremy L Thompson   @param[out] num_fields   Length of field descriptions array
834cdf32b93SJeremy L Thompson 
835cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
836cdf32b93SJeremy L Thompson 
837cdf32b93SJeremy L Thompson   @ref User
838cdf32b93SJeremy L Thompson **/
8392b730f8bSJeremy L Thompson int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
8403668ca4bSJeremy L Thompson   *field_labels = ctx->field_labels;
841cdf32b93SJeremy L Thompson   *num_fields   = ctx->num_fields;
842cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
843cdf32b93SJeremy L Thompson }
844cdf32b93SJeremy L Thompson 
845cdf32b93SJeremy L Thompson /**
846ca94c3ddSJeremy L Thompson   @brief Get the descriptive information about a `CeedContextFieldLabel`
8470f86cbe7SJeremy L Thompson 
848ca94c3ddSJeremy L Thompson   @param[in]  label             @ref CeedContextFieldLabel
8490f86cbe7SJeremy L Thompson   @param[out] field_name        Name of labeled field
8501ff07f3dSJeremy L Thompson   @param[out] field_offset      Offset of field registered
8517bfe0f0eSJeremy L Thompson   @param[out] num_values        Number of values registered
8521ff07f3dSJeremy L Thompson   @param[out] field_description Description of field, or NULL for none
853ca94c3ddSJeremy L Thompson   @param[out] field_type        @ref CeedContextFieldType
8540f86cbe7SJeremy L Thompson 
8550f86cbe7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8560f86cbe7SJeremy L Thompson 
8570f86cbe7SJeremy L Thompson   @ref User
8580f86cbe7SJeremy L Thompson **/
8591ff07f3dSJeremy L Thompson int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, size_t *field_offset, size_t *num_values,
8601ff07f3dSJeremy L Thompson                                         const char **field_description, CeedContextFieldType *field_type) {
8610f86cbe7SJeremy L Thompson   if (field_name) *field_name = label->name;
8621ff07f3dSJeremy L Thompson   if (field_offset) *field_offset = label->offset;
8637bfe0f0eSJeremy L Thompson   if (num_values) *num_values = label->num_values;
8641ff07f3dSJeremy L Thompson   if (field_description) *field_description = label->description;
8650f86cbe7SJeremy L Thompson   if (field_type) *field_type = label->type;
8660f86cbe7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8670f86cbe7SJeremy L Thompson }
8680f86cbe7SJeremy L Thompson 
8690f86cbe7SJeremy L Thompson /**
87080a9ef05SNatalie Beams   @brief Get data size for a Context
87180a9ef05SNatalie Beams 
872ca94c3ddSJeremy L Thompson   @param[in]  ctx      `CeedQFunctionContext`
87380a9ef05SNatalie Beams   @param[out] ctx_size Variable to store size of context data values
87480a9ef05SNatalie Beams 
87580a9ef05SNatalie Beams   @return An error code: 0 - success, otherwise - failure
87680a9ef05SNatalie Beams 
87780a9ef05SNatalie Beams   @ref User
87880a9ef05SNatalie Beams **/
8792b730f8bSJeremy L Thompson int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) {
88080a9ef05SNatalie Beams   *ctx_size = ctx->ctx_size;
88180a9ef05SNatalie Beams   return CEED_ERROR_SUCCESS;
88280a9ef05SNatalie Beams }
88380a9ef05SNatalie Beams 
88480a9ef05SNatalie Beams /**
885ca94c3ddSJeremy L Thompson   @brief View a `CeedQFunctionContext`
886777ff853SJeremy L Thompson 
887ca94c3ddSJeremy L Thompson   @param[in] ctx    `CeedQFunctionContext` to view
888777ff853SJeremy L Thompson   @param[in] stream Filestream to write to
889777ff853SJeremy L Thompson 
890777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
891777ff853SJeremy L Thompson 
892777ff853SJeremy L Thompson   @ref User
893777ff853SJeremy L Thompson **/
894777ff853SJeremy L Thompson int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
895777ff853SJeremy L Thompson   fprintf(stream, "CeedQFunctionContext\n");
896249f8407SJeremy L Thompson   fprintf(stream, "  Context Data Size: %zu\n", ctx->ctx_size);
8973668ca4bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
8982b730f8bSJeremy L Thompson     fprintf(stream, "  Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name);
8993668ca4bSJeremy L Thompson   }
900e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
901777ff853SJeremy L Thompson }
902777ff853SJeremy L Thompson 
903777ff853SJeremy L Thompson /**
904ca94c3ddSJeremy L Thompson   @brief Set additional destroy routine for `CeedQFunctionContext` user data
9052790b72bSJeremy L Thompson 
906ca94c3ddSJeremy L Thompson   @param[in,out] ctx        `CeedQFunctionContext` to set user destroy function
9072e64a2b9SJeremy L Thompson   @param[in]     f_mem_type Memory type to use when passing data into `f`
9082e64a2b9SJeremy L Thompson   @param[in]     f          Additional routine to use to destroy user data
9092790b72bSJeremy L Thompson 
9102790b72bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9112790b72bSJeremy L Thompson 
9122790b72bSJeremy L Thompson   @ref User
9132790b72bSJeremy L Thompson **/
9142b730f8bSJeremy L Thompson int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) {
9156e536b99SJeremy L Thompson   CeedCheck(f, CeedQFunctionContextReturnCeed(ctx), 1, "Must provide valid callback function for destroying user data");
9162790b72bSJeremy L Thompson   ctx->data_destroy_mem_type = f_mem_type;
9172790b72bSJeremy L Thompson   ctx->data_destroy_function = f;
9182790b72bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
9192790b72bSJeremy L Thompson }
9202790b72bSJeremy L Thompson 
9212790b72bSJeremy L Thompson /**
922ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedQFunctionContext`
923777ff853SJeremy L Thompson 
924ca94c3ddSJeremy L Thompson   @param[in,out] ctx `CeedQFunctionContext` to destroy
925777ff853SJeremy L Thompson 
926777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
927777ff853SJeremy L Thompson 
928777ff853SJeremy L Thompson   @ref User
929777ff853SJeremy L Thompson **/
930777ff853SJeremy L Thompson int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
931ad6481ceSJeremy L Thompson   if (!*ctx || --(*ctx)->ref_count > 0) {
932ad6481ceSJeremy L Thompson     *ctx = NULL;
933ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
934ad6481ceSJeremy L Thompson   }
9356574a04fSJeremy L Thompson   CeedCheck(((*ctx)->state % 2) == 0, (*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use");
936777ff853SJeremy L Thompson 
9372b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(*ctx));
9382b730f8bSJeremy L Thompson   if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx));
939cdf32b93SJeremy L Thompson   for (CeedInt i = 0; i < (*ctx)->num_fields; i++) {
9402b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->name));
9412b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->description));
9422b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]));
943cdf32b93SJeremy L Thompson   }
9442b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ctx)->field_labels));
9452b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*ctx)->ceed));
9462b730f8bSJeremy L Thompson   CeedCall(CeedFree(ctx));
947e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
948777ff853SJeremy L Thompson }
949777ff853SJeremy L Thompson 
950777ff853SJeremy L Thompson /// @}
951