xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
6*3d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
8ec3da8bcSJed Brown #include <ceed/ceed.h>
9ec3da8bcSJed Brown #include <ceed/backend.h>
103d576824SJeremy L Thompson #include <ceed-impl.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 /**
25e15f9bd0SJeremy L Thompson   @brief Check if a CeedOperator Field matches the QFunction Field
26e15f9bd0SJeremy L Thompson 
27e15f9bd0SJeremy L Thompson   @param[in] ceed      Ceed object for error handling
28d1d35e2fSjeremylt   @param[in] qf_field  QFunction Field matching Operator Field
29e15f9bd0SJeremy L Thompson   @param[in] r         Operator Field ElemRestriction
30e15f9bd0SJeremy L Thompson   @param[in] b         Operator Field Basis
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 **/
36d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field,
37e15f9bd0SJeremy L Thompson                                   CeedElemRestriction r, CeedBasis b) {
38e15f9bd0SJeremy L Thompson   int ierr;
39d1d35e2fSjeremylt   CeedEvalMode eval_mode = qf_field->eval_mode;
40d1d35e2fSjeremylt   CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size;
41e15f9bd0SJeremy L Thompson   // Restriction
42e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
43d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_WEIGHT) {
44e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
45e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
46e1e9e29dSJed Brown                        "CEED_ELEMRESTRICTION_NONE should be used "
47e15f9bd0SJeremy L Thompson                        "for a field with eval mode CEED_EVAL_WEIGHT");
48e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
49e15f9bd0SJeremy L Thompson     }
50d1d35e2fSjeremylt     ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp);
5178464608Sjeremylt     CeedChk(ierr);
52e1e9e29dSJed Brown   }
53d1d35e2fSjeremylt   if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) {
54e1e9e29dSJed Brown     // LCOV_EXCL_START
55e1e9e29dSJed Brown     return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
56e1e9e29dSJed Brown                      "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT "
57e1e9e29dSJed Brown                      "must be used together.");
58e1e9e29dSJed Brown     // LCOV_EXCL_STOP
59e1e9e29dSJed Brown   }
60e15f9bd0SJeremy L Thompson   // Basis
61e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
62d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_NONE)
638229195eSjeremylt       // LCOV_EXCL_START
64e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
65d1d35e2fSjeremylt                        "Field '%s' configured with CEED_EVAL_NONE must "
66d1d35e2fSjeremylt                        "be used with CEED_BASIS_COLLOCATED",
678229195eSjeremylt                        // LCOV_EXCL_STOP
68d1d35e2fSjeremylt                        qf_field->field_name);
69e15f9bd0SJeremy L Thompson     ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr);
70d1d35e2fSjeremylt     ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr);
71d1d35e2fSjeremylt     if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) {
72e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
73e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
74d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s: ElemRestriction "
75d1d35e2fSjeremylt                        "has %d components, but Basis has %d components",
76d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
77d1d35e2fSjeremylt                        restr_num_comp,
78d1d35e2fSjeremylt                        num_comp);
79e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
80e15f9bd0SJeremy L Thompson     }
81e15f9bd0SJeremy L Thompson   }
82e15f9bd0SJeremy L Thompson   // Field size
83d1d35e2fSjeremylt   switch(eval_mode) {
84e15f9bd0SJeremy L Thompson   case CEED_EVAL_NONE:
85d1d35e2fSjeremylt     if (size != restr_num_comp)
86e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
87e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
88e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components",
89d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
90d1d35e2fSjeremylt                        restr_num_comp);
91e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
92e15f9bd0SJeremy L Thompson     break;
93e15f9bd0SJeremy L Thompson   case CEED_EVAL_INTERP:
94d1d35e2fSjeremylt     if (size != 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/Basis has %d components",
98d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
99d1d35e2fSjeremylt                        num_comp);
100e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
101e15f9bd0SJeremy L Thompson     break;
102e15f9bd0SJeremy L Thompson   case CEED_EVAL_GRAD:
103d1d35e2fSjeremylt     if (size != num_comp * dim)
104e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
105e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
106d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s in %d dimensions: "
107d1d35e2fSjeremylt                        "ElemRestriction/Basis has %d components",
108d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim,
109d1d35e2fSjeremylt                        num_comp);
110e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
111e15f9bd0SJeremy L Thompson     break;
112e15f9bd0SJeremy L Thompson   case CEED_EVAL_WEIGHT:
113d1d35e2fSjeremylt     // No additional checks required
114e15f9bd0SJeremy L Thompson     break;
115e15f9bd0SJeremy L Thompson   case CEED_EVAL_DIV:
116e15f9bd0SJeremy L Thompson     // Not implemented
117e15f9bd0SJeremy L Thompson     break;
118e15f9bd0SJeremy L Thompson   case CEED_EVAL_CURL:
119e15f9bd0SJeremy L Thompson     // Not implemented
120e15f9bd0SJeremy L Thompson     break;
121e15f9bd0SJeremy L Thompson   }
122e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1237a982d89SJeremy L. Thompson }
1247a982d89SJeremy L. Thompson 
1257a982d89SJeremy L. Thompson /**
1267a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
1277a982d89SJeremy L. Thompson 
1287a982d89SJeremy L. Thompson   @param[in] field         Operator field to view
129d1d35e2fSjeremylt   @param[in] qf_field      QFunction field (carries field name)
130d1d35e2fSjeremylt   @param[in] field_number  Number of field being viewed
1314c4400c7SValeria Barra   @param[in] sub           true indicates sub-operator, which increases indentation; false for top-level operator
132d1d35e2fSjeremylt   @param[in] input         true for an input field; false for output field
1337a982d89SJeremy L. Thompson   @param[in] stream        Stream to view to, e.g., stdout
1347a982d89SJeremy L. Thompson 
1357a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1367a982d89SJeremy L. Thompson 
1377a982d89SJeremy L. Thompson   @ref Utility
1387a982d89SJeremy L. Thompson **/
1397a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
140d1d35e2fSjeremylt                                  CeedQFunctionField qf_field,
141d1d35e2fSjeremylt                                  CeedInt field_number, bool sub, bool input,
1427a982d89SJeremy L. Thompson                                  FILE *stream) {
1437a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
144d1d35e2fSjeremylt   const char *in_out = input ? "Input" : "Output";
1457a982d89SJeremy L. Thompson 
1467a982d89SJeremy L. Thompson   fprintf(stream, "%s    %s Field [%d]:\n"
1477a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
148d1d35e2fSjeremylt           pre, in_out, field_number, pre, qf_field->field_name);
1497a982d89SJeremy L. Thompson 
1507a982d89SJeremy L. Thompson   if (field->basis == CEED_BASIS_COLLOCATED)
1517a982d89SJeremy L. Thompson     fprintf(stream, "%s      Collocated basis\n", pre);
1527a982d89SJeremy L. Thompson 
1537a982d89SJeremy L. Thompson   if (field->vec == CEED_VECTOR_ACTIVE)
1547a982d89SJeremy L. Thompson     fprintf(stream, "%s      Active vector\n", pre);
1557a982d89SJeremy L. Thompson   else if (field->vec == CEED_VECTOR_NONE)
1567a982d89SJeremy L. Thompson     fprintf(stream, "%s      No vector\n", pre);
157e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1587a982d89SJeremy L. Thompson }
1597a982d89SJeremy L. Thompson 
1607a982d89SJeremy L. Thompson /**
1617a982d89SJeremy L. Thompson   @brief View a single CeedOperator
1627a982d89SJeremy L. Thompson 
1637a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
1647a982d89SJeremy L. Thompson   @param[in] sub     Boolean flag for sub-operator
1657a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
1667a982d89SJeremy L. Thompson 
1677a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
1687a982d89SJeremy L. Thompson 
1697a982d89SJeremy L. Thompson   @ref Utility
1707a982d89SJeremy L. Thompson **/
1717a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
1727a982d89SJeremy L. Thompson   int ierr;
1737a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
1747a982d89SJeremy L. Thompson 
17578464608Sjeremylt   CeedInt total_fields = 0;
17678464608Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr);
1777a982d89SJeremy L. Thompson 
17878464608Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, total_fields,
17978464608Sjeremylt           total_fields>1 ? "s" : "");
1807a982d89SJeremy L. Thompson 
181d1d35e2fSjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->num_input_fields,
182d1d35e2fSjeremylt           op->qf->num_input_fields>1 ? "s" : "");
183d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
184d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i],
1857a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
1867a982d89SJeremy L. Thompson   }
1877a982d89SJeremy L. Thompson 
188d1d35e2fSjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->num_output_fields,
189d1d35e2fSjeremylt           op->qf->num_output_fields>1 ? "s" : "");
190d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
191d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i],
1927a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
1937a982d89SJeremy L. Thompson   }
194e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1957a982d89SJeremy L. Thompson }
1967a982d89SJeremy L. Thompson 
197d99fa3c5SJeremy L Thompson /**
198eaf62fffSJeremy L Thompson   @brief Find the active vector basis for a CeedOperator
199eaf62fffSJeremy L Thompson 
200eaf62fffSJeremy L Thompson   @param[in] op             CeedOperator to find active basis for
201eaf62fffSJeremy L Thompson   @param[out] active_basis  Basis for active input vector
202eaf62fffSJeremy L Thompson 
203eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
204eaf62fffSJeremy L Thompson 
205eaf62fffSJeremy L Thompson   @ ref Developer
206eaf62fffSJeremy L Thompson **/
207eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
208eaf62fffSJeremy L Thompson   *active_basis = NULL;
209eaf62fffSJeremy L Thompson   for (int i = 0; i < op->qf->num_input_fields; i++)
210eaf62fffSJeremy L Thompson     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
211eaf62fffSJeremy L Thompson       *active_basis = op->input_fields[i]->basis;
212eaf62fffSJeremy L Thompson       break;
213eaf62fffSJeremy L Thompson     }
214eaf62fffSJeremy L Thompson 
215eaf62fffSJeremy L Thompson   if (!*active_basis) {
216eaf62fffSJeremy L Thompson     // LCOV_EXCL_START
217eaf62fffSJeremy L Thompson     int ierr;
218eaf62fffSJeremy L Thompson     Ceed ceed;
219eaf62fffSJeremy L Thompson     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
220eaf62fffSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
221eaf62fffSJeremy L Thompson                      "No active CeedBasis found");
222eaf62fffSJeremy L Thompson     // LCOV_EXCL_STOP
223eaf62fffSJeremy L Thompson   }
224eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
225eaf62fffSJeremy L Thompson }
226eaf62fffSJeremy L Thompson 
227eaf62fffSJeremy L Thompson /**
228e2f04181SAndrew T. Barker   @brief Find the active vector ElemRestriction for a CeedOperator
229e2f04181SAndrew T. Barker 
230e2f04181SAndrew T. Barker   @param[in] op            CeedOperator to find active basis for
231d1d35e2fSjeremylt   @param[out] active_rstr  ElemRestriction for active input vector
232e2f04181SAndrew T. Barker 
233e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
234e2f04181SAndrew T. Barker 
235e2f04181SAndrew T. Barker   @ref Utility
236e2f04181SAndrew T. Barker **/
237eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op,
238d1d35e2fSjeremylt     CeedElemRestriction *active_rstr) {
239d1d35e2fSjeremylt   *active_rstr = NULL;
240d1d35e2fSjeremylt   for (int i = 0; i < op->qf->num_input_fields; i++)
241d1d35e2fSjeremylt     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
242d1d35e2fSjeremylt       *active_rstr = op->input_fields[i]->elem_restr;
243e2f04181SAndrew T. Barker       break;
244e2f04181SAndrew T. Barker     }
245e2f04181SAndrew T. Barker 
246d1d35e2fSjeremylt   if (!*active_rstr) {
247e2f04181SAndrew T. Barker     // LCOV_EXCL_START
248e2f04181SAndrew T. Barker     int ierr;
249e2f04181SAndrew T. Barker     Ceed ceed;
250e2f04181SAndrew T. Barker     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
251e2f04181SAndrew T. Barker     return CeedError(ceed, CEED_ERROR_INCOMPLETE,
252eaf62fffSJeremy L Thompson                      "No active CeedElemRestriction found");
253e2f04181SAndrew T. Barker     // LCOV_EXCL_STOP
254e2f04181SAndrew T. Barker   }
255e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
256e2f04181SAndrew T. Barker }
257e2f04181SAndrew T. Barker 
258d8dd9a91SJeremy L Thompson /**
259d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field value of the specified type.
260d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
261d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
262d8dd9a91SJeremy L Thompson            A non-zero error code is returned for single operators
263d8dd9a91SJeremy L Thompson            that do not have a matching field of the same type or composite
264d8dd9a91SJeremy L Thompson            operators that do not have any field of a matching type.
265d8dd9a91SJeremy L Thompson 
266d8dd9a91SJeremy L Thompson   @param op          CeedOperator
2673668ca4bSJeremy L Thompson   @param field_label Label of field to set
268d8dd9a91SJeremy L Thompson   @param field_type  Type of field to set
269d8dd9a91SJeremy L Thompson   @param value       Value to set
270d8dd9a91SJeremy L Thompson 
271d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
272d8dd9a91SJeremy L Thompson 
273d8dd9a91SJeremy L Thompson   @ref User
274d8dd9a91SJeremy L Thompson **/
275d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op,
2763668ca4bSJeremy L Thompson     CeedContextFieldLabel field_label, CeedContextFieldType field_type,
2773668ca4bSJeremy L Thompson     void *value) {
278d8dd9a91SJeremy L Thompson   int ierr;
279d8dd9a91SJeremy L Thompson 
2803668ca4bSJeremy L Thompson   if (!field_label)
2813668ca4bSJeremy L Thompson     // LCOV_EXCL_START
2823668ca4bSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
2833668ca4bSJeremy L Thompson                      "Invalid field label");
2843668ca4bSJeremy L Thompson   // LCOV_EXCL_STOP
2853668ca4bSJeremy L Thompson 
2863668ca4bSJeremy L Thompson   bool is_composite = false;
287d8dd9a91SJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
288d8dd9a91SJeremy L Thompson   if (is_composite) {
289d8dd9a91SJeremy L Thompson     CeedInt num_sub;
290d8dd9a91SJeremy L Thompson     CeedOperator *sub_operators;
291d8dd9a91SJeremy L Thompson 
292d8dd9a91SJeremy L Thompson     ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr);
293d8dd9a91SJeremy L Thompson     ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
2943668ca4bSJeremy L Thompson     if (num_sub != field_label->num_sub_labels)
2953668ca4bSJeremy L Thompson       // LCOV_EXCL_START
2963668ca4bSJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
2973668ca4bSJeremy L Thompson                        "ContextLabel does not correspond to composite operator.\n"
2983668ca4bSJeremy L Thompson                        "Use CeedOperatorGetContextFieldLabel().");
2993668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
300d8dd9a91SJeremy L Thompson 
301d8dd9a91SJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
302d8dd9a91SJeremy L Thompson       // Try every sub-operator, ok if some sub-operators do not have field
3033668ca4bSJeremy L Thompson       if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) {
3043668ca4bSJeremy L Thompson         ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx,
3053668ca4bSJeremy L Thompson                                               field_label->sub_labels[i],
3063668ca4bSJeremy L Thompson                                               field_type, value); CeedChk(ierr);
307d8dd9a91SJeremy L Thompson       }
308d8dd9a91SJeremy L Thompson     }
309d8dd9a91SJeremy L Thompson   } else {
310d8dd9a91SJeremy L Thompson     if (!op->qf->ctx)
311d8dd9a91SJeremy L Thompson       // LCOV_EXCL_START
312d8dd9a91SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
313d8dd9a91SJeremy L Thompson                        "QFunction does not have context data");
314d8dd9a91SJeremy L Thompson     // LCOV_EXCL_STOP
315d8dd9a91SJeremy L Thompson 
3163668ca4bSJeremy L Thompson     ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label,
3173668ca4bSJeremy L Thompson                                           field_type, value); CeedChk(ierr);
318d8dd9a91SJeremy L Thompson   }
319d8dd9a91SJeremy L Thompson 
320d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
321d8dd9a91SJeremy L Thompson }
322d8dd9a91SJeremy L Thompson 
3237a982d89SJeremy L. Thompson /// @}
3247a982d89SJeremy L. Thompson 
3257a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3267a982d89SJeremy L. Thompson /// CeedOperator Backend API
3277a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3287a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
3297a982d89SJeremy L. Thompson /// @{
3307a982d89SJeremy L. Thompson 
3317a982d89SJeremy L. Thompson /**
3327a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
3337a982d89SJeremy L. Thompson 
3347a982d89SJeremy L. Thompson   @param op             CeedOperator
335d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
3367a982d89SJeremy L. Thompson 
3377a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3387a982d89SJeremy L. Thompson 
3397a982d89SJeremy L. Thompson   @ref Backend
3407a982d89SJeremy L. Thompson **/
3417a982d89SJeremy L. Thompson 
342d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
343f04ea552SJeremy L Thompson   if (op->is_composite)
3447a982d89SJeremy L. Thompson     // LCOV_EXCL_START
345e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
346e15f9bd0SJeremy L Thompson                      "Not defined for composite operators");
3477a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3487a982d89SJeremy L. Thompson 
349d1d35e2fSjeremylt   *num_args = op->num_fields;
350e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3517a982d89SJeremy L. Thompson }
3527a982d89SJeremy L. Thompson 
3537a982d89SJeremy L. Thompson /**
3547a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
3557a982d89SJeremy L. Thompson 
3567a982d89SJeremy L. Thompson   @param op                  CeedOperator
357d1d35e2fSjeremylt   @param[out] is_setup_done  Variable to store setup status
3587a982d89SJeremy L. Thompson 
3597a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3607a982d89SJeremy L. Thompson 
3617a982d89SJeremy L. Thompson   @ref Backend
3627a982d89SJeremy L. Thompson **/
3637a982d89SJeremy L. Thompson 
364d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
365f04ea552SJeremy L Thompson   *is_setup_done = op->is_backend_setup;
366e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3677a982d89SJeremy L. Thompson }
3687a982d89SJeremy L. Thompson 
3697a982d89SJeremy L. Thompson /**
3707a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
3717a982d89SJeremy L. Thompson 
3727a982d89SJeremy L. Thompson   @param op       CeedOperator
3737a982d89SJeremy L. Thompson   @param[out] qf  Variable to store QFunction
3747a982d89SJeremy L. Thompson 
3757a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3767a982d89SJeremy L. Thompson 
3777a982d89SJeremy L. Thompson   @ref Backend
3787a982d89SJeremy L. Thompson **/
3797a982d89SJeremy L. Thompson 
3807a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
381f04ea552SJeremy L Thompson   if (op->is_composite)
3827a982d89SJeremy L. Thompson     // LCOV_EXCL_START
383e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
384e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
3857a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3867a982d89SJeremy L. Thompson 
3877a982d89SJeremy L. Thompson   *qf = op->qf;
388e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3897a982d89SJeremy L. Thompson }
3907a982d89SJeremy L. Thompson 
3917a982d89SJeremy L. Thompson /**
392c04a41a7SJeremy L Thompson   @brief Get a boolean value indicating if the CeedOperator is composite
393c04a41a7SJeremy L Thompson 
394c04a41a7SJeremy L Thompson   @param op                 CeedOperator
395d1d35e2fSjeremylt   @param[out] is_composite  Variable to store composite status
396c04a41a7SJeremy L Thompson 
397c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
398c04a41a7SJeremy L Thompson 
399c04a41a7SJeremy L Thompson   @ref Backend
400c04a41a7SJeremy L Thompson **/
401c04a41a7SJeremy L Thompson 
402d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
403f04ea552SJeremy L Thompson   *is_composite = op->is_composite;
404e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
405c04a41a7SJeremy L Thompson }
406c04a41a7SJeremy L Thompson 
407c04a41a7SJeremy L Thompson /**
408d1d35e2fSjeremylt   @brief Get the number of sub_operators associated with a CeedOperator
4097a982d89SJeremy L. Thompson 
4107a982d89SJeremy L. Thompson   @param op                     CeedOperator
411d1d35e2fSjeremylt   @param[out] num_suboperators  Variable to store number of sub_operators
4127a982d89SJeremy L. Thompson 
4137a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4147a982d89SJeremy L. Thompson 
4157a982d89SJeremy L. Thompson   @ref Backend
4167a982d89SJeremy L. Thompson **/
4177a982d89SJeremy L. Thompson 
418d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
419f04ea552SJeremy L Thompson   if (!op->is_composite)
4207a982d89SJeremy L. Thompson     // LCOV_EXCL_START
421e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4227a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4237a982d89SJeremy L. Thompson 
424d1d35e2fSjeremylt   *num_suboperators = op->num_suboperators;
425e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4267a982d89SJeremy L. Thompson }
4277a982d89SJeremy L. Thompson 
4287a982d89SJeremy L. Thompson /**
429d1d35e2fSjeremylt   @brief Get the list of sub_operators associated with a CeedOperator
4307a982d89SJeremy L. Thompson 
4317a982d89SJeremy L. Thompson   @param op                  CeedOperator
432d1d35e2fSjeremylt   @param[out] sub_operators  Variable to store list of sub_operators
4337a982d89SJeremy L. Thompson 
4347a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4357a982d89SJeremy L. Thompson 
4367a982d89SJeremy L. Thompson   @ref Backend
4377a982d89SJeremy L. Thompson **/
4387a982d89SJeremy L. Thompson 
439d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) {
440f04ea552SJeremy L Thompson   if (!op->is_composite)
4417a982d89SJeremy L. Thompson     // LCOV_EXCL_START
442e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4437a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4447a982d89SJeremy L. Thompson 
445d1d35e2fSjeremylt   *sub_operators = op->sub_operators;
446e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4477a982d89SJeremy L. Thompson }
4487a982d89SJeremy L. Thompson 
4497a982d89SJeremy L. Thompson /**
4507a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
4517a982d89SJeremy L. Thompson 
4527a982d89SJeremy L. Thompson   @param op         CeedOperator
4537a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
4547a982d89SJeremy L. Thompson 
4557a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4567a982d89SJeremy L. Thompson 
4577a982d89SJeremy L. Thompson   @ref Backend
4587a982d89SJeremy L. Thompson **/
4597a982d89SJeremy L. Thompson 
460777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
461777ff853SJeremy L Thompson   *(void **)data = op->data;
462e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4637a982d89SJeremy L. Thompson }
4647a982d89SJeremy L. Thompson 
4657a982d89SJeremy L. Thompson /**
4667a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
4677a982d89SJeremy L. Thompson 
4687a982d89SJeremy L. Thompson   @param[out] op  CeedOperator
4697a982d89SJeremy L. Thompson   @param data     Data to set
4707a982d89SJeremy L. Thompson 
4717a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4727a982d89SJeremy L. Thompson 
4737a982d89SJeremy L. Thompson   @ref Backend
4747a982d89SJeremy L. Thompson **/
4757a982d89SJeremy L. Thompson 
476777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
477777ff853SJeremy L Thompson   op->data = data;
478e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4797a982d89SJeremy L. Thompson }
4807a982d89SJeremy L. Thompson 
4817a982d89SJeremy L. Thompson /**
48234359f16Sjeremylt   @brief Increment the reference counter for a CeedOperator
48334359f16Sjeremylt 
48434359f16Sjeremylt   @param op  CeedOperator to increment the reference counter
48534359f16Sjeremylt 
48634359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
48734359f16Sjeremylt 
48834359f16Sjeremylt   @ref Backend
48934359f16Sjeremylt **/
4909560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
49134359f16Sjeremylt   op->ref_count++;
49234359f16Sjeremylt   return CEED_ERROR_SUCCESS;
49334359f16Sjeremylt }
49434359f16Sjeremylt 
49534359f16Sjeremylt /**
4967a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
4977a982d89SJeremy L. Thompson 
4987a982d89SJeremy L. Thompson   @param op  CeedOperator
4997a982d89SJeremy L. Thompson 
5007a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5017a982d89SJeremy L. Thompson 
5027a982d89SJeremy L. Thompson   @ref Backend
5037a982d89SJeremy L. Thompson **/
5047a982d89SJeremy L. Thompson 
5057a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
506f04ea552SJeremy L Thompson   op->is_backend_setup = true;
507e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5087a982d89SJeremy L. Thompson }
5097a982d89SJeremy L. Thompson 
5107a982d89SJeremy L. Thompson /// @}
5117a982d89SJeremy L. Thompson 
5127a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5137a982d89SJeremy L. Thompson /// CeedOperator Public API
5147a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5157a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
516dfdf5a53Sjeremylt /// @{
517d7b241e6Sjeremylt 
518d7b241e6Sjeremylt /**
5190219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
5200219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
5210219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
522d7b241e6Sjeremylt 
523b11c1e72Sjeremylt   @param ceed     A Ceed object where the CeedOperator will be created
524d7b241e6Sjeremylt   @param qf       QFunction defining the action of the operator at quadrature points
52534138859Sjeremylt   @param dqf      QFunction defining the action of the Jacobian of @a qf (or
5264cc79fe7SJed Brown                     @ref CEED_QFUNCTION_NONE)
527d7b241e6Sjeremylt   @param dqfT     QFunction defining the action of the transpose of the Jacobian
5284cc79fe7SJed Brown                     of @a qf (or @ref CEED_QFUNCTION_NONE)
529b11c1e72Sjeremylt   @param[out] op  Address of the variable where the newly created
530b11c1e72Sjeremylt                     CeedOperator will be stored
531b11c1e72Sjeremylt 
532b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
533dfdf5a53Sjeremylt 
5347a982d89SJeremy L. Thompson   @ref User
535d7b241e6Sjeremylt  */
536d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
537d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
538d7b241e6Sjeremylt   int ierr;
539d7b241e6Sjeremylt 
5405fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
5415fe0d4faSjeremylt     Ceed delegate;
542aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
5435fe0d4faSjeremylt 
5445fe0d4faSjeremylt     if (!delegate)
545c042f62fSJeremy L Thompson       // LCOV_EXCL_START
546e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
547e15f9bd0SJeremy L Thompson                        "Backend does not support OperatorCreate");
548c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5495fe0d4faSjeremylt 
5505fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
551e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5525fe0d4faSjeremylt   }
5535fe0d4faSjeremylt 
554b3b7035fSJeremy L Thompson   if (!qf || qf == CEED_QFUNCTION_NONE)
555b3b7035fSJeremy L Thompson     // LCOV_EXCL_START
556e15f9bd0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
557e15f9bd0SJeremy L Thompson                      "Operator must have a valid QFunction.");
558b3b7035fSJeremy L Thompson   // LCOV_EXCL_STOP
559d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
560d7b241e6Sjeremylt   (*op)->ceed = ceed;
5619560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
562d1d35e2fSjeremylt   (*op)->ref_count = 1;
563d7b241e6Sjeremylt   (*op)->qf = qf;
5649560d06aSjeremylt   ierr = CeedQFunctionReference(qf); CeedChk(ierr);
565442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
566d7b241e6Sjeremylt     (*op)->dqf = dqf;
5679560d06aSjeremylt     ierr = CeedQFunctionReference(dqf); CeedChk(ierr);
568442e7f0bSjeremylt   }
569442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
570d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
5719560d06aSjeremylt     ierr = CeedQFunctionReference(dqfT); CeedChk(ierr);
572442e7f0bSjeremylt   }
573480fae85SJeremy L Thompson   ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled);
574480fae85SJeremy L Thompson   CeedChk(ierr);
575bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr);
576bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr);
577d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
578e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
579d7b241e6Sjeremylt }
580d7b241e6Sjeremylt 
581d7b241e6Sjeremylt /**
58252d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
58352d6035fSJeremy L Thompson 
58452d6035fSJeremy L Thompson   @param ceed     A Ceed object where the CeedOperator will be created
58552d6035fSJeremy L Thompson   @param[out] op  Address of the variable where the newly created
58652d6035fSJeremy L Thompson                     Composite CeedOperator will be stored
58752d6035fSJeremy L Thompson 
58852d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
58952d6035fSJeremy L Thompson 
5907a982d89SJeremy L. Thompson   @ref User
59152d6035fSJeremy L Thompson  */
59252d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
59352d6035fSJeremy L Thompson   int ierr;
59452d6035fSJeremy L Thompson 
59552d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
59652d6035fSJeremy L Thompson     Ceed delegate;
597aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
59852d6035fSJeremy L Thompson 
599250756a7Sjeremylt     if (delegate) {
60052d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
601e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
60252d6035fSJeremy L Thompson     }
603250756a7Sjeremylt   }
60452d6035fSJeremy L Thompson 
60552d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
60652d6035fSJeremy L Thompson   (*op)->ceed = ceed;
6079560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
608f04ea552SJeremy L Thompson   (*op)->is_composite = true;
609bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr);
610250756a7Sjeremylt 
611250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
61252d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
613250756a7Sjeremylt   }
614e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
61552d6035fSJeremy L Thompson }
61652d6035fSJeremy L Thompson 
61752d6035fSJeremy L Thompson /**
6189560d06aSjeremylt   @brief Copy the pointer to a CeedOperator. Both pointers should
6199560d06aSjeremylt            be destroyed with `CeedOperatorDestroy()`;
6209560d06aSjeremylt            Note: If `*op_copy` is non-NULL, then it is assumed that
6219560d06aSjeremylt            `*op_copy` is a pointer to a CeedOperator. This
6229560d06aSjeremylt            CeedOperator will be destroyed if `*op_copy` is the only
6239560d06aSjeremylt            reference to this CeedOperator.
6249560d06aSjeremylt 
6259560d06aSjeremylt   @param op            CeedOperator to copy reference to
6269560d06aSjeremylt   @param[out] op_copy  Variable to store copied reference
6279560d06aSjeremylt 
6289560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6299560d06aSjeremylt 
6309560d06aSjeremylt   @ref User
6319560d06aSjeremylt **/
6329560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
6339560d06aSjeremylt   int ierr;
6349560d06aSjeremylt 
6359560d06aSjeremylt   ierr = CeedOperatorReference(op); CeedChk(ierr);
6369560d06aSjeremylt   ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr);
6379560d06aSjeremylt   *op_copy = op;
6389560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6399560d06aSjeremylt }
6409560d06aSjeremylt 
6419560d06aSjeremylt /**
642b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
643d7b241e6Sjeremylt 
644d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
645d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
646d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
647d7b241e6Sjeremylt 
648d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
649d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
650d7b241e6Sjeremylt   input and at most one active output.
651d7b241e6Sjeremylt 
6528c91a0c9SJeremy L Thompson   @param op          CeedOperator on which to provide the field
653d1d35e2fSjeremylt   @param field_name  Name of the field (to be matched with the name used by
6548795c945Sjeremylt                        CeedQFunction)
655b11c1e72Sjeremylt   @param r           CeedElemRestriction
6564cc79fe7SJed Brown   @param b           CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED
657b11c1e72Sjeremylt                        if collocated with quadrature points
6584cc79fe7SJed Brown   @param v           CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE
6594cc79fe7SJed Brown                        if field is active or @ref CEED_VECTOR_NONE if using
6604cc79fe7SJed Brown                        @ref CEED_EVAL_WEIGHT in the QFunction
661b11c1e72Sjeremylt 
662b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
663dfdf5a53Sjeremylt 
6647a982d89SJeremy L. Thompson   @ref User
665b11c1e72Sjeremylt **/
666d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name,
667a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
668d7b241e6Sjeremylt   int ierr;
669f04ea552SJeremy L Thompson   if (op->is_composite)
670c042f62fSJeremy L Thompson     // LCOV_EXCL_START
671e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
672e15f9bd0SJeremy L Thompson                      "Cannot add field to composite operator.");
673c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
674f04ea552SJeremy L Thompson   if (op->is_immutable)
675f04ea552SJeremy L Thompson     // LCOV_EXCL_START
676f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
677f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
678f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
6798b067b84SJed Brown   if (!r)
680c042f62fSJeremy L Thompson     // LCOV_EXCL_START
681e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
682c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
683d1d35e2fSjeremylt                      field_name);
684c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6858b067b84SJed Brown   if (!b)
686c042f62fSJeremy L Thompson     // LCOV_EXCL_START
687e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
688e15f9bd0SJeremy L Thompson                      "Basis b for field \"%s\" must be non-NULL.",
689d1d35e2fSjeremylt                      field_name);
690c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6918b067b84SJed Brown   if (!v)
692c042f62fSJeremy L Thompson     // LCOV_EXCL_START
693e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
694e15f9bd0SJeremy L Thompson                      "Vector v for field \"%s\" must be non-NULL.",
695d1d35e2fSjeremylt                      field_name);
696c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
69752d6035fSJeremy L Thompson 
698d1d35e2fSjeremylt   CeedInt num_elem;
699d1d35e2fSjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr);
700d1d35e2fSjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction &&
701d1d35e2fSjeremylt       op->num_elem != num_elem)
702c042f62fSJeremy L Thompson     // LCOV_EXCL_START
703e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_DIMENSION,
7041d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
705d1d35e2fSjeremylt                      "%d elements", num_elem, op->num_elem);
706c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
707d7b241e6Sjeremylt 
70878464608Sjeremylt   CeedInt num_qpts = 0;
709e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
710d1d35e2fSjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr);
711d1d35e2fSjeremylt     if (op->num_qpts && op->num_qpts != num_qpts)
712c042f62fSJeremy L Thompson       // LCOV_EXCL_START
713e15f9bd0SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_DIMENSION,
714e15f9bd0SJeremy L Thompson                        "Basis with %d quadrature points "
715d1d35e2fSjeremylt                        "incompatible with prior %d points", num_qpts,
716d1d35e2fSjeremylt                        op->num_qpts);
717c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
718d7b241e6Sjeremylt   }
719d1d35e2fSjeremylt   CeedQFunctionField qf_field;
720d1d35e2fSjeremylt   CeedOperatorField *op_field;
721d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
722d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) {
723d1d35e2fSjeremylt       qf_field = op->qf->input_fields[i];
724d1d35e2fSjeremylt       op_field = &op->input_fields[i];
725d7b241e6Sjeremylt       goto found;
726d7b241e6Sjeremylt     }
727d7b241e6Sjeremylt   }
728d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
729d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) {
730d1d35e2fSjeremylt       qf_field = op->qf->output_fields[i];
731d1d35e2fSjeremylt       op_field = &op->output_fields[i];
732d7b241e6Sjeremylt       goto found;
733d7b241e6Sjeremylt     }
734d7b241e6Sjeremylt   }
735c042f62fSJeremy L Thompson   // LCOV_EXCL_START
736e15f9bd0SJeremy L Thompson   return CeedError(op->ceed, CEED_ERROR_INCOMPLETE,
737e15f9bd0SJeremy L Thompson                    "QFunction has no knowledge of field '%s'",
738d1d35e2fSjeremylt                    field_name);
739c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
740d7b241e6Sjeremylt found:
741d1d35e2fSjeremylt   ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr);
742d1d35e2fSjeremylt   ierr = CeedCalloc(1, op_field); CeedChk(ierr);
743e15f9bd0SJeremy L Thompson 
744d1d35e2fSjeremylt   (*op_field)->vec = v;
745e15f9bd0SJeremy L Thompson   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) {
7469560d06aSjeremylt     ierr = CeedVectorReference(v); CeedChk(ierr);
747e15f9bd0SJeremy L Thompson   }
748e15f9bd0SJeremy L Thompson 
749d1d35e2fSjeremylt   (*op_field)->elem_restr = r;
7509560d06aSjeremylt   ierr = CeedElemRestrictionReference(r); CeedChk(ierr);
751e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
752d1d35e2fSjeremylt     op->num_elem = num_elem;
753d1d35e2fSjeremylt     op->has_restriction = true; // Restriction set, but num_elem may be 0
754e15f9bd0SJeremy L Thompson   }
755d99fa3c5SJeremy L Thompson 
756d1d35e2fSjeremylt   (*op_field)->basis = b;
757e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
758cd4dfc48Sjeremylt     if (!op->num_qpts) {
759cd4dfc48Sjeremylt       ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr);
760cd4dfc48Sjeremylt     }
7619560d06aSjeremylt     ierr = CeedBasisReference(b); CeedChk(ierr);
762e15f9bd0SJeremy L Thompson   }
763e15f9bd0SJeremy L Thompson 
764d1d35e2fSjeremylt   op->num_fields += 1;
765f7e22acaSJeremy L Thompson   ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name);
766f7e22acaSJeremy L Thompson   CeedChk(ierr);
767e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
768d7b241e6Sjeremylt }
769d7b241e6Sjeremylt 
770d7b241e6Sjeremylt /**
77143bbe138SJeremy L Thompson   @brief Get the CeedOperatorFields of a CeedOperator
77243bbe138SJeremy L Thompson 
773f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
774f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
775f04ea552SJeremy L Thompson 
77643bbe138SJeremy L Thompson   @param op                      CeedOperator
777f74ec584SJeremy L Thompson   @param[out] num_input_fields   Variable to store number of input fields
77843bbe138SJeremy L Thompson   @param[out] input_fields       Variable to store input_fields
779f74ec584SJeremy L Thompson   @param[out] num_output_fields  Variable to store number of output fields
78043bbe138SJeremy L Thompson   @param[out] output_fields      Variable to store output_fields
78143bbe138SJeremy L Thompson 
78243bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
78343bbe138SJeremy L Thompson 
784e9b533fbSJeremy L Thompson   @ref Advanced
78543bbe138SJeremy L Thompson **/
78643bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields,
78743bbe138SJeremy L Thompson                           CeedOperatorField **input_fields,
78843bbe138SJeremy L Thompson                           CeedInt *num_output_fields,
78943bbe138SJeremy L Thompson                           CeedOperatorField **output_fields) {
790f04ea552SJeremy L Thompson   int ierr;
791f04ea552SJeremy L Thompson 
792f04ea552SJeremy L Thompson   if (op->is_composite)
79343bbe138SJeremy L Thompson     // LCOV_EXCL_START
79443bbe138SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
79543bbe138SJeremy L Thompson                      "Not defined for composite operator");
79643bbe138SJeremy L Thompson   // LCOV_EXCL_STOP
797f04ea552SJeremy L Thompson   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
79843bbe138SJeremy L Thompson 
79943bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = op->qf->num_input_fields;
80043bbe138SJeremy L Thompson   if (input_fields) *input_fields = op->input_fields;
80143bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = op->qf->num_output_fields;
80243bbe138SJeremy L Thompson   if (output_fields) *output_fields = op->output_fields;
80343bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
80443bbe138SJeremy L Thompson }
80543bbe138SJeremy L Thompson 
80643bbe138SJeremy L Thompson /**
80728567f8fSJeremy L Thompson   @brief Get the name of a CeedOperatorField
80828567f8fSJeremy L Thompson 
80928567f8fSJeremy L Thompson   @param op_field         CeedOperatorField
81028567f8fSJeremy L Thompson   @param[out] field_name  Variable to store the field name
81128567f8fSJeremy L Thompson 
81228567f8fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
81328567f8fSJeremy L Thompson 
814e9b533fbSJeremy L Thompson   @ref Advanced
81528567f8fSJeremy L Thompson **/
81628567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) {
81728567f8fSJeremy L Thompson   *field_name = (char *)op_field->field_name;
81828567f8fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
81928567f8fSJeremy L Thompson }
82028567f8fSJeremy L Thompson 
82128567f8fSJeremy L Thompson /**
82243bbe138SJeremy L Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
82343bbe138SJeremy L Thompson 
82443bbe138SJeremy L Thompson   @param op_field   CeedOperatorField
82543bbe138SJeremy L Thompson   @param[out] rstr  Variable to store CeedElemRestriction
82643bbe138SJeremy L Thompson 
82743bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
82843bbe138SJeremy L Thompson 
829e9b533fbSJeremy L Thompson   @ref Advanced
83043bbe138SJeremy L Thompson **/
83143bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,
83243bbe138SJeremy L Thompson                                         CeedElemRestriction *rstr) {
83343bbe138SJeremy L Thompson   *rstr = op_field->elem_restr;
83443bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
83543bbe138SJeremy L Thompson }
83643bbe138SJeremy L Thompson 
83743bbe138SJeremy L Thompson /**
83843bbe138SJeremy L Thompson   @brief Get the CeedBasis of a CeedOperatorField
83943bbe138SJeremy L Thompson 
84043bbe138SJeremy L Thompson   @param op_field    CeedOperatorField
84143bbe138SJeremy L Thompson   @param[out] basis  Variable to store CeedBasis
84243bbe138SJeremy L Thompson 
84343bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
84443bbe138SJeremy L Thompson 
845e9b533fbSJeremy L Thompson   @ref Advanced
84643bbe138SJeremy L Thompson **/
84743bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
84843bbe138SJeremy L Thompson   *basis = op_field->basis;
84943bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
85043bbe138SJeremy L Thompson }
85143bbe138SJeremy L Thompson 
85243bbe138SJeremy L Thompson /**
85343bbe138SJeremy L Thompson   @brief Get the CeedVector of a CeedOperatorField
85443bbe138SJeremy L Thompson 
85543bbe138SJeremy L Thompson   @param op_field  CeedOperatorField
85643bbe138SJeremy L Thompson   @param[out] vec  Variable to store CeedVector
85743bbe138SJeremy L Thompson 
85843bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
85943bbe138SJeremy L Thompson 
860e9b533fbSJeremy L Thompson   @ref Advanced
86143bbe138SJeremy L Thompson **/
86243bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
86343bbe138SJeremy L Thompson   *vec = op_field->vec;
86443bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
86543bbe138SJeremy L Thompson }
86643bbe138SJeremy L Thompson 
86743bbe138SJeremy L Thompson /**
86852d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
869288c0443SJeremy L Thompson 
870d1d35e2fSjeremylt   @param[out] composite_op  Composite CeedOperator
871d1d35e2fSjeremylt   @param      sub_op        Sub-operator CeedOperator
87252d6035fSJeremy L Thompson 
87352d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
87452d6035fSJeremy L Thompson 
8757a982d89SJeremy L. Thompson   @ref User
87652d6035fSJeremy L Thompson  */
877d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op,
878d1d35e2fSjeremylt                                 CeedOperator sub_op) {
87934359f16Sjeremylt   int ierr;
88034359f16Sjeremylt 
881f04ea552SJeremy L Thompson   if (!composite_op->is_composite)
882c042f62fSJeremy L Thompson     // LCOV_EXCL_START
883d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_MINOR,
884e2f04181SAndrew T. Barker                      "CeedOperator is not a composite operator");
885c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
88652d6035fSJeremy L Thompson 
887d1d35e2fSjeremylt   if (composite_op->num_suboperators == CEED_COMPOSITE_MAX)
888c042f62fSJeremy L Thompson     // LCOV_EXCL_START
889d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED,
890d1d35e2fSjeremylt                      "Cannot add additional sub_operators");
891c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
892f04ea552SJeremy L Thompson   if (composite_op->is_immutable)
893f04ea552SJeremy L Thompson     // LCOV_EXCL_START
894f04ea552SJeremy L Thompson     return CeedError(composite_op->ceed, CEED_ERROR_MAJOR,
895f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
896f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
89752d6035fSJeremy L Thompson 
898d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
8999560d06aSjeremylt   ierr = CeedOperatorReference(sub_op); CeedChk(ierr);
900d1d35e2fSjeremylt   composite_op->num_suboperators++;
901e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
90252d6035fSJeremy L Thompson }
90352d6035fSJeremy L Thompson 
90452d6035fSJeremy L Thompson /**
9054db537f9SJeremy L Thompson   @brief Check if a CeedOperator is ready to be used.
9064db537f9SJeremy L Thompson 
9074db537f9SJeremy L Thompson   @param[in] op  CeedOperator to check
9084db537f9SJeremy L Thompson 
9094db537f9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9104db537f9SJeremy L Thompson 
9114db537f9SJeremy L Thompson   @ref User
9124db537f9SJeremy L Thompson **/
9134db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
9144db537f9SJeremy L Thompson   int ierr;
9154db537f9SJeremy L Thompson   Ceed ceed;
9164db537f9SJeremy L Thompson   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
9174db537f9SJeremy L Thompson 
9184db537f9SJeremy L Thompson   if (op->is_interface_setup)
9194db537f9SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9204db537f9SJeremy L Thompson 
9214db537f9SJeremy L Thompson   CeedQFunction qf = op->qf;
9224db537f9SJeremy L Thompson   if (op->is_composite) {
9234db537f9SJeremy L Thompson     if (!op->num_suboperators)
9244db537f9SJeremy L Thompson       // LCOV_EXCL_START
9254db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set");
9264db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9274db537f9SJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
9284db537f9SJeremy L Thompson       ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr);
9294db537f9SJeremy L Thompson     }
9304db537f9SJeremy L Thompson   } else {
9314db537f9SJeremy L Thompson     if (op->num_fields == 0)
9324db537f9SJeremy L Thompson       // LCOV_EXCL_START
9334db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set");
9344db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9354db537f9SJeremy L Thompson     if (op->num_fields < qf->num_input_fields + qf->num_output_fields)
9364db537f9SJeremy L Thompson       // LCOV_EXCL_START
9374db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set");
9384db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9394db537f9SJeremy L Thompson     if (!op->has_restriction)
9404db537f9SJeremy L Thompson       // LCOV_EXCL_START
9414db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
9424db537f9SJeremy L Thompson                        "At least one restriction required");
9434db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9444db537f9SJeremy L Thompson     if (op->num_qpts == 0)
9454db537f9SJeremy L Thompson       // LCOV_EXCL_START
9464db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
9474db537f9SJeremy L Thompson                        "At least one non-collocated basis is required "
9484db537f9SJeremy L Thompson                        "or the number of quadrature points must be set");
9494db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9504db537f9SJeremy L Thompson   }
9514db537f9SJeremy L Thompson 
9524db537f9SJeremy L Thompson   // Flag as immutable and ready
9534db537f9SJeremy L Thompson   op->is_interface_setup = true;
9544db537f9SJeremy L Thompson   if (op->qf && op->qf != CEED_QFUNCTION_NONE)
9554db537f9SJeremy L Thompson     // LCOV_EXCL_START
9564db537f9SJeremy L Thompson     op->qf->is_immutable = true;
9574db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
9584db537f9SJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE)
9594db537f9SJeremy L Thompson     // LCOV_EXCL_START
9604db537f9SJeremy L Thompson     op->dqf->is_immutable = true;
9614db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
9624db537f9SJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE)
9634db537f9SJeremy L Thompson     // LCOV_EXCL_START
9644db537f9SJeremy L Thompson     op->dqfT->is_immutable = true;
9654db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
9664db537f9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9674db537f9SJeremy L Thompson }
9684db537f9SJeremy L Thompson 
9694db537f9SJeremy L Thompson /**
970beecbf24SJeremy L Thompson   @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions.
971beecbf24SJeremy L Thompson            When `reuse_assembly_data = false` (default), the CeedQFunction associated
972beecbf24SJeremy L Thompson            with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*`
973beecbf24SJeremy L Thompson            function is called.
974beecbf24SJeremy L Thompson            When `reuse_assembly_data = true`, the CeedQFunction associated with
975beecbf24SJeremy L Thompson            this CeedOperator is reused between calls to
976beecbf24SJeremy L Thompson            `CeedOperatorSetQFunctionAssemblyDataUpdated`.
9778b919e6bSJeremy L Thompson 
978beecbf24SJeremy L Thompson   @param[in] op                  CeedOperator
979beecbf24SJeremy L Thompson   @param[in] reuse_assembly_data Boolean flag setting assembly data reuse
9808b919e6bSJeremy L Thompson 
9818b919e6bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9828b919e6bSJeremy L Thompson 
9838b919e6bSJeremy L Thompson   @ref Advanced
9848b919e6bSJeremy L Thompson **/
985beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op,
986beecbf24SJeremy L Thompson     bool reuse_assembly_data) {
9878b919e6bSJeremy L Thompson   int ierr;
9888b919e6bSJeremy L Thompson   bool is_composite;
9898b919e6bSJeremy L Thompson 
9908b919e6bSJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
9918b919e6bSJeremy L Thompson   if (is_composite) {
9928b919e6bSJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
993beecbf24SJeremy L Thompson       ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i],
994beecbf24SJeremy L Thompson              reuse_assembly_data); CeedChk(ierr);
9958b919e6bSJeremy L Thompson     }
9968b919e6bSJeremy L Thompson   } else {
997beecbf24SJeremy L Thompson     ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data);
998beecbf24SJeremy L Thompson     CeedChk(ierr);
999beecbf24SJeremy L Thompson   }
1000beecbf24SJeremy L Thompson 
1001beecbf24SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1002beecbf24SJeremy L Thompson }
1003beecbf24SJeremy L Thompson 
1004beecbf24SJeremy L Thompson /**
1005beecbf24SJeremy L Thompson   @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly.
1006beecbf24SJeremy L Thompson 
1007beecbf24SJeremy L Thompson   @param[in] op                  CeedOperator
1008beecbf24SJeremy L Thompson   @param[in] reuse_assembly_data Boolean flag setting assembly data reuse
1009beecbf24SJeremy L Thompson 
1010beecbf24SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1011beecbf24SJeremy L Thompson 
1012beecbf24SJeremy L Thompson   @ref Advanced
1013beecbf24SJeremy L Thompson **/
1014beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op,
1015beecbf24SJeremy L Thompson     bool needs_data_update) {
1016beecbf24SJeremy L Thompson   int ierr;
1017beecbf24SJeremy L Thompson   bool is_composite;
1018beecbf24SJeremy L Thompson 
1019beecbf24SJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
1020beecbf24SJeremy L Thompson   if (is_composite) {
1021beecbf24SJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
1022beecbf24SJeremy L Thompson       ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i],
1023beecbf24SJeremy L Thompson              needs_data_update); CeedChk(ierr);
1024beecbf24SJeremy L Thompson     }
1025beecbf24SJeremy L Thompson   } else {
1026beecbf24SJeremy L Thompson     ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled,
1027beecbf24SJeremy L Thompson            needs_data_update);
10288b919e6bSJeremy L Thompson     CeedChk(ierr);
10298b919e6bSJeremy L Thompson   }
10308b919e6bSJeremy L Thompson 
10318b919e6bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
10328b919e6bSJeremy L Thompson }
10338b919e6bSJeremy L Thompson 
10348b919e6bSJeremy L Thompson /**
1035cd4dfc48Sjeremylt   @brief Set the number of quadrature points associated with a CeedOperator.
1036cd4dfc48Sjeremylt            This should be used when creating a CeedOperator where every
1037cd4dfc48Sjeremylt            field has a collocated basis. This function cannot be used for
1038cd4dfc48Sjeremylt            composite CeedOperators.
1039cd4dfc48Sjeremylt 
1040cd4dfc48Sjeremylt   @param op        CeedOperator
1041cd4dfc48Sjeremylt   @param num_qpts  Number of quadrature points to set
1042cd4dfc48Sjeremylt 
1043cd4dfc48Sjeremylt   @return An error code: 0 - success, otherwise - failure
1044cd4dfc48Sjeremylt 
1045e9b533fbSJeremy L Thompson   @ref Advanced
1046cd4dfc48Sjeremylt **/
1047cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) {
1048f04ea552SJeremy L Thompson   if (op->is_composite)
1049cd4dfc48Sjeremylt     // LCOV_EXCL_START
1050cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
1051cd4dfc48Sjeremylt                      "Not defined for composite operator");
1052cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
1053cd4dfc48Sjeremylt   if (op->num_qpts)
1054cd4dfc48Sjeremylt     // LCOV_EXCL_START
1055cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
1056cd4dfc48Sjeremylt                      "Number of quadrature points already defined");
1057cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
1058f04ea552SJeremy L Thompson   if (op->is_immutable)
1059f04ea552SJeremy L Thompson     // LCOV_EXCL_START
1060f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
1061f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
1062f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
1063cd4dfc48Sjeremylt 
1064cd4dfc48Sjeremylt   op->num_qpts = num_qpts;
1065cd4dfc48Sjeremylt   return CEED_ERROR_SUCCESS;
1066cd4dfc48Sjeremylt }
1067cd4dfc48Sjeremylt 
1068cd4dfc48Sjeremylt /**
10697a982d89SJeremy L. Thompson   @brief View a CeedOperator
10707a982d89SJeremy L. Thompson 
10717a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
10727a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
10737a982d89SJeremy L. Thompson 
10747a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
10757a982d89SJeremy L. Thompson 
10767a982d89SJeremy L. Thompson   @ref User
10777a982d89SJeremy L. Thompson **/
10787a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
10797a982d89SJeremy L. Thompson   int ierr;
10807a982d89SJeremy L. Thompson 
1081f04ea552SJeremy L Thompson   if (op->is_composite) {
10827a982d89SJeremy L. Thompson     fprintf(stream, "Composite CeedOperator\n");
10837a982d89SJeremy L. Thompson 
1084d1d35e2fSjeremylt     for (CeedInt i=0; i<op->num_suboperators; i++) {
10857a982d89SJeremy L. Thompson       fprintf(stream, "  SubOperator [%d]:\n", i);
1086d1d35e2fSjeremylt       ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream);
10877a982d89SJeremy L. Thompson       CeedChk(ierr);
10887a982d89SJeremy L. Thompson     }
10897a982d89SJeremy L. Thompson   } else {
10907a982d89SJeremy L. Thompson     fprintf(stream, "CeedOperator\n");
10917a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
10927a982d89SJeremy L. Thompson   }
1093e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10947a982d89SJeremy L. Thompson }
10953bd813ffSjeremylt 
10963bd813ffSjeremylt /**
1097b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedOperator
1098b7c9bbdaSJeremy L Thompson 
1099b7c9bbdaSJeremy L Thompson   @param op         CeedOperator
1100b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
1101b7c9bbdaSJeremy L Thompson 
1102b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1103b7c9bbdaSJeremy L Thompson 
1104b7c9bbdaSJeremy L Thompson   @ref Advanced
1105b7c9bbdaSJeremy L Thompson **/
1106b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
1107b7c9bbdaSJeremy L Thompson   *ceed = op->ceed;
1108b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1109b7c9bbdaSJeremy L Thompson }
1110b7c9bbdaSJeremy L Thompson 
1111b7c9bbdaSJeremy L Thompson /**
1112b7c9bbdaSJeremy L Thompson   @brief Get the number of elements associated with a CeedOperator
1113b7c9bbdaSJeremy L Thompson 
1114b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1115b7c9bbdaSJeremy L Thompson   @param[out] num_elem  Variable to store number of elements
1116b7c9bbdaSJeremy L Thompson 
1117b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1118b7c9bbdaSJeremy L Thompson 
1119b7c9bbdaSJeremy L Thompson   @ref Advanced
1120b7c9bbdaSJeremy L Thompson **/
1121b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
1122b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1123b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1124b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1125b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1126b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1127b7c9bbdaSJeremy L Thompson 
1128b7c9bbdaSJeremy L Thompson   *num_elem = op->num_elem;
1129b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1130b7c9bbdaSJeremy L Thompson }
1131b7c9bbdaSJeremy L Thompson 
1132b7c9bbdaSJeremy L Thompson /**
1133b7c9bbdaSJeremy L Thompson   @brief Get the number of quadrature points associated with a CeedOperator
1134b7c9bbdaSJeremy L Thompson 
1135b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1136b7c9bbdaSJeremy L Thompson   @param[out] num_qpts  Variable to store vector number of quadrature points
1137b7c9bbdaSJeremy L Thompson 
1138b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1139b7c9bbdaSJeremy L Thompson 
1140b7c9bbdaSJeremy L Thompson   @ref Advanced
1141b7c9bbdaSJeremy L Thompson **/
1142b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
1143b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1144b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1145b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1146b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1147b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1148b7c9bbdaSJeremy L Thompson 
1149b7c9bbdaSJeremy L Thompson   *num_qpts = op->num_qpts;
1150b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1151b7c9bbdaSJeremy L Thompson }
1152b7c9bbdaSJeremy L Thompson 
1153b7c9bbdaSJeremy L Thompson /**
11543668ca4bSJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no
11553668ca4bSJeremy L Thompson            field has been registered with this `field_name`.
11563668ca4bSJeremy L Thompson 
11573668ca4bSJeremy L Thompson   @param[in] op            CeedOperator
11583668ca4bSJeremy L Thompson   @param[in] field_name    Name of field to retrieve label
11593668ca4bSJeremy L Thompson   @param[out] field_label  Variable to field label
11603668ca4bSJeremy L Thompson 
11613668ca4bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
11623668ca4bSJeremy L Thompson 
11633668ca4bSJeremy L Thompson   @ref User
11643668ca4bSJeremy L Thompson **/
11653668ca4bSJeremy L Thompson int CeedOperatorContextGetFieldLabel(CeedOperator op,
11663668ca4bSJeremy L Thompson                                      const char *field_name,
11673668ca4bSJeremy L Thompson                                      CeedContextFieldLabel *field_label) {
11683668ca4bSJeremy L Thompson   int ierr;
11693668ca4bSJeremy L Thompson 
11703668ca4bSJeremy L Thompson   bool is_composite;
11713668ca4bSJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
11723668ca4bSJeremy L Thompson   if (is_composite) {
11733668ca4bSJeremy L Thompson     // Check if composite label already created
11743668ca4bSJeremy L Thompson     for (CeedInt i=0; i<op->num_context_labels; i++) {
11753668ca4bSJeremy L Thompson       if (!strcmp(op->context_labels[i]->name, field_name)) {
11763668ca4bSJeremy L Thompson         *field_label = op->context_labels[i];
11773668ca4bSJeremy L Thompson         return CEED_ERROR_SUCCESS;
11783668ca4bSJeremy L Thompson       }
11793668ca4bSJeremy L Thompson     }
11803668ca4bSJeremy L Thompson 
11813668ca4bSJeremy L Thompson     // Create composite label if needed
11823668ca4bSJeremy L Thompson     CeedInt num_sub;
11833668ca4bSJeremy L Thompson     CeedOperator *sub_operators;
11843668ca4bSJeremy L Thompson     CeedContextFieldLabel new_field_label;
11853668ca4bSJeremy L Thompson 
11863668ca4bSJeremy L Thompson     ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr);
11873668ca4bSJeremy L Thompson     ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr);
11883668ca4bSJeremy L Thompson     ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
11893668ca4bSJeremy L Thompson     ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr);
11903668ca4bSJeremy L Thompson     new_field_label->num_sub_labels = num_sub;
11913668ca4bSJeremy L Thompson 
11923668ca4bSJeremy L Thompson     bool label_found = false;
11933668ca4bSJeremy L Thompson     for (CeedInt i=0; i<num_sub; i++) {
11943668ca4bSJeremy L Thompson       if (sub_operators[i]->qf->ctx) {
11953668ca4bSJeremy L Thompson         CeedContextFieldLabel new_field_label_i;
11963668ca4bSJeremy L Thompson         ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name,
11973668ca4bSJeremy L Thompson                &new_field_label_i); CeedChk(ierr);
11983668ca4bSJeremy L Thompson         if (new_field_label_i) {
11993668ca4bSJeremy L Thompson           label_found = true;
12003668ca4bSJeremy L Thompson           new_field_label->sub_labels[i] = new_field_label_i;
12013668ca4bSJeremy L Thompson           new_field_label->name = new_field_label_i->name;
12023668ca4bSJeremy L Thompson           new_field_label->description = new_field_label_i->description;
12037bfe0f0eSJeremy L Thompson           if (new_field_label->type &&
12047bfe0f0eSJeremy L Thompson               new_field_label->type != new_field_label_i->type) {
12057bfe0f0eSJeremy L Thompson             // LCOV_EXCL_START
12067bfe0f0eSJeremy L Thompson             ierr = CeedFree(&new_field_label); CeedChk(ierr);
12077bfe0f0eSJeremy L Thompson             return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
12087bfe0f0eSJeremy L Thompson                              "Incompatible field types on sub-operator contexts. "
12097bfe0f0eSJeremy L Thompson                              "%s != %s",
12107bfe0f0eSJeremy L Thompson                              CeedContextFieldTypes[new_field_label->type],
12117bfe0f0eSJeremy L Thompson                              CeedContextFieldTypes[new_field_label_i->type]);
12127bfe0f0eSJeremy L Thompson             // LCOV_EXCL_STOP
12137bfe0f0eSJeremy L Thompson           } else {
12147bfe0f0eSJeremy L Thompson             new_field_label->type = new_field_label_i->type;
12157bfe0f0eSJeremy L Thompson           }
12167bfe0f0eSJeremy L Thompson           if (new_field_label->num_values != 0 &&
12177bfe0f0eSJeremy L Thompson               new_field_label->num_values != new_field_label_i->num_values) {
12187bfe0f0eSJeremy L Thompson             // LCOV_EXCL_START
12197bfe0f0eSJeremy L Thompson             ierr = CeedFree(&new_field_label); CeedChk(ierr);
12207bfe0f0eSJeremy L Thompson             return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
12217bfe0f0eSJeremy L Thompson                              "Incompatible field number of values on sub-operator"
12227bfe0f0eSJeremy L Thompson                              " contexts. %ld != %ld",
12237bfe0f0eSJeremy L Thompson                              new_field_label->num_values, new_field_label_i->num_values);
12247bfe0f0eSJeremy L Thompson             // LCOV_EXCL_STOP
12257bfe0f0eSJeremy L Thompson           } else {
12267bfe0f0eSJeremy L Thompson             new_field_label->num_values = new_field_label_i->num_values;
12277bfe0f0eSJeremy L Thompson           }
12283668ca4bSJeremy L Thompson         }
12293668ca4bSJeremy L Thompson       }
12303668ca4bSJeremy L Thompson     }
12313668ca4bSJeremy L Thompson     if (!label_found) {
12323668ca4bSJeremy L Thompson       // LCOV_EXCL_START
1233a48e5f43SJeremy L Thompson       ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr);
12343668ca4bSJeremy L Thompson       ierr = CeedFree(&new_field_label); CeedChk(ierr);
12353668ca4bSJeremy L Thompson       *field_label = NULL;
12363668ca4bSJeremy L Thompson       // LCOV_EXCL_STOP
12373668ca4bSJeremy L Thompson     } else {
12383668ca4bSJeremy L Thompson       // Move new composite label to operator
12393668ca4bSJeremy L Thompson       if (op->num_context_labels == 0) {
12403668ca4bSJeremy L Thompson         ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr);
12413668ca4bSJeremy L Thompson         op->max_context_labels = 1;
12423668ca4bSJeremy L Thompson       } else if (op->num_context_labels == op->max_context_labels) {
12433668ca4bSJeremy L Thompson         ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels);
12443668ca4bSJeremy L Thompson         CeedChk(ierr);
12453668ca4bSJeremy L Thompson         op->max_context_labels *= 2;
12463668ca4bSJeremy L Thompson       }
12473668ca4bSJeremy L Thompson       op->context_labels[op->num_context_labels] = new_field_label;
12483668ca4bSJeremy L Thompson       *field_label = new_field_label;
12493668ca4bSJeremy L Thompson       op->num_context_labels++;
12503668ca4bSJeremy L Thompson     }
12513668ca4bSJeremy L Thompson 
12523668ca4bSJeremy L Thompson     return CEED_ERROR_SUCCESS;
12533668ca4bSJeremy L Thompson   } else {
12543668ca4bSJeremy L Thompson     return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label);
12553668ca4bSJeremy L Thompson   }
12563668ca4bSJeremy L Thompson }
12573668ca4bSJeremy L Thompson 
12583668ca4bSJeremy L Thompson /**
1259d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value.
1260d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
1261d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
1262d8dd9a91SJeremy L Thompson 
1263d8dd9a91SJeremy L Thompson   @param op          CeedOperator
12643668ca4bSJeremy L Thompson   @param field_label Label of field to register
12657bfe0f0eSJeremy L Thompson   @param values      Values to set
1266d8dd9a91SJeremy L Thompson 
1267d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1268d8dd9a91SJeremy L Thompson 
1269d8dd9a91SJeremy L Thompson   @ref User
1270d8dd9a91SJeremy L Thompson **/
12713668ca4bSJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op,
12723668ca4bSJeremy L Thompson                                  CeedContextFieldLabel field_label,
12737bfe0f0eSJeremy L Thompson                                  double *values) {
12743668ca4bSJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE,
12757bfe0f0eSJeremy L Thompson                                        values);
1276d8dd9a91SJeremy L Thompson }
1277d8dd9a91SJeremy L Thompson 
1278d8dd9a91SJeremy L Thompson /**
1279d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value.
1280d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
1281d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
1282d8dd9a91SJeremy L Thompson 
1283d8dd9a91SJeremy L Thompson   @param op          CeedOperator
12843668ca4bSJeremy L Thompson   @param field_label Label of field to set
12857bfe0f0eSJeremy L Thompson   @param values      Values to set
1286d8dd9a91SJeremy L Thompson 
1287d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1288d8dd9a91SJeremy L Thompson 
1289d8dd9a91SJeremy L Thompson   @ref User
1290d8dd9a91SJeremy L Thompson **/
12913668ca4bSJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op,
12923668ca4bSJeremy L Thompson                                 CeedContextFieldLabel field_label,
12937bfe0f0eSJeremy L Thompson                                 int *values) {
12943668ca4bSJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32,
12957bfe0f0eSJeremy L Thompson                                        values);
1296d8dd9a91SJeremy L Thompson }
1297d8dd9a91SJeremy L Thompson 
1298d8dd9a91SJeremy L Thompson /**
12993bd813ffSjeremylt   @brief Apply CeedOperator to a vector
1300d7b241e6Sjeremylt 
1301d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
1302d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1303d7b241e6Sjeremylt   CeedOperatorSetField().
1304d7b241e6Sjeremylt 
1305f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
1306f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
1307f04ea552SJeremy L Thompson 
1308d7b241e6Sjeremylt   @param op        CeedOperator to apply
13094cc79fe7SJed Brown   @param[in] in    CeedVector containing input state or @ref CEED_VECTOR_NONE if
131034138859Sjeremylt                      there are no active inputs
1311b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
13124cc79fe7SJed Brown                      distinct from @a in) or @ref CEED_VECTOR_NONE if there are no
131334138859Sjeremylt                      active outputs
1314d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
13154cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1316b11c1e72Sjeremylt 
1317b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1318dfdf5a53Sjeremylt 
13197a982d89SJeremy L. Thompson   @ref User
1320b11c1e72Sjeremylt **/
1321692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
1322692c2638Sjeremylt                       CeedRequest *request) {
1323d7b241e6Sjeremylt   int ierr;
1324e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1325d7b241e6Sjeremylt 
1326d1d35e2fSjeremylt   if (op->num_elem)  {
1327250756a7Sjeremylt     // Standard Operator
1328cae8b89aSjeremylt     if (op->Apply) {
1329250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
1330cae8b89aSjeremylt     } else {
1331cae8b89aSjeremylt       // Zero all output vectors
1332250756a7Sjeremylt       CeedQFunction qf = op->qf;
1333d1d35e2fSjeremylt       for (CeedInt i=0; i<qf->num_output_fields; i++) {
1334d1d35e2fSjeremylt         CeedVector vec = op->output_fields[i]->vec;
1335cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
1336cae8b89aSjeremylt           vec = out;
1337cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
1338cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1339cae8b89aSjeremylt         }
1340cae8b89aSjeremylt       }
1341250756a7Sjeremylt       // Apply
1342250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1343250756a7Sjeremylt     }
1344f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1345250756a7Sjeremylt     // Composite Operator
1346250756a7Sjeremylt     if (op->ApplyComposite) {
1347250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
1348250756a7Sjeremylt     } else {
1349d1d35e2fSjeremylt       CeedInt num_suboperators;
1350d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1351d1d35e2fSjeremylt       CeedOperator *sub_operators;
1352d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1353250756a7Sjeremylt 
1354250756a7Sjeremylt       // Zero all output vectors
1355250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
1356cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
1357cae8b89aSjeremylt       }
1358d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1359d1d35e2fSjeremylt         for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) {
1360d1d35e2fSjeremylt           CeedVector vec = sub_operators[i]->output_fields[j]->vec;
1361250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
1362250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1363250756a7Sjeremylt           }
1364250756a7Sjeremylt         }
1365250756a7Sjeremylt       }
1366250756a7Sjeremylt       // Apply
1367d1d35e2fSjeremylt       for (CeedInt i=0; i<op->num_suboperators; i++) {
1368d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request);
1369cae8b89aSjeremylt         CeedChk(ierr);
1370cae8b89aSjeremylt       }
1371cae8b89aSjeremylt     }
1372250756a7Sjeremylt   }
1373e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1374cae8b89aSjeremylt }
1375cae8b89aSjeremylt 
1376cae8b89aSjeremylt /**
1377cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
1378cae8b89aSjeremylt 
1379cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
1380cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1381cae8b89aSjeremylt   CeedOperatorSetField().
1382cae8b89aSjeremylt 
1383cae8b89aSjeremylt   @param op        CeedOperator to apply
1384cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
1385cae8b89aSjeremylt                      active inputs
1386cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
1387cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
1388cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
13894cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1390cae8b89aSjeremylt 
1391cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
1392cae8b89aSjeremylt 
13937a982d89SJeremy L. Thompson   @ref User
1394cae8b89aSjeremylt **/
1395cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
1396cae8b89aSjeremylt                          CeedRequest *request) {
1397cae8b89aSjeremylt   int ierr;
1398e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1399cae8b89aSjeremylt 
1400d1d35e2fSjeremylt   if (op->num_elem)  {
1401250756a7Sjeremylt     // Standard Operator
1402250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1403f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1404250756a7Sjeremylt     // Composite Operator
1405250756a7Sjeremylt     if (op->ApplyAddComposite) {
1406250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
1407cae8b89aSjeremylt     } else {
1408d1d35e2fSjeremylt       CeedInt num_suboperators;
1409d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1410d1d35e2fSjeremylt       CeedOperator *sub_operators;
1411d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1412250756a7Sjeremylt 
1413d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1414d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request);
1415cae8b89aSjeremylt         CeedChk(ierr);
14161d7d2407SJeremy L Thompson       }
1417250756a7Sjeremylt     }
1418250756a7Sjeremylt   }
1419e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1420d7b241e6Sjeremylt }
1421d7b241e6Sjeremylt 
1422d7b241e6Sjeremylt /**
1423b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1424d7b241e6Sjeremylt 
1425d7b241e6Sjeremylt   @param op  CeedOperator to destroy
1426b11c1e72Sjeremylt 
1427b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1428dfdf5a53Sjeremylt 
14297a982d89SJeremy L. Thompson   @ref User
1430b11c1e72Sjeremylt **/
1431d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1432d7b241e6Sjeremylt   int ierr;
1433d7b241e6Sjeremylt 
1434d1d35e2fSjeremylt   if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS;
1435d7b241e6Sjeremylt   if ((*op)->Destroy) {
1436d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1437d7b241e6Sjeremylt   }
1438fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1439fe2413ffSjeremylt   // Free fields
14403668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_fields; i++)
1441d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
1442d1d35e2fSjeremylt       if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) {
1443d1d35e2fSjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr);
144471352a93Sjeremylt         CeedChk(ierr);
144515910d16Sjeremylt       }
1446d1d35e2fSjeremylt       if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1447d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr);
144871352a93Sjeremylt       }
1449d1d35e2fSjeremylt       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1450d1d35e2fSjeremylt           (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) {
1451d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr);
145271352a93Sjeremylt       }
1453d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr);
1454d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr);
1455fe2413ffSjeremylt     }
14563668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_fields; i++)
1457d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
1458d1d35e2fSjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr);
145971352a93Sjeremylt       CeedChk(ierr);
1460d1d35e2fSjeremylt       if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1461d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr);
146271352a93Sjeremylt       }
1463d1d35e2fSjeremylt       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1464d1d35e2fSjeremylt           (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) {
1465d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr);
146671352a93Sjeremylt       }
1467d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr);
1468d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr);
1469fe2413ffSjeremylt     }
1470d1d35e2fSjeremylt   // Destroy sub_operators
14713668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_suboperators; i++)
1472d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
1473d1d35e2fSjeremylt       ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr);
147452d6035fSJeremy L Thompson     }
1475d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1476d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1477d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
14783668ca4bSJeremy L Thompson   // Destroy any composite labels
14793668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_context_labels; i++) {
14803668ca4bSJeremy L Thompson     ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr);
14813668ca4bSJeremy L Thompson     ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr);
14823668ca4bSJeremy L Thompson   }
14833668ca4bSJeremy L Thompson   ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr);
1484fe2413ffSjeremylt 
14855107b09fSJeremy L Thompson   // Destroy fallback
1486d1d35e2fSjeremylt   if ((*op)->op_fallback) {
1487d1d35e2fSjeremylt     ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr);
1488d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr);
1489d1d35e2fSjeremylt     ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr);
1490d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr);
14915107b09fSJeremy L Thompson   }
14925107b09fSJeremy L Thompson 
149370a7ffb3SJeremy L Thompson   // Destroy QF assembly cache
1494480fae85SJeremy L Thompson   ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr);
149570a7ffb3SJeremy L Thompson 
1496d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr);
1497d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr);
1498d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr);
1499d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1500e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1501d7b241e6Sjeremylt }
1502d7b241e6Sjeremylt 
1503d7b241e6Sjeremylt /// @}
1504