xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision 990fdeb6bb8fc9af2da4472bdc0d1f57da5da0e5)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
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,
74*990fdeb6SJeremy L Thompson                        "Field '%s' of size %" CeedInt_FMT " and EvalMode %s: ElemRestriction "
75*990fdeb6SJeremy L Thompson                        "has %" CeedInt_FMT " components, but Basis has %" CeedInt_FMT " 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,
88*990fdeb6SJeremy L Thompson                        "Field '%s' of size %" CeedInt_FMT " and EvalMode %s: ElemRestriction has "
89*990fdeb6SJeremy L Thompson                        CeedInt_FMT " components",
90d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
91d1d35e2fSjeremylt                        restr_num_comp);
92e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
93e15f9bd0SJeremy L Thompson     break;
94e15f9bd0SJeremy L Thompson   case CEED_EVAL_INTERP:
95d1d35e2fSjeremylt     if (size != num_comp)
96e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
97e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
98*990fdeb6SJeremy L Thompson                        "Field '%s' of size %" CeedInt_FMT
99*990fdeb6SJeremy L Thompson                        " and EvalMode %s: ElemRestriction/Basis has "
100*990fdeb6SJeremy L Thompson                        CeedInt_FMT " components",
101d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
102d1d35e2fSjeremylt                        num_comp);
103e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
104e15f9bd0SJeremy L Thompson     break;
105e15f9bd0SJeremy L Thompson   case CEED_EVAL_GRAD:
106d1d35e2fSjeremylt     if (size != num_comp * dim)
107e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
108e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
109*990fdeb6SJeremy L Thompson                        "Field '%s' of size %" CeedInt_FMT " and EvalMode %s in %" CeedInt_FMT
110*990fdeb6SJeremy L Thompson                        " dimensions: "
111*990fdeb6SJeremy L Thompson                        "ElemRestriction/Basis has %" CeedInt_FMT " components",
112d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim,
113d1d35e2fSjeremylt                        num_comp);
114e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
115e15f9bd0SJeremy L Thompson     break;
116e15f9bd0SJeremy L Thompson   case CEED_EVAL_WEIGHT:
117d1d35e2fSjeremylt     // No additional checks required
118e15f9bd0SJeremy L Thompson     break;
119e15f9bd0SJeremy L Thompson   case CEED_EVAL_DIV:
120e15f9bd0SJeremy L Thompson     // Not implemented
121e15f9bd0SJeremy L Thompson     break;
122e15f9bd0SJeremy L Thompson   case CEED_EVAL_CURL:
123e15f9bd0SJeremy L Thompson     // Not implemented
124e15f9bd0SJeremy L Thompson     break;
125e15f9bd0SJeremy L Thompson   }
126e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1277a982d89SJeremy L. Thompson }
1287a982d89SJeremy L. Thompson 
1297a982d89SJeremy L. Thompson /**
1307a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
1317a982d89SJeremy L. Thompson 
1327a982d89SJeremy L. Thompson   @param[in] field         Operator field to view
133d1d35e2fSjeremylt   @param[in] qf_field      QFunction field (carries field name)
134d1d35e2fSjeremylt   @param[in] field_number  Number of field being viewed
1354c4400c7SValeria Barra   @param[in] sub           true indicates sub-operator, which increases indentation; false for top-level operator
136d1d35e2fSjeremylt   @param[in] input         true for an input field; false for output field
1377a982d89SJeremy L. Thompson   @param[in] stream        Stream to view to, e.g., stdout
1387a982d89SJeremy L. Thompson 
1397a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1407a982d89SJeremy L. Thompson 
1417a982d89SJeremy L. Thompson   @ref Utility
1427a982d89SJeremy L. Thompson **/
1437a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
144d1d35e2fSjeremylt                                  CeedQFunctionField qf_field,
145d1d35e2fSjeremylt                                  CeedInt field_number, bool sub, bool input,
1467a982d89SJeremy L. Thompson                                  FILE *stream) {
1477a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
148d1d35e2fSjeremylt   const char *in_out = input ? "Input" : "Output";
1497a982d89SJeremy L. Thompson 
150*990fdeb6SJeremy L Thompson   fprintf(stream, "%s    %s field %" CeedInt_FMT ":\n"
1517a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
152d1d35e2fSjeremylt           pre, in_out, field_number, pre, qf_field->field_name);
1537a982d89SJeremy L. Thompson 
154*990fdeb6SJeremy L Thompson   fprintf(stream, "%s      Size: %" CeedInt_FMT "\n", pre, qf_field->size);
155f5ebfb90SJeremy L Thompson 
156f5ebfb90SJeremy L Thompson   fprintf(stream, "%s      EvalMode: %s\n", pre,
157f5ebfb90SJeremy L Thompson           CeedEvalModes[qf_field->eval_mode]);
158f5ebfb90SJeremy 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);
166f5ebfb90SJeremy L Thompson 
167e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1687a982d89SJeremy L. Thompson }
1697a982d89SJeremy L. Thompson 
1707a982d89SJeremy L. Thompson /**
1717a982d89SJeremy L. Thompson   @brief View a single CeedOperator
1727a982d89SJeremy L. Thompson 
1737a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
1747a982d89SJeremy L. Thompson   @param[in] sub     Boolean flag for sub-operator
1757a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
1767a982d89SJeremy L. Thompson 
1777a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
1787a982d89SJeremy L. Thompson 
1797a982d89SJeremy L. Thompson   @ref Utility
1807a982d89SJeremy L. Thompson **/
1817a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
1827a982d89SJeremy L. Thompson   int ierr;
1837a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
1847a982d89SJeremy L. Thompson 
185381e6593SJeremy L Thompson   CeedInt num_elem, num_qpts;
186381e6593SJeremy L Thompson   ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChk(ierr);
187381e6593SJeremy L Thompson   ierr = CeedOperatorGetNumQuadraturePoints(op, &num_qpts); CeedChk(ierr);
188381e6593SJeremy L Thompson 
18978464608Sjeremylt   CeedInt total_fields = 0;
19078464608Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr);
191*990fdeb6SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " elements with %" CeedInt_FMT
192*990fdeb6SJeremy L Thompson           " quadrature points each\n",
193381e6593SJeremy L Thompson           pre, num_elem, num_qpts);
1947a982d89SJeremy L. Thompson 
195*990fdeb6SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " field%s\n", pre, total_fields,
19678464608Sjeremylt           total_fields>1 ? "s" : "");
1977a982d89SJeremy L. Thompson 
198*990fdeb6SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " input field%s:\n", pre,
199*990fdeb6SJeremy L Thompson           op->qf->num_input_fields,
200d1d35e2fSjeremylt           op->qf->num_input_fields>1 ? "s" : "");
201d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
202d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i],
2037a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
2047a982d89SJeremy L. Thompson   }
2057a982d89SJeremy L. Thompson 
206*990fdeb6SJeremy L Thompson   fprintf(stream, "%s  %" CeedInt_FMT " output field%s:\n", pre,
207*990fdeb6SJeremy L Thompson           op->qf->num_output_fields,
208d1d35e2fSjeremylt           op->qf->num_output_fields>1 ? "s" : "");
209d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
210d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i],
2117a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
2127a982d89SJeremy L. Thompson   }
213e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2147a982d89SJeremy L. Thompson }
2157a982d89SJeremy L. Thompson 
216d99fa3c5SJeremy L Thompson /**
2170f60e0a8SJeremy L Thompson   @brief Find the active vector basis for a non-composite CeedOperator
218eaf62fffSJeremy L Thompson 
219eaf62fffSJeremy L Thompson   @param[in] op             CeedOperator to find active basis for
2200f60e0a8SJeremy L Thompson   @param[out] active_basis  Basis for active input vector or NULL for composite operator
221eaf62fffSJeremy L Thompson 
222eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
223eaf62fffSJeremy L Thompson 
224eaf62fffSJeremy L Thompson   @ ref Developer
225eaf62fffSJeremy L Thompson **/
226eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
227eaf62fffSJeremy L Thompson   *active_basis = NULL;
2280f60e0a8SJeremy L Thompson   if (op->is_composite) return CEED_ERROR_SUCCESS;
22992ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < op->qf->num_input_fields; i++)
230eaf62fffSJeremy L Thompson     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
231eaf62fffSJeremy L Thompson       *active_basis = op->input_fields[i]->basis;
232eaf62fffSJeremy L Thompson       break;
233eaf62fffSJeremy L Thompson     }
234eaf62fffSJeremy L Thompson 
235eaf62fffSJeremy L Thompson   if (!*active_basis) {
236eaf62fffSJeremy L Thompson     // LCOV_EXCL_START
237eaf62fffSJeremy L Thompson     int ierr;
238eaf62fffSJeremy L Thompson     Ceed ceed;
239eaf62fffSJeremy L Thompson     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
240eaf62fffSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
241eaf62fffSJeremy L Thompson                      "No active CeedBasis found");
242eaf62fffSJeremy L Thompson     // LCOV_EXCL_STOP
243eaf62fffSJeremy L Thompson   }
244eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
245eaf62fffSJeremy L Thompson }
246eaf62fffSJeremy L Thompson 
247eaf62fffSJeremy L Thompson /**
2480f60e0a8SJeremy L Thompson   @brief Find the active vector ElemRestriction for a non-composite CeedOperator
249e2f04181SAndrew T. Barker 
250e2f04181SAndrew T. Barker   @param[in] op            CeedOperator to find active basis for
2510f60e0a8SJeremy L Thompson   @param[out] active_rstr  ElemRestriction for active input vector or NULL for composite operator
252e2f04181SAndrew T. Barker 
253e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
254e2f04181SAndrew T. Barker 
255e2f04181SAndrew T. Barker   @ref Utility
256e2f04181SAndrew T. Barker **/
257eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op,
258d1d35e2fSjeremylt     CeedElemRestriction *active_rstr) {
259d1d35e2fSjeremylt   *active_rstr = NULL;
2600f60e0a8SJeremy L Thompson   if (op->is_composite) return CEED_ERROR_SUCCESS;
26192ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < op->qf->num_input_fields; i++)
262d1d35e2fSjeremylt     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
263d1d35e2fSjeremylt       *active_rstr = op->input_fields[i]->elem_restr;
264e2f04181SAndrew T. Barker       break;
265e2f04181SAndrew T. Barker     }
266e2f04181SAndrew T. Barker 
267d1d35e2fSjeremylt   if (!*active_rstr) {
268e2f04181SAndrew T. Barker     // LCOV_EXCL_START
269e2f04181SAndrew T. Barker     int ierr;
270e2f04181SAndrew T. Barker     Ceed ceed;
271e2f04181SAndrew T. Barker     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
272e2f04181SAndrew T. Barker     return CeedError(ceed, CEED_ERROR_INCOMPLETE,
273eaf62fffSJeremy L Thompson                      "No active CeedElemRestriction found");
274e2f04181SAndrew T. Barker     // LCOV_EXCL_STOP
275e2f04181SAndrew T. Barker   }
276e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
277e2f04181SAndrew T. Barker }
278e2f04181SAndrew T. Barker 
279d8dd9a91SJeremy L Thompson /**
280d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field value of the specified type.
281d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
282d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
283d8dd9a91SJeremy L Thompson            A non-zero error code is returned for single operators
284d8dd9a91SJeremy L Thompson            that do not have a matching field of the same type or composite
285d8dd9a91SJeremy L Thompson            operators that do not have any field of a matching type.
286d8dd9a91SJeremy L Thompson 
287d8dd9a91SJeremy L Thompson   @param op          CeedOperator
2883668ca4bSJeremy L Thompson   @param field_label Label of field to set
289d8dd9a91SJeremy L Thompson   @param field_type  Type of field to set
290d8dd9a91SJeremy L Thompson   @param value       Value to set
291d8dd9a91SJeremy L Thompson 
292d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
293d8dd9a91SJeremy L Thompson 
294d8dd9a91SJeremy L Thompson   @ref User
295d8dd9a91SJeremy L Thompson **/
296d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op,
2973668ca4bSJeremy L Thompson     CeedContextFieldLabel field_label, CeedContextFieldType field_type,
2983668ca4bSJeremy L Thompson     void *value) {
299d8dd9a91SJeremy L Thompson   int ierr;
300d8dd9a91SJeremy L Thompson 
3013668ca4bSJeremy L Thompson   if (!field_label)
3023668ca4bSJeremy L Thompson     // LCOV_EXCL_START
3033668ca4bSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
3043668ca4bSJeremy L Thompson                      "Invalid field label");
3053668ca4bSJeremy L Thompson   // LCOV_EXCL_STOP
3063668ca4bSJeremy L Thompson 
3073668ca4bSJeremy L Thompson   bool is_composite = false;
308d8dd9a91SJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
309d8dd9a91SJeremy L Thompson   if (is_composite) {
310d8dd9a91SJeremy L Thompson     CeedInt num_sub;
311d8dd9a91SJeremy L Thompson     CeedOperator *sub_operators;
312d8dd9a91SJeremy L Thompson 
313d8dd9a91SJeremy L Thompson     ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr);
314d8dd9a91SJeremy L Thompson     ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
3153668ca4bSJeremy L Thompson     if (num_sub != field_label->num_sub_labels)
3163668ca4bSJeremy L Thompson       // LCOV_EXCL_START
3173668ca4bSJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
3183668ca4bSJeremy L Thompson                        "ContextLabel does not correspond to composite operator.\n"
3193668ca4bSJeremy L Thompson                        "Use CeedOperatorGetContextFieldLabel().");
3203668ca4bSJeremy L Thompson     // LCOV_EXCL_STOP
321d8dd9a91SJeremy L Thompson 
322d8dd9a91SJeremy L Thompson     for (CeedInt i = 0; i < num_sub; i++) {
323d8dd9a91SJeremy L Thompson       // Try every sub-operator, ok if some sub-operators do not have field
3243668ca4bSJeremy L Thompson       if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) {
3253668ca4bSJeremy L Thompson         ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx,
3263668ca4bSJeremy L Thompson                                               field_label->sub_labels[i],
3273668ca4bSJeremy L Thompson                                               field_type, value); CeedChk(ierr);
328d8dd9a91SJeremy L Thompson       }
329d8dd9a91SJeremy L Thompson     }
330d8dd9a91SJeremy L Thompson   } else {
331d8dd9a91SJeremy L Thompson     if (!op->qf->ctx)
332d8dd9a91SJeremy L Thompson       // LCOV_EXCL_START
333d8dd9a91SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED,
334d8dd9a91SJeremy L Thompson                        "QFunction does not have context data");
335d8dd9a91SJeremy L Thompson     // LCOV_EXCL_STOP
336d8dd9a91SJeremy L Thompson 
3373668ca4bSJeremy L Thompson     ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label,
3383668ca4bSJeremy L Thompson                                           field_type, value); CeedChk(ierr);
339d8dd9a91SJeremy L Thompson   }
340d8dd9a91SJeremy L Thompson 
341d8dd9a91SJeremy L Thompson   return CEED_ERROR_SUCCESS;
342d8dd9a91SJeremy L Thompson }
343d8dd9a91SJeremy L Thompson 
3447a982d89SJeremy L. Thompson /// @}
3457a982d89SJeremy L. Thompson 
3467a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3477a982d89SJeremy L. Thompson /// CeedOperator Backend API
3487a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3497a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
3507a982d89SJeremy L. Thompson /// @{
3517a982d89SJeremy L. Thompson 
3527a982d89SJeremy L. Thompson /**
3537a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
3547a982d89SJeremy L. Thompson 
3557a982d89SJeremy L. Thompson   @param op             CeedOperator
356d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
3577a982d89SJeremy L. Thompson 
3587a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3597a982d89SJeremy L. Thompson 
3607a982d89SJeremy L. Thompson   @ref Backend
3617a982d89SJeremy L. Thompson **/
3627a982d89SJeremy L. Thompson 
363d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
364f04ea552SJeremy L Thompson   if (op->is_composite)
3657a982d89SJeremy L. Thompson     // LCOV_EXCL_START
366e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
367e15f9bd0SJeremy L Thompson                      "Not defined for composite operators");
3687a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3697a982d89SJeremy L. Thompson 
370d1d35e2fSjeremylt   *num_args = op->num_fields;
371e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3727a982d89SJeremy L. Thompson }
3737a982d89SJeremy L. Thompson 
3747a982d89SJeremy L. Thompson /**
3757a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
3767a982d89SJeremy L. Thompson 
3777a982d89SJeremy L. Thompson   @param op                  CeedOperator
378d1d35e2fSjeremylt   @param[out] is_setup_done  Variable to store setup status
3797a982d89SJeremy L. Thompson 
3807a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3817a982d89SJeremy L. Thompson 
3827a982d89SJeremy L. Thompson   @ref Backend
3837a982d89SJeremy L. Thompson **/
3847a982d89SJeremy L. Thompson 
385d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
386f04ea552SJeremy L Thompson   *is_setup_done = op->is_backend_setup;
387e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3887a982d89SJeremy L. Thompson }
3897a982d89SJeremy L. Thompson 
3907a982d89SJeremy L. Thompson /**
3917a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
3927a982d89SJeremy L. Thompson 
3937a982d89SJeremy L. Thompson   @param op       CeedOperator
3947a982d89SJeremy L. Thompson   @param[out] qf  Variable to store QFunction
3957a982d89SJeremy L. Thompson 
3967a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3977a982d89SJeremy L. Thompson 
3987a982d89SJeremy L. Thompson   @ref Backend
3997a982d89SJeremy L. Thompson **/
4007a982d89SJeremy L. Thompson 
4017a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
402f04ea552SJeremy L Thompson   if (op->is_composite)
4037a982d89SJeremy L. Thompson     // LCOV_EXCL_START
404e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
405e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
4067a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4077a982d89SJeremy L. Thompson 
4087a982d89SJeremy L. Thompson   *qf = op->qf;
409e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4107a982d89SJeremy L. Thompson }
4117a982d89SJeremy L. Thompson 
4127a982d89SJeremy L. Thompson /**
413c04a41a7SJeremy L Thompson   @brief Get a boolean value indicating if the CeedOperator is composite
414c04a41a7SJeremy L Thompson 
415c04a41a7SJeremy L Thompson   @param op                 CeedOperator
416d1d35e2fSjeremylt   @param[out] is_composite  Variable to store composite status
417c04a41a7SJeremy L Thompson 
418c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
419c04a41a7SJeremy L Thompson 
420c04a41a7SJeremy L Thompson   @ref Backend
421c04a41a7SJeremy L Thompson **/
422c04a41a7SJeremy L Thompson 
423d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
424f04ea552SJeremy L Thompson   *is_composite = op->is_composite;
425e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
426c04a41a7SJeremy L Thompson }
427c04a41a7SJeremy L Thompson 
428c04a41a7SJeremy L Thompson /**
429d1d35e2fSjeremylt   @brief Get the number of sub_operators associated with a CeedOperator
4307a982d89SJeremy L. Thompson 
4317a982d89SJeremy L. Thompson   @param op                     CeedOperator
432d1d35e2fSjeremylt   @param[out] num_suboperators  Variable to store number 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 CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
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   *num_suboperators = op->num_suboperators;
446e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4477a982d89SJeremy L. Thompson }
4487a982d89SJeremy L. Thompson 
4497a982d89SJeremy L. Thompson /**
450d1d35e2fSjeremylt   @brief Get the list of sub_operators associated with a CeedOperator
4517a982d89SJeremy L. Thompson 
4527a982d89SJeremy L. Thompson   @param op                  CeedOperator
453d1d35e2fSjeremylt   @param[out] sub_operators  Variable to store list of sub_operators
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 
460d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) {
461f04ea552SJeremy L Thompson   if (!op->is_composite)
4627a982d89SJeremy L. Thompson     // LCOV_EXCL_START
463e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4647a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4657a982d89SJeremy L. Thompson 
466d1d35e2fSjeremylt   *sub_operators = op->sub_operators;
467e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4687a982d89SJeremy L. Thompson }
4697a982d89SJeremy L. Thompson 
4707a982d89SJeremy L. Thompson /**
4717a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
4727a982d89SJeremy L. Thompson 
4737a982d89SJeremy L. Thompson   @param op         CeedOperator
4747a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
4757a982d89SJeremy L. Thompson 
4767a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4777a982d89SJeremy L. Thompson 
4787a982d89SJeremy L. Thompson   @ref Backend
4797a982d89SJeremy L. Thompson **/
4807a982d89SJeremy L. Thompson 
481777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
482777ff853SJeremy L Thompson   *(void **)data = op->data;
483e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4847a982d89SJeremy L. Thompson }
4857a982d89SJeremy L. Thompson 
4867a982d89SJeremy L. Thompson /**
4877a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
4887a982d89SJeremy L. Thompson 
4897a982d89SJeremy L. Thompson   @param[out] op  CeedOperator
4907a982d89SJeremy L. Thompson   @param data     Data to set
4917a982d89SJeremy L. Thompson 
4927a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4937a982d89SJeremy L. Thompson 
4947a982d89SJeremy L. Thompson   @ref Backend
4957a982d89SJeremy L. Thompson **/
4967a982d89SJeremy L. Thompson 
497777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
498777ff853SJeremy L Thompson   op->data = data;
499e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5007a982d89SJeremy L. Thompson }
5017a982d89SJeremy L. Thompson 
5027a982d89SJeremy L. Thompson /**
50334359f16Sjeremylt   @brief Increment the reference counter for a CeedOperator
50434359f16Sjeremylt 
50534359f16Sjeremylt   @param op  CeedOperator to increment the reference counter
50634359f16Sjeremylt 
50734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
50834359f16Sjeremylt 
50934359f16Sjeremylt   @ref Backend
51034359f16Sjeremylt **/
5119560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
51234359f16Sjeremylt   op->ref_count++;
51334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
51434359f16Sjeremylt }
51534359f16Sjeremylt 
51634359f16Sjeremylt /**
5177a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
5187a982d89SJeremy L. Thompson 
5197a982d89SJeremy L. Thompson   @param op  CeedOperator
5207a982d89SJeremy L. Thompson 
5217a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5227a982d89SJeremy L. Thompson 
5237a982d89SJeremy L. Thompson   @ref Backend
5247a982d89SJeremy L. Thompson **/
5257a982d89SJeremy L. Thompson 
5267a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
527f04ea552SJeremy L Thompson   op->is_backend_setup = true;
528e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5297a982d89SJeremy L. Thompson }
5307a982d89SJeremy L. Thompson 
5317a982d89SJeremy L. Thompson /// @}
5327a982d89SJeremy L. Thompson 
5337a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5347a982d89SJeremy L. Thompson /// CeedOperator Public API
5357a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5367a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
537dfdf5a53Sjeremylt /// @{
538d7b241e6Sjeremylt 
539d7b241e6Sjeremylt /**
5400219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
5410219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
5420219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
543d7b241e6Sjeremylt 
544b11c1e72Sjeremylt   @param ceed     A Ceed object where the CeedOperator will be created
545d7b241e6Sjeremylt   @param qf       QFunction defining the action of the operator at quadrature points
54634138859Sjeremylt   @param dqf      QFunction defining the action of the Jacobian of @a qf (or
5474cc79fe7SJed Brown                     @ref CEED_QFUNCTION_NONE)
548d7b241e6Sjeremylt   @param dqfT     QFunction defining the action of the transpose of the Jacobian
5494cc79fe7SJed Brown                     of @a qf (or @ref CEED_QFUNCTION_NONE)
550b11c1e72Sjeremylt   @param[out] op  Address of the variable where the newly created
551b11c1e72Sjeremylt                     CeedOperator will be stored
552b11c1e72Sjeremylt 
553b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
554dfdf5a53Sjeremylt 
5557a982d89SJeremy L. Thompson   @ref User
556d7b241e6Sjeremylt  */
557d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
558d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
559d7b241e6Sjeremylt   int ierr;
560d7b241e6Sjeremylt 
5615fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
5625fe0d4faSjeremylt     Ceed delegate;
563aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
5645fe0d4faSjeremylt 
5655fe0d4faSjeremylt     if (!delegate)
566c042f62fSJeremy L Thompson       // LCOV_EXCL_START
567e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
568e15f9bd0SJeremy L Thompson                        "Backend does not support OperatorCreate");
569c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5705fe0d4faSjeremylt 
5715fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
572e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5735fe0d4faSjeremylt   }
5745fe0d4faSjeremylt 
575b3b7035fSJeremy L Thompson   if (!qf || qf == CEED_QFUNCTION_NONE)
576b3b7035fSJeremy L Thompson     // LCOV_EXCL_START
577e15f9bd0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
578e15f9bd0SJeremy L Thompson                      "Operator must have a valid QFunction.");
579b3b7035fSJeremy L Thompson   // LCOV_EXCL_STOP
580d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
581d7b241e6Sjeremylt   (*op)->ceed = ceed;
5829560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
583d1d35e2fSjeremylt   (*op)->ref_count = 1;
584d7b241e6Sjeremylt   (*op)->qf = qf;
5852b104005SJeremy L Thompson   (*op)->input_size = -1;
5862b104005SJeremy L Thompson   (*op)->output_size = -1;
5879560d06aSjeremylt   ierr = CeedQFunctionReference(qf); CeedChk(ierr);
588442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
589d7b241e6Sjeremylt     (*op)->dqf = dqf;
5909560d06aSjeremylt     ierr = CeedQFunctionReference(dqf); CeedChk(ierr);
591442e7f0bSjeremylt   }
592442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
593d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
5949560d06aSjeremylt     ierr = CeedQFunctionReference(dqfT); CeedChk(ierr);
595442e7f0bSjeremylt   }
596480fae85SJeremy L Thompson   ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled);
597480fae85SJeremy L Thompson   CeedChk(ierr);
598bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr);
599bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr);
600d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
601e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
602d7b241e6Sjeremylt }
603d7b241e6Sjeremylt 
604d7b241e6Sjeremylt /**
60552d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
60652d6035fSJeremy L Thompson 
60752d6035fSJeremy L Thompson   @param ceed     A Ceed object where the CeedOperator will be created
60852d6035fSJeremy L Thompson   @param[out] op  Address of the variable where the newly created
60952d6035fSJeremy L Thompson                     Composite CeedOperator will be stored
61052d6035fSJeremy L Thompson 
61152d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
61252d6035fSJeremy L Thompson 
6137a982d89SJeremy L. Thompson   @ref User
61452d6035fSJeremy L Thompson  */
61552d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
61652d6035fSJeremy L Thompson   int ierr;
61752d6035fSJeremy L Thompson 
61852d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
61952d6035fSJeremy L Thompson     Ceed delegate;
620aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
62152d6035fSJeremy L Thompson 
622250756a7Sjeremylt     if (delegate) {
62352d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
624e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
62552d6035fSJeremy L Thompson     }
626250756a7Sjeremylt   }
62752d6035fSJeremy L Thompson 
62852d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
62952d6035fSJeremy L Thompson   (*op)->ceed = ceed;
6309560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
631f04ea552SJeremy L Thompson   (*op)->is_composite = true;
632bf4cb664SJeremy L Thompson   ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr);
6332b104005SJeremy L Thompson   (*op)->input_size = -1;
6342b104005SJeremy L Thompson   (*op)->output_size = -1;
635250756a7Sjeremylt 
636250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
63752d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
638250756a7Sjeremylt   }
639e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
64052d6035fSJeremy L Thompson }
64152d6035fSJeremy L Thompson 
64252d6035fSJeremy L Thompson /**
6439560d06aSjeremylt   @brief Copy the pointer to a CeedOperator. Both pointers should
6449560d06aSjeremylt            be destroyed with `CeedOperatorDestroy()`;
6459560d06aSjeremylt            Note: If `*op_copy` is non-NULL, then it is assumed that
6469560d06aSjeremylt            `*op_copy` is a pointer to a CeedOperator. This
6479560d06aSjeremylt            CeedOperator will be destroyed if `*op_copy` is the only
6489560d06aSjeremylt            reference to this CeedOperator.
6499560d06aSjeremylt 
6509560d06aSjeremylt   @param op            CeedOperator to copy reference to
6519560d06aSjeremylt   @param[out] op_copy  Variable to store copied reference
6529560d06aSjeremylt 
6539560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6549560d06aSjeremylt 
6559560d06aSjeremylt   @ref User
6569560d06aSjeremylt **/
6579560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
6589560d06aSjeremylt   int ierr;
6599560d06aSjeremylt 
6609560d06aSjeremylt   ierr = CeedOperatorReference(op); CeedChk(ierr);
6619560d06aSjeremylt   ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr);
6629560d06aSjeremylt   *op_copy = op;
6639560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6649560d06aSjeremylt }
6659560d06aSjeremylt 
6669560d06aSjeremylt /**
667b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
668d7b241e6Sjeremylt 
669d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
670d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
671d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
672d7b241e6Sjeremylt 
673d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
674d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
675979e564eSJames Wright   input CeedVector and at most one active output CeedVector passed to
676979e564eSJames Wright   CeedOperatorApply().
677d7b241e6Sjeremylt 
6788c91a0c9SJeremy L Thompson   @param op          CeedOperator on which to provide the field
679d1d35e2fSjeremylt   @param field_name  Name of the field (to be matched with the name used by
6808795c945Sjeremylt                        CeedQFunction)
681b11c1e72Sjeremylt   @param r           CeedElemRestriction
6824cc79fe7SJed Brown   @param b           CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED
683b11c1e72Sjeremylt                        if collocated with quadrature points
6844cc79fe7SJed Brown   @param v           CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE
6854cc79fe7SJed Brown                        if field is active or @ref CEED_VECTOR_NONE if using
6864cc79fe7SJed Brown                        @ref CEED_EVAL_WEIGHT in the QFunction
687b11c1e72Sjeremylt 
688b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
689dfdf5a53Sjeremylt 
6907a982d89SJeremy L. Thompson   @ref User
691b11c1e72Sjeremylt **/
692d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name,
693a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
694d7b241e6Sjeremylt   int ierr;
695f04ea552SJeremy L Thompson   if (op->is_composite)
696c042f62fSJeremy L Thompson     // LCOV_EXCL_START
697e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
698e15f9bd0SJeremy L Thompson                      "Cannot add field to composite operator.");
699c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
700f04ea552SJeremy L Thompson   if (op->is_immutable)
701f04ea552SJeremy L Thompson     // LCOV_EXCL_START
702f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
703f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
704f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
7058b067b84SJed Brown   if (!r)
706c042f62fSJeremy L Thompson     // LCOV_EXCL_START
707e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
708c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
709d1d35e2fSjeremylt                      field_name);
710c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
7118b067b84SJed Brown   if (!b)
712c042f62fSJeremy L Thompson     // LCOV_EXCL_START
713e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
714e15f9bd0SJeremy L Thompson                      "Basis b for field \"%s\" must be non-NULL.",
715d1d35e2fSjeremylt                      field_name);
716c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
7178b067b84SJed Brown   if (!v)
718c042f62fSJeremy L Thompson     // LCOV_EXCL_START
719e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
720e15f9bd0SJeremy L Thompson                      "Vector v for field \"%s\" must be non-NULL.",
721d1d35e2fSjeremylt                      field_name);
722c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
72352d6035fSJeremy L Thompson 
724d1d35e2fSjeremylt   CeedInt num_elem;
725d1d35e2fSjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr);
726d1d35e2fSjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction &&
727d1d35e2fSjeremylt       op->num_elem != num_elem)
728c042f62fSJeremy L Thompson     // LCOV_EXCL_START
729e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_DIMENSION,
730*990fdeb6SJeremy L Thompson                      "ElemRestriction with %" CeedInt_FMT " elements incompatible with prior "
731*990fdeb6SJeremy L Thompson                      CeedInt_FMT " elements", num_elem, op->num_elem);
732c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
733d7b241e6Sjeremylt 
73478464608Sjeremylt   CeedInt num_qpts = 0;
735e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
736d1d35e2fSjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr);
737d1d35e2fSjeremylt     if (op->num_qpts && op->num_qpts != num_qpts)
738c042f62fSJeremy L Thompson       // LCOV_EXCL_START
739e15f9bd0SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_DIMENSION,
740*990fdeb6SJeremy L Thompson                        "Basis with %" CeedInt_FMT " quadrature points "
741*990fdeb6SJeremy L Thompson                        "incompatible with prior %" CeedInt_FMT " points", num_qpts,
742d1d35e2fSjeremylt                        op->num_qpts);
743c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
744d7b241e6Sjeremylt   }
745d1d35e2fSjeremylt   CeedQFunctionField qf_field;
746d1d35e2fSjeremylt   CeedOperatorField *op_field;
7472b104005SJeremy L Thompson   bool is_input = true;
748d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
749d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) {
750d1d35e2fSjeremylt       qf_field = op->qf->input_fields[i];
751d1d35e2fSjeremylt       op_field = &op->input_fields[i];
752d7b241e6Sjeremylt       goto found;
753d7b241e6Sjeremylt     }
754d7b241e6Sjeremylt   }
7552b104005SJeremy L Thompson   is_input = false;
756d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
757d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) {
758d1d35e2fSjeremylt       qf_field = op->qf->output_fields[i];
759d1d35e2fSjeremylt       op_field = &op->output_fields[i];
760d7b241e6Sjeremylt       goto found;
761d7b241e6Sjeremylt     }
762d7b241e6Sjeremylt   }
763c042f62fSJeremy L Thompson   // LCOV_EXCL_START
764e15f9bd0SJeremy L Thompson   return CeedError(op->ceed, CEED_ERROR_INCOMPLETE,
765e15f9bd0SJeremy L Thompson                    "QFunction has no knowledge of field '%s'",
766d1d35e2fSjeremylt                    field_name);
767c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
768d7b241e6Sjeremylt found:
769d1d35e2fSjeremylt   ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr);
770d1d35e2fSjeremylt   ierr = CeedCalloc(1, op_field); CeedChk(ierr);
771e15f9bd0SJeremy L Thompson 
7722b104005SJeremy L Thompson   if (v == CEED_VECTOR_ACTIVE) {
7732b104005SJeremy L Thompson     CeedSize l_size;
7742b104005SJeremy L Thompson     ierr = CeedElemRestrictionGetLVectorSize(r, &l_size); CeedChk(ierr);
7752b104005SJeremy L Thompson     if (is_input) {
7762b104005SJeremy L Thompson       if (op->input_size == -1) op->input_size = l_size;
7772b104005SJeremy L Thompson       if (l_size != op->input_size)
7782b104005SJeremy L Thompson         // LCOV_EXCL_START
7792b104005SJeremy L Thompson         return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
7802b104005SJeremy L Thompson                          "LVector size %td does not match previous size %td",
7812b104005SJeremy L Thompson                          l_size, op->input_size);
7822b104005SJeremy L Thompson       // LCOV_EXCL_STOP
7832b104005SJeremy L Thompson     } else {
7842b104005SJeremy L Thompson       if (op->output_size == -1) op->output_size = l_size;
7852b104005SJeremy L Thompson       if (l_size != op->output_size)
7862b104005SJeremy L Thompson         // LCOV_EXCL_START
7872b104005SJeremy L Thompson         return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
7882b104005SJeremy L Thompson                          "LVector size %td does not match previous size %td",
7892b104005SJeremy L Thompson                          l_size, op->output_size);
7902b104005SJeremy L Thompson       // LCOV_EXCL_STOP
7912b104005SJeremy L Thompson     }
7922b104005SJeremy L Thompson   }
7932b104005SJeremy L Thompson 
794d1d35e2fSjeremylt   (*op_field)->vec = v;
795e15f9bd0SJeremy L Thompson   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) {
7969560d06aSjeremylt     ierr = CeedVectorReference(v); CeedChk(ierr);
797e15f9bd0SJeremy L Thompson   }
798e15f9bd0SJeremy L Thompson 
799d1d35e2fSjeremylt   (*op_field)->elem_restr = r;
8009560d06aSjeremylt   ierr = CeedElemRestrictionReference(r); CeedChk(ierr);
801e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
802d1d35e2fSjeremylt     op->num_elem = num_elem;
803d1d35e2fSjeremylt     op->has_restriction = true; // Restriction set, but num_elem may be 0
804e15f9bd0SJeremy L Thompson   }
805d99fa3c5SJeremy L Thompson 
806d1d35e2fSjeremylt   (*op_field)->basis = b;
807e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
808cd4dfc48Sjeremylt     if (!op->num_qpts) {
809cd4dfc48Sjeremylt       ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr);
810cd4dfc48Sjeremylt     }
8119560d06aSjeremylt     ierr = CeedBasisReference(b); CeedChk(ierr);
812e15f9bd0SJeremy L Thompson   }
813e15f9bd0SJeremy L Thompson 
814d1d35e2fSjeremylt   op->num_fields += 1;
815f7e22acaSJeremy L Thompson   ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name);
816f7e22acaSJeremy L Thompson   CeedChk(ierr);
817e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
818d7b241e6Sjeremylt }
819d7b241e6Sjeremylt 
820d7b241e6Sjeremylt /**
82143bbe138SJeremy L Thompson   @brief Get the CeedOperatorFields of a CeedOperator
82243bbe138SJeremy L Thompson 
823f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
824f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
825f04ea552SJeremy L Thompson 
82643bbe138SJeremy L Thompson   @param op                      CeedOperator
827f74ec584SJeremy L Thompson   @param[out] num_input_fields   Variable to store number of input fields
82843bbe138SJeremy L Thompson   @param[out] input_fields       Variable to store input_fields
829f74ec584SJeremy L Thompson   @param[out] num_output_fields  Variable to store number of output fields
83043bbe138SJeremy L Thompson   @param[out] output_fields      Variable to store output_fields
83143bbe138SJeremy L Thompson 
83243bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83343bbe138SJeremy L Thompson 
834e9b533fbSJeremy L Thompson   @ref Advanced
83543bbe138SJeremy L Thompson **/
83643bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields,
83743bbe138SJeremy L Thompson                           CeedOperatorField **input_fields,
83843bbe138SJeremy L Thompson                           CeedInt *num_output_fields,
83943bbe138SJeremy L Thompson                           CeedOperatorField **output_fields) {
840f04ea552SJeremy L Thompson   int ierr;
841f04ea552SJeremy L Thompson 
842f04ea552SJeremy L Thompson   if (op->is_composite)
84343bbe138SJeremy L Thompson     // LCOV_EXCL_START
84443bbe138SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
84543bbe138SJeremy L Thompson                      "Not defined for composite operator");
84643bbe138SJeremy L Thompson   // LCOV_EXCL_STOP
847f04ea552SJeremy L Thompson   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
84843bbe138SJeremy L Thompson 
84943bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = op->qf->num_input_fields;
85043bbe138SJeremy L Thompson   if (input_fields) *input_fields = op->input_fields;
85143bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = op->qf->num_output_fields;
85243bbe138SJeremy L Thompson   if (output_fields) *output_fields = op->output_fields;
85343bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
85443bbe138SJeremy L Thompson }
85543bbe138SJeremy L Thompson 
85643bbe138SJeremy L Thompson /**
85728567f8fSJeremy L Thompson   @brief Get the name of a CeedOperatorField
85828567f8fSJeremy L Thompson 
85928567f8fSJeremy L Thompson   @param op_field         CeedOperatorField
86028567f8fSJeremy L Thompson   @param[out] field_name  Variable to store the field name
86128567f8fSJeremy L Thompson 
86228567f8fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
86328567f8fSJeremy L Thompson 
864e9b533fbSJeremy L Thompson   @ref Advanced
86528567f8fSJeremy L Thompson **/
86628567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) {
86728567f8fSJeremy L Thompson   *field_name = (char *)op_field->field_name;
86828567f8fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
86928567f8fSJeremy L Thompson }
87028567f8fSJeremy L Thompson 
87128567f8fSJeremy L Thompson /**
87243bbe138SJeremy L Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
87343bbe138SJeremy L Thompson 
87443bbe138SJeremy L Thompson   @param op_field   CeedOperatorField
87543bbe138SJeremy L Thompson   @param[out] rstr  Variable to store CeedElemRestriction
87643bbe138SJeremy L Thompson 
87743bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
87843bbe138SJeremy L Thompson 
879e9b533fbSJeremy L Thompson   @ref Advanced
88043bbe138SJeremy L Thompson **/
88143bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,
88243bbe138SJeremy L Thompson                                         CeedElemRestriction *rstr) {
88343bbe138SJeremy L Thompson   *rstr = op_field->elem_restr;
88443bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
88543bbe138SJeremy L Thompson }
88643bbe138SJeremy L Thompson 
88743bbe138SJeremy L Thompson /**
88843bbe138SJeremy L Thompson   @brief Get the CeedBasis of a CeedOperatorField
88943bbe138SJeremy L Thompson 
89043bbe138SJeremy L Thompson   @param op_field    CeedOperatorField
89143bbe138SJeremy L Thompson   @param[out] basis  Variable to store CeedBasis
89243bbe138SJeremy L Thompson 
89343bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
89443bbe138SJeremy L Thompson 
895e9b533fbSJeremy L Thompson   @ref Advanced
89643bbe138SJeremy L Thompson **/
89743bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
89843bbe138SJeremy L Thompson   *basis = op_field->basis;
89943bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
90043bbe138SJeremy L Thompson }
90143bbe138SJeremy L Thompson 
90243bbe138SJeremy L Thompson /**
90343bbe138SJeremy L Thompson   @brief Get the CeedVector of a CeedOperatorField
90443bbe138SJeremy L Thompson 
90543bbe138SJeremy L Thompson   @param op_field  CeedOperatorField
90643bbe138SJeremy L Thompson   @param[out] vec  Variable to store CeedVector
90743bbe138SJeremy L Thompson 
90843bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
90943bbe138SJeremy L Thompson 
910e9b533fbSJeremy L Thompson   @ref Advanced
91143bbe138SJeremy L Thompson **/
91243bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
91343bbe138SJeremy L Thompson   *vec = op_field->vec;
91443bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
91543bbe138SJeremy L Thompson }
91643bbe138SJeremy L Thompson 
91743bbe138SJeremy L Thompson /**
91852d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
919288c0443SJeremy L Thompson 
920d1d35e2fSjeremylt   @param[out] composite_op  Composite CeedOperator
921d1d35e2fSjeremylt   @param      sub_op        Sub-operator CeedOperator
92252d6035fSJeremy L Thompson 
92352d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
92452d6035fSJeremy L Thompson 
9257a982d89SJeremy L. Thompson   @ref User
92652d6035fSJeremy L Thompson  */
927d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op,
928d1d35e2fSjeremylt                                 CeedOperator sub_op) {
92934359f16Sjeremylt   int ierr;
93034359f16Sjeremylt 
931f04ea552SJeremy L Thompson   if (!composite_op->is_composite)
932c042f62fSJeremy L Thompson     // LCOV_EXCL_START
933d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_MINOR,
934e2f04181SAndrew T. Barker                      "CeedOperator is not a composite operator");
935c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
93652d6035fSJeremy L Thompson 
937d1d35e2fSjeremylt   if (composite_op->num_suboperators == CEED_COMPOSITE_MAX)
938c042f62fSJeremy L Thompson     // LCOV_EXCL_START
939d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED,
9402b104005SJeremy L Thompson                      "Cannot add additional sub-operators");
941c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
942f04ea552SJeremy L Thompson   if (composite_op->is_immutable)
943f04ea552SJeremy L Thompson     // LCOV_EXCL_START
944f04ea552SJeremy L Thompson     return CeedError(composite_op->ceed, CEED_ERROR_MAJOR,
945f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
946f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
94752d6035fSJeremy L Thompson 
9482b104005SJeremy L Thompson   {
9492b104005SJeremy L Thompson     CeedSize input_size, output_size;
9502b104005SJeremy L Thompson     ierr = CeedOperatorGetActiveVectorLengths(sub_op, &input_size, &output_size);
9512b104005SJeremy L Thompson     CeedChk(ierr);
9522b104005SJeremy L Thompson     if (composite_op->input_size == -1) composite_op->input_size = input_size;
9532b104005SJeremy L Thompson     if (composite_op->output_size == -1) composite_op->output_size = output_size;
9542b104005SJeremy L Thompson     // Note, a size of -1 means no active vector restriction set, so no incompatibility
9552b104005SJeremy L Thompson     if ((input_size != -1 && input_size != composite_op->input_size) ||
9562b104005SJeremy L Thompson         (output_size != -1 && output_size != composite_op->output_size))
9572b104005SJeremy L Thompson       // LCOV_EXCL_START
9582b104005SJeremy L Thompson       return CeedError(composite_op->ceed, CEED_ERROR_MAJOR,
9592b104005SJeremy L Thompson                        "Sub-operators must have compatible dimensions; "
9602b104005SJeremy L Thompson                        "composite operator of shape (%td, %td) not compatible with "
9612b104005SJeremy L Thompson                        "sub-operator of shape (%td, %td)",
9622b104005SJeremy L Thompson                        composite_op->input_size, composite_op->output_size, input_size, output_size);
9632b104005SJeremy L Thompson     // LCOV_EXCL_STOP
9642b104005SJeremy L Thompson   }
9652b104005SJeremy L Thompson 
966d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
9679560d06aSjeremylt   ierr = CeedOperatorReference(sub_op); CeedChk(ierr);
968d1d35e2fSjeremylt   composite_op->num_suboperators++;
969e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
97052d6035fSJeremy L Thompson }
97152d6035fSJeremy L Thompson 
97252d6035fSJeremy L Thompson /**
9734db537f9SJeremy L Thompson   @brief Check if a CeedOperator is ready to be used.
9744db537f9SJeremy L Thompson 
9754db537f9SJeremy L Thompson   @param[in] op  CeedOperator to check
9764db537f9SJeremy L Thompson 
9774db537f9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9784db537f9SJeremy L Thompson 
9794db537f9SJeremy L Thompson   @ref User
9804db537f9SJeremy L Thompson **/
9814db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
9824db537f9SJeremy L Thompson   int ierr;
9834db537f9SJeremy L Thompson   Ceed ceed;
9844db537f9SJeremy L Thompson   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
9854db537f9SJeremy L Thompson 
9864db537f9SJeremy L Thompson   if (op->is_interface_setup)
9874db537f9SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9884db537f9SJeremy L Thompson 
9894db537f9SJeremy L Thompson   CeedQFunction qf = op->qf;
9904db537f9SJeremy L Thompson   if (op->is_composite) {
9914db537f9SJeremy L Thompson     if (!op->num_suboperators)
9924db537f9SJeremy L Thompson       // LCOV_EXCL_START
9934db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set");
9944db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
9954db537f9SJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
9964db537f9SJeremy L Thompson       ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr);
9974db537f9SJeremy L Thompson     }
9982b104005SJeremy L Thompson     // Sub-operators could be modified after adding to composite operator
9992b104005SJeremy L Thompson     // Need to verify no lvec incompatibility from any changes
10002b104005SJeremy L Thompson     CeedSize input_size, output_size;
10012b104005SJeremy L Thompson     ierr = CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size);
10022b104005SJeremy L Thompson     CeedChk(ierr);
10034db537f9SJeremy L Thompson   } else {
10044db537f9SJeremy L Thompson     if (op->num_fields == 0)
10054db537f9SJeremy L Thompson       // LCOV_EXCL_START
10064db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set");
10074db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
10084db537f9SJeremy L Thompson     if (op->num_fields < qf->num_input_fields + qf->num_output_fields)
10094db537f9SJeremy L Thompson       // LCOV_EXCL_START
10104db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set");
10114db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
10124db537f9SJeremy L Thompson     if (!op->has_restriction)
10134db537f9SJeremy L Thompson       // LCOV_EXCL_START
10144db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
10154db537f9SJeremy L Thompson                        "At least one restriction required");
10164db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
10174db537f9SJeremy L Thompson     if (op->num_qpts == 0)
10184db537f9SJeremy L Thompson       // LCOV_EXCL_START
10194db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
10204db537f9SJeremy L Thompson                        "At least one non-collocated basis is required "
10214db537f9SJeremy L Thompson                        "or the number of quadrature points must be set");
10224db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
10234db537f9SJeremy L Thompson   }
10244db537f9SJeremy L Thompson 
10254db537f9SJeremy L Thompson   // Flag as immutable and ready
10264db537f9SJeremy L Thompson   op->is_interface_setup = true;
10274db537f9SJeremy L Thompson   if (op->qf && op->qf != CEED_QFUNCTION_NONE)
10284db537f9SJeremy L Thompson     // LCOV_EXCL_START
10294db537f9SJeremy L Thompson     op->qf->is_immutable = true;
10304db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
10314db537f9SJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE)
10324db537f9SJeremy L Thompson     // LCOV_EXCL_START
10334db537f9SJeremy L Thompson     op->dqf->is_immutable = true;
10344db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
10354db537f9SJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE)
10364db537f9SJeremy L Thompson     // LCOV_EXCL_START
10374db537f9SJeremy L Thompson     op->dqfT->is_immutable = true;
10384db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
10394db537f9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10404db537f9SJeremy L Thompson }
10414db537f9SJeremy L Thompson 
10424db537f9SJeremy L Thompson /**
1043c9366a6bSJeremy L Thompson   @brief Get vector lengths for the active input and/or output vectors of a CeedOperator.
1044c9366a6bSJeremy L Thompson            Note: Lengths of -1 indicate that the CeedOperator does not have an
1045c9366a6bSJeremy L Thompson            active input and/or output.
1046c9366a6bSJeremy L Thompson 
1047c9366a6bSJeremy L Thompson   @param[in] op           CeedOperator
1048c9366a6bSJeremy L Thompson   @param[out] input_size  Variable to store active input vector length, or NULL
1049c9366a6bSJeremy L Thompson   @param[out] output_size Variable to store active output vector length, or NULL
1050c9366a6bSJeremy L Thompson 
1051c9366a6bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1052c9366a6bSJeremy L Thompson 
1053c9366a6bSJeremy L Thompson   @ref User
1054c9366a6bSJeremy L Thompson **/
1055c9366a6bSJeremy L Thompson int CeedOperatorGetActiveVectorLengths(CeedOperator op, CeedSize *input_size,
1056c9366a6bSJeremy L Thompson                                        CeedSize *output_size) {
1057c9366a6bSJeremy L Thompson   int ierr;
1058c9366a6bSJeremy L Thompson   bool is_composite;
1059c9366a6bSJeremy L Thompson 
10602b104005SJeremy L Thompson   if (input_size) *input_size = op->input_size;
10612b104005SJeremy L Thompson   if (output_size) *output_size = op->output_size;
1062c9366a6bSJeremy L Thompson 
1063c9366a6bSJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
10642b104005SJeremy L Thompson   if (is_composite && (op->input_size == -1 || op->output_size == -1)) {
1065c9366a6bSJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
1066c9366a6bSJeremy L Thompson       CeedSize sub_input_size, sub_output_size;
1067c9366a6bSJeremy L Thompson       ierr = CeedOperatorGetActiveVectorLengths(op->sub_operators[i],
10682b104005SJeremy L Thompson              &sub_input_size, &sub_output_size); CeedChk(ierr);
10692b104005SJeremy L Thompson       if (op->input_size == -1) op->input_size = sub_input_size;
10702b104005SJeremy L Thompson       if (op->output_size == -1) op->output_size = sub_output_size;
10712b104005SJeremy L Thompson       // Note, a size of -1 means no active vector restriction set, so no incompatibility
10722b104005SJeremy L Thompson       if ((sub_input_size != -1 && sub_input_size != op->input_size) ||
10732b104005SJeremy L Thompson           (sub_output_size != -1 && sub_output_size != op->output_size))
10742b104005SJeremy L Thompson         // LCOV_EXCL_START
10752b104005SJeremy L Thompson         return CeedError(op->ceed, CEED_ERROR_MAJOR,
10762b104005SJeremy L Thompson                          "Sub-operators must have compatible dimensions; "
10772b104005SJeremy L Thompson                          "composite operator of shape (%td, %td) not compatible with "
10782b104005SJeremy L Thompson                          "sub-operator of shape (%td, %td)",
10792b104005SJeremy L Thompson                          op->input_size, op->output_size, input_size, output_size);
10802b104005SJeremy L Thompson       // LCOV_EXCL_STOP
1081c9366a6bSJeremy L Thompson     }
1082c9366a6bSJeremy L Thompson   }
1083c9366a6bSJeremy L Thompson 
1084c9366a6bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1085c9366a6bSJeremy L Thompson }
1086c9366a6bSJeremy L Thompson 
1087c9366a6bSJeremy L Thompson /**
1088beecbf24SJeremy L Thompson   @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions.
1089beecbf24SJeremy L Thompson            When `reuse_assembly_data = false` (default), the CeedQFunction associated
1090beecbf24SJeremy L Thompson            with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*`
1091beecbf24SJeremy L Thompson            function is called.
1092beecbf24SJeremy L Thompson            When `reuse_assembly_data = true`, the CeedQFunction associated with
1093beecbf24SJeremy L Thompson            this CeedOperator is reused between calls to
1094beecbf24SJeremy L Thompson            `CeedOperatorSetQFunctionAssemblyDataUpdated`.
10958b919e6bSJeremy L Thompson 
1096beecbf24SJeremy L Thompson   @param[in] op                  CeedOperator
1097beecbf24SJeremy L Thompson   @param[in] reuse_assembly_data Boolean flag setting assembly data reuse
10988b919e6bSJeremy L Thompson 
10998b919e6bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
11008b919e6bSJeremy L Thompson 
11018b919e6bSJeremy L Thompson   @ref Advanced
11028b919e6bSJeremy L Thompson **/
1103beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op,
1104beecbf24SJeremy L Thompson     bool reuse_assembly_data) {
11058b919e6bSJeremy L Thompson   int ierr;
11068b919e6bSJeremy L Thompson   bool is_composite;
11078b919e6bSJeremy L Thompson 
11088b919e6bSJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
11098b919e6bSJeremy L Thompson   if (is_composite) {
11108b919e6bSJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
1111beecbf24SJeremy L Thompson       ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i],
1112beecbf24SJeremy L Thompson              reuse_assembly_data); CeedChk(ierr);
11138b919e6bSJeremy L Thompson     }
11148b919e6bSJeremy L Thompson   } else {
1115beecbf24SJeremy L Thompson     ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data);
1116beecbf24SJeremy L Thompson     CeedChk(ierr);
1117beecbf24SJeremy L Thompson   }
1118beecbf24SJeremy L Thompson 
1119beecbf24SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1120beecbf24SJeremy L Thompson }
1121beecbf24SJeremy L Thompson 
1122beecbf24SJeremy L Thompson /**
1123beecbf24SJeremy L Thompson   @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly.
1124beecbf24SJeremy L Thompson 
1125beecbf24SJeremy L Thompson   @param[in] op                CeedOperator
11266e15d496SJeremy L Thompson   @param[in] needs_data_update Boolean flag setting assembly data reuse
1127beecbf24SJeremy L Thompson 
1128beecbf24SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1129beecbf24SJeremy L Thompson 
1130beecbf24SJeremy L Thompson   @ref Advanced
1131beecbf24SJeremy L Thompson **/
1132beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op,
1133beecbf24SJeremy L Thompson     bool needs_data_update) {
1134beecbf24SJeremy L Thompson   int ierr;
1135beecbf24SJeremy L Thompson   bool is_composite;
1136beecbf24SJeremy L Thompson 
1137beecbf24SJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
1138beecbf24SJeremy L Thompson   if (is_composite) {
1139beecbf24SJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
1140beecbf24SJeremy L Thompson       ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i],
1141beecbf24SJeremy L Thompson              needs_data_update); CeedChk(ierr);
1142beecbf24SJeremy L Thompson     }
1143beecbf24SJeremy L Thompson   } else {
1144beecbf24SJeremy L Thompson     ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled,
1145beecbf24SJeremy L Thompson            needs_data_update);
11468b919e6bSJeremy L Thompson     CeedChk(ierr);
11478b919e6bSJeremy L Thompson   }
11488b919e6bSJeremy L Thompson 
11498b919e6bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
11508b919e6bSJeremy L Thompson }
11518b919e6bSJeremy L Thompson 
11528b919e6bSJeremy L Thompson /**
1153cd4dfc48Sjeremylt   @brief Set the number of quadrature points associated with a CeedOperator.
1154cd4dfc48Sjeremylt            This should be used when creating a CeedOperator where every
1155cd4dfc48Sjeremylt            field has a collocated basis. This function cannot be used for
1156cd4dfc48Sjeremylt            composite CeedOperators.
1157cd4dfc48Sjeremylt 
1158cd4dfc48Sjeremylt   @param op        CeedOperator
1159cd4dfc48Sjeremylt   @param num_qpts  Number of quadrature points to set
1160cd4dfc48Sjeremylt 
1161cd4dfc48Sjeremylt   @return An error code: 0 - success, otherwise - failure
1162cd4dfc48Sjeremylt 
1163e9b533fbSJeremy L Thompson   @ref Advanced
1164cd4dfc48Sjeremylt **/
1165cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) {
1166f04ea552SJeremy L Thompson   if (op->is_composite)
1167cd4dfc48Sjeremylt     // LCOV_EXCL_START
1168cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
1169cd4dfc48Sjeremylt                      "Not defined for composite operator");
1170cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
1171cd4dfc48Sjeremylt   if (op->num_qpts)
1172cd4dfc48Sjeremylt     // LCOV_EXCL_START
1173cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
1174cd4dfc48Sjeremylt                      "Number of quadrature points already defined");
1175cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
1176f04ea552SJeremy L Thompson   if (op->is_immutable)
1177f04ea552SJeremy L Thompson     // LCOV_EXCL_START
1178f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
1179f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
1180f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
1181cd4dfc48Sjeremylt 
1182cd4dfc48Sjeremylt   op->num_qpts = num_qpts;
1183cd4dfc48Sjeremylt   return CEED_ERROR_SUCCESS;
1184cd4dfc48Sjeremylt }
1185cd4dfc48Sjeremylt 
1186cd4dfc48Sjeremylt /**
1187ea6b5821SJeremy L Thompson   @brief Set name of CeedOperator for CeedOperatorView output
1188ea6b5821SJeremy L Thompson 
1189ea6b5821SJeremy L Thompson   @param op    CeedOperator
1190ea6b5821SJeremy L Thompson   @param name  Name to set, or NULL to remove previously set name
1191ea6b5821SJeremy L Thompson 
1192ea6b5821SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1193ea6b5821SJeremy L Thompson 
1194ea6b5821SJeremy L Thompson   @ref User
1195ea6b5821SJeremy L Thompson **/
1196ea6b5821SJeremy L Thompson int CeedOperatorSetName(CeedOperator op, const char *name) {
1197ea6b5821SJeremy L Thompson   int ierr;
1198ea6b5821SJeremy L Thompson   char *name_copy;
1199ea6b5821SJeremy L Thompson   size_t name_len = name ? strlen(name) : 0;
1200ea6b5821SJeremy L Thompson 
1201ea6b5821SJeremy L Thompson   ierr = CeedFree(&op->name); CeedChk(ierr);
1202ea6b5821SJeremy L Thompson   if (name_len > 0) {
1203ea6b5821SJeremy L Thompson     ierr = CeedCalloc(name_len + 1, &name_copy); CeedChk(ierr);
1204ea6b5821SJeremy L Thompson     memcpy(name_copy, name, name_len);
1205ea6b5821SJeremy L Thompson     op->name = name_copy;
1206ea6b5821SJeremy L Thompson   }
1207ea6b5821SJeremy L Thompson 
1208ea6b5821SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1209ea6b5821SJeremy L Thompson }
1210ea6b5821SJeremy L Thompson 
1211ea6b5821SJeremy L Thompson /**
12127a982d89SJeremy L. Thompson   @brief View a CeedOperator
12137a982d89SJeremy L. Thompson 
12147a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
12157a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
12167a982d89SJeremy L. Thompson 
12177a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
12187a982d89SJeremy L. Thompson 
12197a982d89SJeremy L. Thompson   @ref User
12207a982d89SJeremy L. Thompson **/
12217a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
12227a982d89SJeremy L. Thompson   int ierr;
1223ea6b5821SJeremy L Thompson   bool has_name = op->name;
12247a982d89SJeremy L. Thompson 
1225f04ea552SJeremy L Thompson   if (op->is_composite) {
1226ea6b5821SJeremy L Thompson     fprintf(stream, "Composite CeedOperator%s%s\n",
1227ea6b5821SJeremy L Thompson             has_name ? " - " : "", has_name ? op->name : "");
12287a982d89SJeremy L. Thompson 
1229d1d35e2fSjeremylt     for (CeedInt i=0; i<op->num_suboperators; i++) {
1230ea6b5821SJeremy L Thompson       has_name = op->sub_operators[i]->name;
1231*990fdeb6SJeremy L Thompson       fprintf(stream, "  SubOperator %" CeedInt_FMT "%s%s:\n", i,
1232ea6b5821SJeremy L Thompson               has_name ? " - " : "",
1233ea6b5821SJeremy L Thompson               has_name ? op->sub_operators[i]->name : "");
1234d1d35e2fSjeremylt       ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream);
12357a982d89SJeremy L. Thompson       CeedChk(ierr);
12367a982d89SJeremy L. Thompson     }
12377a982d89SJeremy L. Thompson   } else {
1238ea6b5821SJeremy L Thompson     fprintf(stream, "CeedOperator%s%s\n",
1239ea6b5821SJeremy L Thompson             has_name ? " - " : "", has_name ? op->name : "");
12407a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
12417a982d89SJeremy L. Thompson   }
1242e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12437a982d89SJeremy L. Thompson }
12443bd813ffSjeremylt 
12453bd813ffSjeremylt /**
1246b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedOperator
1247b7c9bbdaSJeremy L Thompson 
1248b7c9bbdaSJeremy L Thompson   @param op         CeedOperator
1249b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
1250b7c9bbdaSJeremy L Thompson 
1251b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1252b7c9bbdaSJeremy L Thompson 
1253b7c9bbdaSJeremy L Thompson   @ref Advanced
1254b7c9bbdaSJeremy L Thompson **/
1255b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
1256b7c9bbdaSJeremy L Thompson   *ceed = op->ceed;
1257b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1258b7c9bbdaSJeremy L Thompson }
1259b7c9bbdaSJeremy L Thompson 
1260b7c9bbdaSJeremy L Thompson /**
1261b7c9bbdaSJeremy L Thompson   @brief Get the number of elements associated with a CeedOperator
1262b7c9bbdaSJeremy L Thompson 
1263b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1264b7c9bbdaSJeremy L Thompson   @param[out] num_elem  Variable to store number of elements
1265b7c9bbdaSJeremy L Thompson 
1266b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1267b7c9bbdaSJeremy L Thompson 
1268b7c9bbdaSJeremy L Thompson   @ref Advanced
1269b7c9bbdaSJeremy L Thompson **/
1270b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
1271b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1272b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1273b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1274b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1275b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1276b7c9bbdaSJeremy L Thompson 
1277b7c9bbdaSJeremy L Thompson   *num_elem = op->num_elem;
1278b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1279b7c9bbdaSJeremy L Thompson }
1280b7c9bbdaSJeremy L Thompson 
1281b7c9bbdaSJeremy L Thompson /**
1282b7c9bbdaSJeremy L Thompson   @brief Get the number of quadrature points associated with a CeedOperator
1283b7c9bbdaSJeremy L Thompson 
1284b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1285b7c9bbdaSJeremy L Thompson   @param[out] num_qpts  Variable to store vector number of quadrature points
1286b7c9bbdaSJeremy L Thompson 
1287b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1288b7c9bbdaSJeremy L Thompson 
1289b7c9bbdaSJeremy L Thompson   @ref Advanced
1290b7c9bbdaSJeremy L Thompson **/
1291b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
1292b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1293b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1294b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1295b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1296b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1297b7c9bbdaSJeremy L Thompson 
1298b7c9bbdaSJeremy L Thompson   *num_qpts = op->num_qpts;
1299b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1300b7c9bbdaSJeremy L Thompson }
1301b7c9bbdaSJeremy L Thompson 
1302b7c9bbdaSJeremy L Thompson /**
13036e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedOperator on the active vector
13046e15d496SJeremy L Thompson 
13056e15d496SJeremy L Thompson   @param op    Operator to estimate FLOPs for
13066e15d496SJeremy L Thompson   @param flops Address of variable to hold FLOPs estimate
13076e15d496SJeremy L Thompson 
13086e15d496SJeremy L Thompson   @ref Backend
13096e15d496SJeremy L Thompson **/
13109d36ca50SJeremy L Thompson int CeedOperatorGetFlopsEstimate(CeedOperator op, CeedSize *flops) {
13116e15d496SJeremy L Thompson   int ierr;
13126e15d496SJeremy L Thompson   bool is_composite;
13136e15d496SJeremy L Thompson   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
13146e15d496SJeremy L Thompson 
13156e15d496SJeremy L Thompson   *flops = 0;
13166e15d496SJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
13176e15d496SJeremy L Thompson   if (is_composite) {
13186e15d496SJeremy L Thompson     CeedInt num_suboperators;
13196e15d496SJeremy L Thompson     ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
13206e15d496SJeremy L Thompson     CeedOperator *sub_operators;
13216e15d496SJeremy L Thompson     ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
13226e15d496SJeremy L Thompson 
13236e15d496SJeremy L Thompson     // FLOPs for each suboperator
13246e15d496SJeremy L Thompson     for (CeedInt i = 0; i < num_suboperators; i++) {
13259d36ca50SJeremy L Thompson       CeedSize suboperator_flops;
13266e15d496SJeremy L Thompson       ierr = CeedOperatorGetFlopsEstimate(sub_operators[i], &suboperator_flops);
13276e15d496SJeremy L Thompson       CeedChk(ierr);
13286e15d496SJeremy L Thompson       *flops += suboperator_flops;
13296e15d496SJeremy L Thompson     }
13306e15d496SJeremy L Thompson   } else {
13316e15d496SJeremy L Thompson     CeedInt num_input_fields, num_output_fields;
13326e15d496SJeremy L Thompson     CeedOperatorField *input_fields, *output_fields;
13336e15d496SJeremy L Thompson 
13346e15d496SJeremy L Thompson     ierr = CeedOperatorGetFields(op, &num_input_fields, &input_fields,
13356e15d496SJeremy L Thompson                                  &num_output_fields, &output_fields); CeedChk(ierr);
13366e15d496SJeremy L Thompson 
13376e15d496SJeremy L Thompson     CeedInt num_elem = 0;
13386e15d496SJeremy L Thompson     ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChk(ierr);
13396e15d496SJeremy L Thompson     // Input FLOPs
13406e15d496SJeremy L Thompson     for (CeedInt i = 0; i < num_input_fields; i++) {
13416e15d496SJeremy L Thompson       if (input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
13429d36ca50SJeremy L Thompson         CeedSize restr_flops, basis_flops;
13436e15d496SJeremy L Thompson 
13446e15d496SJeremy L Thompson         ierr = CeedElemRestrictionGetFlopsEstimate(input_fields[i]->elem_restr,
13456e15d496SJeremy L Thompson                CEED_NOTRANSPOSE, &restr_flops); CeedChk(ierr);
13466e15d496SJeremy L Thompson         *flops += restr_flops;
13476e15d496SJeremy L Thompson         ierr = CeedBasisGetFlopsEstimate(input_fields[i]->basis, CEED_NOTRANSPOSE,
13486e15d496SJeremy L Thompson                                          op->qf->input_fields[i]->eval_mode, &basis_flops); CeedChk(ierr);
13496e15d496SJeremy L Thompson         *flops += basis_flops * num_elem;
13506e15d496SJeremy L Thompson       }
13516e15d496SJeremy L Thompson     }
13526e15d496SJeremy L Thompson     // QF FLOPs
13539d36ca50SJeremy L Thompson     CeedInt num_qpts;
13549d36ca50SJeremy L Thompson     CeedSize qf_flops;
13556e15d496SJeremy L Thompson     ierr = CeedOperatorGetNumQuadraturePoints(op, &num_qpts); CeedChk(ierr);
13566e15d496SJeremy L Thompson     ierr = CeedQFunctionGetFlopsEstimate(op->qf, &qf_flops); CeedChk(ierr);
13576e15d496SJeremy L Thompson     *flops += num_elem * num_qpts * qf_flops;
13586e15d496SJeremy L Thompson     // Output FLOPs
13596e15d496SJeremy L Thompson     for (CeedInt i = 0; i < num_output_fields; i++) {
13606e15d496SJeremy L Thompson       if (output_fields[i]->vec == CEED_VECTOR_ACTIVE) {
13619d36ca50SJeremy L Thompson         CeedSize restr_flops, basis_flops;
13626e15d496SJeremy L Thompson 
13636e15d496SJeremy L Thompson         ierr = CeedElemRestrictionGetFlopsEstimate(output_fields[i]->elem_restr,
13646e15d496SJeremy L Thompson                CEED_TRANSPOSE, &restr_flops); CeedChk(ierr);
13656e15d496SJeremy L Thompson         *flops += restr_flops;
13666e15d496SJeremy L Thompson         ierr = CeedBasisGetFlopsEstimate(output_fields[i]->basis, CEED_TRANSPOSE,
13676e15d496SJeremy L Thompson                                          op->qf->output_fields[i]->eval_mode, &basis_flops); CeedChk(ierr);
13686e15d496SJeremy L Thompson         *flops += basis_flops * num_elem;
13696e15d496SJeremy L Thompson       }
13706e15d496SJeremy L Thompson     }
13716e15d496SJeremy L Thompson   }
13726e15d496SJeremy L Thompson 
13736e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
13746e15d496SJeremy L Thompson }
13756e15d496SJeremy L Thompson 
13766e15d496SJeremy L Thompson /**
13773668ca4bSJeremy L Thompson   @brief Get label for a registered QFunctionContext field, or `NULL` if no
13783668ca4bSJeremy L Thompson            field has been registered with this `field_name`.
13793668ca4bSJeremy L Thompson 
13803668ca4bSJeremy L Thompson   @param[in] op            CeedOperator
13813668ca4bSJeremy L Thompson   @param[in] field_name    Name of field to retrieve label
13823668ca4bSJeremy L Thompson   @param[out] field_label  Variable to field label
13833668ca4bSJeremy L Thompson 
13843668ca4bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
13853668ca4bSJeremy L Thompson 
13863668ca4bSJeremy L Thompson   @ref User
13873668ca4bSJeremy L Thompson **/
13883668ca4bSJeremy L Thompson int CeedOperatorContextGetFieldLabel(CeedOperator op,
13893668ca4bSJeremy L Thompson                                      const char *field_name,
13903668ca4bSJeremy L Thompson                                      CeedContextFieldLabel *field_label) {
13913668ca4bSJeremy L Thompson   int ierr;
13923668ca4bSJeremy L Thompson 
13933668ca4bSJeremy L Thompson   bool is_composite;
13943668ca4bSJeremy L Thompson   ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr);
13953668ca4bSJeremy L Thompson   if (is_composite) {
13963668ca4bSJeremy L Thompson     // Check if composite label already created
13973668ca4bSJeremy L Thompson     for (CeedInt i=0; i<op->num_context_labels; i++) {
13983668ca4bSJeremy L Thompson       if (!strcmp(op->context_labels[i]->name, field_name)) {
13993668ca4bSJeremy L Thompson         *field_label = op->context_labels[i];
14003668ca4bSJeremy L Thompson         return CEED_ERROR_SUCCESS;
14013668ca4bSJeremy L Thompson       }
14023668ca4bSJeremy L Thompson     }
14033668ca4bSJeremy L Thompson 
14043668ca4bSJeremy L Thompson     // Create composite label if needed
14053668ca4bSJeremy L Thompson     CeedInt num_sub;
14063668ca4bSJeremy L Thompson     CeedOperator *sub_operators;
14073668ca4bSJeremy L Thompson     CeedContextFieldLabel new_field_label;
14083668ca4bSJeremy L Thompson 
14093668ca4bSJeremy L Thompson     ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr);
14103668ca4bSJeremy L Thompson     ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr);
14113668ca4bSJeremy L Thompson     ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
14123668ca4bSJeremy L Thompson     ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr);
14133668ca4bSJeremy L Thompson     new_field_label->num_sub_labels = num_sub;
14143668ca4bSJeremy L Thompson 
14153668ca4bSJeremy L Thompson     bool label_found = false;
14163668ca4bSJeremy L Thompson     for (CeedInt i=0; i<num_sub; i++) {
14173668ca4bSJeremy L Thompson       if (sub_operators[i]->qf->ctx) {
14183668ca4bSJeremy L Thompson         CeedContextFieldLabel new_field_label_i;
14193668ca4bSJeremy L Thompson         ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name,
14203668ca4bSJeremy L Thompson                &new_field_label_i); CeedChk(ierr);
14213668ca4bSJeremy L Thompson         if (new_field_label_i) {
14223668ca4bSJeremy L Thompson           label_found = true;
14233668ca4bSJeremy L Thompson           new_field_label->sub_labels[i] = new_field_label_i;
14243668ca4bSJeremy L Thompson           new_field_label->name = new_field_label_i->name;
14253668ca4bSJeremy L Thompson           new_field_label->description = new_field_label_i->description;
14267bfe0f0eSJeremy L Thompson           if (new_field_label->type &&
14277bfe0f0eSJeremy L Thompson               new_field_label->type != new_field_label_i->type) {
14287bfe0f0eSJeremy L Thompson             // LCOV_EXCL_START
14297bfe0f0eSJeremy L Thompson             ierr = CeedFree(&new_field_label); CeedChk(ierr);
14307bfe0f0eSJeremy L Thompson             return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
14317bfe0f0eSJeremy L Thompson                              "Incompatible field types on sub-operator contexts. "
14327bfe0f0eSJeremy L Thompson                              "%s != %s",
14337bfe0f0eSJeremy L Thompson                              CeedContextFieldTypes[new_field_label->type],
14347bfe0f0eSJeremy L Thompson                              CeedContextFieldTypes[new_field_label_i->type]);
14357bfe0f0eSJeremy L Thompson             // LCOV_EXCL_STOP
14367bfe0f0eSJeremy L Thompson           } else {
14377bfe0f0eSJeremy L Thompson             new_field_label->type = new_field_label_i->type;
14387bfe0f0eSJeremy L Thompson           }
14397bfe0f0eSJeremy L Thompson           if (new_field_label->num_values != 0 &&
14407bfe0f0eSJeremy L Thompson               new_field_label->num_values != new_field_label_i->num_values) {
14417bfe0f0eSJeremy L Thompson             // LCOV_EXCL_START
14427bfe0f0eSJeremy L Thompson             ierr = CeedFree(&new_field_label); CeedChk(ierr);
14437bfe0f0eSJeremy L Thompson             return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
14447bfe0f0eSJeremy L Thompson                              "Incompatible field number of values on sub-operator"
14457bfe0f0eSJeremy L Thompson                              " contexts. %ld != %ld",
14467bfe0f0eSJeremy L Thompson                              new_field_label->num_values, new_field_label_i->num_values);
14477bfe0f0eSJeremy L Thompson             // LCOV_EXCL_STOP
14487bfe0f0eSJeremy L Thompson           } else {
14497bfe0f0eSJeremy L Thompson             new_field_label->num_values = new_field_label_i->num_values;
14507bfe0f0eSJeremy L Thompson           }
14513668ca4bSJeremy L Thompson         }
14523668ca4bSJeremy L Thompson       }
14533668ca4bSJeremy L Thompson     }
14543668ca4bSJeremy L Thompson     if (!label_found) {
14553668ca4bSJeremy L Thompson       // LCOV_EXCL_START
1456a48e5f43SJeremy L Thompson       ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr);
14573668ca4bSJeremy L Thompson       ierr = CeedFree(&new_field_label); CeedChk(ierr);
14583668ca4bSJeremy L Thompson       *field_label = NULL;
14593668ca4bSJeremy L Thompson       // LCOV_EXCL_STOP
14603668ca4bSJeremy L Thompson     } else {
14613668ca4bSJeremy L Thompson       // Move new composite label to operator
14623668ca4bSJeremy L Thompson       if (op->num_context_labels == 0) {
14633668ca4bSJeremy L Thompson         ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr);
14643668ca4bSJeremy L Thompson         op->max_context_labels = 1;
14653668ca4bSJeremy L Thompson       } else if (op->num_context_labels == op->max_context_labels) {
14663668ca4bSJeremy L Thompson         ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels);
14673668ca4bSJeremy L Thompson         CeedChk(ierr);
14683668ca4bSJeremy L Thompson         op->max_context_labels *= 2;
14693668ca4bSJeremy L Thompson       }
14703668ca4bSJeremy L Thompson       op->context_labels[op->num_context_labels] = new_field_label;
14713668ca4bSJeremy L Thompson       *field_label = new_field_label;
14723668ca4bSJeremy L Thompson       op->num_context_labels++;
14733668ca4bSJeremy L Thompson     }
14743668ca4bSJeremy L Thompson 
14753668ca4bSJeremy L Thompson     return CEED_ERROR_SUCCESS;
14763668ca4bSJeremy L Thompson   } else {
14773668ca4bSJeremy L Thompson     return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label);
14783668ca4bSJeremy L Thompson   }
14793668ca4bSJeremy L Thompson }
14803668ca4bSJeremy L Thompson 
14813668ca4bSJeremy L Thompson /**
1482d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field holding a double precision value.
1483d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
1484d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
1485d8dd9a91SJeremy L Thompson 
1486d8dd9a91SJeremy L Thompson   @param op          CeedOperator
14873668ca4bSJeremy L Thompson   @param field_label Label of field to register
14887bfe0f0eSJeremy L Thompson   @param values      Values to set
1489d8dd9a91SJeremy L Thompson 
1490d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1491d8dd9a91SJeremy L Thompson 
1492d8dd9a91SJeremy L Thompson   @ref User
1493d8dd9a91SJeremy L Thompson **/
14943668ca4bSJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op,
14953668ca4bSJeremy L Thompson                                  CeedContextFieldLabel field_label,
14967bfe0f0eSJeremy L Thompson                                  double *values) {
14973668ca4bSJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE,
14987bfe0f0eSJeremy L Thompson                                        values);
1499d8dd9a91SJeremy L Thompson }
1500d8dd9a91SJeremy L Thompson 
1501d8dd9a91SJeremy L Thompson /**
1502d8dd9a91SJeremy L Thompson   @brief Set QFunctionContext field holding an int32 value.
1503d8dd9a91SJeremy L Thompson            For composite operators, the value is set in all
1504d8dd9a91SJeremy L Thompson            sub-operator QFunctionContexts that have a matching `field_name`.
1505d8dd9a91SJeremy L Thompson 
1506d8dd9a91SJeremy L Thompson   @param op          CeedOperator
15073668ca4bSJeremy L Thompson   @param field_label Label of field to set
15087bfe0f0eSJeremy L Thompson   @param values      Values to set
1509d8dd9a91SJeremy L Thompson 
1510d8dd9a91SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1511d8dd9a91SJeremy L Thompson 
1512d8dd9a91SJeremy L Thompson   @ref User
1513d8dd9a91SJeremy L Thompson **/
15143668ca4bSJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op,
15153668ca4bSJeremy L Thompson                                 CeedContextFieldLabel field_label,
15167bfe0f0eSJeremy L Thompson                                 int *values) {
15173668ca4bSJeremy L Thompson   return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32,
15187bfe0f0eSJeremy L Thompson                                        values);
1519d8dd9a91SJeremy L Thompson }
1520d8dd9a91SJeremy L Thompson 
1521d8dd9a91SJeremy L Thompson /**
15223bd813ffSjeremylt   @brief Apply CeedOperator to a vector
1523d7b241e6Sjeremylt 
1524d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
1525d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1526d7b241e6Sjeremylt   CeedOperatorSetField().
1527d7b241e6Sjeremylt 
1528f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
1529f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
1530f04ea552SJeremy L Thompson 
1531d7b241e6Sjeremylt   @param op        CeedOperator to apply
15324cc79fe7SJed Brown   @param[in] in    CeedVector containing input state or @ref CEED_VECTOR_NONE if
153334138859Sjeremylt                      there are no active inputs
1534b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
15354cc79fe7SJed Brown                      distinct from @a in) or @ref CEED_VECTOR_NONE if there are no
153634138859Sjeremylt                      active outputs
1537d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
15384cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1539b11c1e72Sjeremylt 
1540b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1541dfdf5a53Sjeremylt 
15427a982d89SJeremy L. Thompson   @ref User
1543b11c1e72Sjeremylt **/
1544692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
1545692c2638Sjeremylt                       CeedRequest *request) {
1546d7b241e6Sjeremylt   int ierr;
1547e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1548d7b241e6Sjeremylt 
1549d1d35e2fSjeremylt   if (op->num_elem)  {
1550250756a7Sjeremylt     // Standard Operator
1551cae8b89aSjeremylt     if (op->Apply) {
1552250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
1553cae8b89aSjeremylt     } else {
1554cae8b89aSjeremylt       // Zero all output vectors
1555250756a7Sjeremylt       CeedQFunction qf = op->qf;
1556d1d35e2fSjeremylt       for (CeedInt i=0; i<qf->num_output_fields; i++) {
1557d1d35e2fSjeremylt         CeedVector vec = op->output_fields[i]->vec;
1558cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
1559cae8b89aSjeremylt           vec = out;
1560cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
1561cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1562cae8b89aSjeremylt         }
1563cae8b89aSjeremylt       }
1564250756a7Sjeremylt       // Apply
1565250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1566250756a7Sjeremylt     }
1567f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1568250756a7Sjeremylt     // Composite Operator
1569250756a7Sjeremylt     if (op->ApplyComposite) {
1570250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
1571250756a7Sjeremylt     } else {
1572d1d35e2fSjeremylt       CeedInt num_suboperators;
1573d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1574d1d35e2fSjeremylt       CeedOperator *sub_operators;
1575d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1576250756a7Sjeremylt 
1577250756a7Sjeremylt       // Zero all output vectors
1578250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
1579cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
1580cae8b89aSjeremylt       }
1581d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1582d1d35e2fSjeremylt         for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) {
1583d1d35e2fSjeremylt           CeedVector vec = sub_operators[i]->output_fields[j]->vec;
1584250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
1585250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1586250756a7Sjeremylt           }
1587250756a7Sjeremylt         }
1588250756a7Sjeremylt       }
1589250756a7Sjeremylt       // Apply
1590d1d35e2fSjeremylt       for (CeedInt i=0; i<op->num_suboperators; i++) {
1591d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request);
1592cae8b89aSjeremylt         CeedChk(ierr);
1593cae8b89aSjeremylt       }
1594cae8b89aSjeremylt     }
1595250756a7Sjeremylt   }
1596e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1597cae8b89aSjeremylt }
1598cae8b89aSjeremylt 
1599cae8b89aSjeremylt /**
1600cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
1601cae8b89aSjeremylt 
1602cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
1603cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1604cae8b89aSjeremylt   CeedOperatorSetField().
1605cae8b89aSjeremylt 
1606cae8b89aSjeremylt   @param op        CeedOperator to apply
1607cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
1608cae8b89aSjeremylt                      active inputs
1609cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
1610cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
1611cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
16124cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1613cae8b89aSjeremylt 
1614cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
1615cae8b89aSjeremylt 
16167a982d89SJeremy L. Thompson   @ref User
1617cae8b89aSjeremylt **/
1618cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
1619cae8b89aSjeremylt                          CeedRequest *request) {
1620cae8b89aSjeremylt   int ierr;
1621e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1622cae8b89aSjeremylt 
1623d1d35e2fSjeremylt   if (op->num_elem)  {
1624250756a7Sjeremylt     // Standard Operator
1625250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1626f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1627250756a7Sjeremylt     // Composite Operator
1628250756a7Sjeremylt     if (op->ApplyAddComposite) {
1629250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
1630cae8b89aSjeremylt     } else {
1631d1d35e2fSjeremylt       CeedInt num_suboperators;
1632d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1633d1d35e2fSjeremylt       CeedOperator *sub_operators;
1634d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1635250756a7Sjeremylt 
1636d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1637d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request);
1638cae8b89aSjeremylt         CeedChk(ierr);
16391d7d2407SJeremy L Thompson       }
1640250756a7Sjeremylt     }
1641250756a7Sjeremylt   }
1642e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1643d7b241e6Sjeremylt }
1644d7b241e6Sjeremylt 
1645d7b241e6Sjeremylt /**
1646b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1647d7b241e6Sjeremylt 
1648d7b241e6Sjeremylt   @param op  CeedOperator to destroy
1649b11c1e72Sjeremylt 
1650b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1651dfdf5a53Sjeremylt 
16527a982d89SJeremy L. Thompson   @ref User
1653b11c1e72Sjeremylt **/
1654d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1655d7b241e6Sjeremylt   int ierr;
1656d7b241e6Sjeremylt 
1657d1d35e2fSjeremylt   if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS;
1658d7b241e6Sjeremylt   if ((*op)->Destroy) {
1659d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1660d7b241e6Sjeremylt   }
1661fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1662fe2413ffSjeremylt   // Free fields
16633668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_fields; i++)
1664d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
1665d1d35e2fSjeremylt       if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) {
1666d1d35e2fSjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr);
166771352a93Sjeremylt         CeedChk(ierr);
166815910d16Sjeremylt       }
1669d1d35e2fSjeremylt       if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1670d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr);
167171352a93Sjeremylt       }
1672d1d35e2fSjeremylt       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1673d1d35e2fSjeremylt           (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) {
1674d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr);
167571352a93Sjeremylt       }
1676d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr);
1677d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr);
1678fe2413ffSjeremylt     }
16793668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_fields; i++)
1680d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
1681d1d35e2fSjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr);
168271352a93Sjeremylt       CeedChk(ierr);
1683d1d35e2fSjeremylt       if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1684d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr);
168571352a93Sjeremylt       }
1686d1d35e2fSjeremylt       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1687d1d35e2fSjeremylt           (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) {
1688d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr);
168971352a93Sjeremylt       }
1690d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr);
1691d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr);
1692fe2413ffSjeremylt     }
1693d1d35e2fSjeremylt   // Destroy sub_operators
16943668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_suboperators; i++)
1695d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
1696d1d35e2fSjeremylt       ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr);
169752d6035fSJeremy L Thompson     }
1698d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1699d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1700d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
17013668ca4bSJeremy L Thompson   // Destroy any composite labels
17023668ca4bSJeremy L Thompson   for (CeedInt i=0; i<(*op)->num_context_labels; i++) {
17033668ca4bSJeremy L Thompson     ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr);
17043668ca4bSJeremy L Thompson     ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr);
17053668ca4bSJeremy L Thompson   }
17063668ca4bSJeremy L Thompson   ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr);
1707fe2413ffSjeremylt 
17085107b09fSJeremy L Thompson   // Destroy fallback
1709805fe78eSJeremy L Thompson   ierr = CeedOperatorDestroy(&(*op)->op_fallback); CeedChk(ierr);
17105107b09fSJeremy L Thompson 
1711ed9e99e6SJeremy L Thompson   // Destroy assembly data
1712480fae85SJeremy L Thompson   ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr);
1713ed9e99e6SJeremy L Thompson   ierr = CeedOperatorAssemblyDataDestroy(&(*op)->op_assembled); CeedChk(ierr);
171470a7ffb3SJeremy L Thompson 
1715d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr);
1716d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr);
1717d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr);
1718ea6b5821SJeremy L Thompson   ierr = CeedFree(&(*op)->name); CeedChk(ierr);
1719d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1720e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1721d7b241e6Sjeremylt }
1722d7b241e6Sjeremylt 
1723d7b241e6Sjeremylt /// @}
1724