xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision d8dd9a912dc9d585dc5c0667639a4157f4b711a3)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17ec3da8bcSJed Brown #include <ceed/ceed.h>
18ec3da8bcSJed Brown #include <ceed/backend.h>
193d576824SJeremy L Thompson #include <ceed-impl.h>
203d576824SJeremy L Thompson #include <stdbool.h>
213d576824SJeremy L Thompson #include <stdio.h>
223d576824SJeremy L Thompson #include <string.h>
23d7b241e6Sjeremylt 
24dfdf5a53Sjeremylt /// @file
257a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces
267a982d89SJeremy L. Thompson 
277a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
287a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions
297a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
307a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper
317a982d89SJeremy L. Thompson /// @{
327a982d89SJeremy L. Thompson 
337a982d89SJeremy L. Thompson /**
34e15f9bd0SJeremy L Thompson   @brief Check if a CeedOperator Field matches the QFunction Field
35e15f9bd0SJeremy L Thompson 
36e15f9bd0SJeremy L Thompson   @param[in] ceed      Ceed object for error handling
37d1d35e2fSjeremylt   @param[in] qf_field  QFunction Field matching Operator Field
38e15f9bd0SJeremy L Thompson   @param[in] r         Operator Field ElemRestriction
39e15f9bd0SJeremy L Thompson   @param[in] b         Operator Field Basis
40e15f9bd0SJeremy L Thompson 
41e15f9bd0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
42e15f9bd0SJeremy L Thompson 
43e15f9bd0SJeremy L Thompson   @ref Developer
44e15f9bd0SJeremy L Thompson **/
45d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field,
46e15f9bd0SJeremy L Thompson                                   CeedElemRestriction r, CeedBasis b) {
47e15f9bd0SJeremy L Thompson   int ierr;
48d1d35e2fSjeremylt   CeedEvalMode eval_mode = qf_field->eval_mode;
49d1d35e2fSjeremylt   CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size;
50e15f9bd0SJeremy L Thompson   // Restriction
51e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
52d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_WEIGHT) {
53e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
54e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
55e1e9e29dSJed Brown                        "CEED_ELEMRESTRICTION_NONE should be used "
56e15f9bd0SJeremy L Thompson                        "for a field with eval mode CEED_EVAL_WEIGHT");
57e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
58e15f9bd0SJeremy L Thompson     }
59d1d35e2fSjeremylt     ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp);
6078464608Sjeremylt     CeedChk(ierr);
61e1e9e29dSJed Brown   }
62d1d35e2fSjeremylt   if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) {
63e1e9e29dSJed Brown     // LCOV_EXCL_START
64e1e9e29dSJed Brown     return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
65e1e9e29dSJed Brown                      "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT "
66e1e9e29dSJed Brown                      "must be used together.");
67e1e9e29dSJed Brown     // LCOV_EXCL_STOP
68e1e9e29dSJed Brown   }
69e15f9bd0SJeremy L Thompson   // Basis
70e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
71d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_NONE)
728229195eSjeremylt       // LCOV_EXCL_START
73e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
74d1d35e2fSjeremylt                        "Field '%s' configured with CEED_EVAL_NONE must "
75d1d35e2fSjeremylt                        "be used with CEED_BASIS_COLLOCATED",
768229195eSjeremylt                        // LCOV_EXCL_STOP
77d1d35e2fSjeremylt                        qf_field->field_name);
78e15f9bd0SJeremy L Thompson     ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr);
79d1d35e2fSjeremylt     ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr);
80d1d35e2fSjeremylt     if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) {
81e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
82e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
83d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s: ElemRestriction "
84d1d35e2fSjeremylt                        "has %d components, but Basis has %d components",
85d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
86d1d35e2fSjeremylt                        restr_num_comp,
87d1d35e2fSjeremylt                        num_comp);
88e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
89e15f9bd0SJeremy L Thompson     }
90e15f9bd0SJeremy L Thompson   }
91e15f9bd0SJeremy L Thompson   // Field size
92d1d35e2fSjeremylt   switch(eval_mode) {
93e15f9bd0SJeremy L Thompson   case CEED_EVAL_NONE:
94d1d35e2fSjeremylt     if (size != restr_num_comp)
95e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
96e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
97e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components",
98d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
99d1d35e2fSjeremylt                        restr_num_comp);
100e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
101e15f9bd0SJeremy L Thompson     break;
102e15f9bd0SJeremy L Thompson   case CEED_EVAL_INTERP:
103d1d35e2fSjeremylt     if (size != num_comp)
104e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
105e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
106e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components",
107d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
108d1d35e2fSjeremylt                        num_comp);
109e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
110e15f9bd0SJeremy L Thompson     break;
111e15f9bd0SJeremy L Thompson   case CEED_EVAL_GRAD:
112d1d35e2fSjeremylt     if (size != num_comp * dim)
113e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
114e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
115d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s in %d dimensions: "
116d1d35e2fSjeremylt                        "ElemRestriction/Basis has %d components",
117d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim,
118d1d35e2fSjeremylt                        num_comp);
119e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
120e15f9bd0SJeremy L Thompson     break;
121e15f9bd0SJeremy L Thompson   case CEED_EVAL_WEIGHT:
122d1d35e2fSjeremylt     // No additional checks required
123e15f9bd0SJeremy L Thompson     break;
124e15f9bd0SJeremy L Thompson   case CEED_EVAL_DIV:
125e15f9bd0SJeremy L Thompson     // Not implemented
126e15f9bd0SJeremy L Thompson     break;
127e15f9bd0SJeremy L Thompson   case CEED_EVAL_CURL:
128e15f9bd0SJeremy L Thompson     // Not implemented
129e15f9bd0SJeremy L Thompson     break;
130e15f9bd0SJeremy L Thompson   }
131e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1327a982d89SJeremy L. Thompson }
1337a982d89SJeremy L. Thompson 
1347a982d89SJeremy L. Thompson /**
1357a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
1367a982d89SJeremy L. Thompson 
1377a982d89SJeremy L. Thompson   @param[in] field         Operator field to view
138d1d35e2fSjeremylt   @param[in] qf_field      QFunction field (carries field name)
139d1d35e2fSjeremylt   @param[in] field_number  Number of field being viewed
1404c4400c7SValeria Barra   @param[in] sub           true indicates sub-operator, which increases indentation; false for top-level operator
141d1d35e2fSjeremylt   @param[in] input         true for an input field; false for output field
1427a982d89SJeremy L. Thompson   @param[in] stream        Stream to view to, e.g., stdout
1437a982d89SJeremy L. Thompson 
1447a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1457a982d89SJeremy L. Thompson 
1467a982d89SJeremy L. Thompson   @ref Utility
1477a982d89SJeremy L. Thompson **/
1487a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
149d1d35e2fSjeremylt                                  CeedQFunctionField qf_field,
150d1d35e2fSjeremylt                                  CeedInt field_number, bool sub, bool input,
1517a982d89SJeremy L. Thompson                                  FILE *stream) {
1527a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
153d1d35e2fSjeremylt   const char *in_out = input ? "Input" : "Output";
1547a982d89SJeremy L. Thompson 
1557a982d89SJeremy L. Thompson   fprintf(stream, "%s    %s Field [%d]:\n"
1567a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
157d1d35e2fSjeremylt           pre, in_out, field_number, pre, qf_field->field_name);
1587a982d89SJeremy L. Thompson 
1597a982d89SJeremy L. Thompson   if (field->basis == CEED_BASIS_COLLOCATED)
1607a982d89SJeremy L. Thompson     fprintf(stream, "%s      Collocated basis\n", pre);
1617a982d89SJeremy L. Thompson 
1627a982d89SJeremy L. Thompson   if (field->vec == CEED_VECTOR_ACTIVE)
1637a982d89SJeremy L. Thompson     fprintf(stream, "%s      Active vector\n", pre);
1647a982d89SJeremy L. Thompson   else if (field->vec == CEED_VECTOR_NONE)
1657a982d89SJeremy L. Thompson     fprintf(stream, "%s      No vector\n", pre);
166e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1677a982d89SJeremy L. Thompson }
1687a982d89SJeremy L. Thompson 
1697a982d89SJeremy L. Thompson /**
1707a982d89SJeremy L. Thompson   @brief View a single CeedOperator
1717a982d89SJeremy L. Thompson 
1727a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
1737a982d89SJeremy L. Thompson   @param[in] sub     Boolean flag for sub-operator
1747a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
1757a982d89SJeremy L. Thompson 
1767a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
1777a982d89SJeremy L. Thompson 
1787a982d89SJeremy L. Thompson   @ref Utility
1797a982d89SJeremy L. Thompson **/
1807a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
1817a982d89SJeremy L. Thompson   int ierr;
1827a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
1837a982d89SJeremy L. Thompson 
18478464608Sjeremylt   CeedInt total_fields = 0;
18578464608Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr);
1867a982d89SJeremy L. Thompson 
18778464608Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, total_fields,
18878464608Sjeremylt           total_fields>1 ? "s" : "");
1897a982d89SJeremy L. Thompson 
190d1d35e2fSjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->num_input_fields,
191d1d35e2fSjeremylt           op->qf->num_input_fields>1 ? "s" : "");
192d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
193d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i],
1947a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
1957a982d89SJeremy L. Thompson   }
1967a982d89SJeremy L. Thompson 
197d1d35e2fSjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->num_output_fields,
198d1d35e2fSjeremylt           op->qf->num_output_fields>1 ? "s" : "");
199d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
200d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i],
2017a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
2027a982d89SJeremy L. Thompson   }
203e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2047a982d89SJeremy L. Thompson }
2057a982d89SJeremy L. Thompson 
206d99fa3c5SJeremy L Thompson /**
207eaf62fffSJeremy L Thompson   @brief Find the active vector basis for a CeedOperator
208eaf62fffSJeremy L Thompson 
209eaf62fffSJeremy L Thompson   @param[in] op             CeedOperator to find active basis for
210eaf62fffSJeremy L Thompson   @param[out] active_basis  Basis for active input vector
211eaf62fffSJeremy L Thompson 
212eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
213eaf62fffSJeremy L Thompson 
214eaf62fffSJeremy L Thompson   @ ref Developer
215eaf62fffSJeremy L Thompson **/
216eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
217eaf62fffSJeremy L Thompson   *active_basis = NULL;
218eaf62fffSJeremy L Thompson   for (int i = 0; i < op->qf->num_input_fields; i++)
219eaf62fffSJeremy L Thompson     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
220eaf62fffSJeremy L Thompson       *active_basis = op->input_fields[i]->basis;
221eaf62fffSJeremy L Thompson       break;
222eaf62fffSJeremy L Thompson     }
223eaf62fffSJeremy L Thompson 
224eaf62fffSJeremy L Thompson   if (!*active_basis) {
225eaf62fffSJeremy L Thompson     // LCOV_EXCL_START
226eaf62fffSJeremy L Thompson     int ierr;
227eaf62fffSJeremy L Thompson     Ceed ceed;
228eaf62fffSJeremy L Thompson     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
229eaf62fffSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
230eaf62fffSJeremy L Thompson                      "No active CeedBasis found");
231eaf62fffSJeremy L Thompson     // LCOV_EXCL_STOP
232eaf62fffSJeremy L Thompson   }
233eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
234eaf62fffSJeremy L Thompson }
235eaf62fffSJeremy L Thompson 
236eaf62fffSJeremy L Thompson /**
237e2f04181SAndrew T. Barker   @brief Find the active vector ElemRestriction for a CeedOperator
238e2f04181SAndrew T. Barker 
239e2f04181SAndrew T. Barker   @param[in] op            CeedOperator to find active basis for
240d1d35e2fSjeremylt   @param[out] active_rstr  ElemRestriction for active input vector
241e2f04181SAndrew T. Barker 
242e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
243e2f04181SAndrew T. Barker 
244e2f04181SAndrew T. Barker   @ref Utility
245e2f04181SAndrew T. Barker **/
246eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op,
247d1d35e2fSjeremylt     CeedElemRestriction *active_rstr) {
248d1d35e2fSjeremylt   *active_rstr = NULL;
249d1d35e2fSjeremylt   for (int i = 0; i < op->qf->num_input_fields; i++)
250d1d35e2fSjeremylt     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
251d1d35e2fSjeremylt       *active_rstr = op->input_fields[i]->elem_restr;
252e2f04181SAndrew T. Barker       break;
253e2f04181SAndrew T. Barker     }
254e2f04181SAndrew T. Barker 
255d1d35e2fSjeremylt   if (!*active_rstr) {
256e2f04181SAndrew T. Barker     // LCOV_EXCL_START
257e2f04181SAndrew T. Barker     int ierr;
258e2f04181SAndrew T. Barker     Ceed ceed;
259e2f04181SAndrew T. Barker     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
260e2f04181SAndrew T. Barker     return CeedError(ceed, CEED_ERROR_INCOMPLETE,
261eaf62fffSJeremy L Thompson                      "No active CeedElemRestriction found");
262e2f04181SAndrew T. Barker     // LCOV_EXCL_STOP
263e2f04181SAndrew T. Barker   }
264e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
265e2f04181SAndrew T. Barker }
266e2f04181SAndrew T. Barker 
267*d8dd9a91SJeremy L Thompson /**
268*d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field value of the specified type.
269*d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
270*d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
271*d8dd9a91SJeremy L Thompson            A non-zero error code is returned for single operators
272*d8dd9a91SJeremy L Thompson            that do not have a matching field of the same type or composite
273*d8dd9a91SJeremy L Thompson            operators that do not have any field of a matching type.
274*d8dd9a91SJeremy L Thompson 
275*d8dd9a91SJeremy L Thompson   @param op         CeedOperator
276*d8dd9a91SJeremy L Thompson   @param field_name Name of field to set
277*d8dd9a91SJeremy L Thompson   @param field_type Type of field to set
278*d8dd9a91SJeremy L Thompson   @param value      Value to set
279*d8dd9a91SJeremy L Thompson 
280*d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
281*d8dd9a91SJeremy L Thompson 
282*d8dd9a91SJeremy L Thompson   @ref User
283*d8dd9a91SJeremy L Thompson **/
284*d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op,
285*d8dd9a91SJeremy L Thompson     const char *field_name, CeedContextFieldType field_type, void *value) {
286*d8dd9a91SJeremy L Thompson   int ierr;
287*d8dd9a91SJeremy L Thompson   bool is_set = false, is_composite = false;
288*d8dd9a91SJeremy L Thompson 
289*d8dd9a91SJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
290*d8dd9a91SJeremy L Thompson 
291*d8dd9a91SJeremy L Thompson   if (is_composite) {
292*d8dd9a91SJeremy L Thompson     CeedInt num_sub;
293*d8dd9a91SJeremy L Thompson     CeedOperator *sub_operators;
294*d8dd9a91SJeremy L Thompson 
295*d8dd9a91SJeremy L Thompson     ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr);
296*d8dd9a91SJeremy L Thompson     ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
297*d8dd9a91SJeremy L Thompson 
298*d8dd9a91SJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
299*d8dd9a91SJeremy L Thompson       // Try every sub-operator, ok if some sub-operators do not have field
300*d8dd9a91SJeremy L Thompson       if (sub_operators[i]->qf->ctx) {
301*d8dd9a91SJeremy L Thompson         bool is_set_i = false;
302*d8dd9a91SJeremy L Thompson         ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx, field_name,
303*d8dd9a91SJeremy L Thompson                                               field_type, &is_set_i, value);
304*d8dd9a91SJeremy L Thompson         CeedChk(ierr);
305*d8dd9a91SJeremy L Thompson         is_set = is_set || is_set_i;
306*d8dd9a91SJeremy L Thompson       }
307*d8dd9a91SJeremy L Thompson     }
308*d8dd9a91SJeremy L Thompson   } else {
309*d8dd9a91SJeremy L Thompson     if (!op->qf->ctx)
310*d8dd9a91SJeremy L Thompson       // LCOV_EXCL_START
311*d8dd9a91SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
312*d8dd9a91SJeremy L Thompson                        "QFunction does not have context data");
313*d8dd9a91SJeremy L Thompson     // LCOV_EXCL_STOP
314*d8dd9a91SJeremy L Thompson 
315*d8dd9a91SJeremy L Thompson     ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_name,
316*d8dd9a91SJeremy L Thompson                                           field_type, &is_set, value); CeedChk(ierr);
317*d8dd9a91SJeremy L Thompson   }
318*d8dd9a91SJeremy L Thompson 
319*d8dd9a91SJeremy L Thompson   if (!is_set)
320*d8dd9a91SJeremy L Thompson     // LCOV_EXCL_START
321*d8dd9a91SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
322*d8dd9a91SJeremy L Thompson                      "QFunctionContext field with name \"%s\" not registered",
323*d8dd9a91SJeremy L Thompson                      field_name);
324*d8dd9a91SJeremy L Thompson   // LCOV_EXCL_STOP
325*d8dd9a91SJeremy L Thompson 
326*d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
327*d8dd9a91SJeremy L Thompson }
328*d8dd9a91SJeremy L Thompson 
3297a982d89SJeremy L. Thompson /// @}
3307a982d89SJeremy L. Thompson 
3317a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3327a982d89SJeremy L. Thompson /// CeedOperator Backend API
3337a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3347a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
3357a982d89SJeremy L. Thompson /// @{
3367a982d89SJeremy L. Thompson 
3377a982d89SJeremy L. Thompson /**
3387a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
3397a982d89SJeremy L. Thompson 
3407a982d89SJeremy L. Thompson   @param op             CeedOperator
341d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
3427a982d89SJeremy L. Thompson 
3437a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3447a982d89SJeremy L. Thompson 
3457a982d89SJeremy L. Thompson   @ref Backend
3467a982d89SJeremy L. Thompson **/
3477a982d89SJeremy L. Thompson 
348d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
349f04ea552SJeremy L Thompson   if (op->is_composite)
3507a982d89SJeremy L. Thompson     // LCOV_EXCL_START
351e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
352e15f9bd0SJeremy L Thompson                      "Not defined for composite operators");
3537a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3547a982d89SJeremy L. Thompson 
355d1d35e2fSjeremylt   *num_args = op->num_fields;
356e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3577a982d89SJeremy L. Thompson }
3587a982d89SJeremy L. Thompson 
3597a982d89SJeremy L. Thompson /**
3607a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
3617a982d89SJeremy L. Thompson 
3627a982d89SJeremy L. Thompson   @param op                  CeedOperator
363d1d35e2fSjeremylt   @param[out] is_setup_done  Variable to store setup status
3647a982d89SJeremy L. Thompson 
3657a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3667a982d89SJeremy L. Thompson 
3677a982d89SJeremy L. Thompson   @ref Backend
3687a982d89SJeremy L. Thompson **/
3697a982d89SJeremy L. Thompson 
370d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
371f04ea552SJeremy L Thompson   *is_setup_done = op->is_backend_setup;
372e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3737a982d89SJeremy L. Thompson }
3747a982d89SJeremy L. Thompson 
3757a982d89SJeremy L. Thompson /**
3767a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
3777a982d89SJeremy L. Thompson 
3787a982d89SJeremy L. Thompson   @param op       CeedOperator
3797a982d89SJeremy L. Thompson   @param[out] qf  Variable to store QFunction
3807a982d89SJeremy L. Thompson 
3817a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3827a982d89SJeremy L. Thompson 
3837a982d89SJeremy L. Thompson   @ref Backend
3847a982d89SJeremy L. Thompson **/
3857a982d89SJeremy L. Thompson 
3867a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
387f04ea552SJeremy L Thompson   if (op->is_composite)
3887a982d89SJeremy L. Thompson     // LCOV_EXCL_START
389e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
390e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
3917a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3927a982d89SJeremy L. Thompson 
3937a982d89SJeremy L. Thompson   *qf = op->qf;
394e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3957a982d89SJeremy L. Thompson }
3967a982d89SJeremy L. Thompson 
3977a982d89SJeremy L. Thompson /**
398c04a41a7SJeremy L Thompson   @brief Get a boolean value indicating if the CeedOperator is composite
399c04a41a7SJeremy L Thompson 
400c04a41a7SJeremy L Thompson   @param op                 CeedOperator
401d1d35e2fSjeremylt   @param[out] is_composite  Variable to store composite status
402c04a41a7SJeremy L Thompson 
403c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
404c04a41a7SJeremy L Thompson 
405c04a41a7SJeremy L Thompson   @ref Backend
406c04a41a7SJeremy L Thompson **/
407c04a41a7SJeremy L Thompson 
408d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
409f04ea552SJeremy L Thompson   *is_composite = op->is_composite;
410e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
411c04a41a7SJeremy L Thompson }
412c04a41a7SJeremy L Thompson 
413c04a41a7SJeremy L Thompson /**
414d1d35e2fSjeremylt   @brief Get the number of sub_operators associated with a CeedOperator
4157a982d89SJeremy L. Thompson 
4167a982d89SJeremy L. Thompson   @param op                     CeedOperator
417d1d35e2fSjeremylt   @param[out] num_suboperators  Variable to store number of sub_operators
4187a982d89SJeremy L. Thompson 
4197a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4207a982d89SJeremy L. Thompson 
4217a982d89SJeremy L. Thompson   @ref Backend
4227a982d89SJeremy L. Thompson **/
4237a982d89SJeremy L. Thompson 
424d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
425f04ea552SJeremy L Thompson   if (!op->is_composite)
4267a982d89SJeremy L. Thompson     // LCOV_EXCL_START
427e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4287a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4297a982d89SJeremy L. Thompson 
430d1d35e2fSjeremylt   *num_suboperators = op->num_suboperators;
431e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4327a982d89SJeremy L. Thompson }
4337a982d89SJeremy L. Thompson 
4347a982d89SJeremy L. Thompson /**
435d1d35e2fSjeremylt   @brief Get the list of sub_operators associated with a CeedOperator
4367a982d89SJeremy L. Thompson 
4377a982d89SJeremy L. Thompson   @param op                  CeedOperator
438d1d35e2fSjeremylt   @param[out] sub_operators  Variable to store list of sub_operators
4397a982d89SJeremy L. Thompson 
4407a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4417a982d89SJeremy L. Thompson 
4427a982d89SJeremy L. Thompson   @ref Backend
4437a982d89SJeremy L. Thompson **/
4447a982d89SJeremy L. Thompson 
445d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) {
446f04ea552SJeremy L Thompson   if (!op->is_composite)
4477a982d89SJeremy L. Thompson     // LCOV_EXCL_START
448e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4497a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4507a982d89SJeremy L. Thompson 
451d1d35e2fSjeremylt   *sub_operators = op->sub_operators;
452e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4537a982d89SJeremy L. Thompson }
4547a982d89SJeremy L. Thompson 
4557a982d89SJeremy L. Thompson /**
4567a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
4577a982d89SJeremy L. Thompson 
4587a982d89SJeremy L. Thompson   @param op         CeedOperator
4597a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
4607a982d89SJeremy L. Thompson 
4617a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4627a982d89SJeremy L. Thompson 
4637a982d89SJeremy L. Thompson   @ref Backend
4647a982d89SJeremy L. Thompson **/
4657a982d89SJeremy L. Thompson 
466777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
467777ff853SJeremy L Thompson   *(void **)data = op->data;
468e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4697a982d89SJeremy L. Thompson }
4707a982d89SJeremy L. Thompson 
4717a982d89SJeremy L. Thompson /**
4727a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
4737a982d89SJeremy L. Thompson 
4747a982d89SJeremy L. Thompson   @param[out] op  CeedOperator
4757a982d89SJeremy L. Thompson   @param data     Data to set
4767a982d89SJeremy L. Thompson 
4777a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4787a982d89SJeremy L. Thompson 
4797a982d89SJeremy L. Thompson   @ref Backend
4807a982d89SJeremy L. Thompson **/
4817a982d89SJeremy L. Thompson 
482777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
483777ff853SJeremy L Thompson   op->data = data;
484e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4857a982d89SJeremy L. Thompson }
4867a982d89SJeremy L. Thompson 
4877a982d89SJeremy L. Thompson /**
48834359f16Sjeremylt   @brief Increment the reference counter for a CeedOperator
48934359f16Sjeremylt 
49034359f16Sjeremylt   @param op  CeedOperator to increment the reference counter
49134359f16Sjeremylt 
49234359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
49334359f16Sjeremylt 
49434359f16Sjeremylt   @ref Backend
49534359f16Sjeremylt **/
4969560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
49734359f16Sjeremylt   op->ref_count++;
49834359f16Sjeremylt   return CEED_ERROR_SUCCESS;
49934359f16Sjeremylt }
50034359f16Sjeremylt 
50134359f16Sjeremylt /**
5027a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
5037a982d89SJeremy L. Thompson 
5047a982d89SJeremy L. Thompson   @param op  CeedOperator
5057a982d89SJeremy L. Thompson 
5067a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5077a982d89SJeremy L. Thompson 
5087a982d89SJeremy L. Thompson   @ref Backend
5097a982d89SJeremy L. Thompson **/
5107a982d89SJeremy L. Thompson 
5117a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
512f04ea552SJeremy L Thompson   op->is_backend_setup = true;
513e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5147a982d89SJeremy L. Thompson }
5157a982d89SJeremy L. Thompson 
5167a982d89SJeremy L. Thompson /// @}
5177a982d89SJeremy L. Thompson 
5187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5197a982d89SJeremy L. Thompson /// CeedOperator Public API
5207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5217a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
522dfdf5a53Sjeremylt /// @{
523d7b241e6Sjeremylt 
524d7b241e6Sjeremylt /**
5250219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
5260219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
5270219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
528d7b241e6Sjeremylt 
529b11c1e72Sjeremylt   @param ceed     A Ceed object where the CeedOperator will be created
530d7b241e6Sjeremylt   @param qf       QFunction defining the action of the operator at quadrature points
53134138859Sjeremylt   @param dqf      QFunction defining the action of the Jacobian of @a qf (or
5324cc79fe7SJed Brown                     @ref CEED_QFUNCTION_NONE)
533d7b241e6Sjeremylt   @param dqfT     QFunction defining the action of the transpose of the Jacobian
5344cc79fe7SJed Brown                     of @a qf (or @ref CEED_QFUNCTION_NONE)
535b11c1e72Sjeremylt   @param[out] op  Address of the variable where the newly created
536b11c1e72Sjeremylt                     CeedOperator will be stored
537b11c1e72Sjeremylt 
538b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
539dfdf5a53Sjeremylt 
5407a982d89SJeremy L. Thompson   @ref User
541d7b241e6Sjeremylt  */
542d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
543d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
544d7b241e6Sjeremylt   int ierr;
545d7b241e6Sjeremylt 
5465fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
5475fe0d4faSjeremylt     Ceed delegate;
548aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
5495fe0d4faSjeremylt 
5505fe0d4faSjeremylt     if (!delegate)
551c042f62fSJeremy L Thompson       // LCOV_EXCL_START
552e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
553e15f9bd0SJeremy L Thompson                        "Backend does not support OperatorCreate");
554c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5555fe0d4faSjeremylt 
5565fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
557e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5585fe0d4faSjeremylt   }
5595fe0d4faSjeremylt 
560b3b7035fSJeremy L Thompson   if (!qf || qf == CEED_QFUNCTION_NONE)
561b3b7035fSJeremy L Thompson     // LCOV_EXCL_START
562e15f9bd0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
563e15f9bd0SJeremy L Thompson                      "Operator must have a valid QFunction.");
564b3b7035fSJeremy L Thompson   // LCOV_EXCL_STOP
565d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
566d7b241e6Sjeremylt   (*op)->ceed = ceed;
5679560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
568d1d35e2fSjeremylt   (*op)->ref_count = 1;
569d7b241e6Sjeremylt   (*op)->qf = qf;
5709560d06aSjeremylt   ierr = CeedQFunctionReference(qf); CeedChk(ierr);
571442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
572d7b241e6Sjeremylt     (*op)->dqf = dqf;
5739560d06aSjeremylt     ierr = CeedQFunctionReference(dqf); CeedChk(ierr);
574442e7f0bSjeremylt   }
575442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
576d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
5779560d06aSjeremylt     ierr = CeedQFunctionReference(dqfT); CeedChk(ierr);
578442e7f0bSjeremylt   }
579bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr);
580bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr);
581d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
582e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
583d7b241e6Sjeremylt }
584d7b241e6Sjeremylt 
585d7b241e6Sjeremylt /**
58652d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
58752d6035fSJeremy L Thompson 
58852d6035fSJeremy L Thompson   @param ceed     A Ceed object where the CeedOperator will be created
58952d6035fSJeremy L Thompson   @param[out] op  Address of the variable where the newly created
59052d6035fSJeremy L Thompson                     Composite CeedOperator will be stored
59152d6035fSJeremy L Thompson 
59252d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
59352d6035fSJeremy L Thompson 
5947a982d89SJeremy L. Thompson   @ref User
59552d6035fSJeremy L Thompson  */
59652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
59752d6035fSJeremy L Thompson   int ierr;
59852d6035fSJeremy L Thompson 
59952d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
60052d6035fSJeremy L Thompson     Ceed delegate;
601aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
60252d6035fSJeremy L Thompson 
603250756a7Sjeremylt     if (delegate) {
60452d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
605e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
60652d6035fSJeremy L Thompson     }
607250756a7Sjeremylt   }
60852d6035fSJeremy L Thompson 
60952d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
61052d6035fSJeremy L Thompson   (*op)->ceed = ceed;
6119560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
612f04ea552SJeremy L Thompson   (*op)->is_composite = true;
613bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr);
614250756a7Sjeremylt 
615250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
61652d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
617250756a7Sjeremylt   }
618e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
61952d6035fSJeremy L Thompson }
62052d6035fSJeremy L Thompson 
62152d6035fSJeremy L Thompson /**
6229560d06aSjeremylt   @brief Copy the pointer to a CeedOperator. Both pointers should
6239560d06aSjeremylt            be destroyed with `CeedOperatorDestroy()`;
6249560d06aSjeremylt            Note: If `*op_copy` is non-NULL, then it is assumed that
6259560d06aSjeremylt            `*op_copy` is a pointer to a CeedOperator. This
6269560d06aSjeremylt            CeedOperator will be destroyed if `*op_copy` is the only
6279560d06aSjeremylt            reference to this CeedOperator.
6289560d06aSjeremylt 
6299560d06aSjeremylt   @param op            CeedOperator to copy reference to
6309560d06aSjeremylt   @param[out] op_copy  Variable to store copied reference
6319560d06aSjeremylt 
6329560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6339560d06aSjeremylt 
6349560d06aSjeremylt   @ref User
6359560d06aSjeremylt **/
6369560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
6379560d06aSjeremylt   int ierr;
6389560d06aSjeremylt 
6399560d06aSjeremylt   ierr = CeedOperatorReference(op); CeedChk(ierr);
6409560d06aSjeremylt   ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr);
6419560d06aSjeremylt   *op_copy = op;
6429560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6439560d06aSjeremylt }
6449560d06aSjeremylt 
6459560d06aSjeremylt /**
646b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
647d7b241e6Sjeremylt 
648d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
649d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
650d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
651d7b241e6Sjeremylt 
652d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
653d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
654d7b241e6Sjeremylt   input and at most one active output.
655d7b241e6Sjeremylt 
6568c91a0c9SJeremy L Thompson   @param op          CeedOperator on which to provide the field
657d1d35e2fSjeremylt   @param field_name  Name of the field (to be matched with the name used by
6588795c945Sjeremylt                        CeedQFunction)
659b11c1e72Sjeremylt   @param r           CeedElemRestriction
6604cc79fe7SJed Brown   @param b           CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED
661b11c1e72Sjeremylt                        if collocated with quadrature points
6624cc79fe7SJed Brown   @param v           CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE
6634cc79fe7SJed Brown                        if field is active or @ref CEED_VECTOR_NONE if using
6644cc79fe7SJed Brown                        @ref CEED_EVAL_WEIGHT in the QFunction
665b11c1e72Sjeremylt 
666b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
667dfdf5a53Sjeremylt 
6687a982d89SJeremy L. Thompson   @ref User
669b11c1e72Sjeremylt **/
670d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name,
671a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
672d7b241e6Sjeremylt   int ierr;
673f04ea552SJeremy L Thompson   if (op->is_composite)
674c042f62fSJeremy L Thompson     // LCOV_EXCL_START
675e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
676e15f9bd0SJeremy L Thompson                      "Cannot add field to composite operator.");
677c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
678f04ea552SJeremy L Thompson   if (op->is_immutable)
679f04ea552SJeremy L Thompson     // LCOV_EXCL_START
680f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
681f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
682f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
6838b067b84SJed Brown   if (!r)
684c042f62fSJeremy L Thompson     // LCOV_EXCL_START
685e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
686c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
687d1d35e2fSjeremylt                      field_name);
688c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6898b067b84SJed Brown   if (!b)
690c042f62fSJeremy L Thompson     // LCOV_EXCL_START
691e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
692e15f9bd0SJeremy L Thompson                      "Basis b for field \"%s\" must be non-NULL.",
693d1d35e2fSjeremylt                      field_name);
694c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6958b067b84SJed Brown   if (!v)
696c042f62fSJeremy L Thompson     // LCOV_EXCL_START
697e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
698e15f9bd0SJeremy L Thompson                      "Vector v for field \"%s\" must be non-NULL.",
699d1d35e2fSjeremylt                      field_name);
700c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
70152d6035fSJeremy L Thompson 
702d1d35e2fSjeremylt   CeedInt num_elem;
703d1d35e2fSjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr);
704d1d35e2fSjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction &&
705d1d35e2fSjeremylt       op->num_elem != num_elem)
706c042f62fSJeremy L Thompson     // LCOV_EXCL_START
707e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_DIMENSION,
7081d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
709d1d35e2fSjeremylt                      "%d elements", num_elem, op->num_elem);
710c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
711d7b241e6Sjeremylt 
71278464608Sjeremylt   CeedInt num_qpts = 0;
713e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
714d1d35e2fSjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr);
715d1d35e2fSjeremylt     if (op->num_qpts && op->num_qpts != num_qpts)
716c042f62fSJeremy L Thompson       // LCOV_EXCL_START
717e15f9bd0SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_DIMENSION,
718e15f9bd0SJeremy L Thompson                        "Basis with %d quadrature points "
719d1d35e2fSjeremylt                        "incompatible with prior %d points", num_qpts,
720d1d35e2fSjeremylt                        op->num_qpts);
721c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
722d7b241e6Sjeremylt   }
723d1d35e2fSjeremylt   CeedQFunctionField qf_field;
724d1d35e2fSjeremylt   CeedOperatorField *op_field;
725d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
726d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) {
727d1d35e2fSjeremylt       qf_field = op->qf->input_fields[i];
728d1d35e2fSjeremylt       op_field = &op->input_fields[i];
729d7b241e6Sjeremylt       goto found;
730d7b241e6Sjeremylt     }
731d7b241e6Sjeremylt   }
732d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
733d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) {
734d1d35e2fSjeremylt       qf_field = op->qf->output_fields[i];
735d1d35e2fSjeremylt       op_field = &op->output_fields[i];
736d7b241e6Sjeremylt       goto found;
737d7b241e6Sjeremylt     }
738d7b241e6Sjeremylt   }
739c042f62fSJeremy L Thompson   // LCOV_EXCL_START
740e15f9bd0SJeremy L Thompson   return CeedError(op->ceed, CEED_ERROR_INCOMPLETE,
741e15f9bd0SJeremy L Thompson                    "QFunction has no knowledge of field '%s'",
742d1d35e2fSjeremylt                    field_name);
743c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
744d7b241e6Sjeremylt found:
745d1d35e2fSjeremylt   ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr);
746d1d35e2fSjeremylt   ierr = CeedCalloc(1, op_field); CeedChk(ierr);
747e15f9bd0SJeremy L Thompson 
748d1d35e2fSjeremylt   (*op_field)->vec = v;
749e15f9bd0SJeremy L Thompson   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) {
7509560d06aSjeremylt     ierr = CeedVectorReference(v); CeedChk(ierr);
751e15f9bd0SJeremy L Thompson   }
752e15f9bd0SJeremy L Thompson 
753d1d35e2fSjeremylt   (*op_field)->elem_restr = r;
7549560d06aSjeremylt   ierr = CeedElemRestrictionReference(r); CeedChk(ierr);
755e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
756d1d35e2fSjeremylt     op->num_elem = num_elem;
757d1d35e2fSjeremylt     op->has_restriction = true; // Restriction set, but num_elem may be 0
758e15f9bd0SJeremy L Thompson   }
759d99fa3c5SJeremy L Thompson 
760d1d35e2fSjeremylt   (*op_field)->basis = b;
761e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
762cd4dfc48Sjeremylt     if (!op->num_qpts) {
763cd4dfc48Sjeremylt       ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr);
764cd4dfc48Sjeremylt     }
7659560d06aSjeremylt     ierr = CeedBasisReference(b); CeedChk(ierr);
766e15f9bd0SJeremy L Thompson   }
767e15f9bd0SJeremy L Thompson 
768d1d35e2fSjeremylt   op->num_fields += 1;
769f7e22acaSJeremy L Thompson   ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name);
770f7e22acaSJeremy L Thompson   CeedChk(ierr);
771e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
772d7b241e6Sjeremylt }
773d7b241e6Sjeremylt 
774d7b241e6Sjeremylt /**
77543bbe138SJeremy L Thompson   @brief Get the CeedOperatorFields of a CeedOperator
77643bbe138SJeremy L Thompson 
777f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
778f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
779f04ea552SJeremy L Thompson 
78043bbe138SJeremy L Thompson   @param op                      CeedOperator
781f74ec584SJeremy L Thompson   @param[out] num_input_fields   Variable to store number of input fields
78243bbe138SJeremy L Thompson   @param[out] input_fields       Variable to store input_fields
783f74ec584SJeremy L Thompson   @param[out] num_output_fields  Variable to store number of output fields
78443bbe138SJeremy L Thompson   @param[out] output_fields      Variable to store output_fields
78543bbe138SJeremy L Thompson 
78643bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
78743bbe138SJeremy L Thompson 
788e9b533fbSJeremy L Thompson   @ref Advanced
78943bbe138SJeremy L Thompson **/
79043bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields,
79143bbe138SJeremy L Thompson                           CeedOperatorField **input_fields,
79243bbe138SJeremy L Thompson                           CeedInt *num_output_fields,
79343bbe138SJeremy L Thompson                           CeedOperatorField **output_fields) {
794f04ea552SJeremy L Thompson   int ierr;
795f04ea552SJeremy L Thompson 
796f04ea552SJeremy L Thompson   if (op->is_composite)
79743bbe138SJeremy L Thompson     // LCOV_EXCL_START
79843bbe138SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
79943bbe138SJeremy L Thompson                      "Not defined for composite operator");
80043bbe138SJeremy L Thompson   // LCOV_EXCL_STOP
801f04ea552SJeremy L Thompson   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
80243bbe138SJeremy L Thompson 
80343bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = op->qf->num_input_fields;
80443bbe138SJeremy L Thompson   if (input_fields) *input_fields = op->input_fields;
80543bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = op->qf->num_output_fields;
80643bbe138SJeremy L Thompson   if (output_fields) *output_fields = op->output_fields;
80743bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
80843bbe138SJeremy L Thompson }
80943bbe138SJeremy L Thompson 
81043bbe138SJeremy L Thompson /**
81128567f8fSJeremy L Thompson   @brief Get the name of a CeedOperatorField
81228567f8fSJeremy L Thompson 
81328567f8fSJeremy L Thompson   @param op_field         CeedOperatorField
81428567f8fSJeremy L Thompson   @param[out] field_name  Variable to store the field name
81528567f8fSJeremy L Thompson 
81628567f8fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
81728567f8fSJeremy L Thompson 
818e9b533fbSJeremy L Thompson   @ref Advanced
81928567f8fSJeremy L Thompson **/
82028567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) {
82128567f8fSJeremy L Thompson   *field_name = (char *)op_field->field_name;
82228567f8fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
82328567f8fSJeremy L Thompson }
82428567f8fSJeremy L Thompson 
82528567f8fSJeremy L Thompson /**
82643bbe138SJeremy L Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
82743bbe138SJeremy L Thompson 
82843bbe138SJeremy L Thompson   @param op_field   CeedOperatorField
82943bbe138SJeremy L Thompson   @param[out] rstr  Variable to store CeedElemRestriction
83043bbe138SJeremy L Thompson 
83143bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83243bbe138SJeremy L Thompson 
833e9b533fbSJeremy L Thompson   @ref Advanced
83443bbe138SJeremy L Thompson **/
83543bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,
83643bbe138SJeremy L Thompson                                         CeedElemRestriction *rstr) {
83743bbe138SJeremy L Thompson   *rstr = op_field->elem_restr;
83843bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
83943bbe138SJeremy L Thompson }
84043bbe138SJeremy L Thompson 
84143bbe138SJeremy L Thompson /**
84243bbe138SJeremy L Thompson   @brief Get the CeedBasis of a CeedOperatorField
84343bbe138SJeremy L Thompson 
84443bbe138SJeremy L Thompson   @param op_field    CeedOperatorField
84543bbe138SJeremy L Thompson   @param[out] basis  Variable to store CeedBasis
84643bbe138SJeremy L Thompson 
84743bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
84843bbe138SJeremy L Thompson 
849e9b533fbSJeremy L Thompson   @ref Advanced
85043bbe138SJeremy L Thompson **/
85143bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
85243bbe138SJeremy L Thompson   *basis = op_field->basis;
85343bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
85443bbe138SJeremy L Thompson }
85543bbe138SJeremy L Thompson 
85643bbe138SJeremy L Thompson /**
85743bbe138SJeremy L Thompson   @brief Get the CeedVector of a CeedOperatorField
85843bbe138SJeremy L Thompson 
85943bbe138SJeremy L Thompson   @param op_field  CeedOperatorField
86043bbe138SJeremy L Thompson   @param[out] vec  Variable to store CeedVector
86143bbe138SJeremy L Thompson 
86243bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
86343bbe138SJeremy L Thompson 
864e9b533fbSJeremy L Thompson   @ref Advanced
86543bbe138SJeremy L Thompson **/
86643bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
86743bbe138SJeremy L Thompson   *vec = op_field->vec;
86843bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
86943bbe138SJeremy L Thompson }
87043bbe138SJeremy L Thompson 
87143bbe138SJeremy L Thompson /**
87252d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
873288c0443SJeremy L Thompson 
874d1d35e2fSjeremylt   @param[out] composite_op  Composite CeedOperator
875d1d35e2fSjeremylt   @param      sub_op        Sub-operator CeedOperator
87652d6035fSJeremy L Thompson 
87752d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
87852d6035fSJeremy L Thompson 
8797a982d89SJeremy L. Thompson   @ref User
88052d6035fSJeremy L Thompson  */
881d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op,
882d1d35e2fSjeremylt                                 CeedOperator sub_op) {
88334359f16Sjeremylt   int ierr;
88434359f16Sjeremylt 
885f04ea552SJeremy L Thompson   if (!composite_op->is_composite)
886c042f62fSJeremy L Thompson     // LCOV_EXCL_START
887d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_MINOR,
888e2f04181SAndrew T. Barker                      "CeedOperator is not a composite operator");
889c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
89052d6035fSJeremy L Thompson 
891d1d35e2fSjeremylt   if (composite_op->num_suboperators == CEED_COMPOSITE_MAX)
892c042f62fSJeremy L Thompson     // LCOV_EXCL_START
893d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED,
894d1d35e2fSjeremylt                      "Cannot add additional sub_operators");
895c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
896f04ea552SJeremy L Thompson   if (composite_op->is_immutable)
897f04ea552SJeremy L Thompson     // LCOV_EXCL_START
898f04ea552SJeremy L Thompson     return CeedError(composite_op->ceed, CEED_ERROR_MAJOR,
899f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
900f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
90152d6035fSJeremy L Thompson 
902d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
9039560d06aSjeremylt   ierr = CeedOperatorReference(sub_op); CeedChk(ierr);
904d1d35e2fSjeremylt   composite_op->num_suboperators++;
905e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
90652d6035fSJeremy L Thompson }
90752d6035fSJeremy L Thompson 
90852d6035fSJeremy L Thompson /**
9094db537f9SJeremy L Thompson   @brief Check if a CeedOperator is ready to be used.
9104db537f9SJeremy L Thompson 
9114db537f9SJeremy L Thompson   @param[in] op  CeedOperator to check
9124db537f9SJeremy L Thompson 
9134db537f9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9144db537f9SJeremy L Thompson 
9154db537f9SJeremy L Thompson   @ref User
9164db537f9SJeremy L Thompson **/
9174db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
9184db537f9SJeremy L Thompson   int ierr;
9194db537f9SJeremy L Thompson   Ceed ceed;
9204db537f9SJeremy L Thompson   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
9214db537f9SJeremy L Thompson 
9224db537f9SJeremy L Thompson   if (op->is_interface_setup)
9234db537f9SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9244db537f9SJeremy L Thompson 
9254db537f9SJeremy L Thompson   CeedQFunction qf = op->qf;
9264db537f9SJeremy L Thompson   if (op->is_composite) {
9274db537f9SJeremy L Thompson     if (!op->num_suboperators)
9284db537f9SJeremy L Thompson       // LCOV_EXCL_START
9294db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set");
9304db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9314db537f9SJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
9324db537f9SJeremy L Thompson       ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr);
9334db537f9SJeremy L Thompson     }
9344db537f9SJeremy L Thompson   } else {
9354db537f9SJeremy L Thompson     if (op->num_fields == 0)
9364db537f9SJeremy L Thompson       // LCOV_EXCL_START
9374db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set");
9384db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9394db537f9SJeremy L Thompson     if (op->num_fields < qf->num_input_fields + qf->num_output_fields)
9404db537f9SJeremy L Thompson       // LCOV_EXCL_START
9414db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set");
9424db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9434db537f9SJeremy L Thompson     if (!op->has_restriction)
9444db537f9SJeremy L Thompson       // LCOV_EXCL_START
9454db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
9464db537f9SJeremy L Thompson                        "At least one restriction required");
9474db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9484db537f9SJeremy L Thompson     if (op->num_qpts == 0)
9494db537f9SJeremy L Thompson       // LCOV_EXCL_START
9504db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
9514db537f9SJeremy L Thompson                        "At least one non-collocated basis is required "
9524db537f9SJeremy L Thompson                        "or the number of quadrature points must be set");
9534db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9544db537f9SJeremy L Thompson   }
9554db537f9SJeremy L Thompson 
9564db537f9SJeremy L Thompson   // Flag as immutable and ready
9574db537f9SJeremy L Thompson   op->is_interface_setup = true;
9584db537f9SJeremy L Thompson   if (op->qf && op->qf != CEED_QFUNCTION_NONE)
9594db537f9SJeremy L Thompson     // LCOV_EXCL_START
9604db537f9SJeremy L Thompson     op->qf->is_immutable = true;
9614db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
9624db537f9SJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE)
9634db537f9SJeremy L Thompson     // LCOV_EXCL_START
9644db537f9SJeremy L Thompson     op->dqf->is_immutable = true;
9654db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
9664db537f9SJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE)
9674db537f9SJeremy L Thompson     // LCOV_EXCL_START
9684db537f9SJeremy L Thompson     op->dqfT->is_immutable = true;
9694db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
9704db537f9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9714db537f9SJeremy L Thompson }
9724db537f9SJeremy L Thompson 
9734db537f9SJeremy L Thompson /**
974cd4dfc48Sjeremylt   @brief Set the number of quadrature points associated with a CeedOperator.
975cd4dfc48Sjeremylt            This should be used when creating a CeedOperator where every
976cd4dfc48Sjeremylt            field has a collocated basis. This function cannot be used for
977cd4dfc48Sjeremylt            composite CeedOperators.
978cd4dfc48Sjeremylt 
979cd4dfc48Sjeremylt   @param op        CeedOperator
980cd4dfc48Sjeremylt   @param num_qpts  Number of quadrature points to set
981cd4dfc48Sjeremylt 
982cd4dfc48Sjeremylt   @return An error code: 0 - success, otherwise - failure
983cd4dfc48Sjeremylt 
984e9b533fbSJeremy L Thompson   @ref Advanced
985cd4dfc48Sjeremylt **/
986cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) {
987f04ea552SJeremy L Thompson   if (op->is_composite)
988cd4dfc48Sjeremylt     // LCOV_EXCL_START
989cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
990cd4dfc48Sjeremylt                      "Not defined for composite operator");
991cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
992cd4dfc48Sjeremylt   if (op->num_qpts)
993cd4dfc48Sjeremylt     // LCOV_EXCL_START
994cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
995cd4dfc48Sjeremylt                      "Number of quadrature points already defined");
996cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
997f04ea552SJeremy L Thompson   if (op->is_immutable)
998f04ea552SJeremy L Thompson     // LCOV_EXCL_START
999f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
1000f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
1001f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
1002cd4dfc48Sjeremylt 
1003cd4dfc48Sjeremylt   op->num_qpts = num_qpts;
1004cd4dfc48Sjeremylt   return CEED_ERROR_SUCCESS;
1005cd4dfc48Sjeremylt }
1006cd4dfc48Sjeremylt 
1007cd4dfc48Sjeremylt /**
10087a982d89SJeremy L. Thompson   @brief View a CeedOperator
10097a982d89SJeremy L. Thompson 
10107a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
10117a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
10127a982d89SJeremy L. Thompson 
10137a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
10147a982d89SJeremy L. Thompson 
10157a982d89SJeremy L. Thompson   @ref User
10167a982d89SJeremy L. Thompson **/
10177a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
10187a982d89SJeremy L. Thompson   int ierr;
10197a982d89SJeremy L. Thompson 
1020f04ea552SJeremy L Thompson   if (op->is_composite) {
10217a982d89SJeremy L. Thompson     fprintf(stream, "Composite CeedOperator\n");
10227a982d89SJeremy L. Thompson 
1023d1d35e2fSjeremylt     for (CeedInt i=0; i<op->num_suboperators; i++) {
10247a982d89SJeremy L. Thompson       fprintf(stream, "  SubOperator [%d]:\n", i);
1025d1d35e2fSjeremylt       ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream);
10267a982d89SJeremy L. Thompson       CeedChk(ierr);
10277a982d89SJeremy L. Thompson     }
10287a982d89SJeremy L. Thompson   } else {
10297a982d89SJeremy L. Thompson     fprintf(stream, "CeedOperator\n");
10307a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
10317a982d89SJeremy L. Thompson   }
1032e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10337a982d89SJeremy L. Thompson }
10343bd813ffSjeremylt 
10353bd813ffSjeremylt /**
1036b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedOperator
1037b7c9bbdaSJeremy L Thompson 
1038b7c9bbdaSJeremy L Thompson   @param op         CeedOperator
1039b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
1040b7c9bbdaSJeremy L Thompson 
1041b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1042b7c9bbdaSJeremy L Thompson 
1043b7c9bbdaSJeremy L Thompson   @ref Advanced
1044b7c9bbdaSJeremy L Thompson **/
1045b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
1046b7c9bbdaSJeremy L Thompson   *ceed = op->ceed;
1047b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1048b7c9bbdaSJeremy L Thompson }
1049b7c9bbdaSJeremy L Thompson 
1050b7c9bbdaSJeremy L Thompson /**
1051b7c9bbdaSJeremy L Thompson   @brief Get the number of elements associated with a CeedOperator
1052b7c9bbdaSJeremy L Thompson 
1053b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1054b7c9bbdaSJeremy L Thompson   @param[out] num_elem  Variable to store number of elements
1055b7c9bbdaSJeremy L Thompson 
1056b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1057b7c9bbdaSJeremy L Thompson 
1058b7c9bbdaSJeremy L Thompson   @ref Advanced
1059b7c9bbdaSJeremy L Thompson **/
1060b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
1061b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1062b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1063b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1064b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1065b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1066b7c9bbdaSJeremy L Thompson 
1067b7c9bbdaSJeremy L Thompson   *num_elem = op->num_elem;
1068b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1069b7c9bbdaSJeremy L Thompson }
1070b7c9bbdaSJeremy L Thompson 
1071b7c9bbdaSJeremy L Thompson /**
1072b7c9bbdaSJeremy L Thompson   @brief Get the number of quadrature points associated with a CeedOperator
1073b7c9bbdaSJeremy L Thompson 
1074b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1075b7c9bbdaSJeremy L Thompson   @param[out] num_qpts  Variable to store vector number of quadrature points
1076b7c9bbdaSJeremy L Thompson 
1077b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1078b7c9bbdaSJeremy L Thompson 
1079b7c9bbdaSJeremy L Thompson   @ref Advanced
1080b7c9bbdaSJeremy L Thompson **/
1081b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
1082b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1083b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1084b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1085b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1086b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1087b7c9bbdaSJeremy L Thompson 
1088b7c9bbdaSJeremy L Thompson   *num_qpts = op->num_qpts;
1089b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1090b7c9bbdaSJeremy L Thompson }
1091b7c9bbdaSJeremy L Thompson 
1092b7c9bbdaSJeremy L Thompson /**
1093*d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value.
1094*d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
1095*d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
1096*d8dd9a91SJeremy L Thompson 
1097*d8dd9a91SJeremy L Thompson   @param op         CeedOperator
1098*d8dd9a91SJeremy L Thompson   @param field_name Name of field to register
1099*d8dd9a91SJeremy L Thompson   @param value      Value to set
1100*d8dd9a91SJeremy L Thompson 
1101*d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1102*d8dd9a91SJeremy L Thompson 
1103*d8dd9a91SJeremy L Thompson   @ref User
1104*d8dd9a91SJeremy L Thompson **/
1105*d8dd9a91SJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op, const char *field_name,
1106*d8dd9a91SJeremy L Thompson                                  double value) {
1107*d8dd9a91SJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_name, CEED_CONTEXT_FIELD_DOUBLE,
1108*d8dd9a91SJeremy L Thompson                                        &value);
1109*d8dd9a91SJeremy L Thompson }
1110*d8dd9a91SJeremy L Thompson 
1111*d8dd9a91SJeremy L Thompson /**
1112*d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value.
1113*d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
1114*d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
1115*d8dd9a91SJeremy L Thompson 
1116*d8dd9a91SJeremy L Thompson   @param op         CeedOperator
1117*d8dd9a91SJeremy L Thompson   @param field_name Name of field to set
1118*d8dd9a91SJeremy L Thompson   @param value      Value to set
1119*d8dd9a91SJeremy L Thompson 
1120*d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1121*d8dd9a91SJeremy L Thompson 
1122*d8dd9a91SJeremy L Thompson   @ref User
1123*d8dd9a91SJeremy L Thompson **/
1124*d8dd9a91SJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op, const char *field_name,
1125*d8dd9a91SJeremy L Thompson                                 int value) {
1126*d8dd9a91SJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_name, CEED_CONTEXT_FIELD_INT32,
1127*d8dd9a91SJeremy L Thompson                                        &value);
1128*d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1129*d8dd9a91SJeremy L Thompson }
1130*d8dd9a91SJeremy L Thompson 
1131*d8dd9a91SJeremy L Thompson /**
11323bd813ffSjeremylt   @brief Apply CeedOperator to a vector
1133d7b241e6Sjeremylt 
1134d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
1135d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1136d7b241e6Sjeremylt   CeedOperatorSetField().
1137d7b241e6Sjeremylt 
1138f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
1139f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
1140f04ea552SJeremy L Thompson 
1141d7b241e6Sjeremylt   @param op        CeedOperator to apply
11424cc79fe7SJed Brown   @param[in] in    CeedVector containing input state or @ref CEED_VECTOR_NONE if
114334138859Sjeremylt                      there are no active inputs
1144b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
11454cc79fe7SJed Brown                      distinct from @a in) or @ref CEED_VECTOR_NONE if there are no
114634138859Sjeremylt                      active outputs
1147d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
11484cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1149b11c1e72Sjeremylt 
1150b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1151dfdf5a53Sjeremylt 
11527a982d89SJeremy L. Thompson   @ref User
1153b11c1e72Sjeremylt **/
1154692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
1155692c2638Sjeremylt                       CeedRequest *request) {
1156d7b241e6Sjeremylt   int ierr;
1157e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1158d7b241e6Sjeremylt 
1159d1d35e2fSjeremylt   if (op->num_elem)  {
1160250756a7Sjeremylt     // Standard Operator
1161cae8b89aSjeremylt     if (op->Apply) {
1162250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
1163cae8b89aSjeremylt     } else {
1164cae8b89aSjeremylt       // Zero all output vectors
1165250756a7Sjeremylt       CeedQFunction qf = op->qf;
1166d1d35e2fSjeremylt       for (CeedInt i=0; i<qf->num_output_fields; i++) {
1167d1d35e2fSjeremylt         CeedVector vec = op->output_fields[i]->vec;
1168cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
1169cae8b89aSjeremylt           vec = out;
1170cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
1171cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1172cae8b89aSjeremylt         }
1173cae8b89aSjeremylt       }
1174250756a7Sjeremylt       // Apply
1175250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1176250756a7Sjeremylt     }
1177f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1178250756a7Sjeremylt     // Composite Operator
1179250756a7Sjeremylt     if (op->ApplyComposite) {
1180250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
1181250756a7Sjeremylt     } else {
1182d1d35e2fSjeremylt       CeedInt num_suboperators;
1183d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1184d1d35e2fSjeremylt       CeedOperator *sub_operators;
1185d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1186250756a7Sjeremylt 
1187250756a7Sjeremylt       // Zero all output vectors
1188250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
1189cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
1190cae8b89aSjeremylt       }
1191d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1192d1d35e2fSjeremylt         for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) {
1193d1d35e2fSjeremylt           CeedVector vec = sub_operators[i]->output_fields[j]->vec;
1194250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
1195250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1196250756a7Sjeremylt           }
1197250756a7Sjeremylt         }
1198250756a7Sjeremylt       }
1199250756a7Sjeremylt       // Apply
1200d1d35e2fSjeremylt       for (CeedInt i=0; i<op->num_suboperators; i++) {
1201d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request);
1202cae8b89aSjeremylt         CeedChk(ierr);
1203cae8b89aSjeremylt       }
1204cae8b89aSjeremylt     }
1205250756a7Sjeremylt   }
1206e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1207cae8b89aSjeremylt }
1208cae8b89aSjeremylt 
1209cae8b89aSjeremylt /**
1210cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
1211cae8b89aSjeremylt 
1212cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
1213cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1214cae8b89aSjeremylt   CeedOperatorSetField().
1215cae8b89aSjeremylt 
1216cae8b89aSjeremylt   @param op        CeedOperator to apply
1217cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
1218cae8b89aSjeremylt                      active inputs
1219cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
1220cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
1221cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
12224cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1223cae8b89aSjeremylt 
1224cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
1225cae8b89aSjeremylt 
12267a982d89SJeremy L. Thompson   @ref User
1227cae8b89aSjeremylt **/
1228cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
1229cae8b89aSjeremylt                          CeedRequest *request) {
1230cae8b89aSjeremylt   int ierr;
1231e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1232cae8b89aSjeremylt 
1233d1d35e2fSjeremylt   if (op->num_elem)  {
1234250756a7Sjeremylt     // Standard Operator
1235250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1236f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1237250756a7Sjeremylt     // Composite Operator
1238250756a7Sjeremylt     if (op->ApplyAddComposite) {
1239250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
1240cae8b89aSjeremylt     } else {
1241d1d35e2fSjeremylt       CeedInt num_suboperators;
1242d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1243d1d35e2fSjeremylt       CeedOperator *sub_operators;
1244d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1245250756a7Sjeremylt 
1246d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1247d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request);
1248cae8b89aSjeremylt         CeedChk(ierr);
12491d7d2407SJeremy L Thompson       }
1250250756a7Sjeremylt     }
1251250756a7Sjeremylt   }
1252e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1253d7b241e6Sjeremylt }
1254d7b241e6Sjeremylt 
1255d7b241e6Sjeremylt /**
1256b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1257d7b241e6Sjeremylt 
1258d7b241e6Sjeremylt   @param op  CeedOperator to destroy
1259b11c1e72Sjeremylt 
1260b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1261dfdf5a53Sjeremylt 
12627a982d89SJeremy L. Thompson   @ref User
1263b11c1e72Sjeremylt **/
1264d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1265d7b241e6Sjeremylt   int ierr;
1266d7b241e6Sjeremylt 
1267d1d35e2fSjeremylt   if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS;
1268d7b241e6Sjeremylt   if ((*op)->Destroy) {
1269d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1270d7b241e6Sjeremylt   }
1271fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1272fe2413ffSjeremylt   // Free fields
1273d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1274d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
1275d1d35e2fSjeremylt       if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) {
1276d1d35e2fSjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr);
127771352a93Sjeremylt         CeedChk(ierr);
127815910d16Sjeremylt       }
1279d1d35e2fSjeremylt       if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1280d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr);
128171352a93Sjeremylt       }
1282d1d35e2fSjeremylt       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1283d1d35e2fSjeremylt           (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) {
1284d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr);
128571352a93Sjeremylt       }
1286d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr);
1287d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr);
1288fe2413ffSjeremylt     }
1289d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1290d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
1291d1d35e2fSjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr);
129271352a93Sjeremylt       CeedChk(ierr);
1293d1d35e2fSjeremylt       if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1294d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr);
129571352a93Sjeremylt       }
1296d1d35e2fSjeremylt       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1297d1d35e2fSjeremylt           (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) {
1298d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr);
129971352a93Sjeremylt       }
1300d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr);
1301d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr);
1302fe2413ffSjeremylt     }
1303d1d35e2fSjeremylt   // Destroy sub_operators
1304d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_suboperators; i++)
1305d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
1306d1d35e2fSjeremylt       ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr);
130752d6035fSJeremy L Thompson     }
1308d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1309d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1310d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1311fe2413ffSjeremylt 
13125107b09fSJeremy L Thompson   // Destroy fallback
1313d1d35e2fSjeremylt   if ((*op)->op_fallback) {
1314d1d35e2fSjeremylt     ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr);
1315d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr);
131670a7ffb3SJeremy L Thompson     ierr = CeedVectorDestroy(&(*op)->op_fallback->qf_assembled); CeedChk(ierr);
131770a7ffb3SJeremy L Thompson     ierr = CeedElemRestrictionDestroy(&(*op)->op_fallback->qf_assembled_rstr);
131870a7ffb3SJeremy L Thompson     CeedChk(ierr);
1319d1d35e2fSjeremylt     ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr);
1320d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr);
13215107b09fSJeremy L Thompson   }
13225107b09fSJeremy L Thompson 
132370a7ffb3SJeremy L Thompson   // Destroy QF assembly cache
132470a7ffb3SJeremy L Thompson   ierr = CeedVectorDestroy(&(*op)->qf_assembled); CeedChk(ierr);
132570a7ffb3SJeremy L Thompson   ierr = CeedElemRestrictionDestroy(&(*op)->qf_assembled_rstr); CeedChk(ierr);
132670a7ffb3SJeremy L Thompson 
1327d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr);
1328d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr);
1329d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr);
1330d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1331e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1332d7b241e6Sjeremylt }
1333d7b241e6Sjeremylt 
1334d7b241e6Sjeremylt /// @}
1335