xref: /libCEED/interface/ceed-qfunctioncontext.c (revision 75a19770cda24d00f4da8d6890f256f14dd4565b)
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 
8ec3da8bcSJed Brown #include <ceed/ceed.h>
9ec3da8bcSJed Brown #include <ceed/backend.h>
103d576824SJeremy L Thompson #include <ceed-impl.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 **/
35cdf32b93SJeremy L Thompson int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx,
36cdf32b93SJeremy L Thompson                                       const char *field_name, CeedInt *field_index) {
37cdf32b93SJeremy L Thompson   *field_index = -1;
38cdf32b93SJeremy L Thompson   for (CeedInt i=0; i<ctx->num_fields; i++)
393668ca4bSJeremy L Thompson     if (!strcmp(ctx->field_labels[i]->name, field_name))
40cdf32b93SJeremy L Thompson       *field_index = i;
41cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
42cdf32b93SJeremy L Thompson }
43cdf32b93SJeremy L Thompson 
44cdf32b93SJeremy L Thompson /**
45cdf32b93SJeremy L Thompson   @brief Common function for registering QFunctionContext fields
46cdf32b93SJeremy L Thompson 
47cdf32b93SJeremy L Thompson   @param ctx               CeedQFunctionContext
48cdf32b93SJeremy L Thompson   @param field_name        Name of field to register
49cdf32b93SJeremy L Thompson   @param field_offset      Offset of field to register
50cdf32b93SJeremy L Thompson   @param field_description Description of field, or NULL for none
51cdf32b93SJeremy L Thompson   @param field_type        Field data type, such as double or int32
52cdf32b93SJeremy L Thompson   @param field_size        Size of field, in bytes
537bfe0f0eSJeremy L Thompson   @param num_values        Number of values to register, must be contiguous in memory
54cdf32b93SJeremy L Thompson 
55cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
56cdf32b93SJeremy L Thompson 
57cdf32b93SJeremy L Thompson   @ref Developer
58cdf32b93SJeremy L Thompson **/
59cdf32b93SJeremy L Thompson int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx,
60cdf32b93SJeremy L Thompson                                         const char *field_name, size_t field_offset,
61cdf32b93SJeremy L Thompson                                         const char *field_description,
62cdf32b93SJeremy L Thompson                                         CeedContextFieldType field_type,
637bfe0f0eSJeremy L Thompson                                         size_t field_size, size_t num_values) {
64cdf32b93SJeremy L Thompson   int ierr;
65cdf32b93SJeremy L Thompson 
66cdf32b93SJeremy L Thompson   // Check for duplicate
67cdf32b93SJeremy L Thompson   CeedInt field_index = -1;
68cdf32b93SJeremy L Thompson   ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index);
69cdf32b93SJeremy L Thompson   CeedChk(ierr);
70cdf32b93SJeremy L Thompson   if (field_index != -1)
71cdf32b93SJeremy L Thompson     // LCOV_EXCL_START
72cdf32b93SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
73cdf32b93SJeremy L Thompson                      "QFunctionContext field with name \"%s\" already registered",
74cdf32b93SJeremy L Thompson                      field_name);
75cdf32b93SJeremy L Thompson   // LCOV_EXCL_STOP
76cdf32b93SJeremy L Thompson 
77cdf32b93SJeremy L Thompson   // Allocate space for field data
78cdf32b93SJeremy L Thompson   if (ctx->num_fields == 0) {
793668ca4bSJeremy L Thompson     ierr = CeedCalloc(1, &ctx->field_labels); CeedChk(ierr);
80cdf32b93SJeremy L Thompson     ctx->max_fields = 1;
81cdf32b93SJeremy L Thompson   } else if (ctx->num_fields == ctx->max_fields) {
823668ca4bSJeremy L Thompson     ierr = CeedRealloc(2*ctx->max_fields, &ctx->field_labels);
83cdf32b93SJeremy L Thompson     CeedChk(ierr);
84cdf32b93SJeremy L Thompson     ctx->max_fields *= 2;
85cdf32b93SJeremy L Thompson   }
863668ca4bSJeremy L Thompson   ierr = CeedCalloc(1, &ctx->field_labels[ctx->num_fields]); CeedChk(ierr);
87cdf32b93SJeremy L Thompson 
88cdf32b93SJeremy L Thompson   // Copy field data
89f7e22acaSJeremy L Thompson   ierr = CeedStringAllocCopy(field_name,
903668ca4bSJeremy L Thompson                              (char **)&ctx->field_labels[ctx->num_fields]->name);
91f7e22acaSJeremy L Thompson   CeedChk(ierr);
92f7e22acaSJeremy L Thompson   ierr = CeedStringAllocCopy(field_description,
933668ca4bSJeremy L Thompson                              (char **)&ctx->field_labels[ctx->num_fields]->description);
94f7e22acaSJeremy L Thompson   CeedChk(ierr);
953668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->type = field_type;
963668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->offset = field_offset;
977bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->size = field_size * num_values;
987bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->num_values = num_values;
99cdf32b93SJeremy L Thompson   ctx->num_fields++;
100cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
101cdf32b93SJeremy L Thompson }
102cdf32b93SJeremy L Thompson 
1033b190ab8SJeremy L Thompson /**
1043b190ab8SJeremy L Thompson   @brief Destroy user data held by CeedQFunctionContext, using function set by
1053b190ab8SJeremy L Thompson      CeedQFunctionContextSetDataDestroy, if applicable
1063b190ab8SJeremy L Thompson 
1073b190ab8SJeremy L Thompson   @param[in,out] ctx  CeedQFunctionContext to destroy user data
1083b190ab8SJeremy L Thompson 
1093b190ab8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1103b190ab8SJeremy L Thompson 
1113b190ab8SJeremy L Thompson   @ref Developer
1123b190ab8SJeremy L Thompson **/
1133b190ab8SJeremy L Thompson static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) {
1143b190ab8SJeremy L Thompson   int ierr;
1153b190ab8SJeremy L Thompson 
1163b190ab8SJeremy L Thompson   if (ctx->DataDestroy) {
1173b190ab8SJeremy L Thompson     ierr = ctx->DataDestroy(ctx); CeedChk(ierr);
1183b190ab8SJeremy L Thompson   } else {
1193b190ab8SJeremy L Thompson     CeedQFunctionContextDataDestroyUser data_destroy_function;
1203b190ab8SJeremy L Thompson     CeedMemType data_destroy_mem_type;
1213b190ab8SJeremy L Thompson 
1223b190ab8SJeremy L Thompson     ierr = CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type,
1233b190ab8SJeremy L Thompson            &data_destroy_function); CeedChk(ierr);
1243b190ab8SJeremy L Thompson     if (data_destroy_function) {
1253b190ab8SJeremy L Thompson       void *data;
1263b190ab8SJeremy L Thompson 
1273b190ab8SJeremy L Thompson       ierr = CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data);
1283b190ab8SJeremy L Thompson       CeedChk(ierr);
1293b190ab8SJeremy L Thompson       ierr = data_destroy_function(data); CeedChk(ierr);
1303b190ab8SJeremy L Thompson       ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr);
1313b190ab8SJeremy L Thompson     }
1323b190ab8SJeremy L Thompson   }
1333b190ab8SJeremy L Thompson 
1343b190ab8SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1353b190ab8SJeremy L Thompson }
1363b190ab8SJeremy L Thompson 
137cdf32b93SJeremy L Thompson /// @}
138cdf32b93SJeremy L Thompson 
139cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
140777ff853SJeremy L Thompson /// CeedQFunctionContext Backend API
141777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
142777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionBackend
143777ff853SJeremy L Thompson /// @{
144777ff853SJeremy L Thompson 
145777ff853SJeremy L Thompson /**
146777ff853SJeremy L Thompson   @brief Get the Ceed associated with a CeedQFunctionContext
147777ff853SJeremy L Thompson 
148777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext
149777ff853SJeremy L Thompson   @param[out] ceed  Variable to store Ceed
150777ff853SJeremy L Thompson 
151777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
152777ff853SJeremy L Thompson 
153777ff853SJeremy L Thompson   @ref Backend
154777ff853SJeremy L Thompson **/
155777ff853SJeremy L Thompson int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) {
156777ff853SJeremy L Thompson   *ceed = ctx->ceed;
157e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
158777ff853SJeremy L Thompson }
159777ff853SJeremy L Thompson 
160777ff853SJeremy L Thompson /**
1619c774eddSJeremy L Thompson   @brief Check for valid data in a CeedQFunctionContext
1629c774eddSJeremy L Thompson 
1639c774eddSJeremy L Thompson   @param ctx                  CeedQFunctionContext to check validity
1649c774eddSJeremy L Thompson   @param[out] has_valid_data  Variable to store validity
1659c774eddSJeremy L Thompson 
1669c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1679c774eddSJeremy L Thompson 
1689c774eddSJeremy L Thompson   @ref Backend
1699c774eddSJeremy L Thompson **/
1709c774eddSJeremy L Thompson int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx,
1719c774eddSJeremy L Thompson                                      bool *has_valid_data) {
1729c774eddSJeremy L Thompson   int ierr;
1739c774eddSJeremy L Thompson 
1749c774eddSJeremy L Thompson   if (!ctx->HasValidData)
1759c774eddSJeremy L Thompson     // LCOV_EXCL_START
1769c774eddSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
1779c774eddSJeremy L Thompson                      "Backend does not support HasValidData");
1789c774eddSJeremy L Thompson   // LCOV_EXCL_STOP
1799c774eddSJeremy L Thompson 
1809c774eddSJeremy L Thompson   ierr = ctx->HasValidData(ctx, has_valid_data); CeedChk(ierr);
1819c774eddSJeremy L Thompson 
1829c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1839c774eddSJeremy L Thompson }
1849c774eddSJeremy L Thompson 
1859c774eddSJeremy L Thompson /**
1869c774eddSJeremy L Thompson   @brief Check for borrowed data of a specific CeedMemType in a
1879c774eddSJeremy L Thompson            CeedQFunctionContext
1889c774eddSJeremy L Thompson 
1899c774eddSJeremy L Thompson   @param ctx                             CeedQFunctionContext to check
1909c774eddSJeremy L Thompson   @param mem_type                        Memory type to check
1919c774eddSJeremy L Thompson   @param[out] has_borrowed_data_of_type  Variable to store result
1929c774eddSJeremy L Thompson 
1939c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1949c774eddSJeremy L Thompson 
1959c774eddSJeremy L Thompson   @ref Backend
1969c774eddSJeremy L Thompson **/
1979c774eddSJeremy L Thompson int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx,
1989c774eddSJeremy L Thompson     CeedMemType mem_type, bool *has_borrowed_data_of_type) {
1999c774eddSJeremy L Thompson   int ierr;
2009c774eddSJeremy L Thompson 
2019c774eddSJeremy L Thompson   if (!ctx->HasBorrowedDataOfType)
2029c774eddSJeremy L Thompson     // LCOV_EXCL_START
2039c774eddSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
2049c774eddSJeremy L Thompson                      "Backend does not support HasBorrowedDataOfType");
2059c774eddSJeremy L Thompson   // LCOV_EXCL_STOP
2069c774eddSJeremy L Thompson 
2079c774eddSJeremy L Thompson   ierr = ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type);
2089c774eddSJeremy L Thompson   CeedChk(ierr);
2099c774eddSJeremy L Thompson 
2109c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
2119c774eddSJeremy L Thompson }
2129c774eddSJeremy L Thompson 
2139c774eddSJeremy L Thompson /**
214777ff853SJeremy L Thompson   @brief Get the state of a CeedQFunctionContext
215777ff853SJeremy L Thompson 
216777ff853SJeremy L Thompson   @param ctx         CeedQFunctionContext to retrieve state
217777ff853SJeremy L Thompson   @param[out] state  Variable to store state
218777ff853SJeremy L Thompson 
219777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
220777ff853SJeremy L Thompson 
221777ff853SJeremy L Thompson   @ref Backend
222777ff853SJeremy L Thompson **/
223777ff853SJeremy L Thompson int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
224777ff853SJeremy L Thompson   *state = ctx->state;
225e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
226777ff853SJeremy L Thompson }
227777ff853SJeremy L Thompson 
228777ff853SJeremy L Thompson /**
229777ff853SJeremy L Thompson   @brief Get backend data of a CeedQFunctionContext
230777ff853SJeremy L Thompson 
231777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext
232777ff853SJeremy L Thompson   @param[out] data  Variable to store data
233777ff853SJeremy L Thompson 
234777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
235777ff853SJeremy L Thompson 
236777ff853SJeremy L Thompson   @ref Backend
237777ff853SJeremy L Thompson **/
238777ff853SJeremy L Thompson int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
239777ff853SJeremy L Thompson   *(void **)data = ctx->data;
240e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
241777ff853SJeremy L Thompson }
242777ff853SJeremy L Thompson 
243777ff853SJeremy L Thompson /**
244777ff853SJeremy L Thompson   @brief Set backend data of a CeedQFunctionContext
245777ff853SJeremy L Thompson 
246777ff853SJeremy L Thompson   @param[out] ctx  CeedQFunctionContext
247777ff853SJeremy L Thompson   @param data      Data to set
248777ff853SJeremy L Thompson 
249777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
250777ff853SJeremy L Thompson 
251777ff853SJeremy L Thompson   @ref Backend
252777ff853SJeremy L Thompson **/
253777ff853SJeremy L Thompson int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
254777ff853SJeremy L Thompson   ctx->data = data;
255e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
256777ff853SJeremy L Thompson }
257777ff853SJeremy L Thompson 
25834359f16Sjeremylt /**
259e6a0ab89SJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no
260e6a0ab89SJeremy L Thompson            field has been registered with this `field_name`
261e6a0ab89SJeremy L Thompson 
262e6a0ab89SJeremy L Thompson   @param[in] ctx           CeedQFunctionContext
263e6a0ab89SJeremy L Thompson   @param[in] field_name    Name of field to retrieve label
264e6a0ab89SJeremy L Thompson   @param[out] field_label  Variable to field label
265e6a0ab89SJeremy L Thompson 
266e6a0ab89SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
267e6a0ab89SJeremy L Thompson 
2683e1e85abSJeremy L Thompson   @ref Backend
269e6a0ab89SJeremy L Thompson **/
270e6a0ab89SJeremy L Thompson int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx,
271e6a0ab89SJeremy L Thompson                                       const char *field_name,
272e6a0ab89SJeremy L Thompson                                       CeedContextFieldLabel *field_label) {
273e6a0ab89SJeremy L Thompson   int ierr;
274e6a0ab89SJeremy L Thompson 
275e6a0ab89SJeremy L Thompson   CeedInt field_index;
276e6a0ab89SJeremy L Thompson   ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index);
277e6a0ab89SJeremy L Thompson   CeedChk(ierr);
278e6a0ab89SJeremy L Thompson 
279e6a0ab89SJeremy L Thompson   if (field_index != -1) {
280e6a0ab89SJeremy L Thompson     *field_label = ctx->field_labels[field_index];
281e6a0ab89SJeremy L Thompson   } else {
282e6a0ab89SJeremy L Thompson     *field_label = NULL;
283e6a0ab89SJeremy L Thompson   }
284e6a0ab89SJeremy L Thompson 
285e6a0ab89SJeremy L Thompson   return CEED_ERROR_SUCCESS;
286e6a0ab89SJeremy L Thompson }
287e6a0ab89SJeremy L Thompson 
288e6a0ab89SJeremy L Thompson /**
289d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field
290d8dd9a91SJeremy L Thompson 
291d8dd9a91SJeremy L Thompson   @param ctx         CeedQFunctionContext
2923668ca4bSJeremy L Thompson   @param field_label Label of field to set
293d8dd9a91SJeremy L Thompson   @param field_type  Type of field to set
294d8dd9a91SJeremy L Thompson   @param value       Value to set
295d8dd9a91SJeremy L Thompson 
296d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
297d8dd9a91SJeremy L Thompson 
2983e1e85abSJeremy L Thompson   @ref Backend
299d8dd9a91SJeremy L Thompson **/
300d8dd9a91SJeremy L Thompson int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx,
3013668ca4bSJeremy L Thompson                                    CeedContextFieldLabel field_label,
302d8dd9a91SJeremy L Thompson                                    CeedContextFieldType field_type,
3033668ca4bSJeremy L Thompson                                    void *value) {
304d8dd9a91SJeremy L Thompson   int ierr;
305d8dd9a91SJeremy L Thompson 
3063668ca4bSJeremy L Thompson   // Check field type
3073668ca4bSJeremy L Thompson   if (field_label->type != field_type)
308d8dd9a91SJeremy L Thompson     // LCOV_EXCL_START
309d8dd9a91SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
310d8dd9a91SJeremy L Thompson                      "QFunctionContext field with name \"%s\" registered as %s, "
3113668ca4bSJeremy L Thompson                      "not registered as %s", field_label->name,
3123668ca4bSJeremy L Thompson                      CeedContextFieldTypes[field_label->type],
313d8dd9a91SJeremy L Thompson                      CeedContextFieldTypes[field_type]);
314d8dd9a91SJeremy L Thompson   // LCOV_EXCL_STOP
315d8dd9a91SJeremy L Thompson 
316d8dd9a91SJeremy L Thompson   char *data;
317d8dd9a91SJeremy L Thompson   ierr = CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data); CeedChk(ierr);
3183668ca4bSJeremy L Thompson   memcpy(&data[field_label->offset], value, field_label->size);
319d8dd9a91SJeremy L Thompson   ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr);
320d8dd9a91SJeremy L Thompson 
321d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
322d8dd9a91SJeremy L Thompson }
323d8dd9a91SJeremy L Thompson 
324d8dd9a91SJeremy L Thompson /**
325bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value
326bfacc300SJeremy L Thompson 
327bfacc300SJeremy L Thompson   @param ctx         CeedQFunctionContext
328bfacc300SJeremy L Thompson   @param field_label Label for field to register
329bfacc300SJeremy L Thompson   @param values      Values to set
330bfacc300SJeremy L Thompson 
331bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
332bfacc300SJeremy L Thompson 
3333e1e85abSJeremy L Thompson   @ref Backend
334bfacc300SJeremy L Thompson **/
335bfacc300SJeremy L Thompson int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx,
336bfacc300SJeremy L Thompson                                   CeedContextFieldLabel field_label, double *values) {
337bfacc300SJeremy L Thompson   int ierr;
338bfacc300SJeremy L Thompson 
339bfacc300SJeremy L Thompson   if (!field_label)
340bfacc300SJeremy L Thompson     // LCOV_EXCL_START
341bfacc300SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
342bfacc300SJeremy L Thompson                      "Invalid field label");
343bfacc300SJeremy L Thompson   // LCOV_EXCL_STOP
344bfacc300SJeremy L Thompson 
345bfacc300SJeremy L Thompson   ierr = CeedQFunctionContextSetGeneric(ctx, field_label,
346bfacc300SJeremy L Thompson                                         CEED_CONTEXT_FIELD_DOUBLE,
347bfacc300SJeremy L Thompson                                         values); CeedChk(ierr);
348bfacc300SJeremy L Thompson 
349bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
350bfacc300SJeremy L Thompson }
351bfacc300SJeremy L Thompson 
352bfacc300SJeremy L Thompson /**
353bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value
354bfacc300SJeremy L Thompson 
355bfacc300SJeremy L Thompson   @param ctx         CeedQFunctionContext
356bfacc300SJeremy L Thompson   @param field_label Label for field to register
357bfacc300SJeremy L Thompson   @param values      Values to set
358bfacc300SJeremy L Thompson 
359bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
360bfacc300SJeremy L Thompson 
3613e1e85abSJeremy L Thompson   @ref Backend
362bfacc300SJeremy L Thompson **/
363bfacc300SJeremy L Thompson int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx,
364bfacc300SJeremy L Thompson                                  CeedContextFieldLabel field_label, int *values) {
365bfacc300SJeremy L Thompson   int ierr;
366bfacc300SJeremy L Thompson 
367bfacc300SJeremy L Thompson   if (!field_label)
368bfacc300SJeremy L Thompson     // LCOV_EXCL_START
369bfacc300SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
370bfacc300SJeremy L Thompson                      "Invalid field label");
371bfacc300SJeremy L Thompson   // LCOV_EXCL_STOP
372bfacc300SJeremy L Thompson 
373bfacc300SJeremy L Thompson   ierr = CeedQFunctionContextSetGeneric(ctx, field_label,
374bfacc300SJeremy L Thompson                                         CEED_CONTEXT_FIELD_INT32,
375bfacc300SJeremy L Thompson                                         values); CeedChk(ierr);
376bfacc300SJeremy L Thompson 
377bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
378bfacc300SJeremy L Thompson }
379bfacc300SJeremy L Thompson 
380bfacc300SJeremy L Thompson /**
3812e64a2b9SJeremy L Thompson   @brief Get additional destroy routine for CeedQFunctionContext user data
3822e64a2b9SJeremy L Thompson 
3832e64a2b9SJeremy L Thompson   @param[in] ctx          CeedQFunctionContext to get user destroy function
3842e64a2b9SJeremy L Thompson   @param[out] f_mem_type  Memory type to use when passing data into `f`
3852e64a2b9SJeremy L Thompson   @param[out] f           Additional routine to use to destroy user data
3862e64a2b9SJeremy L Thompson 
3872e64a2b9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3882e64a2b9SJeremy L Thompson 
3892e64a2b9SJeremy L Thompson   @ref Backend
3902e64a2b9SJeremy L Thompson **/
3912e64a2b9SJeremy L Thompson int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx,
3922e64a2b9SJeremy L Thompson                                        CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) {
3932e64a2b9SJeremy L Thompson   if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type;
3942e64a2b9SJeremy L Thompson   if (f) *f = ctx->data_destroy_function;
3952e64a2b9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3962e64a2b9SJeremy L Thompson }
3972e64a2b9SJeremy L Thompson 
3982e64a2b9SJeremy L Thompson /**
39934359f16Sjeremylt   @brief Increment the reference counter for a CeedQFunctionContext
40034359f16Sjeremylt 
40134359f16Sjeremylt   @param ctx  CeedQFunctionContext to increment the reference counter
40234359f16Sjeremylt 
40334359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
40434359f16Sjeremylt 
40534359f16Sjeremylt   @ref Backend
40634359f16Sjeremylt **/
4079560d06aSjeremylt int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
40834359f16Sjeremylt   ctx->ref_count++;
40934359f16Sjeremylt   return CEED_ERROR_SUCCESS;
41034359f16Sjeremylt }
41134359f16Sjeremylt 
412777ff853SJeremy L Thompson /// @}
413777ff853SJeremy L Thompson 
414777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
415777ff853SJeremy L Thompson /// CeedQFunctionContext Public API
416777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
417777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionUser
418777ff853SJeremy L Thompson /// @{
419777ff853SJeremy L Thompson 
420777ff853SJeremy L Thompson /**
421777ff853SJeremy L Thompson   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
422777ff853SJeremy L Thompson 
423777ff853SJeremy L Thompson   @param ceed      A Ceed object where the CeedQFunctionContext will be created
424777ff853SJeremy L Thompson   @param[out] ctx  Address of the variable where the newly created
425777ff853SJeremy L Thompson                      CeedQFunctionContext will be stored
426777ff853SJeremy L Thompson 
427777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
428777ff853SJeremy L Thompson 
429777ff853SJeremy L Thompson   @ref User
430777ff853SJeremy L Thompson **/
431777ff853SJeremy L Thompson int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
432777ff853SJeremy L Thompson   int ierr;
433777ff853SJeremy L Thompson 
434777ff853SJeremy L Thompson   if (!ceed->QFunctionContextCreate) {
435777ff853SJeremy L Thompson     Ceed delegate;
436777ff853SJeremy L Thompson     ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr);
437777ff853SJeremy L Thompson 
438777ff853SJeremy L Thompson     if (!delegate)
439777ff853SJeremy L Thompson       // LCOV_EXCL_START
440e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
441e15f9bd0SJeremy L Thompson                        "Backend does not support ContextCreate");
442777ff853SJeremy L Thompson     // LCOV_EXCL_STOP
443777ff853SJeremy L Thompson 
444777ff853SJeremy L Thompson     ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr);
445e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
446777ff853SJeremy L Thompson   }
447777ff853SJeremy L Thompson 
448777ff853SJeremy L Thompson   ierr = CeedCalloc(1, ctx); CeedChk(ierr);
449777ff853SJeremy L Thompson   (*ctx)->ceed = ceed;
4509560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
451d1d35e2fSjeremylt   (*ctx)->ref_count = 1;
452777ff853SJeremy L Thompson   ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr);
453e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
454777ff853SJeremy L Thompson }
455777ff853SJeremy L Thompson 
456777ff853SJeremy L Thompson /**
4579560d06aSjeremylt   @brief Copy the pointer to a CeedQFunctionContext. Both pointers should
4589560d06aSjeremylt            be destroyed with `CeedQFunctionContextDestroy()`;
4599560d06aSjeremylt            Note: If `*ctx_copy` is non-NULL, then it is assumed that
4609560d06aSjeremylt            `*ctx_copy` is a pointer to a CeedQFunctionContext. This
4619560d06aSjeremylt            CeedQFunctionContext will be destroyed if `*ctx_copy` is the
4629560d06aSjeremylt            only reference to this CeedQFunctionContext.
4639560d06aSjeremylt 
4649560d06aSjeremylt   @param ctx            CeedQFunctionContext to copy reference to
4659560d06aSjeremylt   @param[out] ctx_copy  Variable to store copied reference
4669560d06aSjeremylt 
4679560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
4689560d06aSjeremylt 
4699560d06aSjeremylt   @ref User
4709560d06aSjeremylt **/
4719560d06aSjeremylt int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx,
4729560d06aSjeremylt                                       CeedQFunctionContext *ctx_copy) {
4739560d06aSjeremylt   int ierr;
4749560d06aSjeremylt 
4759560d06aSjeremylt   ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr);
4769560d06aSjeremylt   ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr);
4779560d06aSjeremylt   *ctx_copy = ctx;
4789560d06aSjeremylt   return CEED_ERROR_SUCCESS;
4799560d06aSjeremylt }
4809560d06aSjeremylt 
4819560d06aSjeremylt /**
482777ff853SJeremy L Thompson   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated
483777ff853SJeremy L Thompson            data if applicable. The backend may copy values to a different
484777ff853SJeremy L Thompson            memtype, such as during @ref CeedQFunctionApply().
485777ff853SJeremy L Thompson            See also @ref CeedQFunctionContextTakeData().
486777ff853SJeremy L Thompson 
487777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext
488d1d35e2fSjeremylt   @param mem_type   Memory type of the data being passed
489d1d35e2fSjeremylt   @param copy_mode  Copy mode for the data
490891038deSjeremylt   @param size       Size of data, in bytes
491777ff853SJeremy L Thompson   @param data       Data to be used
492777ff853SJeremy L Thompson 
493777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
494777ff853SJeremy L Thompson 
495777ff853SJeremy L Thompson   @ref User
496777ff853SJeremy L Thompson **/
497d1d35e2fSjeremylt int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type,
498d1d35e2fSjeremylt                                 CeedCopyMode copy_mode,
499777ff853SJeremy L Thompson                                 size_t size, void *data) {
500777ff853SJeremy L Thompson   int ierr;
501777ff853SJeremy L Thompson 
502777ff853SJeremy L Thompson   if (!ctx->SetData)
503777ff853SJeremy L Thompson     // LCOV_EXCL_START
504e15f9bd0SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
505e15f9bd0SJeremy L Thompson                      "Backend does not support ContextSetData");
506777ff853SJeremy L Thompson   // LCOV_EXCL_STOP
507777ff853SJeremy L Thompson 
508777ff853SJeremy L Thompson   if (ctx->state % 2 == 1)
509777ff853SJeremy L Thompson     // LCOV_EXCL_START
510777ff853SJeremy L Thompson     return CeedError(ctx->ceed, 1,
511777ff853SJeremy L Thompson                      "Cannot grant CeedQFunctionContext data access, the "
512777ff853SJeremy L Thompson                      "access lock is already in use");
513777ff853SJeremy L Thompson   // LCOV_EXCL_STOP
514777ff853SJeremy L Thompson 
5152e64a2b9SJeremy L Thompson   ierr = CeedQFunctionContextDestroyData(ctx); CeedChk(ierr);
516d1d35e2fSjeremylt   ctx->ctx_size = size;
517d1d35e2fSjeremylt   ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr);
518777ff853SJeremy L Thompson   ctx->state += 2;
519e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
520777ff853SJeremy L Thompson }
521777ff853SJeremy L Thompson 
522777ff853SJeremy L Thompson /**
523891038deSjeremylt   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
524891038deSjeremylt            The caller is responsible for managing and freeing the memory.
525891038deSjeremylt 
526891038deSjeremylt   @param ctx        CeedQFunctionContext to access
527891038deSjeremylt   @param mem_type   Memory type on which to access the data. If the backend
528891038deSjeremylt                       uses a different memory type, this will perform a copy.
529891038deSjeremylt   @param[out] data  Data on memory type mem_type
530891038deSjeremylt 
531891038deSjeremylt   @return An error code: 0 - success, otherwise - failure
532891038deSjeremylt 
533891038deSjeremylt   @ref User
534891038deSjeremylt **/
535891038deSjeremylt int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type,
536891038deSjeremylt                                  void *data) {
537891038deSjeremylt   int ierr;
538891038deSjeremylt 
5399c774eddSJeremy L Thompson   bool has_valid_data = true;
5409c774eddSJeremy L Thompson   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
5419c774eddSJeremy L Thompson   if (!has_valid_data)
5429c774eddSJeremy L Thompson     // LCOV_EXCL_START
5439c774eddSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
5449c774eddSJeremy L Thompson                      "CeedQFunctionContext has no valid data to take, must set data");
5459c774eddSJeremy L Thompson   // LCOV_EXCL_STOP
5469c774eddSJeremy L Thompson 
547891038deSjeremylt   if (!ctx->TakeData)
548891038deSjeremylt     // LCOV_EXCL_START
549891038deSjeremylt     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
550891038deSjeremylt                      "Backend does not support TakeData");
551891038deSjeremylt   // LCOV_EXCL_STOP
552891038deSjeremylt 
553891038deSjeremylt   if (ctx->state % 2 == 1)
554891038deSjeremylt     // LCOV_EXCL_START
555891038deSjeremylt     return CeedError(ctx->ceed, 1,
556891038deSjeremylt                      "Cannot grant CeedQFunctionContext data access, the "
557891038deSjeremylt                      "access lock is already in use");
558891038deSjeremylt   // LCOV_EXCL_STOP
559891038deSjeremylt 
5609c774eddSJeremy L Thompson   bool has_borrowed_data_of_type = true;
5619c774eddSJeremy L Thompson   ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type,
5629c774eddSJeremy L Thompson          &has_borrowed_data_of_type); CeedChk(ierr);
5639c774eddSJeremy L Thompson   if (!has_borrowed_data_of_type)
5649c774eddSJeremy L Thompson     // LCOV_EXCL_START
5659c774eddSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
5669c774eddSJeremy L Thompson                      "CeedQFunctionContext has no borowed %s data, "
5679c774eddSJeremy L Thompson                      "must set data with CeedQFunctionContextSetData",
5689c774eddSJeremy L Thompson                      CeedMemTypes[mem_type]);
5699c774eddSJeremy L Thompson   // LCOV_EXCL_STOP
5709c774eddSJeremy L Thompson 
571891038deSjeremylt   void *temp_data = NULL;
572891038deSjeremylt   ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr);
573891038deSjeremylt   if (data) (*(void **)data) = temp_data;
574891038deSjeremylt   return CEED_ERROR_SUCCESS;
575891038deSjeremylt }
576891038deSjeremylt 
577891038deSjeremylt /**
578777ff853SJeremy L Thompson   @brief Get read/write access to a CeedQFunctionContext via the specified memory type.
579777ff853SJeremy L Thompson            Restore access with @ref CeedQFunctionContextRestoreData().
580777ff853SJeremy L Thompson 
581777ff853SJeremy L Thompson   @param ctx        CeedQFunctionContext to access
582d1d35e2fSjeremylt   @param mem_type   Memory type on which to access the data. If the backend
583777ff853SJeremy L Thompson                       uses a different memory type, this will perform a copy.
584d1d35e2fSjeremylt   @param[out] data  Data on memory type mem_type
585777ff853SJeremy L Thompson 
586777ff853SJeremy L Thompson   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions
587777ff853SJeremy L Thompson     provide access to array pointers in the desired memory space. Pairing
588777ff853SJeremy L Thompson     get/restore allows the Context to track access.
589777ff853SJeremy L Thompson 
590777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
591777ff853SJeremy L Thompson 
592777ff853SJeremy L Thompson   @ref User
593777ff853SJeremy L Thompson **/
594d1d35e2fSjeremylt int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type,
595777ff853SJeremy L Thompson                                 void *data) {
596777ff853SJeremy L Thompson   int ierr;
597777ff853SJeremy L Thompson 
598777ff853SJeremy L Thompson   if (!ctx->GetData)
599777ff853SJeremy L Thompson     // LCOV_EXCL_START
600e15f9bd0SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
601e15f9bd0SJeremy L Thompson                      "Backend does not support GetData");
602777ff853SJeremy L Thompson   // LCOV_EXCL_STOP
603777ff853SJeremy L Thompson 
604777ff853SJeremy L Thompson   if (ctx->state % 2 == 1)
605777ff853SJeremy L Thompson     // LCOV_EXCL_START
606777ff853SJeremy L Thompson     return CeedError(ctx->ceed, 1,
607777ff853SJeremy L Thompson                      "Cannot grant CeedQFunctionContext data access, the "
608777ff853SJeremy L Thompson                      "access lock is already in use");
609777ff853SJeremy L Thompson   // LCOV_EXCL_STOP
610777ff853SJeremy L Thompson 
61128bfd0b7SJeremy L Thompson   if (ctx->num_readers > 0)
61228bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
61328bfd0b7SJeremy L Thompson     return CeedError(ctx->ceed, 1,
61428bfd0b7SJeremy L Thompson                      "Cannot grant CeedQFunctionContext data access, a "
61528bfd0b7SJeremy L Thompson                      "process has read access");
61628bfd0b7SJeremy L Thompson   // LCOV_EXCL_STOP
61728bfd0b7SJeremy L Thompson 
6189c774eddSJeremy L Thompson   bool has_valid_data = true;
6199c774eddSJeremy L Thompson   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
6209c774eddSJeremy L Thompson   if (!has_valid_data)
6219c774eddSJeremy L Thompson     // LCOV_EXCL_START
6229c774eddSJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
6239c774eddSJeremy L Thompson                      "CeedQFunctionContext has no valid data to get, must set data");
6249c774eddSJeremy L Thompson   // LCOV_EXCL_STOP
6259c774eddSJeremy L Thompson 
626d1d35e2fSjeremylt   ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr);
62728bfd0b7SJeremy L Thompson   ctx->state++;
62828bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
62928bfd0b7SJeremy L Thompson }
63028bfd0b7SJeremy L Thompson 
63128bfd0b7SJeremy L Thompson /**
63228bfd0b7SJeremy L Thompson   @brief Get read only access to a CeedQFunctionContext via the specified memory type.
63328bfd0b7SJeremy L Thompson            Restore access with @ref CeedQFunctionContextRestoreData().
63428bfd0b7SJeremy L Thompson 
63528bfd0b7SJeremy L Thompson   @param ctx        CeedQFunctionContext to access
63628bfd0b7SJeremy L Thompson   @param mem_type   Memory type on which to access the data. If the backend
63728bfd0b7SJeremy L Thompson                       uses a different memory type, this will perform a copy.
63828bfd0b7SJeremy L Thompson   @param[out] data  Data on memory type mem_type
63928bfd0b7SJeremy L Thompson 
64028bfd0b7SJeremy L Thompson   @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead()
64128bfd0b7SJeremy L Thompson     functions provide access to array pointers in the desired memory space. Pairing
64228bfd0b7SJeremy L Thompson     get/restore allows the Context to track access.
64328bfd0b7SJeremy L Thompson 
64428bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
64528bfd0b7SJeremy L Thompson 
64628bfd0b7SJeremy L Thompson   @ref User
64728bfd0b7SJeremy L Thompson **/
64828bfd0b7SJeremy L Thompson int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx,
64928bfd0b7SJeremy L Thompson                                     CeedMemType mem_type,
65028bfd0b7SJeremy L Thompson                                     void *data) {
65128bfd0b7SJeremy L Thompson   int ierr;
65228bfd0b7SJeremy L Thompson 
65328bfd0b7SJeremy L Thompson   if (!ctx->GetDataRead)
65428bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
65528bfd0b7SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
65628bfd0b7SJeremy L Thompson                      "Backend does not support GetDataRead");
65728bfd0b7SJeremy L Thompson   // LCOV_EXCL_STOP
65828bfd0b7SJeremy L Thompson 
65928bfd0b7SJeremy L Thompson   if (ctx->state % 2 == 1)
66028bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
66128bfd0b7SJeremy L Thompson     return CeedError(ctx->ceed, 1,
66228bfd0b7SJeremy L Thompson                      "Cannot grant CeedQFunctionContext data access, the "
66328bfd0b7SJeremy L Thompson                      "access lock is already in use");
66428bfd0b7SJeremy L Thompson   // LCOV_EXCL_STOP
66528bfd0b7SJeremy L Thompson 
66628bfd0b7SJeremy L Thompson   bool has_valid_data = true;
66728bfd0b7SJeremy L Thompson   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
66828bfd0b7SJeremy L Thompson   if (!has_valid_data)
66928bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
67028bfd0b7SJeremy L Thompson     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
67128bfd0b7SJeremy L Thompson                      "CeedQFunctionContext has no valid data to get, must set data");
67228bfd0b7SJeremy L Thompson   // LCOV_EXCL_STOP
67328bfd0b7SJeremy L Thompson 
67428bfd0b7SJeremy L Thompson   ierr = ctx->GetDataRead(ctx, mem_type, data); CeedChk(ierr);
67528bfd0b7SJeremy L Thompson   ctx->num_readers++;
676e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
677777ff853SJeremy L Thompson }
678777ff853SJeremy L Thompson 
679777ff853SJeremy L Thompson /**
680777ff853SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
681777ff853SJeremy L Thompson 
682777ff853SJeremy L Thompson   @param ctx   CeedQFunctionContext to restore
683777ff853SJeremy L Thompson   @param data  Data to restore
684777ff853SJeremy L Thompson 
685777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
686777ff853SJeremy L Thompson 
687777ff853SJeremy L Thompson   @ref User
688777ff853SJeremy L Thompson **/
689777ff853SJeremy L Thompson int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
690777ff853SJeremy L Thompson   int ierr;
691777ff853SJeremy L Thompson 
692777ff853SJeremy L Thompson   if (ctx->state % 2 != 1)
693777ff853SJeremy L Thompson     // LCOV_EXCL_START
694777ff853SJeremy L Thompson     return CeedError(ctx->ceed, 1,
695777ff853SJeremy L Thompson                      "Cannot restore CeedQFunctionContext array access, "
696777ff853SJeremy L Thompson                      "access was not granted");
697777ff853SJeremy L Thompson   // LCOV_EXCL_STOP
698777ff853SJeremy L Thompson 
699706efda3SJeremy L Thompson   if (ctx->RestoreData) {
700777ff853SJeremy L Thompson     ierr = ctx->RestoreData(ctx); CeedChk(ierr);
701706efda3SJeremy L Thompson   }
702777ff853SJeremy L Thompson   *(void **)data = NULL;
70328bfd0b7SJeremy L Thompson   ctx->state++;
70428bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
70528bfd0b7SJeremy L Thompson }
70628bfd0b7SJeremy L Thompson 
70728bfd0b7SJeremy L Thompson /**
70828bfd0b7SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead()
70928bfd0b7SJeremy L Thompson 
71028bfd0b7SJeremy L Thompson   @param ctx   CeedQFunctionContext to restore
71128bfd0b7SJeremy L Thompson   @param data  Data to restore
71228bfd0b7SJeremy L Thompson 
71328bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
71428bfd0b7SJeremy L Thompson 
71528bfd0b7SJeremy L Thompson   @ref User
71628bfd0b7SJeremy L Thompson **/
71728bfd0b7SJeremy L Thompson int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) {
71828bfd0b7SJeremy L Thompson   int ierr;
71928bfd0b7SJeremy L Thompson 
72028bfd0b7SJeremy L Thompson   if (ctx->num_readers == 0)
72128bfd0b7SJeremy L Thompson     // LCOV_EXCL_START
72228bfd0b7SJeremy L Thompson     return CeedError(ctx->ceed, 1,
72328bfd0b7SJeremy L Thompson                      "Cannot restore CeedQFunctionContext array access, "
72428bfd0b7SJeremy L Thompson                      "access was not granted");
72528bfd0b7SJeremy L Thompson   // LCOV_EXCL_STOP
72628bfd0b7SJeremy L Thompson 
727*75a19770SJeremy L Thompson   ctx->num_readers--;
728*75a19770SJeremy L Thompson   if (ctx->num_readers == 0 && ctx->RestoreDataRead) {
72928bfd0b7SJeremy L Thompson     ierr = ctx->RestoreData(ctx); CeedChk(ierr);
73028bfd0b7SJeremy L Thompson   }
73128bfd0b7SJeremy L Thompson   *(void **)data = NULL;
732*75a19770SJeremy L Thompson 
733e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
734777ff853SJeremy L Thompson }
735777ff853SJeremy L Thompson 
736777ff853SJeremy L Thompson /**
737cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a double precision value
738cdf32b93SJeremy L Thompson 
739cdf32b93SJeremy L Thompson   @param ctx               CeedQFunctionContext
740cdf32b93SJeremy L Thompson   @param field_name        Name of field to register
741cdf32b93SJeremy L Thompson   @param field_offset      Offset of field to register
7427bfe0f0eSJeremy L Thompson   @param num_values        Number of values to register, must be contiguous in memory
743cdf32b93SJeremy L Thompson   @param field_description Description of field, or NULL for none
744cdf32b93SJeremy L Thompson 
745cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
746cdf32b93SJeremy L Thompson 
747cdf32b93SJeremy L Thompson   @ref User
748cdf32b93SJeremy L Thompson **/
749cdf32b93SJeremy L Thompson int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx,
750cdf32b93SJeremy L Thompson                                        const char *field_name, size_t field_offset,
7517bfe0f0eSJeremy L Thompson                                        size_t num_values,
752cdf32b93SJeremy L Thompson                                        const char *field_description) {
753cdf32b93SJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset,
7547bfe0f0eSJeremy L Thompson          field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values);
755cdf32b93SJeremy L Thompson }
756cdf32b93SJeremy L Thompson 
757cdf32b93SJeremy L Thompson /**
758cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a int32 value
759cdf32b93SJeremy L Thompson 
760cdf32b93SJeremy L Thompson   @param ctx               CeedQFunctionContext
761cdf32b93SJeremy L Thompson   @param field_name        Name of field to register
762cdf32b93SJeremy L Thompson   @param field_offset      Offset of field to register
7637bfe0f0eSJeremy L Thompson   @param num_values        Number of values to register, must be contiguous in memory
764cdf32b93SJeremy L Thompson   @param field_description Description of field, or NULL for none
765cdf32b93SJeremy L Thompson 
766cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
767cdf32b93SJeremy L Thompson 
768cdf32b93SJeremy L Thompson   @ref User
769cdf32b93SJeremy L Thompson **/
770cdf32b93SJeremy L Thompson int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx,
771cdf32b93SJeremy L Thompson                                       const char *field_name, size_t field_offset,
7727bfe0f0eSJeremy L Thompson                                       size_t num_values,
773cdf32b93SJeremy L Thompson                                       const char *field_description) {
774cdf32b93SJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset,
7757bfe0f0eSJeremy L Thompson          field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values);
776cdf32b93SJeremy L Thompson }
777cdf32b93SJeremy L Thompson 
778cdf32b93SJeremy L Thompson /**
7793668ca4bSJeremy L Thompson   @brief Get labels for all registered QFunctionContext fields
780cdf32b93SJeremy L Thompson 
781cdf32b93SJeremy L Thompson   @param ctx                CeedQFunctionContext
7823668ca4bSJeremy L Thompson   @param[out] field_labels  Variable to hold array of field labels
783cdf32b93SJeremy L Thompson   @param[out] num_fields    Length of field descriptions array
784cdf32b93SJeremy L Thompson 
785cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
786cdf32b93SJeremy L Thompson 
787cdf32b93SJeremy L Thompson   @ref User
788cdf32b93SJeremy L Thompson **/
7893668ca4bSJeremy L Thompson int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx,
7903668ca4bSJeremy L Thompson     const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
7913668ca4bSJeremy L Thompson   *field_labels = ctx->field_labels;
792cdf32b93SJeremy L Thompson   *num_fields = ctx->num_fields;
793cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
794cdf32b93SJeremy L Thompson }
795cdf32b93SJeremy L Thompson 
796cdf32b93SJeremy L Thompson /**
7970f86cbe7SJeremy L Thompson   @brief Get the descriptive information about a CeedContextFieldLabel
7980f86cbe7SJeremy L Thompson 
7990f86cbe7SJeremy L Thompson   @param[in] label              CeedContextFieldLabel
8000f86cbe7SJeremy L Thompson   @param[out] field_name        Name of labeled field
8010f86cbe7SJeremy L Thompson   @param[out] field_description Description of field, or NULL for none
8027bfe0f0eSJeremy L Thompson   @param[out] num_values        Number of values registered
8030f86cbe7SJeremy L Thompson   @param[out] field_type        CeedContextFieldType
8040f86cbe7SJeremy L Thompson 
8050f86cbe7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8060f86cbe7SJeremy L Thompson 
8070f86cbe7SJeremy L Thompson   @ref User
8080f86cbe7SJeremy L Thompson **/
8090f86cbe7SJeremy L Thompson int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label,
8100f86cbe7SJeremy L Thompson                                         const char **field_name,
8110f86cbe7SJeremy L Thompson                                         const char **field_description,
8127bfe0f0eSJeremy L Thompson                                         size_t *num_values,
8130f86cbe7SJeremy L Thompson                                         CeedContextFieldType *field_type) {
8140f86cbe7SJeremy L Thompson   if (field_name) *field_name = label->name;
8150f86cbe7SJeremy L Thompson   if (field_description) *field_description = label->description;
8167bfe0f0eSJeremy L Thompson   if (num_values) *num_values = label->num_values;
8170f86cbe7SJeremy L Thompson   if (field_type) *field_type = label->type;
8180f86cbe7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8190f86cbe7SJeremy L Thompson }
8200f86cbe7SJeremy L Thompson 
8210f86cbe7SJeremy L Thompson /**
82280a9ef05SNatalie Beams   @brief Get data size for a Context
82380a9ef05SNatalie Beams 
82480a9ef05SNatalie Beams   @param ctx            CeedQFunctionContext
82580a9ef05SNatalie Beams   @param[out] ctx_size  Variable to store size of context data values
82680a9ef05SNatalie Beams 
82780a9ef05SNatalie Beams   @return An error code: 0 - success, otherwise - failure
82880a9ef05SNatalie Beams 
82980a9ef05SNatalie Beams   @ref User
83080a9ef05SNatalie Beams **/
83180a9ef05SNatalie Beams int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx,
83280a9ef05SNatalie Beams                                        size_t *ctx_size) {
83380a9ef05SNatalie Beams   *ctx_size = ctx->ctx_size;
83480a9ef05SNatalie Beams   return CEED_ERROR_SUCCESS;
83580a9ef05SNatalie Beams }
83680a9ef05SNatalie Beams 
83780a9ef05SNatalie Beams 
83880a9ef05SNatalie Beams /**
839777ff853SJeremy L Thompson   @brief View a CeedQFunctionContext
840777ff853SJeremy L Thompson 
841777ff853SJeremy L Thompson   @param[in] ctx     CeedQFunctionContext to view
842777ff853SJeremy L Thompson   @param[in] stream  Filestream to write to
843777ff853SJeremy L Thompson 
844777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
845777ff853SJeremy L Thompson 
846777ff853SJeremy L Thompson   @ref User
847777ff853SJeremy L Thompson **/
848777ff853SJeremy L Thompson int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
849777ff853SJeremy L Thompson   fprintf(stream, "CeedQFunctionContext\n");
850d1d35e2fSjeremylt   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
8513668ca4bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
8523668ca4bSJeremy L Thompson     // LCOV_EXCL_START
8533668ca4bSJeremy L Thompson     fprintf(stream, "  Labeled %s field: %s\n",
8543668ca4bSJeremy L Thompson             CeedContextFieldTypes[ctx->field_labels[i]->type],
8553668ca4bSJeremy L Thompson             ctx->field_labels[i]->name);
8563668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
8573668ca4bSJeremy L Thompson   }
858e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
859777ff853SJeremy L Thompson }
860777ff853SJeremy L Thompson 
861777ff853SJeremy L Thompson /**
8622790b72bSJeremy L Thompson   @brief Set additional destroy routine for CeedQFunctionContext user data
8632790b72bSJeremy L Thompson 
8642e64a2b9SJeremy L Thompson   @param[in] ctx         CeedQFunctionContext to set user destroy function
8652e64a2b9SJeremy L Thompson   @param[in] f_mem_type  Memory type to use when passing data into `f`
8662e64a2b9SJeremy L Thompson   @param[in] f           Additional routine to use to destroy user data
8672790b72bSJeremy L Thompson 
8682790b72bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8692790b72bSJeremy L Thompson 
8702790b72bSJeremy L Thompson   @ref User
8712790b72bSJeremy L Thompson **/
8722790b72bSJeremy L Thompson int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx,
8732790b72bSJeremy L Thompson                                        CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) {
8742790b72bSJeremy L Thompson   if (!f)
8752790b72bSJeremy L Thompson     // LCOV_EXCL_START
8762790b72bSJeremy L Thompson     return CeedError(ctx->ceed, 1,
8772790b72bSJeremy L Thompson                      "Must provide valid callback function for destroying user data");
8782790b72bSJeremy L Thompson   // LCOV_EXCL_STOP
8792790b72bSJeremy L Thompson   ctx->data_destroy_mem_type = f_mem_type;
8802790b72bSJeremy L Thompson   ctx->data_destroy_function = f;
8812790b72bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
8822790b72bSJeremy L Thompson }
8832790b72bSJeremy L Thompson 
8842790b72bSJeremy L Thompson /**
885777ff853SJeremy L Thompson   @brief Destroy a CeedQFunctionContext
886777ff853SJeremy L Thompson 
887777ff853SJeremy L Thompson   @param ctx  CeedQFunctionContext to destroy
888777ff853SJeremy L Thompson 
889777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
890777ff853SJeremy L Thompson 
891777ff853SJeremy L Thompson   @ref User
892777ff853SJeremy L Thompson **/
893777ff853SJeremy L Thompson int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
894777ff853SJeremy L Thompson   int ierr;
895777ff853SJeremy L Thompson 
896d1d35e2fSjeremylt   if (!*ctx || --(*ctx)->ref_count > 0)
897e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
898777ff853SJeremy L Thompson 
899777ff853SJeremy L Thompson   if ((*ctx) && ((*ctx)->state % 2) == 1)
900777ff853SJeremy L Thompson     // LCOV_EXCL_START
901777ff853SJeremy L Thompson     return CeedError((*ctx)->ceed, 1,
902777ff853SJeremy L Thompson                      "Cannot destroy CeedQFunctionContext, the access "
903777ff853SJeremy L Thompson                      "lock is in use");
904777ff853SJeremy L Thompson   // LCOV_EXCL_STOP
905777ff853SJeremy L Thompson 
9062e64a2b9SJeremy L Thompson   ierr = CeedQFunctionContextDestroyData(*ctx); CeedChk(ierr);
907777ff853SJeremy L Thompson   if ((*ctx)->Destroy) {
908777ff853SJeremy L Thompson     ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr);
909777ff853SJeremy L Thompson   }
910cdf32b93SJeremy L Thompson   for (CeedInt i=0; i<(*ctx)->num_fields; i++) {
9113668ca4bSJeremy L Thompson     ierr = CeedFree(&(*ctx)->field_labels[i]->name); CeedChk(ierr);
9123668ca4bSJeremy L Thompson     ierr = CeedFree(&(*ctx)->field_labels[i]->description); CeedChk(ierr);
9133668ca4bSJeremy L Thompson     ierr = CeedFree(&(*ctx)->field_labels[i]); CeedChk(ierr);
914cdf32b93SJeremy L Thompson   }
9153668ca4bSJeremy L Thompson   ierr = CeedFree(&(*ctx)->field_labels); CeedChk(ierr);
916777ff853SJeremy L Thompson   ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr);
917777ff853SJeremy L Thompson   ierr = CeedFree(ctx); CeedChk(ierr);
918cdf32b93SJeremy L Thompson 
919e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
920777ff853SJeremy L Thompson }
921777ff853SJeremy L Thompson 
922777ff853SJeremy L Thompson /// @}
923