xref: /libCEED/interface/ceed-operator.c (revision eaf62fff1deb4c7d4a34a324240d6e3aac43fc8b)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17ec3da8bcSJed Brown #include <ceed/ceed.h>
18ec3da8bcSJed Brown #include <ceed/backend.h>
193d576824SJeremy L Thompson #include <ceed-impl.h>
203bd813ffSjeremylt #include <math.h>
213d576824SJeremy L Thompson #include <stdbool.h>
223d576824SJeremy L Thompson #include <stdio.h>
233d576824SJeremy L Thompson #include <string.h>
24d7b241e6Sjeremylt 
25dfdf5a53Sjeremylt /// @file
267a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces
277a982d89SJeremy L. Thompson 
287a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
297a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions
307a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
317a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper
327a982d89SJeremy L. Thompson /// @{
337a982d89SJeremy L. Thompson 
347a982d89SJeremy L. Thompson /**
35e15f9bd0SJeremy L Thompson   @brief Check if a CeedOperator Field matches the QFunction Field
36e15f9bd0SJeremy L Thompson 
37e15f9bd0SJeremy L Thompson   @param[in] ceed      Ceed object for error handling
38d1d35e2fSjeremylt   @param[in] qf_field  QFunction Field matching Operator Field
39e15f9bd0SJeremy L Thompson   @param[in] r         Operator Field ElemRestriction
40e15f9bd0SJeremy L Thompson   @param[in] b         Operator Field Basis
41e15f9bd0SJeremy L Thompson 
42e15f9bd0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
43e15f9bd0SJeremy L Thompson 
44e15f9bd0SJeremy L Thompson   @ref Developer
45e15f9bd0SJeremy L Thompson **/
46d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field,
47e15f9bd0SJeremy L Thompson                                   CeedElemRestriction r, CeedBasis b) {
48e15f9bd0SJeremy L Thompson   int ierr;
49d1d35e2fSjeremylt   CeedEvalMode eval_mode = qf_field->eval_mode;
50d1d35e2fSjeremylt   CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size;
51e15f9bd0SJeremy L Thompson   // Restriction
52e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
53d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_WEIGHT) {
54e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
55e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
56e1e9e29dSJed Brown                        "CEED_ELEMRESTRICTION_NONE should be used "
57e15f9bd0SJeremy L Thompson                        "for a field with eval mode CEED_EVAL_WEIGHT");
58e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
59e15f9bd0SJeremy L Thompson     }
60d1d35e2fSjeremylt     ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp);
6178464608Sjeremylt     CeedChk(ierr);
62e1e9e29dSJed Brown   }
63d1d35e2fSjeremylt   if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) {
64e1e9e29dSJed Brown     // LCOV_EXCL_START
65e1e9e29dSJed Brown     return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
66e1e9e29dSJed Brown                      "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT "
67e1e9e29dSJed Brown                      "must be used together.");
68e1e9e29dSJed Brown     // LCOV_EXCL_STOP
69e1e9e29dSJed Brown   }
70e15f9bd0SJeremy L Thompson   // Basis
71e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
72d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_NONE)
738229195eSjeremylt       // LCOV_EXCL_START
74e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
75d1d35e2fSjeremylt                        "Field '%s' configured with CEED_EVAL_NONE must "
76d1d35e2fSjeremylt                        "be used with CEED_BASIS_COLLOCATED",
778229195eSjeremylt                        // LCOV_EXCL_STOP
78d1d35e2fSjeremylt                        qf_field->field_name);
79e15f9bd0SJeremy L Thompson     ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr);
80d1d35e2fSjeremylt     ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr);
81d1d35e2fSjeremylt     if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) {
82e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
83e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
84d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s: ElemRestriction "
85d1d35e2fSjeremylt                        "has %d components, but Basis has %d components",
86d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
87d1d35e2fSjeremylt                        restr_num_comp,
88d1d35e2fSjeremylt                        num_comp);
89e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
90e15f9bd0SJeremy L Thompson     }
91e15f9bd0SJeremy L Thompson   }
92e15f9bd0SJeremy L Thompson   // Field size
93d1d35e2fSjeremylt   switch(eval_mode) {
94e15f9bd0SJeremy L Thompson   case CEED_EVAL_NONE:
95d1d35e2fSjeremylt     if (size != restr_num_comp)
96e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
97e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
98e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components",
99d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
100d1d35e2fSjeremylt                        restr_num_comp);
101e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
102e15f9bd0SJeremy L Thompson     break;
103e15f9bd0SJeremy L Thompson   case CEED_EVAL_INTERP:
104d1d35e2fSjeremylt     if (size != num_comp)
105e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
106e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
107e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components",
108d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
109d1d35e2fSjeremylt                        num_comp);
110e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
111e15f9bd0SJeremy L Thompson     break;
112e15f9bd0SJeremy L Thompson   case CEED_EVAL_GRAD:
113d1d35e2fSjeremylt     if (size != num_comp * dim)
114e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
115e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
116d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s in %d dimensions: "
117d1d35e2fSjeremylt                        "ElemRestriction/Basis has %d components",
118d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim,
119d1d35e2fSjeremylt                        num_comp);
120e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
121e15f9bd0SJeremy L Thompson     break;
122e15f9bd0SJeremy L Thompson   case CEED_EVAL_WEIGHT:
123d1d35e2fSjeremylt     // No additional checks required
124e15f9bd0SJeremy L Thompson     break;
125e15f9bd0SJeremy L Thompson   case CEED_EVAL_DIV:
126e15f9bd0SJeremy L Thompson     // Not implemented
127e15f9bd0SJeremy L Thompson     break;
128e15f9bd0SJeremy L Thompson   case CEED_EVAL_CURL:
129e15f9bd0SJeremy L Thompson     // Not implemented
130e15f9bd0SJeremy L Thompson     break;
131e15f9bd0SJeremy L Thompson   }
132e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1337a982d89SJeremy L. Thompson }
1347a982d89SJeremy L. Thompson 
1357a982d89SJeremy L. Thompson /**
1367a982d89SJeremy L. Thompson   @brief Check if a CeedOperator is ready to be used.
1377a982d89SJeremy L. Thompson 
1387a982d89SJeremy L. Thompson   @param[in] op  CeedOperator to check
1397a982d89SJeremy L. Thompson 
1407a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1417a982d89SJeremy L. Thompson 
1427a982d89SJeremy L. Thompson   @ref Developer
1437a982d89SJeremy L. Thompson **/
144*eaf62fffSJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
145e2f04181SAndrew T. Barker   int ierr;
146e2f04181SAndrew T. Barker   Ceed ceed;
147e2f04181SAndrew T. Barker   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
148e2f04181SAndrew T. Barker 
149d1d35e2fSjeremylt   if (op->interface_setup)
150e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
1517a982d89SJeremy L. Thompson 
152e15f9bd0SJeremy L Thompson   CeedQFunction qf = op->qf;
1537a982d89SJeremy L. Thompson   if (op->composite) {
154d1d35e2fSjeremylt     if (!op->num_suboperators)
1557a982d89SJeremy L. Thompson       // LCOV_EXCL_START
156d1d35e2fSjeremylt       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set");
1577a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
1587a982d89SJeremy L. Thompson   } else {
159d1d35e2fSjeremylt     if (op->num_fields == 0)
1607a982d89SJeremy L. Thompson       // LCOV_EXCL_START
161e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set");
1627a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
163d1d35e2fSjeremylt     if (op->num_fields < qf->num_input_fields + qf->num_output_fields)
1647a982d89SJeremy L. Thompson       // LCOV_EXCL_START
165e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set");
1667a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
167d1d35e2fSjeremylt     if (!op->has_restriction)
1687a982d89SJeremy L. Thompson       // LCOV_EXCL_START
169e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
170e15f9bd0SJeremy L Thompson                        "At least one restriction required");
1717a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
172d1d35e2fSjeremylt     if (op->num_qpts == 0)
1737a982d89SJeremy L. Thompson       // LCOV_EXCL_START
174e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
175cd4dfc48Sjeremylt                        "At least one non-collocated basis is required "
176cd4dfc48Sjeremylt                        "or the number of quadrature points must be set");
1777a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
1787a982d89SJeremy L. Thompson   }
1797a982d89SJeremy L. Thompson 
180e15f9bd0SJeremy L Thompson   // Flag as immutable and ready
181d1d35e2fSjeremylt   op->interface_setup = true;
182e15f9bd0SJeremy L Thompson   if (op->qf && op->qf != CEED_QFUNCTION_NONE)
183e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
184d1d35e2fSjeremylt     op->qf->operators_set++;
185e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
186e15f9bd0SJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE)
187e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
188d1d35e2fSjeremylt     op->dqf->operators_set++;
189e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
190e15f9bd0SJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE)
191e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
192d1d35e2fSjeremylt     op->dqfT->operators_set++;
193e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
194e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1957a982d89SJeremy L. Thompson }
1967a982d89SJeremy L. Thompson 
1977a982d89SJeremy L. Thompson /**
1987a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
1997a982d89SJeremy L. Thompson 
2007a982d89SJeremy L. Thompson   @param[in] field         Operator field to view
201d1d35e2fSjeremylt   @param[in] qf_field      QFunction field (carries field name)
202d1d35e2fSjeremylt   @param[in] field_number  Number of field being viewed
2034c4400c7SValeria Barra   @param[in] sub           true indicates sub-operator, which increases indentation; false for top-level operator
204d1d35e2fSjeremylt   @param[in] input         true for an input field; false for output field
2057a982d89SJeremy L. Thompson   @param[in] stream        Stream to view to, e.g., stdout
2067a982d89SJeremy L. Thompson 
2077a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2087a982d89SJeremy L. Thompson 
2097a982d89SJeremy L. Thompson   @ref Utility
2107a982d89SJeremy L. Thompson **/
2117a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
212d1d35e2fSjeremylt                                  CeedQFunctionField qf_field,
213d1d35e2fSjeremylt                                  CeedInt field_number, bool sub, bool input,
2147a982d89SJeremy L. Thompson                                  FILE *stream) {
2157a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
216d1d35e2fSjeremylt   const char *in_out = input ? "Input" : "Output";
2177a982d89SJeremy L. Thompson 
2187a982d89SJeremy L. Thompson   fprintf(stream, "%s    %s Field [%d]:\n"
2197a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
220d1d35e2fSjeremylt           pre, in_out, field_number, pre, qf_field->field_name);
2217a982d89SJeremy L. Thompson 
2227a982d89SJeremy L. Thompson   if (field->basis == CEED_BASIS_COLLOCATED)
2237a982d89SJeremy L. Thompson     fprintf(stream, "%s      Collocated basis\n", pre);
2247a982d89SJeremy L. Thompson 
2257a982d89SJeremy L. Thompson   if (field->vec == CEED_VECTOR_ACTIVE)
2267a982d89SJeremy L. Thompson     fprintf(stream, "%s      Active vector\n", pre);
2277a982d89SJeremy L. Thompson   else if (field->vec == CEED_VECTOR_NONE)
2287a982d89SJeremy L. Thompson     fprintf(stream, "%s      No vector\n", pre);
229e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2307a982d89SJeremy L. Thompson }
2317a982d89SJeremy L. Thompson 
2327a982d89SJeremy L. Thompson /**
2337a982d89SJeremy L. Thompson   @brief View a single CeedOperator
2347a982d89SJeremy L. Thompson 
2357a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
2367a982d89SJeremy L. Thompson   @param[in] sub     Boolean flag for sub-operator
2377a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
2387a982d89SJeremy L. Thompson 
2397a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
2407a982d89SJeremy L. Thompson 
2417a982d89SJeremy L. Thompson   @ref Utility
2427a982d89SJeremy L. Thompson **/
2437a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
2447a982d89SJeremy L. Thompson   int ierr;
2457a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
2467a982d89SJeremy L. Thompson 
24778464608Sjeremylt   CeedInt total_fields = 0;
24878464608Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr);
2497a982d89SJeremy L. Thompson 
25078464608Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, total_fields,
25178464608Sjeremylt           total_fields>1 ? "s" : "");
2527a982d89SJeremy L. Thompson 
253d1d35e2fSjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->num_input_fields,
254d1d35e2fSjeremylt           op->qf->num_input_fields>1 ? "s" : "");
255d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
256d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i],
2577a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
2587a982d89SJeremy L. Thompson   }
2597a982d89SJeremy L. Thompson 
260d1d35e2fSjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->num_output_fields,
261d1d35e2fSjeremylt           op->qf->num_output_fields>1 ? "s" : "");
262d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
263d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i],
2647a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
2657a982d89SJeremy L. Thompson   }
266e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2677a982d89SJeremy L. Thompson }
2687a982d89SJeremy L. Thompson 
269d99fa3c5SJeremy L Thompson /**
270*eaf62fffSJeremy L Thompson   @brief Find the active vector basis for a CeedOperator
271*eaf62fffSJeremy L Thompson 
272*eaf62fffSJeremy L Thompson   @param[in] op             CeedOperator to find active basis for
273*eaf62fffSJeremy L Thompson   @param[out] active_basis  Basis for active input vector
274*eaf62fffSJeremy L Thompson 
275*eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
276*eaf62fffSJeremy L Thompson 
277*eaf62fffSJeremy L Thompson   @ ref Developer
278*eaf62fffSJeremy L Thompson **/
279*eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
280*eaf62fffSJeremy L Thompson   *active_basis = NULL;
281*eaf62fffSJeremy L Thompson   for (int i = 0; i < op->qf->num_input_fields; i++)
282*eaf62fffSJeremy L Thompson     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
283*eaf62fffSJeremy L Thompson       *active_basis = op->input_fields[i]->basis;
284*eaf62fffSJeremy L Thompson       break;
285*eaf62fffSJeremy L Thompson     }
286*eaf62fffSJeremy L Thompson 
287*eaf62fffSJeremy L Thompson   if (!*active_basis) {
288*eaf62fffSJeremy L Thompson     // LCOV_EXCL_START
289*eaf62fffSJeremy L Thompson     int ierr;
290*eaf62fffSJeremy L Thompson     Ceed ceed;
291*eaf62fffSJeremy L Thompson     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
292*eaf62fffSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
293*eaf62fffSJeremy L Thompson                      "No active CeedBasis found");
294*eaf62fffSJeremy L Thompson     // LCOV_EXCL_STOP
295*eaf62fffSJeremy L Thompson   }
296*eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
297*eaf62fffSJeremy L Thompson }
298*eaf62fffSJeremy L Thompson 
299*eaf62fffSJeremy L Thompson /**
300e2f04181SAndrew T. Barker   @brief Find the active vector ElemRestriction for a CeedOperator
301e2f04181SAndrew T. Barker 
302e2f04181SAndrew T. Barker   @param[in] op            CeedOperator to find active basis for
303d1d35e2fSjeremylt   @param[out] active_rstr  ElemRestriction for active input vector
304e2f04181SAndrew T. Barker 
305e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
306e2f04181SAndrew T. Barker 
307e2f04181SAndrew T. Barker   @ref Utility
308e2f04181SAndrew T. Barker **/
309*eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op,
310d1d35e2fSjeremylt     CeedElemRestriction *active_rstr) {
311d1d35e2fSjeremylt   *active_rstr = NULL;
312d1d35e2fSjeremylt   for (int i = 0; i < op->qf->num_input_fields; i++)
313d1d35e2fSjeremylt     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
314d1d35e2fSjeremylt       *active_rstr = op->input_fields[i]->elem_restr;
315e2f04181SAndrew T. Barker       break;
316e2f04181SAndrew T. Barker     }
317e2f04181SAndrew T. Barker 
318d1d35e2fSjeremylt   if (!*active_rstr) {
319e2f04181SAndrew T. Barker     // LCOV_EXCL_START
320e2f04181SAndrew T. Barker     int ierr;
321e2f04181SAndrew T. Barker     Ceed ceed;
322e2f04181SAndrew T. Barker     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
323e2f04181SAndrew T. Barker     return CeedError(ceed, CEED_ERROR_INCOMPLETE,
324*eaf62fffSJeremy L Thompson                      "No active CeedElemRestriction found");
325e2f04181SAndrew T. Barker     // LCOV_EXCL_STOP
326e2f04181SAndrew T. Barker   }
327e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
328e2f04181SAndrew T. Barker }
329e2f04181SAndrew T. Barker 
3307a982d89SJeremy L. Thompson /// @}
3317a982d89SJeremy L. Thompson 
3327a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3337a982d89SJeremy L. Thompson /// CeedOperator Backend API
3347a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3357a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
3367a982d89SJeremy L. Thompson /// @{
3377a982d89SJeremy L. Thompson 
3387a982d89SJeremy L. Thompson /**
3397a982d89SJeremy L. Thompson   @brief Get the Ceed associated with a CeedOperator
3407a982d89SJeremy L. Thompson 
3417a982d89SJeremy L. Thompson   @param op         CeedOperator
3427a982d89SJeremy L. Thompson   @param[out] ceed  Variable to store Ceed
3437a982d89SJeremy L. Thompson 
3447a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3457a982d89SJeremy L. Thompson 
3467a982d89SJeremy L. Thompson   @ref Backend
3477a982d89SJeremy L. Thompson **/
3487a982d89SJeremy L. Thompson 
3497a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
3507a982d89SJeremy L. Thompson   *ceed = op->ceed;
351e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3527a982d89SJeremy L. Thompson }
3537a982d89SJeremy L. Thompson 
3547a982d89SJeremy L. Thompson /**
3557a982d89SJeremy L. Thompson   @brief Get the number of elements associated with a CeedOperator
3567a982d89SJeremy L. Thompson 
3577a982d89SJeremy L. Thompson   @param op             CeedOperator
358d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
3597a982d89SJeremy L. Thompson 
3607a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3617a982d89SJeremy L. Thompson 
3627a982d89SJeremy L. Thompson   @ref Backend
3637a982d89SJeremy L. Thompson **/
3647a982d89SJeremy L. Thompson 
365d1d35e2fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
3667a982d89SJeremy L. Thompson   if (op->composite)
3677a982d89SJeremy L. Thompson     // LCOV_EXCL_START
368e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
369e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
3707a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3717a982d89SJeremy L. Thompson 
372d1d35e2fSjeremylt   *num_elem = op->num_elem;
373e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3747a982d89SJeremy L. Thompson }
3757a982d89SJeremy L. Thompson 
3767a982d89SJeremy L. Thompson /**
3777a982d89SJeremy L. Thompson   @brief Get the number of quadrature points associated with a CeedOperator
3787a982d89SJeremy L. Thompson 
3797a982d89SJeremy L. Thompson   @param op             CeedOperator
380d1d35e2fSjeremylt   @param[out] num_qpts  Variable to store vector number of quadrature points
3817a982d89SJeremy L. Thompson 
3827a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3837a982d89SJeremy L. Thompson 
3847a982d89SJeremy L. Thompson   @ref Backend
3857a982d89SJeremy L. Thompson **/
3867a982d89SJeremy L. Thompson 
387d1d35e2fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
3887a982d89SJeremy L. Thompson   if (op->composite)
3897a982d89SJeremy L. Thompson     // LCOV_EXCL_START
390e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
391e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
3927a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3937a982d89SJeremy L. Thompson 
394d1d35e2fSjeremylt   *num_qpts = op->num_qpts;
395e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3967a982d89SJeremy L. Thompson }
3977a982d89SJeremy L. Thompson 
3987a982d89SJeremy L. Thompson /**
3997a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
4007a982d89SJeremy L. Thompson 
4017a982d89SJeremy L. Thompson   @param op             CeedOperator
402d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
4037a982d89SJeremy L. Thompson 
4047a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4057a982d89SJeremy L. Thompson 
4067a982d89SJeremy L. Thompson   @ref Backend
4077a982d89SJeremy L. Thompson **/
4087a982d89SJeremy L. Thompson 
409d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
4107a982d89SJeremy L. Thompson   if (op->composite)
4117a982d89SJeremy L. Thompson     // LCOV_EXCL_START
412e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
413e15f9bd0SJeremy L Thompson                      "Not defined for composite operators");
4147a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4157a982d89SJeremy L. Thompson 
416d1d35e2fSjeremylt   *num_args = op->num_fields;
417e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4187a982d89SJeremy L. Thompson }
4197a982d89SJeremy L. Thompson 
4207a982d89SJeremy L. Thompson /**
4217a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
4227a982d89SJeremy L. Thompson 
4237a982d89SJeremy L. Thompson   @param op                  CeedOperator
424d1d35e2fSjeremylt   @param[out] is_setup_done  Variable to store setup status
4257a982d89SJeremy L. Thompson 
4267a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4277a982d89SJeremy L. Thompson 
4287a982d89SJeremy L. Thompson   @ref Backend
4297a982d89SJeremy L. Thompson **/
4307a982d89SJeremy L. Thompson 
431d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
432d1d35e2fSjeremylt   *is_setup_done = op->backend_setup;
433e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4347a982d89SJeremy L. Thompson }
4357a982d89SJeremy L. Thompson 
4367a982d89SJeremy L. Thompson /**
4377a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
4387a982d89SJeremy L. Thompson 
4397a982d89SJeremy L. Thompson   @param op       CeedOperator
4407a982d89SJeremy L. Thompson   @param[out] qf  Variable to store QFunction
4417a982d89SJeremy L. Thompson 
4427a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4437a982d89SJeremy L. Thompson 
4447a982d89SJeremy L. Thompson   @ref Backend
4457a982d89SJeremy L. Thompson **/
4467a982d89SJeremy L. Thompson 
4477a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
4487a982d89SJeremy L. Thompson   if (op->composite)
4497a982d89SJeremy L. Thompson     // LCOV_EXCL_START
450e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
451e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
4527a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4537a982d89SJeremy L. Thompson 
4547a982d89SJeremy L. Thompson   *qf = op->qf;
455e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4567a982d89SJeremy L. Thompson }
4577a982d89SJeremy L. Thompson 
4587a982d89SJeremy L. Thompson /**
459c04a41a7SJeremy L Thompson   @brief Get a boolean value indicating if the CeedOperator is composite
460c04a41a7SJeremy L Thompson 
461c04a41a7SJeremy L Thompson   @param op                 CeedOperator
462d1d35e2fSjeremylt   @param[out] is_composite  Variable to store composite status
463c04a41a7SJeremy L Thompson 
464c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
465c04a41a7SJeremy L Thompson 
466c04a41a7SJeremy L Thompson   @ref Backend
467c04a41a7SJeremy L Thompson **/
468c04a41a7SJeremy L Thompson 
469d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
470d1d35e2fSjeremylt   *is_composite = op->composite;
471e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
472c04a41a7SJeremy L Thompson }
473c04a41a7SJeremy L Thompson 
474c04a41a7SJeremy L Thompson /**
475d1d35e2fSjeremylt   @brief Get the number of sub_operators associated with a CeedOperator
4767a982d89SJeremy L. Thompson 
4777a982d89SJeremy L. Thompson   @param op                     CeedOperator
478d1d35e2fSjeremylt   @param[out] num_suboperators  Variable to store number of sub_operators
4797a982d89SJeremy L. Thompson 
4807a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4817a982d89SJeremy L. Thompson 
4827a982d89SJeremy L. Thompson   @ref Backend
4837a982d89SJeremy L. Thompson **/
4847a982d89SJeremy L. Thompson 
485d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
4867a982d89SJeremy L. Thompson   if (!op->composite)
4877a982d89SJeremy L. Thompson     // LCOV_EXCL_START
488e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4897a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4907a982d89SJeremy L. Thompson 
491d1d35e2fSjeremylt   *num_suboperators = op->num_suboperators;
492e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4937a982d89SJeremy L. Thompson }
4947a982d89SJeremy L. Thompson 
4957a982d89SJeremy L. Thompson /**
496d1d35e2fSjeremylt   @brief Get the list of sub_operators associated with a CeedOperator
4977a982d89SJeremy L. Thompson 
4987a982d89SJeremy L. Thompson   @param op                  CeedOperator
499d1d35e2fSjeremylt   @param[out] sub_operators  Variable to store list of sub_operators
5007a982d89SJeremy L. Thompson 
5017a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5027a982d89SJeremy L. Thompson 
5037a982d89SJeremy L. Thompson   @ref Backend
5047a982d89SJeremy L. Thompson **/
5057a982d89SJeremy L. Thompson 
506d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) {
5077a982d89SJeremy L. Thompson   if (!op->composite)
5087a982d89SJeremy L. Thompson     // LCOV_EXCL_START
509e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
5107a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
5117a982d89SJeremy L. Thompson 
512d1d35e2fSjeremylt   *sub_operators = op->sub_operators;
513e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5147a982d89SJeremy L. Thompson }
5157a982d89SJeremy L. Thompson 
5167a982d89SJeremy L. Thompson /**
5177a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
5187a982d89SJeremy L. Thompson 
5197a982d89SJeremy L. Thompson   @param op         CeedOperator
5207a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
5217a982d89SJeremy L. Thompson 
5227a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5237a982d89SJeremy L. Thompson 
5247a982d89SJeremy L. Thompson   @ref Backend
5257a982d89SJeremy L. Thompson **/
5267a982d89SJeremy L. Thompson 
527777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
528777ff853SJeremy L Thompson   *(void **)data = op->data;
529e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5307a982d89SJeremy L. Thompson }
5317a982d89SJeremy L. Thompson 
5327a982d89SJeremy L. Thompson /**
5337a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
5347a982d89SJeremy L. Thompson 
5357a982d89SJeremy L. Thompson   @param[out] op  CeedOperator
5367a982d89SJeremy L. Thompson   @param data     Data to set
5377a982d89SJeremy L. Thompson 
5387a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5397a982d89SJeremy L. Thompson 
5407a982d89SJeremy L. Thompson   @ref Backend
5417a982d89SJeremy L. Thompson **/
5427a982d89SJeremy L. Thompson 
543777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
544777ff853SJeremy L Thompson   op->data = data;
545e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5467a982d89SJeremy L. Thompson }
5477a982d89SJeremy L. Thompson 
5487a982d89SJeremy L. Thompson /**
54934359f16Sjeremylt   @brief Increment the reference counter for a CeedOperator
55034359f16Sjeremylt 
55134359f16Sjeremylt   @param op  CeedOperator to increment the reference counter
55234359f16Sjeremylt 
55334359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
55434359f16Sjeremylt 
55534359f16Sjeremylt   @ref Backend
55634359f16Sjeremylt **/
5579560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
55834359f16Sjeremylt   op->ref_count++;
55934359f16Sjeremylt   return CEED_ERROR_SUCCESS;
56034359f16Sjeremylt }
56134359f16Sjeremylt 
56234359f16Sjeremylt /**
5637a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
5647a982d89SJeremy L. Thompson 
5657a982d89SJeremy L. Thompson   @param op  CeedOperator
5667a982d89SJeremy L. Thompson 
5677a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5687a982d89SJeremy L. Thompson 
5697a982d89SJeremy L. Thompson   @ref Backend
5707a982d89SJeremy L. Thompson **/
5717a982d89SJeremy L. Thompson 
5727a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
573d1d35e2fSjeremylt   op->backend_setup = true;
574e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5757a982d89SJeremy L. Thompson }
5767a982d89SJeremy L. Thompson 
5777a982d89SJeremy L. Thompson /**
5787a982d89SJeremy L. Thompson   @brief Get the CeedOperatorFields of a CeedOperator
5797a982d89SJeremy L. Thompson 
5807a982d89SJeremy L. Thompson   @param op                  CeedOperator
581d1d35e2fSjeremylt   @param[out] input_fields   Variable to store input_fields
582d1d35e2fSjeremylt   @param[out] output_fields  Variable to store output_fields
5837a982d89SJeremy L. Thompson 
5847a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5857a982d89SJeremy L. Thompson 
5867a982d89SJeremy L. Thompson   @ref Backend
5877a982d89SJeremy L. Thompson **/
5887a982d89SJeremy L. Thompson 
589d1d35e2fSjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **input_fields,
590d1d35e2fSjeremylt                           CeedOperatorField **output_fields) {
5917a982d89SJeremy L. Thompson   if (op->composite)
5927a982d89SJeremy L. Thompson     // LCOV_EXCL_START
593e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
594e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
5957a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
5967a982d89SJeremy L. Thompson 
597d1d35e2fSjeremylt   if (input_fields) *input_fields = op->input_fields;
598d1d35e2fSjeremylt   if (output_fields) *output_fields = op->output_fields;
599e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6007a982d89SJeremy L. Thompson }
6017a982d89SJeremy L. Thompson 
6027a982d89SJeremy L. Thompson /**
6037a982d89SJeremy L. Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
6047a982d89SJeremy L. Thompson 
605d1d35e2fSjeremylt   @param op_field   CeedOperatorField
6067a982d89SJeremy L. Thompson   @param[out] rstr  Variable to store CeedElemRestriction
6077a982d89SJeremy L. Thompson 
6087a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6097a982d89SJeremy L. Thompson 
6107a982d89SJeremy L. Thompson   @ref Backend
6117a982d89SJeremy L. Thompson **/
6127a982d89SJeremy L. Thompson 
613d1d35e2fSjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,
6147a982d89SJeremy L. Thompson                                         CeedElemRestriction *rstr) {
615d1d35e2fSjeremylt   *rstr = op_field->elem_restr;
616e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6177a982d89SJeremy L. Thompson }
6187a982d89SJeremy L. Thompson 
6197a982d89SJeremy L. Thompson /**
6207a982d89SJeremy L. Thompson   @brief Get the CeedBasis of a CeedOperatorField
6217a982d89SJeremy L. Thompson 
622d1d35e2fSjeremylt   @param op_field    CeedOperatorField
6237a982d89SJeremy L. Thompson   @param[out] basis  Variable to store CeedBasis
6247a982d89SJeremy L. Thompson 
6257a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6267a982d89SJeremy L. Thompson 
6277a982d89SJeremy L. Thompson   @ref Backend
6287a982d89SJeremy L. Thompson **/
6297a982d89SJeremy L. Thompson 
630d1d35e2fSjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
631d1d35e2fSjeremylt   *basis = op_field->basis;
632e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6337a982d89SJeremy L. Thompson }
6347a982d89SJeremy L. Thompson 
6357a982d89SJeremy L. Thompson /**
6367a982d89SJeremy L. Thompson   @brief Get the CeedVector of a CeedOperatorField
6377a982d89SJeremy L. Thompson 
638d1d35e2fSjeremylt   @param op_field  CeedOperatorField
6397a982d89SJeremy L. Thompson   @param[out] vec  Variable to store CeedVector
6407a982d89SJeremy L. Thompson 
6417a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6427a982d89SJeremy L. Thompson 
6437a982d89SJeremy L. Thompson   @ref Backend
6447a982d89SJeremy L. Thompson **/
6457a982d89SJeremy L. Thompson 
646d1d35e2fSjeremylt int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
647d1d35e2fSjeremylt   *vec = op_field->vec;
648e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6497a982d89SJeremy L. Thompson }
6507a982d89SJeremy L. Thompson 
6517a982d89SJeremy L. Thompson /// @}
6527a982d89SJeremy L. Thompson 
6537a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
6547a982d89SJeremy L. Thompson /// CeedOperator Public API
6557a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
6567a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
657dfdf5a53Sjeremylt /// @{
658d7b241e6Sjeremylt 
659d7b241e6Sjeremylt /**
6600219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
6610219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
6620219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
663d7b241e6Sjeremylt 
664b11c1e72Sjeremylt   @param ceed     A Ceed object where the CeedOperator will be created
665d7b241e6Sjeremylt   @param qf       QFunction defining the action of the operator at quadrature points
66634138859Sjeremylt   @param dqf      QFunction defining the action of the Jacobian of @a qf (or
6674cc79fe7SJed Brown                     @ref CEED_QFUNCTION_NONE)
668d7b241e6Sjeremylt   @param dqfT     QFunction defining the action of the transpose of the Jacobian
6694cc79fe7SJed Brown                     of @a qf (or @ref CEED_QFUNCTION_NONE)
670b11c1e72Sjeremylt   @param[out] op  Address of the variable where the newly created
671b11c1e72Sjeremylt                     CeedOperator will be stored
672b11c1e72Sjeremylt 
673b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
674dfdf5a53Sjeremylt 
6757a982d89SJeremy L. Thompson   @ref User
676d7b241e6Sjeremylt  */
677d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
678d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
679d7b241e6Sjeremylt   int ierr;
680d7b241e6Sjeremylt 
6815fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
6825fe0d4faSjeremylt     Ceed delegate;
683aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
6845fe0d4faSjeremylt 
6855fe0d4faSjeremylt     if (!delegate)
686c042f62fSJeremy L Thompson       // LCOV_EXCL_START
687e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
688e15f9bd0SJeremy L Thompson                        "Backend does not support OperatorCreate");
689c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
6905fe0d4faSjeremylt 
6915fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
692e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6935fe0d4faSjeremylt   }
6945fe0d4faSjeremylt 
695b3b7035fSJeremy L Thompson   if (!qf || qf == CEED_QFUNCTION_NONE)
696b3b7035fSJeremy L Thompson     // LCOV_EXCL_START
697e15f9bd0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
698e15f9bd0SJeremy L Thompson                      "Operator must have a valid QFunction.");
699b3b7035fSJeremy L Thompson   // LCOV_EXCL_STOP
700d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
701d7b241e6Sjeremylt   (*op)->ceed = ceed;
7029560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
703d1d35e2fSjeremylt   (*op)->ref_count = 1;
704d7b241e6Sjeremylt   (*op)->qf = qf;
7059560d06aSjeremylt   ierr = CeedQFunctionReference(qf); CeedChk(ierr);
706442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
707d7b241e6Sjeremylt     (*op)->dqf = dqf;
7089560d06aSjeremylt     ierr = CeedQFunctionReference(dqf); CeedChk(ierr);
709442e7f0bSjeremylt   }
710442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
711d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
7129560d06aSjeremylt     ierr = CeedQFunctionReference(dqfT); CeedChk(ierr);
713442e7f0bSjeremylt   }
714d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr);
715d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr);
716d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
717e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
718d7b241e6Sjeremylt }
719d7b241e6Sjeremylt 
720d7b241e6Sjeremylt /**
72152d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
72252d6035fSJeremy L Thompson 
72352d6035fSJeremy L Thompson   @param ceed     A Ceed object where the CeedOperator will be created
72452d6035fSJeremy L Thompson   @param[out] op  Address of the variable where the newly created
72552d6035fSJeremy L Thompson                     Composite CeedOperator will be stored
72652d6035fSJeremy L Thompson 
72752d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
72852d6035fSJeremy L Thompson 
7297a982d89SJeremy L. Thompson   @ref User
73052d6035fSJeremy L Thompson  */
73152d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
73252d6035fSJeremy L Thompson   int ierr;
73352d6035fSJeremy L Thompson 
73452d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
73552d6035fSJeremy L Thompson     Ceed delegate;
736aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
73752d6035fSJeremy L Thompson 
738250756a7Sjeremylt     if (delegate) {
73952d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
740e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
74152d6035fSJeremy L Thompson     }
742250756a7Sjeremylt   }
74352d6035fSJeremy L Thompson 
74452d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
74552d6035fSJeremy L Thompson   (*op)->ceed = ceed;
7469560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
74752d6035fSJeremy L Thompson   (*op)->composite = true;
748d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr);
749250756a7Sjeremylt 
750250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
75152d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
752250756a7Sjeremylt   }
753e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
75452d6035fSJeremy L Thompson }
75552d6035fSJeremy L Thompson 
75652d6035fSJeremy L Thompson /**
7579560d06aSjeremylt   @brief Copy the pointer to a CeedOperator. Both pointers should
7589560d06aSjeremylt            be destroyed with `CeedOperatorDestroy()`;
7599560d06aSjeremylt            Note: If `*op_copy` is non-NULL, then it is assumed that
7609560d06aSjeremylt            `*op_copy` is a pointer to a CeedOperator. This
7619560d06aSjeremylt            CeedOperator will be destroyed if `*op_copy` is the only
7629560d06aSjeremylt            reference to this CeedOperator.
7639560d06aSjeremylt 
7649560d06aSjeremylt   @param op            CeedOperator to copy reference to
7659560d06aSjeremylt   @param[out] op_copy  Variable to store copied reference
7669560d06aSjeremylt 
7679560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
7689560d06aSjeremylt 
7699560d06aSjeremylt   @ref User
7709560d06aSjeremylt **/
7719560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
7729560d06aSjeremylt   int ierr;
7739560d06aSjeremylt 
7749560d06aSjeremylt   ierr = CeedOperatorReference(op); CeedChk(ierr);
7759560d06aSjeremylt   ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr);
7769560d06aSjeremylt   *op_copy = op;
7779560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7789560d06aSjeremylt }
7799560d06aSjeremylt 
7809560d06aSjeremylt /**
781b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
782d7b241e6Sjeremylt 
783d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
784d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
785d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
786d7b241e6Sjeremylt 
787d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
788d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
789d7b241e6Sjeremylt   input and at most one active output.
790d7b241e6Sjeremylt 
7918c91a0c9SJeremy L Thompson   @param op          CeedOperator on which to provide the field
792d1d35e2fSjeremylt   @param field_name  Name of the field (to be matched with the name used by
7938795c945Sjeremylt                        CeedQFunction)
794b11c1e72Sjeremylt   @param r           CeedElemRestriction
7954cc79fe7SJed Brown   @param b           CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED
796b11c1e72Sjeremylt                        if collocated with quadrature points
7974cc79fe7SJed Brown   @param v           CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE
7984cc79fe7SJed Brown                        if field is active or @ref CEED_VECTOR_NONE if using
7994cc79fe7SJed Brown                        @ref CEED_EVAL_WEIGHT in the QFunction
800b11c1e72Sjeremylt 
801b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
802dfdf5a53Sjeremylt 
8037a982d89SJeremy L. Thompson   @ref User
804b11c1e72Sjeremylt **/
805d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name,
806a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
807d7b241e6Sjeremylt   int ierr;
80852d6035fSJeremy L Thompson   if (op->composite)
809c042f62fSJeremy L Thompson     // LCOV_EXCL_START
810e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
811e15f9bd0SJeremy L Thompson                      "Cannot add field to composite operator.");
812c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
8138b067b84SJed Brown   if (!r)
814c042f62fSJeremy L Thompson     // LCOV_EXCL_START
815e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
816c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
817d1d35e2fSjeremylt                      field_name);
818c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
8198b067b84SJed Brown   if (!b)
820c042f62fSJeremy L Thompson     // LCOV_EXCL_START
821e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
822e15f9bd0SJeremy L Thompson                      "Basis b for field \"%s\" must be non-NULL.",
823d1d35e2fSjeremylt                      field_name);
824c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
8258b067b84SJed Brown   if (!v)
826c042f62fSJeremy L Thompson     // LCOV_EXCL_START
827e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
828e15f9bd0SJeremy L Thompson                      "Vector v for field \"%s\" must be non-NULL.",
829d1d35e2fSjeremylt                      field_name);
830c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
83152d6035fSJeremy L Thompson 
832d1d35e2fSjeremylt   CeedInt num_elem;
833d1d35e2fSjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr);
834d1d35e2fSjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction &&
835d1d35e2fSjeremylt       op->num_elem != num_elem)
836c042f62fSJeremy L Thompson     // LCOV_EXCL_START
837e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_DIMENSION,
8381d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
839d1d35e2fSjeremylt                      "%d elements", num_elem, op->num_elem);
840c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
841d7b241e6Sjeremylt 
84278464608Sjeremylt   CeedInt num_qpts = 0;
843e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
844d1d35e2fSjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr);
845d1d35e2fSjeremylt     if (op->num_qpts && op->num_qpts != num_qpts)
846c042f62fSJeremy L Thompson       // LCOV_EXCL_START
847e15f9bd0SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_DIMENSION,
848e15f9bd0SJeremy L Thompson                        "Basis with %d quadrature points "
849d1d35e2fSjeremylt                        "incompatible with prior %d points", num_qpts,
850d1d35e2fSjeremylt                        op->num_qpts);
851c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
852d7b241e6Sjeremylt   }
853d1d35e2fSjeremylt   CeedQFunctionField qf_field;
854d1d35e2fSjeremylt   CeedOperatorField *op_field;
855d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
856d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) {
857d1d35e2fSjeremylt       qf_field = op->qf->input_fields[i];
858d1d35e2fSjeremylt       op_field = &op->input_fields[i];
859d7b241e6Sjeremylt       goto found;
860d7b241e6Sjeremylt     }
861d7b241e6Sjeremylt   }
862d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
863d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) {
864d1d35e2fSjeremylt       qf_field = op->qf->output_fields[i];
865d1d35e2fSjeremylt       op_field = &op->output_fields[i];
866d7b241e6Sjeremylt       goto found;
867d7b241e6Sjeremylt     }
868d7b241e6Sjeremylt   }
869c042f62fSJeremy L Thompson   // LCOV_EXCL_START
870e15f9bd0SJeremy L Thompson   return CeedError(op->ceed, CEED_ERROR_INCOMPLETE,
871e15f9bd0SJeremy L Thompson                    "QFunction has no knowledge of field '%s'",
872d1d35e2fSjeremylt                    field_name);
873c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
874d7b241e6Sjeremylt found:
875d1d35e2fSjeremylt   ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr);
876d1d35e2fSjeremylt   ierr = CeedCalloc(1, op_field); CeedChk(ierr);
877e15f9bd0SJeremy L Thompson 
878d1d35e2fSjeremylt   (*op_field)->vec = v;
879e15f9bd0SJeremy L Thompson   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) {
8809560d06aSjeremylt     ierr = CeedVectorReference(v); CeedChk(ierr);
881e15f9bd0SJeremy L Thompson   }
882e15f9bd0SJeremy L Thompson 
883d1d35e2fSjeremylt   (*op_field)->elem_restr = r;
8849560d06aSjeremylt   ierr = CeedElemRestrictionReference(r); CeedChk(ierr);
885e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
886d1d35e2fSjeremylt     op->num_elem = num_elem;
887d1d35e2fSjeremylt     op->has_restriction = true; // Restriction set, but num_elem may be 0
888e15f9bd0SJeremy L Thompson   }
889d99fa3c5SJeremy L Thompson 
890d1d35e2fSjeremylt   (*op_field)->basis = b;
891e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
892cd4dfc48Sjeremylt     if (!op->num_qpts) {
893cd4dfc48Sjeremylt       ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr);
894cd4dfc48Sjeremylt     }
8959560d06aSjeremylt     ierr = CeedBasisReference(b); CeedChk(ierr);
896e15f9bd0SJeremy L Thompson   }
897e15f9bd0SJeremy L Thompson 
898d1d35e2fSjeremylt   op->num_fields += 1;
899d1d35e2fSjeremylt   size_t len = strlen(field_name);
900d99fa3c5SJeremy L Thompson   char *tmp;
901d99fa3c5SJeremy L Thompson   ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr);
902d1d35e2fSjeremylt   memcpy(tmp, field_name, len+1);
903d1d35e2fSjeremylt   (*op_field)->field_name = tmp;
904e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
905d7b241e6Sjeremylt }
906d7b241e6Sjeremylt 
907d7b241e6Sjeremylt /**
90852d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
909288c0443SJeremy L Thompson 
910d1d35e2fSjeremylt   @param[out] composite_op  Composite CeedOperator
911d1d35e2fSjeremylt   @param      sub_op        Sub-operator CeedOperator
91252d6035fSJeremy L Thompson 
91352d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
91452d6035fSJeremy L Thompson 
9157a982d89SJeremy L. Thompson   @ref User
91652d6035fSJeremy L Thompson  */
917d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op,
918d1d35e2fSjeremylt                                 CeedOperator sub_op) {
91934359f16Sjeremylt   int ierr;
92034359f16Sjeremylt 
921d1d35e2fSjeremylt   if (!composite_op->composite)
922c042f62fSJeremy L Thompson     // LCOV_EXCL_START
923d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_MINOR,
924e2f04181SAndrew T. Barker                      "CeedOperator is not a composite operator");
925c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
92652d6035fSJeremy L Thompson 
927d1d35e2fSjeremylt   if (composite_op->num_suboperators == CEED_COMPOSITE_MAX)
928c042f62fSJeremy L Thompson     // LCOV_EXCL_START
929d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED,
930d1d35e2fSjeremylt                      "Cannot add additional sub_operators");
931c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
93252d6035fSJeremy L Thompson 
933d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
9349560d06aSjeremylt   ierr = CeedOperatorReference(sub_op); CeedChk(ierr);
935d1d35e2fSjeremylt   composite_op->num_suboperators++;
936e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
93752d6035fSJeremy L Thompson }
93852d6035fSJeremy L Thompson 
93952d6035fSJeremy L Thompson /**
940cd4dfc48Sjeremylt   @brief Set the number of quadrature points associated with a CeedOperator.
941cd4dfc48Sjeremylt            This should be used when creating a CeedOperator where every
942cd4dfc48Sjeremylt            field has a collocated basis. This function cannot be used for
943cd4dfc48Sjeremylt            composite CeedOperators.
944cd4dfc48Sjeremylt 
945cd4dfc48Sjeremylt   @param op        CeedOperator
946cd4dfc48Sjeremylt   @param num_qpts  Number of quadrature points to set
947cd4dfc48Sjeremylt 
948cd4dfc48Sjeremylt   @return An error code: 0 - success, otherwise - failure
949cd4dfc48Sjeremylt 
950cd4dfc48Sjeremylt   @ref Backend
951cd4dfc48Sjeremylt **/
952cd4dfc48Sjeremylt 
953cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) {
954cd4dfc48Sjeremylt   if (op->composite)
955cd4dfc48Sjeremylt     // LCOV_EXCL_START
956cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
957cd4dfc48Sjeremylt                      "Not defined for composite operator");
958cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
959cd4dfc48Sjeremylt   if (op->num_qpts)
960cd4dfc48Sjeremylt     // LCOV_EXCL_START
961cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
962cd4dfc48Sjeremylt                      "Number of quadrature points already defined");
963cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
964cd4dfc48Sjeremylt 
965cd4dfc48Sjeremylt   op->num_qpts = num_qpts;
966cd4dfc48Sjeremylt   return CEED_ERROR_SUCCESS;
967cd4dfc48Sjeremylt }
968cd4dfc48Sjeremylt 
969cd4dfc48Sjeremylt /**
9707a982d89SJeremy L. Thompson   @brief View a CeedOperator
9717a982d89SJeremy L. Thompson 
9727a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
9737a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
9747a982d89SJeremy L. Thompson 
9757a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
9767a982d89SJeremy L. Thompson 
9777a982d89SJeremy L. Thompson   @ref User
9787a982d89SJeremy L. Thompson **/
9797a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
9807a982d89SJeremy L. Thompson   int ierr;
9817a982d89SJeremy L. Thompson 
9827a982d89SJeremy L. Thompson   if (op->composite) {
9837a982d89SJeremy L. Thompson     fprintf(stream, "Composite CeedOperator\n");
9847a982d89SJeremy L. Thompson 
985d1d35e2fSjeremylt     for (CeedInt i=0; i<op->num_suboperators; i++) {
9867a982d89SJeremy L. Thompson       fprintf(stream, "  SubOperator [%d]:\n", i);
987d1d35e2fSjeremylt       ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream);
9887a982d89SJeremy L. Thompson       CeedChk(ierr);
9897a982d89SJeremy L. Thompson     }
9907a982d89SJeremy L. Thompson   } else {
9917a982d89SJeremy L. Thompson     fprintf(stream, "CeedOperator\n");
9927a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
9937a982d89SJeremy L. Thompson   }
994e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9957a982d89SJeremy L. Thompson }
9963bd813ffSjeremylt 
9973bd813ffSjeremylt /**
9983bd813ffSjeremylt   @brief Apply CeedOperator to a vector
999d7b241e6Sjeremylt 
1000d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
1001d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1002d7b241e6Sjeremylt   CeedOperatorSetField().
1003d7b241e6Sjeremylt 
1004d7b241e6Sjeremylt   @param op        CeedOperator to apply
10054cc79fe7SJed Brown   @param[in] in    CeedVector containing input state or @ref CEED_VECTOR_NONE if
100634138859Sjeremylt                      there are no active inputs
1007b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
10084cc79fe7SJed Brown                      distinct from @a in) or @ref CEED_VECTOR_NONE if there are no
100934138859Sjeremylt                      active outputs
1010d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
10114cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1012b11c1e72Sjeremylt 
1013b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1014dfdf5a53Sjeremylt 
10157a982d89SJeremy L. Thompson   @ref User
1016b11c1e72Sjeremylt **/
1017692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
1018692c2638Sjeremylt                       CeedRequest *request) {
1019d7b241e6Sjeremylt   int ierr;
1020e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1021d7b241e6Sjeremylt 
1022d1d35e2fSjeremylt   if (op->num_elem)  {
1023250756a7Sjeremylt     // Standard Operator
1024cae8b89aSjeremylt     if (op->Apply) {
1025250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
1026cae8b89aSjeremylt     } else {
1027cae8b89aSjeremylt       // Zero all output vectors
1028250756a7Sjeremylt       CeedQFunction qf = op->qf;
1029d1d35e2fSjeremylt       for (CeedInt i=0; i<qf->num_output_fields; i++) {
1030d1d35e2fSjeremylt         CeedVector vec = op->output_fields[i]->vec;
1031cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
1032cae8b89aSjeremylt           vec = out;
1033cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
1034cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1035cae8b89aSjeremylt         }
1036cae8b89aSjeremylt       }
1037250756a7Sjeremylt       // Apply
1038250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1039250756a7Sjeremylt     }
1040250756a7Sjeremylt   } else if (op->composite) {
1041250756a7Sjeremylt     // Composite Operator
1042250756a7Sjeremylt     if (op->ApplyComposite) {
1043250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
1044250756a7Sjeremylt     } else {
1045d1d35e2fSjeremylt       CeedInt num_suboperators;
1046d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1047d1d35e2fSjeremylt       CeedOperator *sub_operators;
1048d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1049250756a7Sjeremylt 
1050250756a7Sjeremylt       // Zero all output vectors
1051250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
1052cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
1053cae8b89aSjeremylt       }
1054d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1055d1d35e2fSjeremylt         for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) {
1056d1d35e2fSjeremylt           CeedVector vec = sub_operators[i]->output_fields[j]->vec;
1057250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
1058250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1059250756a7Sjeremylt           }
1060250756a7Sjeremylt         }
1061250756a7Sjeremylt       }
1062250756a7Sjeremylt       // Apply
1063d1d35e2fSjeremylt       for (CeedInt i=0; i<op->num_suboperators; i++) {
1064d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request);
1065cae8b89aSjeremylt         CeedChk(ierr);
1066cae8b89aSjeremylt       }
1067cae8b89aSjeremylt     }
1068250756a7Sjeremylt   }
1069e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1070cae8b89aSjeremylt }
1071cae8b89aSjeremylt 
1072cae8b89aSjeremylt /**
1073cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
1074cae8b89aSjeremylt 
1075cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
1076cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1077cae8b89aSjeremylt   CeedOperatorSetField().
1078cae8b89aSjeremylt 
1079cae8b89aSjeremylt   @param op        CeedOperator to apply
1080cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
1081cae8b89aSjeremylt                      active inputs
1082cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
1083cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
1084cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
10854cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1086cae8b89aSjeremylt 
1087cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
1088cae8b89aSjeremylt 
10897a982d89SJeremy L. Thompson   @ref User
1090cae8b89aSjeremylt **/
1091cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
1092cae8b89aSjeremylt                          CeedRequest *request) {
1093cae8b89aSjeremylt   int ierr;
1094e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1095cae8b89aSjeremylt 
1096d1d35e2fSjeremylt   if (op->num_elem)  {
1097250756a7Sjeremylt     // Standard Operator
1098250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1099250756a7Sjeremylt   } else if (op->composite) {
1100250756a7Sjeremylt     // Composite Operator
1101250756a7Sjeremylt     if (op->ApplyAddComposite) {
1102250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
1103cae8b89aSjeremylt     } else {
1104d1d35e2fSjeremylt       CeedInt num_suboperators;
1105d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1106d1d35e2fSjeremylt       CeedOperator *sub_operators;
1107d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1108250756a7Sjeremylt 
1109d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1110d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request);
1111cae8b89aSjeremylt         CeedChk(ierr);
11121d7d2407SJeremy L Thompson       }
1113250756a7Sjeremylt     }
1114250756a7Sjeremylt   }
1115e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1116d7b241e6Sjeremylt }
1117d7b241e6Sjeremylt 
1118d7b241e6Sjeremylt /**
1119b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1120d7b241e6Sjeremylt 
1121d7b241e6Sjeremylt   @param op  CeedOperator to destroy
1122b11c1e72Sjeremylt 
1123b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1124dfdf5a53Sjeremylt 
11257a982d89SJeremy L. Thompson   @ref User
1126b11c1e72Sjeremylt **/
1127d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1128d7b241e6Sjeremylt   int ierr;
1129d7b241e6Sjeremylt 
1130d1d35e2fSjeremylt   if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS;
1131d7b241e6Sjeremylt   if ((*op)->Destroy) {
1132d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1133d7b241e6Sjeremylt   }
1134fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1135fe2413ffSjeremylt   // Free fields
1136d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1137d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
1138d1d35e2fSjeremylt       if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) {
1139d1d35e2fSjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr);
114071352a93Sjeremylt         CeedChk(ierr);
114115910d16Sjeremylt       }
1142d1d35e2fSjeremylt       if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1143d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr);
114471352a93Sjeremylt       }
1145d1d35e2fSjeremylt       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1146d1d35e2fSjeremylt           (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) {
1147d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr);
114871352a93Sjeremylt       }
1149d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr);
1150d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr);
1151fe2413ffSjeremylt     }
1152d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1153d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
1154d1d35e2fSjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr);
115571352a93Sjeremylt       CeedChk(ierr);
1156d1d35e2fSjeremylt       if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1157d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr);
115871352a93Sjeremylt       }
1159d1d35e2fSjeremylt       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1160d1d35e2fSjeremylt           (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) {
1161d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr);
116271352a93Sjeremylt       }
1163d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr);
1164d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr);
1165fe2413ffSjeremylt     }
1166d1d35e2fSjeremylt   // Destroy sub_operators
1167d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_suboperators; i++)
1168d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
1169d1d35e2fSjeremylt       ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr);
117052d6035fSJeremy L Thompson     }
1171e15f9bd0SJeremy L Thompson   if ((*op)->qf)
1172e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
1173d1d35e2fSjeremylt     (*op)->qf->operators_set--;
1174e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
1175d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1176e15f9bd0SJeremy L Thompson   if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE)
1177e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
1178d1d35e2fSjeremylt     (*op)->dqf->operators_set--;
1179e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
1180d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1181e15f9bd0SJeremy L Thompson   if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE)
1182e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
1183d1d35e2fSjeremylt     (*op)->dqfT->operators_set--;
1184e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
1185d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1186fe2413ffSjeremylt 
11875107b09fSJeremy L Thompson   // Destroy fallback
1188d1d35e2fSjeremylt   if ((*op)->op_fallback) {
1189d1d35e2fSjeremylt     ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr);
1190d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr);
1191d1d35e2fSjeremylt     ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr);
1192d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr);
11935107b09fSJeremy L Thompson   }
11945107b09fSJeremy L Thompson 
1195d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr);
1196d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr);
1197d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr);
1198d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1199e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1200d7b241e6Sjeremylt }
1201d7b241e6Sjeremylt 
1202d7b241e6Sjeremylt /// @}
1203