xref: /libCEED/interface/ceed-operator.c (revision 7a982d89c751e293e39d23a7c44a161cef1fcd06)
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 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt #include <string.h>
203bd813ffSjeremylt #include <math.h>
21d7b241e6Sjeremylt 
22dfdf5a53Sjeremylt /// @file
23*7a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces
24*7a982d89SJeremy L. Thompson 
25*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
26*7a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions
27*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
28*7a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper
29*7a982d89SJeremy L. Thompson /// @{
30*7a982d89SJeremy L. Thompson 
31*7a982d89SJeremy L. Thompson /**
32*7a982d89SJeremy L. Thompson   @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced
33*7a982d89SJeremy L. Thompson            CeedOperator functionality
34*7a982d89SJeremy L. Thompson 
35*7a982d89SJeremy L. Thompson   @param op           CeedOperator to create fallback for
36*7a982d89SJeremy L. Thompson 
37*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
38*7a982d89SJeremy L. Thompson 
39*7a982d89SJeremy L. Thompson   @ref Developer
40*7a982d89SJeremy L. Thompson **/
41*7a982d89SJeremy L. Thompson int CeedOperatorCreateFallback(CeedOperator op) {
42*7a982d89SJeremy L. Thompson   int ierr;
43*7a982d89SJeremy L. Thompson 
44*7a982d89SJeremy L. Thompson   // Fallback Ceed
45*7a982d89SJeremy L. Thompson   const char *resource, *fallbackresource;
46*7a982d89SJeremy L. Thompson   ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr);
47*7a982d89SJeremy L. Thompson   ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource);
48*7a982d89SJeremy L. Thompson   CeedChk(ierr);
49*7a982d89SJeremy L. Thompson   if (!strcmp(resource, fallbackresource))
50*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
51*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Backend %s cannot create an operator"
52*7a982d89SJeremy L. Thompson                      "fallback to resource %s", resource, fallbackresource);
53*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
54*7a982d89SJeremy L. Thompson 
55*7a982d89SJeremy L. Thompson   // Fallback Ceed
56*7a982d89SJeremy L. Thompson   Ceed ceedref;
57*7a982d89SJeremy L. Thompson   if (!op->ceed->opfallbackceed) {
58*7a982d89SJeremy L. Thompson     ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr);
59*7a982d89SJeremy L. Thompson     ceedref->opfallbackparent = op->ceed;
60*7a982d89SJeremy L. Thompson     op->ceed->opfallbackceed = ceedref;
61*7a982d89SJeremy L. Thompson   }
62*7a982d89SJeremy L. Thompson   ceedref = op->ceed->opfallbackceed;
63*7a982d89SJeremy L. Thompson 
64*7a982d89SJeremy L. Thompson   // Clone Op
65*7a982d89SJeremy L. Thompson   CeedOperator opref;
66*7a982d89SJeremy L. Thompson   ierr = CeedCalloc(1, &opref); CeedChk(ierr);
67*7a982d89SJeremy L. Thompson   memcpy(opref, op, sizeof(*opref)); CeedChk(ierr);
68*7a982d89SJeremy L. Thompson   opref->data = NULL;
69*7a982d89SJeremy L. Thompson   opref->setupdone = 0;
70*7a982d89SJeremy L. Thompson   opref->ceed = ceedref;
71*7a982d89SJeremy L. Thompson   ierr = ceedref->OperatorCreate(opref); CeedChk(ierr);
72*7a982d89SJeremy L. Thompson   op->opfallback = opref;
73*7a982d89SJeremy L. Thompson 
74*7a982d89SJeremy L. Thompson   // Clone QF
75*7a982d89SJeremy L. Thompson   CeedQFunction qfref;
76*7a982d89SJeremy L. Thompson   ierr = CeedCalloc(1, &qfref); CeedChk(ierr);
77*7a982d89SJeremy L. Thompson   memcpy(qfref, (op->qf), sizeof(*qfref)); CeedChk(ierr);
78*7a982d89SJeremy L. Thompson   qfref->data = NULL;
79*7a982d89SJeremy L. Thompson   qfref->ceed = ceedref;
80*7a982d89SJeremy L. Thompson   ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr);
81*7a982d89SJeremy L. Thompson   opref->qf = qfref;
82*7a982d89SJeremy L. Thompson   op->qffallback = qfref;
83*7a982d89SJeremy L. Thompson 
84*7a982d89SJeremy L. Thompson   return 0;
85*7a982d89SJeremy L. Thompson }
86*7a982d89SJeremy L. Thompson 
87*7a982d89SJeremy L. Thompson /**
88*7a982d89SJeremy L. Thompson   @brief Check if a CeedOperator is ready to be used.
89*7a982d89SJeremy L. Thompson 
90*7a982d89SJeremy L. Thompson   @param[in] ceed Ceed object for error handling
91*7a982d89SJeremy L. Thompson   @param[in] op   CeedOperator to check
92*7a982d89SJeremy L. Thompson 
93*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
94*7a982d89SJeremy L. Thompson 
95*7a982d89SJeremy L. Thompson   @ref Developer
96*7a982d89SJeremy L. Thompson **/
97*7a982d89SJeremy L. Thompson static int CeedOperatorCheckReady(Ceed ceed, CeedOperator op) {
98*7a982d89SJeremy L. Thompson   CeedQFunction qf = op->qf;
99*7a982d89SJeremy L. Thompson 
100*7a982d89SJeremy L. Thompson   if (op->composite) {
101*7a982d89SJeremy L. Thompson     if (!op->numsub)
102*7a982d89SJeremy L. Thompson       // LCOV_EXCL_START
103*7a982d89SJeremy L. Thompson       return CeedError(ceed, 1, "No suboperators set");
104*7a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
105*7a982d89SJeremy L. Thompson   } else {
106*7a982d89SJeremy L. Thompson     if (op->nfields == 0)
107*7a982d89SJeremy L. Thompson       // LCOV_EXCL_START
108*7a982d89SJeremy L. Thompson       return CeedError(ceed, 1, "No operator fields set");
109*7a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
110*7a982d89SJeremy L. Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
111*7a982d89SJeremy L. Thompson       // LCOV_EXCL_START
112*7a982d89SJeremy L. Thompson       return CeedError(ceed, 1, "Not all operator fields set");
113*7a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
114*7a982d89SJeremy L. Thompson     if (!op->hasrestriction)
115*7a982d89SJeremy L. Thompson       // LCOV_EXCL_START
116*7a982d89SJeremy L. Thompson       return CeedError(ceed, 1,"At least one restriction required");
117*7a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
118*7a982d89SJeremy L. Thompson     if (op->numqpoints == 0)
119*7a982d89SJeremy L. Thompson       // LCOV_EXCL_START
120*7a982d89SJeremy L. Thompson       return CeedError(ceed, 1,"At least one non-collocated basis required");
121*7a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
122*7a982d89SJeremy L. Thompson   }
123*7a982d89SJeremy L. Thompson 
124*7a982d89SJeremy L. Thompson   return 0;
125*7a982d89SJeremy L. Thompson }
126*7a982d89SJeremy L. Thompson 
127*7a982d89SJeremy L. Thompson /**
128*7a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
129*7a982d89SJeremy L. Thompson 
130*7a982d89SJeremy L. Thompson   @param[in] field       Operator field to view
131*7a982d89SJeremy L. Thompson   @param[in] fieldnumber Number of field being viewed
132*7a982d89SJeremy L. Thompson   @param[in] stream      Stream to view to, e.g., stdout
133*7a982d89SJeremy L. Thompson 
134*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
135*7a982d89SJeremy L. Thompson 
136*7a982d89SJeremy L. Thompson   @ref Utility
137*7a982d89SJeremy L. Thompson **/
138*7a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
139*7a982d89SJeremy L. Thompson                                  CeedQFunctionField qffield,
140*7a982d89SJeremy L. Thompson                                  CeedInt fieldnumber, bool sub, bool in,
141*7a982d89SJeremy L. Thompson                                  FILE *stream) {
142*7a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
143*7a982d89SJeremy L. Thompson   const char *inout = in ? "Input" : "Output";
144*7a982d89SJeremy L. Thompson 
145*7a982d89SJeremy L. Thompson   fprintf(stream, "%s    %s Field [%d]:\n"
146*7a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
147*7a982d89SJeremy L. Thompson           pre, inout, fieldnumber, pre, qffield->fieldname);
148*7a982d89SJeremy L. Thompson 
149*7a982d89SJeremy L. Thompson   if (field->basis == CEED_BASIS_COLLOCATED)
150*7a982d89SJeremy L. Thompson     fprintf(stream, "%s      Collocated basis\n", pre);
151*7a982d89SJeremy L. Thompson 
152*7a982d89SJeremy L. Thompson   if (field->vec == CEED_VECTOR_ACTIVE)
153*7a982d89SJeremy L. Thompson     fprintf(stream, "%s      Active vector\n", pre);
154*7a982d89SJeremy L. Thompson   else if (field->vec == CEED_VECTOR_NONE)
155*7a982d89SJeremy L. Thompson     fprintf(stream, "%s      No vector\n", pre);
156*7a982d89SJeremy L. Thompson 
157*7a982d89SJeremy L. Thompson   return 0;
158*7a982d89SJeremy L. Thompson }
159*7a982d89SJeremy L. Thompson 
160*7a982d89SJeremy L. Thompson /**
161*7a982d89SJeremy L. Thompson   @brief View a single CeedOperator
162*7a982d89SJeremy L. Thompson 
163*7a982d89SJeremy L. Thompson   @param[in] op     CeedOperator to view
164*7a982d89SJeremy L. Thompson   @param[in] sub    Boolean flag for sub-operator
165*7a982d89SJeremy L. Thompson   @param[in] stream Stream to write; typically stdout/stderr or a file
166*7a982d89SJeremy L. Thompson 
167*7a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
168*7a982d89SJeremy L. Thompson 
169*7a982d89SJeremy L. Thompson   @ref Utility
170*7a982d89SJeremy L. Thompson **/
171*7a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
172*7a982d89SJeremy L. Thompson   int ierr;
173*7a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
174*7a982d89SJeremy L. Thompson 
175*7a982d89SJeremy L. Thompson   CeedInt totalfields;
176*7a982d89SJeremy L. Thompson   ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr);
177*7a982d89SJeremy L. Thompson 
178*7a982d89SJeremy L. Thompson   fprintf(stream, "%s  %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : "");
179*7a982d89SJeremy L. Thompson 
180*7a982d89SJeremy L. Thompson   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->numinputfields,
181*7a982d89SJeremy L. Thompson           op->qf->numinputfields>1 ? "s" : "");
182*7a982d89SJeremy L. Thompson   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
183*7a982d89SJeremy L. Thompson     ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i],
184*7a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
185*7a982d89SJeremy L. Thompson   }
186*7a982d89SJeremy L. Thompson 
187*7a982d89SJeremy L. Thompson   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->numoutputfields,
188*7a982d89SJeremy L. Thompson           op->qf->numoutputfields>1 ? "s" : "");
189*7a982d89SJeremy L. Thompson   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
190*7a982d89SJeremy L. Thompson     ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i],
191*7a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
192*7a982d89SJeremy L. Thompson   }
193*7a982d89SJeremy L. Thompson 
194*7a982d89SJeremy L. Thompson   return 0;
195*7a982d89SJeremy L. Thompson }
196*7a982d89SJeremy L. Thompson 
197*7a982d89SJeremy L. Thompson /// @}
198*7a982d89SJeremy L. Thompson 
199*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
200*7a982d89SJeremy L. Thompson /// CeedOperator Backend API
201*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
202*7a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
203*7a982d89SJeremy L. Thompson /// @{
204*7a982d89SJeremy L. Thompson 
205*7a982d89SJeremy L. Thompson /**
206*7a982d89SJeremy L. Thompson   @brief Get the Ceed associated with a CeedOperator
207*7a982d89SJeremy L. Thompson 
208*7a982d89SJeremy L. Thompson   @param op              CeedOperator
209*7a982d89SJeremy L. Thompson   @param[out] ceed       Variable to store Ceed
210*7a982d89SJeremy L. Thompson 
211*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
212*7a982d89SJeremy L. Thompson 
213*7a982d89SJeremy L. Thompson   @ref Backend
214*7a982d89SJeremy L. Thompson **/
215*7a982d89SJeremy L. Thompson 
216*7a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
217*7a982d89SJeremy L. Thompson   *ceed = op->ceed;
218*7a982d89SJeremy L. Thompson   return 0;
219*7a982d89SJeremy L. Thompson }
220*7a982d89SJeremy L. Thompson 
221*7a982d89SJeremy L. Thompson /**
222*7a982d89SJeremy L. Thompson   @brief Get the number of elements associated with a CeedOperator
223*7a982d89SJeremy L. Thompson 
224*7a982d89SJeremy L. Thompson   @param op              CeedOperator
225*7a982d89SJeremy L. Thompson   @param[out] numelem    Variable to store number of elements
226*7a982d89SJeremy L. Thompson 
227*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
228*7a982d89SJeremy L. Thompson 
229*7a982d89SJeremy L. Thompson   @ref Backend
230*7a982d89SJeremy L. Thompson **/
231*7a982d89SJeremy L. Thompson 
232*7a982d89SJeremy L. Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
233*7a982d89SJeremy L. Thompson   if (op->composite)
234*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
235*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
236*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
237*7a982d89SJeremy L. Thompson 
238*7a982d89SJeremy L. Thompson   *numelem = op->numelements;
239*7a982d89SJeremy L. Thompson   return 0;
240*7a982d89SJeremy L. Thompson }
241*7a982d89SJeremy L. Thompson 
242*7a982d89SJeremy L. Thompson /**
243*7a982d89SJeremy L. Thompson   @brief Get the number of quadrature points associated with a CeedOperator
244*7a982d89SJeremy L. Thompson 
245*7a982d89SJeremy L. Thompson   @param op              CeedOperator
246*7a982d89SJeremy L. Thompson   @param[out] numqpts    Variable to store vector number of quadrature points
247*7a982d89SJeremy L. Thompson 
248*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
249*7a982d89SJeremy L. Thompson 
250*7a982d89SJeremy L. Thompson   @ref Backend
251*7a982d89SJeremy L. Thompson **/
252*7a982d89SJeremy L. Thompson 
253*7a982d89SJeremy L. Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
254*7a982d89SJeremy L. Thompson   if (op->composite)
255*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
256*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
257*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
258*7a982d89SJeremy L. Thompson 
259*7a982d89SJeremy L. Thompson   *numqpts = op->numqpoints;
260*7a982d89SJeremy L. Thompson   return 0;
261*7a982d89SJeremy L. Thompson }
262*7a982d89SJeremy L. Thompson 
263*7a982d89SJeremy L. Thompson /**
264*7a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
265*7a982d89SJeremy L. Thompson 
266*7a982d89SJeremy L. Thompson   @param op              CeedOperator
267*7a982d89SJeremy L. Thompson   @param[out] numargs    Variable to store vector number of arguments
268*7a982d89SJeremy L. Thompson 
269*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
270*7a982d89SJeremy L. Thompson 
271*7a982d89SJeremy L. Thompson   @ref Backend
272*7a982d89SJeremy L. Thompson **/
273*7a982d89SJeremy L. Thompson 
274*7a982d89SJeremy L. Thompson int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
275*7a982d89SJeremy L. Thompson   if (op->composite)
276*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
277*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not defined for composite operators");
278*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
279*7a982d89SJeremy L. Thompson 
280*7a982d89SJeremy L. Thompson   *numargs = op->nfields;
281*7a982d89SJeremy L. Thompson   return 0;
282*7a982d89SJeremy L. Thompson }
283*7a982d89SJeremy L. Thompson 
284*7a982d89SJeremy L. Thompson /**
285*7a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
286*7a982d89SJeremy L. Thompson 
287*7a982d89SJeremy L. Thompson   @param op             CeedOperator
288*7a982d89SJeremy L. Thompson   @param[out] setupdone Variable to store setup status
289*7a982d89SJeremy L. Thompson 
290*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
291*7a982d89SJeremy L. Thompson 
292*7a982d89SJeremy L. Thompson   @ref Backend
293*7a982d89SJeremy L. Thompson **/
294*7a982d89SJeremy L. Thompson 
295*7a982d89SJeremy L. Thompson int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
296*7a982d89SJeremy L. Thompson   *setupdone = op->setupdone;
297*7a982d89SJeremy L. Thompson   return 0;
298*7a982d89SJeremy L. Thompson }
299*7a982d89SJeremy L. Thompson 
300*7a982d89SJeremy L. Thompson /**
301*7a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
302*7a982d89SJeremy L. Thompson 
303*7a982d89SJeremy L. Thompson   @param op              CeedOperator
304*7a982d89SJeremy L. Thompson   @param[out] qf         Variable to store QFunction
305*7a982d89SJeremy L. Thompson 
306*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
307*7a982d89SJeremy L. Thompson 
308*7a982d89SJeremy L. Thompson   @ref Backend
309*7a982d89SJeremy L. Thompson **/
310*7a982d89SJeremy L. Thompson 
311*7a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
312*7a982d89SJeremy L. Thompson   if (op->composite)
313*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
314*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
315*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
316*7a982d89SJeremy L. Thompson 
317*7a982d89SJeremy L. Thompson   *qf = op->qf;
318*7a982d89SJeremy L. Thompson   return 0;
319*7a982d89SJeremy L. Thompson }
320*7a982d89SJeremy L. Thompson 
321*7a982d89SJeremy L. Thompson /**
322*7a982d89SJeremy L. Thompson   @brief Get the number of suboperators associated with a CeedOperator
323*7a982d89SJeremy L. Thompson 
324*7a982d89SJeremy L. Thompson   @param op              CeedOperator
325*7a982d89SJeremy L. Thompson   @param[out] numsub     Variable to store number of suboperators
326*7a982d89SJeremy L. Thompson 
327*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
328*7a982d89SJeremy L. Thompson 
329*7a982d89SJeremy L. Thompson   @ref Backend
330*7a982d89SJeremy L. Thompson **/
331*7a982d89SJeremy L. Thompson 
332*7a982d89SJeremy L. Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) {
333*7a982d89SJeremy L. Thompson   if (!op->composite)
334*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
335*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
336*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
337*7a982d89SJeremy L. Thompson 
338*7a982d89SJeremy L. Thompson   *numsub = op->numsub;
339*7a982d89SJeremy L. Thompson   return 0;
340*7a982d89SJeremy L. Thompson }
341*7a982d89SJeremy L. Thompson 
342*7a982d89SJeremy L. Thompson /**
343*7a982d89SJeremy L. Thompson   @brief Get the list of suboperators associated with a CeedOperator
344*7a982d89SJeremy L. Thompson 
345*7a982d89SJeremy L. Thompson   @param op                CeedOperator
346*7a982d89SJeremy L. Thompson   @param[out] suboperators Variable to store list of suboperators
347*7a982d89SJeremy L. Thompson 
348*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
349*7a982d89SJeremy L. Thompson 
350*7a982d89SJeremy L. Thompson   @ref Backend
351*7a982d89SJeremy L. Thompson **/
352*7a982d89SJeremy L. Thompson 
353*7a982d89SJeremy L. Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) {
354*7a982d89SJeremy L. Thompson   if (!op->composite)
355*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
356*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
357*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
358*7a982d89SJeremy L. Thompson 
359*7a982d89SJeremy L. Thompson   *suboperators = op->suboperators;
360*7a982d89SJeremy L. Thompson   return 0;
361*7a982d89SJeremy L. Thompson }
362*7a982d89SJeremy L. Thompson 
363*7a982d89SJeremy L. Thompson /**
364*7a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
365*7a982d89SJeremy L. Thompson 
366*7a982d89SJeremy L. Thompson   @param op              CeedOperator
367*7a982d89SJeremy L. Thompson   @param[out] data       Variable to store data
368*7a982d89SJeremy L. Thompson 
369*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
370*7a982d89SJeremy L. Thompson 
371*7a982d89SJeremy L. Thompson   @ref Backend
372*7a982d89SJeremy L. Thompson **/
373*7a982d89SJeremy L. Thompson 
374*7a982d89SJeremy L. Thompson int CeedOperatorGetData(CeedOperator op, void **data) {
375*7a982d89SJeremy L. Thompson   *data = op->data;
376*7a982d89SJeremy L. Thompson   return 0;
377*7a982d89SJeremy L. Thompson }
378*7a982d89SJeremy L. Thompson 
379*7a982d89SJeremy L. Thompson /**
380*7a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
381*7a982d89SJeremy L. Thompson 
382*7a982d89SJeremy L. Thompson   @param[out] op         CeedOperator
383*7a982d89SJeremy L. Thompson   @param data            Data to set
384*7a982d89SJeremy L. Thompson 
385*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
386*7a982d89SJeremy L. Thompson 
387*7a982d89SJeremy L. Thompson   @ref Backend
388*7a982d89SJeremy L. Thompson **/
389*7a982d89SJeremy L. Thompson 
390*7a982d89SJeremy L. Thompson int CeedOperatorSetData(CeedOperator op, void **data) {
391*7a982d89SJeremy L. Thompson   op->data = *data;
392*7a982d89SJeremy L. Thompson   return 0;
393*7a982d89SJeremy L. Thompson }
394*7a982d89SJeremy L. Thompson 
395*7a982d89SJeremy L. Thompson /**
396*7a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
397*7a982d89SJeremy L. Thompson 
398*7a982d89SJeremy L. Thompson   @param op              CeedOperator
399*7a982d89SJeremy L. Thompson 
400*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
401*7a982d89SJeremy L. Thompson 
402*7a982d89SJeremy L. Thompson   @ref Backend
403*7a982d89SJeremy L. Thompson **/
404*7a982d89SJeremy L. Thompson 
405*7a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
406*7a982d89SJeremy L. Thompson   op->setupdone = 1;
407*7a982d89SJeremy L. Thompson   return 0;
408*7a982d89SJeremy L. Thompson }
409*7a982d89SJeremy L. Thompson 
410*7a982d89SJeremy L. Thompson /**
411*7a982d89SJeremy L. Thompson   @brief Get the CeedOperatorFields of a CeedOperator
412*7a982d89SJeremy L. Thompson 
413*7a982d89SJeremy L. Thompson   @param op                 CeedOperator
414*7a982d89SJeremy L. Thompson   @param[out] inputfields   Variable to store inputfields
415*7a982d89SJeremy L. Thompson   @param[out] outputfields  Variable to store outputfields
416*7a982d89SJeremy L. Thompson 
417*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
418*7a982d89SJeremy L. Thompson 
419*7a982d89SJeremy L. Thompson   @ref Backend
420*7a982d89SJeremy L. Thompson **/
421*7a982d89SJeremy L. Thompson 
422*7a982d89SJeremy L. Thompson int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields,
423*7a982d89SJeremy L. Thompson                           CeedOperatorField **outputfields) {
424*7a982d89SJeremy L. Thompson   if (op->composite)
425*7a982d89SJeremy L. Thompson     // LCOV_EXCL_START
426*7a982d89SJeremy L. Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
427*7a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
428*7a982d89SJeremy L. Thompson 
429*7a982d89SJeremy L. Thompson   if (inputfields) *inputfields = op->inputfields;
430*7a982d89SJeremy L. Thompson   if (outputfields) *outputfields = op->outputfields;
431*7a982d89SJeremy L. Thompson   return 0;
432*7a982d89SJeremy L. Thompson }
433*7a982d89SJeremy L. Thompson 
434*7a982d89SJeremy L. Thompson /**
435*7a982d89SJeremy L. Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
436*7a982d89SJeremy L. Thompson 
437*7a982d89SJeremy L. Thompson   @param opfield         CeedOperatorField
438*7a982d89SJeremy L. Thompson   @param[out] rstr       Variable to store CeedElemRestriction
439*7a982d89SJeremy L. Thompson 
440*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
441*7a982d89SJeremy L. Thompson 
442*7a982d89SJeremy L. Thompson   @ref Backend
443*7a982d89SJeremy L. Thompson **/
444*7a982d89SJeremy L. Thompson 
445*7a982d89SJeremy L. Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
446*7a982d89SJeremy L. Thompson                                         CeedElemRestriction *rstr) {
447*7a982d89SJeremy L. Thompson   *rstr = opfield->Erestrict;
448*7a982d89SJeremy L. Thompson   return 0;
449*7a982d89SJeremy L. Thompson }
450*7a982d89SJeremy L. Thompson 
451*7a982d89SJeremy L. Thompson /**
452*7a982d89SJeremy L. Thompson   @brief Get the CeedBasis of a CeedOperatorField
453*7a982d89SJeremy L. Thompson 
454*7a982d89SJeremy L. Thompson   @param opfield         CeedOperatorField
455*7a982d89SJeremy L. Thompson   @param[out] basis      Variable to store CeedBasis
456*7a982d89SJeremy L. Thompson 
457*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
458*7a982d89SJeremy L. Thompson 
459*7a982d89SJeremy L. Thompson   @ref Backend
460*7a982d89SJeremy L. Thompson **/
461*7a982d89SJeremy L. Thompson 
462*7a982d89SJeremy L. Thompson int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) {
463*7a982d89SJeremy L. Thompson   *basis = opfield->basis;
464*7a982d89SJeremy L. Thompson   return 0;
465*7a982d89SJeremy L. Thompson }
466*7a982d89SJeremy L. Thompson 
467*7a982d89SJeremy L. Thompson /**
468*7a982d89SJeremy L. Thompson   @brief Get the CeedVector of a CeedOperatorField
469*7a982d89SJeremy L. Thompson 
470*7a982d89SJeremy L. Thompson   @param opfield         CeedOperatorField
471*7a982d89SJeremy L. Thompson   @param[out] vec        Variable to store CeedVector
472*7a982d89SJeremy L. Thompson 
473*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
474*7a982d89SJeremy L. Thompson 
475*7a982d89SJeremy L. Thompson   @ref Backend
476*7a982d89SJeremy L. Thompson **/
477*7a982d89SJeremy L. Thompson 
478*7a982d89SJeremy L. Thompson int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) {
479*7a982d89SJeremy L. Thompson   *vec = opfield->vec;
480*7a982d89SJeremy L. Thompson   return 0;
481*7a982d89SJeremy L. Thompson }
482*7a982d89SJeremy L. Thompson 
483*7a982d89SJeremy L. Thompson /// @}
484*7a982d89SJeremy L. Thompson 
485*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
486*7a982d89SJeremy L. Thompson /// CeedOperator Public API
487*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
488*7a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
489dfdf5a53Sjeremylt /// @{
490d7b241e6Sjeremylt 
491d7b241e6Sjeremylt /**
4920219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
4930219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
4940219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
495d7b241e6Sjeremylt 
496b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
497d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
49834138859Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or
49934138859Sjeremylt                    CEED_QFUNCTION_NONE)
500d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
50134138859Sjeremylt                    of @a qf (or CEED_QFUNCTION_NONE)
502b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
503b11c1e72Sjeremylt                      CeedOperator will be stored
504b11c1e72Sjeremylt 
505b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
506dfdf5a53Sjeremylt 
507*7a982d89SJeremy L. Thompson   @ref User
508d7b241e6Sjeremylt  */
509d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
510d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
511d7b241e6Sjeremylt   int ierr;
512d7b241e6Sjeremylt 
5135fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
5145fe0d4faSjeremylt     Ceed delegate;
515aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
5165fe0d4faSjeremylt 
5175fe0d4faSjeremylt     if (!delegate)
518c042f62fSJeremy L Thompson       // LCOV_EXCL_START
5195fe0d4faSjeremylt       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
520c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5215fe0d4faSjeremylt 
5225fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
5235fe0d4faSjeremylt     return 0;
5245fe0d4faSjeremylt   }
5255fe0d4faSjeremylt 
526d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
527d7b241e6Sjeremylt   (*op)->ceed = ceed;
528d7b241e6Sjeremylt   ceed->refcount++;
529d7b241e6Sjeremylt   (*op)->refcount = 1;
530442e7f0bSjeremylt   if (qf == CEED_QFUNCTION_NONE)
531442e7f0bSjeremylt     // LCOV_EXCL_START
532442e7f0bSjeremylt     return CeedError(ceed, 1, "Operator must have a valid QFunction.");
533442e7f0bSjeremylt   // LCOV_EXCL_STOP
534d7b241e6Sjeremylt   (*op)->qf = qf;
535d7b241e6Sjeremylt   qf->refcount++;
536442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
537d7b241e6Sjeremylt     (*op)->dqf = dqf;
538442e7f0bSjeremylt     dqf->refcount++;
539442e7f0bSjeremylt   }
540442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
541d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
542442e7f0bSjeremylt     dqfT->refcount++;
543442e7f0bSjeremylt   }
544fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr);
545fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr);
546d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
547d7b241e6Sjeremylt   return 0;
548d7b241e6Sjeremylt }
549d7b241e6Sjeremylt 
550d7b241e6Sjeremylt /**
55152d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
55252d6035fSJeremy L Thompson 
55352d6035fSJeremy L Thompson   @param ceed    A Ceed object where the CeedOperator will be created
55452d6035fSJeremy L Thompson   @param[out] op Address of the variable where the newly created
55552d6035fSJeremy L Thompson                      Composite CeedOperator will be stored
55652d6035fSJeremy L Thompson 
55752d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
55852d6035fSJeremy L Thompson 
559*7a982d89SJeremy L. Thompson   @ref User
56052d6035fSJeremy L Thompson  */
56152d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
56252d6035fSJeremy L Thompson   int ierr;
56352d6035fSJeremy L Thompson 
56452d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
56552d6035fSJeremy L Thompson     Ceed delegate;
566aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
56752d6035fSJeremy L Thompson 
568250756a7Sjeremylt     if (delegate) {
56952d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
57052d6035fSJeremy L Thompson       return 0;
57152d6035fSJeremy L Thompson     }
572250756a7Sjeremylt   }
57352d6035fSJeremy L Thompson 
57452d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
57552d6035fSJeremy L Thompson   (*op)->ceed = ceed;
57652d6035fSJeremy L Thompson   ceed->refcount++;
57752d6035fSJeremy L Thompson   (*op)->composite = true;
57852d6035fSJeremy L Thompson   ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr);
579250756a7Sjeremylt 
580250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
58152d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
582250756a7Sjeremylt   }
58352d6035fSJeremy L Thompson   return 0;
58452d6035fSJeremy L Thompson }
58552d6035fSJeremy L Thompson 
58652d6035fSJeremy L Thompson /**
587b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
588d7b241e6Sjeremylt 
589d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
590d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
591d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
592d7b241e6Sjeremylt 
593d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
594d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
595d7b241e6Sjeremylt   input and at most one active output.
596d7b241e6Sjeremylt 
5978c91a0c9SJeremy L Thompson   @param op         CeedOperator on which to provide the field
5988795c945Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by
5998795c945Sjeremylt                       CeedQFunction)
600b11c1e72Sjeremylt   @param r          CeedElemRestriction
601783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
602b11c1e72Sjeremylt                       if collocated with quadrature points
603b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
604b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
6058c91a0c9SJeremy L Thompson                       CEED_EVAL_WEIGHT in the QFunction
606b11c1e72Sjeremylt 
607b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
608dfdf5a53Sjeremylt 
609*7a982d89SJeremy L. Thompson   @ref User
610b11c1e72Sjeremylt **/
611d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
612a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
613d7b241e6Sjeremylt   int ierr;
61452d6035fSJeremy L Thompson   if (op->composite)
615c042f62fSJeremy L Thompson     // LCOV_EXCL_START
61652d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Cannot add field to composite operator.");
617c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6188b067b84SJed Brown   if (!r)
619c042f62fSJeremy L Thompson     // LCOV_EXCL_START
620c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1,
621c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
622c042f62fSJeremy L Thompson                      fieldname);
623c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6248b067b84SJed Brown   if (!b)
625c042f62fSJeremy L Thompson     // LCOV_EXCL_START
626c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.",
627c042f62fSJeremy L Thompson                      fieldname);
628c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6298b067b84SJed Brown   if (!v)
630c042f62fSJeremy L Thompson     // LCOV_EXCL_START
631c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.",
632c042f62fSJeremy L Thompson                      fieldname);
633c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
63452d6035fSJeremy L Thompson 
635d7b241e6Sjeremylt   CeedInt numelements;
636d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
63715910d16Sjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->hasrestriction &&
63815910d16Sjeremylt       op->numelements != numelements)
639c042f62fSJeremy L Thompson     // LCOV_EXCL_START
640d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
6411d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
6421d102b48SJeremy L Thompson                      "%d elements", numelements, op->numelements);
643c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
64415910d16Sjeremylt   if (r != CEED_ELEMRESTRICTION_NONE) {
645d7b241e6Sjeremylt     op->numelements = numelements;
6462cb0afc5Sjeremylt     op->hasrestriction = true; // Restriction set, but numelements may be 0
64715910d16Sjeremylt   }
648d7b241e6Sjeremylt 
649783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
650d7b241e6Sjeremylt     CeedInt numqpoints;
651d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
652d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
653c042f62fSJeremy L Thompson       // LCOV_EXCL_START
6541d102b48SJeremy L Thompson       return CeedError(op->ceed, 1, "Basis with %d quadrature points "
6551d102b48SJeremy L Thompson                        "incompatible with prior %d points", numqpoints,
6561d102b48SJeremy L Thompson                        op->numqpoints);
657c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
658d7b241e6Sjeremylt     op->numqpoints = numqpoints;
659d7b241e6Sjeremylt   }
66015910d16Sjeremylt   CeedQFunctionField qfield;
661d1bcdac9Sjeremylt   CeedOperatorField *ofield;
662d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
663fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) {
66415910d16Sjeremylt       qfield = op->qf->inputfields[i];
665d7b241e6Sjeremylt       ofield = &op->inputfields[i];
666d7b241e6Sjeremylt       goto found;
667d7b241e6Sjeremylt     }
668d7b241e6Sjeremylt   }
669d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
670fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) {
67115910d16Sjeremylt       qfield = op->qf->inputfields[i];
672d7b241e6Sjeremylt       ofield = &op->outputfields[i];
673d7b241e6Sjeremylt       goto found;
674d7b241e6Sjeremylt     }
675d7b241e6Sjeremylt   }
676c042f62fSJeremy L Thompson   // LCOV_EXCL_START
677d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
678d7b241e6Sjeremylt                    fieldname);
679c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
680d7b241e6Sjeremylt found:
68115910d16Sjeremylt   if (r == CEED_ELEMRESTRICTION_NONE && qfield->emode != CEED_EVAL_WEIGHT)
68215910d16Sjeremylt     return CeedError(op->ceed, 1, "CEED_ELEMRESTRICTION_NONE can only be used "
68315910d16Sjeremylt                      "for a field with eval mode CEED_EVAL_WEIGHT");
684fe2413ffSjeremylt   ierr = CeedCalloc(1, ofield); CeedChk(ierr);
685fe2413ffSjeremylt   (*ofield)->Erestrict = r;
68671352a93Sjeremylt   r->refcount += 1;
687fe2413ffSjeremylt   (*ofield)->basis = b;
68871352a93Sjeremylt   if (b != CEED_BASIS_COLLOCATED)
68971352a93Sjeremylt     b->refcount += 1;
690fe2413ffSjeremylt   (*ofield)->vec = v;
69171352a93Sjeremylt   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE)
69271352a93Sjeremylt     v->refcount += 1;
693d7b241e6Sjeremylt   op->nfields += 1;
694d7b241e6Sjeremylt   return 0;
695d7b241e6Sjeremylt }
696d7b241e6Sjeremylt 
697d7b241e6Sjeremylt /**
69852d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
699288c0443SJeremy L Thompson 
70034138859Sjeremylt   @param[out] compositeop Composite CeedOperator
70134138859Sjeremylt   @param      subop       Sub-operator CeedOperator
70252d6035fSJeremy L Thompson 
70352d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
70452d6035fSJeremy L Thompson 
705*7a982d89SJeremy L. Thompson   @ref User
70652d6035fSJeremy L Thompson  */
707692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) {
70852d6035fSJeremy L Thompson   if (!compositeop->composite)
709c042f62fSJeremy L Thompson     // LCOV_EXCL_START
7101d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite "
7111d102b48SJeremy L Thompson                      "operator");
712c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
71352d6035fSJeremy L Thompson 
71452d6035fSJeremy L Thompson   if (compositeop->numsub == CEED_COMPOSITE_MAX)
715c042f62fSJeremy L Thompson     // LCOV_EXCL_START
7161d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators");
717c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
71852d6035fSJeremy L Thompson 
71952d6035fSJeremy L Thompson   compositeop->suboperators[compositeop->numsub] = subop;
72052d6035fSJeremy L Thompson   subop->refcount++;
72152d6035fSJeremy L Thompson   compositeop->numsub++;
72252d6035fSJeremy L Thompson   return 0;
72352d6035fSJeremy L Thompson }
72452d6035fSJeremy L Thompson 
72552d6035fSJeremy L Thompson /**
7261d102b48SJeremy L Thompson   @brief Assemble a linear CeedQFunction associated with a CeedOperator
7271d102b48SJeremy L Thompson 
7281d102b48SJeremy L Thompson   This returns a CeedVector containing a matrix at each quadrature point
7291d102b48SJeremy L Thompson     providing the action of the CeedQFunction associated with the CeedOperator.
7301d102b48SJeremy L Thompson     The vector 'assembled' is of shape
7311d102b48SJeremy L Thompson       [num_elements, num_input_fields, num_output_fields, num_quad_points]
7321d102b48SJeremy L Thompson     and contains column-major matrices representing the action of the
7331d102b48SJeremy L Thompson     CeedQFunction for a corresponding quadrature point on an element. Inputs and
7341d102b48SJeremy L Thompson     outputs are in the order provided by the user when adding CeedOperator fields.
7351d102b48SJeremy L Thompson     For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and
7361d102b48SJeremy L Thompson     'v', provided in that order, would result in an assembled QFunction that
7371d102b48SJeremy L Thompson     consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting
7381d102b48SJeremy L Thompson     on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v].
7391d102b48SJeremy L Thompson 
7401d102b48SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
7411d102b48SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedQFunction at
7421d102b48SJeremy L Thompson                           quadrature points
7431d102b48SJeremy L Thompson   @param[out] rstr      CeedElemRestriction for CeedVector containing assembled
7441d102b48SJeremy L Thompson                           CeedQFunction
7451d102b48SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
7461d102b48SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
7471d102b48SJeremy L Thompson 
7481d102b48SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7491d102b48SJeremy L Thompson 
750*7a982d89SJeremy L. Thompson   @ref User
7511d102b48SJeremy L Thompson **/
7521d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled,
7537f823360Sjeremylt                                         CeedElemRestriction *rstr,
7547f823360Sjeremylt                                         CeedRequest *request) {
7551d102b48SJeremy L Thompson   int ierr;
7561d102b48SJeremy L Thompson   Ceed ceed = op->ceed;
757250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
7581d102b48SJeremy L Thompson 
7597172caadSjeremylt   // Backend version
7605107b09fSJeremy L Thompson   if (op->AssembleLinearQFunction) {
7611d102b48SJeremy L Thompson     ierr = op->AssembleLinearQFunction(op, assembled, rstr, request);
7621d102b48SJeremy L Thompson     CeedChk(ierr);
7635107b09fSJeremy L Thompson   } else {
7645107b09fSJeremy L Thompson     // Fallback to reference Ceed
7655107b09fSJeremy L Thompson     if (!op->opfallback) {
7665107b09fSJeremy L Thompson       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
7675107b09fSJeremy L Thompson     }
7685107b09fSJeremy L Thompson     // Assemble
7695107b09fSJeremy L Thompson     ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled,
7705107b09fSJeremy L Thompson            rstr, request); CeedChk(ierr);
7715107b09fSJeremy L Thompson   }
772250756a7Sjeremylt 
7731d102b48SJeremy L Thompson   return 0;
7741d102b48SJeremy L Thompson }
7751d102b48SJeremy L Thompson 
7761d102b48SJeremy L Thompson /**
777b7ec98d8SJeremy L Thompson   @brief Assemble the diagonal of a square linear Operator
778b7ec98d8SJeremy L Thompson 
779b7ec98d8SJeremy L Thompson   This returns a CeedVector containing the diagonal of a linear CeedOperator.
780b7ec98d8SJeremy L Thompson 
781b7ec98d8SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
782b7ec98d8SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedOperator diagonal
783b7ec98d8SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
784b7ec98d8SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
785b7ec98d8SJeremy L Thompson 
786b7ec98d8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
787b7ec98d8SJeremy L Thompson 
788*7a982d89SJeremy L. Thompson   @ref User
789b7ec98d8SJeremy L Thompson **/
7907f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled,
7917f823360Sjeremylt                                        CeedRequest *request) {
792b7ec98d8SJeremy L Thompson   int ierr;
793b7ec98d8SJeremy L Thompson   Ceed ceed = op->ceed;
794250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
795b7ec98d8SJeremy L Thompson 
796b7ec98d8SJeremy L Thompson   // Use backend version, if available
797b7ec98d8SJeremy L Thompson   if (op->AssembleLinearDiagonal) {
798b7ec98d8SJeremy L Thompson     ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr);
7997172caadSjeremylt   } else {
8007172caadSjeremylt     // Fallback to reference Ceed
8017172caadSjeremylt     if (!op->opfallback) {
8027172caadSjeremylt       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
803b7ec98d8SJeremy L Thompson     }
8047172caadSjeremylt     // Assemble
8057172caadSjeremylt     ierr = op->opfallback->AssembleLinearDiagonal(op->opfallback, assembled,
8067172caadSjeremylt            request); CeedChk(ierr);
807b7ec98d8SJeremy L Thompson   }
808b7ec98d8SJeremy L Thompson 
809b7ec98d8SJeremy L Thompson   return 0;
810b7ec98d8SJeremy L Thompson }
811b7ec98d8SJeremy L Thompson 
812b7ec98d8SJeremy L Thompson /**
8133bd813ffSjeremylt   @brief Build a FDM based approximate inverse for each element for a
8143bd813ffSjeremylt            CeedOperator
8153bd813ffSjeremylt 
8163bd813ffSjeremylt   This returns a CeedOperator and CeedVector to apply a Fast Diagonalization
8173bd813ffSjeremylt     Method based approximate inverse. This function obtains the simultaneous
8183bd813ffSjeremylt     diagonalization for the 1D mass and Laplacian operators,
8193bd813ffSjeremylt       M = V^T V, K = V^T S V.
8203bd813ffSjeremylt     The assembled QFunction is used to modify the eigenvalues from simultaneous
8213bd813ffSjeremylt     diagonalization and obtain an approximate inverse of the form
8223bd813ffSjeremylt       V^T S^hat V. The CeedOperator must be linear and non-composite. The
8233bd813ffSjeremylt     associated CeedQFunction must therefore also be linear.
8243bd813ffSjeremylt 
8253bd813ffSjeremylt   @param op             CeedOperator to create element inverses
8263bd813ffSjeremylt   @param[out] fdminv    CeedOperator to apply the action of a FDM based inverse
8273bd813ffSjeremylt                           for each element
8283bd813ffSjeremylt   @param request        Address of CeedRequest for non-blocking completion, else
8293bd813ffSjeremylt                           CEED_REQUEST_IMMEDIATE
8303bd813ffSjeremylt 
8313bd813ffSjeremylt   @return An error code: 0 - success, otherwise - failure
8323bd813ffSjeremylt 
833*7a982d89SJeremy L. Thompson   @ref Backend
8343bd813ffSjeremylt **/
8353bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv,
8363bd813ffSjeremylt                                         CeedRequest *request) {
8373bd813ffSjeremylt   int ierr;
8383bd813ffSjeremylt   Ceed ceed = op->ceed;
839713f43c3Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
8403bd813ffSjeremylt 
841713f43c3Sjeremylt   // Use backend version, if available
842713f43c3Sjeremylt   if (op->CreateFDMElementInverse) {
843713f43c3Sjeremylt     ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr);
844713f43c3Sjeremylt   } else {
845713f43c3Sjeremylt     // Fallback to reference Ceed
846713f43c3Sjeremylt     if (!op->opfallback) {
847713f43c3Sjeremylt       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
8483bd813ffSjeremylt     }
849713f43c3Sjeremylt     // Assemble
850713f43c3Sjeremylt     ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv,
8513bd813ffSjeremylt            request); CeedChk(ierr);
8523bd813ffSjeremylt   }
8533bd813ffSjeremylt 
8543bd813ffSjeremylt   return 0;
8553bd813ffSjeremylt }
8563bd813ffSjeremylt 
857*7a982d89SJeremy L. Thompson /**
858*7a982d89SJeremy L. Thompson   @brief View a CeedOperator
859*7a982d89SJeremy L. Thompson 
860*7a982d89SJeremy L. Thompson   @param[in] op     CeedOperator to view
861*7a982d89SJeremy L. Thompson   @param[in] stream Stream to write; typically stdout/stderr or a file
862*7a982d89SJeremy L. Thompson 
863*7a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
864*7a982d89SJeremy L. Thompson 
865*7a982d89SJeremy L. Thompson   @ref User
866*7a982d89SJeremy L. Thompson **/
867*7a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
868*7a982d89SJeremy L. Thompson   int ierr;
869*7a982d89SJeremy L. Thompson 
870*7a982d89SJeremy L. Thompson   if (op->composite) {
871*7a982d89SJeremy L. Thompson     fprintf(stream, "Composite CeedOperator\n");
872*7a982d89SJeremy L. Thompson 
873*7a982d89SJeremy L. Thompson     for (CeedInt i=0; i<op->numsub; i++) {
874*7a982d89SJeremy L. Thompson       fprintf(stream, "  SubOperator [%d]:\n", i);
875*7a982d89SJeremy L. Thompson       ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream);
876*7a982d89SJeremy L. Thompson       CeedChk(ierr);
877*7a982d89SJeremy L. Thompson     }
878*7a982d89SJeremy L. Thompson   } else {
879*7a982d89SJeremy L. Thompson     fprintf(stream, "CeedOperator\n");
880*7a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
881*7a982d89SJeremy L. Thompson   }
882*7a982d89SJeremy L. Thompson 
883*7a982d89SJeremy L. Thompson   return 0;
884*7a982d89SJeremy L. Thompson }
8853bd813ffSjeremylt 
8863bd813ffSjeremylt /**
8873bd813ffSjeremylt   @brief Apply CeedOperator to a vector
888d7b241e6Sjeremylt 
889d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
890d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
891d7b241e6Sjeremylt   CeedOperatorSetField().
892d7b241e6Sjeremylt 
893d7b241e6Sjeremylt   @param op        CeedOperator to apply
89434138859Sjeremylt   @param[in] in    CeedVector containing input state or CEED_VECTOR_NONE if
89534138859Sjeremylt                   there are no active inputs
896b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
89734138859Sjeremylt                      distinct from @a in) or CEED_VECTOR_NONE if there are no
89834138859Sjeremylt                      active outputs
899d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
900d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
901b11c1e72Sjeremylt 
902b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
903dfdf5a53Sjeremylt 
904*7a982d89SJeremy L. Thompson   @ref User
905b11c1e72Sjeremylt **/
906692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
907692c2638Sjeremylt                       CeedRequest *request) {
908d7b241e6Sjeremylt   int ierr;
909d7b241e6Sjeremylt   Ceed ceed = op->ceed;
910250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
911d7b241e6Sjeremylt 
912250756a7Sjeremylt   if (op->numelements)  {
913250756a7Sjeremylt     // Standard Operator
914cae8b89aSjeremylt     if (op->Apply) {
915250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
916cae8b89aSjeremylt     } else {
917cae8b89aSjeremylt       // Zero all output vectors
918250756a7Sjeremylt       CeedQFunction qf = op->qf;
919cae8b89aSjeremylt       for (CeedInt i=0; i<qf->numoutputfields; i++) {
920cae8b89aSjeremylt         CeedVector vec = op->outputfields[i]->vec;
921cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
922cae8b89aSjeremylt           vec = out;
923cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
924cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
925cae8b89aSjeremylt         }
926cae8b89aSjeremylt       }
927250756a7Sjeremylt       // Apply
928250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
929250756a7Sjeremylt     }
930250756a7Sjeremylt   } else if (op->composite) {
931250756a7Sjeremylt     // Composite Operator
932250756a7Sjeremylt     if (op->ApplyComposite) {
933250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
934250756a7Sjeremylt     } else {
935250756a7Sjeremylt       CeedInt numsub;
936250756a7Sjeremylt       ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr);
937250756a7Sjeremylt       CeedOperator *suboperators;
938250756a7Sjeremylt       ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr);
939250756a7Sjeremylt 
940250756a7Sjeremylt       // Zero all output vectors
941250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
942cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
943cae8b89aSjeremylt       }
944250756a7Sjeremylt       for (CeedInt i=0; i<numsub; i++) {
945250756a7Sjeremylt         for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) {
946250756a7Sjeremylt           CeedVector vec = suboperators[i]->outputfields[j]->vec;
947250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
948250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
949250756a7Sjeremylt           }
950250756a7Sjeremylt         }
951250756a7Sjeremylt       }
952250756a7Sjeremylt       // Apply
953250756a7Sjeremylt       for (CeedInt i=0; i<op->numsub; i++) {
954250756a7Sjeremylt         ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request);
955cae8b89aSjeremylt         CeedChk(ierr);
956cae8b89aSjeremylt       }
957cae8b89aSjeremylt     }
958250756a7Sjeremylt   }
959250756a7Sjeremylt 
960cae8b89aSjeremylt   return 0;
961cae8b89aSjeremylt }
962cae8b89aSjeremylt 
963cae8b89aSjeremylt /**
964cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
965cae8b89aSjeremylt 
966cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
967cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
968cae8b89aSjeremylt   CeedOperatorSetField().
969cae8b89aSjeremylt 
970cae8b89aSjeremylt   @param op        CeedOperator to apply
971cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
972cae8b89aSjeremylt                      active inputs
973cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
974cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
975cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
976cae8b89aSjeremylt                      CEED_REQUEST_IMMEDIATE
977cae8b89aSjeremylt 
978cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
979cae8b89aSjeremylt 
980*7a982d89SJeremy L. Thompson   @ref User
981cae8b89aSjeremylt **/
982cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
983cae8b89aSjeremylt                          CeedRequest *request) {
984cae8b89aSjeremylt   int ierr;
985cae8b89aSjeremylt   Ceed ceed = op->ceed;
986250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
987cae8b89aSjeremylt 
988250756a7Sjeremylt   if (op->numelements)  {
989250756a7Sjeremylt     // Standard Operator
990250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
991250756a7Sjeremylt   } else if (op->composite) {
992250756a7Sjeremylt     // Composite Operator
993250756a7Sjeremylt     if (op->ApplyAddComposite) {
994250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
995cae8b89aSjeremylt     } else {
996250756a7Sjeremylt       CeedInt numsub;
997250756a7Sjeremylt       ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr);
998250756a7Sjeremylt       CeedOperator *suboperators;
999250756a7Sjeremylt       ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr);
1000250756a7Sjeremylt 
1001250756a7Sjeremylt       for (CeedInt i=0; i<numsub; i++) {
1002250756a7Sjeremylt         ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request);
1003cae8b89aSjeremylt         CeedChk(ierr);
10041d7d2407SJeremy L Thompson       }
1005250756a7Sjeremylt     }
1006250756a7Sjeremylt   }
1007250756a7Sjeremylt 
1008d7b241e6Sjeremylt   return 0;
1009d7b241e6Sjeremylt }
1010d7b241e6Sjeremylt 
1011d7b241e6Sjeremylt /**
1012b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1013d7b241e6Sjeremylt 
1014d7b241e6Sjeremylt   @param op CeedOperator to destroy
1015b11c1e72Sjeremylt 
1016b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1017dfdf5a53Sjeremylt 
1018*7a982d89SJeremy L. Thompson   @ref User
1019b11c1e72Sjeremylt **/
1020d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1021d7b241e6Sjeremylt   int ierr;
1022d7b241e6Sjeremylt 
1023d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
1024d7b241e6Sjeremylt   if ((*op)->Destroy) {
1025d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1026d7b241e6Sjeremylt   }
1027fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1028fe2413ffSjeremylt   // Free fields
10291d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
103052d6035fSJeremy L Thompson     if ((*op)->inputfields[i]) {
103115910d16Sjeremylt       if ((*op)->inputfields[i]->Erestrict != CEED_ELEMRESTRICTION_NONE) {
103271352a93Sjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict);
103371352a93Sjeremylt         CeedChk(ierr);
103415910d16Sjeremylt       }
103571352a93Sjeremylt       if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) {
103671352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr);
103771352a93Sjeremylt       }
103871352a93Sjeremylt       if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE &&
103971352a93Sjeremylt           (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) {
104071352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr);
104171352a93Sjeremylt       }
1042fe2413ffSjeremylt       ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr);
1043fe2413ffSjeremylt     }
10441d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
1045d0eb30a5Sjeremylt     if ((*op)->outputfields[i]) {
104671352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict);
104771352a93Sjeremylt       CeedChk(ierr);
104871352a93Sjeremylt       if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) {
104971352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr);
105071352a93Sjeremylt       }
105171352a93Sjeremylt       if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE &&
105271352a93Sjeremylt           (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) {
105371352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr);
105471352a93Sjeremylt       }
1055fe2413ffSjeremylt       ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr);
1056fe2413ffSjeremylt     }
105752d6035fSJeremy L Thompson   // Destroy suboperators
10581d102b48SJeremy L Thompson   for (int i=0; i<(*op)->numsub; i++)
105952d6035fSJeremy L Thompson     if ((*op)->suboperators[i]) {
106052d6035fSJeremy L Thompson       ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr);
106152d6035fSJeremy L Thompson     }
1062d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1063d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1064d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1065fe2413ffSjeremylt 
10665107b09fSJeremy L Thompson   // Destroy fallback
10675107b09fSJeremy L Thompson   if ((*op)->opfallback) {
10685107b09fSJeremy L Thompson     ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr);
10695107b09fSJeremy L Thompson     ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr);
10705107b09fSJeremy L Thompson     ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr);
10715107b09fSJeremy L Thompson     ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr);
10725107b09fSJeremy L Thompson   }
10735107b09fSJeremy L Thompson 
1074fe2413ffSjeremylt   ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr);
1075fe2413ffSjeremylt   ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr);
107652d6035fSJeremy L Thompson   ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr);
1077d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1078d7b241e6Sjeremylt   return 0;
1079d7b241e6Sjeremylt }
1080d7b241e6Sjeremylt 
1081d7b241e6Sjeremylt /// @}
1082