xref: /libCEED/interface/ceed-operator.c (revision a49e5d53e180225109bfad71df325c7cfa170c69)
19ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, 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.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
133d576824SJeremy L Thompson #include <string.h>
14d7b241e6Sjeremylt 
15dfdf5a53Sjeremylt /// @file
167a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces
177a982d89SJeremy L. Thompson 
187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
197a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions
207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
217a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper
227a982d89SJeremy L. Thompson /// @{
237a982d89SJeremy L. Thompson 
247a982d89SJeremy L. Thompson /**
25ca94c3ddSJeremy L Thompson   @brief Check if a `CeedOperator` Field matches the `CeedQFunction` Field
26e15f9bd0SJeremy L Thompson 
27ca94c3ddSJeremy L Thompson   @param[in] ceed     `Ceed` object for error handling
28ca94c3ddSJeremy L Thompson   @param[in] qf_field `CeedQFunction` Field matching `CeedOperator` Field
29bafebce1SSebastian Grimberg   @param[in] rstr     `CeedOperator` Field `CeedElemRestriction`
30bafebce1SSebastian Grimberg   @param[in] basis    `CeedOperator` Field `CeedBasis`
31e15f9bd0SJeremy L Thompson 
32e15f9bd0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
33e15f9bd0SJeremy L Thompson 
34e15f9bd0SJeremy L Thompson   @ref Developer
35e15f9bd0SJeremy L Thompson **/
CeedOperatorCheckField(Ceed ceed,CeedQFunctionField qf_field,CeedElemRestriction rstr,CeedBasis basis)36bafebce1SSebastian Grimberg static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, CeedElemRestriction rstr, CeedBasis basis) {
376f8994e9SJeremy L Thompson   const char  *field_name;
381203703bSJeremy L Thompson   CeedInt      dim = 1, num_comp = 1, q_comp = 1, rstr_num_comp = 1, size;
391203703bSJeremy L Thompson   CeedEvalMode eval_mode;
401203703bSJeremy L Thompson 
411203703bSJeremy L Thompson   // Field data
42ab747706SJeremy L Thompson   CeedCall(CeedQFunctionFieldGetData(qf_field, &field_name, &size, &eval_mode));
432b730f8bSJeremy L Thompson 
44e15f9bd0SJeremy L Thompson   // Restriction
45bafebce1SSebastian Grimberg   CeedCheck((rstr == CEED_ELEMRESTRICTION_NONE) == (eval_mode == CEED_EVAL_WEIGHT), ceed, CEED_ERROR_INCOMPATIBLE,
466574a04fSJeremy L Thompson             "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT must be used together.");
47bafebce1SSebastian Grimberg   if (rstr != CEED_ELEMRESTRICTION_NONE) {
48bafebce1SSebastian Grimberg     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &rstr_num_comp));
49e1e9e29dSJed Brown   }
50e15f9bd0SJeremy L Thompson   // Basis
51bafebce1SSebastian Grimberg   CeedCheck((basis == CEED_BASIS_NONE) == (eval_mode == CEED_EVAL_NONE), ceed, CEED_ERROR_INCOMPATIBLE,
52356036faSJeremy L Thompson             "CEED_BASIS_NONE and CEED_EVAL_NONE must be used together.");
53bafebce1SSebastian Grimberg   if (basis != CEED_BASIS_NONE) {
54bafebce1SSebastian Grimberg     CeedCall(CeedBasisGetDimension(basis, &dim));
55bafebce1SSebastian Grimberg     CeedCall(CeedBasisGetNumComponents(basis, &num_comp));
56bafebce1SSebastian Grimberg     CeedCall(CeedBasisGetNumQuadratureComponents(basis, eval_mode, &q_comp));
57bafebce1SSebastian Grimberg     CeedCheck(rstr == CEED_ELEMRESTRICTION_NONE || rstr_num_comp == num_comp, ceed, CEED_ERROR_DIMENSION,
58ca94c3ddSJeremy L Thompson               "Field '%s' of size %" CeedInt_FMT " and EvalMode %s: CeedElemRestriction has %" CeedInt_FMT
59ca94c3ddSJeremy L Thompson               " components, but CeedBasis has %" CeedInt_FMT " components",
601203703bSJeremy L Thompson               field_name, size, CeedEvalModes[eval_mode], rstr_num_comp, num_comp);
61e15f9bd0SJeremy L Thompson   }
62e15f9bd0SJeremy L Thompson   // Field size
63d1d35e2fSjeremylt   switch (eval_mode) {
64e15f9bd0SJeremy L Thompson     case CEED_EVAL_NONE:
65edb2538eSJeremy L Thompson       CeedCheck(size == rstr_num_comp, ceed, CEED_ERROR_DIMENSION,
661203703bSJeremy L Thompson                 "Field '%s' of size %" CeedInt_FMT " and EvalMode %s: CeedElemRestriction has %" CeedInt_FMT " components", field_name, size,
671203703bSJeremy L Thompson                 CeedEvalModes[eval_mode], rstr_num_comp);
68e15f9bd0SJeremy L Thompson       break;
69e15f9bd0SJeremy L Thompson     case CEED_EVAL_INTERP:
70c4e3f59bSSebastian Grimberg     case CEED_EVAL_GRAD:
71c4e3f59bSSebastian Grimberg     case CEED_EVAL_DIV:
72c4e3f59bSSebastian Grimberg     case CEED_EVAL_CURL:
736574a04fSJeremy L Thompson       CeedCheck(size == num_comp * q_comp, ceed, CEED_ERROR_DIMENSION,
741203703bSJeremy L Thompson                 "Field '%s' of size %" CeedInt_FMT " and EvalMode %s: CeedElemRestriction/Basis has %" CeedInt_FMT " components", field_name, size,
751203703bSJeremy L Thompson                 CeedEvalModes[eval_mode], num_comp * q_comp);
76e15f9bd0SJeremy L Thompson       break;
77e15f9bd0SJeremy L Thompson     case CEED_EVAL_WEIGHT:
78d1d35e2fSjeremylt       // No additional checks required
79e15f9bd0SJeremy L Thompson       break;
80e15f9bd0SJeremy L Thompson   }
81e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
827a982d89SJeremy L. Thompson }
837a982d89SJeremy L. Thompson 
847a982d89SJeremy L. Thompson /**
85ca94c3ddSJeremy L Thompson   @brief View a field of a `CeedOperator`
867a982d89SJeremy L. Thompson 
871203703bSJeremy L Thompson   @param[in] op_field     `CeedOperator` Field to view
88ca94c3ddSJeremy L Thompson   @param[in] qf_field     `CeedQFunction` Field (carries field name)
89d1d35e2fSjeremylt   @param[in] field_number Number of field being viewed
905a526491SJeremy L Thompson   @param[in] tabs         Tabs to append before each line
91b7fd8817SJeremy L Thompson   @param[in] is_input    `true` for an input field; `false` for output field
92ca94c3ddSJeremy L Thompson   @param[in] stream       Stream to view to, e.g., `stdout`
937a982d89SJeremy L. Thompson 
947a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
957a982d89SJeremy L. Thompson 
967a982d89SJeremy L. Thompson   @ref Utility
977a982d89SJeremy L. Thompson **/
CeedOperatorFieldView(CeedOperatorField op_field,CeedQFunctionField qf_field,CeedInt field_number,const char * tabs,bool is_input,FILE * stream)98b7fd8817SJeremy L Thompson static int CeedOperatorFieldView(CeedOperatorField op_field, CeedQFunctionField qf_field, CeedInt field_number, const char *tabs, bool is_input,
995a526491SJeremy L Thompson                                  FILE *stream) {
100b7fd8817SJeremy L Thompson   const char  *field_type = is_input ? "Input" : "Output";
1016f8994e9SJeremy L Thompson   const char  *field_name;
1021203703bSJeremy L Thompson   CeedInt      size;
1031203703bSJeremy L Thompson   CeedEvalMode eval_mode;
1041203703bSJeremy L Thompson   CeedVector   vec;
1051203703bSJeremy L Thompson   CeedBasis    basis;
1061203703bSJeremy L Thompson 
1071203703bSJeremy L Thompson   // Field data
108ab747706SJeremy L Thompson   CeedCall(CeedQFunctionFieldGetData(qf_field, &field_name, &size, &eval_mode));
109ab747706SJeremy L Thompson   CeedCall(CeedOperatorFieldGetData(op_field, NULL, NULL, &basis, &vec));
1107a982d89SJeremy L. Thompson 
1112b730f8bSJeremy L Thompson   fprintf(stream,
1122b730f8bSJeremy L Thompson           "%s    %s field %" CeedInt_FMT
1132b730f8bSJeremy L Thompson           ":\n"
1147a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
115b7fd8817SJeremy L Thompson           tabs, field_type, field_number, tabs, field_name);
1165a526491SJeremy L Thompson   fprintf(stream, "%s      Size: %" CeedInt_FMT "\n", tabs, size);
1175a526491SJeremy L Thompson   fprintf(stream, "%s      EvalMode: %s\n", tabs, CeedEvalModes[eval_mode]);
1185a526491SJeremy L Thompson   if (basis == CEED_BASIS_NONE) fprintf(stream, "%s      No basis\n", tabs);
1195a526491SJeremy L Thompson   if (vec == CEED_VECTOR_ACTIVE) fprintf(stream, "%s      Active vector\n", tabs);
1205a526491SJeremy L Thompson   else if (vec == CEED_VECTOR_NONE) fprintf(stream, "%s      No vector\n", tabs);
121681d0ea7SJeremy L Thompson 
122681d0ea7SJeremy L Thompson   CeedCall(CeedVectorDestroy(&vec));
123681d0ea7SJeremy L Thompson   CeedCall(CeedBasisDestroy(&basis));
124e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1257a982d89SJeremy L. Thompson }
1267a982d89SJeremy L. Thompson 
1277a982d89SJeremy L. Thompson /**
128ca94c3ddSJeremy L Thompson   @brief View a single `CeedOperator`
1297a982d89SJeremy L. Thompson 
130ca94c3ddSJeremy L Thompson   @param[in] op     `CeedOperator` to view
1315a526491SJeremy L Thompson   @param[in] tabs   Tabs to append before each new line
132ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1337a982d89SJeremy L. Thompson 
1347a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
1357a982d89SJeremy L. Thompson 
1367a982d89SJeremy L. Thompson   @ref Utility
1377a982d89SJeremy L. Thompson **/
CeedOperatorSingleView(CeedOperator op,const char * tabs,FILE * stream)1385a526491SJeremy L Thompson int CeedOperatorSingleView(CeedOperator op, const char *tabs, FILE *stream) {
13999f7f61fSJeremy L Thompson   bool                is_at_points;
1401203703bSJeremy L Thompson   CeedInt             num_elem, num_qpts, total_fields = 0, num_input_fields, num_output_fields;
1411203703bSJeremy L Thompson   CeedQFunction       qf;
1421203703bSJeremy L Thompson   CeedQFunctionField *qf_input_fields, *qf_output_fields;
1431203703bSJeremy L Thompson   CeedOperatorField  *op_input_fields, *op_output_fields;
1447a982d89SJeremy L. Thompson 
14599f7f61fSJeremy L Thompson   CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
1462b730f8bSJeremy L Thompson   CeedCall(CeedOperatorGetNumElements(op, &num_elem));
1472b730f8bSJeremy L Thompson   CeedCall(CeedOperatorGetNumQuadraturePoints(op, &num_qpts));
1482b730f8bSJeremy L Thompson   CeedCall(CeedOperatorGetNumArgs(op, &total_fields));
1491203703bSJeremy L Thompson   CeedCall(CeedOperatorGetFields(op, &num_input_fields, &op_input_fields, &num_output_fields, &op_output_fields));
1501203703bSJeremy L Thompson   CeedCall(CeedOperatorGetQFunction(op, &qf));
1511203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetFields(qf, NULL, &qf_input_fields, NULL, &qf_output_fields));
152c11e12f4SJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&qf));
1531c66c397SJeremy L Thompson 
15499f7f61fSJeremy L Thompson   if (is_at_points) {
15599f7f61fSJeremy L Thompson     CeedInt             max_points = 0;
15699f7f61fSJeremy L Thompson     CeedElemRestriction rstr_points;
15799f7f61fSJeremy L Thompson 
15899f7f61fSJeremy L Thompson     CeedCall(CeedOperatorAtPointsGetPoints(op, &rstr_points, NULL));
15999f7f61fSJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr_points, &max_points));
1605a526491SJeremy L Thompson     fprintf(stream, "%s  %" CeedInt_FMT " elements with %" CeedInt_FMT " max points each\n", tabs, num_elem, max_points);
16199f7f61fSJeremy L Thompson     CeedCall(CeedElemRestrictionDestroy(&rstr_points));
16299f7f61fSJeremy L Thompson   } else {
1635a526491SJeremy L Thompson     fprintf(stream, "%s  %" CeedInt_FMT " elements with %" CeedInt_FMT " quadrature points each\n", tabs, num_elem, num_qpts);
16499f7f61fSJeremy L Thompson   }
1655a526491SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " field%s\n", tabs, total_fields, total_fields > 1 ? "s" : "");
1665a526491SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " input field%s:\n", tabs, num_input_fields, num_input_fields > 1 ? "s" : "");
1671203703bSJeremy L Thompson   for (CeedInt i = 0; i < num_input_fields; i++) {
1685a526491SJeremy L Thompson     CeedCall(CeedOperatorFieldView(op_input_fields[i], qf_input_fields[i], i, tabs, 1, stream));
1697a982d89SJeremy L. Thompson   }
1705a526491SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " output field%s:\n", tabs, num_output_fields, num_output_fields > 1 ? "s" : "");
1711203703bSJeremy L Thompson   for (CeedInt i = 0; i < num_output_fields; i++) {
1725a526491SJeremy L Thompson     CeedCall(CeedOperatorFieldView(op_output_fields[i], qf_output_fields[i], i, tabs, 0, stream));
1737a982d89SJeremy L. Thompson   }
174e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1757a982d89SJeremy L. Thompson }
1767a982d89SJeremy L. Thompson 
177d99fa3c5SJeremy L Thompson /**
178b0f67a9cSJeremy L Thompson   @brief View a `CeedOperator` passed as a `CeedObject`
179b0f67a9cSJeremy L Thompson 
180b0f67a9cSJeremy L Thompson   @param[in] op     `CeedOperator` to view
181b0f67a9cSJeremy L Thompson   @param[in] stream Filestream to write to
182b0f67a9cSJeremy L Thompson 
183b0f67a9cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
184b0f67a9cSJeremy L Thompson 
185b0f67a9cSJeremy L Thompson   @ref Developer
186b0f67a9cSJeremy L Thompson **/
CeedOperatorView_Object(CeedObject op,FILE * stream)187b0f67a9cSJeremy L Thompson static int CeedOperatorView_Object(CeedObject op, FILE *stream) {
188b0f67a9cSJeremy L Thompson   CeedCall(CeedOperatorView((CeedOperator)op, stream));
189b0f67a9cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
190b0f67a9cSJeremy L Thompson }
191b0f67a9cSJeremy L Thompson 
192b0f67a9cSJeremy L Thompson /**
1936c328a79SJeremy L Thompson   @brief Destroy a `CeedOperator` passed as a `CeedObject`
1946c328a79SJeremy L Thompson 
1956c328a79SJeremy L Thompson   @param[in,out] op Address of `CeedOperator` to destroy
1966c328a79SJeremy L Thompson 
1976c328a79SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1986c328a79SJeremy L Thompson 
1996c328a79SJeremy L Thompson   @ref Developer
2006c328a79SJeremy L Thompson **/
CeedOperatorDestroy_Object(CeedObject * op)2016c328a79SJeremy L Thompson static int CeedOperatorDestroy_Object(CeedObject *op) {
2026c328a79SJeremy L Thompson   CeedCall(CeedOperatorDestroy((CeedOperator *)op));
2036c328a79SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2046c328a79SJeremy L Thompson }
2056c328a79SJeremy L Thompson 
2066c328a79SJeremy L Thompson /**
207681d0ea7SJeremy L Thompson   @brief Find the active input vector `CeedBasis` for a non-composite `CeedOperator`.
208681d0ea7SJeremy L Thompson 
209681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the `active_basis` with @ref CeedBasisDestroy().
210eaf62fffSJeremy L Thompson 
211ca94c3ddSJeremy L Thompson   @param[in]  op           `CeedOperator` to find active `CeedBasis` for
212ca94c3ddSJeremy L Thompson   @param[out] active_basis `CeedBasis` for active input vector or `NULL` for composite operator
213eaf62fffSJeremy L Thompson 
214eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
215eaf62fffSJeremy L Thompson 
216eaf62fffSJeremy L Thompson   @ref Developer
217eaf62fffSJeremy L Thompson **/
CeedOperatorGetActiveBasis(CeedOperator op,CeedBasis * active_basis)218eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
219506b1a0cSSebastian Grimberg   CeedCall(CeedOperatorGetActiveBases(op, active_basis, NULL));
220506b1a0cSSebastian Grimberg   return CEED_ERROR_SUCCESS;
221506b1a0cSSebastian Grimberg }
222506b1a0cSSebastian Grimberg 
223506b1a0cSSebastian Grimberg /**
224681d0ea7SJeremy L Thompson   @brief Find the active input and output vector `CeedBasis` for a non-composite `CeedOperator`.
225681d0ea7SJeremy L Thompson 
226681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the bases with @ref CeedBasisDestroy().
227506b1a0cSSebastian Grimberg 
228ca94c3ddSJeremy L Thompson   @param[in]  op                  `CeedOperator` to find active `CeedBasis` for
229ca94c3ddSJeremy L Thompson   @param[out] active_input_basis  `CeedBasis` for active input vector or `NULL` for composite operator
230ca94c3ddSJeremy L Thompson   @param[out] active_output_basis `CeedBasis` for active output vector or `NULL` for composite operator
231506b1a0cSSebastian Grimberg 
232506b1a0cSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
233506b1a0cSSebastian Grimberg 
234506b1a0cSSebastian Grimberg   @ref Developer
235506b1a0cSSebastian Grimberg **/
CeedOperatorGetActiveBases(CeedOperator op,CeedBasis * active_input_basis,CeedBasis * active_output_basis)236506b1a0cSSebastian Grimberg int CeedOperatorGetActiveBases(CeedOperator op, CeedBasis *active_input_basis, CeedBasis *active_output_basis) {
2371203703bSJeremy L Thompson   bool               is_composite;
2381203703bSJeremy L Thompson   CeedInt            num_input_fields, num_output_fields;
2391203703bSJeremy L Thompson   CeedOperatorField *op_input_fields, *op_output_fields;
2401c66c397SJeremy L Thompson 
2411203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
2421203703bSJeremy L Thompson   CeedCall(CeedOperatorGetFields(op, &num_input_fields, &op_input_fields, &num_output_fields, &op_output_fields));
2431203703bSJeremy L Thompson 
244506b1a0cSSebastian Grimberg   if (active_input_basis) {
245506b1a0cSSebastian Grimberg     *active_input_basis = NULL;
2461203703bSJeremy L Thompson     if (!is_composite) {
2471203703bSJeremy L Thompson       for (CeedInt i = 0; i < num_input_fields; i++) {
2481203703bSJeremy L Thompson         CeedVector vec;
2491203703bSJeremy L Thompson 
2501203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetVector(op_input_fields[i], &vec));
2511203703bSJeremy L Thompson         if (vec == CEED_VECTOR_ACTIVE) {
2521203703bSJeremy L Thompson           CeedBasis basis;
2531203703bSJeremy L Thompson 
2541203703bSJeremy L Thompson           CeedCall(CeedOperatorFieldGetBasis(op_input_fields[i], &basis));
2559bc66399SJeremy L Thompson           CeedCheck(!*active_input_basis || *active_input_basis == basis, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR,
2569bc66399SJeremy L Thompson                     "Multiple active input CeedBases found");
257681d0ea7SJeremy L Thompson           if (!*active_input_basis) CeedCall(CeedBasisReferenceCopy(basis, active_input_basis));
258681d0ea7SJeremy L Thompson           CeedCall(CeedBasisDestroy(&basis));
259eaf62fffSJeremy L Thompson         }
260681d0ea7SJeremy L Thompson         CeedCall(CeedVectorDestroy(&vec));
2612b730f8bSJeremy L Thompson       }
2629bc66399SJeremy L Thompson       CeedCheck(*active_input_basis, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "No active input CeedBasis found");
263506b1a0cSSebastian Grimberg     }
264506b1a0cSSebastian Grimberg   }
265506b1a0cSSebastian Grimberg   if (active_output_basis) {
266506b1a0cSSebastian Grimberg     *active_output_basis = NULL;
2671203703bSJeremy L Thompson     if (!is_composite) {
2681203703bSJeremy L Thompson       for (CeedInt i = 0; i < num_output_fields; i++) {
2691203703bSJeremy L Thompson         CeedVector vec;
2701203703bSJeremy L Thompson 
2711203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetVector(op_output_fields[i], &vec));
2721203703bSJeremy L Thompson         if (vec == CEED_VECTOR_ACTIVE) {
2731203703bSJeremy L Thompson           CeedBasis basis;
2741203703bSJeremy L Thompson 
2751203703bSJeremy L Thompson           CeedCall(CeedOperatorFieldGetBasis(op_output_fields[i], &basis));
2769bc66399SJeremy L Thompson           CeedCheck(!*active_output_basis || *active_output_basis == basis, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR,
2779bc66399SJeremy L Thompson                     "Multiple active output CeedBases found");
278681d0ea7SJeremy L Thompson           if (!*active_output_basis) CeedCall(CeedBasisReferenceCopy(basis, active_output_basis));
279681d0ea7SJeremy L Thompson           CeedCall(CeedBasisDestroy(&basis));
280506b1a0cSSebastian Grimberg         }
281681d0ea7SJeremy L Thompson         CeedCall(CeedVectorDestroy(&vec));
282506b1a0cSSebastian Grimberg       }
2839bc66399SJeremy L Thompson       CeedCheck(*active_output_basis, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "No active output CeedBasis found");
284506b1a0cSSebastian Grimberg     }
285506b1a0cSSebastian Grimberg   }
286eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
287eaf62fffSJeremy L Thompson }
288eaf62fffSJeremy L Thompson 
289eaf62fffSJeremy L Thompson /**
290681d0ea7SJeremy L Thompson   @brief Find the active vector `CeedElemRestriction` for a non-composite `CeedOperator`.
291681d0ea7SJeremy L Thompson 
292681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the `active_rstr` with @ref CeedElemRestrictionDestroy().
293e2f04181SAndrew T. Barker 
294ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator` to find active `CeedElemRestriction` for
295ca94c3ddSJeremy L Thompson   @param[out] active_rstr `CeedElemRestriction` for active input vector or NULL for composite operator
296e2f04181SAndrew T. Barker 
297e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
298e2f04181SAndrew T. Barker 
299e2f04181SAndrew T. Barker   @ref Utility
300e2f04181SAndrew T. Barker **/
CeedOperatorGetActiveElemRestriction(CeedOperator op,CeedElemRestriction * active_rstr)3012b730f8bSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op, CeedElemRestriction *active_rstr) {
302506b1a0cSSebastian Grimberg   CeedCall(CeedOperatorGetActiveElemRestrictions(op, active_rstr, NULL));
303506b1a0cSSebastian Grimberg   return CEED_ERROR_SUCCESS;
304506b1a0cSSebastian Grimberg }
305506b1a0cSSebastian Grimberg 
306506b1a0cSSebastian Grimberg /**
307681d0ea7SJeremy L Thompson   @brief Find the active input and output vector `CeedElemRestriction` for a non-composite `CeedOperator`.
308681d0ea7SJeremy L Thompson 
309681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the restrictions with @ref CeedElemRestrictionDestroy().
310506b1a0cSSebastian Grimberg 
311ca94c3ddSJeremy L Thompson   @param[in]  op                 `CeedOperator` to find active `CeedElemRestriction` for
312ca94c3ddSJeremy L Thompson   @param[out] active_input_rstr  `CeedElemRestriction` for active input vector or NULL for composite operator
313ca94c3ddSJeremy L Thompson   @param[out] active_output_rstr `CeedElemRestriction` for active output vector or NULL for composite operator
314506b1a0cSSebastian Grimberg 
315506b1a0cSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
316506b1a0cSSebastian Grimberg 
317506b1a0cSSebastian Grimberg   @ref Utility
318506b1a0cSSebastian Grimberg **/
CeedOperatorGetActiveElemRestrictions(CeedOperator op,CeedElemRestriction * active_input_rstr,CeedElemRestriction * active_output_rstr)319506b1a0cSSebastian Grimberg int CeedOperatorGetActiveElemRestrictions(CeedOperator op, CeedElemRestriction *active_input_rstr, CeedElemRestriction *active_output_rstr) {
3201203703bSJeremy L Thompson   bool               is_composite;
3211203703bSJeremy L Thompson   CeedInt            num_input_fields, num_output_fields;
3221203703bSJeremy L Thompson   CeedOperatorField *op_input_fields, *op_output_fields;
3231c66c397SJeremy L Thompson 
3241203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
3251203703bSJeremy L Thompson   CeedCall(CeedOperatorGetFields(op, &num_input_fields, &op_input_fields, &num_output_fields, &op_output_fields));
3261203703bSJeremy L Thompson 
327506b1a0cSSebastian Grimberg   if (active_input_rstr) {
328506b1a0cSSebastian Grimberg     *active_input_rstr = NULL;
3291203703bSJeremy L Thompson     if (!is_composite) {
3301203703bSJeremy L Thompson       for (CeedInt i = 0; i < num_input_fields; i++) {
3311203703bSJeremy L Thompson         CeedVector vec;
3321203703bSJeremy L Thompson 
3331203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetVector(op_input_fields[i], &vec));
3341203703bSJeremy L Thompson         if (vec == CEED_VECTOR_ACTIVE) {
3351203703bSJeremy L Thompson           CeedElemRestriction rstr;
3361203703bSJeremy L Thompson 
3371203703bSJeremy L Thompson           CeedCall(CeedOperatorFieldGetElemRestriction(op_input_fields[i], &rstr));
3389bc66399SJeremy L Thompson           CeedCheck(!*active_input_rstr || *active_input_rstr == rstr, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR,
3399bc66399SJeremy L Thompson                     "Multiple active input CeedElemRestrictions found");
340681d0ea7SJeremy L Thompson           if (!*active_input_rstr) CeedCall(CeedElemRestrictionReferenceCopy(rstr, active_input_rstr));
341681d0ea7SJeremy L Thompson           CeedCall(CeedElemRestrictionDestroy(&rstr));
342e2f04181SAndrew T. Barker         }
343681d0ea7SJeremy L Thompson         CeedCall(CeedVectorDestroy(&vec));
3442b730f8bSJeremy L Thompson       }
3459bc66399SJeremy L Thompson       CeedCheck(*active_input_rstr, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "No active input CeedElemRestriction found");
346506b1a0cSSebastian Grimberg     }
347506b1a0cSSebastian Grimberg   }
348506b1a0cSSebastian Grimberg   if (active_output_rstr) {
349506b1a0cSSebastian Grimberg     *active_output_rstr = NULL;
3501203703bSJeremy L Thompson     if (!is_composite) {
3511203703bSJeremy L Thompson       for (CeedInt i = 0; i < num_output_fields; i++) {
3521203703bSJeremy L Thompson         CeedVector vec;
3531203703bSJeremy L Thompson 
3541203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetVector(op_output_fields[i], &vec));
3551203703bSJeremy L Thompson         if (vec == CEED_VECTOR_ACTIVE) {
3561203703bSJeremy L Thompson           CeedElemRestriction rstr;
3571203703bSJeremy L Thompson 
3581203703bSJeremy L Thompson           CeedCall(CeedOperatorFieldGetElemRestriction(op_output_fields[i], &rstr));
3599bc66399SJeremy L Thompson           CeedCheck(!*active_output_rstr || *active_output_rstr == rstr, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR,
3609bc66399SJeremy L Thompson                     "Multiple active output CeedElemRestrictions found");
361681d0ea7SJeremy L Thompson           if (!*active_output_rstr) CeedCall(CeedElemRestrictionReferenceCopy(rstr, active_output_rstr));
362681d0ea7SJeremy L Thompson           CeedCall(CeedElemRestrictionDestroy(&rstr));
363506b1a0cSSebastian Grimberg         }
364681d0ea7SJeremy L Thompson         CeedCall(CeedVectorDestroy(&vec));
365506b1a0cSSebastian Grimberg       }
3669bc66399SJeremy L Thompson       CeedCheck(*active_output_rstr, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "No active output CeedElemRestriction found");
367506b1a0cSSebastian Grimberg     }
368506b1a0cSSebastian Grimberg   }
369e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
370e2f04181SAndrew T. Barker }
371e2f04181SAndrew T. Barker 
372d8dd9a91SJeremy L Thompson /**
373ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field values of the specified type.
3744385fb7fSSebastian Grimberg 
375ca94c3ddSJeremy L Thompson   For composite operators, the value is set in all sub-operator `CeedQFunctionContext` that have a matching `field_name`.
376ca94c3ddSJeremy L Thompson   A non-zero error code is returned for single operators that do not have a matching field of the same type or composite operators that do not have any field of a matching type.
377d8dd9a91SJeremy L Thompson 
378ca94c3ddSJeremy L Thompson   @param[in,out] op          `CeedOperator`
379ea61e9acSJeremy L Thompson   @param[in]     field_label Label of field to set
380ea61e9acSJeremy L Thompson   @param[in]     field_type  Type of field to set
3812788fa27SJeremy L Thompson   @param[in]     values      Values to set
382d8dd9a91SJeremy L Thompson 
383d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
384d8dd9a91SJeremy L Thompson 
3856ab8e59fSJames Wright   @ref Developer
386d8dd9a91SJeremy L Thompson **/
CeedOperatorContextSetGeneric(CeedOperator op,CeedContextFieldLabel field_label,CeedContextFieldType field_type,void * values)3872788fa27SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) {
3881c66c397SJeremy L Thompson   bool is_composite = false;
3891c66c397SJeremy L Thompson 
3909bc66399SJeremy L Thompson   CeedCheck(field_label, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "Invalid field label");
3913668ca4bSJeremy L Thompson 
3925ac9af79SJeremy L Thompson   // Check if field_label and op correspond
3935ac9af79SJeremy L Thompson   if (field_label->from_op) {
3945ac9af79SJeremy L Thompson     CeedInt index = -1;
3955ac9af79SJeremy L Thompson 
3965ac9af79SJeremy L Thompson     for (CeedInt i = 0; i < op->num_context_labels; i++) {
3975ac9af79SJeremy L Thompson       if (op->context_labels[i] == field_label) index = i;
3985ac9af79SJeremy L Thompson     }
3999bc66399SJeremy L Thompson     CeedCheck(index != -1, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "ContextFieldLabel does not correspond to the operator");
4005ac9af79SJeremy L Thompson   }
4015ac9af79SJeremy L Thompson 
4022b730f8bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
403d8dd9a91SJeremy L Thompson   if (is_composite) {
404d8dd9a91SJeremy L Thompson     CeedInt       num_sub;
405d8dd9a91SJeremy L Thompson     CeedOperator *sub_operators;
406d8dd9a91SJeremy L Thompson 
407ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_sub));
408ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
4099bc66399SJeremy L Thompson     CeedCheck(num_sub == field_label->num_sub_labels, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED,
4109bc66399SJeremy L Thompson               "Composite operator modified after ContextFieldLabel created");
411d8dd9a91SJeremy L Thompson 
412d8dd9a91SJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
4131203703bSJeremy L Thompson       CeedQFunctionContext ctx;
4141203703bSJeremy L Thompson 
4151485364cSJeremy L Thompson       CeedCall(CeedOperatorGetContext(sub_operators[i], &ctx));
416d8dd9a91SJeremy L Thompson       // Try every sub-operator, ok if some sub-operators do not have field
4171485364cSJeremy L Thompson       if (ctx && field_label->sub_labels[i]) {
4181203703bSJeremy L Thompson         CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label->sub_labels[i], field_type, values));
419d8dd9a91SJeremy L Thompson       }
4201485364cSJeremy L Thompson       CeedCall(CeedQFunctionContextDestroy(&ctx));
421d8dd9a91SJeremy L Thompson     }
422d8dd9a91SJeremy L Thompson   } else {
4231203703bSJeremy L Thompson     CeedQFunctionContext ctx;
4241203703bSJeremy L Thompson 
4251485364cSJeremy L Thompson     CeedCall(CeedOperatorGetContext(op, &ctx));
4269bc66399SJeremy L Thompson     CeedCheck(ctx, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "QFunction does not have context data");
4271203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, field_type, values));
4281485364cSJeremy L Thompson     CeedCall(CeedQFunctionContextDestroy(&ctx));
4292788fa27SJeremy L Thompson   }
4306d95ab46SJeremy L Thompson   CeedCall(CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op, true));
4312788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4322788fa27SJeremy L Thompson }
4332788fa27SJeremy L Thompson 
4342788fa27SJeremy L Thompson /**
435ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field values of the specified type, read-only.
4364385fb7fSSebastian Grimberg 
437ca94c3ddSJeremy L Thompson   For composite operators, the values retrieved are for the first sub-operator `CeedQFunctionContext` that have a matching `field_name`.
438ca94c3ddSJeremy L Thompson   A non-zero error code is returned for single operators that do not have a matching field of the same type or composite operators that do not have any field of a matching type.
4392788fa27SJeremy L Thompson 
440ca94c3ddSJeremy L Thompson   @param[in,out] op          `CeedOperator`
4412788fa27SJeremy L Thompson   @param[in]     field_label Label of field to set
4422788fa27SJeremy L Thompson   @param[in]     field_type  Type of field to set
443c5d0f995SJed Brown   @param[out]    num_values  Number of values of type `field_type` in array `values`
444c5d0f995SJed Brown   @param[out]    values      Values in the label
4452788fa27SJeremy L Thompson 
4462788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
4472788fa27SJeremy L Thompson 
4486ab8e59fSJames Wright   @ref Developer
4492788fa27SJeremy L Thompson **/
CeedOperatorContextGetGenericRead(CeedOperator op,CeedContextFieldLabel field_label,CeedContextFieldType field_type,size_t * num_values,void * values)4502788fa27SJeremy L Thompson static int CeedOperatorContextGetGenericRead(CeedOperator op, CeedContextFieldLabel field_label, CeedContextFieldType field_type, size_t *num_values,
4512788fa27SJeremy L Thompson                                              void *values) {
4521c66c397SJeremy L Thompson   bool is_composite = false;
4531c66c397SJeremy L Thompson 
4549bc66399SJeremy L Thompson   CeedCheck(field_label, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "Invalid field label");
4552788fa27SJeremy L Thompson 
4562788fa27SJeremy L Thompson   *(void **)values = NULL;
4572788fa27SJeremy L Thompson   *num_values      = 0;
4582788fa27SJeremy L Thompson 
4595ac9af79SJeremy L Thompson   // Check if field_label and op correspond
4605ac9af79SJeremy L Thompson   if (field_label->from_op) {
4615ac9af79SJeremy L Thompson     CeedInt index = -1;
4625ac9af79SJeremy L Thompson 
4635ac9af79SJeremy L Thompson     for (CeedInt i = 0; i < op->num_context_labels; i++) {
4645ac9af79SJeremy L Thompson       if (op->context_labels[i] == field_label) index = i;
4655ac9af79SJeremy L Thompson     }
4669bc66399SJeremy L Thompson     CeedCheck(index != -1, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "ContextFieldLabel does not correspond to the operator");
4675ac9af79SJeremy L Thompson   }
4685ac9af79SJeremy L Thompson 
4692788fa27SJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
4702788fa27SJeremy L Thompson   if (is_composite) {
4712788fa27SJeremy L Thompson     CeedInt       num_sub;
4722788fa27SJeremy L Thompson     CeedOperator *sub_operators;
4732788fa27SJeremy L Thompson 
474ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_sub));
475ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
4769bc66399SJeremy L Thompson     CeedCheck(num_sub == field_label->num_sub_labels, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED,
4779bc66399SJeremy L Thompson               "Composite operator modified after ContextFieldLabel created");
4782788fa27SJeremy L Thompson 
4792788fa27SJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
4801203703bSJeremy L Thompson       CeedQFunctionContext ctx;
4811203703bSJeremy L Thompson 
4821485364cSJeremy L Thompson       CeedCall(CeedOperatorGetContext(sub_operators[i], &ctx));
4832788fa27SJeremy L Thompson       // Try every sub-operator, ok if some sub-operators do not have field
4841485364cSJeremy L Thompson       if (ctx && field_label->sub_labels[i]) {
4851203703bSJeremy L Thompson         CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label->sub_labels[i], field_type, num_values, values));
4861485364cSJeremy L Thompson         CeedCall(CeedQFunctionContextDestroy(&ctx));
4872788fa27SJeremy L Thompson         return CEED_ERROR_SUCCESS;
4882788fa27SJeremy L Thompson       }
4891485364cSJeremy L Thompson       CeedCall(CeedQFunctionContextDestroy(&ctx));
4902788fa27SJeremy L Thompson     }
4912788fa27SJeremy L Thompson   } else {
4921203703bSJeremy L Thompson     CeedQFunctionContext ctx;
4931203703bSJeremy L Thompson 
4941485364cSJeremy L Thompson     CeedCall(CeedOperatorGetContext(op, &ctx));
4959bc66399SJeremy L Thompson     CeedCheck(ctx, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "QFunction does not have context data");
4961203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, field_type, num_values, values));
4971485364cSJeremy L Thompson     CeedCall(CeedQFunctionContextDestroy(&ctx));
4982788fa27SJeremy L Thompson   }
4992788fa27SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5002788fa27SJeremy L Thompson }
5012788fa27SJeremy L Thompson 
5022788fa27SJeremy L Thompson /**
503ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field values of the specified type, read-only.
5044385fb7fSSebastian Grimberg 
505ca94c3ddSJeremy L Thompson   For composite operators, the values restored are for the first sub-operator `CeedQFunctionContext` that have a matching `field_name`.
506ca94c3ddSJeremy L Thompson   A non-zero error code is returned for single operators that do not have a matching field of the same type or composite operators that do not have any field of a matching type.
5072788fa27SJeremy L Thompson 
508ca94c3ddSJeremy L Thompson   @param[in,out] op          `CeedOperator`
5092788fa27SJeremy L Thompson   @param[in]     field_label Label of field to set
5102788fa27SJeremy L Thompson   @param[in]     field_type  Type of field to set
511c5d0f995SJed Brown   @param[in]     values      Values array to restore
5122788fa27SJeremy L Thompson 
5132788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5142788fa27SJeremy L Thompson 
5156ab8e59fSJames Wright   @ref Developer
5162788fa27SJeremy L Thompson **/
CeedOperatorContextRestoreGenericRead(CeedOperator op,CeedContextFieldLabel field_label,CeedContextFieldType field_type,void * values)5172788fa27SJeremy L Thompson static int CeedOperatorContextRestoreGenericRead(CeedOperator op, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) {
5181c66c397SJeremy L Thompson   bool is_composite = false;
5191c66c397SJeremy L Thompson 
5209bc66399SJeremy L Thompson   CeedCheck(field_label, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "Invalid field label");
5212788fa27SJeremy L Thompson 
5225ac9af79SJeremy L Thompson   // Check if field_label and op correspond
5235ac9af79SJeremy L Thompson   if (field_label->from_op) {
5245ac9af79SJeremy L Thompson     CeedInt index = -1;
5255ac9af79SJeremy L Thompson 
5265ac9af79SJeremy L Thompson     for (CeedInt i = 0; i < op->num_context_labels; i++) {
5275ac9af79SJeremy L Thompson       if (op->context_labels[i] == field_label) index = i;
5285ac9af79SJeremy L Thompson     }
5299bc66399SJeremy L Thompson     CeedCheck(index != -1, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "ContextFieldLabel does not correspond to the operator");
5305ac9af79SJeremy L Thompson   }
5315ac9af79SJeremy L Thompson 
5322788fa27SJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
5332788fa27SJeremy L Thompson   if (is_composite) {
5342788fa27SJeremy L Thompson     CeedInt       num_sub;
5352788fa27SJeremy L Thompson     CeedOperator *sub_operators;
5362788fa27SJeremy L Thompson 
537ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_sub));
538ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
5399bc66399SJeremy L Thompson     CeedCheck(num_sub == field_label->num_sub_labels, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED,
5409bc66399SJeremy L Thompson               "Composite operator modified after ContextFieldLabel created");
5412788fa27SJeremy L Thompson 
5422788fa27SJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
5431203703bSJeremy L Thompson       CeedQFunctionContext ctx;
5441203703bSJeremy L Thompson 
5451485364cSJeremy L Thompson       CeedCall(CeedOperatorGetContext(sub_operators[i], &ctx));
5462788fa27SJeremy L Thompson       // Try every sub-operator, ok if some sub-operators do not have field
5471485364cSJeremy L Thompson       if (ctx && field_label->sub_labels[i]) {
5481203703bSJeremy L Thompson         CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label->sub_labels[i], field_type, values));
5491485364cSJeremy L Thompson         CeedCall(CeedQFunctionContextDestroy(&ctx));
5502788fa27SJeremy L Thompson         return CEED_ERROR_SUCCESS;
5512788fa27SJeremy L Thompson       }
5521485364cSJeremy L Thompson       CeedCall(CeedQFunctionContextDestroy(&ctx));
5532788fa27SJeremy L Thompson     }
5542788fa27SJeremy L Thompson   } else {
5551203703bSJeremy L Thompson     CeedQFunctionContext ctx;
5561203703bSJeremy L Thompson 
5571485364cSJeremy L Thompson     CeedCall(CeedOperatorGetContext(op, &ctx));
5589bc66399SJeremy L Thompson     CeedCheck(ctx, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED, "QFunction does not have context data");
5591203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, field_type, values));
5601485364cSJeremy L Thompson     CeedCall(CeedQFunctionContextDestroy(&ctx));
561d8dd9a91SJeremy L Thompson   }
562d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
563d8dd9a91SJeremy L Thompson }
564d8dd9a91SJeremy L Thompson 
5657a982d89SJeremy L. Thompson /// @}
5667a982d89SJeremy L. Thompson 
5677a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5687a982d89SJeremy L. Thompson /// CeedOperator Backend API
5697a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5707a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
5717a982d89SJeremy L. Thompson /// @{
5727a982d89SJeremy L. Thompson 
5737a982d89SJeremy L. Thompson /**
574ca94c3ddSJeremy L Thompson   @brief Get the number of arguments associated with a `CeedOperator`
5757a982d89SJeremy L. Thompson 
576ca94c3ddSJeremy L Thompson   @param[in]  op        `CeedOperator`
577d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
5787a982d89SJeremy L. Thompson 
5797a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5807a982d89SJeremy L. Thompson 
5817a982d89SJeremy L. Thompson   @ref Backend
5827a982d89SJeremy L. Thompson **/
CeedOperatorGetNumArgs(CeedOperator op,CeedInt * num_args)583d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
5841203703bSJeremy L Thompson   bool is_composite;
5851203703bSJeremy L Thompson 
5861203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
5876e536b99SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Not defined for composite operators");
588d1d35e2fSjeremylt   *num_args = op->num_fields;
589e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5907a982d89SJeremy L. Thompson }
5917a982d89SJeremy L. Thompson 
5927a982d89SJeremy L. Thompson /**
5939463e855SJeremy L Thompson   @brief Get the tensor product status of all bases for a `CeedOperator`.
5949463e855SJeremy L Thompson 
5959463e855SJeremy L Thompson   `has_tensor_bases` is only set to `true` if every field uses a tensor-product basis.
5969463e855SJeremy L Thompson 
5979463e855SJeremy L Thompson   @param[in]  op               `CeedOperator`
5989463e855SJeremy L Thompson   @param[out] has_tensor_bases Variable to store tensor bases status
5999463e855SJeremy L Thompson 
6009463e855SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
6019463e855SJeremy L Thompson 
6029463e855SJeremy L Thompson   @ref Backend
6039463e855SJeremy L Thompson **/
CeedOperatorHasTensorBases(CeedOperator op,bool * has_tensor_bases)6049463e855SJeremy L Thompson int CeedOperatorHasTensorBases(CeedOperator op, bool *has_tensor_bases) {
6059463e855SJeremy L Thompson   CeedInt            num_inputs, num_outputs;
6069463e855SJeremy L Thompson   CeedOperatorField *input_fields, *output_fields;
6079463e855SJeremy L Thompson 
6089463e855SJeremy L Thompson   CeedCall(CeedOperatorGetFields(op, &num_inputs, &input_fields, &num_outputs, &output_fields));
6099463e855SJeremy L Thompson   *has_tensor_bases = true;
6109463e855SJeremy L Thompson   for (CeedInt i = 0; i < num_inputs; i++) {
6119463e855SJeremy L Thompson     bool      is_tensor;
6129463e855SJeremy L Thompson     CeedBasis basis;
6139463e855SJeremy L Thompson 
6149463e855SJeremy L Thompson     CeedCall(CeedOperatorFieldGetBasis(input_fields[i], &basis));
6159463e855SJeremy L Thompson     if (basis != CEED_BASIS_NONE) {
6169463e855SJeremy L Thompson       CeedCall(CeedBasisIsTensor(basis, &is_tensor));
617025ec10cSJeremy L Thompson       *has_tensor_bases = *has_tensor_bases & is_tensor;
6189463e855SJeremy L Thompson     }
619681d0ea7SJeremy L Thompson     CeedCall(CeedBasisDestroy(&basis));
6209463e855SJeremy L Thompson   }
6219463e855SJeremy L Thompson   for (CeedInt i = 0; i < num_outputs; i++) {
6229463e855SJeremy L Thompson     bool      is_tensor;
6239463e855SJeremy L Thompson     CeedBasis basis;
6249463e855SJeremy L Thompson 
6259463e855SJeremy L Thompson     CeedCall(CeedOperatorFieldGetBasis(output_fields[i], &basis));
6269463e855SJeremy L Thompson     if (basis != CEED_BASIS_NONE) {
6279463e855SJeremy L Thompson       CeedCall(CeedBasisIsTensor(basis, &is_tensor));
628025ec10cSJeremy L Thompson       *has_tensor_bases = *has_tensor_bases & is_tensor;
6299463e855SJeremy L Thompson     }
630681d0ea7SJeremy L Thompson     CeedCall(CeedBasisDestroy(&basis));
6319463e855SJeremy L Thompson   }
6329463e855SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6339463e855SJeremy L Thompson }
6349463e855SJeremy L Thompson 
6359463e855SJeremy L Thompson /**
6361203703bSJeremy L Thompson   @brief Get a boolean value indicating if the `CeedOperator` is immutable
6371203703bSJeremy L Thompson 
6381203703bSJeremy L Thompson   @param[in]  op           `CeedOperator`
6391203703bSJeremy L Thompson   @param[out] is_immutable Variable to store immutability status
6401203703bSJeremy L Thompson 
6411203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
6421203703bSJeremy L Thompson 
6431203703bSJeremy L Thompson   @ref Backend
6441203703bSJeremy L Thompson **/
CeedOperatorIsImmutable(CeedOperator op,bool * is_immutable)6451203703bSJeremy L Thompson int CeedOperatorIsImmutable(CeedOperator op, bool *is_immutable) {
6461203703bSJeremy L Thompson   *is_immutable = op->is_immutable;
6471203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
6481203703bSJeremy L Thompson }
6491203703bSJeremy L Thompson 
6501203703bSJeremy L Thompson /**
651ca94c3ddSJeremy L Thompson   @brief Get the setup status of a `CeedOperator`
6527a982d89SJeremy L. Thompson 
653ca94c3ddSJeremy L Thompson   @param[in]  op            `CeedOperator`
654d1d35e2fSjeremylt   @param[out] is_setup_done Variable to store setup status
6557a982d89SJeremy L. Thompson 
6567a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6577a982d89SJeremy L. Thompson 
6587a982d89SJeremy L. Thompson   @ref Backend
6597a982d89SJeremy L. Thompson **/
CeedOperatorIsSetupDone(CeedOperator op,bool * is_setup_done)660d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
661f04ea552SJeremy L Thompson   *is_setup_done = op->is_backend_setup;
662e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6637a982d89SJeremy L. Thompson }
6647a982d89SJeremy L. Thompson 
6657a982d89SJeremy L. Thompson /**
666ca94c3ddSJeremy L Thompson   @brief Get the `CeedQFunction` associated with a `CeedOperator`
6677a982d89SJeremy L. Thompson 
668ca94c3ddSJeremy L Thompson   @param[in]  op `CeedOperator`
669ca94c3ddSJeremy L Thompson   @param[out] qf Variable to store `CeedQFunction`
6707a982d89SJeremy L. Thompson 
6717a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6727a982d89SJeremy L. Thompson 
6737a982d89SJeremy L. Thompson   @ref Backend
6747a982d89SJeremy L. Thompson **/
CeedOperatorGetQFunction(CeedOperator op,CeedQFunction * qf)6757a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
6761203703bSJeremy L Thompson   bool is_composite;
6771203703bSJeremy L Thompson 
6781203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
6796e536b99SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Not defined for composite operator");
680c11e12f4SJeremy L Thompson   *qf = NULL;
681c11e12f4SJeremy L Thompson   CeedCall(CeedQFunctionReferenceCopy(op->qf, qf));
682e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6837a982d89SJeremy L. Thompson }
6847a982d89SJeremy L. Thompson 
6857a982d89SJeremy L. Thompson /**
686ca94c3ddSJeremy L Thompson   @brief Get a boolean value indicating if the `CeedOperator` is composite
687c04a41a7SJeremy L Thompson 
688ca94c3ddSJeremy L Thompson   @param[in]  op           `CeedOperator`
689d1d35e2fSjeremylt   @param[out] is_composite Variable to store composite status
690c04a41a7SJeremy L Thompson 
691c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
692c04a41a7SJeremy L Thompson 
693c04a41a7SJeremy L Thompson   @ref Backend
694c04a41a7SJeremy L Thompson **/
CeedOperatorIsComposite(CeedOperator op,bool * is_composite)695d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
696f04ea552SJeremy L Thompson   *is_composite = op->is_composite;
697e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
698c04a41a7SJeremy L Thompson }
699c04a41a7SJeremy L Thompson 
700c04a41a7SJeremy L Thompson /**
701ca94c3ddSJeremy L Thompson   @brief Get the backend data of a `CeedOperator`
7027a982d89SJeremy L. Thompson 
703ca94c3ddSJeremy L Thompson   @param[in]  op   `CeedOperator`
7047a982d89SJeremy L. Thompson   @param[out] data Variable to store data
7057a982d89SJeremy L. Thompson 
7067a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
7077a982d89SJeremy L. Thompson 
7087a982d89SJeremy L. Thompson   @ref Backend
7097a982d89SJeremy L. Thompson **/
CeedOperatorGetData(CeedOperator op,void * data)710777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
711777ff853SJeremy L Thompson   *(void **)data = op->data;
712e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7137a982d89SJeremy L. Thompson }
7147a982d89SJeremy L. Thompson 
7157a982d89SJeremy L. Thompson /**
716ca94c3ddSJeremy L Thompson   @brief Set the backend data of a `CeedOperator`
7177a982d89SJeremy L. Thompson 
718ca94c3ddSJeremy L Thompson   @param[in,out] op   `CeedOperator`
719ea61e9acSJeremy L Thompson   @param[in]     data Data to set
7207a982d89SJeremy L. Thompson 
7217a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
7227a982d89SJeremy L. Thompson 
7237a982d89SJeremy L. Thompson   @ref Backend
7247a982d89SJeremy L. Thompson **/
CeedOperatorSetData(CeedOperator op,void * data)725777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
726777ff853SJeremy L Thompson   op->data = data;
727e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7287a982d89SJeremy L. Thompson }
7297a982d89SJeremy L. Thompson 
7307a982d89SJeremy L. Thompson /**
731ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedOperator`
73234359f16Sjeremylt 
733ca94c3ddSJeremy L Thompson   @param[in,out] op `CeedOperator` to increment the reference counter
73434359f16Sjeremylt 
73534359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
73634359f16Sjeremylt 
73734359f16Sjeremylt   @ref Backend
73834359f16Sjeremylt **/
CeedOperatorReference(CeedOperator op)7399560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
740b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectReference((CeedObject)op));
74134359f16Sjeremylt   return CEED_ERROR_SUCCESS;
74234359f16Sjeremylt }
74334359f16Sjeremylt 
74434359f16Sjeremylt /**
745ca94c3ddSJeremy L Thompson   @brief Set the setup flag of a `CeedOperator` to `true`
7467a982d89SJeremy L. Thompson 
747ca94c3ddSJeremy L Thompson   @param[in,out] op `CeedOperator`
7487a982d89SJeremy L. Thompson 
7497a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
7507a982d89SJeremy L. Thompson 
7517a982d89SJeremy L. Thompson   @ref Backend
7527a982d89SJeremy L. Thompson **/
CeedOperatorSetSetupDone(CeedOperator op)7537a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
754f04ea552SJeremy L Thompson   op->is_backend_setup = true;
755e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7567a982d89SJeremy L. Thompson }
7577a982d89SJeremy L. Thompson 
7587a982d89SJeremy L. Thompson /// @}
7597a982d89SJeremy L. Thompson 
7607a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
7617a982d89SJeremy L. Thompson /// CeedOperator Public API
7627a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
7637a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
764dfdf5a53Sjeremylt /// @{
765d7b241e6Sjeremylt 
766d7b241e6Sjeremylt /**
767ca94c3ddSJeremy L Thompson   @brief Create a `CeedOperator` and associate a `CeedQFunction`.
7684385fb7fSSebastian Grimberg 
769ca94c3ddSJeremy L Thompson   A `CeedBasis` and `CeedElemRestriction` can be associated with `CeedQFunction` fields with @ref CeedOperatorSetField().
770d7b241e6Sjeremylt 
771ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedOperator`
772ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction` defining the action of the operator at quadrature points
773ca94c3ddSJeremy L Thompson   @param[in]  dqf  `CeedQFunction` defining the action of the Jacobian of `qf` (or @ref CEED_QFUNCTION_NONE)
774ca94c3ddSJeremy L Thompson   @param[in]  dqfT `CeedQFunction` defining the action of the transpose of the Jacobian of `qf` (or @ref CEED_QFUNCTION_NONE)
775ca94c3ddSJeremy L Thompson   @param[out] op   Address of the variable where the newly created `CeedOperator` will be stored
776b11c1e72Sjeremylt 
777b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
778dfdf5a53Sjeremylt 
7797a982d89SJeremy L. Thompson   @ref User
780d7b241e6Sjeremylt  */
CeedOperatorCreate(Ceed ceed,CeedQFunction qf,CeedQFunction dqf,CeedQFunction dqfT,CeedOperator * op)7812b730f8bSJeremy L Thompson int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, CeedQFunction dqfT, CeedOperator *op) {
7825fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
7835fe0d4faSjeremylt     Ceed delegate;
7846574a04fSJeremy L Thompson 
7852b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Operator"));
7861ef3a2a9SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedOperatorCreate");
7872b730f8bSJeremy L Thompson     CeedCall(CeedOperatorCreate(delegate, qf, dqf, dqfT, op));
7889bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
789e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7905fe0d4faSjeremylt   }
7915fe0d4faSjeremylt 
792ca94c3ddSJeremy L Thompson   CeedCheck(qf && qf != CEED_QFUNCTION_NONE, ceed, CEED_ERROR_MINOR, "Operator must have a valid CeedQFunction.");
793db002c03SJeremy L Thompson 
7942b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, op));
7956c328a79SJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedOperatorView_Object, CeedOperatorDestroy_Object, &(*op)->obj));
7962b104005SJeremy L Thompson   (*op)->input_size  = -1;
7972b104005SJeremy L Thompson   (*op)->output_size = -1;
798db002c03SJeremy L Thompson   CeedCall(CeedQFunctionReferenceCopy(qf, &(*op)->qf));
799db002c03SJeremy L Thompson   if (dqf && dqf != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionReferenceCopy(dqf, &(*op)->dqf));
800db002c03SJeremy L Thompson   if (dqfT && dqfT != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionReferenceCopy(dqfT, &(*op)->dqfT));
8012b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields));
8022b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields));
8032b730f8bSJeremy L Thompson   CeedCall(ceed->OperatorCreate(*op));
804e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
805d7b241e6Sjeremylt }
806d7b241e6Sjeremylt 
807d7b241e6Sjeremylt /**
808ca94c3ddSJeremy L Thompson   @brief Create a `CeedOperator` for evaluation at evaluation at arbitrary points in each element.
80948acf710SJeremy L Thompson 
810ca94c3ddSJeremy L Thompson   A `CeedBasis` and `CeedElemRestriction` can be associated with `CeedQFunction` fields with `CeedOperator` SetField.
811ca94c3ddSJeremy L Thompson   The locations of each point are set with @ref CeedOperatorAtPointsSetPoints().
81248acf710SJeremy L Thompson 
813ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedOperator`
814ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction` defining the action of the operator at quadrature points
815ca94c3ddSJeremy L Thompson   @param[in]  dqf  `CeedQFunction` defining the action of the Jacobian of @a qf (or @ref CEED_QFUNCTION_NONE)
816ca94c3ddSJeremy L Thompson   @param[in]  dqfT `CeedQFunction` defining the action of the transpose of the Jacobian of @a qf (or @ref CEED_QFUNCTION_NONE)
81748acf710SJeremy L Thompson   @param[out] op   Address of the variable where the newly created CeedOperator will be stored
81848acf710SJeremy L Thompson 
81948acf710SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
82048acf710SJeremy L Thompson 
82148acf710SJeremy L Thompson   @ref User
82248acf710SJeremy L Thompson  */
CeedOperatorCreateAtPoints(Ceed ceed,CeedQFunction qf,CeedQFunction dqf,CeedQFunction dqfT,CeedOperator * op)82348acf710SJeremy L Thompson int CeedOperatorCreateAtPoints(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, CeedQFunction dqfT, CeedOperator *op) {
82448acf710SJeremy L Thompson   if (!ceed->OperatorCreateAtPoints) {
82548acf710SJeremy L Thompson     Ceed delegate;
82648acf710SJeremy L Thompson 
82748acf710SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Operator"));
8281ef3a2a9SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedOperatorCreateAtPoints");
82948acf710SJeremy L Thompson     CeedCall(CeedOperatorCreateAtPoints(delegate, qf, dqf, dqfT, op));
8309bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
83148acf710SJeremy L Thompson     return CEED_ERROR_SUCCESS;
83248acf710SJeremy L Thompson   }
83348acf710SJeremy L Thompson 
834ca94c3ddSJeremy L Thompson   CeedCheck(qf && qf != CEED_QFUNCTION_NONE, ceed, CEED_ERROR_MINOR, "Operator must have a valid CeedQFunction.");
83548acf710SJeremy L Thompson 
83648acf710SJeremy L Thompson   CeedCall(CeedCalloc(1, op));
8376c328a79SJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedOperatorView_Object, CeedOperatorDestroy_Object, &(*op)->obj));
83848acf710SJeremy L Thompson   (*op)->is_at_points = true;
83948acf710SJeremy L Thompson   (*op)->input_size   = -1;
84048acf710SJeremy L Thompson   (*op)->output_size  = -1;
84148acf710SJeremy L Thompson   CeedCall(CeedQFunctionReferenceCopy(qf, &(*op)->qf));
84248acf710SJeremy L Thompson   if (dqf && dqf != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionReferenceCopy(dqf, &(*op)->dqf));
84348acf710SJeremy L Thompson   if (dqfT && dqfT != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionReferenceCopy(dqfT, &(*op)->dqfT));
84448acf710SJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields));
84548acf710SJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields));
84648acf710SJeremy L Thompson   CeedCall(ceed->OperatorCreateAtPoints(*op));
84748acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84848acf710SJeremy L Thompson }
84948acf710SJeremy L Thompson 
85048acf710SJeremy L Thompson /**
851ca94c3ddSJeremy L Thompson   @brief Create a composite `CeedOperator` that composes the action of several `CeedOperator`
85252d6035fSJeremy L Thompson 
853ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedOperator`
854ca94c3ddSJeremy L Thompson   @param[out] op   Address of the variable where the newly created composite `CeedOperator` will be stored
85552d6035fSJeremy L Thompson 
85652d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
85752d6035fSJeremy L Thompson 
8587a982d89SJeremy L. Thompson   @ref User
85952d6035fSJeremy L Thompson  */
CeedOperatorCreateComposite(Ceed ceed,CeedOperator * op)860ed094490SJeremy L Thompson int CeedOperatorCreateComposite(Ceed ceed, CeedOperator *op) {
86152d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
86252d6035fSJeremy L Thompson     Ceed delegate;
86352d6035fSJeremy L Thompson 
8641c66c397SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Operator"));
865250756a7Sjeremylt     if (delegate) {
866ed094490SJeremy L Thompson       CeedCall(CeedOperatorCreateComposite(delegate, op));
8679bc66399SJeremy L Thompson       CeedCall(CeedDestroy(&delegate));
868e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
86952d6035fSJeremy L Thompson     }
870250756a7Sjeremylt   }
87152d6035fSJeremy L Thompson 
8722b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, op));
8736c328a79SJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedOperatorView_Object, CeedOperatorDestroy_Object, &(*op)->obj));
874f04ea552SJeremy L Thompson   (*op)->is_composite = true;
8752b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators));
8762b104005SJeremy L Thompson   (*op)->input_size  = -1;
8772b104005SJeremy L Thompson   (*op)->output_size = -1;
878250756a7Sjeremylt 
879db002c03SJeremy L Thompson   if (ceed->CompositeOperatorCreate) CeedCall(ceed->CompositeOperatorCreate(*op));
880e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
88152d6035fSJeremy L Thompson }
88252d6035fSJeremy L Thompson 
88352d6035fSJeremy L Thompson /**
884ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedOperator`.
8854385fb7fSSebastian Grimberg 
886ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedOperatorDestroy().
887512bb800SJeremy L Thompson 
888ca94c3ddSJeremy L Thompson   Note: If the value of `*op_copy` passed to this function is non-`NULL`, then it is assumed that `*op_copy` is a pointer to a `CeedOperator`.
889ca94c3ddSJeremy L Thompson         This `CeedOperator` will be destroyed if `*op_copy` is the only reference to this `CeedOperator`.
8909560d06aSjeremylt 
891ca94c3ddSJeremy L Thompson   @param[in]     op      `CeedOperator` to copy reference to
892ea61e9acSJeremy L Thompson   @param[in,out] op_copy Variable to store copied reference
8939560d06aSjeremylt 
8949560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
8959560d06aSjeremylt 
8969560d06aSjeremylt   @ref User
8979560d06aSjeremylt **/
CeedOperatorReferenceCopy(CeedOperator op,CeedOperator * op_copy)8989560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
8992b730f8bSJeremy L Thompson   CeedCall(CeedOperatorReference(op));
9002b730f8bSJeremy L Thompson   CeedCall(CeedOperatorDestroy(op_copy));
9019560d06aSjeremylt   *op_copy = op;
9029560d06aSjeremylt   return CEED_ERROR_SUCCESS;
9039560d06aSjeremylt }
9049560d06aSjeremylt 
9059560d06aSjeremylt /**
906ca94c3ddSJeremy L Thompson   @brief Provide a field to a `CeedOperator` for use by its `CeedQFunction`.
907d7b241e6Sjeremylt 
908ca94c3ddSJeremy L Thompson   This function is used to specify both active and passive fields to a `CeedOperator`.
909bafebce1SSebastian Grimberg   For passive fields, a `CeedVector` `vec` must be provided.
910ea61e9acSJeremy L Thompson   Passive fields can inputs or outputs (updated in-place when operator is applied).
911d7b241e6Sjeremylt 
912ca94c3ddSJeremy L Thompson   Active fields must be specified using this function, but their data (in a `CeedVector`) is passed in @ref CeedOperatorApply().
913ca94c3ddSJeremy L Thompson   There can be at most one active input `CeedVector` and at most one active output@ref  CeedVector passed to @ref CeedOperatorApply().
914d7b241e6Sjeremylt 
915528a22edSJeremy L Thompson   The number of quadrature points must agree across all points.
916bafebce1SSebastian Grimberg   When using @ref CEED_BASIS_NONE, the number of quadrature points is determined by the element size of `rstr`.
917528a22edSJeremy L Thompson 
918ca94c3ddSJeremy L Thompson   @param[in,out] op         `CeedOperator` on which to provide the field
919ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of the field (to be matched with the name used by `CeedQFunction`)
920bafebce1SSebastian Grimberg   @param[in]     rstr       `CeedElemRestriction`
921bafebce1SSebastian Grimberg   @param[in]     basis      `CeedBasis` in which the field resides or @ref CEED_BASIS_NONE if collocated with quadrature points
922bafebce1SSebastian Grimberg   @param[in]     vec        `CeedVector` to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE if field is active or @ref CEED_VECTOR_NONE if using @ref CEED_EVAL_WEIGHT in the `CeedQFunction`
923b11c1e72Sjeremylt 
924b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
925dfdf5a53Sjeremylt 
9267a982d89SJeremy L. Thompson   @ref User
927b11c1e72Sjeremylt **/
CeedOperatorSetField(CeedOperator op,const char * field_name,CeedElemRestriction rstr,CeedBasis basis,CeedVector vec)928bafebce1SSebastian Grimberg int CeedOperatorSetField(CeedOperator op, const char *field_name, CeedElemRestriction rstr, CeedBasis basis, CeedVector vec) {
9291203703bSJeremy L Thompson   bool               is_input = true, is_at_points, is_composite, is_immutable;
9301203703bSJeremy L Thompson   CeedInt            num_elem = 0, num_qpts = 0, num_input_fields, num_output_fields;
9311203703bSJeremy L Thompson   CeedQFunction      qf;
9321203703bSJeremy L Thompson   CeedQFunctionField qf_field, *qf_input_fields, *qf_output_fields;
9331c66c397SJeremy L Thompson   CeedOperatorField *op_field;
9341c66c397SJeremy L Thompson 
9351203703bSJeremy L Thompson   CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
9361203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
9371203703bSJeremy L Thompson   CeedCall(CeedOperatorIsImmutable(op, &is_immutable));
9389bc66399SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE, "Cannot add field to composite operator.");
9399bc66399SJeremy L Thompson   CeedCheck(!is_immutable, CeedOperatorReturnCeed(op), CEED_ERROR_MAJOR, "Operator cannot be changed after set as immutable");
9409bc66399SJeremy L Thompson   CeedCheck(rstr, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE, "CeedElemRestriction rstr for field \"%s\" must be non-NULL.", field_name);
9419bc66399SJeremy L Thompson   CeedCheck(basis, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE, "CeedBasis basis for field \"%s\" must be non-NULL.", field_name);
9429bc66399SJeremy L Thompson   CeedCheck(vec, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE, "CeedVector vec for field \"%s\" must be non-NULL.", field_name);
94352d6035fSJeremy L Thompson 
944bafebce1SSebastian Grimberg   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
9459bc66399SJeremy L Thompson   CeedCheck(rstr == CEED_ELEMRESTRICTION_NONE || !op->has_restriction || num_elem == op->num_elem, CeedOperatorReturnCeed(op), CEED_ERROR_DIMENSION,
946ca94c3ddSJeremy L Thompson             "CeedElemRestriction with %" CeedInt_FMT " elements incompatible with prior %" CeedInt_FMT " elements", num_elem, op->num_elem);
9472c7e7413SJeremy L Thompson   {
9482c7e7413SJeremy L Thompson     CeedRestrictionType rstr_type;
9492c7e7413SJeremy L Thompson 
950bafebce1SSebastian Grimberg     CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
95148acf710SJeremy L Thompson     if (rstr_type == CEED_RESTRICTION_POINTS) {
9529bc66399SJeremy L Thompson       CeedCheck(is_at_points, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED,
9539bc66399SJeremy L Thompson                 "CeedElemRestriction AtPoints not supported for standard operator fields");
9549bc66399SJeremy L Thompson       CeedCheck(basis == CEED_BASIS_NONE, CeedOperatorReturnCeed(op), CEED_ERROR_UNSUPPORTED,
9559bc66399SJeremy L Thompson                 "CeedElemRestriction AtPoints must be used with CEED_BASIS_NONE");
95648acf710SJeremy L Thompson       if (!op->first_points_rstr) {
957bafebce1SSebastian Grimberg         CeedCall(CeedElemRestrictionReferenceCopy(rstr, &op->first_points_rstr));
95848acf710SJeremy L Thompson       } else {
95948acf710SJeremy L Thompson         bool are_compatible;
96048acf710SJeremy L Thompson 
961bafebce1SSebastian Grimberg         CeedCall(CeedElemRestrictionAtPointsAreCompatible(op->first_points_rstr, rstr, &are_compatible));
9629bc66399SJeremy L Thompson         CeedCheck(are_compatible, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE,
963ca94c3ddSJeremy L Thompson                   "CeedElemRestriction must have compatible offsets with previously set CeedElemRestriction");
96448acf710SJeremy L Thompson       }
96548acf710SJeremy L Thompson     }
9662c7e7413SJeremy L Thompson   }
967d7b241e6Sjeremylt 
968bafebce1SSebastian Grimberg   if (basis == CEED_BASIS_NONE) CeedCall(CeedElemRestrictionGetElementSize(rstr, &num_qpts));
969bafebce1SSebastian Grimberg   else CeedCall(CeedBasisGetNumQuadraturePoints(basis, &num_qpts));
9709bc66399SJeremy L Thompson   CeedCheck(op->num_qpts == 0 || num_qpts == op->num_qpts, CeedOperatorReturnCeed(op), CEED_ERROR_DIMENSION,
971ca94c3ddSJeremy L Thompson             "%s must correspond to the same number of quadrature points as previously added CeedBases. Found %" CeedInt_FMT
972528a22edSJeremy L Thompson             " quadrature points but expected %" CeedInt_FMT " quadrature points.",
973bafebce1SSebastian Grimberg             basis == CEED_BASIS_NONE ? "CeedElemRestriction" : "CeedBasis", num_qpts, op->num_qpts);
9741203703bSJeremy L Thompson 
9751203703bSJeremy L Thompson   CeedCall(CeedOperatorGetQFunction(op, &qf));
9761203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetFields(qf, &num_input_fields, &qf_input_fields, &num_output_fields, &qf_output_fields));
977c11e12f4SJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&qf));
9781203703bSJeremy L Thompson   for (CeedInt i = 0; i < num_input_fields; i++) {
9796f8994e9SJeremy L Thompson     const char *qf_field_name;
9801203703bSJeremy L Thompson 
9811203703bSJeremy L Thompson     CeedCall(CeedQFunctionFieldGetName(qf_input_fields[i], &qf_field_name));
9821203703bSJeremy L Thompson     if (!strcmp(field_name, qf_field_name)) {
9831203703bSJeremy L Thompson       qf_field = qf_input_fields[i];
984d1d35e2fSjeremylt       op_field = &op->input_fields[i];
985d7b241e6Sjeremylt       goto found;
986d7b241e6Sjeremylt     }
987d7b241e6Sjeremylt   }
9882b104005SJeremy L Thompson   is_input = false;
9891203703bSJeremy L Thompson   for (CeedInt i = 0; i < num_output_fields; i++) {
9906f8994e9SJeremy L Thompson     const char *qf_field_name;
9911203703bSJeremy L Thompson 
9921203703bSJeremy L Thompson     CeedCall(CeedQFunctionFieldGetName(qf_output_fields[i], &qf_field_name));
9931203703bSJeremy L Thompson     if (!strcmp(field_name, qf_field_name)) {
9941203703bSJeremy L Thompson       qf_field = qf_output_fields[i];
995d1d35e2fSjeremylt       op_field = &op->output_fields[i];
996d7b241e6Sjeremylt       goto found;
997d7b241e6Sjeremylt     }
998d7b241e6Sjeremylt   }
999c042f62fSJeremy L Thompson   // LCOV_EXCL_START
10009bc66399SJeremy L Thompson   return CeedError(CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "CeedQFunction has no knowledge of field '%s'", field_name);
1001c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1002d7b241e6Sjeremylt found:
10039bc66399SJeremy L Thompson   CeedCall(CeedOperatorCheckField(CeedOperatorReturnCeed(op), qf_field, rstr, basis));
10042b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, op_field));
1005e15f9bd0SJeremy L Thompson 
1006bafebce1SSebastian Grimberg   if (vec == CEED_VECTOR_ACTIVE) {
10072b104005SJeremy L Thompson     CeedSize l_size;
10081c66c397SJeremy L Thompson 
1009bafebce1SSebastian Grimberg     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
10102b104005SJeremy L Thompson     if (is_input) {
10112b104005SJeremy L Thompson       if (op->input_size == -1) op->input_size = l_size;
10129bc66399SJeremy L Thompson       CeedCheck(l_size == op->input_size, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE,
1013249f8407SJeremy L Thompson                 "LVector size %" CeedSize_FMT " does not match previous size %" CeedSize_FMT "", l_size, op->input_size);
10142b104005SJeremy L Thompson     } else {
10152b104005SJeremy L Thompson       if (op->output_size == -1) op->output_size = l_size;
10169bc66399SJeremy L Thompson       CeedCheck(l_size == op->output_size, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE,
1017249f8407SJeremy L Thompson                 "LVector size %" CeedSize_FMT " does not match previous size %" CeedSize_FMT "", l_size, op->output_size);
10182b104005SJeremy L Thompson     }
10192b730f8bSJeremy L Thompson   }
10202b104005SJeremy L Thompson 
1021bafebce1SSebastian Grimberg   CeedCall(CeedVectorReferenceCopy(vec, &(*op_field)->vec));
1022bafebce1SSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*op_field)->elem_rstr));
1023bafebce1SSebastian Grimberg   if (rstr != CEED_ELEMRESTRICTION_NONE && !op->has_restriction) {
1024d1d35e2fSjeremylt     op->num_elem        = num_elem;
1025d1d35e2fSjeremylt     op->has_restriction = true;  // Restriction set, but num_elem may be 0
1026e15f9bd0SJeremy L Thompson   }
1027bafebce1SSebastian Grimberg   CeedCall(CeedBasisReferenceCopy(basis, &(*op_field)->basis));
10282a3ff1c9SZach Atkins   if (op->num_qpts == 0 && !is_at_points) op->num_qpts = num_qpts;  // no consistent number of qpts for OperatorAtPoints
1029d1d35e2fSjeremylt   op->num_fields += 1;
10302b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name));
1031e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1032d7b241e6Sjeremylt }
1033d7b241e6Sjeremylt 
1034d7b241e6Sjeremylt /**
1035ca94c3ddSJeremy L Thompson   @brief Get the `CeedOperator` Field of a `CeedOperator`.
103643bbe138SJeremy L Thompson 
1037ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
1038f04ea552SJeremy L Thompson 
1039ca94c3ddSJeremy L Thompson   @param[in]  op                `CeedOperator`
1040f74ec584SJeremy L Thompson   @param[out] num_input_fields  Variable to store number of input fields
1041ca94c3ddSJeremy L Thompson   @param[out] input_fields      Variable to store input fields
1042f74ec584SJeremy L Thompson   @param[out] num_output_fields Variable to store number of output fields
1043ca94c3ddSJeremy L Thompson   @param[out] output_fields     Variable to store output fields
104443bbe138SJeremy L Thompson 
104543bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
104643bbe138SJeremy L Thompson 
1047e9b533fbSJeremy L Thompson   @ref Advanced
104843bbe138SJeremy L Thompson **/
CeedOperatorGetFields(CeedOperator op,CeedInt * num_input_fields,CeedOperatorField ** input_fields,CeedInt * num_output_fields,CeedOperatorField ** output_fields)10492b730f8bSJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields, CeedOperatorField **input_fields, CeedInt *num_output_fields,
105043bbe138SJeremy L Thompson                           CeedOperatorField **output_fields) {
10511203703bSJeremy L Thompson   bool          is_composite;
10521203703bSJeremy L Thompson   CeedQFunction qf;
10531203703bSJeremy L Thompson 
10541203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
10556e536b99SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Not defined for composite operator");
10562b730f8bSJeremy L Thompson   CeedCall(CeedOperatorCheckReady(op));
105743bbe138SJeremy L Thompson 
10581203703bSJeremy L Thompson   CeedCall(CeedOperatorGetQFunction(op, &qf));
10591203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetFields(qf, num_input_fields, NULL, num_output_fields, NULL));
1060c11e12f4SJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&qf));
106143bbe138SJeremy L Thompson   if (input_fields) *input_fields = op->input_fields;
106243bbe138SJeremy L Thompson   if (output_fields) *output_fields = op->output_fields;
106343bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
106443bbe138SJeremy L Thompson }
106543bbe138SJeremy L Thompson 
106643bbe138SJeremy L Thompson /**
1067ca94c3ddSJeremy L Thompson   @brief Set the arbitrary points in each element for a `CeedOperator` at points.
106848acf710SJeremy L Thompson 
1069ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
107048acf710SJeremy L Thompson 
1071ca94c3ddSJeremy L Thompson   @param[in,out] op           `CeedOperator` at points
1072ca94c3ddSJeremy L Thompson   @param[in]     rstr_points  `CeedElemRestriction` for the coordinates of each point by element
1073ca94c3ddSJeremy L Thompson   @param[in]     point_coords `CeedVector` holding coordinates of each point
107448acf710SJeremy L Thompson 
107548acf710SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
107648acf710SJeremy L Thompson 
107748acf710SJeremy L Thompson   @ref Advanced
107848acf710SJeremy L Thompson **/
CeedOperatorAtPointsSetPoints(CeedOperator op,CeedElemRestriction rstr_points,CeedVector point_coords)107948acf710SJeremy L Thompson int CeedOperatorAtPointsSetPoints(CeedOperator op, CeedElemRestriction rstr_points, CeedVector point_coords) {
10801203703bSJeremy L Thompson   bool is_at_points, is_immutable;
10812a3ff1c9SZach Atkins 
10822a3ff1c9SZach Atkins   CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
10831203703bSJeremy L Thompson   CeedCall(CeedOperatorIsImmutable(op, &is_immutable));
10849bc66399SJeremy L Thompson   CeedCheck(is_at_points, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for operator at points");
10859bc66399SJeremy L Thompson   CeedCheck(!is_immutable, CeedOperatorReturnCeed(op), CEED_ERROR_MAJOR, "Operator cannot be changed after set as immutable");
108648acf710SJeremy L Thompson 
108748acf710SJeremy L Thompson   if (!op->first_points_rstr) {
108848acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionReferenceCopy(rstr_points, &op->first_points_rstr));
108948acf710SJeremy L Thompson   } else {
109048acf710SJeremy L Thompson     bool are_compatible;
109148acf710SJeremy L Thompson 
109248acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionAtPointsAreCompatible(op->first_points_rstr, rstr_points, &are_compatible));
10939bc66399SJeremy L Thompson     CeedCheck(are_compatible, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE,
1094ca94c3ddSJeremy L Thompson               "CeedElemRestriction must have compatible offsets with previously set field CeedElemRestriction");
109548acf710SJeremy L Thompson   }
109648acf710SJeremy L Thompson 
109748acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionReferenceCopy(rstr_points, &op->rstr_points));
109848acf710SJeremy L Thompson   CeedCall(CeedVectorReferenceCopy(point_coords, &op->point_coords));
109948acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
110048acf710SJeremy L Thompson }
110148acf710SJeremy L Thompson 
110248acf710SJeremy L Thompson /**
1103b594f9faSZach Atkins   @brief Get a boolean value indicating if the `CeedOperator` was created with `CeedOperatorCreateAtPoints`
1104b594f9faSZach Atkins 
1105b594f9faSZach Atkins   @param[in]  op           `CeedOperator`
1106b594f9faSZach Atkins   @param[out] is_at_points Variable to store at points status
1107b594f9faSZach Atkins 
1108b594f9faSZach Atkins   @return An error code: 0 - success, otherwise - failure
1109b594f9faSZach Atkins 
1110b594f9faSZach Atkins   @ref User
1111b594f9faSZach Atkins **/
CeedOperatorIsAtPoints(CeedOperator op,bool * is_at_points)1112b594f9faSZach Atkins int CeedOperatorIsAtPoints(CeedOperator op, bool *is_at_points) {
1113b594f9faSZach Atkins   *is_at_points = op->is_at_points;
1114b594f9faSZach Atkins   return CEED_ERROR_SUCCESS;
1115b594f9faSZach Atkins }
1116b594f9faSZach Atkins 
1117b594f9faSZach Atkins /**
1118ca94c3ddSJeremy L Thompson   @brief Get the arbitrary points in each element for a `CeedOperator` at points.
111948acf710SJeremy L Thompson 
1120ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
112148acf710SJeremy L Thompson 
1122ca94c3ddSJeremy L Thompson   @param[in]  op           `CeedOperator` at points
1123ca94c3ddSJeremy L Thompson   @param[out] rstr_points  Variable to hold `CeedElemRestriction` for the coordinates of each point by element
1124ca94c3ddSJeremy L Thompson   @param[out] point_coords Variable to hold `CeedVector` holding coordinates of each point
112548acf710SJeremy L Thompson 
112648acf710SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
112748acf710SJeremy L Thompson 
112848acf710SJeremy L Thompson   @ref Advanced
112948acf710SJeremy L Thompson **/
CeedOperatorAtPointsGetPoints(CeedOperator op,CeedElemRestriction * rstr_points,CeedVector * point_coords)113048acf710SJeremy L Thompson int CeedOperatorAtPointsGetPoints(CeedOperator op, CeedElemRestriction *rstr_points, CeedVector *point_coords) {
11312a3ff1c9SZach Atkins   bool is_at_points;
11322a3ff1c9SZach Atkins 
11332a3ff1c9SZach Atkins   CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
11346e536b99SJeremy L Thompson   CeedCheck(is_at_points, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for operator at points");
113548acf710SJeremy L Thompson   CeedCall(CeedOperatorCheckReady(op));
113648acf710SJeremy L Thompson 
11373f919cbcSJeremy L Thompson   if (rstr_points) {
11383f919cbcSJeremy L Thompson     *rstr_points = NULL;
11393f919cbcSJeremy L Thompson     CeedCall(CeedElemRestrictionReferenceCopy(op->rstr_points, rstr_points));
11403f919cbcSJeremy L Thompson   }
11413f919cbcSJeremy L Thompson   if (point_coords) {
11423f919cbcSJeremy L Thompson     *point_coords = NULL;
11433f919cbcSJeremy L Thompson     CeedCall(CeedVectorReferenceCopy(op->point_coords, point_coords));
11443f919cbcSJeremy L Thompson   }
114548acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
114648acf710SJeremy L Thompson }
114748acf710SJeremy L Thompson 
114848acf710SJeremy L Thompson /**
1149be9c6463SJeremy L Thompson   @brief Get a `CeedOperator` Field of a `CeedOperator` from its name.
1150be9c6463SJeremy L Thompson 
1151be9c6463SJeremy L Thompson   `op_field` is set to `NULL` if the field is not found.
1152de5900adSJames Wright 
1153ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
1154de5900adSJames Wright 
1155ca94c3ddSJeremy L Thompson   @param[in]  op         `CeedOperator`
1156ca94c3ddSJeremy L Thompson   @param[in]  field_name Name of desired `CeedOperator` Field
1157ca94c3ddSJeremy L Thompson   @param[out] op_field   `CeedOperator` Field corresponding to the name
1158de5900adSJames Wright 
1159de5900adSJames Wright   @return An error code: 0 - success, otherwise - failure
1160de5900adSJames Wright 
1161de5900adSJames Wright   @ref Advanced
1162de5900adSJames Wright **/
CeedOperatorGetFieldByName(CeedOperator op,const char * field_name,CeedOperatorField * op_field)1163de5900adSJames Wright int CeedOperatorGetFieldByName(CeedOperator op, const char *field_name, CeedOperatorField *op_field) {
11646f8994e9SJeremy L Thompson   const char        *name;
1165de5900adSJames Wright   CeedInt            num_input_fields, num_output_fields;
1166de5900adSJames Wright   CeedOperatorField *input_fields, *output_fields;
1167de5900adSJames Wright 
1168be9c6463SJeremy L Thompson   *op_field = NULL;
11691c66c397SJeremy L Thompson   CeedCall(CeedOperatorGetFields(op, &num_input_fields, &input_fields, &num_output_fields, &output_fields));
1170de5900adSJames Wright   for (CeedInt i = 0; i < num_input_fields; i++) {
1171de5900adSJames Wright     CeedCall(CeedOperatorFieldGetName(input_fields[i], &name));
1172de5900adSJames Wright     if (!strcmp(name, field_name)) {
1173de5900adSJames Wright       *op_field = input_fields[i];
1174de5900adSJames Wright       return CEED_ERROR_SUCCESS;
1175de5900adSJames Wright     }
1176de5900adSJames Wright   }
1177de5900adSJames Wright   for (CeedInt i = 0; i < num_output_fields; i++) {
1178de5900adSJames Wright     CeedCall(CeedOperatorFieldGetName(output_fields[i], &name));
1179de5900adSJames Wright     if (!strcmp(name, field_name)) {
1180de5900adSJames Wright       *op_field = output_fields[i];
1181de5900adSJames Wright       return CEED_ERROR_SUCCESS;
1182de5900adSJames Wright     }
1183de5900adSJames Wright   }
1184be9c6463SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1185de5900adSJames Wright }
1186de5900adSJames Wright 
1187de5900adSJames Wright /**
1188ca94c3ddSJeremy L Thompson   @brief Get the name of a `CeedOperator` Field
118928567f8fSJeremy L Thompson 
1190ca94c3ddSJeremy L Thompson   @param[in]  op_field   `CeedOperator` Field
119128567f8fSJeremy L Thompson   @param[out] field_name Variable to store the field name
119228567f8fSJeremy L Thompson 
119328567f8fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
119428567f8fSJeremy L Thompson 
1195e9b533fbSJeremy L Thompson   @ref Advanced
119628567f8fSJeremy L Thompson **/
CeedOperatorFieldGetName(CeedOperatorField op_field,const char ** field_name)11976f8994e9SJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, const char **field_name) {
11986f8994e9SJeremy L Thompson   *field_name = op_field->field_name;
119928567f8fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
120028567f8fSJeremy L Thompson }
120128567f8fSJeremy L Thompson 
120228567f8fSJeremy L Thompson /**
1203681d0ea7SJeremy L Thompson   @brief Get the `CeedElemRestriction` of a `CeedOperator` Field.
1204681d0ea7SJeremy L Thompson 
1205681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the `rstr` with @ref CeedElemRestrictionDestroy().
120643bbe138SJeremy L Thompson 
1207ca94c3ddSJeremy L Thompson   @param[in]  op_field `CeedOperator` Field
1208ca94c3ddSJeremy L Thompson   @param[out] rstr     Variable to store `CeedElemRestriction`
120943bbe138SJeremy L Thompson 
121043bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
121143bbe138SJeremy L Thompson 
1212e9b533fbSJeremy L Thompson   @ref Advanced
121343bbe138SJeremy L Thompson **/
CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,CeedElemRestriction * rstr)12142b730f8bSJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, CeedElemRestriction *rstr) {
1215681d0ea7SJeremy L Thompson   *rstr = NULL;
1216681d0ea7SJeremy L Thompson   CeedCall(CeedElemRestrictionReferenceCopy(op_field->elem_rstr, rstr));
121743bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
121843bbe138SJeremy L Thompson }
121943bbe138SJeremy L Thompson 
122043bbe138SJeremy L Thompson /**
1221681d0ea7SJeremy L Thompson   @brief Get the `CeedBasis` of a `CeedOperator` Field.
1222681d0ea7SJeremy L Thompson 
1223681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the `basis` with @ref CeedBasisDestroy().
122443bbe138SJeremy L Thompson 
1225ca94c3ddSJeremy L Thompson   @param[in]  op_field `CeedOperator` Field
1226ca94c3ddSJeremy L Thompson   @param[out] basis    Variable to store `CeedBasis`
122743bbe138SJeremy L Thompson 
122843bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
122943bbe138SJeremy L Thompson 
1230e9b533fbSJeremy L Thompson   @ref Advanced
123143bbe138SJeremy L Thompson **/
CeedOperatorFieldGetBasis(CeedOperatorField op_field,CeedBasis * basis)123243bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
1233681d0ea7SJeremy L Thompson   *basis = NULL;
1234681d0ea7SJeremy L Thompson   CeedCall(CeedBasisReferenceCopy(op_field->basis, basis));
123543bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
123643bbe138SJeremy L Thompson }
123743bbe138SJeremy L Thompson 
123843bbe138SJeremy L Thompson /**
1239681d0ea7SJeremy L Thompson   @brief Get the `CeedVector` of a `CeedOperator` Field.
1240681d0ea7SJeremy L Thompson 
1241681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the `vec` with @ref CeedVectorDestroy().
124243bbe138SJeremy L Thompson 
1243ca94c3ddSJeremy L Thompson   @param[in]  op_field `CeedOperator` Field
1244ca94c3ddSJeremy L Thompson   @param[out] vec      Variable to store `CeedVector`
124543bbe138SJeremy L Thompson 
124643bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
124743bbe138SJeremy L Thompson 
1248e9b533fbSJeremy L Thompson   @ref Advanced
124943bbe138SJeremy L Thompson **/
CeedOperatorFieldGetVector(CeedOperatorField op_field,CeedVector * vec)125043bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
1251681d0ea7SJeremy L Thompson   *vec = NULL;
1252681d0ea7SJeremy L Thompson   CeedCall(CeedVectorReferenceCopy(op_field->vec, vec));
125343bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
125443bbe138SJeremy L Thompson }
125543bbe138SJeremy L Thompson 
125643bbe138SJeremy L Thompson /**
1257ab747706SJeremy L Thompson   @brief Get the data of a `CeedOperator` Field.
1258ab747706SJeremy L Thompson 
1259681d0ea7SJeremy L Thompson   Any arguments set as `NULL` are ignored..
1260681d0ea7SJeremy L Thompson 
1261681d0ea7SJeremy L Thompson   Note: Caller is responsible for destroying the `rstr`, `basis`, and `vec`.
1262ab747706SJeremy L Thompson 
1263ab747706SJeremy L Thompson   @param[in]  op_field   `CeedOperator` Field
1264ab747706SJeremy L Thompson   @param[out] field_name Variable to store the field name
1265ab747706SJeremy L Thompson   @param[out] rstr       Variable to store `CeedElemRestriction`
1266ab747706SJeremy L Thompson   @param[out] basis      Variable to store `CeedBasis`
1267ab747706SJeremy L Thompson   @param[out] vec        Variable to store `CeedVector`
1268ab747706SJeremy L Thompson 
1269ab747706SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1270ab747706SJeremy L Thompson 
1271ab747706SJeremy L Thompson   @ref Advanced
1272ab747706SJeremy L Thompson **/
CeedOperatorFieldGetData(CeedOperatorField op_field,const char ** field_name,CeedElemRestriction * rstr,CeedBasis * basis,CeedVector * vec)12736f8994e9SJeremy L Thompson int CeedOperatorFieldGetData(CeedOperatorField op_field, const char **field_name, CeedElemRestriction *rstr, CeedBasis *basis, CeedVector *vec) {
1274ab747706SJeremy L Thompson   if (field_name) CeedCall(CeedOperatorFieldGetName(op_field, field_name));
1275ab747706SJeremy L Thompson   if (rstr) CeedCall(CeedOperatorFieldGetElemRestriction(op_field, rstr));
1276ab747706SJeremy L Thompson   if (basis) CeedCall(CeedOperatorFieldGetBasis(op_field, basis));
1277ab747706SJeremy L Thompson   if (vec) CeedCall(CeedOperatorFieldGetVector(op_field, vec));
1278ab747706SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1279ab747706SJeremy L Thompson }
1280ab747706SJeremy L Thompson 
1281ab747706SJeremy L Thompson /**
1282ca94c3ddSJeremy L Thompson   @brief Add a sub-operator to a composite `CeedOperator`
1283288c0443SJeremy L Thompson 
1284ca94c3ddSJeremy L Thompson   @param[in,out] composite_op Composite `CeedOperator`
1285ca94c3ddSJeremy L Thompson   @param[in]     sub_op       Sub-operator `CeedOperator`
128652d6035fSJeremy L Thompson 
128752d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
128852d6035fSJeremy L Thompson 
12897a982d89SJeremy L. Thompson   @ref User
129052d6035fSJeremy L Thompson  */
CeedOperatorCompositeAddSub(CeedOperator composite_op,CeedOperator sub_op)1291ed094490SJeremy L Thompson int CeedOperatorCompositeAddSub(CeedOperator composite_op, CeedOperator sub_op) {
12921203703bSJeremy L Thompson   bool is_immutable;
12931203703bSJeremy L Thompson 
12949bc66399SJeremy L Thompson   CeedCheck(composite_op->is_composite, CeedOperatorReturnCeed(composite_op), CEED_ERROR_MINOR, "CeedOperator is not a composite operator");
12959bc66399SJeremy L Thompson   CeedCheck(composite_op->num_suboperators < CEED_COMPOSITE_MAX, CeedOperatorReturnCeed(composite_op), CEED_ERROR_UNSUPPORTED,
12969bc66399SJeremy L Thompson             "Cannot add additional sub-operators");
12971203703bSJeremy L Thompson   CeedCall(CeedOperatorIsImmutable(composite_op, &is_immutable));
12989bc66399SJeremy L Thompson   CeedCheck(!is_immutable, CeedOperatorReturnCeed(composite_op), CEED_ERROR_MAJOR, "Operator cannot be changed after set as immutable");
12992b730f8bSJeremy L Thompson 
13002b730f8bSJeremy L Thompson   {
13012b730f8bSJeremy L Thompson     CeedSize input_size, output_size;
13021c66c397SJeremy L Thompson 
13032b730f8bSJeremy L Thompson     CeedCall(CeedOperatorGetActiveVectorLengths(sub_op, &input_size, &output_size));
13042b730f8bSJeremy L Thompson     if (composite_op->input_size == -1) composite_op->input_size = input_size;
13052b730f8bSJeremy L Thompson     if (composite_op->output_size == -1) composite_op->output_size = output_size;
13062b730f8bSJeremy L Thompson     // Note, a size of -1 means no active vector restriction set, so no incompatibility
13079bc66399SJeremy L Thompson     CeedCheck((input_size == -1 || input_size == composite_op->input_size) && (output_size == -1 || output_size == composite_op->output_size),
13089bc66399SJeremy L Thompson               CeedOperatorReturnCeed(composite_op), CEED_ERROR_MAJOR,
1309249f8407SJeremy L Thompson               "Sub-operators must have compatible dimensions; composite operator of shape (%" CeedSize_FMT ", %" CeedSize_FMT
1310249f8407SJeremy L Thompson               ") not compatible with sub-operator of "
1311249f8407SJeremy L Thompson               "shape (%" CeedSize_FMT ", %" CeedSize_FMT ")",
13122b730f8bSJeremy L Thompson               composite_op->input_size, composite_op->output_size, input_size, output_size);
13132b730f8bSJeremy L Thompson   }
13142b730f8bSJeremy L Thompson 
1315d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
13162b730f8bSJeremy L Thompson   CeedCall(CeedOperatorReference(sub_op));
1317d1d35e2fSjeremylt   composite_op->num_suboperators++;
1318e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
131952d6035fSJeremy L Thompson }
132052d6035fSJeremy L Thompson 
132152d6035fSJeremy L Thompson /**
1322ca94c3ddSJeremy L Thompson   @brief Get the number of sub-operators associated with a `CeedOperator`
132375f0d5a4SJeremy L Thompson 
1324ca94c3ddSJeremy L Thompson   @param[in]  op               `CeedOperator`
1325ca94c3ddSJeremy L Thompson   @param[out] num_suboperators Variable to store number of sub-operators
132675f0d5a4SJeremy L Thompson 
132775f0d5a4SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
132875f0d5a4SJeremy L Thompson 
132975f0d5a4SJeremy L Thompson   @ref Backend
133075f0d5a4SJeremy L Thompson **/
CeedOperatorCompositeGetNumSub(CeedOperator op,CeedInt * num_suboperators)1331ed094490SJeremy L Thompson int CeedOperatorCompositeGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
13321203703bSJeremy L Thompson   bool is_composite;
13331203703bSJeremy L Thompson 
13341203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
13356e536b99SJeremy L Thompson   CeedCheck(is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for a composite operator");
133675f0d5a4SJeremy L Thompson   *num_suboperators = op->num_suboperators;
133775f0d5a4SJeremy L Thompson   return CEED_ERROR_SUCCESS;
133875f0d5a4SJeremy L Thompson }
133975f0d5a4SJeremy L Thompson 
134075f0d5a4SJeremy L Thompson /**
1341ca94c3ddSJeremy L Thompson   @brief Get the list of sub-operators associated with a `CeedOperator`
134275f0d5a4SJeremy L Thompson 
1343ca94c3ddSJeremy L Thompson   @param[in]  op             `CeedOperator`
1344ca94c3ddSJeremy L Thompson   @param[out] sub_operators  Variable to store list of sub-operators
134575f0d5a4SJeremy L Thompson 
134675f0d5a4SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
134775f0d5a4SJeremy L Thompson 
134875f0d5a4SJeremy L Thompson   @ref Backend
134975f0d5a4SJeremy L Thompson **/
CeedOperatorCompositeGetSubList(CeedOperator op,CeedOperator ** sub_operators)1350ed094490SJeremy L Thompson int CeedOperatorCompositeGetSubList(CeedOperator op, CeedOperator **sub_operators) {
13511203703bSJeremy L Thompson   bool is_composite;
13521203703bSJeremy L Thompson 
13531203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
13546e536b99SJeremy L Thompson   CeedCheck(is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for a composite operator");
135575f0d5a4SJeremy L Thompson   *sub_operators = op->sub_operators;
135675f0d5a4SJeremy L Thompson   return CEED_ERROR_SUCCESS;
135775f0d5a4SJeremy L Thompson }
135875f0d5a4SJeremy L Thompson 
135975f0d5a4SJeremy L Thompson /**
13608a297abdSJames Wright   @brief Get a sub `CeedOperator` of a composite `CeedOperator` from its name.
13618a297abdSJames Wright 
13628a297abdSJames Wright   `sub_op` is set to `NULL` if the sub operator is not found.
13638a297abdSJames Wright 
13648a297abdSJames Wright   Note: Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
13658a297abdSJames Wright 
13668a297abdSJames Wright   @param[in]  op      Composite `CeedOperator`
13678a297abdSJames Wright   @param[in]  op_name Name of desired sub `CeedOperator`
13688a297abdSJames Wright   @param[out] sub_op  Sub `CeedOperator` corresponding to the name
13698a297abdSJames Wright 
13708a297abdSJames Wright   @return An error code: 0 - success, otherwise - failure
13718a297abdSJames Wright 
13728a297abdSJames Wright   @ref Advanced
13738a297abdSJames Wright **/
CeedOperatorCompositeGetSubByName(CeedOperator op,const char * op_name,CeedOperator * sub_op)1374ed094490SJeremy L Thompson int CeedOperatorCompositeGetSubByName(CeedOperator op, const char *op_name, CeedOperator *sub_op) {
13758a297abdSJames Wright   bool          is_composite;
13768a297abdSJames Wright   CeedInt       num_sub_ops;
13778a297abdSJames Wright   CeedOperator *sub_ops;
13788a297abdSJames Wright 
13798a297abdSJames Wright   CeedCall(CeedOperatorIsComposite(op, &is_composite));
13808a297abdSJames Wright   CeedCheck(is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for a composite operator");
13818a297abdSJames Wright   *sub_op = NULL;
1382ed094490SJeremy L Thompson   CeedCall(CeedOperatorCompositeGetNumSub(op, &num_sub_ops));
1383ed094490SJeremy L Thompson   CeedCall(CeedOperatorCompositeGetSubList(op, &sub_ops));
13848a297abdSJames Wright   for (CeedInt i = 0; i < num_sub_ops; i++) {
13858a297abdSJames Wright     if (sub_ops[i]->name && !strcmp(op_name, sub_ops[i]->name)) {
13868a297abdSJames Wright       *sub_op = sub_ops[i];
13878a297abdSJames Wright       return CEED_ERROR_SUCCESS;
13888a297abdSJames Wright     }
13898a297abdSJames Wright   }
13908a297abdSJames Wright   return CEED_ERROR_SUCCESS;
13918a297abdSJames Wright }
13928a297abdSJames Wright 
13938a297abdSJames Wright /**
1394*be395853SZach Atkins   @brief Set whether the sub-operators of the composite `CeedOperator` must be run sequentially.
1395*be395853SZach Atkins 
1396*be395853SZach Atkins   Note: This value currently only affects the GPU `/gpu/cuda/gen` and `/gpu/hip/gen` backends.
1397*be395853SZach Atkins 
1398*be395853SZach Atkins   @param[in] op            Composite `CeedOperator`
1399*be395853SZach Atkins   @param[in] is_sequential Flag value to set, if `true`, forces the composite `CeedOperator` to execute sequentially
1400*be395853SZach Atkins 
1401*be395853SZach Atkins   @return An error code: 0 - success, otherwise - failure
1402*be395853SZach Atkins 
1403*be395853SZach Atkins   @ref Advanced
1404*be395853SZach Atkins **/
CeedOperatorCompositeSetSequential(CeedOperator op,bool is_sequential)1405*be395853SZach Atkins int CeedOperatorCompositeSetSequential(CeedOperator op, bool is_sequential) {
1406*be395853SZach Atkins   bool is_composite;
1407*be395853SZach Atkins 
1408*be395853SZach Atkins   CeedCall(CeedOperatorIsComposite(op, &is_composite));
1409*be395853SZach Atkins   CeedCheck(is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for a composite operator");
1410*be395853SZach Atkins   op->is_sequential = is_sequential;
1411*be395853SZach Atkins   return CEED_ERROR_SUCCESS;
1412*be395853SZach Atkins }
1413*be395853SZach Atkins 
1414*be395853SZach Atkins /**
1415*be395853SZach Atkins   @brief Get whether the sub-operators of the composite `CeedOperator` must be run sequentially.
1416*be395853SZach Atkins 
1417*be395853SZach Atkins   Note: This value currently only affects the GPU `/gpu/cuda/gen` and `/gpu/hip/gen` backends.
1418*be395853SZach Atkins 
1419*be395853SZach Atkins   @param[in]  op            Composite `CeedOperator`
1420*be395853SZach Atkins   @param[out] is_sequential Variable to store sequential status
1421*be395853SZach Atkins 
1422*be395853SZach Atkins   @return An error code: 0 - success, otherwise - failure
1423*be395853SZach Atkins 
1424*be395853SZach Atkins   @ref Advanced
1425*be395853SZach Atkins **/
CeedOperatorCompositeIsSequential(CeedOperator op,bool * is_sequential)1426*be395853SZach Atkins int CeedOperatorCompositeIsSequential(CeedOperator op, bool *is_sequential) {
1427*be395853SZach Atkins   bool is_composite;
1428*be395853SZach Atkins 
1429*be395853SZach Atkins   CeedCall(CeedOperatorIsComposite(op, &is_composite));
1430*be395853SZach Atkins   CeedCheck(is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Only defined for a composite operator");
1431*be395853SZach Atkins   *is_sequential = op->is_sequential;
1432*be395853SZach Atkins   return CEED_ERROR_SUCCESS;
1433*be395853SZach Atkins }
1434*be395853SZach Atkins 
1435*be395853SZach Atkins /**
1436ca94c3ddSJeremy L Thompson   @brief Check if a `CeedOperator` is ready to be used.
14374db537f9SJeremy L Thompson 
1438ca94c3ddSJeremy L Thompson   @param[in] op `CeedOperator` to check
14394db537f9SJeremy L Thompson 
14404db537f9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
14414db537f9SJeremy L Thompson 
14424db537f9SJeremy L Thompson   @ref User
14434db537f9SJeremy L Thompson **/
CeedOperatorCheckReady(CeedOperator op)14444db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
14451203703bSJeremy L Thompson   bool          is_at_points, is_composite;
14461203703bSJeremy L Thompson   CeedQFunction qf = NULL;
14474db537f9SJeremy L Thompson 
14482b730f8bSJeremy L Thompson   if (op->is_interface_setup) return CEED_ERROR_SUCCESS;
14494db537f9SJeremy L Thompson 
14501203703bSJeremy L Thompson   CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
14511203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
14521203703bSJeremy L Thompson   if (!is_composite) CeedCall(CeedOperatorGetQFunction(op, &qf));
14531203703bSJeremy L Thompson   if (is_composite) {
14541203703bSJeremy L Thompson     CeedInt num_suboperators;
14551203703bSJeremy L Thompson 
1456ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
14571203703bSJeremy L Thompson     if (!num_suboperators) {
145843622462SJeremy L Thompson       // Empty operator setup
145943622462SJeremy L Thompson       op->input_size  = 0;
146043622462SJeremy L Thompson       op->output_size = 0;
146143622462SJeremy L Thompson     } else {
14621203703bSJeremy L Thompson       CeedOperator *sub_operators;
14631203703bSJeremy L Thompson 
1464ed094490SJeremy L Thompson       CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
14651203703bSJeremy L Thompson       for (CeedInt i = 0; i < num_suboperators; i++) {
14661203703bSJeremy L Thompson         CeedCall(CeedOperatorCheckReady(sub_operators[i]));
14674db537f9SJeremy L Thompson       }
14682b104005SJeremy L Thompson       // Sub-operators could be modified after adding to composite operator
14692b104005SJeremy L Thompson       // Need to verify no lvec incompatibility from any changes
14702b104005SJeremy L Thompson       CeedSize input_size, output_size;
14712b730f8bSJeremy L Thompson       CeedCall(CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size));
147243622462SJeremy L Thompson     }
14734db537f9SJeremy L Thompson   } else {
14741203703bSJeremy L Thompson     CeedInt num_input_fields, num_output_fields;
14751203703bSJeremy L Thompson 
14769bc66399SJeremy L Thompson     CeedCheck(op->num_fields > 0, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "No operator fields set");
14771203703bSJeremy L Thompson     CeedCall(CeedQFunctionGetFields(qf, &num_input_fields, NULL, &num_output_fields, NULL));
14789bc66399SJeremy L Thompson     CeedCheck(op->num_fields == num_input_fields + num_output_fields, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE,
14799bc66399SJeremy L Thompson               "Not all operator fields set");
14809bc66399SJeremy L Thompson     CeedCheck(op->has_restriction, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE, "At least one restriction required");
14819bc66399SJeremy L Thompson     CeedCheck(op->num_qpts > 0 || is_at_points, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE,
1482ca94c3ddSJeremy L Thompson               "At least one non-collocated CeedBasis is required or the number of quadrature points must be set");
14832b730f8bSJeremy L Thompson   }
14844db537f9SJeremy L Thompson 
14854db537f9SJeremy L Thompson   // Flag as immutable and ready
14864db537f9SJeremy L Thompson   op->is_interface_setup = true;
14871203703bSJeremy L Thompson   if (qf && qf != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionSetImmutable(qf));
1488c11e12f4SJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&qf));
14891203703bSJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionSetImmutable(op->dqf));
14901203703bSJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) CeedCall(CeedQFunctionSetImmutable(op->dqfT));
14914db537f9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
14924db537f9SJeremy L Thompson }
14934db537f9SJeremy L Thompson 
14944db537f9SJeremy L Thompson /**
1495ca94c3ddSJeremy L Thompson   @brief Get vector lengths for the active input and/or output `CeedVector` of a `CeedOperator`.
14964385fb7fSSebastian Grimberg 
1497ca94c3ddSJeremy L Thompson   Note: Lengths of `-1` indicate that the CeedOperator does not have an active input and/or output.
1498c9366a6bSJeremy L Thompson 
1499ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
1500ca94c3ddSJeremy L Thompson   @param[out] input_size  Variable to store active input vector length, or `NULL`
1501ca94c3ddSJeremy L Thompson   @param[out] output_size Variable to store active output vector length, or `NULL`
1502c9366a6bSJeremy L Thompson 
1503c9366a6bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1504c9366a6bSJeremy L Thompson 
1505c9366a6bSJeremy L Thompson   @ref User
1506c9366a6bSJeremy L Thompson **/
CeedOperatorGetActiveVectorLengths(CeedOperator op,CeedSize * input_size,CeedSize * output_size)15072b730f8bSJeremy L Thompson int CeedOperatorGetActiveVectorLengths(CeedOperator op, CeedSize *input_size, CeedSize *output_size) {
1508c9366a6bSJeremy L Thompson   bool is_composite;
1509c9366a6bSJeremy L Thompson 
15102b104005SJeremy L Thompson   if (input_size) *input_size = op->input_size;
15112b104005SJeremy L Thompson   if (output_size) *output_size = op->output_size;
1512c9366a6bSJeremy L Thompson 
15132b730f8bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
15142b104005SJeremy L Thompson   if (is_composite && (op->input_size == -1 || op->output_size == -1)) {
15151203703bSJeremy L Thompson     CeedInt       num_suboperators;
15161203703bSJeremy L Thompson     CeedOperator *sub_operators;
15171203703bSJeremy L Thompson 
1518ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
1519ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
15201203703bSJeremy L Thompson     for (CeedInt i = 0; i < num_suboperators; i++) {
1521c9366a6bSJeremy L Thompson       CeedSize sub_input_size, sub_output_size;
15221c66c397SJeremy L Thompson 
15231203703bSJeremy L Thompson       CeedCall(CeedOperatorGetActiveVectorLengths(sub_operators[i], &sub_input_size, &sub_output_size));
15242b104005SJeremy L Thompson       if (op->input_size == -1) op->input_size = sub_input_size;
15252b104005SJeremy L Thompson       if (op->output_size == -1) op->output_size = sub_output_size;
15262b104005SJeremy L Thompson       // Note, a size of -1 means no active vector restriction set, so no incompatibility
15276e536b99SJeremy L Thompson       CeedCheck((sub_input_size == -1 || sub_input_size == op->input_size) && (sub_output_size == -1 || sub_output_size == op->output_size),
15286e536b99SJeremy L Thompson                 CeedOperatorReturnCeed(op), CEED_ERROR_MAJOR,
1529249f8407SJeremy L Thompson                 "Sub-operators must have compatible dimensions; composite operator of shape (%" CeedSize_FMT ", %" CeedSize_FMT
1530249f8407SJeremy L Thompson                 ") not compatible with sub-operator of "
1531249f8407SJeremy L Thompson                 "shape (%" CeedSize_FMT ", %" CeedSize_FMT ")",
15322b104005SJeremy L Thompson                 op->input_size, op->output_size, input_size, output_size);
1533c9366a6bSJeremy L Thompson     }
15342b730f8bSJeremy L Thompson   }
1535c9366a6bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1536c9366a6bSJeremy L Thompson }
1537c9366a6bSJeremy L Thompson 
1538c9366a6bSJeremy L Thompson /**
1539ca94c3ddSJeremy L Thompson   @brief Set reuse of `CeedQFunction` data in `CeedOperatorLinearAssemble*()` functions.
15404385fb7fSSebastian Grimberg 
1541ca94c3ddSJeremy L Thompson   When `reuse_assembly_data = false` (default), the `CeedQFunction` associated with this `CeedOperator` is re-assembled every time a `CeedOperatorLinearAssemble*()` function is called.
1542ca94c3ddSJeremy L Thompson   When `reuse_assembly_data = true`, the `CeedQFunction` associated with this `CeedOperator` is reused between calls to @ref CeedOperatorSetQFunctionAssemblyDataUpdateNeeded().
15438b919e6bSJeremy L Thompson 
1544ca94c3ddSJeremy L Thompson   @param[in] op                  `CeedOperator`
1545beecbf24SJeremy L Thompson   @param[in] reuse_assembly_data Boolean flag setting assembly data reuse
15468b919e6bSJeremy L Thompson 
15478b919e6bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
15488b919e6bSJeremy L Thompson 
15498b919e6bSJeremy L Thompson   @ref Advanced
15508b919e6bSJeremy L Thompson **/
CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op,bool reuse_assembly_data)15512b730f8bSJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, bool reuse_assembly_data) {
15528b919e6bSJeremy L Thompson   bool is_composite;
15538b919e6bSJeremy L Thompson 
15542b730f8bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
15558b919e6bSJeremy L Thompson   if (is_composite) {
15568b919e6bSJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
15572b730f8bSJeremy L Thompson       CeedCall(CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], reuse_assembly_data));
15588b919e6bSJeremy L Thompson     }
15598b919e6bSJeremy L Thompson   } else {
15607d5185d7SSebastian Grimberg     CeedQFunctionAssemblyData data;
15617d5185d7SSebastian Grimberg 
15627d5185d7SSebastian Grimberg     CeedCall(CeedOperatorGetQFunctionAssemblyData(op, &data));
15637d5185d7SSebastian Grimberg     CeedCall(CeedQFunctionAssemblyDataSetReuse(data, reuse_assembly_data));
1564beecbf24SJeremy L Thompson   }
1565beecbf24SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1566beecbf24SJeremy L Thompson }
1567beecbf24SJeremy L Thompson 
1568beecbf24SJeremy L Thompson /**
1569ca94c3ddSJeremy L Thompson   @brief Mark `CeedQFunction` data as updated and the `CeedQFunction` as requiring re-assembly.
1570beecbf24SJeremy L Thompson 
1571ca94c3ddSJeremy L Thompson   @param[in] op                `CeedOperator`
15726e15d496SJeremy L Thompson   @param[in] needs_data_update Boolean flag setting assembly data reuse
1573beecbf24SJeremy L Thompson 
1574beecbf24SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1575beecbf24SJeremy L Thompson 
1576beecbf24SJeremy L Thompson   @ref Advanced
1577beecbf24SJeremy L Thompson **/
CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op,bool needs_data_update)15782b730f8bSJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, bool needs_data_update) {
1579beecbf24SJeremy L Thompson   bool is_composite;
1580beecbf24SJeremy L Thompson 
15812b730f8bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
1582beecbf24SJeremy L Thompson   if (is_composite) {
15831203703bSJeremy L Thompson     CeedInt       num_suboperators;
15841203703bSJeremy L Thompson     CeedOperator *sub_operators;
15851203703bSJeremy L Thompson 
1586ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
1587ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
15881203703bSJeremy L Thompson     for (CeedInt i = 0; i < num_suboperators; i++) {
15891203703bSJeremy L Thompson       CeedCall(CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(sub_operators[i], needs_data_update));
1590beecbf24SJeremy L Thompson     }
1591beecbf24SJeremy L Thompson   } else {
15927d5185d7SSebastian Grimberg     CeedQFunctionAssemblyData data;
15937d5185d7SSebastian Grimberg 
15947d5185d7SSebastian Grimberg     CeedCall(CeedOperatorGetQFunctionAssemblyData(op, &data));
15957d5185d7SSebastian Grimberg     CeedCall(CeedQFunctionAssemblyDataSetUpdateNeeded(data, needs_data_update));
15968b919e6bSJeremy L Thompson   }
15978b919e6bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
15988b919e6bSJeremy L Thompson }
15998b919e6bSJeremy L Thompson 
16008b919e6bSJeremy L Thompson /**
1601ca94c3ddSJeremy L Thompson   @brief Set name of `CeedOperator` for @ref CeedOperatorView() output
1602ea6b5821SJeremy L Thompson 
1603ca94c3ddSJeremy L Thompson   @param[in,out] op   `CeedOperator`
1604ea61e9acSJeremy L Thompson   @param[in]     name Name to set, or NULL to remove previously set name
1605ea6b5821SJeremy L Thompson 
1606ea6b5821SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1607ea6b5821SJeremy L Thompson 
1608ea6b5821SJeremy L Thompson   @ref User
1609ea6b5821SJeremy L Thompson **/
CeedOperatorSetName(CeedOperator op,const char * name)1610ea6b5821SJeremy L Thompson int CeedOperatorSetName(CeedOperator op, const char *name) {
1611ea6b5821SJeremy L Thompson   char  *name_copy;
1612ea6b5821SJeremy L Thompson   size_t name_len = name ? strlen(name) : 0;
1613ea6b5821SJeremy L Thompson 
16142b730f8bSJeremy L Thompson   CeedCall(CeedFree(&op->name));
1615ea6b5821SJeremy L Thompson   if (name_len > 0) {
16162b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(name_len + 1, &name_copy));
1617ea6b5821SJeremy L Thompson     memcpy(name_copy, name, name_len);
1618ea6b5821SJeremy L Thompson     op->name = name_copy;
1619ea6b5821SJeremy L Thompson   }
1620ea6b5821SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1621ea6b5821SJeremy L Thompson }
1622ea6b5821SJeremy L Thompson 
1623ea6b5821SJeremy L Thompson /**
1624d3d5610dSJeremy L Thompson   @brief Get name of `CeedOperator`
1625d3d5610dSJeremy L Thompson 
1626d3d5610dSJeremy L Thompson   @param[in]     op   `CeedOperator`
1627d3d5610dSJeremy L Thompson   @param[in,out] name Address of variable to hold currently set name
1628d3d5610dSJeremy L Thompson 
1629d3d5610dSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1630d3d5610dSJeremy L Thompson 
1631d3d5610dSJeremy L Thompson   @ref User
1632d3d5610dSJeremy L Thompson **/
CeedOperatorGetName(CeedOperator op,const char ** name)1633d3d5610dSJeremy L Thompson int CeedOperatorGetName(CeedOperator op, const char **name) {
1634d3d5610dSJeremy L Thompson   if (op->name) {
1635d3d5610dSJeremy L Thompson     *name = op->name;
1636d3d5610dSJeremy L Thompson   } else if (!op->is_composite) {
1637d3d5610dSJeremy L Thompson     CeedQFunction qf;
1638d3d5610dSJeremy L Thompson 
1639d3d5610dSJeremy L Thompson     CeedCall(CeedOperatorGetQFunction(op, &qf));
1640d3d5610dSJeremy L Thompson     if (qf) CeedCall(CeedQFunctionGetName(qf, name));
1641d3d5610dSJeremy L Thompson     CeedCall(CeedQFunctionDestroy(&qf));
1642d3d5610dSJeremy L Thompson   }
1643d3d5610dSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1644d3d5610dSJeremy L Thompson }
1645d3d5610dSJeremy L Thompson 
1646d3d5610dSJeremy L Thompson /**
1647935f026aSJeremy L Thompson   @brief Core logic for viewing a `CeedOperator`
16487a982d89SJeremy L. Thompson 
1649935f026aSJeremy L Thompson   @param[in] op     `CeedOperator` to view brief summary
1650ca94c3ddSJeremy L Thompson   @param[in] stream  Stream to write; typically `stdout` or a file
16518bf1b130SJames Wright   @param[in] is_full Whether to write full operator view or terse
16527a982d89SJeremy L. Thompson 
16537a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
16546ab8e59fSJames Wright 
16556ab8e59fSJames Wright   @ref Developer
16567a982d89SJeremy L. Thompson **/
CeedOperatorView_Core(CeedOperator op,FILE * stream,bool is_full)16578bf1b130SJames Wright static int CeedOperatorView_Core(CeedOperator op, FILE *stream, bool is_full) {
1658d3d5610dSJeremy L Thompson   bool        has_name, is_composite, is_at_points;
16595a526491SJeremy L Thompson   char       *tabs     = NULL;
1660d3d5610dSJeremy L Thompson   const char *name     = NULL;
16615a526491SJeremy L Thompson   CeedInt     num_tabs = 0;
16627a982d89SJeremy L. Thompson 
1663d3d5610dSJeremy L Thompson   CeedCall(CeedOperatorGetName(op, &name));
1664d3d5610dSJeremy L Thompson   has_name = name ? strlen(name) : false;
16651203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
166699f7f61fSJeremy L Thompson   CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
16675a526491SJeremy L Thompson   // Set tabs
16685a526491SJeremy L Thompson   CeedCall(CeedOperatorGetNumViewTabs(op, &num_tabs));
16694c789ea2SJeremy L Thompson   CeedCall(CeedCalloc(CEED_TAB_WIDTH * (num_tabs + is_composite) + 1, &tabs));
16704c789ea2SJeremy L Thompson   for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' ';
16711203703bSJeremy L Thompson   if (is_composite) {
16721203703bSJeremy L Thompson     CeedInt       num_suboperators;
16731203703bSJeremy L Thompson     CeedOperator *sub_operators;
16741203703bSJeremy L Thompson 
1675ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
1676ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
1677df1daa62SZach Atkins     fprintf(stream, "%s", tabs);
1678d3d5610dSJeremy L Thompson     fprintf(stream, "Composite CeedOperator%s%s\n", has_name ? " - " : "", has_name ? name : "");
16794c789ea2SJeremy L Thompson     for (CeedInt i = 0; i < CEED_TAB_WIDTH; i++) tabs[CEED_TAB_WIDTH * num_tabs + i] = ' ';
16801203703bSJeremy L Thompson     for (CeedInt i = 0; i < num_suboperators; i++) {
16811203703bSJeremy L Thompson       has_name = sub_operators[i]->name;
1682df1daa62SZach Atkins       fprintf(stream, "%s", tabs);
168399f7f61fSJeremy L Thompson       fprintf(stream, "SubOperator%s %" CeedInt_FMT "%s%s%s\n", is_at_points ? " AtPoints" : "", i, has_name ? " - " : "",
168499f7f61fSJeremy L Thompson               has_name ? sub_operators[i]->name : "", is_full ? ":" : "");
16855a526491SJeremy L Thompson       if (is_full) CeedCall(CeedOperatorSingleView(sub_operators[i], tabs, stream));
16867a982d89SJeremy L. Thompson     }
16877a982d89SJeremy L. Thompson   } else {
1688df1daa62SZach Atkins     fprintf(stream, "%s", tabs);
1689d3d5610dSJeremy L Thompson     fprintf(stream, "CeedOperator%s%s%s\n", is_at_points ? " AtPoints" : "", has_name ? " - " : "", has_name ? name : "");
16905a526491SJeremy L Thompson     if (is_full) CeedCall(CeedOperatorSingleView(op, tabs, stream));
16917a982d89SJeremy L. Thompson   }
16925a526491SJeremy L Thompson   CeedCall(CeedFree(&tabs));
16935a526491SJeremy L Thompson   return CEED_ERROR_SUCCESS;
16945a526491SJeremy L Thompson }
16955a526491SJeremy L Thompson 
16965a526491SJeremy L Thompson /**
16975a526491SJeremy L Thompson   @brief Set the number of tabs to indent for @ref CeedOperatorView() output
16985a526491SJeremy L Thompson 
16995a526491SJeremy L Thompson   @param[in] op       `CeedOperator` to set the number of view tabs
17005a526491SJeremy L Thompson   @param[in] num_tabs Number of view tabs to set
17015a526491SJeremy L Thompson 
17025a526491SJeremy L Thompson   @return Error code: 0 - success, otherwise - failure
17035a526491SJeremy L Thompson 
17045a526491SJeremy L Thompson   @ref User
17055a526491SJeremy L Thompson **/
CeedOperatorSetNumViewTabs(CeedOperator op,CeedInt num_tabs)17065a526491SJeremy L Thompson int CeedOperatorSetNumViewTabs(CeedOperator op, CeedInt num_tabs) {
1707a299a25bSJeremy L Thompson   CeedCall(CeedObjectSetNumViewTabs((CeedObject)op, num_tabs));
1708e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
17097a982d89SJeremy L. Thompson }
17103bd813ffSjeremylt 
17113bd813ffSjeremylt /**
1712690992b2SZach Atkins   @brief Get the number of tabs to indent for @ref CeedOperatorView() output
1713690992b2SZach Atkins 
1714690992b2SZach Atkins   @param[in]  op       `CeedOperator` to get the number of view tabs
1715690992b2SZach Atkins   @param[out] num_tabs Number of view tabs
1716690992b2SZach Atkins 
1717690992b2SZach Atkins   @return Error code: 0 - success, otherwise - failure
1718690992b2SZach Atkins 
1719690992b2SZach Atkins   @ref User
1720690992b2SZach Atkins **/
CeedOperatorGetNumViewTabs(CeedOperator op,CeedInt * num_tabs)1721690992b2SZach Atkins int CeedOperatorGetNumViewTabs(CeedOperator op, CeedInt *num_tabs) {
1722a299a25bSJeremy L Thompson   CeedCall(CeedObjectGetNumViewTabs((CeedObject)op, num_tabs));
1723690992b2SZach Atkins   return CEED_ERROR_SUCCESS;
1724690992b2SZach Atkins }
1725690992b2SZach Atkins 
1726690992b2SZach Atkins /**
1727935f026aSJeremy L Thompson   @brief View a `CeedOperator`
1728935f026aSJeremy L Thompson 
1729935f026aSJeremy L Thompson   @param[in] op     `CeedOperator` to view
1730935f026aSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1731935f026aSJeremy L Thompson 
1732935f026aSJeremy L Thompson   @return Error code: 0 - success, otherwise - failure
1733935f026aSJeremy L Thompson 
1734935f026aSJeremy L Thompson   @ref User
1735935f026aSJeremy L Thompson **/
CeedOperatorView(CeedOperator op,FILE * stream)1736935f026aSJeremy L Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
1737935f026aSJeremy L Thompson   CeedCall(CeedOperatorView_Core(op, stream, true));
1738935f026aSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1739935f026aSJeremy L Thompson }
1740935f026aSJeremy L Thompson 
1741935f026aSJeremy L Thompson /**
1742935f026aSJeremy L Thompson   @brief View a brief summary `CeedOperator`
1743935f026aSJeremy L Thompson 
1744935f026aSJeremy L Thompson   @param[in] op     `CeedOperator` to view brief summary
1745935f026aSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1746935f026aSJeremy L Thompson 
1747935f026aSJeremy L Thompson   @return Error code: 0 - success, otherwise - failure
1748935f026aSJeremy L Thompson 
1749935f026aSJeremy L Thompson   @ref User
1750935f026aSJeremy L Thompson **/
CeedOperatorViewTerse(CeedOperator op,FILE * stream)1751935f026aSJeremy L Thompson int CeedOperatorViewTerse(CeedOperator op, FILE *stream) {
1752935f026aSJeremy L Thompson   CeedCall(CeedOperatorView_Core(op, stream, false));
1753935f026aSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1754935f026aSJeremy L Thompson }
1755935f026aSJeremy L Thompson 
1756935f026aSJeremy L Thompson /**
1757ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedOperator`
1758b7c9bbdaSJeremy L Thompson 
1759ca94c3ddSJeremy L Thompson   @param[in]  op   `CeedOperator`
1760ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store `Ceed`
1761b7c9bbdaSJeremy L Thompson 
1762b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1763b7c9bbdaSJeremy L Thompson 
1764b7c9bbdaSJeremy L Thompson   @ref Advanced
1765b7c9bbdaSJeremy L Thompson **/
CeedOperatorGetCeed(CeedOperator op,Ceed * ceed)1766b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
1767b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectGetCeed((CeedObject)op, ceed));
1768b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1769b7c9bbdaSJeremy L Thompson }
1770b7c9bbdaSJeremy L Thompson 
1771b7c9bbdaSJeremy L Thompson /**
17726e536b99SJeremy L Thompson   @brief Return the `Ceed` associated with a `CeedOperator`
17736e536b99SJeremy L Thompson 
17746e536b99SJeremy L Thompson   @param[in]  op `CeedOperator`
17756e536b99SJeremy L Thompson 
17766e536b99SJeremy L Thompson   @return `Ceed` associated with the `op`
17776e536b99SJeremy L Thompson 
17786e536b99SJeremy L Thompson   @ref Advanced
17796e536b99SJeremy L Thompson **/
CeedOperatorReturnCeed(CeedOperator op)1780b0f67a9cSJeremy L Thompson Ceed CeedOperatorReturnCeed(CeedOperator op) { return CeedObjectReturnCeed((CeedObject)op); }
17816e536b99SJeremy L Thompson 
17826e536b99SJeremy L Thompson /**
1783ca94c3ddSJeremy L Thompson   @brief Get the number of elements associated with a `CeedOperator`
1784b7c9bbdaSJeremy L Thompson 
1785ca94c3ddSJeremy L Thompson   @param[in]  op       `CeedOperator`
1786b7c9bbdaSJeremy L Thompson   @param[out] num_elem Variable to store number of elements
1787b7c9bbdaSJeremy L Thompson 
1788b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1789b7c9bbdaSJeremy L Thompson 
1790b7c9bbdaSJeremy L Thompson   @ref Advanced
1791b7c9bbdaSJeremy L Thompson **/
CeedOperatorGetNumElements(CeedOperator op,CeedInt * num_elem)1792b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
17931203703bSJeremy L Thompson   bool is_composite;
17941203703bSJeremy L Thompson 
17951203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
17966e536b99SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Not defined for composite operator");
1797b7c9bbdaSJeremy L Thompson   *num_elem = op->num_elem;
1798b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1799b7c9bbdaSJeremy L Thompson }
1800b7c9bbdaSJeremy L Thompson 
1801b7c9bbdaSJeremy L Thompson /**
1802ca94c3ddSJeremy L Thompson   @brief Get the number of quadrature points associated with a `CeedOperator`
1803b7c9bbdaSJeremy L Thompson 
1804ca94c3ddSJeremy L Thompson   @param[in]  op       `CeedOperator`
1805b7c9bbdaSJeremy L Thompson   @param[out] num_qpts Variable to store vector number of quadrature points
1806b7c9bbdaSJeremy L Thompson 
1807b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1808b7c9bbdaSJeremy L Thompson 
1809b7c9bbdaSJeremy L Thompson   @ref Advanced
1810b7c9bbdaSJeremy L Thompson **/
CeedOperatorGetNumQuadraturePoints(CeedOperator op,CeedInt * num_qpts)1811b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
18121203703bSJeremy L Thompson   bool is_composite;
18131203703bSJeremy L Thompson 
18141203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
18156e536b99SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_MINOR, "Not defined for composite operator");
1816b7c9bbdaSJeremy L Thompson   *num_qpts = op->num_qpts;
1817b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1818b7c9bbdaSJeremy L Thompson }
1819b7c9bbdaSJeremy L Thompson 
1820b7c9bbdaSJeremy L Thompson /**
1821ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs required to apply `CeedOperator` on the active `CeedVector`
18226e15d496SJeremy L Thompson 
1823ca94c3ddSJeremy L Thompson   @param[in]  op    `CeedOperator` to estimate FLOPs for
1824ea61e9acSJeremy L Thompson   @param[out] flops Address of variable to hold FLOPs estimate
18256e15d496SJeremy L Thompson 
18266e15d496SJeremy L Thompson   @ref Backend
18276e15d496SJeremy L Thompson **/
CeedOperatorGetFlopsEstimate(CeedOperator op,CeedSize * flops)18289d36ca50SJeremy L Thompson int CeedOperatorGetFlopsEstimate(CeedOperator op, CeedSize *flops) {
18296e15d496SJeremy L Thompson   bool is_composite;
18301c66c397SJeremy L Thompson 
18312b730f8bSJeremy L Thompson   CeedCall(CeedOperatorCheckReady(op));
18326e15d496SJeremy L Thompson 
18336e15d496SJeremy L Thompson   *flops = 0;
18342b730f8bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
18356e15d496SJeremy L Thompson   if (is_composite) {
18366e15d496SJeremy L Thompson     CeedInt num_suboperators;
18371c66c397SJeremy L Thompson 
1838ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
18396e15d496SJeremy L Thompson     CeedOperator *sub_operators;
1840ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
18416e15d496SJeremy L Thompson 
18426e15d496SJeremy L Thompson     // FLOPs for each suboperator
18436e15d496SJeremy L Thompson     for (CeedInt i = 0; i < num_suboperators; i++) {
18449d36ca50SJeremy L Thompson       CeedSize suboperator_flops;
18451c66c397SJeremy L Thompson 
18462b730f8bSJeremy L Thompson       CeedCall(CeedOperatorGetFlopsEstimate(sub_operators[i], &suboperator_flops));
18476e15d496SJeremy L Thompson       *flops += suboperator_flops;
18486e15d496SJeremy L Thompson     }
18496e15d496SJeremy L Thompson   } else {
18503f919cbcSJeremy L Thompson     bool                is_at_points;
18513f919cbcSJeremy L Thompson     CeedInt             num_input_fields, num_output_fields, num_elem = 0, num_points = 0;
18521203703bSJeremy L Thompson     CeedQFunction       qf;
18531203703bSJeremy L Thompson     CeedQFunctionField *qf_input_fields, *qf_output_fields;
18541203703bSJeremy L Thompson     CeedOperatorField  *op_input_fields, *op_output_fields;
18551c66c397SJeremy L Thompson 
18563f919cbcSJeremy L Thompson     CeedCall(CeedOperatorGetNumElements(op, &num_elem));
185719feff82SJeremy L Thompson     if (num_elem == 0) return CEED_ERROR_SUCCESS;
185819feff82SJeremy L Thompson     CeedCall(CeedOperatorIsAtPoints(op, &is_at_points));
18593f919cbcSJeremy L Thompson     if (is_at_points) {
18603f919cbcSJeremy L Thompson       CeedMemType         mem_type;
18613f919cbcSJeremy L Thompson       CeedElemRestriction rstr_points = NULL;
18623f919cbcSJeremy L Thompson 
18633f919cbcSJeremy L Thompson       CeedCall(CeedOperatorAtPointsGetPoints(op, &rstr_points, NULL));
18643f919cbcSJeremy L Thompson       CeedCall(CeedGetPreferredMemType(CeedOperatorReturnCeed(op), &mem_type));
18653f919cbcSJeremy L Thompson       if (mem_type == CEED_MEM_DEVICE) {
18663f919cbcSJeremy L Thompson         // Device backends pad out to the same number of points per element
18673f919cbcSJeremy L Thompson         CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr_points, &num_points));
18683f919cbcSJeremy L Thompson       } else {
18693f919cbcSJeremy L Thompson         num_points = 0;
18703f919cbcSJeremy L Thompson         for (CeedInt i = 0; i < num_elem; i++) {
18713f919cbcSJeremy L Thompson           CeedInt points_in_elem = 0;
18723f919cbcSJeremy L Thompson 
18733f919cbcSJeremy L Thompson           CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr_points, i, &points_in_elem));
18743f919cbcSJeremy L Thompson           num_points += points_in_elem;
18753f919cbcSJeremy L Thompson         }
18763f919cbcSJeremy L Thompson         num_points = num_points / num_elem + (num_points % num_elem > 0);
18773f919cbcSJeremy L Thompson       }
18783f919cbcSJeremy L Thompson       CeedCall(CeedElemRestrictionDestroy(&rstr_points));
18793f919cbcSJeremy L Thompson     }
18801203703bSJeremy L Thompson     CeedCall(CeedOperatorGetQFunction(op, &qf));
18811203703bSJeremy L Thompson     CeedCall(CeedQFunctionGetFields(qf, &num_input_fields, &qf_input_fields, &num_output_fields, &qf_output_fields));
1882c11e12f4SJeremy L Thompson     CeedCall(CeedQFunctionDestroy(&qf));
18831203703bSJeremy L Thompson     CeedCall(CeedOperatorGetFields(op, NULL, &op_input_fields, NULL, &op_output_fields));
18844385fb7fSSebastian Grimberg 
18856e15d496SJeremy L Thompson     // Input FLOPs
18866e15d496SJeremy L Thompson     for (CeedInt i = 0; i < num_input_fields; i++) {
18871203703bSJeremy L Thompson       CeedVector vec;
18886e15d496SJeremy L Thompson 
18891203703bSJeremy L Thompson       CeedCall(CeedOperatorFieldGetVector(op_input_fields[i], &vec));
18901203703bSJeremy L Thompson       if (vec == CEED_VECTOR_ACTIVE) {
18911203703bSJeremy L Thompson         CeedEvalMode        eval_mode;
18921203703bSJeremy L Thompson         CeedSize            rstr_flops, basis_flops;
18931203703bSJeremy L Thompson         CeedElemRestriction rstr;
18941203703bSJeremy L Thompson         CeedBasis           basis;
18951203703bSJeremy L Thompson 
18961203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetElemRestriction(op_input_fields[i], &rstr));
18971203703bSJeremy L Thompson         CeedCall(CeedElemRestrictionGetFlopsEstimate(rstr, CEED_NOTRANSPOSE, &rstr_flops));
1898681d0ea7SJeremy L Thompson         CeedCall(CeedElemRestrictionDestroy(&rstr));
1899edb2538eSJeremy L Thompson         *flops += rstr_flops;
19001203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetBasis(op_input_fields[i], &basis));
19011203703bSJeremy L Thompson         CeedCall(CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode));
19023f919cbcSJeremy L Thompson         CeedCall(CeedBasisGetFlopsEstimate(basis, CEED_NOTRANSPOSE, eval_mode, is_at_points, num_points, &basis_flops));
1903681d0ea7SJeremy L Thompson         CeedCall(CeedBasisDestroy(&basis));
19046e15d496SJeremy L Thompson         *flops += basis_flops * num_elem;
19056e15d496SJeremy L Thompson       }
1906681d0ea7SJeremy L Thompson       CeedCall(CeedVectorDestroy(&vec));
19076e15d496SJeremy L Thompson     }
19086e15d496SJeremy L Thompson     // QF FLOPs
19091c66c397SJeremy L Thompson     {
19109d36ca50SJeremy L Thompson       CeedInt       num_qpts;
19119d36ca50SJeremy L Thompson       CeedSize      qf_flops;
19121203703bSJeremy L Thompson       CeedQFunction qf;
19131c66c397SJeremy L Thompson 
19143f919cbcSJeremy L Thompson       if (is_at_points) num_qpts = num_points;
19153f919cbcSJeremy L Thompson       else CeedCall(CeedOperatorGetNumQuadraturePoints(op, &num_qpts));
19161203703bSJeremy L Thompson       CeedCall(CeedOperatorGetQFunction(op, &qf));
19171203703bSJeremy L Thompson       CeedCall(CeedQFunctionGetFlopsEstimate(qf, &qf_flops));
1918c11e12f4SJeremy L Thompson       CeedCall(CeedQFunctionDestroy(&qf));
19196e536b99SJeremy L Thompson       CeedCheck(qf_flops > -1, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPLETE,
19206e536b99SJeremy L Thompson                 "Must set CeedQFunction FLOPs estimate with CeedQFunctionSetUserFlopsEstimate");
19216e15d496SJeremy L Thompson       *flops += num_elem * num_qpts * qf_flops;
19221c66c397SJeremy L Thompson     }
19231c66c397SJeremy L Thompson 
19246e15d496SJeremy L Thompson     // Output FLOPs
19256e15d496SJeremy L Thompson     for (CeedInt i = 0; i < num_output_fields; i++) {
19261203703bSJeremy L Thompson       CeedVector vec;
19276e15d496SJeremy L Thompson 
19281203703bSJeremy L Thompson       CeedCall(CeedOperatorFieldGetVector(op_output_fields[i], &vec));
19291203703bSJeremy L Thompson       if (vec == CEED_VECTOR_ACTIVE) {
19301203703bSJeremy L Thompson         CeedEvalMode        eval_mode;
19311203703bSJeremy L Thompson         CeedSize            rstr_flops, basis_flops;
19321203703bSJeremy L Thompson         CeedElemRestriction rstr;
19331203703bSJeremy L Thompson         CeedBasis           basis;
19341203703bSJeremy L Thompson 
19351203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetElemRestriction(op_output_fields[i], &rstr));
19361203703bSJeremy L Thompson         CeedCall(CeedElemRestrictionGetFlopsEstimate(rstr, CEED_TRANSPOSE, &rstr_flops));
1937681d0ea7SJeremy L Thompson         CeedCall(CeedElemRestrictionDestroy(&rstr));
1938edb2538eSJeremy L Thompson         *flops += rstr_flops;
19391203703bSJeremy L Thompson         CeedCall(CeedOperatorFieldGetBasis(op_output_fields[i], &basis));
19401203703bSJeremy L Thompson         CeedCall(CeedQFunctionFieldGetEvalMode(qf_output_fields[i], &eval_mode));
19413f919cbcSJeremy L Thompson         CeedCall(CeedBasisGetFlopsEstimate(basis, CEED_TRANSPOSE, eval_mode, is_at_points, num_points, &basis_flops));
1942681d0ea7SJeremy L Thompson         CeedCall(CeedBasisDestroy(&basis));
19436e15d496SJeremy L Thompson         *flops += basis_flops * num_elem;
19446e15d496SJeremy L Thompson       }
1945681d0ea7SJeremy L Thompson       CeedCall(CeedVectorDestroy(&vec));
19466e15d496SJeremy L Thompson     }
19476e15d496SJeremy L Thompson   }
19486e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19496e15d496SJeremy L Thompson }
19506e15d496SJeremy L Thompson 
19516e15d496SJeremy L Thompson /**
1952ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunction` global context for a `CeedOperator`.
19539fd66db6SSebastian Grimberg 
1954ca94c3ddSJeremy L Thompson   The caller is responsible for destroying `ctx` returned from this function via @ref CeedQFunctionContextDestroy().
1955512bb800SJeremy L Thompson 
1956ca94c3ddSJeremy L Thompson   Note: If the value of `ctx` passed into this function is non-`NULL`, then it is assumed that `ctx` is a pointer to a `CeedQFunctionContext`.
1957ca94c3ddSJeremy L Thompson         This `CeedQFunctionContext` will be destroyed if `ctx` is the only reference to this `CeedQFunctionContext`.
19580126412dSJeremy L Thompson 
1959ca94c3ddSJeremy L Thompson   @param[in]  op  `CeedOperator`
1960ca94c3ddSJeremy L Thompson   @param[out] ctx Variable to store `CeedQFunctionContext`
19610126412dSJeremy L Thompson 
19620126412dSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
19630126412dSJeremy L Thompson 
1964859c15bbSJames Wright   @ref Advanced
19650126412dSJeremy L Thompson **/
CeedOperatorGetContext(CeedOperator op,CeedQFunctionContext * ctx)19660126412dSJeremy L Thompson int CeedOperatorGetContext(CeedOperator op, CeedQFunctionContext *ctx) {
19671203703bSJeremy L Thompson   bool                 is_composite;
19681203703bSJeremy L Thompson   CeedQFunction        qf;
19691203703bSJeremy L Thompson   CeedQFunctionContext qf_ctx;
19701203703bSJeremy L Thompson 
19711203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
19726e536b99SJeremy L Thompson   CeedCheck(!is_composite, CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE, "Cannot retrieve CeedQFunctionContext for composite operator");
19731203703bSJeremy L Thompson   CeedCall(CeedOperatorGetQFunction(op, &qf));
19741203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &qf_ctx));
1975c11e12f4SJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&qf));
19761485364cSJeremy L Thompson   *ctx = NULL;
19771203703bSJeremy L Thompson   if (qf_ctx) CeedCall(CeedQFunctionContextReferenceCopy(qf_ctx, ctx));
19780126412dSJeremy L Thompson   return CEED_ERROR_SUCCESS;
19790126412dSJeremy L Thompson }
19800126412dSJeremy L Thompson 
19810126412dSJeremy L Thompson /**
1982ca94c3ddSJeremy L Thompson   @brief Get label for a registered `CeedQFunctionContext` field, or `NULL` if no field has been registered with this `field_name`.
19833668ca4bSJeremy L Thompson 
1984ca94c3ddSJeremy L Thompson   Fields are registered via `CeedQFunctionContextRegister*()` functions (eg. @ref CeedQFunctionContextRegisterDouble()).
1985859c15bbSJames Wright 
1986ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
19873668ca4bSJeremy L Thompson   @param[in]  field_name  Name of field to retrieve label
19883668ca4bSJeremy L Thompson   @param[out] field_label Variable to field label
19893668ca4bSJeremy L Thompson 
19903668ca4bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
19913668ca4bSJeremy L Thompson 
19923668ca4bSJeremy L Thompson   @ref User
19933668ca4bSJeremy L Thompson **/
CeedOperatorGetContextFieldLabel(CeedOperator op,const char * field_name,CeedContextFieldLabel * field_label)199417b0d5c6SJeremy L Thompson int CeedOperatorGetContextFieldLabel(CeedOperator op, const char *field_name, CeedContextFieldLabel *field_label) {
19951c66c397SJeremy L Thompson   bool is_composite, field_found = false;
19961c66c397SJeremy L Thompson 
19972b730f8bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
19982b730f8bSJeremy L Thompson 
19993668ca4bSJeremy L Thompson   if (is_composite) {
2000a98a090bSJeremy L Thompson     // Composite operator
2001a98a090bSJeremy L Thompson     // -- Check if composite label already created
20023668ca4bSJeremy L Thompson     for (CeedInt i = 0; i < op->num_context_labels; i++) {
20033668ca4bSJeremy L Thompson       if (!strcmp(op->context_labels[i]->name, field_name)) {
20043668ca4bSJeremy L Thompson         *field_label = op->context_labels[i];
20053668ca4bSJeremy L Thompson         return CEED_ERROR_SUCCESS;
20063668ca4bSJeremy L Thompson       }
20073668ca4bSJeremy L Thompson     }
20083668ca4bSJeremy L Thompson 
2009a98a090bSJeremy L Thompson     // -- Create composite label if needed
20103668ca4bSJeremy L Thompson     CeedInt               num_sub;
20113668ca4bSJeremy L Thompson     CeedOperator         *sub_operators;
20123668ca4bSJeremy L Thompson     CeedContextFieldLabel new_field_label;
20133668ca4bSJeremy L Thompson 
20142b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(1, &new_field_label));
2015ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_sub));
2016ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
20172b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(num_sub, &new_field_label->sub_labels));
20183668ca4bSJeremy L Thompson     new_field_label->num_sub_labels = num_sub;
20193668ca4bSJeremy L Thompson 
20203668ca4bSJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
20213668ca4bSJeremy L Thompson       if (sub_operators[i]->qf->ctx) {
20223668ca4bSJeremy L Thompson         CeedContextFieldLabel new_field_label_i;
20231c66c397SJeremy L Thompson 
20242b730f8bSJeremy L Thompson         CeedCall(CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, &new_field_label_i));
20253668ca4bSJeremy L Thompson         if (new_field_label_i) {
2026a98a090bSJeremy L Thompson           field_found                    = true;
20273668ca4bSJeremy L Thompson           new_field_label->sub_labels[i] = new_field_label_i;
20283668ca4bSJeremy L Thompson           new_field_label->name          = new_field_label_i->name;
20293668ca4bSJeremy L Thompson           new_field_label->description   = new_field_label_i->description;
20302b730f8bSJeremy L Thompson           if (new_field_label->type && new_field_label->type != new_field_label_i->type) {
20317bfe0f0eSJeremy L Thompson             // LCOV_EXCL_START
20322b730f8bSJeremy L Thompson             CeedCall(CeedFree(&new_field_label));
20336e536b99SJeremy L Thompson             return CeedError(CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE, "Incompatible field types on sub-operator contexts. %s != %s",
20342b730f8bSJeremy L Thompson                              CeedContextFieldTypes[new_field_label->type], CeedContextFieldTypes[new_field_label_i->type]);
20357bfe0f0eSJeremy L Thompson             // LCOV_EXCL_STOP
20367bfe0f0eSJeremy L Thompson           } else {
20377bfe0f0eSJeremy L Thompson             new_field_label->type = new_field_label_i->type;
20387bfe0f0eSJeremy L Thompson           }
20392b730f8bSJeremy L Thompson           if (new_field_label->num_values != 0 && new_field_label->num_values != new_field_label_i->num_values) {
20407bfe0f0eSJeremy L Thompson             // LCOV_EXCL_START
20412b730f8bSJeremy L Thompson             CeedCall(CeedFree(&new_field_label));
20426e536b99SJeremy L Thompson             return CeedError(CeedOperatorReturnCeed(op), CEED_ERROR_INCOMPATIBLE,
20436e536b99SJeremy L Thompson                              "Incompatible field number of values on sub-operator contexts. %zu != %zu", new_field_label->num_values,
20446e536b99SJeremy L Thompson                              new_field_label_i->num_values);
20457bfe0f0eSJeremy L Thompson             // LCOV_EXCL_STOP
20467bfe0f0eSJeremy L Thompson           } else {
20477bfe0f0eSJeremy L Thompson             new_field_label->num_values = new_field_label_i->num_values;
20487bfe0f0eSJeremy L Thompson           }
20493668ca4bSJeremy L Thompson         }
20503668ca4bSJeremy L Thompson       }
20513668ca4bSJeremy L Thompson     }
2052a98a090bSJeremy L Thompson     // -- Cleanup if field was found
2053a98a090bSJeremy L Thompson     if (field_found) {
2054a98a090bSJeremy L Thompson       *field_label = new_field_label;
2055a98a090bSJeremy L Thompson     } else {
20563668ca4bSJeremy L Thompson       // LCOV_EXCL_START
20572b730f8bSJeremy L Thompson       CeedCall(CeedFree(&new_field_label->sub_labels));
20582b730f8bSJeremy L Thompson       CeedCall(CeedFree(&new_field_label));
20593668ca4bSJeremy L Thompson       *field_label = NULL;
20603668ca4bSJeremy L Thompson       // LCOV_EXCL_STOP
20615ac9af79SJeremy L Thompson     }
20625ac9af79SJeremy L Thompson   } else {
20631203703bSJeremy L Thompson     CeedQFunction        qf;
20641203703bSJeremy L Thompson     CeedQFunctionContext ctx;
20651203703bSJeremy L Thompson 
2066a98a090bSJeremy L Thompson     // Single, non-composite operator
20671203703bSJeremy L Thompson     CeedCall(CeedOperatorGetQFunction(op, &qf));
20681203703bSJeremy L Thompson     CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
2069c11e12f4SJeremy L Thompson     CeedCall(CeedQFunctionDestroy(&qf));
20701203703bSJeremy L Thompson     if (ctx) {
20711203703bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetFieldLabel(ctx, field_name, field_label));
2072a98a090bSJeremy L Thompson     } else {
2073a98a090bSJeremy L Thompson       *field_label = NULL;
2074a98a090bSJeremy L Thompson     }
20755ac9af79SJeremy L Thompson   }
20765ac9af79SJeremy L Thompson 
20775ac9af79SJeremy L Thompson   // Set label in operator
20785ac9af79SJeremy L Thompson   if (*field_label) {
20795ac9af79SJeremy L Thompson     (*field_label)->from_op = true;
20805ac9af79SJeremy L Thompson 
20813668ca4bSJeremy L Thompson     // Move new composite label to operator
20823668ca4bSJeremy L Thompson     if (op->num_context_labels == 0) {
20832b730f8bSJeremy L Thompson       CeedCall(CeedCalloc(1, &op->context_labels));
20843668ca4bSJeremy L Thompson       op->max_context_labels = 1;
20853668ca4bSJeremy L Thompson     } else if (op->num_context_labels == op->max_context_labels) {
20862b730f8bSJeremy L Thompson       CeedCall(CeedRealloc(2 * op->num_context_labels, &op->context_labels));
20873668ca4bSJeremy L Thompson       op->max_context_labels *= 2;
20883668ca4bSJeremy L Thompson     }
20895ac9af79SJeremy L Thompson     op->context_labels[op->num_context_labels] = *field_label;
20903668ca4bSJeremy L Thompson     op->num_context_labels++;
20913668ca4bSJeremy L Thompson   }
20923668ca4bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
20933668ca4bSJeremy L Thompson }
20943668ca4bSJeremy L Thompson 
20953668ca4bSJeremy L Thompson /**
2096ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field holding double precision values.
20974385fb7fSSebastian Grimberg 
2098ca94c3ddSJeremy L Thompson   For composite operators, the values are set in all sub-operator `CeedQFunctionContext` that have a matching `field_name`.
2099d8dd9a91SJeremy L Thompson 
2100ca94c3ddSJeremy L Thompson   @param[in,out] op          `CeedOperator`
21012788fa27SJeremy L Thompson   @param[in]     field_label Label of field to set
2102ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
2103d8dd9a91SJeremy L Thompson 
2104d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2105d8dd9a91SJeremy L Thompson 
2106d8dd9a91SJeremy L Thompson   @ref User
2107d8dd9a91SJeremy L Thompson **/
CeedOperatorSetContextDouble(CeedOperator op,CeedContextFieldLabel field_label,double * values)210817b0d5c6SJeremy L Thompson int CeedOperatorSetContextDouble(CeedOperator op, CeedContextFieldLabel field_label, double *values) {
21092b730f8bSJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, values);
2110d8dd9a91SJeremy L Thompson }
2111d8dd9a91SJeremy L Thompson 
2112d8dd9a91SJeremy L Thompson /**
2113ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field holding double precision values, read-only.
21144385fb7fSSebastian Grimberg 
2115ca94c3ddSJeremy L Thompson   For composite operators, the values correspond to the first sub-operator `CeedQFunctionContext` that has a matching `field_name`.
21162788fa27SJeremy L Thompson 
2117ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
21182788fa27SJeremy L Thompson   @param[in]  field_label Label of field to get
21192788fa27SJeremy L Thompson   @param[out] num_values  Number of values in the field label
21202788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
21212788fa27SJeremy L Thompson 
21222788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21232788fa27SJeremy L Thompson 
21242788fa27SJeremy L Thompson   @ref User
21252788fa27SJeremy L Thompson **/
CeedOperatorGetContextDoubleRead(CeedOperator op,CeedContextFieldLabel field_label,size_t * num_values,const double ** values)212617b0d5c6SJeremy L Thompson int CeedOperatorGetContextDoubleRead(CeedOperator op, CeedContextFieldLabel field_label, size_t *num_values, const double **values) {
21272788fa27SJeremy L Thompson   return CeedOperatorContextGetGenericRead(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, num_values, values);
21282788fa27SJeremy L Thompson }
21292788fa27SJeremy L Thompson 
21302788fa27SJeremy L Thompson /**
2131ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field holding double precision values, read-only.
21322788fa27SJeremy L Thompson 
2133ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
21342788fa27SJeremy L Thompson   @param[in]  field_label Label of field to restore
21352788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
21362788fa27SJeremy L Thompson 
21372788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21382788fa27SJeremy L Thompson 
21392788fa27SJeremy L Thompson   @ref User
21402788fa27SJeremy L Thompson **/
CeedOperatorRestoreContextDoubleRead(CeedOperator op,CeedContextFieldLabel field_label,const double ** values)214117b0d5c6SJeremy L Thompson int CeedOperatorRestoreContextDoubleRead(CeedOperator op, CeedContextFieldLabel field_label, const double **values) {
21422788fa27SJeremy L Thompson   return CeedOperatorContextRestoreGenericRead(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, values);
21432788fa27SJeremy L Thompson }
21442788fa27SJeremy L Thompson 
21452788fa27SJeremy L Thompson /**
2146ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field holding `int32` values.
21474385fb7fSSebastian Grimberg 
2148ca94c3ddSJeremy L Thompson   For composite operators, the values are set in all sub-operator `CeedQFunctionContext` that have a matching `field_name`.
2149d8dd9a91SJeremy L Thompson 
2150ca94c3ddSJeremy L Thompson   @param[in,out] op          `CeedOperator`
2151ea61e9acSJeremy L Thompson   @param[in]     field_label Label of field to set
2152ea61e9acSJeremy L Thompson   @param[in]     values      Values to set
2153d8dd9a91SJeremy L Thompson 
2154d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2155d8dd9a91SJeremy L Thompson 
2156d8dd9a91SJeremy L Thompson   @ref User
2157d8dd9a91SJeremy L Thompson **/
CeedOperatorSetContextInt32(CeedOperator op,CeedContextFieldLabel field_label,int32_t * values)215823dbfd29SJeremy L Thompson int CeedOperatorSetContextInt32(CeedOperator op, CeedContextFieldLabel field_label, int32_t *values) {
21592b730f8bSJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, values);
2160d8dd9a91SJeremy L Thompson }
2161d8dd9a91SJeremy L Thompson 
2162d8dd9a91SJeremy L Thompson /**
2163ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field holding `int32` values, read-only.
21644385fb7fSSebastian Grimberg 
2165ca94c3ddSJeremy L Thompson   For composite operators, the values correspond to the first sub-operator `CeedQFunctionContext` that has a matching `field_name`.
21662788fa27SJeremy L Thompson 
2167ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
21682788fa27SJeremy L Thompson   @param[in]  field_label Label of field to get
2169ca94c3ddSJeremy L Thompson   @param[out] num_values  Number of `int32` values in `values`
21702788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
21712788fa27SJeremy L Thompson 
21722788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21732788fa27SJeremy L Thompson 
21742788fa27SJeremy L Thompson   @ref User
21752788fa27SJeremy L Thompson **/
CeedOperatorGetContextInt32Read(CeedOperator op,CeedContextFieldLabel field_label,size_t * num_values,const int32_t ** values)217623dbfd29SJeremy L Thompson int CeedOperatorGetContextInt32Read(CeedOperator op, CeedContextFieldLabel field_label, size_t *num_values, const int32_t **values) {
21772788fa27SJeremy L Thompson   return CeedOperatorContextGetGenericRead(op, field_label, CEED_CONTEXT_FIELD_INT32, num_values, values);
21782788fa27SJeremy L Thompson }
21792788fa27SJeremy L Thompson 
21802788fa27SJeremy L Thompson /**
2181ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field holding `int32` values, read-only.
21822788fa27SJeremy L Thompson 
2183ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
21842788fa27SJeremy L Thompson   @param[in]  field_label Label of field to get
21852788fa27SJeremy L Thompson   @param[out] values      Pointer to context values
21862788fa27SJeremy L Thompson 
21872788fa27SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21882788fa27SJeremy L Thompson 
21892788fa27SJeremy L Thompson   @ref User
21902788fa27SJeremy L Thompson **/
CeedOperatorRestoreContextInt32Read(CeedOperator op,CeedContextFieldLabel field_label,const int32_t ** values)219123dbfd29SJeremy L Thompson int CeedOperatorRestoreContextInt32Read(CeedOperator op, CeedContextFieldLabel field_label, const int32_t **values) {
21922788fa27SJeremy L Thompson   return CeedOperatorContextRestoreGenericRead(op, field_label, CEED_CONTEXT_FIELD_INT32, values);
21932788fa27SJeremy L Thompson }
21942788fa27SJeremy L Thompson 
21952788fa27SJeremy L Thompson /**
2196ca94c3ddSJeremy L Thompson   @brief Set `CeedQFunctionContext` field holding boolean values.
21975b6ec284SJeremy L Thompson 
2198ca94c3ddSJeremy L Thompson   For composite operators, the values are set in all sub-operator `CeedQFunctionContext` that have a matching `field_name`.
21995b6ec284SJeremy L Thompson 
2200ca94c3ddSJeremy L Thompson   @param[in,out] op          `CeedOperator`
22015b6ec284SJeremy L Thompson   @param[in]     field_label Label of field to set
22025b6ec284SJeremy L Thompson   @param[in]     values      Values to set
22035b6ec284SJeremy L Thompson 
22045b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22055b6ec284SJeremy L Thompson 
22065b6ec284SJeremy L Thompson   @ref User
22075b6ec284SJeremy L Thompson **/
CeedOperatorSetContextBoolean(CeedOperator op,CeedContextFieldLabel field_label,bool * values)22085b6ec284SJeremy L Thompson int CeedOperatorSetContextBoolean(CeedOperator op, CeedContextFieldLabel field_label, bool *values) {
22095b6ec284SJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_BOOL, values);
22105b6ec284SJeremy L Thompson }
22115b6ec284SJeremy L Thompson 
22125b6ec284SJeremy L Thompson /**
2213ca94c3ddSJeremy L Thompson   @brief Get `CeedQFunctionContext` field holding boolean values, read-only.
22145b6ec284SJeremy L Thompson 
2215ca94c3ddSJeremy L Thompson   For composite operators, the values correspond to the first sub-operator `CeedQFunctionContext` that has a matching `field_name`.
22165b6ec284SJeremy L Thompson 
2217ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
22185b6ec284SJeremy L Thompson   @param[in]  field_label Label of field to get
2219ca94c3ddSJeremy L Thompson   @param[out] num_values  Number of boolean values in `values`
22205b6ec284SJeremy L Thompson   @param[out] values      Pointer to context values
22215b6ec284SJeremy L Thompson 
22225b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22235b6ec284SJeremy L Thompson 
22245b6ec284SJeremy L Thompson   @ref User
22255b6ec284SJeremy L Thompson **/
CeedOperatorGetContextBooleanRead(CeedOperator op,CeedContextFieldLabel field_label,size_t * num_values,const bool ** values)22265b6ec284SJeremy L Thompson int CeedOperatorGetContextBooleanRead(CeedOperator op, CeedContextFieldLabel field_label, size_t *num_values, const bool **values) {
22275b6ec284SJeremy L Thompson   return CeedOperatorContextGetGenericRead(op, field_label, CEED_CONTEXT_FIELD_BOOL, num_values, values);
22285b6ec284SJeremy L Thompson }
22295b6ec284SJeremy L Thompson 
22305b6ec284SJeremy L Thompson /**
2231ca94c3ddSJeremy L Thompson   @brief Restore `CeedQFunctionContext` field holding boolean values, read-only.
22325b6ec284SJeremy L Thompson 
2233ca94c3ddSJeremy L Thompson   @param[in]  op          `CeedOperator`
22345b6ec284SJeremy L Thompson   @param[in]  field_label Label of field to get
22355b6ec284SJeremy L Thompson   @param[out] values      Pointer to context values
22365b6ec284SJeremy L Thompson 
22375b6ec284SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22385b6ec284SJeremy L Thompson 
22395b6ec284SJeremy L Thompson   @ref User
22405b6ec284SJeremy L Thompson **/
CeedOperatorRestoreContextBooleanRead(CeedOperator op,CeedContextFieldLabel field_label,const bool ** values)22415b6ec284SJeremy L Thompson int CeedOperatorRestoreContextBooleanRead(CeedOperator op, CeedContextFieldLabel field_label, const bool **values) {
22425b6ec284SJeremy L Thompson   return CeedOperatorContextRestoreGenericRead(op, field_label, CEED_CONTEXT_FIELD_BOOL, values);
22435b6ec284SJeremy L Thompson }
22445b6ec284SJeremy L Thompson 
22455b6ec284SJeremy L Thompson /**
2246ca94c3ddSJeremy L Thompson   @brief Apply `CeedOperator` to a `CeedVector`.
2247d7b241e6Sjeremylt 
2248ea61e9acSJeremy L Thompson   This computes the action of the operator on the specified (active) input, yielding its (active) output.
2249ca94c3ddSJeremy L Thompson   All inputs and outputs must be specified using @ref CeedOperatorSetField().
2250d7b241e6Sjeremylt 
22515da5ab9fSZach Atkins   @note Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
2252f04ea552SJeremy L Thompson 
2253ca94c3ddSJeremy L Thompson   @param[in]  op      `CeedOperator` to apply
2254ca94c3ddSJeremy L Thompson   @param[in]  in      `CeedVector` containing input state or @ref CEED_VECTOR_NONE if there are no active inputs
2255ca94c3ddSJeremy L Thompson   @param[out] out     `CeedVector` to store result of applying operator (must be distinct from `in`) or @ref CEED_VECTOR_NONE if there are no active outputs
2256ca94c3ddSJeremy L Thompson   @param[in]  request Address of @ref CeedRequest for non-blocking completion, else @ref CEED_REQUEST_IMMEDIATE
2257b11c1e72Sjeremylt 
2258b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
2259dfdf5a53Sjeremylt 
22607a982d89SJeremy L. Thompson   @ref User
2261b11c1e72Sjeremylt **/
CeedOperatorApply(CeedOperator op,CeedVector in,CeedVector out,CeedRequest * request)22622b730f8bSJeremy L Thompson int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, CeedRequest *request) {
22631203703bSJeremy L Thompson   bool is_composite;
22641203703bSJeremy L Thompson 
22652b730f8bSJeremy L Thompson   CeedCall(CeedOperatorCheckReady(op));
2266d7b241e6Sjeremylt 
22671203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
22680db52efcSZach Atkins   if (is_composite && op->ApplyComposite) {
2269250756a7Sjeremylt     // Composite Operator
22702b730f8bSJeremy L Thompson     CeedCall(op->ApplyComposite(op, in, out, request));
22710db52efcSZach Atkins   } else if (!is_composite && op->Apply) {
22723ca2b39bSJeremy L Thompson     // Standard Operator
22733ca2b39bSJeremy L Thompson     CeedCall(op->Apply(op, in, out, request));
22743ca2b39bSJeremy L Thompson   } else {
22750db52efcSZach Atkins     // Standard or composite, default to zeroing out and calling ApplyAddActive
22760db52efcSZach Atkins     // Zero active output
22770db52efcSZach Atkins     if (out != CEED_VECTOR_NONE) CeedCall(CeedVectorSetValue(out, 0.0));
22781203703bSJeremy L Thompson 
22790db52efcSZach Atkins     // ApplyAddActive
22800db52efcSZach Atkins     CeedCall(CeedOperatorApplyAddActive(op, in, out, request));
2281250756a7Sjeremylt   }
2282e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2283cae8b89aSjeremylt }
2284cae8b89aSjeremylt 
2285cae8b89aSjeremylt /**
2286ca94c3ddSJeremy L Thompson   @brief Apply `CeedOperator` to a `CeedVector` and add result to output `CeedVector`.
2287cae8b89aSjeremylt 
2288ea61e9acSJeremy L Thompson   This computes the action of the operator on the specified (active) input, yielding its (active) output.
2289ca94c3ddSJeremy L Thompson   All inputs and outputs must be specified using @ref CeedOperatorSetField().
2290cae8b89aSjeremylt 
22915da5ab9fSZach Atkins   @note Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
22925da5ab9fSZach Atkins   @warning This function adds into ALL outputs, including passive outputs. To only add into the active output, use `CeedOperatorApplyAddActive()`.
22935da5ab9fSZach Atkins   @see `CeedOperatorApplyAddActive()`
22945da5ab9fSZach Atkins 
2295ca94c3ddSJeremy L Thompson   @param[in]  op      `CeedOperator` to apply
2296ca94c3ddSJeremy L Thompson   @param[in]  in      `CeedVector` containing input state or @ref CEED_VECTOR_NONE if there are no active inputs
2297ca94c3ddSJeremy L Thompson   @param[out] out     `CeedVector` to sum in result of applying operator (must be distinct from `in`) or @ref CEED_VECTOR_NONE if there are no active outputs
2298ca94c3ddSJeremy L Thompson   @param[in]  request Address of @ref CeedRequest for non-blocking completion, else @ref CEED_REQUEST_IMMEDIATE
2299cae8b89aSjeremylt 
2300cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
2301cae8b89aSjeremylt 
23027a982d89SJeremy L. Thompson   @ref User
2303cae8b89aSjeremylt **/
CeedOperatorApplyAdd(CeedOperator op,CeedVector in,CeedVector out,CeedRequest * request)23042b730f8bSJeremy L Thompson int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, CeedRequest *request) {
23051203703bSJeremy L Thompson   bool is_composite;
23061203703bSJeremy L Thompson 
23072b730f8bSJeremy L Thompson   CeedCall(CeedOperatorCheckReady(op));
2308cae8b89aSjeremylt 
23091203703bSJeremy L Thompson   CeedCall(CeedOperatorIsComposite(op, &is_composite));
23101203703bSJeremy L Thompson   if (is_composite) {
2311250756a7Sjeremylt     // Composite Operator
2312250756a7Sjeremylt     if (op->ApplyAddComposite) {
23132b730f8bSJeremy L Thompson       CeedCall(op->ApplyAddComposite(op, in, out, request));
2314cae8b89aSjeremylt     } else {
2315d1d35e2fSjeremylt       CeedInt       num_suboperators;
2316d1d35e2fSjeremylt       CeedOperator *sub_operators;
2317250756a7Sjeremylt 
2318ed094490SJeremy L Thompson       CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
2319ed094490SJeremy L Thompson       CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
2320d1d35e2fSjeremylt       for (CeedInt i = 0; i < num_suboperators; i++) {
23212b730f8bSJeremy L Thompson         CeedCall(CeedOperatorApplyAdd(sub_operators[i], in, out, request));
23221d7d2407SJeremy L Thompson       }
2323250756a7Sjeremylt     }
23241203703bSJeremy L Thompson   } else if (op->num_elem > 0) {
23253ca2b39bSJeremy L Thompson     // Standard Operator
23263ca2b39bSJeremy L Thompson     CeedCall(op->ApplyAdd(op, in, out, request));
2327250756a7Sjeremylt   }
2328e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2329d7b241e6Sjeremylt }
2330d7b241e6Sjeremylt 
2331d7b241e6Sjeremylt /**
23325da5ab9fSZach Atkins   @brief Apply `CeedOperator` to a `CeedVector` and add result to output `CeedVector`. Only sums into active outputs, overwrites passive outputs.
23335da5ab9fSZach Atkins 
23345da5ab9fSZach Atkins   This computes the action of the operator on the specified (active) input, yielding its (active) output.
23355da5ab9fSZach Atkins   All inputs and outputs must be specified using @ref CeedOperatorSetField().
23365da5ab9fSZach Atkins 
23375da5ab9fSZach Atkins   @note Calling this function asserts that setup is complete and sets the `CeedOperator` as immutable.
23385da5ab9fSZach Atkins 
23395da5ab9fSZach Atkins   @param[in]  op      `CeedOperator` to apply
23405da5ab9fSZach Atkins   @param[in]  in      `CeedVector` containing input state or @ref CEED_VECTOR_NONE if there are no active inputs
23415da5ab9fSZach Atkins   @param[out] out     `CeedVector` to sum in result of applying operator (must be distinct from `in`) or @ref CEED_VECTOR_NONE if there are no active outputs
23425da5ab9fSZach Atkins   @param[in]  request Address of @ref CeedRequest for non-blocking completion, else @ref CEED_REQUEST_IMMEDIATE
23435da5ab9fSZach Atkins 
23445da5ab9fSZach Atkins   @return An error code: 0 - success, otherwise - failure
23455da5ab9fSZach Atkins 
23465da5ab9fSZach Atkins   @ref User
23475da5ab9fSZach Atkins **/
CeedOperatorApplyAddActive(CeedOperator op,CeedVector in,CeedVector out,CeedRequest * request)23485da5ab9fSZach Atkins int CeedOperatorApplyAddActive(CeedOperator op, CeedVector in, CeedVector out, CeedRequest *request) {
23495da5ab9fSZach Atkins   bool is_composite;
23505da5ab9fSZach Atkins 
23515da5ab9fSZach Atkins   CeedCall(CeedOperatorCheckReady(op));
23525da5ab9fSZach Atkins 
23535da5ab9fSZach Atkins   CeedCall(CeedOperatorIsComposite(op, &is_composite));
23545da5ab9fSZach Atkins   if (is_composite) {
23555da5ab9fSZach Atkins     // Composite Operator
23565da5ab9fSZach Atkins     CeedInt       num_suboperators;
23575da5ab9fSZach Atkins     CeedOperator *sub_operators;
23585da5ab9fSZach Atkins 
2359ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
2360ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
23615da5ab9fSZach Atkins 
23625da5ab9fSZach Atkins     // Zero all output vectors
23635da5ab9fSZach Atkins     for (CeedInt i = 0; i < num_suboperators; i++) {
23645da5ab9fSZach Atkins       CeedInt            num_output_fields;
23655da5ab9fSZach Atkins       CeedOperatorField *output_fields;
23665da5ab9fSZach Atkins 
23675da5ab9fSZach Atkins       CeedCall(CeedOperatorGetFields(sub_operators[i], NULL, NULL, &num_output_fields, &output_fields));
23685da5ab9fSZach Atkins       for (CeedInt j = 0; j < num_output_fields; j++) {
23695da5ab9fSZach Atkins         CeedVector vec;
23705da5ab9fSZach Atkins 
23715da5ab9fSZach Atkins         CeedCall(CeedOperatorFieldGetVector(output_fields[j], &vec));
23725da5ab9fSZach Atkins         if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) CeedCall(CeedVectorSetValue(vec, 0.0));
23735da5ab9fSZach Atkins         CeedCall(CeedVectorDestroy(&vec));
23745da5ab9fSZach Atkins       }
23755da5ab9fSZach Atkins     }
23765da5ab9fSZach Atkins     // ApplyAdd
23775da5ab9fSZach Atkins     CeedCall(CeedOperatorApplyAdd(op, in, out, request));
23785da5ab9fSZach Atkins   } else {
23795da5ab9fSZach Atkins     // Standard Operator
23805da5ab9fSZach Atkins     CeedInt            num_output_fields;
23815da5ab9fSZach Atkins     CeedOperatorField *output_fields;
23825da5ab9fSZach Atkins 
23835da5ab9fSZach Atkins     CeedCall(CeedOperatorGetFields(op, NULL, NULL, &num_output_fields, &output_fields));
23845da5ab9fSZach Atkins     // Zero all output vectors
23855da5ab9fSZach Atkins     for (CeedInt i = 0; i < num_output_fields; i++) {
23865da5ab9fSZach Atkins       CeedVector vec;
23875da5ab9fSZach Atkins 
23885da5ab9fSZach Atkins       CeedCall(CeedOperatorFieldGetVector(output_fields[i], &vec));
23895da5ab9fSZach Atkins       if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) CeedCall(CeedVectorSetValue(vec, 0.0));
23905da5ab9fSZach Atkins       CeedCall(CeedVectorDestroy(&vec));
23915da5ab9fSZach Atkins     }
23925da5ab9fSZach Atkins     // ApplyAdd
23935da5ab9fSZach Atkins     CeedCall(CeedOperatorApplyAdd(op, in, out, request));
23945da5ab9fSZach Atkins   }
23955da5ab9fSZach Atkins   return CEED_ERROR_SUCCESS;
23965da5ab9fSZach Atkins }
23975da5ab9fSZach Atkins 
23985da5ab9fSZach Atkins /**
2399536b928cSSebastian Grimberg   @brief Destroy temporary assembly data associated with a `CeedOperator`
2400536b928cSSebastian Grimberg 
2401536b928cSSebastian Grimberg   @param[in,out] op `CeedOperator` whose assembly data to destroy
2402536b928cSSebastian Grimberg 
2403536b928cSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
2404536b928cSSebastian Grimberg 
2405536b928cSSebastian Grimberg   @ref User
2406536b928cSSebastian Grimberg **/
CeedOperatorAssemblyDataStrip(CeedOperator op)2407536b928cSSebastian Grimberg int CeedOperatorAssemblyDataStrip(CeedOperator op) {
2408536b928cSSebastian Grimberg   bool is_composite;
2409536b928cSSebastian Grimberg 
2410536b928cSSebastian Grimberg   CeedCall(CeedQFunctionAssemblyDataDestroy(&op->qf_assembled));
2411536b928cSSebastian Grimberg   CeedCall(CeedOperatorAssemblyDataDestroy(&op->op_assembled));
2412536b928cSSebastian Grimberg   CeedCall(CeedOperatorIsComposite(op, &is_composite));
2413536b928cSSebastian Grimberg   if (is_composite) {
2414536b928cSSebastian Grimberg     CeedInt       num_suboperators;
2415536b928cSSebastian Grimberg     CeedOperator *sub_operators;
2416536b928cSSebastian Grimberg 
2417ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetNumSub(op, &num_suboperators));
2418ed094490SJeremy L Thompson     CeedCall(CeedOperatorCompositeGetSubList(op, &sub_operators));
2419536b928cSSebastian Grimberg     for (CeedInt i = 0; i < num_suboperators; i++) {
2420536b928cSSebastian Grimberg       CeedCall(CeedQFunctionAssemblyDataDestroy(&sub_operators[i]->qf_assembled));
2421536b928cSSebastian Grimberg       CeedCall(CeedOperatorAssemblyDataDestroy(&sub_operators[i]->op_assembled));
2422536b928cSSebastian Grimberg     }
2423536b928cSSebastian Grimberg   }
2424536b928cSSebastian Grimberg   return CEED_ERROR_SUCCESS;
2425536b928cSSebastian Grimberg }
2426536b928cSSebastian Grimberg 
2427536b928cSSebastian Grimberg /**
2428ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedOperator`
2429d7b241e6Sjeremylt 
2430ca94c3ddSJeremy L Thompson   @param[in,out] op `CeedOperator` to destroy
2431b11c1e72Sjeremylt 
2432b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
2433dfdf5a53Sjeremylt 
24347a982d89SJeremy L. Thompson   @ref User
2435b11c1e72Sjeremylt **/
CeedOperatorDestroy(CeedOperator * op)2436d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
2437b0f67a9cSJeremy L Thompson   if (!*op || CeedObjectDereference((CeedObject)*op) > 0) {
2438ad6481ceSJeremy L Thompson     *op = NULL;
2439ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
2440ad6481ceSJeremy L Thompson   }
2441f883f0a5SSebastian Grimberg   // Backend destroy
2442f883f0a5SSebastian Grimberg   if ((*op)->Destroy) {
2443f883f0a5SSebastian Grimberg     CeedCall((*op)->Destroy(*op));
2444f883f0a5SSebastian Grimberg   }
2445fe2413ffSjeremylt   // Free fields
24462b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < (*op)->num_fields; i++) {
2447d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
2448437c7c90SJeremy L Thompson       if ((*op)->input_fields[i]->elem_rstr != CEED_ELEMRESTRICTION_NONE) {
2449437c7c90SJeremy L Thompson         CeedCall(CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_rstr));
245015910d16Sjeremylt       }
2451356036faSJeremy L Thompson       if ((*op)->input_fields[i]->basis != CEED_BASIS_NONE) {
24522b730f8bSJeremy L Thompson         CeedCall(CeedBasisDestroy(&(*op)->input_fields[i]->basis));
245371352a93Sjeremylt       }
24542b730f8bSJeremy L Thompson       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && (*op)->input_fields[i]->vec != CEED_VECTOR_NONE) {
24552b730f8bSJeremy L Thompson         CeedCall(CeedVectorDestroy(&(*op)->input_fields[i]->vec));
245671352a93Sjeremylt       }
24572b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*op)->input_fields[i]->field_name));
24582b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*op)->input_fields[i]));
2459fe2413ffSjeremylt     }
24602b730f8bSJeremy L Thompson   }
24612b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < (*op)->num_fields; i++) {
2462d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
2463437c7c90SJeremy L Thompson       CeedCall(CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_rstr));
2464356036faSJeremy L Thompson       if ((*op)->output_fields[i]->basis != CEED_BASIS_NONE) {
24652b730f8bSJeremy L Thompson         CeedCall(CeedBasisDestroy(&(*op)->output_fields[i]->basis));
246671352a93Sjeremylt       }
24672b730f8bSJeremy L Thompson       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && (*op)->output_fields[i]->vec != CEED_VECTOR_NONE) {
24682b730f8bSJeremy L Thompson         CeedCall(CeedVectorDestroy(&(*op)->output_fields[i]->vec));
246971352a93Sjeremylt       }
24702b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*op)->output_fields[i]->field_name));
24712b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*op)->output_fields[i]));
24722b730f8bSJeremy L Thompson     }
2473fe2413ffSjeremylt   }
2474f883f0a5SSebastian Grimberg   CeedCall(CeedFree(&(*op)->input_fields));
2475f883f0a5SSebastian Grimberg   CeedCall(CeedFree(&(*op)->output_fields));
2476f883f0a5SSebastian Grimberg   // Destroy AtPoints data
247748acf710SJeremy L Thompson   CeedCall(CeedVectorDestroy(&(*op)->point_coords));
247848acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(&(*op)->rstr_points));
247948acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(&(*op)->first_points_rstr));
2480c6b536a8SSebastian Grimberg   // Destroy assembly data (must happen before destroying sub_operators)
2481f883f0a5SSebastian Grimberg   CeedCall(CeedOperatorAssemblyDataStrip(*op));
2482d1d35e2fSjeremylt   // Destroy sub_operators
24832b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < (*op)->num_suboperators; i++) {
2484d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
24852b730f8bSJeremy L Thompson       CeedCall(CeedOperatorDestroy(&(*op)->sub_operators[i]));
248652d6035fSJeremy L Thompson     }
24872b730f8bSJeremy L Thompson   }
2488f883f0a5SSebastian Grimberg   CeedCall(CeedFree(&(*op)->sub_operators));
24892b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&(*op)->qf));
24902b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&(*op)->dqf));
24912b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionDestroy(&(*op)->dqfT));
24923668ca4bSJeremy L Thompson   // Destroy any composite labels
24935ac9af79SJeremy L Thompson   if ((*op)->is_composite) {
24943668ca4bSJeremy L Thompson     for (CeedInt i = 0; i < (*op)->num_context_labels; i++) {
24952b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*op)->context_labels[i]->sub_labels));
24962b730f8bSJeremy L Thompson       CeedCall(CeedFree(&(*op)->context_labels[i]));
24973668ca4bSJeremy L Thompson     }
24985ac9af79SJeremy L Thompson   }
24992b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*op)->context_labels));
2500fe2413ffSjeremylt 
25015107b09fSJeremy L Thompson   // Destroy fallback
25022b730f8bSJeremy L Thompson   CeedCall(CeedOperatorDestroy(&(*op)->op_fallback));
25035107b09fSJeremy L Thompson 
25042b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*op)->name));
25056c328a79SJeremy L Thompson   CeedCall(CeedObjectDestroy_Private(&(*op)->obj));
25062b730f8bSJeremy L Thompson   CeedCall(CeedFree(op));
2507e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2508d7b241e6Sjeremylt }
2509d7b241e6Sjeremylt 
2510d7b241e6Sjeremylt /// @}
2511