xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunctioncontext.c (revision 1a34d7dcf9bf6337bd0ad796eed7399ef441c016)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3777ff853SJeremy L Thompson //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5777ff853SJeremy L Thompson //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7777ff853SJeremy L Thompson 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
1149aac155SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdint.h>
133d576824SJeremy L Thompson #include <stdio.h>
14cdf32b93SJeremy L Thompson #include <string.h>
15777ff853SJeremy L Thompson 
16777ff853SJeremy L Thompson /// @file
17777ff853SJeremy L Thompson /// Implementation of public CeedQFunctionContext interfaces
18777ff853SJeremy L Thompson 
19777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
20cdf32b93SJeremy L Thompson /// CeedQFunctionContext Library Internal Functions
21cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
22cdf32b93SJeremy L Thompson /// @addtogroup CeedQFunctionDeveloper
23cdf32b93SJeremy L Thompson /// @{
24cdf32b93SJeremy L Thompson 
25cdf32b93SJeremy L Thompson /**
26cdf32b93SJeremy L Thompson   @brief Get index for QFunctionContext field
27cdf32b93SJeremy L Thompson 
28ea61e9acSJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
29ea61e9acSJeremy L Thompson   @param[in]  field_name  Name of field
30ea61e9acSJeremy L Thompson   @param[out] field_index Index of field, or -1 if field is not registered
31cdf32b93SJeremy L Thompson 
32cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
33cdf32b93SJeremy L Thompson 
34cdf32b93SJeremy L Thompson   @ref Developer
35cdf32b93SJeremy L Thompson **/
362b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, const char *field_name, CeedInt *field_index) {
37cdf32b93SJeremy L Thompson   *field_index = -1;
382b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
392b730f8bSJeremy L Thompson     if (!strcmp(ctx->field_labels[i]->name, field_name)) *field_index = i;
402b730f8bSJeremy L Thompson   }
41cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
42cdf32b93SJeremy L Thompson }
43cdf32b93SJeremy L Thompson 
44cdf32b93SJeremy L Thompson /**
45cdf32b93SJeremy L Thompson   @brief Common function for registering QFunctionContext fields
46cdf32b93SJeremy L Thompson 
47ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
48ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
49ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
50ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
51ea61e9acSJeremy L Thompson   @param[in]     field_type        Field data type, such as double or int32
52ea61e9acSJeremy L Thompson   @param[in]     field_size        Size of field, in bytes
53ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
54cdf32b93SJeremy L Thompson 
55cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
56cdf32b93SJeremy L Thompson 
57cdf32b93SJeremy L Thompson   @ref Developer
58cdf32b93SJeremy L Thompson **/
592b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, const char *field_description,
602b730f8bSJeremy L Thompson                                         CeedContextFieldType field_type, size_t field_size, size_t num_values) {
61cdf32b93SJeremy L Thompson   CeedInt field_index = -1;
621c66c397SJeremy L Thompson 
631c66c397SJeremy L Thompson   // Check for duplicate
642b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
656574a04fSJeremy L Thompson   CeedCheck(field_index == -1, ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" already registered", field_name);
66cdf32b93SJeremy L Thompson 
67cdf32b93SJeremy L Thompson   // Allocate space for field data
68cdf32b93SJeremy L Thompson   if (ctx->num_fields == 0) {
692b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(1, &ctx->field_labels));
70cdf32b93SJeremy L Thompson     ctx->max_fields = 1;
71cdf32b93SJeremy L Thompson   } else if (ctx->num_fields == ctx->max_fields) {
722b730f8bSJeremy L Thompson     CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels));
73cdf32b93SJeremy L Thompson     ctx->max_fields *= 2;
74cdf32b93SJeremy L Thompson   }
752b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields]));
76cdf32b93SJeremy L Thompson 
77cdf32b93SJeremy L Thompson   // Copy field data
782b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name));
792b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_description, (char **)&ctx->field_labels[ctx->num_fields]->description));
803668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->type       = field_type;
813668ca4bSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->offset     = field_offset;
827bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->size       = field_size * num_values;
837bfe0f0eSJeremy L Thompson   ctx->field_labels[ctx->num_fields]->num_values = num_values;
84cdf32b93SJeremy L Thompson   ctx->num_fields++;
85cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
86cdf32b93SJeremy L Thompson }
87cdf32b93SJeremy L Thompson 
883b190ab8SJeremy L Thompson /**
89ea61e9acSJeremy L Thompson   @brief Destroy user data held by CeedQFunctionContext, using function set by CeedQFunctionContextSetDataDestroy, if applicable
903b190ab8SJeremy L Thompson 
913b190ab8SJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to destroy user data
923b190ab8SJeremy L Thompson 
933b190ab8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
943b190ab8SJeremy L Thompson 
953b190ab8SJeremy L Thompson   @ref Developer
963b190ab8SJeremy L Thompson **/
973b190ab8SJeremy L Thompson static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) {
983b190ab8SJeremy L Thompson   if (ctx->DataDestroy) {
992b730f8bSJeremy L Thompson     CeedCall(ctx->DataDestroy(ctx));
1003b190ab8SJeremy L Thompson   } else {
1013b190ab8SJeremy L Thompson     CeedMemType                         data_destroy_mem_type;
1021c66c397SJeremy L Thompson     CeedQFunctionContextDataDestroyUser data_destroy_function;
1033b190ab8SJeremy L Thompson 
1042b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function));
1053b190ab8SJeremy L Thompson     if (data_destroy_function) {
1063b190ab8SJeremy L Thompson       void *data;
1073b190ab8SJeremy L Thompson 
1082b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data));
1092b730f8bSJeremy L Thompson       CeedCall(data_destroy_function(data));
1102b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
1113b190ab8SJeremy L Thompson     }
1123b190ab8SJeremy L Thompson   }
1133b190ab8SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1143b190ab8SJeremy L Thompson }
1153b190ab8SJeremy L Thompson 
116cdf32b93SJeremy L Thompson /// @}
117cdf32b93SJeremy L Thompson 
118cdf32b93SJeremy L Thompson /// ----------------------------------------------------------------------------
119777ff853SJeremy L Thompson /// CeedQFunctionContext Backend API
120777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
121777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionBackend
122777ff853SJeremy L Thompson /// @{
123777ff853SJeremy L Thompson 
124777ff853SJeremy L Thompson /**
125777ff853SJeremy L Thompson   @brief Get the Ceed associated with a CeedQFunctionContext
126777ff853SJeremy L Thompson 
127ea61e9acSJeremy L Thompson   @param[in]  ctx  CeedQFunctionContext
128777ff853SJeremy L Thompson   @param[out] ceed Variable to store Ceed
129777ff853SJeremy L Thompson 
130777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
131777ff853SJeremy L Thompson 
132777ff853SJeremy L Thompson   @ref Backend
133777ff853SJeremy L Thompson **/
134777ff853SJeremy L Thompson int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) {
135777ff853SJeremy L Thompson   *ceed = ctx->ceed;
136e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
137777ff853SJeremy L Thompson }
138777ff853SJeremy L Thompson 
139777ff853SJeremy L Thompson /**
1409c774eddSJeremy L Thompson   @brief Check for valid data in a CeedQFunctionContext
1419c774eddSJeremy L Thompson 
142ea61e9acSJeremy L Thompson   @param[in]  ctx            CeedQFunctionContext to check validity
1439c774eddSJeremy L Thompson   @param[out] has_valid_data Variable to store validity
1449c774eddSJeremy L Thompson 
1459c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1469c774eddSJeremy L Thompson 
1479c774eddSJeremy L Thompson   @ref Backend
1489c774eddSJeremy L Thompson **/
1492b730f8bSJeremy L Thompson int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, bool *has_valid_data) {
1506574a04fSJeremy L Thompson   CeedCheck(ctx->HasValidData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasValidData");
1512b730f8bSJeremy L Thompson   CeedCall(ctx->HasValidData(ctx, has_valid_data));
1529c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1539c774eddSJeremy L Thompson }
1549c774eddSJeremy L Thompson 
1559c774eddSJeremy L Thompson /**
156ea61e9acSJeremy L Thompson   @brief Check for borrowed data of a specific CeedMemType in a CeedQFunctionContext
1579c774eddSJeremy L Thompson 
158ea61e9acSJeremy L Thompson   @param[in]  ctx                       CeedQFunctionContext to check
159ea61e9acSJeremy L Thompson   @param[in]  mem_type                  Memory type to check
1609c774eddSJeremy L Thompson   @param[out] has_borrowed_data_of_type Variable to store result
1619c774eddSJeremy L Thompson 
1629c774eddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1639c774eddSJeremy L Thompson 
1649c774eddSJeremy L Thompson   @ref Backend
1659c774eddSJeremy L Thompson **/
1662b730f8bSJeremy L Thompson int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) {
1676574a04fSJeremy L Thompson   CeedCheck(ctx->HasBorrowedDataOfType, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedDataOfType");
1682b730f8bSJeremy L Thompson   CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type));
1699c774eddSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1709c774eddSJeremy L Thompson }
1719c774eddSJeremy L Thompson 
1729c774eddSJeremy L Thompson /**
173777ff853SJeremy L Thompson   @brief Get the state of a CeedQFunctionContext
174777ff853SJeremy L Thompson 
175ea61e9acSJeremy L Thompson   @param[in]  ctx   CeedQFunctionContext to retrieve state
176777ff853SJeremy L Thompson   @param[out] state Variable to store state
177777ff853SJeremy L Thompson 
178777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
179777ff853SJeremy L Thompson 
180777ff853SJeremy L Thompson   @ref Backend
181777ff853SJeremy L Thompson **/
182777ff853SJeremy L Thompson int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
183777ff853SJeremy L Thompson   *state = ctx->state;
184e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
185777ff853SJeremy L Thompson }
186777ff853SJeremy L Thompson 
187777ff853SJeremy L Thompson /**
188777ff853SJeremy L Thompson   @brief Get backend data of a CeedQFunctionContext
189777ff853SJeremy L Thompson 
190ea61e9acSJeremy L Thompson   @param[in]  ctx  CeedQFunctionContext
191777ff853SJeremy L Thompson   @param[out] data Variable to store data
192777ff853SJeremy L Thompson 
193777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
194777ff853SJeremy L Thompson 
195777ff853SJeremy L Thompson   @ref Backend
196777ff853SJeremy L Thompson **/
197777ff853SJeremy L Thompson int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
198777ff853SJeremy L Thompson   *(void **)data = ctx->data;
199e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
200777ff853SJeremy L Thompson }
201777ff853SJeremy L Thompson 
202777ff853SJeremy L Thompson /**
203777ff853SJeremy L Thompson   @brief Set backend data of a CeedQFunctionContext
204777ff853SJeremy L Thompson 
205ea61e9acSJeremy L Thompson   @param[in,out] ctx  CeedQFunctionContext
206ea61e9acSJeremy L Thompson   @param[in]     data Data to set
207777ff853SJeremy L Thompson 
208777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
209777ff853SJeremy L Thompson 
210777ff853SJeremy L Thompson   @ref Backend
211777ff853SJeremy L Thompson **/
212777ff853SJeremy L Thompson int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
213777ff853SJeremy L Thompson   ctx->data = data;
214e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
215777ff853SJeremy L Thompson }
216777ff853SJeremy L Thompson 
21734359f16Sjeremylt /**
218ea61e9acSJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no field has been registered with this `field_name`
219e6a0ab89SJeremy L Thompson 
220e6a0ab89SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
221e6a0ab89SJeremy L Thompson   @param[in]  field_name  Name of field to retrieve label
222e6a0ab89SJeremy L Thompson   @param[out] field_label Variable to field label
223e6a0ab89SJeremy L Thompson 
224e6a0ab89SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
225e6a0ab89SJeremy L Thompson 
2263e1e85abSJeremy L Thompson   @ref Backend
227e6a0ab89SJeremy L Thompson **/
2282b730f8bSJeremy L Thompson int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) {
229e6a0ab89SJeremy L Thompson   CeedInt field_index;
2301c66c397SJeremy L Thompson 
2312b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index));
232e6a0ab89SJeremy L Thompson 
233e6a0ab89SJeremy L Thompson   if (field_index != -1) {
234e6a0ab89SJeremy L Thompson     *field_label = ctx->field_labels[field_index];
235e6a0ab89SJeremy L Thompson   } else {
236e6a0ab89SJeremy L Thompson     *field_label = NULL;
237e6a0ab89SJeremy L Thompson   }
238e6a0ab89SJeremy L Thompson   return CEED_ERROR_SUCCESS;
239e6a0ab89SJeremy L Thompson }
240e6a0ab89SJeremy L Thompson 
241e6a0ab89SJeremy L Thompson /**
242d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field
243d8dd9a91SJeremy L Thompson 
244ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
245ea61e9acSJeremy L Thompson   @param[in]     field_label Label of field to set
246ea61e9acSJeremy L Thompson   @param[in]     field_type  Type of field to set
2472788fa27SJeremy L Thompson   @param[in]     values      Value to set
248d8dd9a91SJeremy L Thompson 
249d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
250d8dd9a91SJeremy L Thompson 
2513e1e85abSJeremy L Thompson   @ref Backend
252d8dd9a91SJeremy L Thompson **/
2532788fa27SJeremy L Thompson int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) {
254*1a34d7dcSJeremy L Thompson   bool  is_different;
2551c66c397SJeremy L Thompson   char *data;
2561c66c397SJeremy L Thompson 
2573668ca4bSJeremy L Thompson   // Check field type
2586574a04fSJeremy L Thompson   CeedCheck(field_label->type == field_type, ctx->ceed, CEED_ERROR_UNSUPPORTED,
2596574a04fSJeremy L Thompson             "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name,
2606574a04fSJeremy L Thompson             CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
261d8dd9a91SJeremy L Thompson 
262*1a34d7dcSJeremy L Thompson   CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data));
263*1a34d7dcSJeremy L Thompson   is_different = memcmp(&data[field_label->offset], values, field_label->size);
264*1a34d7dcSJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreDataRead(ctx, &data));
265*1a34d7dcSJeremy L Thompson   if (is_different) {
2662b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data));
2672788fa27SJeremy L Thompson     memcpy(&data[field_label->offset], values, field_label->size);
2682b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextRestoreData(ctx, &data));
269*1a34d7dcSJeremy L Thompson   }
270d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
271d8dd9a91SJeremy L Thompson }
272d8dd9a91SJeremy L Thompson 
273d8dd9a91SJeremy L Thompson /**
2742788fa27SJeremy L Thompson   @brief Get QFunctionContext field data, read-only
2752788fa27SJeremy L Thompson 
2762788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
2772788fa27SJeremy L Thompson   @param[in]  field_label Label of field to read
2782788fa27SJeremy L Thompson   @param[in]  field_type  Type of field to read
2792788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
2802788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
2812788fa27SJeremy L Thompson 
2822788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2832788fa27SJeremy L Thompson 
2842788fa27SJeremy L Thompson   @ref Backend
2852788fa27SJeremy L Thompson **/
2862788fa27SJeremy L Thompson int CeedQFunctionContextGetGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type,
2872788fa27SJeremy L Thompson                                        size_t *num_values, void *values) {
2881c66c397SJeremy L Thompson   char *data;
2891c66c397SJeremy L Thompson 
2902788fa27SJeremy L Thompson   // Check field type
2916574a04fSJeremy L Thompson   CeedCheck(field_label->type == field_type, ctx->ceed, CEED_ERROR_UNSUPPORTED,
2926574a04fSJeremy L Thompson             "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name,
2936574a04fSJeremy L Thompson             CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
2942788fa27SJeremy L Thompson 
2952788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data));
2962788fa27SJeremy L Thompson   *(void **)values = &data[field_label->offset];
2972788fa27SJeremy L Thompson   switch (field_type) {
2982788fa27SJeremy L Thompson     case CEED_CONTEXT_FIELD_INT32:
2992788fa27SJeremy L Thompson       *num_values = field_label->size / sizeof(int);
3002788fa27SJeremy L Thompson       break;
3012788fa27SJeremy L Thompson     case CEED_CONTEXT_FIELD_DOUBLE:
3022788fa27SJeremy L Thompson       *num_values = field_label->size / sizeof(double);
3032788fa27SJeremy L Thompson       break;
3042788fa27SJeremy L Thompson   }
3052788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3062788fa27SJeremy L Thompson }
3072788fa27SJeremy L Thompson 
3082788fa27SJeremy L Thompson /**
3092788fa27SJeremy L Thompson   @brief Restore QFunctionContext field data, read-only
3102788fa27SJeremy L Thompson 
3112788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
3122788fa27SJeremy L Thompson   @param[in]  field_label Label of field to restore
3132788fa27SJeremy L Thompson   @param[in]  field_type  Type of field to restore
3142788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3152788fa27SJeremy L Thompson 
3162788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3172788fa27SJeremy L Thompson 
3182788fa27SJeremy L Thompson   @ref Backend
3192788fa27SJeremy L Thompson **/
3202788fa27SJeremy L Thompson int CeedQFunctionContextRestoreGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type,
3212788fa27SJeremy L Thompson                                            void *values) {
3222788fa27SJeremy L Thompson   // Check field type
3236574a04fSJeremy L Thompson   CeedCheck(field_label->type == field_type, ctx->ceed, CEED_ERROR_UNSUPPORTED,
3246574a04fSJeremy L Thompson             "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name,
3256574a04fSJeremy L Thompson             CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]);
3262788fa27SJeremy L Thompson 
3272788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreDataRead(ctx, values));
3282788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3292788fa27SJeremy L Thompson }
3302788fa27SJeremy L Thompson 
3312788fa27SJeremy L Thompson /**
332bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value
333bfacc300SJeremy L Thompson 
334ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
3352788fa27SJeremy L Thompson   @param[in]     field_label Label for field to set
336ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
337bfacc300SJeremy L Thompson 
338bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
339bfacc300SJeremy L Thompson 
3403e1e85abSJeremy L Thompson   @ref Backend
341bfacc300SJeremy L Thompson **/
3422b730f8bSJeremy L Thompson int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) {
3436574a04fSJeremy L Thompson   CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
3442b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
345bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
346bfacc300SJeremy L Thompson }
347bfacc300SJeremy L Thompson 
348bfacc300SJeremy L Thompson /**
3492788fa27SJeremy L Thompson   @brief Get QFunctionContext field holding a double precision value, read-only
3502788fa27SJeremy L Thompson 
3512788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
3522788fa27SJeremy L Thompson   @param[in]  field_label Label for field to get
3532788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
3542788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3552788fa27SJeremy L Thompson 
3562788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3572788fa27SJeremy L Thompson 
3582788fa27SJeremy L Thompson   @ref Backend
3592788fa27SJeremy L Thompson **/
3602788fa27SJeremy L Thompson int CeedQFunctionContextGetDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const double **values) {
3616574a04fSJeremy L Thompson   CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
3622788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, num_values, values));
3632788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3642788fa27SJeremy L Thompson }
3652788fa27SJeremy L Thompson 
3662788fa27SJeremy L Thompson /**
3672788fa27SJeremy L Thompson   @brief Restore QFunctionContext field holding a double precision value, read-only
3682788fa27SJeremy L Thompson 
3692788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
3702788fa27SJeremy L Thompson   @param[in]  field_label Label for field to restore
3712788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
3722788fa27SJeremy L Thompson 
3732788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3742788fa27SJeremy L Thompson 
3752788fa27SJeremy L Thompson   @ref Backend
3762788fa27SJeremy L Thompson **/
3772788fa27SJeremy L Thompson int CeedQFunctionContextRestoreDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const double **values) {
3786574a04fSJeremy L Thompson   CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
3792788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values));
3802788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3812788fa27SJeremy L Thompson }
3822788fa27SJeremy L Thompson 
3832788fa27SJeremy L Thompson /**
384bfacc300SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value
385bfacc300SJeremy L Thompson 
386ea61e9acSJeremy L Thompson   @param[in,out] ctx         CeedQFunctionContext
3872788fa27SJeremy L Thompson   @param[in]     field_label Label for field to set
388ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
389bfacc300SJeremy L Thompson 
390bfacc300SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
391bfacc300SJeremy L Thompson 
3923e1e85abSJeremy L Thompson   @ref Backend
393bfacc300SJeremy L Thompson **/
3942b730f8bSJeremy L Thompson int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int *values) {
3956574a04fSJeremy L Thompson   CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
3962b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
397bfacc300SJeremy L Thompson   return CEED_ERROR_SUCCESS;
398bfacc300SJeremy L Thompson }
399bfacc300SJeremy L Thompson 
400bfacc300SJeremy L Thompson /**
4012788fa27SJeremy L Thompson   @brief Get QFunctionContext field holding a int32 value, read-only
4022788fa27SJeremy L Thompson 
4032788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
4042788fa27SJeremy L Thompson   @param[in]  field_label Label for field to get
4052788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
4062788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4072788fa27SJeremy L Thompson 
4082788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4092788fa27SJeremy L Thompson 
4102788fa27SJeremy L Thompson   @ref Backend
4112788fa27SJeremy L Thompson **/
4122788fa27SJeremy L Thompson int CeedQFunctionContextGetInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const int **values) {
4136574a04fSJeremy L Thompson   CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
4142788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, num_values, values));
4152788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4162788fa27SJeremy L Thompson }
4172788fa27SJeremy L Thompson 
4182788fa27SJeremy L Thompson /**
4192788fa27SJeremy L Thompson   @brief Restore QFunctionContext field holding a int32 value, read-only
4202788fa27SJeremy L Thompson 
4212788fa27SJeremy L Thompson   @param[in]  ctx         CeedQFunctionContext
4222788fa27SJeremy L Thompson   @param[in]  field_label Label for field to restore
4232788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
4242788fa27SJeremy L Thompson 
4252788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4262788fa27SJeremy L Thompson 
4272788fa27SJeremy L Thompson   @ref Backend
4282788fa27SJeremy L Thompson **/
4292788fa27SJeremy L Thompson int CeedQFunctionContextRestoreInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const int **values) {
4306574a04fSJeremy L Thompson   CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label");
4312788fa27SJeremy L Thompson   CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values));
4322788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4332788fa27SJeremy L Thompson }
4342788fa27SJeremy L Thompson 
4352788fa27SJeremy L Thompson /**
4362e64a2b9SJeremy L Thompson   @brief Get additional destroy routine for CeedQFunctionContext user data
4372e64a2b9SJeremy L Thompson 
4382e64a2b9SJeremy L Thompson   @param[in] ctx         CeedQFunctionContext to get user destroy function
4392e64a2b9SJeremy L Thompson   @param[out] f_mem_type Memory type to use when passing data into `f`
4402e64a2b9SJeremy L Thompson   @param[out] f          Additional routine to use to destroy user data
4412e64a2b9SJeremy L Thompson 
4422e64a2b9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4432e64a2b9SJeremy L Thompson 
4442e64a2b9SJeremy L Thompson   @ref Backend
4452e64a2b9SJeremy L Thompson **/
4462b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) {
4472e64a2b9SJeremy L Thompson   if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type;
4482e64a2b9SJeremy L Thompson   if (f) *f = ctx->data_destroy_function;
4492e64a2b9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4502e64a2b9SJeremy L Thompson }
4512e64a2b9SJeremy L Thompson 
4522e64a2b9SJeremy L Thompson /**
45334359f16Sjeremylt   @brief Increment the reference counter for a CeedQFunctionContext
45434359f16Sjeremylt 
455ea61e9acSJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to increment the reference counter
45634359f16Sjeremylt 
45734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
45834359f16Sjeremylt 
45934359f16Sjeremylt   @ref Backend
46034359f16Sjeremylt **/
4619560d06aSjeremylt int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
46234359f16Sjeremylt   ctx->ref_count++;
46334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
46434359f16Sjeremylt }
46534359f16Sjeremylt 
466777ff853SJeremy L Thompson /// @}
467777ff853SJeremy L Thompson 
468777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
469777ff853SJeremy L Thompson /// CeedQFunctionContext Public API
470777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
471777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionUser
472777ff853SJeremy L Thompson /// @{
473777ff853SJeremy L Thompson 
474777ff853SJeremy L Thompson /**
475777ff853SJeremy L Thompson   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
476777ff853SJeremy L Thompson 
477ea61e9acSJeremy L Thompson   @param[in]  ceed Ceed object where the CeedQFunctionContext will be created
478ea61e9acSJeremy L Thompson   @param[out] ctx  Address of the variable where the newly created CeedQFunctionContext will be stored
479777ff853SJeremy L Thompson 
480777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
481777ff853SJeremy L Thompson 
482777ff853SJeremy L Thompson   @ref User
483777ff853SJeremy L Thompson **/
484777ff853SJeremy L Thompson int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
485777ff853SJeremy L Thompson   if (!ceed->QFunctionContextCreate) {
486777ff853SJeremy L Thompson     Ceed delegate;
4876574a04fSJeremy L Thompson 
4882b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context"));
4896574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextCreate");
4902b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionContextCreate(delegate, ctx));
491e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
492777ff853SJeremy L Thompson   }
493777ff853SJeremy L Thompson 
4942b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, ctx));
495db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*ctx)->ceed));
496d1d35e2fSjeremylt   (*ctx)->ref_count = 1;
4972b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionContextCreate(*ctx));
498e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
499777ff853SJeremy L Thompson }
500777ff853SJeremy L Thompson 
501777ff853SJeremy L Thompson /**
502ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedQFunctionContext.
5034385fb7fSSebastian Grimberg 
504ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedQFunctionContextDestroy()`.
505512bb800SJeremy L Thompson 
506512bb800SJeremy L Thompson   Note: If the value of `ctx_copy` passed to this function is non-NULL, then it is assumed that `ctx_copy` is a pointer to a
507512bb800SJeremy L Thompson         CeedQFunctionContext. This CeedQFunctionContext will be destroyed if `ctx_copy` is the only reference to this CeedQFunctionContext.
5089560d06aSjeremylt 
509ea61e9acSJeremy L Thompson   @param[in]     ctx      CeedQFunctionContext to copy reference to
510ea61e9acSJeremy L Thompson   @param[in,out] ctx_copy Variable to store copied reference
5119560d06aSjeremylt 
5129560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
5139560d06aSjeremylt 
5149560d06aSjeremylt   @ref User
5159560d06aSjeremylt **/
5162b730f8bSJeremy L Thompson int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) {
5172b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextReference(ctx));
5182b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(ctx_copy));
5199560d06aSjeremylt   *ctx_copy = ctx;
5209560d06aSjeremylt   return CEED_ERROR_SUCCESS;
5219560d06aSjeremylt }
5229560d06aSjeremylt 
5239560d06aSjeremylt /**
524ea61e9acSJeremy L Thompson   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated data if applicable.
5254385fb7fSSebastian Grimberg 
526ea61e9acSJeremy L Thompson   The backend may copy values to a different memtype, such as during @ref CeedQFunctionApply().
527777ff853SJeremy L Thompson   See also @ref CeedQFunctionContextTakeData().
528777ff853SJeremy L Thompson 
529ea61e9acSJeremy L Thompson   @param[in,out] ctx       CeedQFunctionContext
530ea61e9acSJeremy L Thompson   @param[in]     mem_type  Memory type of the data being passed
531ea61e9acSJeremy L Thompson   @param[in]     copy_mode Copy mode for the data
532ea61e9acSJeremy L Thompson   @param[in]     size      Size of data, in bytes
533ea61e9acSJeremy L Thompson   @param[in]     data      Data to be used
534777ff853SJeremy L Thompson 
535777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
536777ff853SJeremy L Thompson 
537777ff853SJeremy L Thompson   @ref User
538777ff853SJeremy L Thompson **/
5392b730f8bSJeremy L Thompson int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) {
5406574a04fSJeremy L Thompson   CeedCheck(ctx->SetData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData");
5416574a04fSJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
542777ff853SJeremy L Thompson 
5432b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(ctx));
544d1d35e2fSjeremylt   ctx->ctx_size = size;
5452b730f8bSJeremy L Thompson   CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data));
546777ff853SJeremy L Thompson   ctx->state += 2;
547e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
548777ff853SJeremy L Thompson }
549777ff853SJeremy L Thompson 
550777ff853SJeremy L Thompson /**
551891038deSjeremylt   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
5524385fb7fSSebastian Grimberg 
553891038deSjeremylt   The caller is responsible for managing and freeing the memory.
554891038deSjeremylt 
555ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
556ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
557ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
558891038deSjeremylt   @param[out] data     Data on memory type mem_type
559891038deSjeremylt 
560891038deSjeremylt   @return An error code: 0 - success, otherwise - failure
561891038deSjeremylt 
562891038deSjeremylt   @ref User
563891038deSjeremylt **/
5642b730f8bSJeremy L Thompson int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
5651c66c397SJeremy L Thompson   void *temp_data      = NULL;
5661c66c397SJeremy L Thompson   bool  has_valid_data = true, has_borrowed_data_of_type = true;
5671c66c397SJeremy L Thompson 
5682b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
5696574a04fSJeremy L Thompson   CeedCheck(has_valid_data, ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data");
5709c774eddSJeremy L Thompson 
5716574a04fSJeremy L Thompson   CeedCheck(ctx->TakeData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData");
5726574a04fSJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
573891038deSjeremylt 
5742b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type));
5756574a04fSJeremy L Thompson   CeedCheck(has_borrowed_data_of_type, ctx->ceed, CEED_ERROR_BACKEND,
5766574a04fSJeremy L Thompson             "CeedQFunctionContext has no borrowed %s data, must set data with CeedQFunctionContextSetData", CeedMemTypes[mem_type]);
5779c774eddSJeremy L Thompson 
5782b730f8bSJeremy L Thompson   CeedCall(ctx->TakeData(ctx, mem_type, &temp_data));
579891038deSjeremylt   if (data) (*(void **)data) = temp_data;
580891038deSjeremylt   return CEED_ERROR_SUCCESS;
581891038deSjeremylt }
582891038deSjeremylt 
583891038deSjeremylt /**
584777ff853SJeremy L Thompson   @brief Get read/write access to a CeedQFunctionContext via the specified memory type.
5854385fb7fSSebastian Grimberg 
586777ff853SJeremy L Thompson   Restore access with @ref CeedQFunctionContextRestoreData().
587777ff853SJeremy L Thompson 
588ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
589ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
590ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
591d1d35e2fSjeremylt   @param[out] data     Data on memory type mem_type
592777ff853SJeremy L Thompson 
593ea61e9acSJeremy L Thompson   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory
5949fd66db6SSebastian Grimberg space.
5959fd66db6SSebastian Grimberg         Pairing get/restore allows the Context to track access.
596777ff853SJeremy L Thompson 
597777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
598777ff853SJeremy L Thompson 
599777ff853SJeremy L Thompson   @ref User
600777ff853SJeremy L Thompson **/
6012b730f8bSJeremy L Thompson int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
6021c66c397SJeremy L Thompson   bool has_valid_data = true;
6031c66c397SJeremy L Thompson 
6046574a04fSJeremy L Thompson   CeedCheck(ctx->GetData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData");
6056574a04fSJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
6066574a04fSJeremy L Thompson   CeedCheck(ctx->num_readers == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access");
60728bfd0b7SJeremy L Thompson 
6082b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
6096574a04fSJeremy L Thompson   CeedCheck(has_valid_data, ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
6109c774eddSJeremy L Thompson 
6112b730f8bSJeremy L Thompson   CeedCall(ctx->GetData(ctx, mem_type, data));
61228bfd0b7SJeremy L Thompson   ctx->state++;
61328bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
61428bfd0b7SJeremy L Thompson }
61528bfd0b7SJeremy L Thompson 
61628bfd0b7SJeremy L Thompson /**
61728bfd0b7SJeremy L Thompson   @brief Get read only access to a CeedQFunctionContext via the specified memory type.
6184385fb7fSSebastian Grimberg 
61928bfd0b7SJeremy L Thompson   Restore access with @ref CeedQFunctionContextRestoreData().
62028bfd0b7SJeremy L Thompson 
621ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext to access
622ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
623ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
62428bfd0b7SJeremy L Thompson   @param[out] data     Data on memory type mem_type
62528bfd0b7SJeremy L Thompson 
626ea61e9acSJeremy L Thompson   @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired
6279fd66db6SSebastian Grimberg memory space.
6289fd66db6SSebastian Grimberg         Pairing get/restore allows the Context to track access.
62928bfd0b7SJeremy L Thompson 
63028bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
63128bfd0b7SJeremy L Thompson 
63228bfd0b7SJeremy L Thompson   @ref User
63328bfd0b7SJeremy L Thompson **/
6342b730f8bSJeremy L Thompson int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
6351c66c397SJeremy L Thompson   bool has_valid_data = true;
6361c66c397SJeremy L Thompson 
6376574a04fSJeremy L Thompson   CeedCheck(ctx->GetDataRead, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead");
6386574a04fSJeremy L Thompson   CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use");
63928bfd0b7SJeremy L Thompson 
6402b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data));
6416574a04fSJeremy L Thompson   CeedCheck(has_valid_data, ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data");
64228bfd0b7SJeremy L Thompson 
6432b730f8bSJeremy L Thompson   CeedCall(ctx->GetDataRead(ctx, mem_type, data));
64428bfd0b7SJeremy L Thompson   ctx->num_readers++;
645e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
646777ff853SJeremy L Thompson }
647777ff853SJeremy L Thompson 
648777ff853SJeremy L Thompson /**
649777ff853SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
650777ff853SJeremy L Thompson 
651ea61e9acSJeremy L Thompson   @param[in]     ctx  CeedQFunctionContext to restore
652ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
653777ff853SJeremy L Thompson 
654777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
655777ff853SJeremy L Thompson 
656777ff853SJeremy L Thompson   @ref User
657777ff853SJeremy L Thompson **/
658777ff853SJeremy L Thompson int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
6596574a04fSJeremy L Thompson   CeedCheck(ctx->state % 2 == 1, ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
660777ff853SJeremy L Thompson 
6616574a04fSJeremy L Thompson   if (ctx->RestoreData) CeedCall(ctx->RestoreData(ctx));
662777ff853SJeremy L Thompson   *(void **)data = NULL;
66328bfd0b7SJeremy L Thompson   ctx->state++;
66428bfd0b7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
66528bfd0b7SJeremy L Thompson }
66628bfd0b7SJeremy L Thompson 
66728bfd0b7SJeremy L Thompson /**
66828bfd0b7SJeremy L Thompson   @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead()
66928bfd0b7SJeremy L Thompson 
670ea61e9acSJeremy L Thompson   @param[in]     ctx  CeedQFunctionContext to restore
671ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
67228bfd0b7SJeremy L Thompson 
67328bfd0b7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
67428bfd0b7SJeremy L Thompson 
67528bfd0b7SJeremy L Thompson   @ref User
67628bfd0b7SJeremy L Thompson **/
67728bfd0b7SJeremy L Thompson int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) {
6786574a04fSJeremy L Thompson   CeedCheck(ctx->num_readers > 0, ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted");
67928bfd0b7SJeremy L Thompson 
68075a19770SJeremy L Thompson   ctx->num_readers--;
6816574a04fSJeremy L Thompson   if (ctx->num_readers == 0 && ctx->RestoreDataRead) CeedCall(ctx->RestoreDataRead(ctx));
68228bfd0b7SJeremy L Thompson   *(void **)data = NULL;
683e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
684777ff853SJeremy L Thompson }
685777ff853SJeremy L Thompson 
686777ff853SJeremy L Thompson /**
687cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a double precision value
688cdf32b93SJeremy L Thompson 
689ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
690ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
691ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
692ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
693ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
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 **/
6992b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
700cdf32b93SJeremy L Thompson                                        const char *field_description) {
7012b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values);
702cdf32b93SJeremy L Thompson }
703cdf32b93SJeremy L Thompson 
704cdf32b93SJeremy L Thompson /**
705cdf32b93SJeremy L Thompson   @brief Register QFunctionContext a field holding a int32 value
706cdf32b93SJeremy L Thompson 
707ea61e9acSJeremy L Thompson   @param[in,out] ctx               CeedQFunctionContext
708ea61e9acSJeremy L Thompson   @param[in]     field_name        Name of field to register
709ea61e9acSJeremy L Thompson   @param[in]     field_offset      Offset of field to register
710ea61e9acSJeremy L Thompson   @param[in]     num_values        Number of values to register, must be contiguous in memory
711ea61e9acSJeremy L Thompson   @param[in]     field_description Description of field, or NULL for none
712cdf32b93SJeremy L Thompson 
713cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
714cdf32b93SJeremy L Thompson 
715cdf32b93SJeremy L Thompson   @ref User
716cdf32b93SJeremy L Thompson **/
7172b730f8bSJeremy L Thompson int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values,
718cdf32b93SJeremy L Thompson                                       const char *field_description) {
7192b730f8bSJeremy L Thompson   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values);
720cdf32b93SJeremy L Thompson }
721cdf32b93SJeremy L Thompson 
722cdf32b93SJeremy L Thompson /**
7233668ca4bSJeremy L Thompson   @brief Get labels for all registered QFunctionContext fields
724cdf32b93SJeremy L Thompson 
725ea61e9acSJeremy L Thompson   @param[in]  ctx          CeedQFunctionContext
7263668ca4bSJeremy L Thompson   @param[out] field_labels Variable to hold array of field labels
727cdf32b93SJeremy L Thompson   @param[out] num_fields   Length of field descriptions array
728cdf32b93SJeremy L Thompson 
729cdf32b93SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
730cdf32b93SJeremy L Thompson 
731cdf32b93SJeremy L Thompson   @ref User
732cdf32b93SJeremy L Thompson **/
7332b730f8bSJeremy L Thompson int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
7343668ca4bSJeremy L Thompson   *field_labels = ctx->field_labels;
735cdf32b93SJeremy L Thompson   *num_fields   = ctx->num_fields;
736cdf32b93SJeremy L Thompson   return CEED_ERROR_SUCCESS;
737cdf32b93SJeremy L Thompson }
738cdf32b93SJeremy L Thompson 
739cdf32b93SJeremy L Thompson /**
7400f86cbe7SJeremy L Thompson   @brief Get the descriptive information about a CeedContextFieldLabel
7410f86cbe7SJeremy L Thompson 
7420f86cbe7SJeremy L Thompson   @param[in]  label             CeedContextFieldLabel
7430f86cbe7SJeremy L Thompson   @param[out] field_name        Name of labeled field
7440f86cbe7SJeremy L Thompson   @param[out] field_description Description of field, or NULL for none
7457bfe0f0eSJeremy L Thompson   @param[out] num_values        Number of values registered
7460f86cbe7SJeremy L Thompson   @param[out] field_type        CeedContextFieldType
7470f86cbe7SJeremy L Thompson 
7480f86cbe7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7490f86cbe7SJeremy L Thompson 
7500f86cbe7SJeremy L Thompson   @ref User
7510f86cbe7SJeremy L Thompson **/
7522b730f8bSJeremy L Thompson int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values,
7530f86cbe7SJeremy L Thompson                                         CeedContextFieldType *field_type) {
7540f86cbe7SJeremy L Thompson   if (field_name) *field_name = label->name;
7550f86cbe7SJeremy L Thompson   if (field_description) *field_description = label->description;
7567bfe0f0eSJeremy L Thompson   if (num_values) *num_values = label->num_values;
7570f86cbe7SJeremy L Thompson   if (field_type) *field_type = label->type;
7580f86cbe7SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7590f86cbe7SJeremy L Thompson }
7600f86cbe7SJeremy L Thompson 
7610f86cbe7SJeremy L Thompson /**
76280a9ef05SNatalie Beams   @brief Get data size for a Context
76380a9ef05SNatalie Beams 
764ea61e9acSJeremy L Thompson   @param[in]  ctx      CeedQFunctionContext
76580a9ef05SNatalie Beams   @param[out] ctx_size Variable to store size of context data values
76680a9ef05SNatalie Beams 
76780a9ef05SNatalie Beams   @return An error code: 0 - success, otherwise - failure
76880a9ef05SNatalie Beams 
76980a9ef05SNatalie Beams   @ref User
77080a9ef05SNatalie Beams **/
7712b730f8bSJeremy L Thompson int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) {
77280a9ef05SNatalie Beams   *ctx_size = ctx->ctx_size;
77380a9ef05SNatalie Beams   return CEED_ERROR_SUCCESS;
77480a9ef05SNatalie Beams }
77580a9ef05SNatalie Beams 
77680a9ef05SNatalie Beams /**
777777ff853SJeremy L Thompson   @brief View a CeedQFunctionContext
778777ff853SJeremy L Thompson 
779777ff853SJeremy L Thompson   @param[in] ctx    CeedQFunctionContext to view
780777ff853SJeremy L Thompson   @param[in] stream Filestream to write to
781777ff853SJeremy L Thompson 
782777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
783777ff853SJeremy L Thompson 
784777ff853SJeremy L Thompson   @ref User
785777ff853SJeremy L Thompson **/
786777ff853SJeremy L Thompson int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
787777ff853SJeremy L Thompson   fprintf(stream, "CeedQFunctionContext\n");
788d1d35e2fSjeremylt   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
7893668ca4bSJeremy L Thompson   for (CeedInt i = 0; i < ctx->num_fields; i++) {
7903668ca4bSJeremy L Thompson     // LCOV_EXCL_START
7912b730f8bSJeremy L Thompson     fprintf(stream, "  Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name);
7923668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
7933668ca4bSJeremy L Thompson   }
794e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
795777ff853SJeremy L Thompson }
796777ff853SJeremy L Thompson 
797777ff853SJeremy L Thompson /**
7982790b72bSJeremy L Thompson   @brief Set additional destroy routine for CeedQFunctionContext user data
7992790b72bSJeremy L Thompson 
800ea61e9acSJeremy L Thompson   @param[in,out] ctx        CeedQFunctionContext to set user destroy function
8012e64a2b9SJeremy L Thompson   @param[in]     f_mem_type Memory type to use when passing data into `f`
8022e64a2b9SJeremy L Thompson   @param[in]     f          Additional routine to use to destroy user data
8032790b72bSJeremy L Thompson 
8042790b72bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8052790b72bSJeremy L Thompson 
8062790b72bSJeremy L Thompson   @ref User
8072790b72bSJeremy L Thompson **/
8082b730f8bSJeremy L Thompson int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) {
8096574a04fSJeremy L Thompson   CeedCheck(f, ctx->ceed, 1, "Must provide valid callback function for destroying user data");
8102790b72bSJeremy L Thompson   ctx->data_destroy_mem_type = f_mem_type;
8112790b72bSJeremy L Thompson   ctx->data_destroy_function = f;
8122790b72bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
8132790b72bSJeremy L Thompson }
8142790b72bSJeremy L Thompson 
8152790b72bSJeremy L Thompson /**
816777ff853SJeremy L Thompson   @brief Destroy a CeedQFunctionContext
817777ff853SJeremy L Thompson 
818ea61e9acSJeremy L Thompson   @param[in,out] ctx CeedQFunctionContext to destroy
819777ff853SJeremy L Thompson 
820777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
821777ff853SJeremy L Thompson 
822777ff853SJeremy L Thompson   @ref User
823777ff853SJeremy L Thompson **/
824777ff853SJeremy L Thompson int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
825ad6481ceSJeremy L Thompson   if (!*ctx || --(*ctx)->ref_count > 0) {
826ad6481ceSJeremy L Thompson     *ctx = NULL;
827ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
828ad6481ceSJeremy L Thompson   }
8296574a04fSJeremy L Thompson   CeedCheck(((*ctx)->state % 2) == 0, (*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use");
830777ff853SJeremy L Thompson 
8312b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroyData(*ctx));
8322b730f8bSJeremy L Thompson   if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx));
833cdf32b93SJeremy L Thompson   for (CeedInt i = 0; i < (*ctx)->num_fields; i++) {
8342b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->name));
8352b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]->description));
8362b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*ctx)->field_labels[i]));
837cdf32b93SJeremy L Thompson   }
8382b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*ctx)->field_labels));
8392b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*ctx)->ceed));
8402b730f8bSJeremy L Thompson   CeedCall(CeedFree(ctx));
841e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
842777ff853SJeremy L Thompson }
843777ff853SJeremy L Thompson 
844777ff853SJeremy L Thompson /// @}
845