xref: /libCEED/interface/ceed-operator.c (revision cae8b89ab4384ccb591c7143fd0ca8a192ac9d03)
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;
65442e7f0bSjeremylt   if (qf == CEED_QFUNCTION_NONE)
66442e7f0bSjeremylt     // LCOV_EXCL_START
67442e7f0bSjeremylt     return CeedError(ceed, 1, "Operator must have a valid QFunction.");
68442e7f0bSjeremylt   // LCOV_EXCL_STOP
69d7b241e6Sjeremylt   (*op)->qf = qf;
70d7b241e6Sjeremylt   qf->refcount++;
71442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
72d7b241e6Sjeremylt     (*op)->dqf = dqf;
73442e7f0bSjeremylt     dqf->refcount++;
74442e7f0bSjeremylt   }
75442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
76d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
77442e7f0bSjeremylt     dqfT->refcount++;
78442e7f0bSjeremylt   }
79fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr);
80fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr);
81d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
82d7b241e6Sjeremylt   return 0;
83d7b241e6Sjeremylt }
84d7b241e6Sjeremylt 
85d7b241e6Sjeremylt /**
8652d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
8752d6035fSJeremy L Thompson 
8852d6035fSJeremy L Thompson   @param ceed    A Ceed object where the CeedOperator will be created
8952d6035fSJeremy L Thompson   @param[out] op Address of the variable where the newly created
9052d6035fSJeremy L Thompson                      Composite CeedOperator will be stored
9152d6035fSJeremy L Thompson 
9252d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9352d6035fSJeremy L Thompson 
9452d6035fSJeremy L Thompson   @ref Basic
9552d6035fSJeremy L Thompson  */
9652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
9752d6035fSJeremy L Thompson   int ierr;
9852d6035fSJeremy L Thompson 
9952d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
10052d6035fSJeremy L Thompson     Ceed delegate;
101aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
10252d6035fSJeremy L Thompson 
10352d6035fSJeremy L Thompson     if (!delegate)
104c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1051d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
1061d102b48SJeremy L Thompson                        "CompositeOperatorCreate");
107c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
10852d6035fSJeremy L Thompson 
10952d6035fSJeremy L Thompson     ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
11052d6035fSJeremy L Thompson     return 0;
11152d6035fSJeremy L Thompson   }
11252d6035fSJeremy L Thompson 
11352d6035fSJeremy L Thompson   ierr = CeedCalloc(1,op); CeedChk(ierr);
11452d6035fSJeremy L Thompson   (*op)->ceed = ceed;
11552d6035fSJeremy L Thompson   ceed->refcount++;
11652d6035fSJeremy L Thompson   (*op)->composite = true;
11752d6035fSJeremy L Thompson   ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr);
11852d6035fSJeremy L Thompson   ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
11952d6035fSJeremy L Thompson   return 0;
12052d6035fSJeremy L Thompson }
12152d6035fSJeremy L Thompson 
12252d6035fSJeremy L Thompson /**
123b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
124d7b241e6Sjeremylt 
125d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
126d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
127d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
128d7b241e6Sjeremylt 
129d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
130d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
131d7b241e6Sjeremylt   input and at most one active output.
132d7b241e6Sjeremylt 
1338c91a0c9SJeremy L Thompson   @param op         CeedOperator on which to provide the field
1348795c945Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by
1358795c945Sjeremylt                       CeedQFunction)
136b11c1e72Sjeremylt   @param r          CeedElemRestriction
137b0e29e78Sjeremylt   @param lmode      CeedTransposeMode which specifies the ordering of the
138b0e29e78Sjeremylt                       components of the l-vector used by this CeedOperatorField,
139b0e29e78Sjeremylt                       CEED_NOTRANSPOSE indicates the component is the
140b0e29e78Sjeremylt                       outermost index and CEED_TRANSPOSE indicates the component
141b0e29e78Sjeremylt                       is the innermost index in ordering of the l-vector
142783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
143b11c1e72Sjeremylt                       if collocated with quadrature points
144b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
145b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
1468c91a0c9SJeremy L Thompson                       CEED_EVAL_WEIGHT in the QFunction
147b11c1e72Sjeremylt 
148b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
149dfdf5a53Sjeremylt 
150dfdf5a53Sjeremylt   @ref Basic
151b11c1e72Sjeremylt **/
152d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
1534dccadb6Sjeremylt                          CeedElemRestriction r, CeedTransposeMode lmode,
1544dccadb6Sjeremylt                          CeedBasis b, CeedVector v) {
155d7b241e6Sjeremylt   int ierr;
15652d6035fSJeremy L Thompson   if (op->composite)
157c042f62fSJeremy L Thompson     // LCOV_EXCL_START
15852d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Cannot add field to composite operator.");
159c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1608b067b84SJed Brown   if (!r)
161c042f62fSJeremy L Thompson     // LCOV_EXCL_START
162c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1,
163c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
164c042f62fSJeremy L Thompson                      fieldname);
165c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1668b067b84SJed Brown   if (!b)
167c042f62fSJeremy L Thompson     // LCOV_EXCL_START
168c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.",
169c042f62fSJeremy L Thompson                      fieldname);
170c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1718b067b84SJed Brown   if (!v)
172c042f62fSJeremy L Thompson     // LCOV_EXCL_START
173c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.",
174c042f62fSJeremy L Thompson                      fieldname);
175c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
17652d6035fSJeremy L Thompson 
177d7b241e6Sjeremylt   CeedInt numelements;
178d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
1792cb0afc5Sjeremylt   if (op->hasrestriction && op->numelements != numelements)
180c042f62fSJeremy L Thompson     // LCOV_EXCL_START
181d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
1821d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
1831d102b48SJeremy L Thompson                      "%d elements", numelements, op->numelements);
184c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
185d7b241e6Sjeremylt   op->numelements = numelements;
1862cb0afc5Sjeremylt   op->hasrestriction = true; // Restriction set, but numelements may be 0
187d7b241e6Sjeremylt 
188783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
189d7b241e6Sjeremylt     CeedInt numqpoints;
190d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
191d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
192c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1931d102b48SJeremy L Thompson       return CeedError(op->ceed, 1, "Basis with %d quadrature points "
1941d102b48SJeremy L Thompson                        "incompatible with prior %d points", numqpoints,
1951d102b48SJeremy L Thompson                        op->numqpoints);
196c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
197d7b241e6Sjeremylt     op->numqpoints = numqpoints;
198d7b241e6Sjeremylt   }
199d1bcdac9Sjeremylt   CeedOperatorField *ofield;
200d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
201fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) {
202d7b241e6Sjeremylt       ofield = &op->inputfields[i];
203d7b241e6Sjeremylt       goto found;
204d7b241e6Sjeremylt     }
205d7b241e6Sjeremylt   }
206d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
207fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) {
208d7b241e6Sjeremylt       ofield = &op->outputfields[i];
209d7b241e6Sjeremylt       goto found;
210d7b241e6Sjeremylt     }
211d7b241e6Sjeremylt   }
212c042f62fSJeremy L Thompson   // LCOV_EXCL_START
213d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
214d7b241e6Sjeremylt                    fieldname);
215c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
216d7b241e6Sjeremylt found:
217fe2413ffSjeremylt   ierr = CeedCalloc(1, ofield); CeedChk(ierr);
218fe2413ffSjeremylt   (*ofield)->Erestrict = r;
21971352a93Sjeremylt   r->refcount += 1;
220fe2413ffSjeremylt   (*ofield)->lmode = lmode;
221fe2413ffSjeremylt   (*ofield)->basis = b;
22271352a93Sjeremylt   if (b != CEED_BASIS_COLLOCATED)
22371352a93Sjeremylt     b->refcount += 1;
224fe2413ffSjeremylt   (*ofield)->vec = v;
22571352a93Sjeremylt   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE)
22671352a93Sjeremylt     v->refcount += 1;
227d7b241e6Sjeremylt   op->nfields += 1;
228d7b241e6Sjeremylt   return 0;
229d7b241e6Sjeremylt }
230d7b241e6Sjeremylt 
231d7b241e6Sjeremylt /**
23252d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
233288c0443SJeremy L Thompson 
234288c0443SJeremy L Thompson   @param[out] compositeop Address of the composite CeedOperator
235288c0443SJeremy L Thompson   @param      subop       Address of the sub-operator CeedOperator
23652d6035fSJeremy L Thompson 
23752d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
23852d6035fSJeremy L Thompson 
23952d6035fSJeremy L Thompson   @ref Basic
24052d6035fSJeremy L Thompson  */
241692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) {
24252d6035fSJeremy L Thompson   if (!compositeop->composite)
243c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2441d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite "
2451d102b48SJeremy L Thompson                      "operator");
246c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
24752d6035fSJeremy L Thompson 
24852d6035fSJeremy L Thompson   if (compositeop->numsub == CEED_COMPOSITE_MAX)
249c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2501d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators");
251c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
25252d6035fSJeremy L Thompson 
25352d6035fSJeremy L Thompson   compositeop->suboperators[compositeop->numsub] = subop;
25452d6035fSJeremy L Thompson   subop->refcount++;
25552d6035fSJeremy L Thompson   compositeop->numsub++;
25652d6035fSJeremy L Thompson   return 0;
25752d6035fSJeremy L Thompson }
25852d6035fSJeremy L Thompson 
25952d6035fSJeremy L Thompson /**
2605107b09fSJeremy L Thompson   @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced
2615107b09fSJeremy L Thompson            CeedOperator functionality
2625107b09fSJeremy L Thompson 
2635107b09fSJeremy L Thompson   @param op           CeedOperator to create fallback for
2645107b09fSJeremy L Thompson 
2655107b09fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2665107b09fSJeremy L Thompson 
2675107b09fSJeremy L Thompson   @ref Developer
2685107b09fSJeremy L Thompson **/
2695107b09fSJeremy L Thompson int CeedOperatorCreateFallback(CeedOperator op) {
2705107b09fSJeremy L Thompson   int ierr;
2715107b09fSJeremy L Thompson 
2725107b09fSJeremy L Thompson   // Fallback Ceed
2735107b09fSJeremy L Thompson   const char *resource, *fallbackresource;
2745107b09fSJeremy L Thompson   ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr);
2755107b09fSJeremy L Thompson   ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource);
2765107b09fSJeremy L Thompson   CeedChk(ierr);
2775107b09fSJeremy L Thompson   if (!strcmp(resource, fallbackresource))
2785107b09fSJeremy L Thompson     // LCOV_EXCL_START
2795107b09fSJeremy L Thompson     return CeedError(op->ceed, 1, "Backend %s cannot create an operator"
2805107b09fSJeremy L Thompson                      "fallback to resource %s", resource, fallbackresource);
2815107b09fSJeremy L Thompson   // LCOV_EXCL_STOP
2825107b09fSJeremy L Thompson 
2835107b09fSJeremy L Thompson   Ceed ceedref;
2845107b09fSJeremy L Thompson   ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr);
2855107b09fSJeremy L Thompson   ceedref->opfallbackparent = op->ceed;
2865107b09fSJeremy L Thompson   op->ceed->opfallbackceed = ceedref;
2875107b09fSJeremy L Thompson 
2885107b09fSJeremy L Thompson   // Clone Op
2895107b09fSJeremy L Thompson   CeedOperator opref;
2905107b09fSJeremy L Thompson   ierr = CeedCalloc(1, &opref); CeedChk(ierr);
2915107b09fSJeremy L Thompson   memcpy(opref, op, sizeof(*opref)); CeedChk(ierr);
2925107b09fSJeremy L Thompson   opref->data = NULL;
2935107b09fSJeremy L Thompson   opref->setupdone = 0;
2945107b09fSJeremy L Thompson   opref->ceed = ceedref;
2955107b09fSJeremy L Thompson   ierr = ceedref->OperatorCreate(opref); CeedChk(ierr);
2965107b09fSJeremy L Thompson   op->opfallback = opref;
2975107b09fSJeremy L Thompson 
2985107b09fSJeremy L Thompson   // Clone QF
2995107b09fSJeremy L Thompson   CeedQFunction qfref;
3005107b09fSJeremy L Thompson   ierr = CeedCalloc(1, &qfref); CeedChk(ierr);
3015107b09fSJeremy L Thompson   memcpy(qfref, (op->qf), sizeof(*qfref)); CeedChk(ierr);
3025107b09fSJeremy L Thompson   qfref->data = NULL;
3035107b09fSJeremy L Thompson   qfref->ceed = ceedref;
3045107b09fSJeremy L Thompson   ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr);
3055107b09fSJeremy L Thompson   opref->qf = qfref;
3065107b09fSJeremy L Thompson   op->qffallback = qfref;
3075107b09fSJeremy L Thompson 
3085107b09fSJeremy L Thompson   return 0;
3095107b09fSJeremy L Thompson }
3105107b09fSJeremy L Thompson 
3115107b09fSJeremy L Thompson /**
3121d102b48SJeremy L Thompson   @brief Assemble a linear CeedQFunction associated with a CeedOperator
3131d102b48SJeremy L Thompson 
3141d102b48SJeremy L Thompson   This returns a CeedVector containing a matrix at each quadrature point
3151d102b48SJeremy L Thompson     providing the action of the CeedQFunction associated with the CeedOperator.
3161d102b48SJeremy L Thompson     The vector 'assembled' is of shape
3171d102b48SJeremy L Thompson       [num_elements, num_input_fields, num_output_fields, num_quad_points]
3181d102b48SJeremy L Thompson     and contains column-major matrices representing the action of the
3191d102b48SJeremy L Thompson     CeedQFunction for a corresponding quadrature point on an element. Inputs and
3201d102b48SJeremy L Thompson     outputs are in the order provided by the user when adding CeedOperator fields.
3211d102b48SJeremy L Thompson     For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and
3221d102b48SJeremy L Thompson     'v', provided in that order, would result in an assembled QFunction that
3231d102b48SJeremy L Thompson     consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting
3241d102b48SJeremy L Thompson     on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v].
3251d102b48SJeremy L Thompson 
3261d102b48SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
3271d102b48SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedQFunction at
3281d102b48SJeremy L Thompson                           quadrature points
3291d102b48SJeremy L Thompson   @param[out] rstr      CeedElemRestriction for CeedVector containing assembled
3301d102b48SJeremy L Thompson                           CeedQFunction
3311d102b48SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
3321d102b48SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
3331d102b48SJeremy L Thompson 
3341d102b48SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3351d102b48SJeremy L Thompson 
336b7ec98d8SJeremy L Thompson   @ref Basic
3371d102b48SJeremy L Thompson **/
3381d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled,
3397f823360Sjeremylt                                         CeedElemRestriction *rstr,
3407f823360Sjeremylt                                         CeedRequest *request) {
3411d102b48SJeremy L Thompson   int ierr;
3421d102b48SJeremy L Thompson   Ceed ceed = op->ceed;
3431d102b48SJeremy L Thompson   CeedQFunction qf = op->qf;
3441d102b48SJeremy L Thompson 
3451d102b48SJeremy L Thompson   if (op->composite) {
346138d4072Sjeremylt     // LCOV_EXCL_START
3471d102b48SJeremy L Thompson     return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator");
348138d4072Sjeremylt     // LCOV_EXCL_STOP
3491d102b48SJeremy L Thompson   } else {
3501d102b48SJeremy L Thompson     if (op->nfields == 0)
351138d4072Sjeremylt       // LCOV_EXCL_START
3521d102b48SJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
353138d4072Sjeremylt     // LCOV_EXCL_STOP
3541d102b48SJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
355138d4072Sjeremylt       // LCOV_EXCL_START
3561d102b48SJeremy L Thompson       return CeedError( ceed, 1, "Not all operator fields set");
357138d4072Sjeremylt     // LCOV_EXCL_STOP
3582cb0afc5Sjeremylt     if (!op->hasrestriction)
359138d4072Sjeremylt       // LCOV_EXCL_START
3601d102b48SJeremy L Thompson       return CeedError(ceed, 1, "At least one restriction required");
361138d4072Sjeremylt     // LCOV_EXCL_STOP
3621d102b48SJeremy L Thompson     if (op->numqpoints == 0)
363138d4072Sjeremylt       // LCOV_EXCL_START
3641d102b48SJeremy L Thompson       return CeedError(ceed, 1, "At least one non-collocated basis required");
365138d4072Sjeremylt     // LCOV_EXCL_STOP
3661d102b48SJeremy L Thompson   }
3675107b09fSJeremy L Thompson   if (op->AssembleLinearQFunction) {
3681d102b48SJeremy L Thompson     ierr = op->AssembleLinearQFunction(op, assembled, rstr, request);
3691d102b48SJeremy L Thompson     CeedChk(ierr);
3705107b09fSJeremy L Thompson   } else {
3715107b09fSJeremy L Thompson     // Fallback to reference Ceed
3725107b09fSJeremy L Thompson     if (!op->opfallback) {
3735107b09fSJeremy L Thompson       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
3745107b09fSJeremy L Thompson     }
3755107b09fSJeremy L Thompson     // Assemble
3765107b09fSJeremy L Thompson     ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled,
3775107b09fSJeremy L Thompson            rstr, request); CeedChk(ierr);
3785107b09fSJeremy L Thompson   }
3791d102b48SJeremy L Thompson   return 0;
3801d102b48SJeremy L Thompson }
3811d102b48SJeremy L Thompson 
3821d102b48SJeremy L Thompson /**
383b7ec98d8SJeremy L Thompson   @brief Assemble the diagonal of a square linear Operator
384b7ec98d8SJeremy L Thompson 
385b7ec98d8SJeremy L Thompson   This returns a CeedVector containing the diagonal of a linear CeedOperator.
386b7ec98d8SJeremy L Thompson 
387b7ec98d8SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
388b7ec98d8SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedOperator diagonal
389b7ec98d8SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
390b7ec98d8SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
391b7ec98d8SJeremy L Thompson 
392b7ec98d8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
393b7ec98d8SJeremy L Thompson 
394b7ec98d8SJeremy L Thompson   @ref Basic
395b7ec98d8SJeremy L Thompson **/
3967f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled,
3977f823360Sjeremylt                                        CeedRequest *request) {
398b7ec98d8SJeremy L Thompson   int ierr;
399b7ec98d8SJeremy L Thompson   Ceed ceed = op->ceed;
400b7ec98d8SJeremy L Thompson   CeedQFunction qf = op->qf;
401b7ec98d8SJeremy L Thompson 
402b7ec98d8SJeremy L Thompson   if (op->composite) {
403b7ec98d8SJeremy L Thompson     // LCOV_EXCL_START
404b7ec98d8SJeremy L Thompson     return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator");
405b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
406b7ec98d8SJeremy L Thompson   } else {
407b7ec98d8SJeremy L Thompson     if (op->nfields == 0)
408b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
409b7ec98d8SJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
410b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
411b7ec98d8SJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
412b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
413b7ec98d8SJeremy L Thompson       return CeedError( ceed, 1, "Not all operator fields set");
414b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
4152cb0afc5Sjeremylt     if (!op->hasrestriction)
416b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
417b7ec98d8SJeremy L Thompson       return CeedError(ceed, 1, "At least one restriction required");
418b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
419b7ec98d8SJeremy L Thompson     if (op->numqpoints == 0)
420b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
421b7ec98d8SJeremy L Thompson       return CeedError(ceed, 1, "At least one non-collocated basis required");
422b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
423b7ec98d8SJeremy L Thompson   }
424b7ec98d8SJeremy L Thompson 
425b7ec98d8SJeremy L Thompson   // Use backend version, if available
426b7ec98d8SJeremy L Thompson   if (op->AssembleLinearDiagonal) {
427b7ec98d8SJeremy L Thompson     ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr);
428b7ec98d8SJeremy L Thompson     return 0;
429b7ec98d8SJeremy L Thompson   }
430b7ec98d8SJeremy L Thompson 
431b7ec98d8SJeremy L Thompson   // Assemble QFunction
432b7ec98d8SJeremy L Thompson   CeedVector assembledqf;
433b7ec98d8SJeremy L Thompson   CeedElemRestriction rstr;
434b7ec98d8SJeremy L Thompson   ierr = CeedOperatorAssembleLinearQFunction(op,  &assembledqf, &rstr, request);
435b7ec98d8SJeremy L Thompson   CeedChk(ierr);
436b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr);
437b7ec98d8SJeremy L Thompson 
438b7ec98d8SJeremy L Thompson   // Determine active input basis
439112e3f70Sjeremylt   CeedInt numemodein = 0, ncomp, dim = 1;
440b7ec98d8SJeremy L Thompson   CeedEvalMode *emodein = NULL;
441112e3f70Sjeremylt   CeedBasis basisin = NULL;
442112e3f70Sjeremylt   CeedElemRestriction rstrin = NULL;
443b7ec98d8SJeremy L Thompson   for (CeedInt i=0; i<qf->numinputfields; i++)
444b7ec98d8SJeremy L Thompson     if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) {
445b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetBasis(op->inputfields[i], &basisin);
446b7ec98d8SJeremy L Thompson       CeedChk(ierr);
447b7ec98d8SJeremy L Thompson       ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr);
448b7ec98d8SJeremy L Thompson       ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr);
449b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetElemRestriction(op->inputfields[i], &rstrin);
450b7ec98d8SJeremy L Thompson       CeedChk(ierr);
451b7ec98d8SJeremy L Thompson       CeedEvalMode emode;
452b7ec98d8SJeremy L Thompson       ierr = CeedQFunctionFieldGetEvalMode(qf->inputfields[i], &emode);
453b7ec98d8SJeremy L Thompson       CeedChk(ierr);
454b7ec98d8SJeremy L Thompson       switch (emode) {
455b7ec98d8SJeremy L Thompson       case CEED_EVAL_NONE:
456b7ec98d8SJeremy L Thompson       case CEED_EVAL_INTERP:
457b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr);
458b7ec98d8SJeremy L Thompson         emodein[numemodein] = emode;
459b7ec98d8SJeremy L Thompson         numemodein += 1;
460b7ec98d8SJeremy L Thompson         break;
461b7ec98d8SJeremy L Thompson       case CEED_EVAL_GRAD:
462b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr);
463b7ec98d8SJeremy L Thompson         for (CeedInt d=0; d<dim; d++)
464b7ec98d8SJeremy L Thompson           emodein[numemodein+d] = emode;
465b7ec98d8SJeremy L Thompson         numemodein += dim;
466b7ec98d8SJeremy L Thompson         break;
467b7ec98d8SJeremy L Thompson       case CEED_EVAL_WEIGHT:
468b7ec98d8SJeremy L Thompson       case CEED_EVAL_DIV:
469b7ec98d8SJeremy L Thompson       case CEED_EVAL_CURL:
470b7ec98d8SJeremy L Thompson         break; // Caught by QF Assembly
471b7ec98d8SJeremy L Thompson       }
472b7ec98d8SJeremy L Thompson     }
473b7ec98d8SJeremy L Thompson 
474b7ec98d8SJeremy L Thompson   // Determine active output basis
475b7ec98d8SJeremy L Thompson   CeedInt numemodeout = 0;
476b7ec98d8SJeremy L Thompson   CeedEvalMode *emodeout = NULL;
477112e3f70Sjeremylt   CeedBasis basisout = NULL;
478112e3f70Sjeremylt   CeedElemRestriction rstrout = NULL;
479112e3f70Sjeremylt   CeedTransposeMode lmodeout = CEED_NOTRANSPOSE;
480b7ec98d8SJeremy L Thompson   for (CeedInt i=0; i<qf->numoutputfields; i++)
481b7ec98d8SJeremy L Thompson     if (op->outputfields[i]->vec == CEED_VECTOR_ACTIVE) {
482b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetBasis(op->outputfields[i], &basisout);
483b7ec98d8SJeremy L Thompson       CeedChk(ierr);
484b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetElemRestriction(op->outputfields[i], &rstrout);
485b7ec98d8SJeremy L Thompson       CeedChk(ierr);
486b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetLMode(op->outputfields[i], &lmodeout);
487b7ec98d8SJeremy L Thompson       CeedChk(ierr);
488b7ec98d8SJeremy L Thompson       CeedEvalMode emode;
489b7ec98d8SJeremy L Thompson       ierr = CeedQFunctionFieldGetEvalMode(qf->outputfields[i], &emode);
490b7ec98d8SJeremy L Thompson       CeedChk(ierr);
491b7ec98d8SJeremy L Thompson       switch (emode) {
492b7ec98d8SJeremy L Thompson       case CEED_EVAL_NONE:
493b7ec98d8SJeremy L Thompson       case CEED_EVAL_INTERP:
494b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr);
495b7ec98d8SJeremy L Thompson         emodeout[numemodeout] = emode;
496b7ec98d8SJeremy L Thompson         numemodeout += 1;
497b7ec98d8SJeremy L Thompson         break;
498b7ec98d8SJeremy L Thompson       case CEED_EVAL_GRAD:
499b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr);
500b7ec98d8SJeremy L Thompson         for (CeedInt d=0; d<dim; d++)
501b7ec98d8SJeremy L Thompson           emodeout[numemodeout+d] = emode;
502b7ec98d8SJeremy L Thompson         numemodeout += dim;
503b7ec98d8SJeremy L Thompson         break;
504b7ec98d8SJeremy L Thompson       case CEED_EVAL_WEIGHT:
505b7ec98d8SJeremy L Thompson       case CEED_EVAL_DIV:
506b7ec98d8SJeremy L Thompson       case CEED_EVAL_CURL:
507b7ec98d8SJeremy L Thompson         break; // Caught by QF Assembly
508b7ec98d8SJeremy L Thompson       }
509b7ec98d8SJeremy L Thompson     }
510b7ec98d8SJeremy L Thompson 
511b7ec98d8SJeremy L Thompson   // Create diagonal vector
512b7ec98d8SJeremy L Thompson   CeedVector elemdiag;
513b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag);
514b7ec98d8SJeremy L Thompson   CeedChk(ierr);
515b7ec98d8SJeremy L Thompson 
516b7ec98d8SJeremy L Thompson   // Assemble element operator diagonals
517b7ec98d8SJeremy L Thompson   CeedScalar *elemdiagarray, *assembledqfarray;
518b7ec98d8SJeremy L Thompson   ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr);
519b7ec98d8SJeremy L Thompson   ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray);
520b7ec98d8SJeremy L Thompson   CeedChk(ierr);
521b7ec98d8SJeremy L Thompson   ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray);
522b7ec98d8SJeremy L Thompson   CeedChk(ierr);
523b7ec98d8SJeremy L Thompson   CeedInt nelem, nnodes, nqpts;
524b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr);
525b7ec98d8SJeremy L Thompson   ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr);
526b7ec98d8SJeremy L Thompson   ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr);
527b7ec98d8SJeremy L Thompson   // Compute the diagonal of B^T D B
528b7ec98d8SJeremy L Thompson   // Each node, qpt pair
529b7ec98d8SJeremy L Thompson   for (CeedInt n=0; n<nnodes; n++)
530b7ec98d8SJeremy L Thompson     for (CeedInt q=0; q<nqpts; q++) {
531b7ec98d8SJeremy L Thompson       CeedInt dout = -1;
532b7ec98d8SJeremy L Thompson       // Each basis eval mode pair
533b7ec98d8SJeremy L Thompson       for (CeedInt eout=0; eout<numemodeout; eout++) {
534b7ec98d8SJeremy L Thompson         CeedScalar bt = 1.0;
535b7ec98d8SJeremy L Thompson         if (emodeout[eout] == CEED_EVAL_GRAD)
536b7ec98d8SJeremy L Thompson           dout += 1;
537b7ec98d8SJeremy L Thompson         ierr = CeedBasisGetValue(basisout, emodeout[eout], q, n, dout, &bt);
538b7ec98d8SJeremy L Thompson         CeedChk(ierr);
539b7ec98d8SJeremy L Thompson         CeedInt din = -1;
540b7ec98d8SJeremy L Thompson         for (CeedInt ein=0; ein<numemodein; ein++) {
541b7ec98d8SJeremy L Thompson           CeedScalar b = 0.0;
542b7ec98d8SJeremy L Thompson           if (emodein[ein] == CEED_EVAL_GRAD)
543b7ec98d8SJeremy L Thompson             din += 1;
544b7ec98d8SJeremy L Thompson           ierr = CeedBasisGetValue(basisin, emodein[ein], q, n, din, &b);
545b7ec98d8SJeremy L Thompson           CeedChk(ierr);
546b7ec98d8SJeremy L Thompson           // Each element and component
547b7ec98d8SJeremy L Thompson           for (CeedInt e=0; e<nelem; e++)
548b7ec98d8SJeremy L Thompson             for (CeedInt cout=0; cout<ncomp; cout++) {
549b7ec98d8SJeremy L Thompson               CeedScalar db = 0.0;
550b7ec98d8SJeremy L Thompson               for (CeedInt cin=0; cin<ncomp; cin++)
551b7ec98d8SJeremy L Thompson                 db += assembledqfarray[((((e*numemodein+ein)*ncomp+cin)*
552b7ec98d8SJeremy L Thompson                                          numemodeout+eout)*ncomp+cout)*nqpts+q]*b;
553b7ec98d8SJeremy L Thompson               elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt * db;
554b7ec98d8SJeremy L Thompson             }
555b7ec98d8SJeremy L Thompson         }
556b7ec98d8SJeremy L Thompson       }
557b7ec98d8SJeremy L Thompson     }
558b7ec98d8SJeremy L Thompson 
559b7ec98d8SJeremy L Thompson   ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr);
560b7ec98d8SJeremy L Thompson   ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr);
561b7ec98d8SJeremy L Thompson 
562b7ec98d8SJeremy L Thompson   // Assemble local operator diagonal
563b7ec98d8SJeremy L Thompson   ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr);
564b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag,
565b7ec98d8SJeremy L Thompson                                   *assembled, request); CeedChk(ierr);
566b7ec98d8SJeremy L Thompson 
567b7ec98d8SJeremy L Thompson   // Cleanup
568b7ec98d8SJeremy L Thompson   ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr);
569b7ec98d8SJeremy L Thompson   ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr);
570b7ec98d8SJeremy L Thompson   ierr = CeedFree(&emodein); CeedChk(ierr);
571b7ec98d8SJeremy L Thompson   ierr = CeedFree(&emodeout); CeedChk(ierr);
572b7ec98d8SJeremy L Thompson 
573b7ec98d8SJeremy L Thompson   return 0;
574b7ec98d8SJeremy L Thompson }
575b7ec98d8SJeremy L Thompson 
576b7ec98d8SJeremy L Thompson /**
577*cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and overwrite output vector
578d7b241e6Sjeremylt 
579d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
580d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
581d7b241e6Sjeremylt   CeedOperatorSetField().
582d7b241e6Sjeremylt 
583d7b241e6Sjeremylt   @param op        CeedOperator to apply
584b11c1e72Sjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
585b11c1e72Sjeremylt                      active inputs
586b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
587d7b241e6Sjeremylt                      distinct from @a in) or NULL if there are no active outputs
588d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
589d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
590b11c1e72Sjeremylt 
591b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
592dfdf5a53Sjeremylt 
593dfdf5a53Sjeremylt   @ref Basic
594b11c1e72Sjeremylt **/
595692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
596692c2638Sjeremylt                       CeedRequest *request) {
597d7b241e6Sjeremylt   int ierr;
598d7b241e6Sjeremylt   Ceed ceed = op->ceed;
599d7b241e6Sjeremylt   CeedQFunction qf = op->qf;
600d7b241e6Sjeremylt 
60152d6035fSJeremy L Thompson   if (op->composite) {
602c042f62fSJeremy L Thompson     if (!op->numsub)
603c042f62fSJeremy L Thompson       // LCOV_EXCL_START
604c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "No suboperators set");
605c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
60652d6035fSJeremy L Thompson   } else {
607c042f62fSJeremy L Thompson     if (op->nfields == 0)
608c042f62fSJeremy L Thompson       // LCOV_EXCL_START
609c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
610c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
611c042f62fSJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
612c042f62fSJeremy L Thompson       // LCOV_EXCL_START
613c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "Not all operator fields set");
614c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
6152cb0afc5Sjeremylt     if (!op->hasrestriction)
616c042f62fSJeremy L Thompson       // LCOV_EXCL_START
617c042f62fSJeremy L Thompson       return CeedError(ceed, 1,"At least one restriction required");
618c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
619c042f62fSJeremy L Thompson     if (op->numqpoints == 0)
620c042f62fSJeremy L Thompson       // LCOV_EXCL_START
621c042f62fSJeremy L Thompson       return CeedError(ceed, 1,"At least one non-collocated basis required");
622c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
62352d6035fSJeremy L Thompson   }
6241d7d2407SJeremy L Thompson   if (op->numelements || op->composite) {
625*cae8b89aSjeremylt     if (op->Apply) {
626e97ff134Sjeremylt       ierr = op->Apply(op, in != CEED_VECTOR_NONE ? in : NULL,
627e97ff134Sjeremylt                        out != CEED_VECTOR_NONE ? out : NULL, request);
628e97ff134Sjeremylt       CeedChk(ierr);
629*cae8b89aSjeremylt     } else {
630*cae8b89aSjeremylt       // Zero all output vectors
631*cae8b89aSjeremylt       if (!op->composite) {
632*cae8b89aSjeremylt         for (CeedInt i=0; i<qf->numoutputfields; i++) {
633*cae8b89aSjeremylt           CeedVector vec = op->outputfields[i]->vec;
634*cae8b89aSjeremylt           if (vec == CEED_VECTOR_ACTIVE)
635*cae8b89aSjeremylt             vec = out;
636*cae8b89aSjeremylt           if (vec != CEED_VECTOR_NONE) {
637*cae8b89aSjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
638*cae8b89aSjeremylt           }
639*cae8b89aSjeremylt         }
640*cae8b89aSjeremylt       } else if (out != CEED_VECTOR_NONE) { // Zero active output if composite
641*cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
642*cae8b89aSjeremylt       }
643*cae8b89aSjeremylt       ierr = op->ApplyAdd(op, in != CEED_VECTOR_NONE ? in : NULL,
644*cae8b89aSjeremylt                           out != CEED_VECTOR_NONE ? out : NULL, request);
645*cae8b89aSjeremylt       CeedChk(ierr);
646*cae8b89aSjeremylt     }
647*cae8b89aSjeremylt   }
648*cae8b89aSjeremylt   return 0;
649*cae8b89aSjeremylt }
650*cae8b89aSjeremylt 
651*cae8b89aSjeremylt /**
652*cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
653*cae8b89aSjeremylt 
654*cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
655*cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
656*cae8b89aSjeremylt   CeedOperatorSetField().
657*cae8b89aSjeremylt 
658*cae8b89aSjeremylt   @param op        CeedOperator to apply
659*cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
660*cae8b89aSjeremylt                      active inputs
661*cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
662*cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
663*cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
664*cae8b89aSjeremylt                      CEED_REQUEST_IMMEDIATE
665*cae8b89aSjeremylt 
666*cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
667*cae8b89aSjeremylt 
668*cae8b89aSjeremylt   @ref Basic
669*cae8b89aSjeremylt **/
670*cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
671*cae8b89aSjeremylt                          CeedRequest *request) {
672*cae8b89aSjeremylt   int ierr;
673*cae8b89aSjeremylt   Ceed ceed = op->ceed;
674*cae8b89aSjeremylt   CeedQFunction qf = op->qf;
675*cae8b89aSjeremylt 
676*cae8b89aSjeremylt   if (op->composite) {
677*cae8b89aSjeremylt     if (!op->numsub)
678*cae8b89aSjeremylt       // LCOV_EXCL_START
679*cae8b89aSjeremylt       return CeedError(ceed, 1, "No suboperators set");
680*cae8b89aSjeremylt     // LCOV_EXCL_STOP
681*cae8b89aSjeremylt   } else {
682*cae8b89aSjeremylt     if (op->nfields == 0)
683*cae8b89aSjeremylt       // LCOV_EXCL_START
684*cae8b89aSjeremylt       return CeedError(ceed, 1, "No operator fields set");
685*cae8b89aSjeremylt     // LCOV_EXCL_STOP
686*cae8b89aSjeremylt     if (op->nfields < qf->numinputfields + qf->numoutputfields)
687*cae8b89aSjeremylt       // LCOV_EXCL_START
688*cae8b89aSjeremylt       return CeedError(ceed, 1, "Not all operator fields set");
689*cae8b89aSjeremylt     // LCOV_EXCL_STOP
690*cae8b89aSjeremylt     if (!op->hasrestriction)
691*cae8b89aSjeremylt       // LCOV_EXCL_START
692*cae8b89aSjeremylt       return CeedError(ceed, 1,"At least one restriction required");
693*cae8b89aSjeremylt     // LCOV_EXCL_STOP
694*cae8b89aSjeremylt     if (op->numqpoints == 0)
695*cae8b89aSjeremylt       // LCOV_EXCL_START
696*cae8b89aSjeremylt       return CeedError(ceed, 1,"At least one non-collocated basis required");
697*cae8b89aSjeremylt     // LCOV_EXCL_STOP
698*cae8b89aSjeremylt   }
699*cae8b89aSjeremylt   if (op->numelements || op->composite) {
700*cae8b89aSjeremylt     ierr = op->ApplyAdd(op, in != CEED_VECTOR_NONE ? in : NULL,
701*cae8b89aSjeremylt                         out != CEED_VECTOR_NONE ? out : NULL, request);
702*cae8b89aSjeremylt     CeedChk(ierr);
7031d7d2407SJeremy L Thompson   }
704d7b241e6Sjeremylt   return 0;
705d7b241e6Sjeremylt }
706d7b241e6Sjeremylt 
707d7b241e6Sjeremylt /**
7084ce2993fSjeremylt   @brief Get the Ceed associated with a CeedOperator
7094ce2993fSjeremylt 
7104ce2993fSjeremylt   @param op              CeedOperator
7114ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
7124ce2993fSjeremylt 
7134ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7144ce2993fSjeremylt 
71523617272Sjeremylt   @ref Advanced
7164ce2993fSjeremylt **/
7174ce2993fSjeremylt 
7184ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
7194ce2993fSjeremylt   *ceed = op->ceed;
7204ce2993fSjeremylt   return 0;
7214ce2993fSjeremylt }
7224ce2993fSjeremylt 
7234ce2993fSjeremylt /**
7244ce2993fSjeremylt   @brief Get the number of elements associated with a CeedOperator
7254ce2993fSjeremylt 
7264ce2993fSjeremylt   @param op              CeedOperator
7274ce2993fSjeremylt   @param[out] numelem    Variable to store number of elements
7284ce2993fSjeremylt 
7294ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7304ce2993fSjeremylt 
73123617272Sjeremylt   @ref Advanced
7324ce2993fSjeremylt **/
7334ce2993fSjeremylt 
7344ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
73552d6035fSJeremy L Thompson   if (op->composite)
736c042f62fSJeremy L Thompson     // LCOV_EXCL_START
73752d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
738c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
73952d6035fSJeremy L Thompson 
7404ce2993fSjeremylt   *numelem = op->numelements;
7414ce2993fSjeremylt   return 0;
7424ce2993fSjeremylt }
7434ce2993fSjeremylt 
7444ce2993fSjeremylt /**
7454ce2993fSjeremylt   @brief Get the number of quadrature points associated with a CeedOperator
7464ce2993fSjeremylt 
7474ce2993fSjeremylt   @param op              CeedOperator
7484ce2993fSjeremylt   @param[out] numqpts    Variable to store vector number of quadrature points
7494ce2993fSjeremylt 
7504ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7514ce2993fSjeremylt 
75223617272Sjeremylt   @ref Advanced
7534ce2993fSjeremylt **/
7544ce2993fSjeremylt 
7554ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
75652d6035fSJeremy L Thompson   if (op->composite)
757c042f62fSJeremy L Thompson     // LCOV_EXCL_START
75852d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
759c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
76052d6035fSJeremy L Thompson 
7614ce2993fSjeremylt   *numqpts = op->numqpoints;
7624ce2993fSjeremylt   return 0;
7634ce2993fSjeremylt }
7644ce2993fSjeremylt 
7654ce2993fSjeremylt /**
7664ce2993fSjeremylt   @brief Get the number of arguments associated with a CeedOperator
7674ce2993fSjeremylt 
7684ce2993fSjeremylt   @param op              CeedOperator
7694ce2993fSjeremylt   @param[out] numargs    Variable to store vector number of arguments
7704ce2993fSjeremylt 
7714ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7724ce2993fSjeremylt 
77323617272Sjeremylt   @ref Advanced
7744ce2993fSjeremylt **/
7754ce2993fSjeremylt 
7764ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
77752d6035fSJeremy L Thompson   if (op->composite)
778c042f62fSJeremy L Thompson     // LCOV_EXCL_START
77952d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operators");
780c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
781c042f62fSJeremy L Thompson 
7824ce2993fSjeremylt   *numargs = op->nfields;
7834ce2993fSjeremylt   return 0;
7844ce2993fSjeremylt }
7854ce2993fSjeremylt 
7864ce2993fSjeremylt /**
7874ce2993fSjeremylt   @brief Get the setup status of a CeedOperator
7884ce2993fSjeremylt 
7894ce2993fSjeremylt   @param op             CeedOperator
790288c0443SJeremy L Thompson   @param[out] setupdone Variable to store setup status
7914ce2993fSjeremylt 
7924ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7934ce2993fSjeremylt 
79423617272Sjeremylt   @ref Advanced
7954ce2993fSjeremylt **/
7964ce2993fSjeremylt 
7974ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
7984ce2993fSjeremylt   *setupdone = op->setupdone;
7994ce2993fSjeremylt   return 0;
8004ce2993fSjeremylt }
8014ce2993fSjeremylt 
8024ce2993fSjeremylt /**
8034ce2993fSjeremylt   @brief Get the QFunction associated with a CeedOperator
8044ce2993fSjeremylt 
8054ce2993fSjeremylt   @param op              CeedOperator
8068c91a0c9SJeremy L Thompson   @param[out] qf         Variable to store QFunction
8074ce2993fSjeremylt 
8084ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
8094ce2993fSjeremylt 
81023617272Sjeremylt   @ref Advanced
8114ce2993fSjeremylt **/
8124ce2993fSjeremylt 
8134ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
81452d6035fSJeremy L Thompson   if (op->composite)
815c042f62fSJeremy L Thompson     // LCOV_EXCL_START
81652d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
817c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
81852d6035fSJeremy L Thompson 
8194ce2993fSjeremylt   *qf = op->qf;
8204ce2993fSjeremylt   return 0;
8214ce2993fSjeremylt }
8224ce2993fSjeremylt 
8234ce2993fSjeremylt /**
82452d6035fSJeremy L Thompson   @brief Get the number of suboperators associated with a CeedOperator
82552d6035fSJeremy L Thompson 
82652d6035fSJeremy L Thompson   @param op              CeedOperator
82752d6035fSJeremy L Thompson   @param[out] numsub     Variable to store number of suboperators
82852d6035fSJeremy L Thompson 
82952d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83052d6035fSJeremy L Thompson 
83152d6035fSJeremy L Thompson   @ref Advanced
83252d6035fSJeremy L Thompson **/
83352d6035fSJeremy L Thompson 
83452d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) {
835c042f62fSJeremy L Thompson   if (!op->composite)
836c042f62fSJeremy L Thompson     // LCOV_EXCL_START
837c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
838c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
83952d6035fSJeremy L Thompson 
84052d6035fSJeremy L Thompson   *numsub = op->numsub;
84152d6035fSJeremy L Thompson   return 0;
84252d6035fSJeremy L Thompson }
84352d6035fSJeremy L Thompson 
84452d6035fSJeremy L Thompson /**
84552d6035fSJeremy L Thompson   @brief Get the list of suboperators associated with a CeedOperator
84652d6035fSJeremy L Thompson 
84752d6035fSJeremy L Thompson   @param op                CeedOperator
84852d6035fSJeremy L Thompson   @param[out] suboperators Variable to store list of suboperators
84952d6035fSJeremy L Thompson 
85052d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
85152d6035fSJeremy L Thompson 
85252d6035fSJeremy L Thompson   @ref Advanced
85352d6035fSJeremy L Thompson **/
85452d6035fSJeremy L Thompson 
85552d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) {
856c042f62fSJeremy L Thompson   if (!op->composite)
857c042f62fSJeremy L Thompson     // LCOV_EXCL_START
858c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
859c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
86052d6035fSJeremy L Thompson 
86152d6035fSJeremy L Thompson   *suboperators = op->suboperators;
86252d6035fSJeremy L Thompson   return 0;
86352d6035fSJeremy L Thompson }
86452d6035fSJeremy L Thompson 
86552d6035fSJeremy L Thompson /**
866fe2413ffSjeremylt   @brief Set the backend data of a CeedOperator
867fe2413ffSjeremylt 
868fe2413ffSjeremylt   @param[out] op         CeedOperator
869fe2413ffSjeremylt   @param data            Data to set
870fe2413ffSjeremylt 
871fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
872fe2413ffSjeremylt 
873fe2413ffSjeremylt   @ref Advanced
874fe2413ffSjeremylt **/
875fe2413ffSjeremylt 
876fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void **data) {
877fe2413ffSjeremylt   op->data = *data;
878fe2413ffSjeremylt   return 0;
879fe2413ffSjeremylt }
880fe2413ffSjeremylt 
881fe2413ffSjeremylt /**
8824ce2993fSjeremylt   @brief Get the backend data of a CeedOperator
8834ce2993fSjeremylt 
8844ce2993fSjeremylt   @param op              CeedOperator
8854ce2993fSjeremylt   @param[out] data       Variable to store data
8864ce2993fSjeremylt 
8874ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
8884ce2993fSjeremylt 
88923617272Sjeremylt   @ref Advanced
8904ce2993fSjeremylt **/
8914ce2993fSjeremylt 
8924ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void **data) {
8934ce2993fSjeremylt   *data = op->data;
8944ce2993fSjeremylt   return 0;
8954ce2993fSjeremylt }
8964ce2993fSjeremylt 
8974ce2993fSjeremylt /**
8984ce2993fSjeremylt   @brief Set the setup flag of a CeedOperator to True
8994ce2993fSjeremylt 
9004ce2993fSjeremylt   @param op              CeedOperator
9014ce2993fSjeremylt 
9024ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
9034ce2993fSjeremylt 
90423617272Sjeremylt   @ref Advanced
9054ce2993fSjeremylt **/
9064ce2993fSjeremylt 
9074ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) {
9084ce2993fSjeremylt   op->setupdone = 1;
9094ce2993fSjeremylt   return 0;
9104ce2993fSjeremylt }
9114ce2993fSjeremylt 
9124ce2993fSjeremylt /**
9132ebaca42Sjeremylt   @brief View a field of a CeedOperator
9142ebaca42Sjeremylt 
9152ebaca42Sjeremylt   @param[in] field       Operator field to view
9162ebaca42Sjeremylt   @param[in] fieldnumber Number of field being viewed
9172ebaca42Sjeremylt   @param[in] stream      Stream to view to, e.g., stdout
9182ebaca42Sjeremylt 
9192ebaca42Sjeremylt   @return An error code: 0 - success, otherwise - failure
9202ebaca42Sjeremylt 
9212ebaca42Sjeremylt   @ref Utility
9222ebaca42Sjeremylt **/
9232ebaca42Sjeremylt static int CeedOperatorFieldView(CeedOperatorField field,
9242ebaca42Sjeremylt                                  CeedQFunctionField qffield,
9252da88da5Sjeremylt                                  CeedInt fieldnumber, bool sub, bool in,
9262da88da5Sjeremylt                                  FILE *stream) {
9272ebaca42Sjeremylt   const char *pre = sub ? "  " : "";
9282da88da5Sjeremylt   const char *inout = in ? "Input" : "Output";
9292ebaca42Sjeremylt 
9302da88da5Sjeremylt   fprintf(stream, "%s    %s Field [%d]:\n"
9312da88da5Sjeremylt           "%s      Name: \"%s\"\n"
9322da88da5Sjeremylt           "%s      Lmode: \"%s\"\n",
9332da88da5Sjeremylt           pre, inout, fieldnumber, pre, qffield->fieldname,
9342ebaca42Sjeremylt           pre, CeedTransposeModes[field->lmode]);
9352ebaca42Sjeremylt 
9362ebaca42Sjeremylt   if (field->basis == CEED_BASIS_COLLOCATED)
9372ebaca42Sjeremylt     fprintf(stream, "%s      Collocated basis\n", pre);
9382ebaca42Sjeremylt 
9392ebaca42Sjeremylt   if (field->vec == CEED_VECTOR_ACTIVE)
9402ebaca42Sjeremylt     fprintf(stream, "%s      Active vector\n", pre);
9412ebaca42Sjeremylt   else if (field->vec == CEED_VECTOR_NONE)
9422ebaca42Sjeremylt     fprintf(stream, "%s      No vector\n", pre);
9432ebaca42Sjeremylt 
9442ebaca42Sjeremylt   return 0;
9452ebaca42Sjeremylt }
9462ebaca42Sjeremylt 
9472ebaca42Sjeremylt /**
9482ebaca42Sjeremylt   @brief View a single CeedOperator
9492ebaca42Sjeremylt 
9502ebaca42Sjeremylt   @param[in] op     CeedOperator to view
9512ebaca42Sjeremylt   @param[in] stream Stream to write; typically stdout/stderr or a file
9522ebaca42Sjeremylt 
9532ebaca42Sjeremylt   @return Error code: 0 - success, otherwise - failure
9542ebaca42Sjeremylt 
9552ebaca42Sjeremylt   @ref Utility
9562ebaca42Sjeremylt **/
9572ebaca42Sjeremylt int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
9582ebaca42Sjeremylt   int ierr;
9592ebaca42Sjeremylt   const char *pre = sub ? "  " : "";
9602ebaca42Sjeremylt 
9612ebaca42Sjeremylt   CeedInt totalfields;
9622ebaca42Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr);
9632da88da5Sjeremylt 
9642ebaca42Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : "");
9652ebaca42Sjeremylt 
9662da88da5Sjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->numinputfields,
9672ebaca42Sjeremylt           op->qf->numinputfields>1 ? "s" : "");
9682ebaca42Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
9692ebaca42Sjeremylt     ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i],
9702da88da5Sjeremylt                                  i, sub, 1, stream); CeedChk(ierr);
9712ebaca42Sjeremylt   }
9722ebaca42Sjeremylt 
9732da88da5Sjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->numoutputfields,
9742ebaca42Sjeremylt           op->qf->numoutputfields>1 ? "s" : "");
9752ebaca42Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
9762ebaca42Sjeremylt     ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i],
9772da88da5Sjeremylt                                  i, sub, 0, stream); CeedChk(ierr);
9782ebaca42Sjeremylt   }
9792ebaca42Sjeremylt 
9802ebaca42Sjeremylt   return 0;
9812ebaca42Sjeremylt }
9822ebaca42Sjeremylt 
9832ebaca42Sjeremylt /**
9842ebaca42Sjeremylt   @brief View a CeedOperator
9852ebaca42Sjeremylt 
9862ebaca42Sjeremylt   @param[in] op     CeedOperator to view
9872ebaca42Sjeremylt   @param[in] stream Stream to write; typically stdout/stderr or a file
9882ebaca42Sjeremylt 
9892ebaca42Sjeremylt   @return Error code: 0 - success, otherwise - failure
9902ebaca42Sjeremylt 
9912ebaca42Sjeremylt   @ref Utility
9922ebaca42Sjeremylt **/
9932ebaca42Sjeremylt int CeedOperatorView(CeedOperator op, FILE *stream) {
9942ebaca42Sjeremylt   int ierr;
9952ebaca42Sjeremylt 
9962ebaca42Sjeremylt   if (op->composite) {
9972ebaca42Sjeremylt     fprintf(stream, "Composite CeedOperator\n");
9982ebaca42Sjeremylt 
9992ebaca42Sjeremylt     for (CeedInt i=0; i<op->numsub; i++) {
10002da88da5Sjeremylt       fprintf(stream, "  SubOperator [%d]:\n", i);
10012ebaca42Sjeremylt       ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream);
10022ebaca42Sjeremylt       CeedChk(ierr);
10032ebaca42Sjeremylt     }
10042ebaca42Sjeremylt   } else {
10052ebaca42Sjeremylt     fprintf(stream, "CeedOperator\n");
10062ebaca42Sjeremylt     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
10072ebaca42Sjeremylt   }
10082ebaca42Sjeremylt 
10092ebaca42Sjeremylt   return 0;
10102ebaca42Sjeremylt }
10112ebaca42Sjeremylt 
10122ebaca42Sjeremylt /**
1013d1bcdac9Sjeremylt   @brief Get the CeedOperatorFields of a CeedOperator
1014d1bcdac9Sjeremylt 
1015d1bcdac9Sjeremylt   @param op                 CeedOperator
1016d1bcdac9Sjeremylt   @param[out] inputfields   Variable to store inputfields
1017d1bcdac9Sjeremylt   @param[out] outputfields  Variable to store outputfields
1018d1bcdac9Sjeremylt 
1019d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
1020d1bcdac9Sjeremylt 
1021d1bcdac9Sjeremylt   @ref Advanced
1022d1bcdac9Sjeremylt **/
1023d1bcdac9Sjeremylt 
1024692c2638Sjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields,
1025d1bcdac9Sjeremylt                           CeedOperatorField **outputfields) {
102652d6035fSJeremy L Thompson   if (op->composite)
1027c042f62fSJeremy L Thompson     // LCOV_EXCL_START
102852d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
1029c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
103052d6035fSJeremy L Thompson 
1031d1bcdac9Sjeremylt   if (inputfields) *inputfields = op->inputfields;
1032d1bcdac9Sjeremylt   if (outputfields) *outputfields = op->outputfields;
1033d1bcdac9Sjeremylt   return 0;
1034d1bcdac9Sjeremylt }
1035d1bcdac9Sjeremylt 
1036d1bcdac9Sjeremylt /**
10374dccadb6Sjeremylt   @brief Get the L vector CeedTransposeMode of a CeedOperatorField
10384dccadb6Sjeremylt 
10394dccadb6Sjeremylt   @param opfield         CeedOperatorField
10404dccadb6Sjeremylt   @param[out] lmode      Variable to store CeedTransposeMode
10414dccadb6Sjeremylt 
10424dccadb6Sjeremylt   @return An error code: 0 - success, otherwise - failure
10434dccadb6Sjeremylt 
10444dccadb6Sjeremylt   @ref Advanced
10454dccadb6Sjeremylt **/
10464dccadb6Sjeremylt 
10474dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield,
10484dccadb6Sjeremylt                               CeedTransposeMode *lmode) {
1049fe2413ffSjeremylt   *lmode = opfield->lmode;
10504dccadb6Sjeremylt   return 0;
10512b8e417aSjeremylt }
10522b8e417aSjeremylt 
10532b8e417aSjeremylt /**
1054d1bcdac9Sjeremylt   @brief Get the CeedElemRestriction of a CeedOperatorField
1055d1bcdac9Sjeremylt 
1056d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
1057d1bcdac9Sjeremylt   @param[out] rstr       Variable to store CeedElemRestriction
1058d1bcdac9Sjeremylt 
1059d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
1060d1bcdac9Sjeremylt 
1061d1bcdac9Sjeremylt   @ref Advanced
1062d1bcdac9Sjeremylt **/
1063d1bcdac9Sjeremylt 
1064d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
1065d1bcdac9Sjeremylt                                         CeedElemRestriction *rstr) {
1066fe2413ffSjeremylt   *rstr = opfield->Erestrict;
1067d1bcdac9Sjeremylt   return 0;
1068d1bcdac9Sjeremylt }
1069d1bcdac9Sjeremylt 
1070d1bcdac9Sjeremylt /**
1071d1bcdac9Sjeremylt   @brief Get the CeedBasis of a CeedOperatorField
1072d1bcdac9Sjeremylt 
1073d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
1074d1bcdac9Sjeremylt   @param[out] basis      Variable to store CeedBasis
1075d1bcdac9Sjeremylt 
1076d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
1077d1bcdac9Sjeremylt 
1078d1bcdac9Sjeremylt   @ref Advanced
1079d1bcdac9Sjeremylt **/
1080d1bcdac9Sjeremylt 
1081692c2638Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) {
1082fe2413ffSjeremylt   *basis = opfield->basis;
1083d1bcdac9Sjeremylt   return 0;
1084d1bcdac9Sjeremylt }
1085d1bcdac9Sjeremylt 
1086d1bcdac9Sjeremylt /**
1087d1bcdac9Sjeremylt   @brief Get the CeedVector of a CeedOperatorField
1088d1bcdac9Sjeremylt 
1089d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
1090d1bcdac9Sjeremylt   @param[out] vec        Variable to store CeedVector
1091d1bcdac9Sjeremylt 
1092d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
1093d1bcdac9Sjeremylt 
1094d1bcdac9Sjeremylt   @ref Advanced
1095d1bcdac9Sjeremylt **/
1096d1bcdac9Sjeremylt 
1097692c2638Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) {
1098fe2413ffSjeremylt   *vec = opfield->vec;
1099d1bcdac9Sjeremylt   return 0;
1100d1bcdac9Sjeremylt }
1101d1bcdac9Sjeremylt 
1102d1bcdac9Sjeremylt /**
1103b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1104d7b241e6Sjeremylt 
1105d7b241e6Sjeremylt   @param op CeedOperator to destroy
1106b11c1e72Sjeremylt 
1107b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1108dfdf5a53Sjeremylt 
1109dfdf5a53Sjeremylt   @ref Basic
1110b11c1e72Sjeremylt **/
1111d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1112d7b241e6Sjeremylt   int ierr;
1113d7b241e6Sjeremylt 
1114d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
1115d7b241e6Sjeremylt   if ((*op)->Destroy) {
1116d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1117d7b241e6Sjeremylt   }
1118fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1119fe2413ffSjeremylt   // Free fields
11201d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
112152d6035fSJeremy L Thompson     if ((*op)->inputfields[i]) {
112271352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict);
112371352a93Sjeremylt       CeedChk(ierr);
112471352a93Sjeremylt       if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) {
112571352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr);
112671352a93Sjeremylt       }
112771352a93Sjeremylt       if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE &&
112871352a93Sjeremylt           (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) {
112971352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr);
113071352a93Sjeremylt       }
1131fe2413ffSjeremylt       ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr);
1132fe2413ffSjeremylt     }
11331d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
1134d0eb30a5Sjeremylt     if ((*op)->outputfields[i]) {
113571352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict);
113671352a93Sjeremylt       CeedChk(ierr);
113771352a93Sjeremylt       if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) {
113871352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr);
113971352a93Sjeremylt       }
114071352a93Sjeremylt       if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE &&
114171352a93Sjeremylt           (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) {
114271352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr);
114371352a93Sjeremylt       }
1144fe2413ffSjeremylt       ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr);
1145fe2413ffSjeremylt     }
114652d6035fSJeremy L Thompson   // Destroy suboperators
11471d102b48SJeremy L Thompson   for (int i=0; i<(*op)->numsub; i++)
114852d6035fSJeremy L Thompson     if ((*op)->suboperators[i]) {
114952d6035fSJeremy L Thompson       ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr);
115052d6035fSJeremy L Thompson     }
1151d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1152d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1153d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1154fe2413ffSjeremylt 
11555107b09fSJeremy L Thompson   // Destroy fallback
11565107b09fSJeremy L Thompson   if ((*op)->opfallback) {
11575107b09fSJeremy L Thompson     ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr);
11585107b09fSJeremy L Thompson     ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr);
11595107b09fSJeremy L Thompson     ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr);
11605107b09fSJeremy L Thompson     ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr);
11615107b09fSJeremy L Thompson   }
11625107b09fSJeremy L Thompson 
1163fe2413ffSjeremylt   ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr);
1164fe2413ffSjeremylt   ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr);
116552d6035fSJeremy L Thompson   ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr);
1166d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1167d7b241e6Sjeremylt   return 0;
1168d7b241e6Sjeremylt }
1169d7b241e6Sjeremylt 
1170d7b241e6Sjeremylt /// @}
1171