xref: /libCEED/interface/ceed-qfunctioncontext.c (revision 2b730f8b5a9c809740a0b3b302db43a719c636b1)
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>
9*2b730f8bSJeremy L Thompson #include <ceed/backend.h>
10*2b730f8bSJeremy 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 
27cdf32b93SJeremy L Thompson   @param ctx         CeedQFunctionContext
28cdf32b93SJeremy L Thompson   @param field_name  Name of field
29cdf32b93SJeremy L Thompson   @param 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 **/
35*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, const char *field_name, CeedInt *field_index) {
36cdf32b93SJeremy L Thompson   *field_index = -1;
37*2b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
38*2b730f8bSJeremy L Thompson     if (!strcmp(ctx->field_labels[i]->name, field_name)) *field_index = i;
39*2b730f8bSJeremy 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 
46cdf32b93SJeremy L Thompson   @param ctx               CeedQFunctionContext
47cdf32b93SJeremy L Thompson   @param field_name        Name of field to register
48cdf32b93SJeremy L Thompson   @param field_offset      Offset of field to register
49cdf32b93SJeremy L Thompson   @param field_description Description of field, or NULL for none
50cdf32b93SJeremy L Thompson   @param field_type        Field data type, such as double or int32
51cdf32b93SJeremy L Thompson   @param field_size        Size of field, in bytes
527bfe0f0eSJeremy L Thompson   @param 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 **/
58*2b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, const char *field_description,
59*2b730f8bSJeremy 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;
62*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
63*2b730f8bSJeremy L Thompson   if (field_index != -1) {
64cdf32b93SJeremy L Thompson     // LCOV_EXCL_START
65*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" already registered", field_name);
66cdf32b93SJeremy L Thompson     // LCOV_EXCL_STOP
67*2b730f8bSJeremy L Thompson   }
68cdf32b93SJeremy L Thompson 
69cdf32b93SJeremy L Thompson   // Allocate space for field data
70cdf32b93SJeremy L Thompson   if (ctx->num_fields == 0) {
71*2b730f8bSJeremy 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) {
74*2b730f8bSJeremy L Thompson     CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels));
75cdf32b93SJeremy L Thompson     ctx->max_fields *= 2;
76cdf32b93SJeremy L Thompson   }
77*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields]));
78cdf32b93SJeremy L Thompson 
79cdf32b93SJeremy L Thompson   // Copy field data
80*2b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name));
81*2b730f8bSJeremy 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 /**
913b190ab8SJeremy L Thompson   @brief Destroy user data held by CeedQFunctionContext, using function set by
923b190ab8SJeremy L Thompson      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) {
102*2b730f8bSJeremy 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 
107*2b730f8bSJeremy 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 
111*2b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data));
112*2b730f8bSJeremy L Thompson       CeedCall(data_destroy_function(data));
113*2b730f8bSJeremy 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 
131777ff853SJeremy L Thompson   @param 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 
1469c774eddSJeremy L Thompson   @param 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 **/
153*2b730f8bSJeremy L Thompson int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, bool *has_valid_data) {
154*2b730f8bSJeremy L Thompson   if (!ctx->HasValidData) {
1559c774eddSJeremy L Thompson     // LCOV_EXCL_START
156*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasValidData");
1579c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
158*2b730f8bSJeremy L Thompson   }
1599c774eddSJeremy L Thompson 
160*2b730f8bSJeremy 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 /**
1669c774eddSJeremy L Thompson   @brief Check for borrowed data of a specific CeedMemType in a
1679c774eddSJeremy L Thompson            CeedQFunctionContext
1689c774eddSJeremy L Thompson 
1699c774eddSJeremy L Thompson   @param ctx                             CeedQFunctionContext to check
1709c774eddSJeremy L Thompson   @param mem_type                        Memory type to check
1719c774eddSJeremy L Thompson   @param[out] has_borrowed_data_of_type  Variable to store result
1729c774eddSJeremy L Thompson 
1739c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1749c774eddSJeremy L Thompson 
1759c774eddSJeremy L Thompson   @ref Backend
1769c774eddSJeremy L Thompson **/
177*2b730f8bSJeremy L Thompson int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) {
178*2b730f8bSJeremy L Thompson   if (!ctx->HasBorrowedDataOfType) {
1799c774eddSJeremy L Thompson     // LCOV_EXCL_START
180*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedDataOfType");
1819c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
182*2b730f8bSJeremy L Thompson   }
1839c774eddSJeremy L Thompson 
184*2b730f8bSJeremy L Thompson   CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type));
1859c774eddSJeremy L Thompson 
1869c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1879c774eddSJeremy L Thompson }
1889c774eddSJeremy L Thompson 
1899c774eddSJeremy L Thompson /**
190777ff853SJeremy L Thompson   @brief Get the state of a CeedQFunctionContext
191777ff853SJeremy L Thompson 
192777ff853SJeremy L Thompson   @param ctx         CeedQFunctionContext to retrieve state
193777ff853SJeremy L Thompson   @param[out] state  Variable to store state
194777ff853SJeremy L Thompson 
195777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
196777ff853SJeremy L Thompson 
197777ff853SJeremy L Thompson   @ref Backend
198777ff853SJeremy L Thompson **/
199777ff853SJeremy L Thompson int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
200777ff853SJeremy L Thompson   *state = ctx->state;
201e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
202777ff853SJeremy L Thompson }
203777ff853SJeremy L Thompson 
204777ff853SJeremy L Thompson /**
205777ff853SJeremy L Thompson   @brief Get backend data of a CeedQFunctionContext
206777ff853SJeremy L Thompson 
207777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext
208777ff853SJeremy L Thompson   @param[out] data  Variable to store data
209777ff853SJeremy L Thompson 
210777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
211777ff853SJeremy L Thompson 
212777ff853SJeremy L Thompson   @ref Backend
213777ff853SJeremy L Thompson **/
214777ff853SJeremy L Thompson int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
215777ff853SJeremy L Thompson   *(void **)data = ctx->data;
216e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
217777ff853SJeremy L Thompson }
218777ff853SJeremy L Thompson 
219777ff853SJeremy L Thompson /**
220777ff853SJeremy L Thompson   @brief Set backend data of a CeedQFunctionContext
221777ff853SJeremy L Thompson 
222777ff853SJeremy L Thompson   @param[out] ctx  CeedQFunctionContext
223777ff853SJeremy L Thompson   @param data      Data to set
224777ff853SJeremy L Thompson 
225777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
226777ff853SJeremy L Thompson 
227777ff853SJeremy L Thompson   @ref Backend
228777ff853SJeremy L Thompson **/
229777ff853SJeremy L Thompson int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
230777ff853SJeremy L Thompson   ctx->data = data;
231e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
232777ff853SJeremy L Thompson }
233777ff853SJeremy L Thompson 
23434359f16Sjeremylt /**
235e6a0ab89SJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no
236e6a0ab89SJeremy L Thompson            field has been registered with this `field_name`
237e6a0ab89SJeremy L Thompson 
238e6a0ab89SJeremy L Thompson   @param[in] ctx           CeedQFunctionContext
239e6a0ab89SJeremy L Thompson   @param[in] field_name    Name of field to retrieve label
240e6a0ab89SJeremy L Thompson   @param[out] field_label  Variable to field label
241e6a0ab89SJeremy L Thompson 
242e6a0ab89SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
243e6a0ab89SJeremy L Thompson 
2443e1e85abSJeremy L Thompson   @ref Backend
245e6a0ab89SJeremy L Thompson **/
246*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) {
247e6a0ab89SJeremy L Thompson   CeedInt field_index;
248*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
249e6a0ab89SJeremy L Thompson 
250e6a0ab89SJeremy L Thompson   if (field_index != -1) {
251e6a0ab89SJeremy L Thompson     *field_label = ctx->field_labels[field_index];
252e6a0ab89SJeremy L Thompson   } else {
253e6a0ab89SJeremy L Thompson     *field_label = NULL;
254e6a0ab89SJeremy L Thompson   }
255e6a0ab89SJeremy L Thompson 
256e6a0ab89SJeremy L Thompson   return CEED_ERROR_SUCCESS;
257e6a0ab89SJeremy L Thompson }
258e6a0ab89SJeremy L Thompson 
259e6a0ab89SJeremy L Thompson /**
260d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field
261d8dd9a91SJeremy L Thompson 
262d8dd9a91SJeremy L Thompson   @param ctx         CeedQFunctionContext
2633668ca4bSJeremy L Thompson   @param field_label Label of field to set
264d8dd9a91SJeremy L Thompson   @param field_type  Type of field to set
265d8dd9a91SJeremy L Thompson   @param value       Value to set
266d8dd9a91SJeremy L Thompson 
267d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
268d8dd9a91SJeremy L Thompson 
2693e1e85abSJeremy L Thompson   @ref Backend
270d8dd9a91SJeremy L Thompson **/
271*2b730f8bSJeremy L Thompson int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *value) {
2723668ca4bSJeremy L Thompson   // Check field type
273*2b730f8bSJeremy L Thompson   if (field_label->type != field_type) {
274d8dd9a91SJeremy L Thompson     // LCOV_EXCL_START
275*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s",
276*2b730f8bSJeremy L Thompson                      field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
277d8dd9a91SJeremy L Thompson     // LCOV_EXCL_STOP
278*2b730f8bSJeremy L Thompson   }
279d8dd9a91SJeremy L Thompson 
280d8dd9a91SJeremy L Thompson   char *data;
281*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data));
2823668ca4bSJeremy L Thompson   memcpy(&data[field_label->offset], value, field_label->size);
283*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
284d8dd9a91SJeremy L Thompson 
285d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
286d8dd9a91SJeremy L Thompson }
287d8dd9a91SJeremy L Thompson 
288d8dd9a91SJeremy L Thompson /**
289bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value
290bfacc300SJeremy L Thompson 
291bfacc300SJeremy L Thompson   @param ctx         CeedQFunctionContext
292bfacc300SJeremy L Thompson   @param field_label Label for field to register
293bfacc300SJeremy L Thompson   @param values      Values to set
294bfacc300SJeremy L Thompson 
295bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
296bfacc300SJeremy L Thompson 
2973e1e85abSJeremy L Thompson   @ref Backend
298bfacc300SJeremy L Thompson **/
299*2b730f8bSJeremy L Thompson int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) {
300*2b730f8bSJeremy L Thompson   if (!field_label) {
301bfacc300SJeremy L Thompson     // LCOV_EXCL_START
302*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
303bfacc300SJeremy L Thompson     // LCOV_EXCL_STOP
304*2b730f8bSJeremy L Thompson   }
305bfacc300SJeremy L Thompson 
306*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
307bfacc300SJeremy L Thompson 
308bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
309bfacc300SJeremy L Thompson }
310bfacc300SJeremy L Thompson 
311bfacc300SJeremy L Thompson /**
312bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value
313bfacc300SJeremy L Thompson 
314bfacc300SJeremy L Thompson   @param ctx         CeedQFunctionContext
315bfacc300SJeremy L Thompson   @param field_label Label for field to register
316bfacc300SJeremy L Thompson   @param values      Values to set
317bfacc300SJeremy L Thompson 
318bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
319bfacc300SJeremy L Thompson 
3203e1e85abSJeremy L Thompson   @ref Backend
321bfacc300SJeremy L Thompson **/
322*2b730f8bSJeremy L Thompson int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int *values) {
323*2b730f8bSJeremy L Thompson   if (!field_label) {
324bfacc300SJeremy L Thompson     // LCOV_EXCL_START
325*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
326bfacc300SJeremy L Thompson     // LCOV_EXCL_STOP
327*2b730f8bSJeremy L Thompson   }
328bfacc300SJeremy L Thompson 
329*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
330bfacc300SJeremy L Thompson 
331bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
332bfacc300SJeremy L Thompson }
333bfacc300SJeremy L Thompson 
334bfacc300SJeremy L Thompson /**
3352e64a2b9SJeremy L Thompson   @brief Get additional destroy routine for CeedQFunctionContext user data
3362e64a2b9SJeremy L Thompson 
3372e64a2b9SJeremy L Thompson   @param[in] ctx          CeedQFunctionContext to get user destroy function
3382e64a2b9SJeremy L Thompson   @param[out] f_mem_type  Memory type to use when passing data into `f`
3392e64a2b9SJeremy L Thompson   @param[out] f           Additional routine to use to destroy user data
3402e64a2b9SJeremy L Thompson 
3412e64a2b9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3422e64a2b9SJeremy L Thompson 
3432e64a2b9SJeremy L Thompson   @ref Backend
3442e64a2b9SJeremy L Thompson **/
345*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) {
3462e64a2b9SJeremy L Thompson   if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type;
3472e64a2b9SJeremy L Thompson   if (f) *f = ctx->data_destroy_function;
3482e64a2b9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3492e64a2b9SJeremy L Thompson }
3502e64a2b9SJeremy L Thompson 
3512e64a2b9SJeremy L Thompson /**
35234359f16Sjeremylt   @brief Increment the reference counter for a CeedQFunctionContext
35334359f16Sjeremylt 
35434359f16Sjeremylt   @param ctx  CeedQFunctionContext to increment the reference counter
35534359f16Sjeremylt 
35634359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
35734359f16Sjeremylt 
35834359f16Sjeremylt   @ref Backend
35934359f16Sjeremylt **/
3609560d06aSjeremylt int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
36134359f16Sjeremylt   ctx->ref_count++;
36234359f16Sjeremylt   return CEED_ERROR_SUCCESS;
36334359f16Sjeremylt }
36434359f16Sjeremylt 
365777ff853SJeremy L Thompson /// @}
366777ff853SJeremy L Thompson 
367777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
368777ff853SJeremy L Thompson /// CeedQFunctionContext Public API
369777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
370777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionUser
371777ff853SJeremy L Thompson /// @{
372777ff853SJeremy L Thompson 
373777ff853SJeremy L Thompson /**
374777ff853SJeremy L Thompson   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
375777ff853SJeremy L Thompson 
376777ff853SJeremy L Thompson   @param ceed      A Ceed object where the CeedQFunctionContext will be created
377777ff853SJeremy L Thompson   @param[out] ctx  Address of the variable where the newly created
378777ff853SJeremy L Thompson                      CeedQFunctionContext will be stored
379777ff853SJeremy L Thompson 
380777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
381777ff853SJeremy L Thompson 
382777ff853SJeremy L Thompson   @ref User
383777ff853SJeremy L Thompson **/
384777ff853SJeremy L Thompson int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
385777ff853SJeremy L Thompson   if (!ceed->QFunctionContextCreate) {
386777ff853SJeremy L Thompson     Ceed delegate;
387*2b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context"));
388777ff853SJeremy L Thompson 
389*2b730f8bSJeremy L Thompson     if (!delegate) {
390777ff853SJeremy L Thompson       // LCOV_EXCL_START
391*2b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextCreate");
392777ff853SJeremy L Thompson       // LCOV_EXCL_STOP
393*2b730f8bSJeremy L Thompson     }
394777ff853SJeremy L Thompson 
395*2b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextCreate(delegate, ctx));
396e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
397777ff853SJeremy L Thompson   }
398777ff853SJeremy L Thompson 
399*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, ctx));
400777ff853SJeremy L Thompson   (*ctx)->ceed = ceed;
401*2b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
402d1d35e2fSjeremylt   (*ctx)->ref_count = 1;
403*2b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionContextCreate(*ctx));
404e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
405777ff853SJeremy L Thompson }
406777ff853SJeremy L Thompson 
407777ff853SJeremy L Thompson /**
4089560d06aSjeremylt   @brief Copy the pointer to a CeedQFunctionContext. Both pointers should
4099560d06aSjeremylt            be destroyed with `CeedQFunctionContextDestroy()`;
4109560d06aSjeremylt            Note: If `*ctx_copy` is non-NULL, then it is assumed that
4119560d06aSjeremylt            `*ctx_copy` is a pointer to a CeedQFunctionContext. This
4129560d06aSjeremylt            CeedQFunctionContext will be destroyed if `*ctx_copy` is the
4139560d06aSjeremylt            only reference to this CeedQFunctionContext.
4149560d06aSjeremylt 
4159560d06aSjeremylt   @param ctx            CeedQFunctionContext to copy reference to
4169560d06aSjeremylt   @param[out] ctx_copy  Variable to store copied reference
4179560d06aSjeremylt 
4189560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
4199560d06aSjeremylt 
4209560d06aSjeremylt   @ref User
4219560d06aSjeremylt **/
422*2b730f8bSJeremy L Thompson int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) {
423*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextReference(ctx));
424*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(ctx_copy));
4259560d06aSjeremylt   *ctx_copy = ctx;
4269560d06aSjeremylt   return CEED_ERROR_SUCCESS;
4279560d06aSjeremylt }
4289560d06aSjeremylt 
4299560d06aSjeremylt /**
430777ff853SJeremy L Thompson   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated
431777ff853SJeremy L Thompson            data if applicable. The backend may copy values to a different
432777ff853SJeremy L Thompson            memtype, such as during @ref CeedQFunctionApply().
433777ff853SJeremy L Thompson            See also @ref CeedQFunctionContextTakeData().
434777ff853SJeremy L Thompson 
435777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext
436d1d35e2fSjeremylt   @param mem_type   Memory type of the data being passed
437d1d35e2fSjeremylt   @param copy_mode  Copy mode for the data
438891038deSjeremylt   @param size       Size of data, in bytes
439777ff853SJeremy L Thompson   @param data       Data to be used
440777ff853SJeremy L Thompson 
441777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
442777ff853SJeremy L Thompson 
443777ff853SJeremy L Thompson   @ref User
444777ff853SJeremy L Thompson **/
445*2b730f8bSJeremy L Thompson int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) {
446*2b730f8bSJeremy L Thompson   if (!ctx->SetData) {
447777ff853SJeremy L Thompson     // LCOV_EXCL_START
448*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData");
449777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
450*2b730f8bSJeremy L Thompson   }
451*2b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
452777ff853SJeremy L Thompson     // LCOV_EXCL_START
453*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
454777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
455*2b730f8bSJeremy L Thompson   }
456777ff853SJeremy L Thompson 
457*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(ctx));
458d1d35e2fSjeremylt   ctx->ctx_size = size;
459*2b730f8bSJeremy L Thompson   CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data));
460777ff853SJeremy L Thompson   ctx->state += 2;
461e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
462777ff853SJeremy L Thompson }
463777ff853SJeremy L Thompson 
464777ff853SJeremy L Thompson /**
465891038deSjeremylt   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
466891038deSjeremylt            The caller is responsible for managing and freeing the memory.
467891038deSjeremylt 
468891038deSjeremylt   @param ctx        CeedQFunctionContext to access
469891038deSjeremylt   @param mem_type   Memory type on which to access the data. If the backend
470891038deSjeremylt                       uses a different memory type, this will perform a copy.
471891038deSjeremylt   @param[out] data  Data on memory type mem_type
472891038deSjeremylt 
473891038deSjeremylt   @return An error code: 0 - success, otherwise - failure
474891038deSjeremylt 
475891038deSjeremylt   @ref User
476891038deSjeremylt **/
477*2b730f8bSJeremy L Thompson int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
4789c774eddSJeremy L Thompson   bool has_valid_data = true;
479*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
480*2b730f8bSJeremy L Thompson   if (!has_valid_data) {
4819c774eddSJeremy L Thompson     // LCOV_EXCL_START
482*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data");
4839c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
484*2b730f8bSJeremy L Thompson   }
4859c774eddSJeremy L Thompson 
486*2b730f8bSJeremy L Thompson   if (!ctx->TakeData) {
487891038deSjeremylt     // LCOV_EXCL_START
488*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData");
489891038deSjeremylt     // LCOV_EXCL_STOP
490*2b730f8bSJeremy L Thompson   }
491*2b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
492891038deSjeremylt     // LCOV_EXCL_START
493*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
494891038deSjeremylt     // LCOV_EXCL_STOP
495*2b730f8bSJeremy L Thompson   }
496891038deSjeremylt 
4979c774eddSJeremy L Thompson   bool has_borrowed_data_of_type = true;
498*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type));
499*2b730f8bSJeremy L Thompson   if (!has_borrowed_data_of_type) {
5009c774eddSJeremy L Thompson     // LCOV_EXCL_START
501*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no borowed %s data, must set data with CeedQFunctionContextSetData",
5029c774eddSJeremy L Thompson                      CeedMemTypes[mem_type]);
5039c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
504*2b730f8bSJeremy L Thompson   }
5059c774eddSJeremy L Thompson 
506891038deSjeremylt   void *temp_data = NULL;
507*2b730f8bSJeremy L Thompson   CeedCall(ctx->TakeData(ctx, mem_type, &temp_data));
508891038deSjeremylt   if (data) (*(void **)data) = temp_data;
509891038deSjeremylt   return CEED_ERROR_SUCCESS;
510891038deSjeremylt }
511891038deSjeremylt 
512891038deSjeremylt /**
513777ff853SJeremy L Thompson   @brief Get read/write access to a CeedQFunctionContext via the specified memory type.
514777ff853SJeremy L Thompson            Restore access with @ref CeedQFunctionContextRestoreData().
515777ff853SJeremy L Thompson 
516777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext to access
517d1d35e2fSjeremylt   @param mem_type   Memory type on which to access the data. If the backend
518777ff853SJeremy L Thompson                       uses a different memory type, this will perform a copy.
519d1d35e2fSjeremylt   @param[out] data  Data on memory type mem_type
520777ff853SJeremy L Thompson 
521777ff853SJeremy L Thompson   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions
522777ff853SJeremy L Thompson     provide access to array pointers in the desired memory space. Pairing
523777ff853SJeremy L Thompson     get/restore allows the Context to track access.
524777ff853SJeremy L Thompson 
525777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
526777ff853SJeremy L Thompson 
527777ff853SJeremy L Thompson   @ref User
528777ff853SJeremy L Thompson **/
529*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
530*2b730f8bSJeremy L Thompson   if (!ctx->GetData) {
531777ff853SJeremy L Thompson     // LCOV_EXCL_START
532*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData");
533777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
534*2b730f8bSJeremy L Thompson   }
535*2b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
536777ff853SJeremy L Thompson     // LCOV_EXCL_START
537*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
538777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
539*2b730f8bSJeremy L Thompson   }
540*2b730f8bSJeremy L Thompson   if (ctx->num_readers > 0) {
54128bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
542*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access");
54328bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
544*2b730f8bSJeremy L Thompson   }
54528bfd0b7SJeremy L Thompson 
5469c774eddSJeremy L Thompson   bool has_valid_data = true;
547*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
548*2b730f8bSJeremy L Thompson   if (!has_valid_data) {
5499c774eddSJeremy L Thompson     // LCOV_EXCL_START
550*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
5519c774eddSJeremy L Thompson     // LCOV_EXCL_STOP
552*2b730f8bSJeremy L Thompson   }
5539c774eddSJeremy L Thompson 
554*2b730f8bSJeremy L Thompson   CeedCall(ctx->GetData(ctx, mem_type, data));
55528bfd0b7SJeremy L Thompson   ctx->state++;
55628bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
55728bfd0b7SJeremy L Thompson }
55828bfd0b7SJeremy L Thompson 
55928bfd0b7SJeremy L Thompson /**
56028bfd0b7SJeremy L Thompson   @brief Get read only access to a CeedQFunctionContext via the specified memory type.
56128bfd0b7SJeremy L Thompson            Restore access with @ref CeedQFunctionContextRestoreData().
56228bfd0b7SJeremy L Thompson 
56328bfd0b7SJeremy L Thompson   @param ctx        CeedQFunctionContext to access
56428bfd0b7SJeremy L Thompson   @param mem_type   Memory type on which to access the data. If the backend
56528bfd0b7SJeremy L Thompson                       uses a different memory type, this will perform a copy.
56628bfd0b7SJeremy L Thompson   @param[out] data  Data on memory type mem_type
56728bfd0b7SJeremy L Thompson 
56828bfd0b7SJeremy L Thompson   @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead()
56928bfd0b7SJeremy L Thompson     functions provide access to array pointers in the desired memory space. Pairing
57028bfd0b7SJeremy L Thompson     get/restore allows the Context to track access.
57128bfd0b7SJeremy L Thompson 
57228bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
57328bfd0b7SJeremy L Thompson 
57428bfd0b7SJeremy L Thompson   @ref User
57528bfd0b7SJeremy L Thompson **/
576*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
577*2b730f8bSJeremy L Thompson   if (!ctx->GetDataRead) {
57828bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
579*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead");
58028bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
581*2b730f8bSJeremy L Thompson   }
582*2b730f8bSJeremy L Thompson   if (ctx->state % 2 == 1) {
58328bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
584*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
58528bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
586*2b730f8bSJeremy L Thompson   }
58728bfd0b7SJeremy L Thompson 
58828bfd0b7SJeremy L Thompson   bool has_valid_data = true;
589*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
590*2b730f8bSJeremy L Thompson   if (!has_valid_data) {
59128bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
592*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
59328bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
594*2b730f8bSJeremy L Thompson   }
59528bfd0b7SJeremy L Thompson 
596*2b730f8bSJeremy L Thompson   CeedCall(ctx->GetDataRead(ctx, mem_type, data));
59728bfd0b7SJeremy L Thompson   ctx->num_readers++;
598e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
599777ff853SJeremy L Thompson }
600777ff853SJeremy L Thompson 
601777ff853SJeremy L Thompson /**
602777ff853SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
603777ff853SJeremy L Thompson 
604777ff853SJeremy L Thompson   @param ctx   CeedQFunctionContext to restore
605777ff853SJeremy L Thompson   @param data  Data to restore
606777ff853SJeremy L Thompson 
607777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
608777ff853SJeremy L Thompson 
609777ff853SJeremy L Thompson   @ref User
610777ff853SJeremy L Thompson **/
611777ff853SJeremy L Thompson int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
612*2b730f8bSJeremy L Thompson   if (ctx->state % 2 != 1) {
613777ff853SJeremy L Thompson     // LCOV_EXCL_START
614*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
615777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
616*2b730f8bSJeremy L Thompson   }
617777ff853SJeremy L Thompson 
618706efda3SJeremy L Thompson   if (ctx->RestoreData) {
619*2b730f8bSJeremy L Thompson     CeedCall(ctx->RestoreData(ctx));
620706efda3SJeremy L Thompson   }
621777ff853SJeremy L Thompson   *(void **)data = NULL;
62228bfd0b7SJeremy L Thompson   ctx->state++;
62328bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
62428bfd0b7SJeremy L Thompson }
62528bfd0b7SJeremy L Thompson 
62628bfd0b7SJeremy L Thompson /**
62728bfd0b7SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead()
62828bfd0b7SJeremy L Thompson 
62928bfd0b7SJeremy L Thompson   @param ctx   CeedQFunctionContext to restore
63028bfd0b7SJeremy L Thompson   @param data  Data to restore
63128bfd0b7SJeremy L Thompson 
63228bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
63328bfd0b7SJeremy L Thompson 
63428bfd0b7SJeremy L Thompson   @ref User
63528bfd0b7SJeremy L Thompson **/
63628bfd0b7SJeremy L Thompson int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) {
637*2b730f8bSJeremy L Thompson   if (ctx->num_readers == 0) {
63828bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
639*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
64028bfd0b7SJeremy L Thompson     // LCOV_EXCL_STOP
641*2b730f8bSJeremy L Thompson   }
64228bfd0b7SJeremy L Thompson 
64375a19770SJeremy L Thompson   ctx->num_readers--;
64475a19770SJeremy L Thompson   if (ctx->num_readers == 0 && ctx->RestoreDataRead) {
645*2b730f8bSJeremy L Thompson     CeedCall(ctx->RestoreDataRead(ctx));
64628bfd0b7SJeremy L Thompson   }
64728bfd0b7SJeremy L Thompson   *(void **)data = NULL;
64875a19770SJeremy L Thompson 
649e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
650777ff853SJeremy L Thompson }
651777ff853SJeremy L Thompson 
652777ff853SJeremy L Thompson /**
653cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a double precision value
654cdf32b93SJeremy L Thompson 
655cdf32b93SJeremy L Thompson   @param ctx               CeedQFunctionContext
656cdf32b93SJeremy L Thompson   @param field_name        Name of field to register
657cdf32b93SJeremy L Thompson   @param field_offset      Offset of field to register
6587bfe0f0eSJeremy L Thompson   @param num_values        Number of values to register, must be contiguous in memory
659cdf32b93SJeremy L Thompson   @param field_description Description of field, or NULL for none
660cdf32b93SJeremy L Thompson 
661cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
662cdf32b93SJeremy L Thompson 
663cdf32b93SJeremy L Thompson   @ref User
664cdf32b93SJeremy L Thompson **/
665*2b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
666cdf32b93SJeremy L Thompson                                        const char *field_description) {
667*2b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values);
668cdf32b93SJeremy L Thompson }
669cdf32b93SJeremy L Thompson 
670cdf32b93SJeremy L Thompson /**
671cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a int32 value
672cdf32b93SJeremy L Thompson 
673cdf32b93SJeremy L Thompson   @param ctx               CeedQFunctionContext
674cdf32b93SJeremy L Thompson   @param field_name        Name of field to register
675cdf32b93SJeremy L Thompson   @param field_offset      Offset of field to register
6767bfe0f0eSJeremy L Thompson   @param num_values        Number of values to register, must be contiguous in memory
677cdf32b93SJeremy L Thompson   @param field_description Description of field, or NULL for none
678cdf32b93SJeremy L Thompson 
679cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
680cdf32b93SJeremy L Thompson 
681cdf32b93SJeremy L Thompson   @ref User
682cdf32b93SJeremy L Thompson **/
683*2b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
684cdf32b93SJeremy L Thompson                                       const char *field_description) {
685*2b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values);
686cdf32b93SJeremy L Thompson }
687cdf32b93SJeremy L Thompson 
688cdf32b93SJeremy L Thompson /**
6893668ca4bSJeremy L Thompson   @brief Get labels for all registered QFunctionContext fields
690cdf32b93SJeremy L Thompson 
691cdf32b93SJeremy L Thompson   @param ctx                CeedQFunctionContext
6923668ca4bSJeremy L Thompson   @param[out] field_labels  Variable to hold array of field labels
693cdf32b93SJeremy L Thompson   @param[out] num_fields    Length of field descriptions array
694cdf32b93SJeremy L Thompson 
695cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
696cdf32b93SJeremy L Thompson 
697cdf32b93SJeremy L Thompson   @ref User
698cdf32b93SJeremy L Thompson **/
699*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
7003668ca4bSJeremy L Thompson   *field_labels = ctx->field_labels;
701cdf32b93SJeremy L Thompson   *num_fields   = ctx->num_fields;
702cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
703cdf32b93SJeremy L Thompson }
704cdf32b93SJeremy L Thompson 
705cdf32b93SJeremy L Thompson /**
7060f86cbe7SJeremy L Thompson   @brief Get the descriptive information about a CeedContextFieldLabel
7070f86cbe7SJeremy L Thompson 
7080f86cbe7SJeremy L Thompson   @param[in] label              CeedContextFieldLabel
7090f86cbe7SJeremy L Thompson   @param[out] field_name        Name of labeled field
7100f86cbe7SJeremy L Thompson   @param[out] field_description Description of field, or NULL for none
7117bfe0f0eSJeremy L Thompson   @param[out] num_values        Number of values registered
7120f86cbe7SJeremy L Thompson   @param[out] field_type        CeedContextFieldType
7130f86cbe7SJeremy L Thompson 
7140f86cbe7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7150f86cbe7SJeremy L Thompson 
7160f86cbe7SJeremy L Thompson   @ref User
7170f86cbe7SJeremy L Thompson **/
718*2b730f8bSJeremy L Thompson int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values,
7190f86cbe7SJeremy L Thompson                                         CeedContextFieldType *field_type) {
7200f86cbe7SJeremy L Thompson   if (field_name) *field_name = label->name;
7210f86cbe7SJeremy L Thompson   if (field_description) *field_description = label->description;
7227bfe0f0eSJeremy L Thompson   if (num_values) *num_values = label->num_values;
7230f86cbe7SJeremy L Thompson   if (field_type) *field_type = label->type;
7240f86cbe7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7250f86cbe7SJeremy L Thompson }
7260f86cbe7SJeremy L Thompson 
7270f86cbe7SJeremy L Thompson /**
72880a9ef05SNatalie Beams   @brief Get data size for a Context
72980a9ef05SNatalie Beams 
73080a9ef05SNatalie Beams   @param ctx            CeedQFunctionContext
73180a9ef05SNatalie Beams   @param[out] ctx_size  Variable to store size of context data values
73280a9ef05SNatalie Beams 
73380a9ef05SNatalie Beams   @return An error code: 0 - success, otherwise - failure
73480a9ef05SNatalie Beams 
73580a9ef05SNatalie Beams   @ref User
73680a9ef05SNatalie Beams **/
737*2b730f8bSJeremy L Thompson int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) {
73880a9ef05SNatalie Beams   *ctx_size = ctx->ctx_size;
73980a9ef05SNatalie Beams   return CEED_ERROR_SUCCESS;
74080a9ef05SNatalie Beams }
74180a9ef05SNatalie Beams 
74280a9ef05SNatalie Beams /**
743777ff853SJeremy L Thompson   @brief View a CeedQFunctionContext
744777ff853SJeremy L Thompson 
745777ff853SJeremy L Thompson   @param[in] ctx     CeedQFunctionContext to view
746777ff853SJeremy L Thompson   @param[in] stream  Filestream to write to
747777ff853SJeremy L Thompson 
748777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
749777ff853SJeremy L Thompson 
750777ff853SJeremy L Thompson   @ref User
751777ff853SJeremy L Thompson **/
752777ff853SJeremy L Thompson int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
753777ff853SJeremy L Thompson   fprintf(stream, "CeedQFunctionContext\n");
754d1d35e2fSjeremylt   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
7553668ca4bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
7563668ca4bSJeremy L Thompson     // LCOV_EXCL_START
757*2b730f8bSJeremy L Thompson     fprintf(stream, "  Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name);
7583668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
7593668ca4bSJeremy L Thompson   }
760e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
761777ff853SJeremy L Thompson }
762777ff853SJeremy L Thompson 
763777ff853SJeremy L Thompson /**
7642790b72bSJeremy L Thompson   @brief Set additional destroy routine for CeedQFunctionContext user data
7652790b72bSJeremy L Thompson 
7662e64a2b9SJeremy L Thompson   @param[in] ctx         CeedQFunctionContext to set user destroy function
7672e64a2b9SJeremy L Thompson   @param[in] f_mem_type  Memory type to use when passing data into `f`
7682e64a2b9SJeremy L Thompson   @param[in] f           Additional routine to use to destroy user data
7692790b72bSJeremy L Thompson 
7702790b72bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7712790b72bSJeremy L Thompson 
7722790b72bSJeremy L Thompson   @ref User
7732790b72bSJeremy L Thompson **/
774*2b730f8bSJeremy L Thompson int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) {
775*2b730f8bSJeremy L Thompson   if (!f) {
7762790b72bSJeremy L Thompson     // LCOV_EXCL_START
777*2b730f8bSJeremy L Thompson     return CeedError(ctx->ceed, 1, "Must provide valid callback function for destroying user data");
7782790b72bSJeremy L Thompson     // LCOV_EXCL_STOP
779*2b730f8bSJeremy L Thompson   }
7802790b72bSJeremy L Thompson   ctx->data_destroy_mem_type = f_mem_type;
7812790b72bSJeremy L Thompson   ctx->data_destroy_function = f;
7822790b72bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
7832790b72bSJeremy L Thompson }
7842790b72bSJeremy L Thompson 
7852790b72bSJeremy L Thompson /**
786777ff853SJeremy L Thompson   @brief Destroy a CeedQFunctionContext
787777ff853SJeremy L Thompson 
788777ff853SJeremy L Thompson   @param ctx  CeedQFunctionContext to destroy
789777ff853SJeremy L Thompson 
790777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
791777ff853SJeremy L Thompson 
792777ff853SJeremy L Thompson   @ref User
793777ff853SJeremy L Thompson **/
794777ff853SJeremy L Thompson int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
795*2b730f8bSJeremy L Thompson   if (!*ctx || --(*ctx)->ref_count > 0) return CEED_ERROR_SUCCESS;
796777ff853SJeremy L Thompson 
797*2b730f8bSJeremy L Thompson   if ((*ctx) && ((*ctx)->state % 2) == 1) {
798777ff853SJeremy L Thompson     // LCOV_EXCL_START
799*2b730f8bSJeremy L Thompson     return CeedError((*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use");
800777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
801*2b730f8bSJeremy L Thompson   }
802777ff853SJeremy L Thompson 
803*2b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(*ctx));
804*2b730f8bSJeremy L Thompson   if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx));
805cdf32b93SJeremy L Thompson   for (CeedInt i = 0; i < (*ctx)->num_fields; i++) {
806*2b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->name));
807*2b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->description));
808*2b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]));
809cdf32b93SJeremy L Thompson   }
810*2b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ctx)->field_labels));
811*2b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*ctx)->ceed));
812*2b730f8bSJeremy L Thompson   CeedCall(CeedFree(ctx));
813cdf32b93SJeremy L Thompson 
814e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
815777ff853SJeremy L Thompson }
816777ff853SJeremy L Thompson 
817777ff853SJeremy L Thompson /// @}
818