xref: /libCEED/interface/ceed-qfunctioncontext.c (revision 9fd66db6d1a7a1c9032418479851d404799ab3ba)
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.
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 /**
26cdf32b93SJeremy L Thompson   @brief Get index for QFunctionContext field
27cdf32b93SJeremy L Thompson 
28ea61e9acSJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
29ea61e9acSJeremy L Thompson   @param[in]  field_name  Name of field
30ea61e9acSJeremy 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 /**
45cdf32b93SJeremy L Thompson   @brief Common function for registering QFunctionContext fields
46cdf32b93SJeremy L Thompson 
47ea61e9acSJeremy 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
50ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
51ea61e9acSJeremy L Thompson   @param[in]     field_type        Field data type, such as double or int32
52ea61e9acSJeremy L Thompson   @param[in]     field_size        Size of field, in bytes
53ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
54cdf32b93SJeremy L Thompson 
55cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
56cdf32b93SJeremy L Thompson 
57cdf32b93SJeremy L Thompson   @ref Developer
58cdf32b93SJeremy L Thompson **/
592b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, const char *field_description,
602b730f8bSJeremy L Thompson                                         CeedContextFieldType field_type, size_t field_size, size_t num_values) {
61cdf32b93SJeremy L Thompson   // Check for duplicate
62cdf32b93SJeremy L Thompson   CeedInt field_index = -1;
632b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
642b730f8bSJeremy L Thompson   if (field_index != -1) {
65cdf32b93SJeremy L Thompson     // LCOV_EXCL_START
662b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" already registered", field_name);
67cdf32b93SJeremy L Thompson     // LCOV_EXCL_STOP
682b730f8bSJeremy L Thompson   }
69cdf32b93SJeremy L Thompson 
70cdf32b93SJeremy L Thompson   // Allocate space for field data
71cdf32b93SJeremy L Thompson   if (ctx->num_fields == 0) {
722b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(1, &ctx->field_labels));
73cdf32b93SJeremy L Thompson     ctx->max_fields = 1;
74cdf32b93SJeremy L Thompson   } else if (ctx->num_fields == ctx->max_fields) {
752b730f8bSJeremy L Thompson     CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels));
76cdf32b93SJeremy L Thompson     ctx->max_fields *= 2;
77cdf32b93SJeremy L Thompson   }
782b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields]));
79cdf32b93SJeremy L Thompson 
80cdf32b93SJeremy L Thompson   // Copy field data
812b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name));
822b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_description, (char **)&ctx->field_labels[ctx->num_fields]->description));
833668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->type       = field_type;
843668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->offset     = field_offset;
857bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->size       = field_size * num_values;
867bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->num_values = num_values;
87cdf32b93SJeremy L Thompson   ctx->num_fields++;
88cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
89cdf32b93SJeremy L Thompson }
90cdf32b93SJeremy L Thompson 
913b190ab8SJeremy L Thompson /**
92ea61e9acSJeremy L Thompson   @brief Destroy user data held by CeedQFunctionContext, using function set by CeedQFunctionContextSetDataDestroy, if applicable
933b190ab8SJeremy L Thompson 
943b190ab8SJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to destroy user data
953b190ab8SJeremy L Thompson 
963b190ab8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
973b190ab8SJeremy L Thompson 
983b190ab8SJeremy L Thompson   @ref Developer
993b190ab8SJeremy L Thompson **/
1003b190ab8SJeremy L Thompson static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) {
1013b190ab8SJeremy L Thompson   if (ctx->DataDestroy) {
1022b730f8bSJeremy L Thompson     CeedCall(ctx->DataDestroy(ctx));
1033b190ab8SJeremy L Thompson   } else {
1043b190ab8SJeremy L Thompson     CeedQFunctionContextDataDestroyUser data_destroy_function;
1053b190ab8SJeremy L Thompson     CeedMemType                         data_destroy_mem_type;
1063b190ab8SJeremy L Thompson 
1072b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function));
1083b190ab8SJeremy L Thompson     if (data_destroy_function) {
1093b190ab8SJeremy L Thompson       void *data;
1103b190ab8SJeremy L Thompson 
1112b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data));
1122b730f8bSJeremy L Thompson       CeedCall(data_destroy_function(data));
1132b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
1143b190ab8SJeremy L Thompson     }
1153b190ab8SJeremy L Thompson   }
1163b190ab8SJeremy L Thompson 
1173b190ab8SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1183b190ab8SJeremy L Thompson }
1193b190ab8SJeremy L Thompson 
120cdf32b93SJeremy L Thompson /// @}
121cdf32b93SJeremy L Thompson 
122cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
123777ff853SJeremy L Thompson /// CeedQFunctionContext Backend API
124777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
125777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionBackend
126777ff853SJeremy L Thompson /// @{
127777ff853SJeremy L Thompson 
128777ff853SJeremy L Thompson /**
129777ff853SJeremy L Thompson   @brief Get the Ceed associated with a CeedQFunctionContext
130777ff853SJeremy L Thompson 
131ea61e9acSJeremy L Thompson   @param[in]  ctx  CeedQFunctionContext
132777ff853SJeremy L Thompson   @param[out] ceed Variable to store Ceed
133777ff853SJeremy L Thompson 
134777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
135777ff853SJeremy L Thompson 
136777ff853SJeremy L Thompson   @ref Backend
137777ff853SJeremy L Thompson **/
138777ff853SJeremy L Thompson int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) {
139777ff853SJeremy L Thompson   *ceed = ctx->ceed;
140e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
141777ff853SJeremy L Thompson }
142777ff853SJeremy L Thompson 
143777ff853SJeremy L Thompson /**
1449c774eddSJeremy L Thompson   @brief Check for valid data in a CeedQFunctionContext
1459c774eddSJeremy L Thompson 
146ea61e9acSJeremy L Thompson   @param[in]  ctx            CeedQFunctionContext to check validity
1479c774eddSJeremy L Thompson   @param[out] has_valid_data Variable to store validity
1489c774eddSJeremy L Thompson 
1499c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1509c774eddSJeremy L Thompson 
1519c774eddSJeremy L Thompson   @ref Backend
1529c774eddSJeremy L Thompson **/
1532b730f8bSJeremy L Thompson int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, bool *has_valid_data) {
1542b730f8bSJeremy L Thompson   if (!ctx->HasValidData) {
1559c774eddSJeremy L Thompson     // LCOV_EXCL_START
1562b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasValidData");
1579c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
1582b730f8bSJeremy L Thompson   }
1599c774eddSJeremy L Thompson 
1602b730f8bSJeremy L Thompson   CeedCall(ctx->HasValidData(ctx, has_valid_data));
1619c774eddSJeremy L Thompson 
1629c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1639c774eddSJeremy L Thompson }
1649c774eddSJeremy L Thompson 
1659c774eddSJeremy L Thompson /**
166ea61e9acSJeremy L Thompson   @brief Check for borrowed data of a specific CeedMemType in a CeedQFunctionContext
1679c774eddSJeremy L Thompson 
168ea61e9acSJeremy L Thompson   @param[in]  ctx                       CeedQFunctionContext to check
169ea61e9acSJeremy L Thompson   @param[in]  mem_type                  Memory type to check
1709c774eddSJeremy L Thompson   @param[out] has_borrowed_data_of_type Variable to store result
1719c774eddSJeremy L Thompson 
1729c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1739c774eddSJeremy L Thompson 
1749c774eddSJeremy L Thompson   @ref Backend
1759c774eddSJeremy L Thompson **/
1762b730f8bSJeremy L Thompson int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) {
1772b730f8bSJeremy L Thompson   if (!ctx->HasBorrowedDataOfType) {
1789c774eddSJeremy L Thompson     // LCOV_EXCL_START
1792b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedDataOfType");
1809c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
1812b730f8bSJeremy L Thompson   }
1829c774eddSJeremy L Thompson 
1832b730f8bSJeremy L Thompson   CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type));
1849c774eddSJeremy L Thompson 
1859c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1869c774eddSJeremy L Thompson }
1879c774eddSJeremy L Thompson 
1889c774eddSJeremy L Thompson /**
189777ff853SJeremy L Thompson   @brief Get the state of a CeedQFunctionContext
190777ff853SJeremy L Thompson 
191ea61e9acSJeremy L Thompson   @param[in]  ctx   CeedQFunctionContext to retrieve state
192777ff853SJeremy L Thompson   @param[out] state Variable to store state
193777ff853SJeremy L Thompson 
194777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
195777ff853SJeremy L Thompson 
196777ff853SJeremy L Thompson   @ref Backend
197777ff853SJeremy L Thompson **/
198777ff853SJeremy L Thompson int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
199777ff853SJeremy L Thompson   *state = ctx->state;
200e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
201777ff853SJeremy L Thompson }
202777ff853SJeremy L Thompson 
203777ff853SJeremy L Thompson /**
204777ff853SJeremy L Thompson   @brief Get backend data of a CeedQFunctionContext
205777ff853SJeremy L Thompson 
206ea61e9acSJeremy L Thompson   @param[in]  ctx  CeedQFunctionContext
207777ff853SJeremy L Thompson   @param[out] data Variable to store data
208777ff853SJeremy L Thompson 
209777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
210777ff853SJeremy L Thompson 
211777ff853SJeremy L Thompson   @ref Backend
212777ff853SJeremy L Thompson **/
213777ff853SJeremy L Thompson int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
214777ff853SJeremy L Thompson   *(void **)data = ctx->data;
215e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
216777ff853SJeremy L Thompson }
217777ff853SJeremy L Thompson 
218777ff853SJeremy L Thompson /**
219777ff853SJeremy L Thompson   @brief Set backend data of a CeedQFunctionContext
220777ff853SJeremy L Thompson 
221ea61e9acSJeremy L Thompson   @param[in,out] ctx  CeedQFunctionContext
222ea61e9acSJeremy L Thompson   @param[in]     data Data to set
223777ff853SJeremy L Thompson 
224777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
225777ff853SJeremy L Thompson 
226777ff853SJeremy L Thompson   @ref Backend
227777ff853SJeremy L Thompson **/
228777ff853SJeremy L Thompson int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
229777ff853SJeremy L Thompson   ctx->data = data;
230e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
231777ff853SJeremy L Thompson }
232777ff853SJeremy L Thompson 
23334359f16Sjeremylt /**
234ea61e9acSJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no field has been registered with this `field_name`
235e6a0ab89SJeremy L Thompson 
236e6a0ab89SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
237e6a0ab89SJeremy L Thompson   @param[in]  field_name  Name of field to retrieve label
238e6a0ab89SJeremy L Thompson   @param[out] field_label Variable to field label
239e6a0ab89SJeremy L Thompson 
240e6a0ab89SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
241e6a0ab89SJeremy L Thompson 
2423e1e85abSJeremy L Thompson   @ref Backend
243e6a0ab89SJeremy L Thompson **/
2442b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) {
245e6a0ab89SJeremy L Thompson   CeedInt field_index;
2462b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
247e6a0ab89SJeremy L Thompson 
248e6a0ab89SJeremy L Thompson   if (field_index != -1) {
249e6a0ab89SJeremy L Thompson     *field_label = ctx->field_labels[field_index];
250e6a0ab89SJeremy L Thompson   } else {
251e6a0ab89SJeremy L Thompson     *field_label = NULL;
252e6a0ab89SJeremy L Thompson   }
253e6a0ab89SJeremy L Thompson 
254e6a0ab89SJeremy L Thompson   return CEED_ERROR_SUCCESS;
255e6a0ab89SJeremy L Thompson }
256e6a0ab89SJeremy L Thompson 
257e6a0ab89SJeremy L Thompson /**
258d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field
259d8dd9a91SJeremy L Thompson 
260ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
261ea61e9acSJeremy L Thompson   @param[in]     field_label Label of field to set
262ea61e9acSJeremy L Thompson   @param[in]     field_type  Type of field to set
2632788fa27SJeremy L Thompson   @param[in]     values      Value to set
264d8dd9a91SJeremy L Thompson 
265d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
266d8dd9a91SJeremy L Thompson 
2673e1e85abSJeremy L Thompson   @ref Backend
268d8dd9a91SJeremy L Thompson **/
2692788fa27SJeremy L Thompson int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) {
2703668ca4bSJeremy L Thompson   // Check field type
2712b730f8bSJeremy L Thompson   if (field_label->type != field_type) {
272d8dd9a91SJeremy L Thompson     // LCOV_EXCL_START
2732b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s",
2742b730f8bSJeremy L Thompson                      field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
275d8dd9a91SJeremy L Thompson     // LCOV_EXCL_STOP
2762b730f8bSJeremy L Thompson   }
277d8dd9a91SJeremy L Thompson 
278d8dd9a91SJeremy L Thompson   char *data;
2792b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data));
2802788fa27SJeremy L Thompson   memcpy(&data[field_label->offset], values, field_label->size);
2812b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
282d8dd9a91SJeremy L Thompson 
283d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
284d8dd9a91SJeremy L Thompson }
285d8dd9a91SJeremy L Thompson 
286d8dd9a91SJeremy L Thompson /**
2872788fa27SJeremy L Thompson   @brief Get QFunctionContext field data, read-only
2882788fa27SJeremy L Thompson 
2892788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
2902788fa27SJeremy L Thompson   @param[in]  field_label Label of field to read
2912788fa27SJeremy L Thompson   @param[in]  field_type  Type of field to read
2922788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
2932788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
2942788fa27SJeremy L Thompson 
2952788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2962788fa27SJeremy L Thompson 
2972788fa27SJeremy L Thompson   @ref Backend
2982788fa27SJeremy L Thompson **/
2992788fa27SJeremy L Thompson int CeedQFunctionContextGetGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type,
3002788fa27SJeremy L Thompson                                        size_t *num_values, void *values) {
3012788fa27SJeremy L Thompson   // Check field type
3022788fa27SJeremy L Thompson   if (field_label->type != field_type) {
3032788fa27SJeremy L Thompson     // LCOV_EXCL_START
3042788fa27SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s",
3052788fa27SJeremy L Thompson                      field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
3062788fa27SJeremy L Thompson     // LCOV_EXCL_STOP
3072788fa27SJeremy L Thompson   }
3082788fa27SJeremy L Thompson 
3092788fa27SJeremy L Thompson   char *data;
3102788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data));
3112788fa27SJeremy L Thompson   *(void **)values = &data[field_label->offset];
3122788fa27SJeremy L Thompson   switch (field_type) {
3132788fa27SJeremy L Thompson     case CEED_CONTEXT_FIELD_INT32:
3142788fa27SJeremy L Thompson       *num_values = field_label->size / sizeof(int);
3152788fa27SJeremy L Thompson       break;
3162788fa27SJeremy L Thompson     case CEED_CONTEXT_FIELD_DOUBLE:
3172788fa27SJeremy L Thompson       *num_values = field_label->size / sizeof(double);
3182788fa27SJeremy L Thompson       break;
3192788fa27SJeremy L Thompson   }
3202788fa27SJeremy L Thompson 
3212788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3222788fa27SJeremy L Thompson }
3232788fa27SJeremy L Thompson 
3242788fa27SJeremy L Thompson /**
3252788fa27SJeremy L Thompson   @brief Restore QFunctionContext field data, read-only
3262788fa27SJeremy L Thompson 
3272788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
3282788fa27SJeremy L Thompson   @param[in]  field_label Label of field to restore
3292788fa27SJeremy L Thompson   @param[in]  field_type  Type of field to restore
3302788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3312788fa27SJeremy L Thompson 
3322788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3332788fa27SJeremy L Thompson 
3342788fa27SJeremy L Thompson   @ref Backend
3352788fa27SJeremy L Thompson **/
3362788fa27SJeremy L Thompson int CeedQFunctionContextRestoreGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type,
3372788fa27SJeremy L Thompson                                            void *values) {
3382788fa27SJeremy L Thompson   // Check field type
3392788fa27SJeremy L Thompson   if (field_label->type != field_type) {
3402788fa27SJeremy L Thompson     // LCOV_EXCL_START
3412788fa27SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s",
3422788fa27SJeremy L Thompson                      field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
3432788fa27SJeremy L Thompson     // LCOV_EXCL_STOP
3442788fa27SJeremy L Thompson   }
3452788fa27SJeremy L Thompson 
3462788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreDataRead(ctx, values));
3472788fa27SJeremy L Thompson 
3482788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3492788fa27SJeremy L Thompson }
3502788fa27SJeremy L Thompson 
3512788fa27SJeremy L Thompson /**
352bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value
353bfacc300SJeremy L Thompson 
354ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
3552788fa27SJeremy L Thompson   @param[in]     field_label Label for field to set
356ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
357bfacc300SJeremy L Thompson 
358bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
359bfacc300SJeremy L Thompson 
3603e1e85abSJeremy L Thompson   @ref Backend
361bfacc300SJeremy L Thompson **/
3622b730f8bSJeremy L Thompson int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) {
3632b730f8bSJeremy L Thompson   if (!field_label) {
364bfacc300SJeremy L Thompson     // LCOV_EXCL_START
3652b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
366bfacc300SJeremy L Thompson     // LCOV_EXCL_STOP
3672b730f8bSJeremy L Thompson   }
368bfacc300SJeremy L Thompson 
3692b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
370bfacc300SJeremy L Thompson 
371bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
372bfacc300SJeremy L Thompson }
373bfacc300SJeremy L Thompson 
374bfacc300SJeremy L Thompson /**
3752788fa27SJeremy L Thompson   @brief Get QFunctionContext field holding a double precision value, read-only
3762788fa27SJeremy L Thompson 
3772788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
3782788fa27SJeremy L Thompson   @param[in]  field_label Label for field to get
3792788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
3802788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3812788fa27SJeremy L Thompson 
3822788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3832788fa27SJeremy L Thompson 
3842788fa27SJeremy L Thompson   @ref Backend
3852788fa27SJeremy L Thompson **/
3862788fa27SJeremy L Thompson int CeedQFunctionContextGetDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const double **values) {
3872788fa27SJeremy L Thompson   if (!field_label) {
3882788fa27SJeremy L Thompson     // LCOV_EXCL_START
3892788fa27SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
3902788fa27SJeremy L Thompson     // LCOV_EXCL_STOP
3912788fa27SJeremy L Thompson   }
3922788fa27SJeremy L Thompson 
3932788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, num_values, values));
3942788fa27SJeremy L Thompson 
3952788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3962788fa27SJeremy L Thompson }
3972788fa27SJeremy L Thompson 
3982788fa27SJeremy L Thompson /**
3992788fa27SJeremy L Thompson   @brief Restore QFunctionContext field holding a double precision value, read-only
4002788fa27SJeremy L Thompson 
4012788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
4022788fa27SJeremy L Thompson   @param[in]  field_label Label for field to restore
4032788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4042788fa27SJeremy L Thompson 
4052788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4062788fa27SJeremy L Thompson 
4072788fa27SJeremy L Thompson   @ref Backend
4082788fa27SJeremy L Thompson **/
4092788fa27SJeremy L Thompson int CeedQFunctionContextRestoreDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const double **values) {
4102788fa27SJeremy L Thompson   if (!field_label) {
4112788fa27SJeremy L Thompson     // LCOV_EXCL_START
4122788fa27SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
4132788fa27SJeremy L Thompson     // LCOV_EXCL_STOP
4142788fa27SJeremy L Thompson   }
4152788fa27SJeremy L Thompson 
4162788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
4172788fa27SJeremy L Thompson 
4182788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4192788fa27SJeremy L Thompson }
4202788fa27SJeremy L Thompson 
4212788fa27SJeremy L Thompson /**
422bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value
423bfacc300SJeremy L Thompson 
424ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
4252788fa27SJeremy L Thompson   @param[in]     field_label Label for field to set
426ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
427bfacc300SJeremy L Thompson 
428bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
429bfacc300SJeremy L Thompson 
4303e1e85abSJeremy L Thompson   @ref Backend
431bfacc300SJeremy L Thompson **/
4322b730f8bSJeremy L Thompson int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int *values) {
4332b730f8bSJeremy L Thompson   if (!field_label) {
434bfacc300SJeremy L Thompson     // LCOV_EXCL_START
4352b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
436bfacc300SJeremy L Thompson     // LCOV_EXCL_STOP
4372b730f8bSJeremy L Thompson   }
438bfacc300SJeremy L Thompson 
4392b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
440bfacc300SJeremy L Thompson 
441bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
442bfacc300SJeremy L Thompson }
443bfacc300SJeremy L Thompson 
444bfacc300SJeremy L Thompson /**
4452788fa27SJeremy L Thompson   @brief Get QFunctionContext field holding a int32 value, read-only
4462788fa27SJeremy L Thompson 
4472788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
4482788fa27SJeremy L Thompson   @param[in]  field_label Label for field to get
4492788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
4502788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4512788fa27SJeremy L Thompson 
4522788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4532788fa27SJeremy L Thompson 
4542788fa27SJeremy L Thompson   @ref Backend
4552788fa27SJeremy L Thompson **/
4562788fa27SJeremy L Thompson int CeedQFunctionContextGetInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const int **values) {
4572788fa27SJeremy L Thompson   if (!field_label) {
4582788fa27SJeremy L Thompson     // LCOV_EXCL_START
4592788fa27SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
4602788fa27SJeremy L Thompson     // LCOV_EXCL_STOP
4612788fa27SJeremy L Thompson   }
4622788fa27SJeremy L Thompson 
4632788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, num_values, values));
4642788fa27SJeremy L Thompson 
4652788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4662788fa27SJeremy L Thompson }
4672788fa27SJeremy L Thompson 
4682788fa27SJeremy L Thompson /**
4692788fa27SJeremy L Thompson   @brief Restore QFunctionContext field holding a int32 value, read-only
4702788fa27SJeremy L Thompson 
4712788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
4722788fa27SJeremy L Thompson   @param[in]  field_label Label for field to restore
4732788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4742788fa27SJeremy L Thompson 
4752788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4762788fa27SJeremy L Thompson 
4772788fa27SJeremy L Thompson   @ref Backend
4782788fa27SJeremy L Thompson **/
4792788fa27SJeremy L Thompson int CeedQFunctionContextRestoreInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const int **values) {
4802788fa27SJeremy L Thompson   if (!field_label) {
4812788fa27SJeremy L Thompson     // LCOV_EXCL_START
4822788fa27SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
4832788fa27SJeremy L Thompson     // LCOV_EXCL_STOP
4842788fa27SJeremy L Thompson   }
4852788fa27SJeremy L Thompson 
4862788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
4872788fa27SJeremy L Thompson 
4882788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4892788fa27SJeremy L Thompson }
4902788fa27SJeremy L Thompson 
4912788fa27SJeremy L Thompson /**
4922e64a2b9SJeremy L Thompson   @brief Get additional destroy routine for CeedQFunctionContext user data
4932e64a2b9SJeremy L Thompson 
4942e64a2b9SJeremy L Thompson   @param[in] ctx         CeedQFunctionContext to get user destroy function
4952e64a2b9SJeremy L Thompson   @param[out] f_mem_type Memory type to use when passing data into `f`
4962e64a2b9SJeremy L Thompson   @param[out] f          Additional routine to use to destroy user data
4972e64a2b9SJeremy L Thompson 
4982e64a2b9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4992e64a2b9SJeremy L Thompson 
5002e64a2b9SJeremy L Thompson   @ref Backend
5012e64a2b9SJeremy L Thompson **/
5022b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) {
5032e64a2b9SJeremy L Thompson   if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type;
5042e64a2b9SJeremy L Thompson   if (f) *f = ctx->data_destroy_function;
5052e64a2b9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5062e64a2b9SJeremy L Thompson }
5072e64a2b9SJeremy L Thompson 
5082e64a2b9SJeremy L Thompson /**
50934359f16Sjeremylt   @brief Increment the reference counter for a CeedQFunctionContext
51034359f16Sjeremylt 
511ea61e9acSJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to increment the reference counter
51234359f16Sjeremylt 
51334359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
51434359f16Sjeremylt 
51534359f16Sjeremylt   @ref Backend
51634359f16Sjeremylt **/
5179560d06aSjeremylt int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
51834359f16Sjeremylt   ctx->ref_count++;
51934359f16Sjeremylt   return CEED_ERROR_SUCCESS;
52034359f16Sjeremylt }
52134359f16Sjeremylt 
522777ff853SJeremy L Thompson /// @}
523777ff853SJeremy L Thompson 
524777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
525777ff853SJeremy L Thompson /// CeedQFunctionContext Public API
526777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
527777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionUser
528777ff853SJeremy L Thompson /// @{
529777ff853SJeremy L Thompson 
530777ff853SJeremy L Thompson /**
531777ff853SJeremy L Thompson   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
532777ff853SJeremy L Thompson 
533ea61e9acSJeremy L Thompson   @param[in]  ceed Ceed object where the CeedQFunctionContext will be created
534ea61e9acSJeremy L Thompson   @param[out] ctx  Address of the variable where the newly created CeedQFunctionContext will be stored
535777ff853SJeremy L Thompson 
536777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
537777ff853SJeremy L Thompson 
538777ff853SJeremy L Thompson   @ref User
539777ff853SJeremy L Thompson **/
540777ff853SJeremy L Thompson int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
541777ff853SJeremy L Thompson   if (!ceed->QFunctionContextCreate) {
542777ff853SJeremy L Thompson     Ceed delegate;
5432b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context"));
544777ff853SJeremy L Thompson 
5452b730f8bSJeremy L Thompson     if (!delegate) {
546777ff853SJeremy L Thompson       // LCOV_EXCL_START
5472b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextCreate");
548777ff853SJeremy L Thompson       // LCOV_EXCL_STOP
5492b730f8bSJeremy L Thompson     }
550777ff853SJeremy L Thompson 
5512b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextCreate(delegate, ctx));
552e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
553777ff853SJeremy L Thompson   }
554777ff853SJeremy L Thompson 
5552b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, ctx));
556777ff853SJeremy L Thompson   (*ctx)->ceed = ceed;
5572b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
558d1d35e2fSjeremylt   (*ctx)->ref_count = 1;
5592b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionContextCreate(*ctx));
560e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
561777ff853SJeremy L Thompson }
562777ff853SJeremy L Thompson 
563777ff853SJeremy L Thompson /**
564ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedQFunctionContext.
5654385fb7fSSebastian Grimberg 
566ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedQFunctionContextDestroy()`.
567512bb800SJeremy L Thompson 
568512bb800SJeremy 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
569512bb800SJeremy L Thompson         CeedQFunctionContext. This CeedQFunctionContext will be destroyed if `ctx_copy` is the only reference to this CeedQFunctionContext.
5709560d06aSjeremylt 
571ea61e9acSJeremy L Thompson   @param[in]     ctx      CeedQFunctionContext to copy reference to
572ea61e9acSJeremy L Thompson   @param[in,out] ctx_copy Variable to store copied reference
5739560d06aSjeremylt 
5749560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
5759560d06aSjeremylt 
5769560d06aSjeremylt   @ref User
5779560d06aSjeremylt **/
5782b730f8bSJeremy L Thompson int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) {
5792b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextReference(ctx));
5802b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(ctx_copy));
5819560d06aSjeremylt   *ctx_copy = ctx;
5829560d06aSjeremylt   return CEED_ERROR_SUCCESS;
5839560d06aSjeremylt }
5849560d06aSjeremylt 
5859560d06aSjeremylt /**
586ea61e9acSJeremy L Thompson   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated data if applicable.
5874385fb7fSSebastian Grimberg 
588ea61e9acSJeremy L Thompson   The backend may copy values to a different memtype, such as during @ref CeedQFunctionApply().
589777ff853SJeremy L Thompson   See also @ref CeedQFunctionContextTakeData().
590777ff853SJeremy L Thompson 
591ea61e9acSJeremy L Thompson   @param[in,out] ctx       CeedQFunctionContext
592ea61e9acSJeremy L Thompson   @param[in]     mem_type  Memory type of the data being passed
593ea61e9acSJeremy L Thompson   @param[in]     copy_mode Copy mode for the data
594ea61e9acSJeremy L Thompson   @param[in]     size      Size of data, in bytes
595ea61e9acSJeremy L Thompson   @param[in]     data      Data to be used
596777ff853SJeremy L Thompson 
597777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
598777ff853SJeremy L Thompson 
599777ff853SJeremy L Thompson   @ref User
600777ff853SJeremy L Thompson **/
6012b730f8bSJeremy L Thompson int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) {
6022b730f8bSJeremy L Thompson   if (!ctx->SetData) {
603777ff853SJeremy L Thompson     // LCOV_EXCL_START
6042b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData");
605777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
6062b730f8bSJeremy L Thompson   }
6072b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
608777ff853SJeremy L Thompson     // LCOV_EXCL_START
6092b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
610777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
6112b730f8bSJeremy L Thompson   }
612777ff853SJeremy L Thompson 
6132b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(ctx));
614d1d35e2fSjeremylt   ctx->ctx_size = size;
6152b730f8bSJeremy L Thompson   CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data));
616777ff853SJeremy L Thompson   ctx->state += 2;
617e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
618777ff853SJeremy L Thompson }
619777ff853SJeremy L Thompson 
620777ff853SJeremy L Thompson /**
621891038deSjeremylt   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
6224385fb7fSSebastian Grimberg 
623891038deSjeremylt   The caller is responsible for managing and freeing the memory.
624891038deSjeremylt 
625ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
626ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
627ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
628891038deSjeremylt   @param[out] data     Data on memory type mem_type
629891038deSjeremylt 
630891038deSjeremylt   @return An error code: 0 - success, otherwise - failure
631891038deSjeremylt 
632891038deSjeremylt   @ref User
633891038deSjeremylt **/
6342b730f8bSJeremy L Thompson int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
6359c774eddSJeremy L Thompson   bool has_valid_data = true;
6362b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
6372b730f8bSJeremy L Thompson   if (!has_valid_data) {
6389c774eddSJeremy L Thompson     // LCOV_EXCL_START
6392b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data");
6409c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
6412b730f8bSJeremy L Thompson   }
6429c774eddSJeremy L Thompson 
6432b730f8bSJeremy L Thompson   if (!ctx->TakeData) {
644891038deSjeremylt     // LCOV_EXCL_START
6452b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData");
646891038deSjeremylt     // LCOV_EXCL_STOP
6472b730f8bSJeremy L Thompson   }
6482b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
649891038deSjeremylt     // LCOV_EXCL_START
6502b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
651891038deSjeremylt     // LCOV_EXCL_STOP
6522b730f8bSJeremy L Thompson   }
653891038deSjeremylt 
6549c774eddSJeremy L Thompson   bool has_borrowed_data_of_type = true;
6552b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type));
6562b730f8bSJeremy L Thompson   if (!has_borrowed_data_of_type) {
6579c774eddSJeremy L Thompson     // LCOV_EXCL_START
6586ed4cbd1SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no borrowed %s data, must set data with CeedQFunctionContextSetData",
6599c774eddSJeremy L Thompson                      CeedMemTypes[mem_type]);
6609c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
6612b730f8bSJeremy L Thompson   }
6629c774eddSJeremy L Thompson 
663891038deSjeremylt   void *temp_data = NULL;
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 /**
670777ff853SJeremy 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 
674ea61e9acSJeremy 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 
679ea61e9acSJeremy L Thompson   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory
680*9fd66db6SSebastian Grimberg space.
681*9fd66db6SSebastian Grimberg         Pairing get/restore allows the Context to track access.
682777ff853SJeremy L Thompson 
683777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
684777ff853SJeremy L Thompson 
685777ff853SJeremy L Thompson   @ref User
686777ff853SJeremy L Thompson **/
6872b730f8bSJeremy L Thompson int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
6882b730f8bSJeremy L Thompson   if (!ctx->GetData) {
689777ff853SJeremy L Thompson     // LCOV_EXCL_START
6902b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData");
691777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
6922b730f8bSJeremy L Thompson   }
6932b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
694777ff853SJeremy L Thompson     // LCOV_EXCL_START
6952b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
696777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
6972b730f8bSJeremy L Thompson   }
6982b730f8bSJeremy L Thompson   if (ctx->num_readers > 0) {
69928bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
7002b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access");
70128bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
7022b730f8bSJeremy L Thompson   }
70328bfd0b7SJeremy L Thompson 
7049c774eddSJeremy L Thompson   bool has_valid_data = true;
7052b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
7062b730f8bSJeremy L Thompson   if (!has_valid_data) {
7079c774eddSJeremy L Thompson     // LCOV_EXCL_START
7082b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
7099c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
7102b730f8bSJeremy L Thompson   }
7119c774eddSJeremy L Thompson 
7122b730f8bSJeremy L Thompson   CeedCall(ctx->GetData(ctx, mem_type, data));
71328bfd0b7SJeremy L Thompson   ctx->state++;
71428bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
71528bfd0b7SJeremy L Thompson }
71628bfd0b7SJeremy L Thompson 
71728bfd0b7SJeremy L Thompson /**
71828bfd0b7SJeremy L Thompson   @brief Get read only access to a CeedQFunctionContext via the specified memory type.
7194385fb7fSSebastian Grimberg 
72028bfd0b7SJeremy L Thompson   Restore access with @ref CeedQFunctionContextRestoreData().
72128bfd0b7SJeremy L Thompson 
722ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
723ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
724ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
72528bfd0b7SJeremy L Thompson   @param[out] data     Data on memory type mem_type
72628bfd0b7SJeremy L Thompson 
727ea61e9acSJeremy L Thompson   @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired
728*9fd66db6SSebastian Grimberg memory space.
729*9fd66db6SSebastian Grimberg         Pairing get/restore allows the Context to track access.
73028bfd0b7SJeremy L Thompson 
73128bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
73228bfd0b7SJeremy L Thompson 
73328bfd0b7SJeremy L Thompson   @ref User
73428bfd0b7SJeremy L Thompson **/
7352b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
7362b730f8bSJeremy L Thompson   if (!ctx->GetDataRead) {
73728bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
7382b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead");
73928bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
7402b730f8bSJeremy L Thompson   }
7412b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
74228bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
7432b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
74428bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
7452b730f8bSJeremy L Thompson   }
74628bfd0b7SJeremy L Thompson 
74728bfd0b7SJeremy L Thompson   bool has_valid_data = true;
7482b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
7492b730f8bSJeremy L Thompson   if (!has_valid_data) {
75028bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
7512b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
75228bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
7532b730f8bSJeremy L Thompson   }
75428bfd0b7SJeremy L Thompson 
7552b730f8bSJeremy L Thompson   CeedCall(ctx->GetDataRead(ctx, mem_type, data));
75628bfd0b7SJeremy L Thompson   ctx->num_readers++;
757e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
758777ff853SJeremy L Thompson }
759777ff853SJeremy L Thompson 
760777ff853SJeremy L Thompson /**
761777ff853SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
762777ff853SJeremy L Thompson 
763ea61e9acSJeremy L Thompson   @param[in]     ctx  CeedQFunctionContext to restore
764ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
765777ff853SJeremy L Thompson 
766777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
767777ff853SJeremy L Thompson 
768777ff853SJeremy L Thompson   @ref User
769777ff853SJeremy L Thompson **/
770777ff853SJeremy L Thompson int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
7712b730f8bSJeremy L Thompson   if (ctx->state % 2 != 1) {
772777ff853SJeremy L Thompson     // LCOV_EXCL_START
7732b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
774777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
7752b730f8bSJeremy L Thompson   }
776777ff853SJeremy L Thompson 
777706efda3SJeremy L Thompson   if (ctx->RestoreData) {
7782b730f8bSJeremy L Thompson     CeedCall(ctx->RestoreData(ctx));
779706efda3SJeremy L Thompson   }
780777ff853SJeremy L Thompson   *(void **)data = NULL;
78128bfd0b7SJeremy L Thompson   ctx->state++;
78228bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
78328bfd0b7SJeremy L Thompson }
78428bfd0b7SJeremy L Thompson 
78528bfd0b7SJeremy L Thompson /**
78628bfd0b7SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead()
78728bfd0b7SJeremy L Thompson 
788ea61e9acSJeremy L Thompson   @param[in]     ctx  CeedQFunctionContext to restore
789ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
79028bfd0b7SJeremy L Thompson 
79128bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
79228bfd0b7SJeremy L Thompson 
79328bfd0b7SJeremy L Thompson   @ref User
79428bfd0b7SJeremy L Thompson **/
79528bfd0b7SJeremy L Thompson int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) {
7962b730f8bSJeremy L Thompson   if (ctx->num_readers == 0) {
79728bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
7982b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
79928bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
8002b730f8bSJeremy L Thompson   }
80128bfd0b7SJeremy L Thompson 
80275a19770SJeremy L Thompson   ctx->num_readers--;
80375a19770SJeremy L Thompson   if (ctx->num_readers == 0 && ctx->RestoreDataRead) {
8042b730f8bSJeremy L Thompson     CeedCall(ctx->RestoreDataRead(ctx));
80528bfd0b7SJeremy L Thompson   }
80628bfd0b7SJeremy L Thompson   *(void **)data = NULL;
80775a19770SJeremy L Thompson 
808e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
809777ff853SJeremy L Thompson }
810777ff853SJeremy L Thompson 
811777ff853SJeremy L Thompson /**
812cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a double precision value
813cdf32b93SJeremy L Thompson 
814ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
815ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
816ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
817ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
818ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
819cdf32b93SJeremy L Thompson 
820cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
821cdf32b93SJeremy L Thompson 
822cdf32b93SJeremy L Thompson   @ref User
823cdf32b93SJeremy L Thompson **/
8242b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
825cdf32b93SJeremy L Thompson                                        const char *field_description) {
8262b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values);
827cdf32b93SJeremy L Thompson }
828cdf32b93SJeremy L Thompson 
829cdf32b93SJeremy L Thompson /**
830cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a int32 value
831cdf32b93SJeremy L Thompson 
832ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
833ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
834ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
835ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
836ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
837cdf32b93SJeremy L Thompson 
838cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
839cdf32b93SJeremy L Thompson 
840cdf32b93SJeremy L Thompson   @ref User
841cdf32b93SJeremy L Thompson **/
8422b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
843cdf32b93SJeremy L Thompson                                       const char *field_description) {
8442b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values);
845cdf32b93SJeremy L Thompson }
846cdf32b93SJeremy L Thompson 
847cdf32b93SJeremy L Thompson /**
8483668ca4bSJeremy L Thompson   @brief Get labels for all registered QFunctionContext fields
849cdf32b93SJeremy L Thompson 
850ea61e9acSJeremy L Thompson   @param[in]  ctx          CeedQFunctionContext
8513668ca4bSJeremy L Thompson   @param[out] field_labels Variable to hold array of field labels
852cdf32b93SJeremy L Thompson   @param[out] num_fields   Length of field descriptions array
853cdf32b93SJeremy L Thompson 
854cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
855cdf32b93SJeremy L Thompson 
856cdf32b93SJeremy L Thompson   @ref User
857cdf32b93SJeremy L Thompson **/
8582b730f8bSJeremy L Thompson int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
8593668ca4bSJeremy L Thompson   *field_labels = ctx->field_labels;
860cdf32b93SJeremy L Thompson   *num_fields   = ctx->num_fields;
861cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
862cdf32b93SJeremy L Thompson }
863cdf32b93SJeremy L Thompson 
864cdf32b93SJeremy L Thompson /**
8650f86cbe7SJeremy L Thompson   @brief Get the descriptive information about a CeedContextFieldLabel
8660f86cbe7SJeremy L Thompson 
8670f86cbe7SJeremy L Thompson   @param[in]  label             CeedContextFieldLabel
8680f86cbe7SJeremy L Thompson   @param[out] field_name        Name of labeled field
8690f86cbe7SJeremy L Thompson   @param[out] field_description Description of field, or NULL for none
8707bfe0f0eSJeremy L Thompson   @param[out] num_values        Number of values registered
8710f86cbe7SJeremy L Thompson   @param[out] field_type        CeedContextFieldType
8720f86cbe7SJeremy L Thompson 
8730f86cbe7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8740f86cbe7SJeremy L Thompson 
8750f86cbe7SJeremy L Thompson   @ref User
8760f86cbe7SJeremy L Thompson **/
8772b730f8bSJeremy L Thompson int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values,
8780f86cbe7SJeremy L Thompson                                         CeedContextFieldType *field_type) {
8790f86cbe7SJeremy L Thompson   if (field_name) *field_name = label->name;
8800f86cbe7SJeremy L Thompson   if (field_description) *field_description = label->description;
8817bfe0f0eSJeremy L Thompson   if (num_values) *num_values = label->num_values;
8820f86cbe7SJeremy L Thompson   if (field_type) *field_type = label->type;
8830f86cbe7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8840f86cbe7SJeremy L Thompson }
8850f86cbe7SJeremy L Thompson 
8860f86cbe7SJeremy L Thompson /**
88780a9ef05SNatalie Beams   @brief Get data size for a Context
88880a9ef05SNatalie Beams 
889ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext
89080a9ef05SNatalie Beams   @param[out] ctx_size Variable to store size of context data values
89180a9ef05SNatalie Beams 
89280a9ef05SNatalie Beams   @return An error code: 0 - success, otherwise - failure
89380a9ef05SNatalie Beams 
89480a9ef05SNatalie Beams   @ref User
89580a9ef05SNatalie Beams **/
8962b730f8bSJeremy L Thompson int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) {
89780a9ef05SNatalie Beams   *ctx_size = ctx->ctx_size;
89880a9ef05SNatalie Beams   return CEED_ERROR_SUCCESS;
89980a9ef05SNatalie Beams }
90080a9ef05SNatalie Beams 
90180a9ef05SNatalie Beams /**
902777ff853SJeremy L Thompson   @brief View a CeedQFunctionContext
903777ff853SJeremy L Thompson 
904777ff853SJeremy L Thompson   @param[in] ctx    CeedQFunctionContext to view
905777ff853SJeremy L Thompson   @param[in] stream Filestream to write to
906777ff853SJeremy L Thompson 
907777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
908777ff853SJeremy L Thompson 
909777ff853SJeremy L Thompson   @ref User
910777ff853SJeremy L Thompson **/
911777ff853SJeremy L Thompson int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
912777ff853SJeremy L Thompson   fprintf(stream, "CeedQFunctionContext\n");
913d1d35e2fSjeremylt   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
9143668ca4bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
9153668ca4bSJeremy L Thompson     // LCOV_EXCL_START
9162b730f8bSJeremy L Thompson     fprintf(stream, "  Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name);
9173668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
9183668ca4bSJeremy L Thompson   }
919e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
920777ff853SJeremy L Thompson }
921777ff853SJeremy L Thompson 
922777ff853SJeremy L Thompson /**
9232790b72bSJeremy L Thompson   @brief Set additional destroy routine for CeedQFunctionContext user data
9242790b72bSJeremy L Thompson 
925ea61e9acSJeremy L Thompson   @param[in,out] ctx        CeedQFunctionContext to set user destroy function
9262e64a2b9SJeremy L Thompson   @param[in]     f_mem_type Memory type to use when passing data into `f`
9272e64a2b9SJeremy L Thompson   @param[in]     f          Additional routine to use to destroy user data
9282790b72bSJeremy L Thompson 
9292790b72bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9302790b72bSJeremy L Thompson 
9312790b72bSJeremy L Thompson   @ref User
9322790b72bSJeremy L Thompson **/
9332b730f8bSJeremy L Thompson int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) {
9342b730f8bSJeremy L Thompson   if (!f) {
9352790b72bSJeremy L Thompson     // LCOV_EXCL_START
9362b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Must provide valid callback function for destroying user data");
9372790b72bSJeremy L Thompson     // LCOV_EXCL_STOP
9382b730f8bSJeremy L Thompson   }
9392790b72bSJeremy L Thompson   ctx->data_destroy_mem_type = f_mem_type;
9402790b72bSJeremy L Thompson   ctx->data_destroy_function = f;
9412790b72bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
9422790b72bSJeremy L Thompson }
9432790b72bSJeremy L Thompson 
9442790b72bSJeremy L Thompson /**
945777ff853SJeremy L Thompson   @brief Destroy a CeedQFunctionContext
946777ff853SJeremy L Thompson 
947ea61e9acSJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to destroy
948777ff853SJeremy L Thompson 
949777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
950777ff853SJeremy L Thompson 
951777ff853SJeremy L Thompson   @ref User
952777ff853SJeremy L Thompson **/
953777ff853SJeremy L Thompson int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
954ad6481ceSJeremy L Thompson   if (!*ctx || --(*ctx)->ref_count > 0) {
955ad6481ceSJeremy L Thompson     *ctx = NULL;
956ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
957ad6481ceSJeremy L Thompson   }
9582b730f8bSJeremy L Thompson   if ((*ctx) && ((*ctx)->state % 2) == 1) {
959777ff853SJeremy L Thompson     // LCOV_EXCL_START
9602b730f8bSJeremy L Thompson     return CeedError((*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use");
961777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
9622b730f8bSJeremy L Thompson   }
963777ff853SJeremy L Thompson 
9642b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(*ctx));
9652b730f8bSJeremy L Thompson   if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx));
966cdf32b93SJeremy L Thompson   for (CeedInt i = 0; i < (*ctx)->num_fields; i++) {
9672b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->name));
9682b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->description));
9692b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]));
970cdf32b93SJeremy L Thompson   }
9712b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ctx)->field_labels));
9722b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*ctx)->ceed));
9732b730f8bSJeremy L Thompson   CeedCall(CeedFree(ctx));
974cdf32b93SJeremy L Thompson 
975e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
976777ff853SJeremy L Thompson }
977777ff853SJeremy L Thompson 
978777ff853SJeremy L Thompson /// @}
979