xref: /libCEED/interface/ceed-operator.c (revision 138d40723aa3d9074a0e9bff3a6f097507ae8e2b)
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>
20d7b241e6Sjeremylt 
21dfdf5a53Sjeremylt /// @file
22dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces
23dfdf5a53Sjeremylt ///
24dfdf5a53Sjeremylt /// @addtogroup CeedOperator
25dfdf5a53Sjeremylt ///   @{
26d7b241e6Sjeremylt 
27d7b241e6Sjeremylt /**
280219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
290219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
300219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
31d7b241e6Sjeremylt 
32b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
33d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
34d7b241e6Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
35d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
36d7b241e6Sjeremylt                    of @a qf (or NULL)
37b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
38b11c1e72Sjeremylt                      CeedOperator will be stored
39b11c1e72Sjeremylt 
40b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
41dfdf5a53Sjeremylt 
42dfdf5a53Sjeremylt   @ref Basic
43d7b241e6Sjeremylt  */
44d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
45d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
46d7b241e6Sjeremylt   int ierr;
47d7b241e6Sjeremylt 
485fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
495fe0d4faSjeremylt     Ceed delegate;
50aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
515fe0d4faSjeremylt 
525fe0d4faSjeremylt     if (!delegate)
53c042f62fSJeremy L Thompson       // LCOV_EXCL_START
545fe0d4faSjeremylt       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
55c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
565fe0d4faSjeremylt 
575fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
585fe0d4faSjeremylt     return 0;
595fe0d4faSjeremylt   }
605fe0d4faSjeremylt 
61d7b241e6Sjeremylt   ierr = CeedCalloc(1,op); CeedChk(ierr);
62d7b241e6Sjeremylt   (*op)->ceed = ceed;
63d7b241e6Sjeremylt   ceed->refcount++;
64d7b241e6Sjeremylt   (*op)->refcount = 1;
65d7b241e6Sjeremylt   (*op)->qf = qf;
66d7b241e6Sjeremylt   qf->refcount++;
67d7b241e6Sjeremylt   (*op)->dqf = dqf;
68d7b241e6Sjeremylt   if (dqf) dqf->refcount++;
69d7b241e6Sjeremylt   (*op)->dqfT = dqfT;
70d7b241e6Sjeremylt   if (dqfT) dqfT->refcount++;
71fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr);
72fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr);
73d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
74d7b241e6Sjeremylt   return 0;
75d7b241e6Sjeremylt }
76d7b241e6Sjeremylt 
77d7b241e6Sjeremylt /**
7852d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
7952d6035fSJeremy L Thompson 
8052d6035fSJeremy L Thompson   @param ceed    A Ceed object where the CeedOperator will be created
8152d6035fSJeremy L Thompson   @param[out] op Address of the variable where the newly created
8252d6035fSJeremy L Thompson                      Composite CeedOperator will be stored
8352d6035fSJeremy L Thompson 
8452d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8552d6035fSJeremy L Thompson 
8652d6035fSJeremy L Thompson   @ref Basic
8752d6035fSJeremy L Thompson  */
8852d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
8952d6035fSJeremy L Thompson   int ierr;
9052d6035fSJeremy L Thompson 
9152d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
9252d6035fSJeremy L Thompson     Ceed delegate;
93aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
9452d6035fSJeremy L Thompson 
9552d6035fSJeremy L Thompson     if (!delegate)
96c042f62fSJeremy L Thompson       // LCOV_EXCL_START
971d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
981d102b48SJeremy L Thompson                        "CompositeOperatorCreate");
99c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
10052d6035fSJeremy L Thompson 
10152d6035fSJeremy L Thompson     ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
10252d6035fSJeremy L Thompson     return 0;
10352d6035fSJeremy L Thompson   }
10452d6035fSJeremy L Thompson 
10552d6035fSJeremy L Thompson   ierr = CeedCalloc(1,op); CeedChk(ierr);
10652d6035fSJeremy L Thompson   (*op)->ceed = ceed;
10752d6035fSJeremy L Thompson   ceed->refcount++;
10852d6035fSJeremy L Thompson   (*op)->composite = true;
10952d6035fSJeremy L Thompson   ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr);
11052d6035fSJeremy L Thompson   ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
11152d6035fSJeremy L Thompson   return 0;
11252d6035fSJeremy L Thompson }
11352d6035fSJeremy L Thompson 
11452d6035fSJeremy L Thompson /**
115b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
116d7b241e6Sjeremylt 
117d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
118d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
119d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
120d7b241e6Sjeremylt 
121d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
122d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
123d7b241e6Sjeremylt   input and at most one active output.
124d7b241e6Sjeremylt 
1258c91a0c9SJeremy L Thompson   @param op         CeedOperator on which to provide the field
1268795c945Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by
1278795c945Sjeremylt                       CeedQFunction)
128b11c1e72Sjeremylt   @param r          CeedElemRestriction
129b0e29e78Sjeremylt   @param lmode      CeedTransposeMode which specifies the ordering of the
130b0e29e78Sjeremylt                       components of the l-vector used by this CeedOperatorField,
131b0e29e78Sjeremylt                       CEED_NOTRANSPOSE indicates the component is the
132b0e29e78Sjeremylt                       outermost index and CEED_TRANSPOSE indicates the component
133b0e29e78Sjeremylt                       is the innermost index in ordering of the l-vector
134783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
135b11c1e72Sjeremylt                       if collocated with quadrature points
136b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
137b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
1388c91a0c9SJeremy L Thompson                       CEED_EVAL_WEIGHT in the QFunction
139b11c1e72Sjeremylt 
140b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
141dfdf5a53Sjeremylt 
142dfdf5a53Sjeremylt   @ref Basic
143b11c1e72Sjeremylt **/
144d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
1454dccadb6Sjeremylt                          CeedElemRestriction r, CeedTransposeMode lmode,
1464dccadb6Sjeremylt                          CeedBasis b, CeedVector v) {
147d7b241e6Sjeremylt   int ierr;
14852d6035fSJeremy L Thompson   if (op->composite)
149c042f62fSJeremy L Thompson     // LCOV_EXCL_START
15052d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Cannot add field to composite operator.");
151c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1528b067b84SJed Brown   if (!r)
153c042f62fSJeremy L Thompson     // LCOV_EXCL_START
154c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1,
155c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
156c042f62fSJeremy L Thompson                      fieldname);
157c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1588b067b84SJed Brown   if (!b)
159c042f62fSJeremy L Thompson     // LCOV_EXCL_START
160c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.",
161c042f62fSJeremy L Thompson                      fieldname);
162c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1638b067b84SJed Brown   if (!v)
164c042f62fSJeremy L Thompson     // LCOV_EXCL_START
165c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.",
166c042f62fSJeremy L Thompson                      fieldname);
167c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
16852d6035fSJeremy L Thompson 
169d7b241e6Sjeremylt   CeedInt numelements;
170d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
171d7b241e6Sjeremylt   if (op->numelements && op->numelements != numelements)
172c042f62fSJeremy L Thompson     // LCOV_EXCL_START
173d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
1741d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
1751d102b48SJeremy L Thompson                      "%d elements", numelements, op->numelements);
176c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
177d7b241e6Sjeremylt   op->numelements = numelements;
178d7b241e6Sjeremylt 
179783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
180d7b241e6Sjeremylt     CeedInt numqpoints;
181d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
182d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
183c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1841d102b48SJeremy L Thompson       return CeedError(op->ceed, 1, "Basis with %d quadrature points "
1851d102b48SJeremy L Thompson                        "incompatible with prior %d points", numqpoints,
1861d102b48SJeremy L Thompson                        op->numqpoints);
187c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
188d7b241e6Sjeremylt     op->numqpoints = numqpoints;
189d7b241e6Sjeremylt   }
190d1bcdac9Sjeremylt   CeedOperatorField *ofield;
191d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
192fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) {
193d7b241e6Sjeremylt       ofield = &op->inputfields[i];
194d7b241e6Sjeremylt       goto found;
195d7b241e6Sjeremylt     }
196d7b241e6Sjeremylt   }
197d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
198fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) {
199d7b241e6Sjeremylt       ofield = &op->outputfields[i];
200d7b241e6Sjeremylt       goto found;
201d7b241e6Sjeremylt     }
202d7b241e6Sjeremylt   }
203c042f62fSJeremy L Thompson   // LCOV_EXCL_START
204d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
205d7b241e6Sjeremylt                    fieldname);
206c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
207d7b241e6Sjeremylt found:
208fe2413ffSjeremylt   ierr = CeedCalloc(1, ofield); CeedChk(ierr);
209fe2413ffSjeremylt   (*ofield)->Erestrict = r;
21071352a93Sjeremylt   r->refcount += 1;
211fe2413ffSjeremylt   (*ofield)->lmode = lmode;
212fe2413ffSjeremylt   (*ofield)->basis = b;
21371352a93Sjeremylt   if (b != CEED_BASIS_COLLOCATED)
21471352a93Sjeremylt     b->refcount += 1;
215fe2413ffSjeremylt   (*ofield)->vec = v;
21671352a93Sjeremylt   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE)
21771352a93Sjeremylt     v->refcount += 1;
218d7b241e6Sjeremylt   op->nfields += 1;
219d7b241e6Sjeremylt   return 0;
220d7b241e6Sjeremylt }
221d7b241e6Sjeremylt 
222d7b241e6Sjeremylt /**
22352d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
224288c0443SJeremy L Thompson 
225288c0443SJeremy L Thompson   @param[out] compositeop Address of the composite CeedOperator
226288c0443SJeremy L Thompson   @param      subop       Address of the sub-operator CeedOperator
22752d6035fSJeremy L Thompson 
22852d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22952d6035fSJeremy L Thompson 
23052d6035fSJeremy L Thompson   @ref Basic
23152d6035fSJeremy L Thompson  */
23252d6035fSJeremy L Thompson int CeedCompositeOperatorAddSub(CeedOperator compositeop,
23352d6035fSJeremy L Thompson                                 CeedOperator subop) {
23452d6035fSJeremy L Thompson   if (!compositeop->composite)
235c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2361d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite "
2371d102b48SJeremy L Thompson                      "operator");
238c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
23952d6035fSJeremy L Thompson 
24052d6035fSJeremy L Thompson   if (compositeop->numsub == CEED_COMPOSITE_MAX)
241c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2421d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators");
243c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
24452d6035fSJeremy L Thompson 
24552d6035fSJeremy L Thompson   compositeop->suboperators[compositeop->numsub] = subop;
24652d6035fSJeremy L Thompson   subop->refcount++;
24752d6035fSJeremy L Thompson   compositeop->numsub++;
24852d6035fSJeremy L Thompson   return 0;
24952d6035fSJeremy L Thompson }
25052d6035fSJeremy L Thompson 
25152d6035fSJeremy L Thompson /**
2521d102b48SJeremy L Thompson   @brief Assemble a linear CeedQFunction associated with a CeedOperator
2531d102b48SJeremy L Thompson 
2541d102b48SJeremy L Thompson   This returns a CeedVector containing a matrix at each quadrature point
2551d102b48SJeremy L Thompson     providing the action of the CeedQFunction associated with the CeedOperator.
2561d102b48SJeremy L Thompson     The vector 'assembled' is of shape
2571d102b48SJeremy L Thompson       [num_elements, num_input_fields, num_output_fields, num_quad_points]
2581d102b48SJeremy L Thompson     and contains column-major matrices representing the action of the
2591d102b48SJeremy L Thompson     CeedQFunction for a corresponding quadrature point on an element. Inputs and
2601d102b48SJeremy L Thompson     outputs are in the order provided by the user when adding CeedOperator fields.
2611d102b48SJeremy L Thompson     For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and
2621d102b48SJeremy L Thompson     'v', provided in that order, would result in an assembled QFunction that
2631d102b48SJeremy L Thompson     consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting
2641d102b48SJeremy L Thompson     on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v].
2651d102b48SJeremy L Thompson 
2661d102b48SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
2671d102b48SJeremy L Thompson   @param[out] assembled CeedVector to store assembled Ceed QFunction at
2681d102b48SJeremy L Thompson                           quadrature points
2691d102b48SJeremy L Thompson   @param[out] rstr      CeedElemRestriction for CeedVector containing assembled
2701d102b48SJeremy L Thompson                           CeedQFunction
2711d102b48SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
2721d102b48SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
2731d102b48SJeremy L Thompson 
2741d102b48SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2751d102b48SJeremy L Thompson 
2761d102b48SJeremy L Thompson   @ref Advanced
2771d102b48SJeremy L Thompson **/
2781d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled,
2791d102b48SJeremy L Thompson     CeedElemRestriction *rstr, CeedRequest *request) {
2801d102b48SJeremy L Thompson   int ierr;
2811d102b48SJeremy L Thompson   Ceed ceed = op->ceed;
2821d102b48SJeremy L Thompson   CeedQFunction qf = op->qf;
2831d102b48SJeremy L Thompson 
2841d102b48SJeremy L Thompson   if (op->composite) {
285*138d4072Sjeremylt     // LCOV_EXCL_START
2861d102b48SJeremy L Thompson     return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator");
287*138d4072Sjeremylt     // LCOV_EXCL_STOP
2881d102b48SJeremy L Thompson   } else {
2891d102b48SJeremy L Thompson     if (op->nfields == 0)
290*138d4072Sjeremylt       // LCOV_EXCL_START
2911d102b48SJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
292*138d4072Sjeremylt       // LCOV_EXCL_STOP
2931d102b48SJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
294*138d4072Sjeremylt       // LCOV_EXCL_START
2951d102b48SJeremy L Thompson       return CeedError( ceed, 1, "Not all operator fields set");
296*138d4072Sjeremylt     // LCOV_EXCL_STOP
2971d102b48SJeremy L Thompson     if (op->numelements == 0)
298*138d4072Sjeremylt       // LCOV_EXCL_START
2991d102b48SJeremy L Thompson       return CeedError(ceed, 1, "At least one restriction required");
300*138d4072Sjeremylt     // LCOV_EXCL_STOP
3011d102b48SJeremy L Thompson     if (op->numqpoints == 0)
302*138d4072Sjeremylt       // LCOV_EXCL_START
3031d102b48SJeremy L Thompson       return CeedError(ceed, 1, "At least one non-collocated basis required");
304*138d4072Sjeremylt     // LCOV_EXCL_STOP
3051d102b48SJeremy L Thompson   }
3061d102b48SJeremy L Thompson   ierr = op->AssembleLinearQFunction(op, assembled, rstr, request);
3071d102b48SJeremy L Thompson   CeedChk(ierr);
3081d102b48SJeremy L Thompson   return 0;
3091d102b48SJeremy L Thompson }
3101d102b48SJeremy L Thompson 
3111d102b48SJeremy L Thompson /**
312b11c1e72Sjeremylt   @brief Apply CeedOperator to a vector
313d7b241e6Sjeremylt 
314d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
315d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
316d7b241e6Sjeremylt   CeedOperatorSetField().
317d7b241e6Sjeremylt 
318d7b241e6Sjeremylt   @param op        CeedOperator to apply
319b11c1e72Sjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
320b11c1e72Sjeremylt                      active inputs
321b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
322d7b241e6Sjeremylt                      distinct from @a in) or NULL if there are no active outputs
323d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
324d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
325b11c1e72Sjeremylt 
326b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
327dfdf5a53Sjeremylt 
328dfdf5a53Sjeremylt   @ref Basic
329b11c1e72Sjeremylt **/
330d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in,
331d7b241e6Sjeremylt                       CeedVector out, CeedRequest *request) {
332d7b241e6Sjeremylt   int ierr;
333d7b241e6Sjeremylt   Ceed ceed = op->ceed;
334d7b241e6Sjeremylt   CeedQFunction qf = op->qf;
335d7b241e6Sjeremylt 
33652d6035fSJeremy L Thompson   if (op->composite) {
337c042f62fSJeremy L Thompson     if (!op->numsub)
338c042f62fSJeremy L Thompson       // LCOV_EXCL_START
339c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "No suboperators set");
340c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
34152d6035fSJeremy L Thompson   } else {
342c042f62fSJeremy L Thompson     if (op->nfields == 0)
343c042f62fSJeremy L Thompson       // LCOV_EXCL_START
344c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
345c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
346c042f62fSJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
347c042f62fSJeremy L Thompson       // LCOV_EXCL_START
348c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "Not all operator fields set");
349c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
350c042f62fSJeremy L Thompson     if (op->numelements == 0)
351c042f62fSJeremy L Thompson       // LCOV_EXCL_START
352c042f62fSJeremy L Thompson       return CeedError(ceed, 1,"At least one restriction required");
353c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
354c042f62fSJeremy L Thompson     if (op->numqpoints == 0)
355c042f62fSJeremy L Thompson       // LCOV_EXCL_START
356c042f62fSJeremy L Thompson       return CeedError(ceed, 1,"At least one non-collocated basis required");
357c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
35852d6035fSJeremy L Thompson   }
359d7b241e6Sjeremylt   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
360d7b241e6Sjeremylt   return 0;
361d7b241e6Sjeremylt }
362d7b241e6Sjeremylt 
363d7b241e6Sjeremylt /**
3644ce2993fSjeremylt   @brief Get the Ceed associated with a CeedOperator
3654ce2993fSjeremylt 
3664ce2993fSjeremylt   @param op              CeedOperator
3674ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
3684ce2993fSjeremylt 
3694ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
3704ce2993fSjeremylt 
37123617272Sjeremylt   @ref Advanced
3724ce2993fSjeremylt **/
3734ce2993fSjeremylt 
3744ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
3754ce2993fSjeremylt   *ceed = op->ceed;
3764ce2993fSjeremylt   return 0;
3774ce2993fSjeremylt }
3784ce2993fSjeremylt 
3794ce2993fSjeremylt /**
3804ce2993fSjeremylt   @brief Get the number of elements associated with a CeedOperator
3814ce2993fSjeremylt 
3824ce2993fSjeremylt   @param op              CeedOperator
3834ce2993fSjeremylt   @param[out] numelem    Variable to store number of elements
3844ce2993fSjeremylt 
3854ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
3864ce2993fSjeremylt 
38723617272Sjeremylt   @ref Advanced
3884ce2993fSjeremylt **/
3894ce2993fSjeremylt 
3904ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
39152d6035fSJeremy L Thompson   if (op->composite)
392c042f62fSJeremy L Thompson     // LCOV_EXCL_START
39352d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
394c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
39552d6035fSJeremy L Thompson 
3964ce2993fSjeremylt   *numelem = op->numelements;
3974ce2993fSjeremylt   return 0;
3984ce2993fSjeremylt }
3994ce2993fSjeremylt 
4004ce2993fSjeremylt /**
4014ce2993fSjeremylt   @brief Get the number of quadrature points associated with a CeedOperator
4024ce2993fSjeremylt 
4034ce2993fSjeremylt   @param op              CeedOperator
4044ce2993fSjeremylt   @param[out] numqpts    Variable to store vector number of quadrature points
4054ce2993fSjeremylt 
4064ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4074ce2993fSjeremylt 
40823617272Sjeremylt   @ref Advanced
4094ce2993fSjeremylt **/
4104ce2993fSjeremylt 
4114ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
41252d6035fSJeremy L Thompson   if (op->composite)
413c042f62fSJeremy L Thompson     // LCOV_EXCL_START
41452d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
415c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
41652d6035fSJeremy L Thompson 
4174ce2993fSjeremylt   *numqpts = op->numqpoints;
4184ce2993fSjeremylt   return 0;
4194ce2993fSjeremylt }
4204ce2993fSjeremylt 
4214ce2993fSjeremylt /**
4224ce2993fSjeremylt   @brief Get the number of arguments associated with a CeedOperator
4234ce2993fSjeremylt 
4244ce2993fSjeremylt   @param op              CeedOperator
4254ce2993fSjeremylt   @param[out] numargs    Variable to store vector number of arguments
4264ce2993fSjeremylt 
4274ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4284ce2993fSjeremylt 
42923617272Sjeremylt   @ref Advanced
4304ce2993fSjeremylt **/
4314ce2993fSjeremylt 
4324ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
43352d6035fSJeremy L Thompson   if (op->composite)
434c042f62fSJeremy L Thompson     // LCOV_EXCL_START
43552d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operators");
436c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
437c042f62fSJeremy L Thompson 
4384ce2993fSjeremylt   *numargs = op->nfields;
4394ce2993fSjeremylt   return 0;
4404ce2993fSjeremylt }
4414ce2993fSjeremylt 
4424ce2993fSjeremylt /**
4434ce2993fSjeremylt   @brief Get the setup status of a CeedOperator
4444ce2993fSjeremylt 
4454ce2993fSjeremylt   @param op             CeedOperator
446288c0443SJeremy L Thompson   @param[out] setupdone Variable to store setup status
4474ce2993fSjeremylt 
4484ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4494ce2993fSjeremylt 
45023617272Sjeremylt   @ref Advanced
4514ce2993fSjeremylt **/
4524ce2993fSjeremylt 
4534ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
4544ce2993fSjeremylt   *setupdone = op->setupdone;
4554ce2993fSjeremylt   return 0;
4564ce2993fSjeremylt }
4574ce2993fSjeremylt 
4584ce2993fSjeremylt /**
4594ce2993fSjeremylt   @brief Get the QFunction associated with a CeedOperator
4604ce2993fSjeremylt 
4614ce2993fSjeremylt   @param op              CeedOperator
4628c91a0c9SJeremy L Thompson   @param[out] qf         Variable to store QFunction
4634ce2993fSjeremylt 
4644ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4654ce2993fSjeremylt 
46623617272Sjeremylt   @ref Advanced
4674ce2993fSjeremylt **/
4684ce2993fSjeremylt 
4694ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
47052d6035fSJeremy L Thompson   if (op->composite)
471c042f62fSJeremy L Thompson     // LCOV_EXCL_START
47252d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
473c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
47452d6035fSJeremy L Thompson 
4754ce2993fSjeremylt   *qf = op->qf;
4764ce2993fSjeremylt   return 0;
4774ce2993fSjeremylt }
4784ce2993fSjeremylt 
4794ce2993fSjeremylt /**
48052d6035fSJeremy L Thompson   @brief Get the number of suboperators associated with a CeedOperator
48152d6035fSJeremy L Thompson 
48252d6035fSJeremy L Thompson   @param op              CeedOperator
48352d6035fSJeremy L Thompson   @param[out] numsub     Variable to store number of suboperators
48452d6035fSJeremy L Thompson 
48552d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
48652d6035fSJeremy L Thompson 
48752d6035fSJeremy L Thompson   @ref Advanced
48852d6035fSJeremy L Thompson **/
48952d6035fSJeremy L Thompson 
49052d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) {
491c042f62fSJeremy L Thompson   if (!op->composite)
492c042f62fSJeremy L Thompson     // LCOV_EXCL_START
493c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
494c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
49552d6035fSJeremy L Thompson 
49652d6035fSJeremy L Thompson   *numsub = op->numsub;
49752d6035fSJeremy L Thompson   return 0;
49852d6035fSJeremy L Thompson }
49952d6035fSJeremy L Thompson 
50052d6035fSJeremy L Thompson /**
50152d6035fSJeremy L Thompson   @brief Get the list of suboperators associated with a CeedOperator
50252d6035fSJeremy L Thompson 
50352d6035fSJeremy L Thompson   @param op                CeedOperator
50452d6035fSJeremy L Thompson   @param[out] suboperators Variable to store list of suboperators
50552d6035fSJeremy L Thompson 
50652d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
50752d6035fSJeremy L Thompson 
50852d6035fSJeremy L Thompson   @ref Advanced
50952d6035fSJeremy L Thompson **/
51052d6035fSJeremy L Thompson 
51152d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator* *suboperators) {
512c042f62fSJeremy L Thompson   if (!op->composite)
513c042f62fSJeremy L Thompson     // LCOV_EXCL_START
514c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
515c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
51652d6035fSJeremy L Thompson 
51752d6035fSJeremy L Thompson   *suboperators = op->suboperators;
51852d6035fSJeremy L Thompson   return 0;
51952d6035fSJeremy L Thompson }
52052d6035fSJeremy L Thompson 
52152d6035fSJeremy L Thompson /**
522fe2413ffSjeremylt   @brief Set the backend data of a CeedOperator
523fe2413ffSjeremylt 
524fe2413ffSjeremylt   @param[out] op         CeedOperator
525fe2413ffSjeremylt   @param data            Data to set
526fe2413ffSjeremylt 
527fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
528fe2413ffSjeremylt 
529fe2413ffSjeremylt   @ref Advanced
530fe2413ffSjeremylt **/
531fe2413ffSjeremylt 
532fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void* *data) {
533fe2413ffSjeremylt   op->data = *data;
534fe2413ffSjeremylt   return 0;
535fe2413ffSjeremylt }
536fe2413ffSjeremylt 
537fe2413ffSjeremylt /**
5384ce2993fSjeremylt   @brief Get the backend data of a CeedOperator
5394ce2993fSjeremylt 
5404ce2993fSjeremylt   @param op              CeedOperator
5414ce2993fSjeremylt   @param[out] data       Variable to store data
5424ce2993fSjeremylt 
5434ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5444ce2993fSjeremylt 
54523617272Sjeremylt   @ref Advanced
5464ce2993fSjeremylt **/
5474ce2993fSjeremylt 
5484ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void* *data) {
5494ce2993fSjeremylt   *data = op->data;
5504ce2993fSjeremylt   return 0;
5514ce2993fSjeremylt }
5524ce2993fSjeremylt 
5534ce2993fSjeremylt /**
5544ce2993fSjeremylt   @brief Set the setup flag of a CeedOperator to True
5554ce2993fSjeremylt 
5564ce2993fSjeremylt   @param op              CeedOperator
5574ce2993fSjeremylt 
5584ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5594ce2993fSjeremylt 
56023617272Sjeremylt   @ref Advanced
5614ce2993fSjeremylt **/
5624ce2993fSjeremylt 
5634ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) {
5644ce2993fSjeremylt   op->setupdone = 1;
5654ce2993fSjeremylt   return 0;
5664ce2993fSjeremylt }
5674ce2993fSjeremylt 
5684ce2993fSjeremylt /**
569d1bcdac9Sjeremylt   @brief Get the CeedOperatorFields of a CeedOperator
570d1bcdac9Sjeremylt 
571d1bcdac9Sjeremylt   @param op                 CeedOperator
572d1bcdac9Sjeremylt   @param[out] inputfields   Variable to store inputfields
573d1bcdac9Sjeremylt   @param[out] outputfields  Variable to store outputfields
574d1bcdac9Sjeremylt 
575d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
576d1bcdac9Sjeremylt 
577d1bcdac9Sjeremylt   @ref Advanced
578d1bcdac9Sjeremylt **/
579d1bcdac9Sjeremylt 
580d1bcdac9Sjeremylt int CeedOperatorGetFields(CeedOperator op,
581d1bcdac9Sjeremylt                           CeedOperatorField* *inputfields,
582d1bcdac9Sjeremylt                           CeedOperatorField* *outputfields) {
58352d6035fSJeremy L Thompson   if (op->composite)
584c042f62fSJeremy L Thompson     // LCOV_EXCL_START
58552d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
586c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
58752d6035fSJeremy L Thompson 
588d1bcdac9Sjeremylt   if (inputfields) *inputfields = op->inputfields;
589d1bcdac9Sjeremylt   if (outputfields) *outputfields = op->outputfields;
590d1bcdac9Sjeremylt   return 0;
591d1bcdac9Sjeremylt }
592d1bcdac9Sjeremylt 
593d1bcdac9Sjeremylt /**
5944dccadb6Sjeremylt   @brief Get the L vector CeedTransposeMode of a CeedOperatorField
5954dccadb6Sjeremylt 
5964dccadb6Sjeremylt   @param opfield         CeedOperatorField
5974dccadb6Sjeremylt   @param[out] lmode      Variable to store CeedTransposeMode
5984dccadb6Sjeremylt 
5994dccadb6Sjeremylt   @return An error code: 0 - success, otherwise - failure
6004dccadb6Sjeremylt 
6014dccadb6Sjeremylt   @ref Advanced
6024dccadb6Sjeremylt **/
6034dccadb6Sjeremylt 
6044dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield,
6054dccadb6Sjeremylt                               CeedTransposeMode *lmode) {
606fe2413ffSjeremylt   *lmode = opfield->lmode;
6074dccadb6Sjeremylt   return 0;
6082b8e417aSjeremylt }
6092b8e417aSjeremylt 
6102b8e417aSjeremylt /**
611d1bcdac9Sjeremylt   @brief Get the CeedElemRestriction of a CeedOperatorField
612d1bcdac9Sjeremylt 
613d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
614d1bcdac9Sjeremylt   @param[out] rstr       Variable to store CeedElemRestriction
615d1bcdac9Sjeremylt 
616d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
617d1bcdac9Sjeremylt 
618d1bcdac9Sjeremylt   @ref Advanced
619d1bcdac9Sjeremylt **/
620d1bcdac9Sjeremylt 
621d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
622d1bcdac9Sjeremylt                                         CeedElemRestriction *rstr) {
623fe2413ffSjeremylt   *rstr = opfield->Erestrict;
624d1bcdac9Sjeremylt   return 0;
625d1bcdac9Sjeremylt }
626d1bcdac9Sjeremylt 
627d1bcdac9Sjeremylt /**
628d1bcdac9Sjeremylt   @brief Get the CeedBasis of a CeedOperatorField
629d1bcdac9Sjeremylt 
630d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
631d1bcdac9Sjeremylt   @param[out] basis      Variable to store CeedBasis
632d1bcdac9Sjeremylt 
633d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
634d1bcdac9Sjeremylt 
635d1bcdac9Sjeremylt   @ref Advanced
636d1bcdac9Sjeremylt **/
637d1bcdac9Sjeremylt 
638d1bcdac9Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield,
639d1bcdac9Sjeremylt                               CeedBasis *basis) {
640fe2413ffSjeremylt   *basis = opfield->basis;
641d1bcdac9Sjeremylt   return 0;
642d1bcdac9Sjeremylt }
643d1bcdac9Sjeremylt 
644d1bcdac9Sjeremylt /**
645d1bcdac9Sjeremylt   @brief Get the CeedVector of a CeedOperatorField
646d1bcdac9Sjeremylt 
647d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
648d1bcdac9Sjeremylt   @param[out] vec        Variable to store CeedVector
649d1bcdac9Sjeremylt 
650d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
651d1bcdac9Sjeremylt 
652d1bcdac9Sjeremylt   @ref Advanced
653d1bcdac9Sjeremylt **/
654d1bcdac9Sjeremylt 
655d1bcdac9Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield,
656d1bcdac9Sjeremylt                                CeedVector *vec) {
657fe2413ffSjeremylt   *vec = opfield->vec;
658d1bcdac9Sjeremylt   return 0;
659d1bcdac9Sjeremylt }
660d1bcdac9Sjeremylt 
661d1bcdac9Sjeremylt /**
662b11c1e72Sjeremylt   @brief Destroy a CeedOperator
663d7b241e6Sjeremylt 
664d7b241e6Sjeremylt   @param op CeedOperator to destroy
665b11c1e72Sjeremylt 
666b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
667dfdf5a53Sjeremylt 
668dfdf5a53Sjeremylt   @ref Basic
669b11c1e72Sjeremylt **/
670d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
671d7b241e6Sjeremylt   int ierr;
672d7b241e6Sjeremylt 
673d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
674d7b241e6Sjeremylt   if ((*op)->Destroy) {
675d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
676d7b241e6Sjeremylt   }
677fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
678fe2413ffSjeremylt   // Free fields
6791d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
68052d6035fSJeremy L Thompson     if ((*op)->inputfields[i]) {
68171352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict);
68271352a93Sjeremylt       CeedChk(ierr);
68371352a93Sjeremylt       if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) {
68471352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr);
68571352a93Sjeremylt       }
68671352a93Sjeremylt       if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE &&
68771352a93Sjeremylt           (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) {
68871352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr);
68971352a93Sjeremylt       }
690fe2413ffSjeremylt       ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr);
691fe2413ffSjeremylt     }
6921d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
693d0eb30a5Sjeremylt     if ((*op)->outputfields[i]) {
69471352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict);
69571352a93Sjeremylt       CeedChk(ierr);
69671352a93Sjeremylt       if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) {
69771352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr);
69871352a93Sjeremylt       }
69971352a93Sjeremylt       if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE &&
70071352a93Sjeremylt           (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) {
70171352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr);
70271352a93Sjeremylt       }
703fe2413ffSjeremylt       ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr);
704fe2413ffSjeremylt     }
70552d6035fSJeremy L Thompson   // Destroy suboperators
7061d102b48SJeremy L Thompson   for (int i=0; i<(*op)->numsub; i++)
70752d6035fSJeremy L Thompson     if ((*op)->suboperators[i]) {
70852d6035fSJeremy L Thompson       ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr);
70952d6035fSJeremy L Thompson     }
710d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
711d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
712d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
713fe2413ffSjeremylt 
714fe2413ffSjeremylt   ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr);
715fe2413ffSjeremylt   ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr);
71652d6035fSJeremy L Thompson   ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr);
717d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
718d7b241e6Sjeremylt   return 0;
719d7b241e6Sjeremylt }
720d7b241e6Sjeremylt 
721d7b241e6Sjeremylt /// @}
722