xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunctioncontext.c (revision 0f86cbe7e90c9366c73a141bde379916ec0231bc)
1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3 // reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 #include <ceed/ceed.h>
18 #include <ceed/backend.h>
19 #include <ceed-impl.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 /// @file
25 /// Implementation of public CeedQFunctionContext interfaces
26 
27 /// ----------------------------------------------------------------------------
28 /// CeedQFunctionContext Library Internal Functions
29 /// ----------------------------------------------------------------------------
30 /// @addtogroup CeedQFunctionDeveloper
31 /// @{
32 
33 /**
34   @brief Get index for QFunctionContext field
35 
36   @param ctx         CeedQFunctionContext
37   @param field_name  Name of field
38   @param field_index Index of field, or -1 if field is not registered
39 
40   @return An error code: 0 - success, otherwise - failure
41 
42   @ref Developer
43 **/
44 int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx,
45                                       const char *field_name, CeedInt *field_index) {
46   *field_index = -1;
47   for (CeedInt i=0; i<ctx->num_fields; i++)
48     if (!strcmp(ctx->field_labels[i]->name, field_name))
49       *field_index = i;
50   return CEED_ERROR_SUCCESS;
51 }
52 
53 /**
54   @brief Common function for registering QFunctionContext fields
55 
56   @param ctx               CeedQFunctionContext
57   @param field_name        Name of field to register
58   @param field_offset      Offset of field to register
59   @param field_description Description of field, or NULL for none
60   @param field_type        Field data type, such as double or int32
61   @param field_size        Size of field, in bytes
62 
63   @return An error code: 0 - success, otherwise - failure
64 
65   @ref Developer
66 **/
67 int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx,
68                                         const char *field_name, size_t field_offset,
69                                         const char *field_description,
70                                         CeedContextFieldType field_type,
71                                         size_t field_size) {
72   int ierr;
73 
74   // Check for duplicate
75   CeedInt field_index = -1;
76   ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index);
77   CeedChk(ierr);
78   if (field_index != -1)
79     // LCOV_EXCL_START
80     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
81                      "QFunctionContext field with name \"%s\" already registered",
82                      field_name);
83   // LCOV_EXCL_STOP
84 
85   // Allocate space for field data
86   if (ctx->num_fields == 0) {
87     ierr = CeedCalloc(1, &ctx->field_labels); CeedChk(ierr);
88     ctx->max_fields = 1;
89   } else if (ctx->num_fields == ctx->max_fields) {
90     ierr = CeedRealloc(2*ctx->max_fields, &ctx->field_labels);
91     CeedChk(ierr);
92     ctx->max_fields *= 2;
93   }
94   ierr = CeedCalloc(1, &ctx->field_labels[ctx->num_fields]); CeedChk(ierr);
95 
96   // Copy field data
97   ierr = CeedStringAllocCopy(field_name,
98                              (char **)&ctx->field_labels[ctx->num_fields]->name);
99   CeedChk(ierr);
100   ierr = CeedStringAllocCopy(field_description,
101                              (char **)&ctx->field_labels[ctx->num_fields]->description);
102   CeedChk(ierr);
103   ctx->field_labels[ctx->num_fields]->type = field_type;
104   ctx->field_labels[ctx->num_fields]->offset = field_offset;
105   ctx->field_labels[ctx->num_fields]->size = field_size;
106   ctx->num_fields++;
107   return CEED_ERROR_SUCCESS;
108 }
109 
110 /// @}
111 
112 /// ----------------------------------------------------------------------------
113 /// CeedQFunctionContext Backend API
114 /// ----------------------------------------------------------------------------
115 /// @addtogroup CeedQFunctionBackend
116 /// @{
117 
118 /**
119   @brief Get the Ceed associated with a CeedQFunctionContext
120 
121   @param ctx        CeedQFunctionContext
122   @param[out] ceed  Variable to store Ceed
123 
124   @return An error code: 0 - success, otherwise - failure
125 
126   @ref Backend
127 **/
128 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) {
129   *ceed = ctx->ceed;
130   return CEED_ERROR_SUCCESS;
131 }
132 
133 /**
134   @brief Check for valid data in a CeedQFunctionContext
135 
136   @param ctx                  CeedQFunctionContext to check validity
137   @param[out] has_valid_data  Variable to store validity
138 
139   @return An error code: 0 - success, otherwise - failure
140 
141   @ref Backend
142 **/
143 int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx,
144                                      bool *has_valid_data) {
145   int ierr;
146 
147   if (!ctx->HasValidData)
148     // LCOV_EXCL_START
149     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
150                      "Backend does not support HasValidData");
151   // LCOV_EXCL_STOP
152 
153   ierr = ctx->HasValidData(ctx, has_valid_data); CeedChk(ierr);
154 
155   return CEED_ERROR_SUCCESS;
156 }
157 
158 /**
159   @brief Check for borrowed data of a specific CeedMemType in a
160            CeedQFunctionContext
161 
162   @param ctx                             CeedQFunctionContext to check
163   @param mem_type                        Memory type to check
164   @param[out] has_borrowed_data_of_type  Variable to store result
165 
166   @return An error code: 0 - success, otherwise - failure
167 
168   @ref Backend
169 **/
170 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx,
171     CeedMemType mem_type, bool *has_borrowed_data_of_type) {
172   int ierr;
173 
174   if (!ctx->HasBorrowedDataOfType)
175     // LCOV_EXCL_START
176     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
177                      "Backend does not support HasBorrowedDataOfType");
178   // LCOV_EXCL_STOP
179 
180   ierr = ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type);
181   CeedChk(ierr);
182 
183   return CEED_ERROR_SUCCESS;
184 }
185 
186 /**
187   @brief Get the state of a CeedQFunctionContext
188 
189   @param ctx         CeedQFunctionContext to retrieve state
190   @param[out] state  Variable to store state
191 
192   @return An error code: 0 - success, otherwise - failure
193 
194   @ref Backend
195 **/
196 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
197   *state = ctx->state;
198   return CEED_ERROR_SUCCESS;
199 }
200 
201 /**
202   @brief Get backend data of a CeedQFunctionContext
203 
204   @param ctx        CeedQFunctionContext
205   @param[out] data  Variable to store data
206 
207   @return An error code: 0 - success, otherwise - failure
208 
209   @ref Backend
210 **/
211 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
212   *(void **)data = ctx->data;
213   return CEED_ERROR_SUCCESS;
214 }
215 
216 /**
217   @brief Set backend data of a CeedQFunctionContext
218 
219   @param[out] ctx  CeedQFunctionContext
220   @param data      Data to set
221 
222   @return An error code: 0 - success, otherwise - failure
223 
224   @ref Backend
225 **/
226 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
227   ctx->data = data;
228   return CEED_ERROR_SUCCESS;
229 }
230 
231 /**
232   @brief Set QFunctionContext field
233 
234   @param ctx         CeedQFunctionContext
235   @param field_label Label of field to set
236   @param field_type  Type of field to set
237   @param value       Value to set
238 
239   @return An error code: 0 - success, otherwise - failure
240 
241   @ref User
242 **/
243 int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx,
244                                    CeedContextFieldLabel field_label,
245                                    CeedContextFieldType field_type,
246                                    void *value) {
247   int ierr;
248 
249   // Check field type
250   if (field_label->type != field_type)
251     // LCOV_EXCL_START
252     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
253                      "QFunctionContext field with name \"%s\" registered as %s, "
254                      "not registered as %s", field_label->name,
255                      CeedContextFieldTypes[field_label->type],
256                      CeedContextFieldTypes[field_type]);
257   // LCOV_EXCL_STOP
258 
259   char *data;
260   ierr = CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data); CeedChk(ierr);
261   memcpy(&data[field_label->offset], value, field_label->size);
262   ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr);
263 
264   return CEED_ERROR_SUCCESS;
265 }
266 
267 /**
268   @brief Increment the reference counter for a CeedQFunctionContext
269 
270   @param ctx  CeedQFunctionContext to increment the reference counter
271 
272   @return An error code: 0 - success, otherwise - failure
273 
274   @ref Backend
275 **/
276 int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
277   ctx->ref_count++;
278   return CEED_ERROR_SUCCESS;
279 }
280 
281 /// @}
282 
283 /// ----------------------------------------------------------------------------
284 /// CeedQFunctionContext Public API
285 /// ----------------------------------------------------------------------------
286 /// @addtogroup CeedQFunctionUser
287 /// @{
288 
289 /**
290   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
291 
292   @param ceed      A Ceed object where the CeedQFunctionContext will be created
293   @param[out] ctx  Address of the variable where the newly created
294                      CeedQFunctionContext will be stored
295 
296   @return An error code: 0 - success, otherwise - failure
297 
298   @ref User
299 **/
300 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
301   int ierr;
302 
303   if (!ceed->QFunctionContextCreate) {
304     Ceed delegate;
305     ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr);
306 
307     if (!delegate)
308       // LCOV_EXCL_START
309       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
310                        "Backend does not support ContextCreate");
311     // LCOV_EXCL_STOP
312 
313     ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr);
314     return CEED_ERROR_SUCCESS;
315   }
316 
317   ierr = CeedCalloc(1, ctx); CeedChk(ierr);
318   (*ctx)->ceed = ceed;
319   ierr = CeedReference(ceed); CeedChk(ierr);
320   (*ctx)->ref_count = 1;
321   ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr);
322   return CEED_ERROR_SUCCESS;
323 }
324 
325 /**
326   @brief Copy the pointer to a CeedQFunctionContext. Both pointers should
327            be destroyed with `CeedQFunctionContextDestroy()`;
328            Note: If `*ctx_copy` is non-NULL, then it is assumed that
329            `*ctx_copy` is a pointer to a CeedQFunctionContext. This
330            CeedQFunctionContext will be destroyed if `*ctx_copy` is the
331            only reference to this CeedQFunctionContext.
332 
333   @param ctx            CeedQFunctionContext to copy reference to
334   @param[out] ctx_copy  Variable to store copied reference
335 
336   @return An error code: 0 - success, otherwise - failure
337 
338   @ref User
339 **/
340 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx,
341                                       CeedQFunctionContext *ctx_copy) {
342   int ierr;
343 
344   ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr);
345   ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr);
346   *ctx_copy = ctx;
347   return CEED_ERROR_SUCCESS;
348 }
349 
350 /**
351   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated
352            data if applicable. The backend may copy values to a different
353            memtype, such as during @ref CeedQFunctionApply().
354            See also @ref CeedQFunctionContextTakeData().
355 
356   @param ctx        CeedQFunctionContext
357   @param mem_type   Memory type of the data being passed
358   @param copy_mode  Copy mode for the data
359   @param size       Size of data, in bytes
360   @param data       Data to be used
361 
362   @return An error code: 0 - success, otherwise - failure
363 
364   @ref User
365 **/
366 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type,
367                                 CeedCopyMode copy_mode,
368                                 size_t size, void *data) {
369   int ierr;
370 
371   if (!ctx->SetData)
372     // LCOV_EXCL_START
373     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
374                      "Backend does not support ContextSetData");
375   // LCOV_EXCL_STOP
376 
377   if (ctx->state % 2 == 1)
378     // LCOV_EXCL_START
379     return CeedError(ctx->ceed, 1,
380                      "Cannot grant CeedQFunctionContext data access, the "
381                      "access lock is already in use");
382   // LCOV_EXCL_STOP
383 
384   ctx->ctx_size = size;
385   ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr);
386   ctx->state += 2;
387   return CEED_ERROR_SUCCESS;
388 }
389 
390 /**
391   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
392            The caller is responsible for managing and freeing the memory.
393 
394   @param ctx        CeedQFunctionContext to access
395   @param mem_type   Memory type on which to access the data. If the backend
396                       uses a different memory type, this will perform a copy.
397   @param[out] data  Data on memory type mem_type
398 
399   @return An error code: 0 - success, otherwise - failure
400 
401   @ref User
402 **/
403 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type,
404                                  void *data) {
405   int ierr;
406 
407   bool has_valid_data = true;
408   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
409   if (!has_valid_data)
410     // LCOV_EXCL_START
411     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
412                      "CeedQFunctionContext has no valid data to take, must set data");
413   // LCOV_EXCL_STOP
414 
415   if (!ctx->TakeData)
416     // LCOV_EXCL_START
417     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
418                      "Backend does not support TakeData");
419   // LCOV_EXCL_STOP
420 
421   if (ctx->state % 2 == 1)
422     // LCOV_EXCL_START
423     return CeedError(ctx->ceed, 1,
424                      "Cannot grant CeedQFunctionContext data access, the "
425                      "access lock is already in use");
426   // LCOV_EXCL_STOP
427 
428   bool has_borrowed_data_of_type = true;
429   ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type,
430          &has_borrowed_data_of_type); CeedChk(ierr);
431   if (!has_borrowed_data_of_type)
432     // LCOV_EXCL_START
433     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
434                      "CeedQFunctionContext has no borowed %s data, "
435                      "must set data with CeedQFunctionContextSetData",
436                      CeedMemTypes[mem_type]);
437   // LCOV_EXCL_STOP
438 
439   void *temp_data = NULL;
440   ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr);
441   if (data) (*(void **)data) = temp_data;
442   return CEED_ERROR_SUCCESS;
443 }
444 
445 /**
446   @brief Get read/write access to a CeedQFunctionContext via the specified memory type.
447            Restore access with @ref CeedQFunctionContextRestoreData().
448 
449   @param ctx        CeedQFunctionContext to access
450   @param mem_type   Memory type on which to access the data. If the backend
451                       uses a different memory type, this will perform a copy.
452   @param[out] data  Data on memory type mem_type
453 
454   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions
455     provide access to array pointers in the desired memory space. Pairing
456     get/restore allows the Context to track access.
457 
458   @return An error code: 0 - success, otherwise - failure
459 
460   @ref User
461 **/
462 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type,
463                                 void *data) {
464   int ierr;
465 
466   if (!ctx->GetData)
467     // LCOV_EXCL_START
468     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
469                      "Backend does not support GetData");
470   // LCOV_EXCL_STOP
471 
472   if (ctx->state % 2 == 1)
473     // LCOV_EXCL_START
474     return CeedError(ctx->ceed, 1,
475                      "Cannot grant CeedQFunctionContext data access, the "
476                      "access lock is already in use");
477   // LCOV_EXCL_STOP
478 
479   bool has_valid_data = true;
480   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
481   if (!has_valid_data)
482     // LCOV_EXCL_START
483     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
484                      "CeedQFunctionContext has no valid data to get, must set data");
485   // LCOV_EXCL_STOP
486 
487   ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr);
488   ctx->state += 1;
489   return CEED_ERROR_SUCCESS;
490 }
491 
492 /**
493   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
494 
495   @param ctx   CeedQFunctionContext to restore
496   @param data  Data to restore
497 
498   @return An error code: 0 - success, otherwise - failure
499 
500   @ref User
501 **/
502 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
503   int ierr;
504 
505   if (ctx->state % 2 != 1)
506     // LCOV_EXCL_START
507     return CeedError(ctx->ceed, 1,
508                      "Cannot restore CeedQFunctionContext array access, "
509                      "access was not granted");
510   // LCOV_EXCL_STOP
511 
512   if (ctx->RestoreData) {
513     ierr = ctx->RestoreData(ctx); CeedChk(ierr);
514   }
515   *(void **)data = NULL;
516   ctx->state += 1;
517   return CEED_ERROR_SUCCESS;
518 }
519 
520 /**
521   @brief Register QFunctionContext a field holding a double precision value
522 
523   @param ctx               CeedQFunctionContext
524   @param field_name        Name of field to register
525   @param field_offset      Offset of field to register
526   @param field_description Description of field, or NULL for none
527 
528   @return An error code: 0 - success, otherwise - failure
529 
530   @ref User
531 **/
532 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx,
533                                        const char *field_name, size_t field_offset,
534                                        const char *field_description) {
535   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset,
536          field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double));
537 }
538 
539 /**
540   @brief Register QFunctionContext a field holding a int32 value
541 
542   @param ctx               CeedQFunctionContext
543   @param field_name        Name of field to register
544   @param field_offset      Offset of field to register
545   @param field_description Description of field, or NULL for none
546 
547   @return An error code: 0 - success, otherwise - failure
548 
549   @ref User
550 **/
551 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx,
552                                       const char *field_name, size_t field_offset,
553                                       const char *field_description) {
554   return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset,
555          field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int));
556 }
557 
558 /**
559   @brief Get labels for all registered QFunctionContext fields
560 
561   @param ctx                CeedQFunctionContext
562   @param[out] field_labels  Variable to hold array of field labels
563   @param[out] num_fields    Length of field descriptions array
564 
565   @return An error code: 0 - success, otherwise - failure
566 
567   @ref User
568 **/
569 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx,
570     const CeedContextFieldLabel **field_labels, CeedInt *num_fields) {
571   *field_labels = ctx->field_labels;
572   *num_fields = ctx->num_fields;
573   return CEED_ERROR_SUCCESS;
574 }
575 
576 /**
577   @brief Get label for a registered QFunctionContext field, or `NULL` if no
578            field has been registered with this `field_name`
579 
580   @param[in] ctx           CeedQFunctionContext
581   @param[in] field_name    Name of field to retrieve label
582   @param[out] field_label  Variable to field label
583 
584   @return An error code: 0 - success, otherwise - failure
585 
586   @ref User
587 **/
588 int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx,
589                                       const char *field_name, CeedContextFieldLabel *field_label) {
590   int ierr;
591 
592   CeedInt field_index;
593   ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index);
594   CeedChk(ierr);
595 
596   if (field_index != -1) {
597     *field_label = ctx->field_labels[field_index];
598   } else {
599     *field_label = NULL;
600   }
601 
602   return CEED_ERROR_SUCCESS;
603 }
604 
605 /**
606   @brief Get the descriptive information about a CeedContextFieldLabel
607 
608   @param[in] label              CeedContextFieldLabel
609   @param[out] field_name        Name of labeled field
610   @param[out] field_description Description of field, or NULL for none
611   @param[out] field_type        CeedContextFieldType
612 
613   @return An error code: 0 - success, otherwise - failure
614 
615   @ref User
616 **/
617 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label,
618                                         const char **field_name,
619                                         const char **field_description,
620                                         CeedContextFieldType *field_type) {
621   if (field_name) *field_name = label->name;
622   if (field_description) *field_description = label->description;
623   if (field_type) *field_type = label->type;
624   return CEED_ERROR_SUCCESS;
625 }
626 
627 /**
628   @brief Set QFunctionContext field holding a double precision value
629 
630   @param ctx         CeedQFunctionContext
631   @param field_label Label for field to register
632   @param value       Value to set
633 
634   @return An error code: 0 - success, otherwise - failure
635 
636   @ref User
637 **/
638 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx,
639                                   CeedContextFieldLabel field_label, double value) {
640   int ierr;
641 
642   if (!field_label)
643     // LCOV_EXCL_START
644     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
645                      "Invalid field label");
646   // LCOV_EXCL_STOP
647 
648   ierr = CeedQFunctionContextSetGeneric(ctx, field_label,
649                                         CEED_CONTEXT_FIELD_DOUBLE,
650                                         &value); CeedChk(ierr);
651 
652   return CEED_ERROR_SUCCESS;
653 }
654 
655 /**
656   @brief Set QFunctionContext field holding an int32 value
657 
658   @param ctx         CeedQFunctionContext
659   @param field_label Label for field to register
660   @param value       Value to set
661 
662   @return An error code: 0 - success, otherwise - failure
663 
664   @ref User
665 **/
666 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx,
667                                  CeedContextFieldLabel field_label, int value) {
668   int ierr;
669 
670   if (!field_label)
671     // LCOV_EXCL_START
672     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
673                      "Invalid field label");
674   // LCOV_EXCL_STOP
675 
676   ierr = CeedQFunctionContextSetGeneric(ctx, field_label,
677                                         CEED_CONTEXT_FIELD_INT32,
678                                         &value); CeedChk(ierr);
679 
680   return CEED_ERROR_SUCCESS;
681 }
682 
683 /**
684   @brief Get data size for a Context
685 
686   @param ctx            CeedQFunctionContext
687   @param[out] ctx_size  Variable to store size of context data values
688 
689   @return An error code: 0 - success, otherwise - failure
690 
691   @ref User
692 **/
693 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx,
694                                        size_t *ctx_size) {
695   *ctx_size = ctx->ctx_size;
696   return CEED_ERROR_SUCCESS;
697 }
698 
699 
700 /**
701   @brief View a CeedQFunctionContext
702 
703   @param[in] ctx     CeedQFunctionContext to view
704   @param[in] stream  Filestream to write to
705 
706   @return An error code: 0 - success, otherwise - failure
707 
708   @ref User
709 **/
710 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
711   fprintf(stream, "CeedQFunctionContext\n");
712   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
713   for (CeedInt i = 0; i < ctx->num_fields; i++) {
714     // LCOV_EXCL_START
715     fprintf(stream, "  Labeled %s field: %s\n",
716             CeedContextFieldTypes[ctx->field_labels[i]->type],
717             ctx->field_labels[i]->name);
718     // LCOV_EXCL_STOP
719   }
720   return CEED_ERROR_SUCCESS;
721 }
722 
723 /**
724   @brief Destroy a CeedQFunctionContext
725 
726   @param ctx  CeedQFunctionContext to destroy
727 
728   @return An error code: 0 - success, otherwise - failure
729 
730   @ref User
731 **/
732 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
733   int ierr;
734 
735   if (!*ctx || --(*ctx)->ref_count > 0)
736     return CEED_ERROR_SUCCESS;
737 
738   if ((*ctx) && ((*ctx)->state % 2) == 1)
739     // LCOV_EXCL_START
740     return CeedError((*ctx)->ceed, 1,
741                      "Cannot destroy CeedQFunctionContext, the access "
742                      "lock is in use");
743   // LCOV_EXCL_STOP
744 
745   if ((*ctx)->Destroy) {
746     ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr);
747   }
748   for (CeedInt i=0; i<(*ctx)->num_fields; i++) {
749     ierr = CeedFree(&(*ctx)->field_labels[i]->name); CeedChk(ierr);
750     ierr = CeedFree(&(*ctx)->field_labels[i]->description); CeedChk(ierr);
751     ierr = CeedFree(&(*ctx)->field_labels[i]); CeedChk(ierr);
752   }
753   ierr = CeedFree(&(*ctx)->field_labels); CeedChk(ierr);
754   ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr);
755   ierr = CeedFree(ctx); CeedChk(ierr);
756 
757   return CEED_ERROR_SUCCESS;
758 }
759 
760 /// @}
761