xref: /libCEED/interface/ceed-qfunctioncontext.c (revision ea61e9ac44808524e4667c1525a05976f536c19c)
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>
92b730f8bSJeremy L Thompson #include <ceed/backend.h>
102b730f8bSJeremy L Thompson #include <ceed/ceed.h>
113d576824SJeremy L Thompson #include <stdint.h>
123d576824SJeremy L Thompson #include <stdio.h>
13cdf32b93SJeremy L Thompson #include <string.h>
14777ff853SJeremy L Thompson 
15777ff853SJeremy L Thompson /// @file
16777ff853SJeremy L Thompson /// Implementation of public CeedQFunctionContext interfaces
17777ff853SJeremy L Thompson 
18777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
19cdf32b93SJeremy L Thompson /// CeedQFunctionContext Library Internal Functions
20cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
21cdf32b93SJeremy L Thompson /// @addtogroup CeedQFunctionDeveloper
22cdf32b93SJeremy L Thompson /// @{
23cdf32b93SJeremy L Thompson 
24cdf32b93SJeremy L Thompson /**
25cdf32b93SJeremy L Thompson   @brief Get index for QFunctionContext field
26cdf32b93SJeremy L Thompson 
27*ea61e9acSJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
28*ea61e9acSJeremy L Thompson   @param[in]  field_name  Name of field
29*ea61e9acSJeremy L Thompson   @param[out] field_index Index of field, or -1 if field is not registered
30cdf32b93SJeremy L Thompson 
31cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
32cdf32b93SJeremy L Thompson 
33cdf32b93SJeremy L Thompson   @ref Developer
34cdf32b93SJeremy L Thompson **/
352b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, const char *field_name, CeedInt *field_index) {
36cdf32b93SJeremy L Thompson   *field_index = -1;
372b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
382b730f8bSJeremy L Thompson     if (!strcmp(ctx->field_labels[i]->name, field_name)) *field_index = i;
392b730f8bSJeremy L Thompson   }
40cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
41cdf32b93SJeremy L Thompson }
42cdf32b93SJeremy L Thompson 
43cdf32b93SJeremy L Thompson /**
44cdf32b93SJeremy L Thompson   @brief Common function for registering QFunctionContext fields
45cdf32b93SJeremy L Thompson 
46*ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
47*ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
48*ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
49*ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
50*ea61e9acSJeremy L Thompson   @param[in]     field_type        Field data type, such as double or int32
51*ea61e9acSJeremy L Thompson   @param[in]     field_size        Size of field, in bytes
52*ea61e9acSJeremy 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,
592b730f8bSJeremy L Thompson                                         CeedContextFieldType field_type, size_t field_size, size_t num_values) {
60cdf32b93SJeremy L Thompson   // Check for duplicate
61cdf32b93SJeremy L Thompson   CeedInt field_index = -1;
622b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
632b730f8bSJeremy L Thompson   if (field_index != -1) {
64cdf32b93SJeremy L Thompson     // LCOV_EXCL_START
652b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" already registered", field_name);
66cdf32b93SJeremy L Thompson     // LCOV_EXCL_STOP
672b730f8bSJeremy L Thompson   }
68cdf32b93SJeremy L Thompson 
69cdf32b93SJeremy L Thompson   // Allocate space for field data
70cdf32b93SJeremy L Thompson   if (ctx->num_fields == 0) {
712b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(1, &ctx->field_labels));
72cdf32b93SJeremy L Thompson     ctx->max_fields = 1;
73cdf32b93SJeremy L Thompson   } else if (ctx->num_fields == ctx->max_fields) {
742b730f8bSJeremy L Thompson     CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels));
75cdf32b93SJeremy L Thompson     ctx->max_fields *= 2;
76cdf32b93SJeremy L Thompson   }
772b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields]));
78cdf32b93SJeremy L Thompson 
79cdf32b93SJeremy L Thompson   // Copy field data
802b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name));
812b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_description, (char **)&ctx->field_labels[ctx->num_fields]->description));
823668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->type       = field_type;
833668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->offset     = field_offset;
847bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->size       = field_size * num_values;
857bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->num_values = num_values;
86cdf32b93SJeremy L Thompson   ctx->num_fields++;
87cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
88cdf32b93SJeremy L Thompson }
89cdf32b93SJeremy L Thompson 
903b190ab8SJeremy L Thompson /**
91*ea61e9acSJeremy L Thompson   @brief Destroy user data held by CeedQFunctionContext, using function set by CeedQFunctionContextSetDataDestroy, if applicable
923b190ab8SJeremy L Thompson 
933b190ab8SJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to destroy user data
943b190ab8SJeremy L Thompson 
953b190ab8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
963b190ab8SJeremy L Thompson 
973b190ab8SJeremy L Thompson   @ref Developer
983b190ab8SJeremy L Thompson **/
993b190ab8SJeremy L Thompson static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) {
1003b190ab8SJeremy L Thompson   if (ctx->DataDestroy) {
1012b730f8bSJeremy L Thompson     CeedCall(ctx->DataDestroy(ctx));
1023b190ab8SJeremy L Thompson   } else {
1033b190ab8SJeremy L Thompson     CeedQFunctionContextDataDestroyUser data_destroy_function;
1043b190ab8SJeremy L Thompson     CeedMemType                         data_destroy_mem_type;
1053b190ab8SJeremy L Thompson 
1062b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function));
1073b190ab8SJeremy L Thompson     if (data_destroy_function) {
1083b190ab8SJeremy L Thompson       void *data;
1093b190ab8SJeremy L Thompson 
1102b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data));
1112b730f8bSJeremy L Thompson       CeedCall(data_destroy_function(data));
1122b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
1133b190ab8SJeremy L Thompson     }
1143b190ab8SJeremy L Thompson   }
1153b190ab8SJeremy L Thompson 
1163b190ab8SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1173b190ab8SJeremy L Thompson }
1183b190ab8SJeremy L Thompson 
119cdf32b93SJeremy L Thompson /// @}
120cdf32b93SJeremy L Thompson 
121cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
122777ff853SJeremy L Thompson /// CeedQFunctionContext Backend API
123777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
124777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionBackend
125777ff853SJeremy L Thompson /// @{
126777ff853SJeremy L Thompson 
127777ff853SJeremy L Thompson /**
128777ff853SJeremy L Thompson   @brief Get the Ceed associated with a CeedQFunctionContext
129777ff853SJeremy L Thompson 
130*ea61e9acSJeremy L Thompson   @param[in]  ctx  CeedQFunctionContext
131777ff853SJeremy L Thompson   @param[out] ceed Variable to store Ceed
132777ff853SJeremy L Thompson 
133777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
134777ff853SJeremy L Thompson 
135777ff853SJeremy L Thompson   @ref Backend
136777ff853SJeremy L Thompson **/
137777ff853SJeremy L Thompson int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) {
138777ff853SJeremy L Thompson   *ceed = ctx->ceed;
139e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
140777ff853SJeremy L Thompson }
141777ff853SJeremy L Thompson 
142777ff853SJeremy L Thompson /**
1439c774eddSJeremy L Thompson   @brief Check for valid data in a CeedQFunctionContext
1449c774eddSJeremy L Thompson 
145*ea61e9acSJeremy L Thompson   @param[in]  ctx            CeedQFunctionContext to check validity
1469c774eddSJeremy L Thompson   @param[out] has_valid_data Variable to store validity
1479c774eddSJeremy L Thompson 
1489c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1499c774eddSJeremy L Thompson 
1509c774eddSJeremy L Thompson   @ref Backend
1519c774eddSJeremy L Thompson **/
1522b730f8bSJeremy L Thompson int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, bool *has_valid_data) {
1532b730f8bSJeremy L Thompson   if (!ctx->HasValidData) {
1549c774eddSJeremy L Thompson     // LCOV_EXCL_START
1552b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasValidData");
1569c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
1572b730f8bSJeremy L Thompson   }
1589c774eddSJeremy L Thompson 
1592b730f8bSJeremy L Thompson   CeedCall(ctx->HasValidData(ctx, has_valid_data));
1609c774eddSJeremy L Thompson 
1619c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1629c774eddSJeremy L Thompson }
1639c774eddSJeremy L Thompson 
1649c774eddSJeremy L Thompson /**
165*ea61e9acSJeremy L Thompson   @brief Check for borrowed data of a specific CeedMemType in a CeedQFunctionContext
1669c774eddSJeremy L Thompson 
167*ea61e9acSJeremy L Thompson   @param[in]  ctx                       CeedQFunctionContext to check
168*ea61e9acSJeremy L Thompson   @param[in]  mem_type                  Memory type to check
1699c774eddSJeremy L Thompson   @param[out] has_borrowed_data_of_type Variable to store result
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 CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) {
1762b730f8bSJeremy L Thompson   if (!ctx->HasBorrowedDataOfType) {
1779c774eddSJeremy L Thompson     // LCOV_EXCL_START
1782b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedDataOfType");
1799c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
1802b730f8bSJeremy L Thompson   }
1819c774eddSJeremy L Thompson 
1822b730f8bSJeremy L Thompson   CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type));
1839c774eddSJeremy L Thompson 
1849c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1859c774eddSJeremy L Thompson }
1869c774eddSJeremy L Thompson 
1879c774eddSJeremy L Thompson /**
188777ff853SJeremy L Thompson   @brief Get the state of a CeedQFunctionContext
189777ff853SJeremy L Thompson 
190*ea61e9acSJeremy L Thompson   @param[in]  ctx   CeedQFunctionContext to retrieve state
191777ff853SJeremy L Thompson   @param[out] state Variable to store state
192777ff853SJeremy L Thompson 
193777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
194777ff853SJeremy L Thompson 
195777ff853SJeremy L Thompson   @ref Backend
196777ff853SJeremy L Thompson **/
197777ff853SJeremy L Thompson int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
198777ff853SJeremy L Thompson   *state = ctx->state;
199e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
200777ff853SJeremy L Thompson }
201777ff853SJeremy L Thompson 
202777ff853SJeremy L Thompson /**
203777ff853SJeremy L Thompson   @brief Get backend data of a CeedQFunctionContext
204777ff853SJeremy L Thompson 
205*ea61e9acSJeremy L Thompson   @param[in]  ctx  CeedQFunctionContext
206777ff853SJeremy L Thompson   @param[out] data Variable to store data
207777ff853SJeremy L Thompson 
208777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
209777ff853SJeremy L Thompson 
210777ff853SJeremy L Thompson   @ref Backend
211777ff853SJeremy L Thompson **/
212777ff853SJeremy L Thompson int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
213777ff853SJeremy L Thompson   *(void **)data = ctx->data;
214e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
215777ff853SJeremy L Thompson }
216777ff853SJeremy L Thompson 
217777ff853SJeremy L Thompson /**
218777ff853SJeremy L Thompson   @brief Set backend data of a CeedQFunctionContext
219777ff853SJeremy L Thompson 
220*ea61e9acSJeremy L Thompson   @param[in,out] ctx  CeedQFunctionContext
221*ea61e9acSJeremy L Thompson   @param[in]     data Data to set
222777ff853SJeremy L Thompson 
223777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
224777ff853SJeremy L Thompson 
225777ff853SJeremy L Thompson   @ref Backend
226777ff853SJeremy L Thompson **/
227777ff853SJeremy L Thompson int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
228777ff853SJeremy L Thompson   ctx->data = data;
229e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
230777ff853SJeremy L Thompson }
231777ff853SJeremy L Thompson 
23234359f16Sjeremylt /**
233*ea61e9acSJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no field has been registered with this `field_name`
234e6a0ab89SJeremy L Thompson 
235e6a0ab89SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
236e6a0ab89SJeremy L Thompson   @param[in]  field_name  Name of field to retrieve label
237e6a0ab89SJeremy L Thompson   @param[out] field_label Variable to field label
238e6a0ab89SJeremy L Thompson 
239e6a0ab89SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
240e6a0ab89SJeremy L Thompson 
2413e1e85abSJeremy L Thompson   @ref Backend
242e6a0ab89SJeremy L Thompson **/
2432b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) {
244e6a0ab89SJeremy L Thompson   CeedInt field_index;
2452b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
246e6a0ab89SJeremy L Thompson 
247e6a0ab89SJeremy L Thompson   if (field_index != -1) {
248e6a0ab89SJeremy L Thompson     *field_label = ctx->field_labels[field_index];
249e6a0ab89SJeremy L Thompson   } else {
250e6a0ab89SJeremy L Thompson     *field_label = NULL;
251e6a0ab89SJeremy L Thompson   }
252e6a0ab89SJeremy L Thompson 
253e6a0ab89SJeremy L Thompson   return CEED_ERROR_SUCCESS;
254e6a0ab89SJeremy L Thompson }
255e6a0ab89SJeremy L Thompson 
256e6a0ab89SJeremy L Thompson /**
257d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field
258d8dd9a91SJeremy L Thompson 
259*ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
260*ea61e9acSJeremy L Thompson   @param[in]     field_label Label of field to set
261*ea61e9acSJeremy L Thompson   @param[in]     field_type  Type of field to set
262*ea61e9acSJeremy L Thompson   @param[in]     value       Value to set
263d8dd9a91SJeremy L Thompson 
264d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
265d8dd9a91SJeremy L Thompson 
2663e1e85abSJeremy L Thompson   @ref Backend
267d8dd9a91SJeremy L Thompson **/
2682b730f8bSJeremy L Thompson int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *value) {
2693668ca4bSJeremy L Thompson   // Check field type
2702b730f8bSJeremy L Thompson   if (field_label->type != field_type) {
271d8dd9a91SJeremy L Thompson     // LCOV_EXCL_START
2722b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s",
2732b730f8bSJeremy L Thompson                      field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
274d8dd9a91SJeremy L Thompson     // LCOV_EXCL_STOP
2752b730f8bSJeremy L Thompson   }
276d8dd9a91SJeremy L Thompson 
277d8dd9a91SJeremy L Thompson   char *data;
2782b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data));
2793668ca4bSJeremy L Thompson   memcpy(&data[field_label->offset], value, field_label->size);
2802b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
281d8dd9a91SJeremy L Thompson 
282d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
283d8dd9a91SJeremy L Thompson }
284d8dd9a91SJeremy L Thompson 
285d8dd9a91SJeremy L Thompson /**
286bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value
287bfacc300SJeremy L Thompson 
288*ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
289*ea61e9acSJeremy L Thompson   @param[in]     field_label Label for field to register
290*ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
291bfacc300SJeremy L Thompson 
292bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
293bfacc300SJeremy L Thompson 
2943e1e85abSJeremy L Thompson   @ref Backend
295bfacc300SJeremy L Thompson **/
2962b730f8bSJeremy L Thompson int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) {
2972b730f8bSJeremy L Thompson   if (!field_label) {
298bfacc300SJeremy L Thompson     // LCOV_EXCL_START
2992b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
300bfacc300SJeremy L Thompson     // LCOV_EXCL_STOP
3012b730f8bSJeremy L Thompson   }
302bfacc300SJeremy L Thompson 
3032b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
304bfacc300SJeremy L Thompson 
305bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
306bfacc300SJeremy L Thompson }
307bfacc300SJeremy L Thompson 
308bfacc300SJeremy L Thompson /**
309bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value
310bfacc300SJeremy L Thompson 
311*ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
312*ea61e9acSJeremy L Thompson   @param[in]     field_label Label for field to register
313*ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
314bfacc300SJeremy L Thompson 
315bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
316bfacc300SJeremy L Thompson 
3173e1e85abSJeremy L Thompson   @ref Backend
318bfacc300SJeremy L Thompson **/
3192b730f8bSJeremy L Thompson int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int *values) {
3202b730f8bSJeremy L Thompson   if (!field_label) {
321bfacc300SJeremy L Thompson     // LCOV_EXCL_START
3222b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
323bfacc300SJeremy L Thompson     // LCOV_EXCL_STOP
3242b730f8bSJeremy L Thompson   }
325bfacc300SJeremy L Thompson 
3262b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
327bfacc300SJeremy L Thompson 
328bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
329bfacc300SJeremy L Thompson }
330bfacc300SJeremy L Thompson 
331bfacc300SJeremy L Thompson /**
3322e64a2b9SJeremy L Thompson   @brief Get additional destroy routine for CeedQFunctionContext user data
3332e64a2b9SJeremy L Thompson 
3342e64a2b9SJeremy L Thompson   @param[in] ctx         CeedQFunctionContext to get user destroy function
3352e64a2b9SJeremy L Thompson   @param[out] f_mem_type Memory type to use when passing data into `f`
3362e64a2b9SJeremy L Thompson   @param[out] f          Additional routine to use to destroy user data
3372e64a2b9SJeremy L Thompson 
3382e64a2b9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3392e64a2b9SJeremy L Thompson 
3402e64a2b9SJeremy L Thompson   @ref Backend
3412e64a2b9SJeremy L Thompson **/
3422b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) {
3432e64a2b9SJeremy L Thompson   if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type;
3442e64a2b9SJeremy L Thompson   if (f) *f = ctx->data_destroy_function;
3452e64a2b9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3462e64a2b9SJeremy L Thompson }
3472e64a2b9SJeremy L Thompson 
3482e64a2b9SJeremy L Thompson /**
34934359f16Sjeremylt   @brief Increment the reference counter for a CeedQFunctionContext
35034359f16Sjeremylt 
351*ea61e9acSJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to increment the reference counter
35234359f16Sjeremylt 
35334359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
35434359f16Sjeremylt 
35534359f16Sjeremylt   @ref Backend
35634359f16Sjeremylt **/
3579560d06aSjeremylt int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
35834359f16Sjeremylt   ctx->ref_count++;
35934359f16Sjeremylt   return CEED_ERROR_SUCCESS;
36034359f16Sjeremylt }
36134359f16Sjeremylt 
362777ff853SJeremy L Thompson /// @}
363777ff853SJeremy L Thompson 
364777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
365777ff853SJeremy L Thompson /// CeedQFunctionContext Public API
366777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
367777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionUser
368777ff853SJeremy L Thompson /// @{
369777ff853SJeremy L Thompson 
370777ff853SJeremy L Thompson /**
371777ff853SJeremy L Thompson   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
372777ff853SJeremy L Thompson 
373*ea61e9acSJeremy L Thompson   @param[in]  ceed Ceed object where the CeedQFunctionContext will be created
374*ea61e9acSJeremy L Thompson   @param[out] ctx  Address of the variable where the newly created CeedQFunctionContext will be stored
375777ff853SJeremy L Thompson 
376777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
377777ff853SJeremy L Thompson 
378777ff853SJeremy L Thompson   @ref User
379777ff853SJeremy L Thompson **/
380777ff853SJeremy L Thompson int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
381777ff853SJeremy L Thompson   if (!ceed->QFunctionContextCreate) {
382777ff853SJeremy L Thompson     Ceed delegate;
3832b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context"));
384777ff853SJeremy L Thompson 
3852b730f8bSJeremy L Thompson     if (!delegate) {
386777ff853SJeremy L Thompson       // LCOV_EXCL_START
3872b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextCreate");
388777ff853SJeremy L Thompson       // LCOV_EXCL_STOP
3892b730f8bSJeremy L Thompson     }
390777ff853SJeremy L Thompson 
3912b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextCreate(delegate, ctx));
392e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
393777ff853SJeremy L Thompson   }
394777ff853SJeremy L Thompson 
3952b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, ctx));
396777ff853SJeremy L Thompson   (*ctx)->ceed = ceed;
3972b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
398d1d35e2fSjeremylt   (*ctx)->ref_count = 1;
3992b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionContextCreate(*ctx));
400e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
401777ff853SJeremy L Thompson }
402777ff853SJeremy L Thompson 
403777ff853SJeremy L Thompson /**
404*ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedQFunctionContext.
405*ea61e9acSJeremy L Thompson            Both pointers should be destroyed with `CeedQFunctionContextDestroy()`.
406*ea61e9acSJeremy L Thompson            Note: If `*ctx_copy` is non-NULL, then it is assumed that `*ctx_copy` is a pointer to a CeedQFunctionContext.
407*ea61e9acSJeremy L Thompson              This CeedQFunctionContext will be destroyed if `*ctx_copy` is the only reference to this CeedQFunctionContext.
4089560d06aSjeremylt 
409*ea61e9acSJeremy L Thompson   @param[in]     ctx      CeedQFunctionContext to copy reference to
410*ea61e9acSJeremy L Thompson   @param[in,out] ctx_copy Variable to store copied reference
4119560d06aSjeremylt 
4129560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
4139560d06aSjeremylt 
4149560d06aSjeremylt   @ref User
4159560d06aSjeremylt **/
4162b730f8bSJeremy L Thompson int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) {
4172b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextReference(ctx));
4182b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(ctx_copy));
4199560d06aSjeremylt   *ctx_copy = ctx;
4209560d06aSjeremylt   return CEED_ERROR_SUCCESS;
4219560d06aSjeremylt }
4229560d06aSjeremylt 
4239560d06aSjeremylt /**
424*ea61e9acSJeremy L Thompson   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated data if applicable.
425*ea61e9acSJeremy L Thompson            The backend may copy values to a different memtype, such as during @ref CeedQFunctionApply().
426777ff853SJeremy L Thompson            See also @ref CeedQFunctionContextTakeData().
427777ff853SJeremy L Thompson 
428*ea61e9acSJeremy L Thompson   @param[in,out] ctx       CeedQFunctionContext
429*ea61e9acSJeremy L Thompson   @param[in]     mem_type  Memory type of the data being passed
430*ea61e9acSJeremy L Thompson   @param[in]     copy_mode Copy mode for the data
431*ea61e9acSJeremy L Thompson   @param[in]     size      Size of data, in bytes
432*ea61e9acSJeremy L Thompson   @param[in]     data      Data to be used
433777ff853SJeremy L Thompson 
434777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
435777ff853SJeremy L Thompson 
436777ff853SJeremy L Thompson   @ref User
437777ff853SJeremy L Thompson **/
4382b730f8bSJeremy L Thompson int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) {
4392b730f8bSJeremy L Thompson   if (!ctx->SetData) {
440777ff853SJeremy L Thompson     // LCOV_EXCL_START
4412b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData");
442777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
4432b730f8bSJeremy L Thompson   }
4442b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
445777ff853SJeremy L Thompson     // LCOV_EXCL_START
4462b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
447777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
4482b730f8bSJeremy L Thompson   }
449777ff853SJeremy L Thompson 
4502b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(ctx));
451d1d35e2fSjeremylt   ctx->ctx_size = size;
4522b730f8bSJeremy L Thompson   CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data));
453777ff853SJeremy L Thompson   ctx->state += 2;
454e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
455777ff853SJeremy L Thompson }
456777ff853SJeremy L Thompson 
457777ff853SJeremy L Thompson /**
458891038deSjeremylt   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
459891038deSjeremylt            The caller is responsible for managing and freeing the memory.
460891038deSjeremylt 
461*ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
462*ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
463*ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
464891038deSjeremylt   @param[out] data     Data on memory type mem_type
465891038deSjeremylt 
466891038deSjeremylt   @return An error code: 0 - success, otherwise - failure
467891038deSjeremylt 
468891038deSjeremylt   @ref User
469891038deSjeremylt **/
4702b730f8bSJeremy L Thompson int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
4719c774eddSJeremy L Thompson   bool has_valid_data = true;
4722b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
4732b730f8bSJeremy L Thompson   if (!has_valid_data) {
4749c774eddSJeremy L Thompson     // LCOV_EXCL_START
4752b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data");
4769c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
4772b730f8bSJeremy L Thompson   }
4789c774eddSJeremy L Thompson 
4792b730f8bSJeremy L Thompson   if (!ctx->TakeData) {
480891038deSjeremylt     // LCOV_EXCL_START
4812b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData");
482891038deSjeremylt     // LCOV_EXCL_STOP
4832b730f8bSJeremy L Thompson   }
4842b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
485891038deSjeremylt     // LCOV_EXCL_START
4862b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
487891038deSjeremylt     // LCOV_EXCL_STOP
4882b730f8bSJeremy L Thompson   }
489891038deSjeremylt 
4909c774eddSJeremy L Thompson   bool has_borrowed_data_of_type = true;
4912b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type));
4922b730f8bSJeremy L Thompson   if (!has_borrowed_data_of_type) {
4939c774eddSJeremy L Thompson     // LCOV_EXCL_START
4942b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no borowed %s data, must set data with CeedQFunctionContextSetData",
4959c774eddSJeremy L Thompson                      CeedMemTypes[mem_type]);
4969c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
4972b730f8bSJeremy L Thompson   }
4989c774eddSJeremy L Thompson 
499891038deSjeremylt   void *temp_data = NULL;
5002b730f8bSJeremy L Thompson   CeedCall(ctx->TakeData(ctx, mem_type, &temp_data));
501891038deSjeremylt   if (data) (*(void **)data) = temp_data;
502891038deSjeremylt   return CEED_ERROR_SUCCESS;
503891038deSjeremylt }
504891038deSjeremylt 
505891038deSjeremylt /**
506777ff853SJeremy L Thompson   @brief Get read/write access to a CeedQFunctionContext via the specified memory type.
507777ff853SJeremy L Thompson            Restore access with @ref CeedQFunctionContextRestoreData().
508777ff853SJeremy L Thompson 
509*ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
510*ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
511*ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
512d1d35e2fSjeremylt   @param[out] data     Data on memory type mem_type
513777ff853SJeremy L Thompson 
514*ea61e9acSJeremy L Thompson   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory
515*ea61e9acSJeremy L Thompson space. Pairing get/restore allows the Context to track access.
516777ff853SJeremy L Thompson 
517777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
518777ff853SJeremy L Thompson 
519777ff853SJeremy L Thompson   @ref User
520777ff853SJeremy L Thompson **/
5212b730f8bSJeremy L Thompson int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
5222b730f8bSJeremy L Thompson   if (!ctx->GetData) {
523777ff853SJeremy L Thompson     // LCOV_EXCL_START
5242b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData");
525777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
5262b730f8bSJeremy L Thompson   }
5272b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
528777ff853SJeremy L Thompson     // LCOV_EXCL_START
5292b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
530777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
5312b730f8bSJeremy L Thompson   }
5322b730f8bSJeremy L Thompson   if (ctx->num_readers > 0) {
53328bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
5342b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access");
53528bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
5362b730f8bSJeremy L Thompson   }
53728bfd0b7SJeremy L Thompson 
5389c774eddSJeremy L Thompson   bool has_valid_data = true;
5392b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
5402b730f8bSJeremy L Thompson   if (!has_valid_data) {
5419c774eddSJeremy L Thompson     // LCOV_EXCL_START
5422b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
5439c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
5442b730f8bSJeremy L Thompson   }
5459c774eddSJeremy L Thompson 
5462b730f8bSJeremy L Thompson   CeedCall(ctx->GetData(ctx, mem_type, data));
54728bfd0b7SJeremy L Thompson   ctx->state++;
54828bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
54928bfd0b7SJeremy L Thompson }
55028bfd0b7SJeremy L Thompson 
55128bfd0b7SJeremy L Thompson /**
55228bfd0b7SJeremy L Thompson   @brief Get read only access to a CeedQFunctionContext via the specified memory type.
55328bfd0b7SJeremy L Thompson            Restore access with @ref CeedQFunctionContextRestoreData().
55428bfd0b7SJeremy L Thompson 
555*ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
556*ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
557*ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
55828bfd0b7SJeremy L Thompson   @param[out] data     Data on memory type mem_type
55928bfd0b7SJeremy L Thompson 
560*ea61e9acSJeremy L Thompson   @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired
561*ea61e9acSJeremy L Thompson memory space. Pairing get/restore allows the Context to track access.
56228bfd0b7SJeremy L Thompson 
56328bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
56428bfd0b7SJeremy L Thompson 
56528bfd0b7SJeremy L Thompson   @ref User
56628bfd0b7SJeremy L Thompson **/
5672b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
5682b730f8bSJeremy L Thompson   if (!ctx->GetDataRead) {
56928bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
5702b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead");
57128bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
5722b730f8bSJeremy L Thompson   }
5732b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
57428bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
5752b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
57628bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
5772b730f8bSJeremy L Thompson   }
57828bfd0b7SJeremy L Thompson 
57928bfd0b7SJeremy L Thompson   bool has_valid_data = true;
5802b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
5812b730f8bSJeremy L Thompson   if (!has_valid_data) {
58228bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
5832b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
58428bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
5852b730f8bSJeremy L Thompson   }
58628bfd0b7SJeremy L Thompson 
5872b730f8bSJeremy L Thompson   CeedCall(ctx->GetDataRead(ctx, mem_type, data));
58828bfd0b7SJeremy L Thompson   ctx->num_readers++;
589e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
590777ff853SJeremy L Thompson }
591777ff853SJeremy L Thompson 
592777ff853SJeremy L Thompson /**
593777ff853SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
594777ff853SJeremy L Thompson 
595*ea61e9acSJeremy L Thompson   @param[in]     ctx  CeedQFunctionContext to restore
596*ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
597777ff853SJeremy L Thompson 
598777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
599777ff853SJeremy L Thompson 
600777ff853SJeremy L Thompson   @ref User
601777ff853SJeremy L Thompson **/
602777ff853SJeremy L Thompson int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
6032b730f8bSJeremy L Thompson   if (ctx->state % 2 != 1) {
604777ff853SJeremy L Thompson     // LCOV_EXCL_START
6052b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
606777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
6072b730f8bSJeremy L Thompson   }
608777ff853SJeremy L Thompson 
609706efda3SJeremy L Thompson   if (ctx->RestoreData) {
6102b730f8bSJeremy L Thompson     CeedCall(ctx->RestoreData(ctx));
611706efda3SJeremy L Thompson   }
612777ff853SJeremy L Thompson   *(void **)data = NULL;
61328bfd0b7SJeremy L Thompson   ctx->state++;
61428bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
61528bfd0b7SJeremy L Thompson }
61628bfd0b7SJeremy L Thompson 
61728bfd0b7SJeremy L Thompson /**
61828bfd0b7SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead()
61928bfd0b7SJeremy L Thompson 
620*ea61e9acSJeremy L Thompson   @param[in]     ctx  CeedQFunctionContext to restore
621*ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
62228bfd0b7SJeremy L Thompson 
62328bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
62428bfd0b7SJeremy L Thompson 
62528bfd0b7SJeremy L Thompson   @ref User
62628bfd0b7SJeremy L Thompson **/
62728bfd0b7SJeremy L Thompson int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) {
6282b730f8bSJeremy L Thompson   if (ctx->num_readers == 0) {
62928bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
6302b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
63128bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
6322b730f8bSJeremy L Thompson   }
63328bfd0b7SJeremy L Thompson 
63475a19770SJeremy L Thompson   ctx->num_readers--;
63575a19770SJeremy L Thompson   if (ctx->num_readers == 0 && ctx->RestoreDataRead) {
6362b730f8bSJeremy L Thompson     CeedCall(ctx->RestoreDataRead(ctx));
63728bfd0b7SJeremy L Thompson   }
63828bfd0b7SJeremy L Thompson   *(void **)data = NULL;
63975a19770SJeremy L Thompson 
640e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
641777ff853SJeremy L Thompson }
642777ff853SJeremy L Thompson 
643777ff853SJeremy L Thompson /**
644cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a double precision value
645cdf32b93SJeremy L Thompson 
646*ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
647*ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
648*ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
649*ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
650*ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
651cdf32b93SJeremy L Thompson 
652cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
653cdf32b93SJeremy L Thompson 
654cdf32b93SJeremy L Thompson   @ref User
655cdf32b93SJeremy L Thompson **/
6562b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
657cdf32b93SJeremy L Thompson                                        const char *field_description) {
6582b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values);
659cdf32b93SJeremy L Thompson }
660cdf32b93SJeremy L Thompson 
661cdf32b93SJeremy L Thompson /**
662cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a int32 value
663cdf32b93SJeremy L Thompson 
664*ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
665*ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
666*ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
667*ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
668*ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
669cdf32b93SJeremy L Thompson 
670cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
671cdf32b93SJeremy L Thompson 
672cdf32b93SJeremy L Thompson   @ref User
673cdf32b93SJeremy L Thompson **/
6742b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
675cdf32b93SJeremy L Thompson                                       const char *field_description) {
6762b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values);
677cdf32b93SJeremy L Thompson }
678cdf32b93SJeremy L Thompson 
679cdf32b93SJeremy L Thompson /**
6803668ca4bSJeremy L Thompson   @brief Get labels for all registered QFunctionContext fields
681cdf32b93SJeremy L Thompson 
682*ea61e9acSJeremy L Thompson   @param[in]  ctx          CeedQFunctionContext
6833668ca4bSJeremy L Thompson   @param[out] field_labels Variable to hold array of field labels
684cdf32b93SJeremy L Thompson   @param[out] num_fields   Length of field descriptions array
685cdf32b93SJeremy L Thompson 
686cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
687cdf32b93SJeremy L Thompson 
688cdf32b93SJeremy L Thompson   @ref User
689cdf32b93SJeremy L Thompson **/
6902b730f8bSJeremy L Thompson int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
6913668ca4bSJeremy L Thompson   *field_labels = ctx->field_labels;
692cdf32b93SJeremy L Thompson   *num_fields   = ctx->num_fields;
693cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
694cdf32b93SJeremy L Thompson }
695cdf32b93SJeremy L Thompson 
696cdf32b93SJeremy L Thompson /**
6970f86cbe7SJeremy L Thompson   @brief Get the descriptive information about a CeedContextFieldLabel
6980f86cbe7SJeremy L Thompson 
6990f86cbe7SJeremy L Thompson   @param[in]  label             CeedContextFieldLabel
7000f86cbe7SJeremy L Thompson   @param[out] field_name        Name of labeled field
7010f86cbe7SJeremy L Thompson   @param[out] field_description Description of field, or NULL for none
7027bfe0f0eSJeremy L Thompson   @param[out] num_values        Number of values registered
7030f86cbe7SJeremy L Thompson   @param[out] field_type        CeedContextFieldType
7040f86cbe7SJeremy L Thompson 
7050f86cbe7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7060f86cbe7SJeremy L Thompson 
7070f86cbe7SJeremy L Thompson   @ref User
7080f86cbe7SJeremy L Thompson **/
7092b730f8bSJeremy L Thompson int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values,
7100f86cbe7SJeremy L Thompson                                         CeedContextFieldType *field_type) {
7110f86cbe7SJeremy L Thompson   if (field_name) *field_name = label->name;
7120f86cbe7SJeremy L Thompson   if (field_description) *field_description = label->description;
7137bfe0f0eSJeremy L Thompson   if (num_values) *num_values = label->num_values;
7140f86cbe7SJeremy L Thompson   if (field_type) *field_type = label->type;
7150f86cbe7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7160f86cbe7SJeremy L Thompson }
7170f86cbe7SJeremy L Thompson 
7180f86cbe7SJeremy L Thompson /**
71980a9ef05SNatalie Beams   @brief Get data size for a Context
72080a9ef05SNatalie Beams 
721*ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext
72280a9ef05SNatalie Beams   @param[out] ctx_size Variable to store size of context data values
72380a9ef05SNatalie Beams 
72480a9ef05SNatalie Beams   @return An error code: 0 - success, otherwise - failure
72580a9ef05SNatalie Beams 
72680a9ef05SNatalie Beams   @ref User
72780a9ef05SNatalie Beams **/
7282b730f8bSJeremy L Thompson int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) {
72980a9ef05SNatalie Beams   *ctx_size = ctx->ctx_size;
73080a9ef05SNatalie Beams   return CEED_ERROR_SUCCESS;
73180a9ef05SNatalie Beams }
73280a9ef05SNatalie Beams 
73380a9ef05SNatalie Beams /**
734777ff853SJeremy L Thompson   @brief View a CeedQFunctionContext
735777ff853SJeremy L Thompson 
736777ff853SJeremy L Thompson   @param[in] ctx    CeedQFunctionContext to view
737777ff853SJeremy L Thompson   @param[in] stream Filestream to write to
738777ff853SJeremy L Thompson 
739777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
740777ff853SJeremy L Thompson 
741777ff853SJeremy L Thompson   @ref User
742777ff853SJeremy L Thompson **/
743777ff853SJeremy L Thompson int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
744777ff853SJeremy L Thompson   fprintf(stream, "CeedQFunctionContext\n");
745d1d35e2fSjeremylt   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
7463668ca4bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
7473668ca4bSJeremy L Thompson     // LCOV_EXCL_START
7482b730f8bSJeremy L Thompson     fprintf(stream, "  Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name);
7493668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
7503668ca4bSJeremy L Thompson   }
751e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
752777ff853SJeremy L Thompson }
753777ff853SJeremy L Thompson 
754777ff853SJeremy L Thompson /**
7552790b72bSJeremy L Thompson   @brief Set additional destroy routine for CeedQFunctionContext user data
7562790b72bSJeremy L Thompson 
757*ea61e9acSJeremy L Thompson   @param[in,out] ctx        CeedQFunctionContext to set user destroy function
7582e64a2b9SJeremy L Thompson   @param[in]     f_mem_type Memory type to use when passing data into `f`
7592e64a2b9SJeremy L Thompson   @param[in]     f          Additional routine to use to destroy user data
7602790b72bSJeremy L Thompson 
7612790b72bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7622790b72bSJeremy L Thompson 
7632790b72bSJeremy L Thompson   @ref User
7642790b72bSJeremy L Thompson **/
7652b730f8bSJeremy L Thompson int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) {
7662b730f8bSJeremy L Thompson   if (!f) {
7672790b72bSJeremy L Thompson     // LCOV_EXCL_START
7682b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Must provide valid callback function for destroying user data");
7692790b72bSJeremy L Thompson     // LCOV_EXCL_STOP
7702b730f8bSJeremy L Thompson   }
7712790b72bSJeremy L Thompson   ctx->data_destroy_mem_type = f_mem_type;
7722790b72bSJeremy L Thompson   ctx->data_destroy_function = f;
7732790b72bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
7742790b72bSJeremy L Thompson }
7752790b72bSJeremy L Thompson 
7762790b72bSJeremy L Thompson /**
777777ff853SJeremy L Thompson   @brief Destroy a CeedQFunctionContext
778777ff853SJeremy L Thompson 
779*ea61e9acSJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to destroy
780777ff853SJeremy L Thompson 
781777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
782777ff853SJeremy L Thompson 
783777ff853SJeremy L Thompson   @ref User
784777ff853SJeremy L Thompson **/
785777ff853SJeremy L Thompson int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
7862b730f8bSJeremy L Thompson   if (!*ctx || --(*ctx)->ref_count > 0) return CEED_ERROR_SUCCESS;
787777ff853SJeremy L Thompson 
7882b730f8bSJeremy L Thompson   if ((*ctx) && ((*ctx)->state % 2) == 1) {
789777ff853SJeremy L Thompson     // LCOV_EXCL_START
7902b730f8bSJeremy L Thompson     return CeedError((*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use");
791777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
7922b730f8bSJeremy L Thompson   }
793777ff853SJeremy L Thompson 
7942b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(*ctx));
7952b730f8bSJeremy L Thompson   if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx));
796cdf32b93SJeremy L Thompson   for (CeedInt i = 0; i < (*ctx)->num_fields; i++) {
7972b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->name));
7982b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->description));
7992b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]));
800cdf32b93SJeremy L Thompson   }
8012b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ctx)->field_labels));
8022b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*ctx)->ceed));
8032b730f8bSJeremy L Thompson   CeedCall(CeedFree(ctx));
804cdf32b93SJeremy L Thompson 
805e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
806777ff853SJeremy L Thompson }
807777ff853SJeremy L Thompson 
808777ff853SJeremy L Thompson /// @}
809