xref: /libCEED/interface/ceed-operator.c (revision a8d322087fa8f150327cdc2bf14a171452b711ec)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt #include <string.h>
203bd813ffSjeremylt #include <math.h>
21d7b241e6Sjeremylt 
22dfdf5a53Sjeremylt /// @file
23dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces
24dfdf5a53Sjeremylt ///
25dfdf5a53Sjeremylt /// @addtogroup CeedOperator
26dfdf5a53Sjeremylt ///   @{
27d7b241e6Sjeremylt 
28d7b241e6Sjeremylt /**
290219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
300219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
310219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
32d7b241e6Sjeremylt 
33b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
34d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
3534138859Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or
3634138859Sjeremylt                    CEED_QFUNCTION_NONE)
37d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
3834138859Sjeremylt                    of @a qf (or CEED_QFUNCTION_NONE)
39b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
40b11c1e72Sjeremylt                      CeedOperator will be stored
41b11c1e72Sjeremylt 
42b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
43dfdf5a53Sjeremylt 
44dfdf5a53Sjeremylt   @ref Basic
45d7b241e6Sjeremylt  */
46d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
47d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
48d7b241e6Sjeremylt   int ierr;
49d7b241e6Sjeremylt 
505fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
515fe0d4faSjeremylt     Ceed delegate;
52aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
535fe0d4faSjeremylt 
545fe0d4faSjeremylt     if (!delegate)
55c042f62fSJeremy L Thompson       // LCOV_EXCL_START
565fe0d4faSjeremylt       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
57c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
585fe0d4faSjeremylt 
595fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
605fe0d4faSjeremylt     return 0;
615fe0d4faSjeremylt   }
625fe0d4faSjeremylt 
63d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
64d7b241e6Sjeremylt   (*op)->ceed = ceed;
65d7b241e6Sjeremylt   ceed->refcount++;
66d7b241e6Sjeremylt   (*op)->refcount = 1;
67442e7f0bSjeremylt   if (qf == CEED_QFUNCTION_NONE)
68442e7f0bSjeremylt     // LCOV_EXCL_START
69442e7f0bSjeremylt     return CeedError(ceed, 1, "Operator must have a valid QFunction.");
70442e7f0bSjeremylt   // LCOV_EXCL_STOP
71d7b241e6Sjeremylt   (*op)->qf = qf;
72d7b241e6Sjeremylt   qf->refcount++;
73442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
74d7b241e6Sjeremylt     (*op)->dqf = dqf;
75442e7f0bSjeremylt     dqf->refcount++;
76442e7f0bSjeremylt   }
77442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
78d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
79442e7f0bSjeremylt     dqfT->refcount++;
80442e7f0bSjeremylt   }
81fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr);
82fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr);
83d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
84d7b241e6Sjeremylt   return 0;
85d7b241e6Sjeremylt }
86d7b241e6Sjeremylt 
87d7b241e6Sjeremylt /**
8852d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
8952d6035fSJeremy L Thompson 
9052d6035fSJeremy L Thompson   @param ceed    A Ceed object where the CeedOperator will be created
9152d6035fSJeremy L Thompson   @param[out] op Address of the variable where the newly created
9252d6035fSJeremy L Thompson                      Composite CeedOperator will be stored
9352d6035fSJeremy L Thompson 
9452d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9552d6035fSJeremy L Thompson 
9652d6035fSJeremy L Thompson   @ref Basic
9752d6035fSJeremy L Thompson  */
9852d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
9952d6035fSJeremy L Thompson   int ierr;
10052d6035fSJeremy L Thompson 
10152d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
10252d6035fSJeremy L Thompson     Ceed delegate;
103aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
10452d6035fSJeremy L Thompson 
105250756a7Sjeremylt     if (delegate) {
10652d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
10752d6035fSJeremy L Thompson       return 0;
10852d6035fSJeremy L Thompson     }
109250756a7Sjeremylt   }
11052d6035fSJeremy L Thompson 
11152d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
11252d6035fSJeremy L Thompson   (*op)->ceed = ceed;
11352d6035fSJeremy L Thompson   ceed->refcount++;
11452d6035fSJeremy L Thompson   (*op)->composite = true;
11552d6035fSJeremy L Thompson   ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr);
116250756a7Sjeremylt 
117250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
11852d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
119250756a7Sjeremylt   }
12052d6035fSJeremy L Thompson   return 0;
12152d6035fSJeremy L Thompson }
12252d6035fSJeremy L Thompson 
12352d6035fSJeremy L Thompson /**
124b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
125d7b241e6Sjeremylt 
126d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
127d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
128d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
129d7b241e6Sjeremylt 
130d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
131d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
132d7b241e6Sjeremylt   input and at most one active output.
133d7b241e6Sjeremylt 
1348c91a0c9SJeremy L Thompson   @param op         CeedOperator on which to provide the field
1358795c945Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by
1368795c945Sjeremylt                       CeedQFunction)
137b11c1e72Sjeremylt   @param r          CeedElemRestriction
138783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
139b11c1e72Sjeremylt                       if collocated with quadrature points
140b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
141b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
1428c91a0c9SJeremy L Thompson                       CEED_EVAL_WEIGHT in the QFunction
143b11c1e72Sjeremylt 
144b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
145dfdf5a53Sjeremylt 
146dfdf5a53Sjeremylt   @ref Basic
147b11c1e72Sjeremylt **/
148d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
149*a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
150d7b241e6Sjeremylt   int ierr;
15152d6035fSJeremy L Thompson   if (op->composite)
152c042f62fSJeremy L Thompson     // LCOV_EXCL_START
15352d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Cannot add field to composite operator.");
154c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1558b067b84SJed Brown   if (!r)
156c042f62fSJeremy L Thompson     // LCOV_EXCL_START
157c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1,
158c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
159c042f62fSJeremy L Thompson                      fieldname);
160c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1618b067b84SJed Brown   if (!b)
162c042f62fSJeremy L Thompson     // LCOV_EXCL_START
163c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.",
164c042f62fSJeremy L Thompson                      fieldname);
165c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1668b067b84SJed Brown   if (!v)
167c042f62fSJeremy L Thompson     // LCOV_EXCL_START
168c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.",
169c042f62fSJeremy L Thompson                      fieldname);
170c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
17152d6035fSJeremy L Thompson 
172d7b241e6Sjeremylt   CeedInt numelements;
173d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
1742cb0afc5Sjeremylt   if (op->hasrestriction && op->numelements != numelements)
175c042f62fSJeremy L Thompson     // LCOV_EXCL_START
176d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
1771d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
1781d102b48SJeremy L Thompson                      "%d elements", numelements, op->numelements);
179c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
180d7b241e6Sjeremylt   op->numelements = numelements;
1812cb0afc5Sjeremylt   op->hasrestriction = true; // Restriction set, but numelements may be 0
182d7b241e6Sjeremylt 
183783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
184d7b241e6Sjeremylt     CeedInt numqpoints;
185d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
186d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
187c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1881d102b48SJeremy L Thompson       return CeedError(op->ceed, 1, "Basis with %d quadrature points "
1891d102b48SJeremy L Thompson                        "incompatible with prior %d points", numqpoints,
1901d102b48SJeremy L Thompson                        op->numqpoints);
191c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
192d7b241e6Sjeremylt     op->numqpoints = numqpoints;
193d7b241e6Sjeremylt   }
194d1bcdac9Sjeremylt   CeedOperatorField *ofield;
195d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
196fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) {
197d7b241e6Sjeremylt       ofield = &op->inputfields[i];
198d7b241e6Sjeremylt       goto found;
199d7b241e6Sjeremylt     }
200d7b241e6Sjeremylt   }
201d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
202fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) {
203d7b241e6Sjeremylt       ofield = &op->outputfields[i];
204d7b241e6Sjeremylt       goto found;
205d7b241e6Sjeremylt     }
206d7b241e6Sjeremylt   }
207c042f62fSJeremy L Thompson   // LCOV_EXCL_START
208d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
209d7b241e6Sjeremylt                    fieldname);
210c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
211d7b241e6Sjeremylt found:
212fe2413ffSjeremylt   ierr = CeedCalloc(1, ofield); CeedChk(ierr);
213fe2413ffSjeremylt   (*ofield)->Erestrict = r;
21471352a93Sjeremylt   r->refcount += 1;
215fe2413ffSjeremylt   (*ofield)->basis = b;
21671352a93Sjeremylt   if (b != CEED_BASIS_COLLOCATED)
21771352a93Sjeremylt     b->refcount += 1;
218fe2413ffSjeremylt   (*ofield)->vec = v;
21971352a93Sjeremylt   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE)
22071352a93Sjeremylt     v->refcount += 1;
221d7b241e6Sjeremylt   op->nfields += 1;
222d7b241e6Sjeremylt   return 0;
223d7b241e6Sjeremylt }
224d7b241e6Sjeremylt 
225d7b241e6Sjeremylt /**
22652d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
227288c0443SJeremy L Thompson 
22834138859Sjeremylt   @param[out] compositeop Composite CeedOperator
22934138859Sjeremylt   @param      subop       Sub-operator CeedOperator
23052d6035fSJeremy L Thompson 
23152d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
23252d6035fSJeremy L Thompson 
23352d6035fSJeremy L Thompson   @ref Basic
23452d6035fSJeremy L Thompson  */
235692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) {
23652d6035fSJeremy L Thompson   if (!compositeop->composite)
237c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2381d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite "
2391d102b48SJeremy L Thompson                      "operator");
240c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
24152d6035fSJeremy L Thompson 
24252d6035fSJeremy L Thompson   if (compositeop->numsub == CEED_COMPOSITE_MAX)
243c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2441d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators");
245c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
24652d6035fSJeremy L Thompson 
24752d6035fSJeremy L Thompson   compositeop->suboperators[compositeop->numsub] = subop;
24852d6035fSJeremy L Thompson   subop->refcount++;
24952d6035fSJeremy L Thompson   compositeop->numsub++;
25052d6035fSJeremy L Thompson   return 0;
25152d6035fSJeremy L Thompson }
25252d6035fSJeremy L Thompson 
25352d6035fSJeremy L Thompson /**
2545107b09fSJeremy L Thompson   @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced
2555107b09fSJeremy L Thompson            CeedOperator functionality
2565107b09fSJeremy L Thompson 
2575107b09fSJeremy L Thompson   @param op           CeedOperator to create fallback for
2585107b09fSJeremy L Thompson 
2595107b09fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2605107b09fSJeremy L Thompson 
2615107b09fSJeremy L Thompson   @ref Developer
2625107b09fSJeremy L Thompson **/
2635107b09fSJeremy L Thompson int CeedOperatorCreateFallback(CeedOperator op) {
2645107b09fSJeremy L Thompson   int ierr;
2655107b09fSJeremy L Thompson 
2665107b09fSJeremy L Thompson   // Fallback Ceed
2675107b09fSJeremy L Thompson   const char *resource, *fallbackresource;
2685107b09fSJeremy L Thompson   ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr);
2695107b09fSJeremy L Thompson   ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource);
2705107b09fSJeremy L Thompson   CeedChk(ierr);
2715107b09fSJeremy L Thompson   if (!strcmp(resource, fallbackresource))
2725107b09fSJeremy L Thompson     // LCOV_EXCL_START
2735107b09fSJeremy L Thompson     return CeedError(op->ceed, 1, "Backend %s cannot create an operator"
2745107b09fSJeremy L Thompson                      "fallback to resource %s", resource, fallbackresource);
2755107b09fSJeremy L Thompson   // LCOV_EXCL_STOP
2765107b09fSJeremy L Thompson 
2770ace9bf2Sjeremylt   // Fallback Ceed
2785107b09fSJeremy L Thompson   Ceed ceedref;
2790ace9bf2Sjeremylt   if (!op->ceed->opfallbackceed) {
2805107b09fSJeremy L Thompson     ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr);
2815107b09fSJeremy L Thompson     ceedref->opfallbackparent = op->ceed;
2825107b09fSJeremy L Thompson     op->ceed->opfallbackceed = ceedref;
2830ace9bf2Sjeremylt   }
2840ace9bf2Sjeremylt   ceedref = op->ceed->opfallbackceed;
2855107b09fSJeremy L Thompson 
2865107b09fSJeremy L Thompson   // Clone Op
2875107b09fSJeremy L Thompson   CeedOperator opref;
2885107b09fSJeremy L Thompson   ierr = CeedCalloc(1, &opref); CeedChk(ierr);
2895107b09fSJeremy L Thompson   memcpy(opref, op, sizeof(*opref)); CeedChk(ierr);
2905107b09fSJeremy L Thompson   opref->data = NULL;
2915107b09fSJeremy L Thompson   opref->setupdone = 0;
2925107b09fSJeremy L Thompson   opref->ceed = ceedref;
2935107b09fSJeremy L Thompson   ierr = ceedref->OperatorCreate(opref); CeedChk(ierr);
2945107b09fSJeremy L Thompson   op->opfallback = opref;
2955107b09fSJeremy L Thompson 
2965107b09fSJeremy L Thompson   // Clone QF
2975107b09fSJeremy L Thompson   CeedQFunction qfref;
2985107b09fSJeremy L Thompson   ierr = CeedCalloc(1, &qfref); CeedChk(ierr);
2995107b09fSJeremy L Thompson   memcpy(qfref, (op->qf), sizeof(*qfref)); CeedChk(ierr);
3005107b09fSJeremy L Thompson   qfref->data = NULL;
3015107b09fSJeremy L Thompson   qfref->ceed = ceedref;
3025107b09fSJeremy L Thompson   ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr);
3035107b09fSJeremy L Thompson   opref->qf = qfref;
3045107b09fSJeremy L Thompson   op->qffallback = qfref;
3055107b09fSJeremy L Thompson 
3065107b09fSJeremy L Thompson   return 0;
3075107b09fSJeremy L Thompson }
3085107b09fSJeremy L Thompson 
3095107b09fSJeremy L Thompson /**
310250756a7Sjeremylt   @brief Check if a CeedOperator is ready to be used.
311250756a7Sjeremylt 
312250756a7Sjeremylt   @param[in] ceed Ceed object for error handling
313250756a7Sjeremylt   @param[in] op   CeedOperator to check
314250756a7Sjeremylt 
315250756a7Sjeremylt   @return An error code: 0 - success, otherwise - failure
316250756a7Sjeremylt 
317250756a7Sjeremylt   @ref Basic
318250756a7Sjeremylt **/
319250756a7Sjeremylt static int CeedOperatorCheckReady(Ceed ceed, CeedOperator op) {
320250756a7Sjeremylt   CeedQFunction qf = op->qf;
321250756a7Sjeremylt 
322250756a7Sjeremylt   if (op->composite) {
323250756a7Sjeremylt     if (!op->numsub)
324250756a7Sjeremylt       // LCOV_EXCL_START
325250756a7Sjeremylt       return CeedError(ceed, 1, "No suboperators set");
326250756a7Sjeremylt     // LCOV_EXCL_STOP
327250756a7Sjeremylt   } else {
328250756a7Sjeremylt     if (op->nfields == 0)
329250756a7Sjeremylt       // LCOV_EXCL_START
330250756a7Sjeremylt       return CeedError(ceed, 1, "No operator fields set");
331250756a7Sjeremylt     // LCOV_EXCL_STOP
332250756a7Sjeremylt     if (op->nfields < qf->numinputfields + qf->numoutputfields)
333250756a7Sjeremylt       // LCOV_EXCL_START
334250756a7Sjeremylt       return CeedError(ceed, 1, "Not all operator fields set");
335250756a7Sjeremylt     // LCOV_EXCL_STOP
336250756a7Sjeremylt     if (!op->hasrestriction)
337250756a7Sjeremylt       // LCOV_EXCL_START
338250756a7Sjeremylt       return CeedError(ceed, 1,"At least one restriction required");
339250756a7Sjeremylt     // LCOV_EXCL_STOP
340250756a7Sjeremylt     if (op->numqpoints == 0)
341250756a7Sjeremylt       // LCOV_EXCL_START
342250756a7Sjeremylt       return CeedError(ceed, 1,"At least one non-collocated basis required");
343250756a7Sjeremylt     // LCOV_EXCL_STOP
344250756a7Sjeremylt   }
345250756a7Sjeremylt 
346250756a7Sjeremylt   return 0;
347250756a7Sjeremylt }
348250756a7Sjeremylt 
349250756a7Sjeremylt /**
3501d102b48SJeremy L Thompson   @brief Assemble a linear CeedQFunction associated with a CeedOperator
3511d102b48SJeremy L Thompson 
3521d102b48SJeremy L Thompson   This returns a CeedVector containing a matrix at each quadrature point
3531d102b48SJeremy L Thompson     providing the action of the CeedQFunction associated with the CeedOperator.
3541d102b48SJeremy L Thompson     The vector 'assembled' is of shape
3551d102b48SJeremy L Thompson       [num_elements, num_input_fields, num_output_fields, num_quad_points]
3561d102b48SJeremy L Thompson     and contains column-major matrices representing the action of the
3571d102b48SJeremy L Thompson     CeedQFunction for a corresponding quadrature point on an element. Inputs and
3581d102b48SJeremy L Thompson     outputs are in the order provided by the user when adding CeedOperator fields.
3591d102b48SJeremy L Thompson     For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and
3601d102b48SJeremy L Thompson     'v', provided in that order, would result in an assembled QFunction that
3611d102b48SJeremy L Thompson     consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting
3621d102b48SJeremy L Thompson     on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v].
3631d102b48SJeremy L Thompson 
3641d102b48SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
3651d102b48SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedQFunction at
3661d102b48SJeremy L Thompson                           quadrature points
3671d102b48SJeremy L Thompson   @param[out] rstr      CeedElemRestriction for CeedVector containing assembled
3681d102b48SJeremy L Thompson                           CeedQFunction
3691d102b48SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
3701d102b48SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
3711d102b48SJeremy L Thompson 
3721d102b48SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
3731d102b48SJeremy L Thompson 
374b7ec98d8SJeremy L Thompson   @ref Basic
3751d102b48SJeremy L Thompson **/
3761d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled,
3777f823360Sjeremylt                                         CeedElemRestriction *rstr,
3787f823360Sjeremylt                                         CeedRequest *request) {
3791d102b48SJeremy L Thompson   int ierr;
3801d102b48SJeremy L Thompson   Ceed ceed = op->ceed;
381250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
3821d102b48SJeremy L Thompson 
3837172caadSjeremylt   // Backend version
3845107b09fSJeremy L Thompson   if (op->AssembleLinearQFunction) {
3851d102b48SJeremy L Thompson     ierr = op->AssembleLinearQFunction(op, assembled, rstr, request);
3861d102b48SJeremy L Thompson     CeedChk(ierr);
3875107b09fSJeremy L Thompson   } else {
3885107b09fSJeremy L Thompson     // Fallback to reference Ceed
3895107b09fSJeremy L Thompson     if (!op->opfallback) {
3905107b09fSJeremy L Thompson       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
3915107b09fSJeremy L Thompson     }
3925107b09fSJeremy L Thompson     // Assemble
3935107b09fSJeremy L Thompson     ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled,
3945107b09fSJeremy L Thompson            rstr, request); CeedChk(ierr);
3955107b09fSJeremy L Thompson   }
396250756a7Sjeremylt 
3971d102b48SJeremy L Thompson   return 0;
3981d102b48SJeremy L Thompson }
3991d102b48SJeremy L Thompson 
4001d102b48SJeremy L Thompson /**
401b7ec98d8SJeremy L Thompson   @brief Assemble the diagonal of a square linear Operator
402b7ec98d8SJeremy L Thompson 
403b7ec98d8SJeremy L Thompson   This returns a CeedVector containing the diagonal of a linear CeedOperator.
404b7ec98d8SJeremy L Thompson 
405b7ec98d8SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
406b7ec98d8SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedOperator diagonal
407b7ec98d8SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
408b7ec98d8SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
409b7ec98d8SJeremy L Thompson 
410b7ec98d8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
411b7ec98d8SJeremy L Thompson 
412b7ec98d8SJeremy L Thompson   @ref Basic
413b7ec98d8SJeremy L Thompson **/
4147f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled,
4157f823360Sjeremylt                                        CeedRequest *request) {
416b7ec98d8SJeremy L Thompson   int ierr;
417b7ec98d8SJeremy L Thompson   Ceed ceed = op->ceed;
418250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
419b7ec98d8SJeremy L Thompson 
420b7ec98d8SJeremy L Thompson   // Use backend version, if available
421b7ec98d8SJeremy L Thompson   if (op->AssembleLinearDiagonal) {
422b7ec98d8SJeremy L Thompson     ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr);
4237172caadSjeremylt   } else {
4247172caadSjeremylt     // Fallback to reference Ceed
4257172caadSjeremylt     if (!op->opfallback) {
4267172caadSjeremylt       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
427b7ec98d8SJeremy L Thompson     }
4287172caadSjeremylt     // Assemble
4297172caadSjeremylt     ierr = op->opfallback->AssembleLinearDiagonal(op->opfallback, assembled,
4307172caadSjeremylt            request); CeedChk(ierr);
431b7ec98d8SJeremy L Thompson   }
432b7ec98d8SJeremy L Thompson 
433b7ec98d8SJeremy L Thompson   return 0;
434b7ec98d8SJeremy L Thompson }
435b7ec98d8SJeremy L Thompson 
436b7ec98d8SJeremy L Thompson /**
4373bd813ffSjeremylt   @brief Build a FDM based approximate inverse for each element for a
4383bd813ffSjeremylt            CeedOperator
4393bd813ffSjeremylt 
4403bd813ffSjeremylt   This returns a CeedOperator and CeedVector to apply a Fast Diagonalization
4413bd813ffSjeremylt     Method based approximate inverse. This function obtains the simultaneous
4423bd813ffSjeremylt     diagonalization for the 1D mass and Laplacian operators,
4433bd813ffSjeremylt       M = V^T V, K = V^T S V.
4443bd813ffSjeremylt     The assembled QFunction is used to modify the eigenvalues from simultaneous
4453bd813ffSjeremylt     diagonalization and obtain an approximate inverse of the form
4463bd813ffSjeremylt       V^T S^hat V. The CeedOperator must be linear and non-composite. The
4473bd813ffSjeremylt     associated CeedQFunction must therefore also be linear.
4483bd813ffSjeremylt 
4493bd813ffSjeremylt   @param op             CeedOperator to create element inverses
4503bd813ffSjeremylt   @param[out] fdminv    CeedOperator to apply the action of a FDM based inverse
4513bd813ffSjeremylt                           for each element
4523bd813ffSjeremylt   @param request        Address of CeedRequest for non-blocking completion, else
4533bd813ffSjeremylt                           CEED_REQUEST_IMMEDIATE
4543bd813ffSjeremylt 
4553bd813ffSjeremylt   @return An error code: 0 - success, otherwise - failure
4563bd813ffSjeremylt 
4573bd813ffSjeremylt   @ref Advanced
4583bd813ffSjeremylt **/
4593bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv,
4603bd813ffSjeremylt                                         CeedRequest *request) {
4613bd813ffSjeremylt   int ierr;
4623bd813ffSjeremylt   Ceed ceed = op->ceed;
463713f43c3Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
4643bd813ffSjeremylt 
465713f43c3Sjeremylt   // Use backend version, if available
466713f43c3Sjeremylt   if (op->CreateFDMElementInverse) {
467713f43c3Sjeremylt     ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr);
468713f43c3Sjeremylt   } else {
469713f43c3Sjeremylt     // Fallback to reference Ceed
470713f43c3Sjeremylt     if (!op->opfallback) {
471713f43c3Sjeremylt       ierr = CeedOperatorCreateFallback(op); CeedChk(ierr);
4723bd813ffSjeremylt     }
473713f43c3Sjeremylt     // Assemble
474713f43c3Sjeremylt     ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv,
4753bd813ffSjeremylt            request); CeedChk(ierr);
4763bd813ffSjeremylt   }
4773bd813ffSjeremylt 
4783bd813ffSjeremylt   return 0;
4793bd813ffSjeremylt }
4803bd813ffSjeremylt 
4813bd813ffSjeremylt 
4823bd813ffSjeremylt /**
4833bd813ffSjeremylt   @brief Apply CeedOperator to a vector
484d7b241e6Sjeremylt 
485d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
486d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
487d7b241e6Sjeremylt   CeedOperatorSetField().
488d7b241e6Sjeremylt 
489d7b241e6Sjeremylt   @param op        CeedOperator to apply
49034138859Sjeremylt   @param[in] in    CeedVector containing input state or CEED_VECTOR_NONE if
49134138859Sjeremylt                   there are no active inputs
492b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
49334138859Sjeremylt                      distinct from @a in) or CEED_VECTOR_NONE if there are no
49434138859Sjeremylt                      active outputs
495d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
496d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
497b11c1e72Sjeremylt 
498b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
499dfdf5a53Sjeremylt 
500dfdf5a53Sjeremylt   @ref Basic
501b11c1e72Sjeremylt **/
502692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
503692c2638Sjeremylt                       CeedRequest *request) {
504d7b241e6Sjeremylt   int ierr;
505d7b241e6Sjeremylt   Ceed ceed = op->ceed;
506250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
507d7b241e6Sjeremylt 
508250756a7Sjeremylt   if (op->numelements)  {
509250756a7Sjeremylt     // Standard Operator
510cae8b89aSjeremylt     if (op->Apply) {
511250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
512cae8b89aSjeremylt     } else {
513cae8b89aSjeremylt       // Zero all output vectors
514250756a7Sjeremylt       CeedQFunction qf = op->qf;
515cae8b89aSjeremylt       for (CeedInt i=0; i<qf->numoutputfields; i++) {
516cae8b89aSjeremylt         CeedVector vec = op->outputfields[i]->vec;
517cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
518cae8b89aSjeremylt           vec = out;
519cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
520cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
521cae8b89aSjeremylt         }
522cae8b89aSjeremylt       }
523250756a7Sjeremylt       // Apply
524250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
525250756a7Sjeremylt     }
526250756a7Sjeremylt   } else if (op->composite) {
527250756a7Sjeremylt     // Composite Operator
528250756a7Sjeremylt     if (op->ApplyComposite) {
529250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
530250756a7Sjeremylt     } else {
531250756a7Sjeremylt       CeedInt numsub;
532250756a7Sjeremylt       ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr);
533250756a7Sjeremylt       CeedOperator *suboperators;
534250756a7Sjeremylt       ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr);
535250756a7Sjeremylt 
536250756a7Sjeremylt       // Zero all output vectors
537250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
538cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
539cae8b89aSjeremylt       }
540250756a7Sjeremylt       for (CeedInt i=0; i<numsub; i++) {
541250756a7Sjeremylt         for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) {
542250756a7Sjeremylt           CeedVector vec = suboperators[i]->outputfields[j]->vec;
543250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
544250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
545250756a7Sjeremylt           }
546250756a7Sjeremylt         }
547250756a7Sjeremylt       }
548250756a7Sjeremylt       // Apply
549250756a7Sjeremylt       for (CeedInt i=0; i<op->numsub; i++) {
550250756a7Sjeremylt         ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request);
551cae8b89aSjeremylt         CeedChk(ierr);
552cae8b89aSjeremylt       }
553cae8b89aSjeremylt     }
554250756a7Sjeremylt   }
555250756a7Sjeremylt 
556cae8b89aSjeremylt   return 0;
557cae8b89aSjeremylt }
558cae8b89aSjeremylt 
559cae8b89aSjeremylt /**
560cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
561cae8b89aSjeremylt 
562cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
563cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
564cae8b89aSjeremylt   CeedOperatorSetField().
565cae8b89aSjeremylt 
566cae8b89aSjeremylt   @param op        CeedOperator to apply
567cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
568cae8b89aSjeremylt                      active inputs
569cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
570cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
571cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
572cae8b89aSjeremylt                      CEED_REQUEST_IMMEDIATE
573cae8b89aSjeremylt 
574cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
575cae8b89aSjeremylt 
576cae8b89aSjeremylt   @ref Basic
577cae8b89aSjeremylt **/
578cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
579cae8b89aSjeremylt                          CeedRequest *request) {
580cae8b89aSjeremylt   int ierr;
581cae8b89aSjeremylt   Ceed ceed = op->ceed;
582250756a7Sjeremylt   ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr);
583cae8b89aSjeremylt 
584250756a7Sjeremylt   if (op->numelements)  {
585250756a7Sjeremylt     // Standard Operator
586250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
587250756a7Sjeremylt   } else if (op->composite) {
588250756a7Sjeremylt     // Composite Operator
589250756a7Sjeremylt     if (op->ApplyAddComposite) {
590250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
591cae8b89aSjeremylt     } else {
592250756a7Sjeremylt       CeedInt numsub;
593250756a7Sjeremylt       ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr);
594250756a7Sjeremylt       CeedOperator *suboperators;
595250756a7Sjeremylt       ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr);
596250756a7Sjeremylt 
597250756a7Sjeremylt       for (CeedInt i=0; i<numsub; i++) {
598250756a7Sjeremylt         ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request);
599cae8b89aSjeremylt         CeedChk(ierr);
6001d7d2407SJeremy L Thompson       }
601250756a7Sjeremylt     }
602250756a7Sjeremylt   }
603250756a7Sjeremylt 
604d7b241e6Sjeremylt   return 0;
605d7b241e6Sjeremylt }
606d7b241e6Sjeremylt 
607d7b241e6Sjeremylt /**
6084ce2993fSjeremylt   @brief Get the Ceed associated with a CeedOperator
6094ce2993fSjeremylt 
6104ce2993fSjeremylt   @param op              CeedOperator
6114ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
6124ce2993fSjeremylt 
6134ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6144ce2993fSjeremylt 
61523617272Sjeremylt   @ref Advanced
6164ce2993fSjeremylt **/
6174ce2993fSjeremylt 
6184ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
6194ce2993fSjeremylt   *ceed = op->ceed;
6204ce2993fSjeremylt   return 0;
6214ce2993fSjeremylt }
6224ce2993fSjeremylt 
6234ce2993fSjeremylt /**
6244ce2993fSjeremylt   @brief Get the number of elements associated with a CeedOperator
6254ce2993fSjeremylt 
6264ce2993fSjeremylt   @param op              CeedOperator
6274ce2993fSjeremylt   @param[out] numelem    Variable to store number of elements
6284ce2993fSjeremylt 
6294ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6304ce2993fSjeremylt 
63123617272Sjeremylt   @ref Advanced
6324ce2993fSjeremylt **/
6334ce2993fSjeremylt 
6344ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
63552d6035fSJeremy L Thompson   if (op->composite)
636c042f62fSJeremy L Thompson     // LCOV_EXCL_START
63752d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
638c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
63952d6035fSJeremy L Thompson 
6404ce2993fSjeremylt   *numelem = op->numelements;
6414ce2993fSjeremylt   return 0;
6424ce2993fSjeremylt }
6434ce2993fSjeremylt 
6444ce2993fSjeremylt /**
6454ce2993fSjeremylt   @brief Get the number of quadrature points associated with a CeedOperator
6464ce2993fSjeremylt 
6474ce2993fSjeremylt   @param op              CeedOperator
6484ce2993fSjeremylt   @param[out] numqpts    Variable to store vector number of quadrature points
6494ce2993fSjeremylt 
6504ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6514ce2993fSjeremylt 
65223617272Sjeremylt   @ref Advanced
6534ce2993fSjeremylt **/
6544ce2993fSjeremylt 
6554ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
65652d6035fSJeremy L Thompson   if (op->composite)
657c042f62fSJeremy L Thompson     // LCOV_EXCL_START
65852d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
659c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
66052d6035fSJeremy L Thompson 
6614ce2993fSjeremylt   *numqpts = op->numqpoints;
6624ce2993fSjeremylt   return 0;
6634ce2993fSjeremylt }
6644ce2993fSjeremylt 
6654ce2993fSjeremylt /**
6664ce2993fSjeremylt   @brief Get the number of arguments associated with a CeedOperator
6674ce2993fSjeremylt 
6684ce2993fSjeremylt   @param op              CeedOperator
6694ce2993fSjeremylt   @param[out] numargs    Variable to store vector number of arguments
6704ce2993fSjeremylt 
6714ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6724ce2993fSjeremylt 
67323617272Sjeremylt   @ref Advanced
6744ce2993fSjeremylt **/
6754ce2993fSjeremylt 
6764ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
67752d6035fSJeremy L Thompson   if (op->composite)
678c042f62fSJeremy L Thompson     // LCOV_EXCL_START
67952d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operators");
680c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
681c042f62fSJeremy L Thompson 
6824ce2993fSjeremylt   *numargs = op->nfields;
6834ce2993fSjeremylt   return 0;
6844ce2993fSjeremylt }
6854ce2993fSjeremylt 
6864ce2993fSjeremylt /**
6874ce2993fSjeremylt   @brief Get the setup status of a CeedOperator
6884ce2993fSjeremylt 
6894ce2993fSjeremylt   @param op             CeedOperator
690288c0443SJeremy L Thompson   @param[out] setupdone Variable to store setup status
6914ce2993fSjeremylt 
6924ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6934ce2993fSjeremylt 
69423617272Sjeremylt   @ref Advanced
6954ce2993fSjeremylt **/
6964ce2993fSjeremylt 
6974ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
6984ce2993fSjeremylt   *setupdone = op->setupdone;
6994ce2993fSjeremylt   return 0;
7004ce2993fSjeremylt }
7014ce2993fSjeremylt 
7024ce2993fSjeremylt /**
7034ce2993fSjeremylt   @brief Get the QFunction associated with a CeedOperator
7044ce2993fSjeremylt 
7054ce2993fSjeremylt   @param op              CeedOperator
7068c91a0c9SJeremy L Thompson   @param[out] qf         Variable to store QFunction
7074ce2993fSjeremylt 
7084ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7094ce2993fSjeremylt 
71023617272Sjeremylt   @ref Advanced
7114ce2993fSjeremylt **/
7124ce2993fSjeremylt 
7134ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
71452d6035fSJeremy L Thompson   if (op->composite)
715c042f62fSJeremy L Thompson     // LCOV_EXCL_START
71652d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
717c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
71852d6035fSJeremy L Thompson 
7194ce2993fSjeremylt   *qf = op->qf;
7204ce2993fSjeremylt   return 0;
7214ce2993fSjeremylt }
7224ce2993fSjeremylt 
7234ce2993fSjeremylt /**
72452d6035fSJeremy L Thompson   @brief Get the number of suboperators associated with a CeedOperator
72552d6035fSJeremy L Thompson 
72652d6035fSJeremy L Thompson   @param op              CeedOperator
72752d6035fSJeremy L Thompson   @param[out] numsub     Variable to store number of suboperators
72852d6035fSJeremy L Thompson 
72952d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
73052d6035fSJeremy L Thompson 
73152d6035fSJeremy L Thompson   @ref Advanced
73252d6035fSJeremy L Thompson **/
73352d6035fSJeremy L Thompson 
73452d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) {
735c042f62fSJeremy L Thompson   if (!op->composite)
736c042f62fSJeremy L Thompson     // LCOV_EXCL_START
737c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
738c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
73952d6035fSJeremy L Thompson 
74052d6035fSJeremy L Thompson   *numsub = op->numsub;
74152d6035fSJeremy L Thompson   return 0;
74252d6035fSJeremy L Thompson }
74352d6035fSJeremy L Thompson 
74452d6035fSJeremy L Thompson /**
74552d6035fSJeremy L Thompson   @brief Get the list of suboperators associated with a CeedOperator
74652d6035fSJeremy L Thompson 
74752d6035fSJeremy L Thompson   @param op                CeedOperator
74852d6035fSJeremy L Thompson   @param[out] suboperators Variable to store list of suboperators
74952d6035fSJeremy L Thompson 
75052d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
75152d6035fSJeremy L Thompson 
75252d6035fSJeremy L Thompson   @ref Advanced
75352d6035fSJeremy L Thompson **/
75452d6035fSJeremy L Thompson 
75552d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) {
756c042f62fSJeremy L Thompson   if (!op->composite)
757c042f62fSJeremy L Thompson     // LCOV_EXCL_START
758c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
759c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
76052d6035fSJeremy L Thompson 
76152d6035fSJeremy L Thompson   *suboperators = op->suboperators;
76252d6035fSJeremy L Thompson   return 0;
76352d6035fSJeremy L Thompson }
76452d6035fSJeremy L Thompson 
76552d6035fSJeremy L Thompson /**
766fe2413ffSjeremylt   @brief Set the backend data of a CeedOperator
767fe2413ffSjeremylt 
768fe2413ffSjeremylt   @param[out] op         CeedOperator
769fe2413ffSjeremylt   @param data            Data to set
770fe2413ffSjeremylt 
771fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
772fe2413ffSjeremylt 
773fe2413ffSjeremylt   @ref Advanced
774fe2413ffSjeremylt **/
775fe2413ffSjeremylt 
776fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void **data) {
777fe2413ffSjeremylt   op->data = *data;
778fe2413ffSjeremylt   return 0;
779fe2413ffSjeremylt }
780fe2413ffSjeremylt 
781fe2413ffSjeremylt /**
7824ce2993fSjeremylt   @brief Get the backend data of a CeedOperator
7834ce2993fSjeremylt 
7844ce2993fSjeremylt   @param op              CeedOperator
7854ce2993fSjeremylt   @param[out] data       Variable to store data
7864ce2993fSjeremylt 
7874ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7884ce2993fSjeremylt 
78923617272Sjeremylt   @ref Advanced
7904ce2993fSjeremylt **/
7914ce2993fSjeremylt 
7924ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void **data) {
7934ce2993fSjeremylt   *data = op->data;
7944ce2993fSjeremylt   return 0;
7954ce2993fSjeremylt }
7964ce2993fSjeremylt 
7974ce2993fSjeremylt /**
7984ce2993fSjeremylt   @brief Set the setup flag of a CeedOperator to True
7994ce2993fSjeremylt 
8004ce2993fSjeremylt   @param op              CeedOperator
8014ce2993fSjeremylt 
8024ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
8034ce2993fSjeremylt 
80423617272Sjeremylt   @ref Advanced
8054ce2993fSjeremylt **/
8064ce2993fSjeremylt 
8074ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) {
8084ce2993fSjeremylt   op->setupdone = 1;
8094ce2993fSjeremylt   return 0;
8104ce2993fSjeremylt }
8114ce2993fSjeremylt 
8124ce2993fSjeremylt /**
8132ebaca42Sjeremylt   @brief View a field of a CeedOperator
8142ebaca42Sjeremylt 
8152ebaca42Sjeremylt   @param[in] field       Operator field to view
8162ebaca42Sjeremylt   @param[in] fieldnumber Number of field being viewed
8172ebaca42Sjeremylt   @param[in] stream      Stream to view to, e.g., stdout
8182ebaca42Sjeremylt 
8192ebaca42Sjeremylt   @return An error code: 0 - success, otherwise - failure
8202ebaca42Sjeremylt 
8212ebaca42Sjeremylt   @ref Utility
8222ebaca42Sjeremylt **/
8232ebaca42Sjeremylt static int CeedOperatorFieldView(CeedOperatorField field,
8242ebaca42Sjeremylt                                  CeedQFunctionField qffield,
8252da88da5Sjeremylt                                  CeedInt fieldnumber, bool sub, bool in,
8262da88da5Sjeremylt                                  FILE *stream) {
8272ebaca42Sjeremylt   const char *pre = sub ? "  " : "";
8282da88da5Sjeremylt   const char *inout = in ? "Input" : "Output";
8292ebaca42Sjeremylt 
8302da88da5Sjeremylt   fprintf(stream, "%s    %s Field [%d]:\n"
831*a8d32208Sjeremylt           "%s      Name: \"%s\"\n",
832*a8d32208Sjeremylt           pre, inout, fieldnumber, pre, qffield->fieldname);
8332ebaca42Sjeremylt 
8342ebaca42Sjeremylt   if (field->basis == CEED_BASIS_COLLOCATED)
8352ebaca42Sjeremylt     fprintf(stream, "%s      Collocated basis\n", pre);
8362ebaca42Sjeremylt 
8372ebaca42Sjeremylt   if (field->vec == CEED_VECTOR_ACTIVE)
8382ebaca42Sjeremylt     fprintf(stream, "%s      Active vector\n", pre);
8392ebaca42Sjeremylt   else if (field->vec == CEED_VECTOR_NONE)
8402ebaca42Sjeremylt     fprintf(stream, "%s      No vector\n", pre);
8412ebaca42Sjeremylt 
8422ebaca42Sjeremylt   return 0;
8432ebaca42Sjeremylt }
8442ebaca42Sjeremylt 
8452ebaca42Sjeremylt /**
8462ebaca42Sjeremylt   @brief View a single CeedOperator
8472ebaca42Sjeremylt 
8482ebaca42Sjeremylt   @param[in] op     CeedOperator to view
84977645d7bSjeremylt   @param[in] sub    Boolean flag for sub-operator
8502ebaca42Sjeremylt   @param[in] stream Stream to write; typically stdout/stderr or a file
8512ebaca42Sjeremylt 
8522ebaca42Sjeremylt   @return Error code: 0 - success, otherwise - failure
8532ebaca42Sjeremylt 
8542ebaca42Sjeremylt   @ref Utility
8552ebaca42Sjeremylt **/
8562ebaca42Sjeremylt int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
8572ebaca42Sjeremylt   int ierr;
8582ebaca42Sjeremylt   const char *pre = sub ? "  " : "";
8592ebaca42Sjeremylt 
8602ebaca42Sjeremylt   CeedInt totalfields;
8612ebaca42Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr);
8622da88da5Sjeremylt 
8632ebaca42Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : "");
8642ebaca42Sjeremylt 
8652da88da5Sjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->numinputfields,
8662ebaca42Sjeremylt           op->qf->numinputfields>1 ? "s" : "");
8672ebaca42Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
8682ebaca42Sjeremylt     ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i],
8692da88da5Sjeremylt                                  i, sub, 1, stream); CeedChk(ierr);
8702ebaca42Sjeremylt   }
8712ebaca42Sjeremylt 
8722da88da5Sjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->numoutputfields,
8732ebaca42Sjeremylt           op->qf->numoutputfields>1 ? "s" : "");
8742ebaca42Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
8752ebaca42Sjeremylt     ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i],
8762da88da5Sjeremylt                                  i, sub, 0, stream); CeedChk(ierr);
8772ebaca42Sjeremylt   }
8782ebaca42Sjeremylt 
8792ebaca42Sjeremylt   return 0;
8802ebaca42Sjeremylt }
8812ebaca42Sjeremylt 
8822ebaca42Sjeremylt /**
8832ebaca42Sjeremylt   @brief View a CeedOperator
8842ebaca42Sjeremylt 
8852ebaca42Sjeremylt   @param[in] op     CeedOperator to view
8862ebaca42Sjeremylt   @param[in] stream Stream to write; typically stdout/stderr or a file
8872ebaca42Sjeremylt 
8882ebaca42Sjeremylt   @return Error code: 0 - success, otherwise - failure
8892ebaca42Sjeremylt 
8902ebaca42Sjeremylt   @ref Utility
8912ebaca42Sjeremylt **/
8922ebaca42Sjeremylt int CeedOperatorView(CeedOperator op, FILE *stream) {
8932ebaca42Sjeremylt   int ierr;
8942ebaca42Sjeremylt 
8952ebaca42Sjeremylt   if (op->composite) {
8962ebaca42Sjeremylt     fprintf(stream, "Composite CeedOperator\n");
8972ebaca42Sjeremylt 
8982ebaca42Sjeremylt     for (CeedInt i=0; i<op->numsub; i++) {
8992da88da5Sjeremylt       fprintf(stream, "  SubOperator [%d]:\n", i);
9002ebaca42Sjeremylt       ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream);
9012ebaca42Sjeremylt       CeedChk(ierr);
9022ebaca42Sjeremylt     }
9032ebaca42Sjeremylt   } else {
9042ebaca42Sjeremylt     fprintf(stream, "CeedOperator\n");
9052ebaca42Sjeremylt     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
9062ebaca42Sjeremylt   }
9072ebaca42Sjeremylt 
9082ebaca42Sjeremylt   return 0;
9092ebaca42Sjeremylt }
9102ebaca42Sjeremylt 
9112ebaca42Sjeremylt /**
912d1bcdac9Sjeremylt   @brief Get the CeedOperatorFields of a CeedOperator
913d1bcdac9Sjeremylt 
914d1bcdac9Sjeremylt   @param op                 CeedOperator
915d1bcdac9Sjeremylt   @param[out] inputfields   Variable to store inputfields
916d1bcdac9Sjeremylt   @param[out] outputfields  Variable to store outputfields
917d1bcdac9Sjeremylt 
918d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
919d1bcdac9Sjeremylt 
920d1bcdac9Sjeremylt   @ref Advanced
921d1bcdac9Sjeremylt **/
922d1bcdac9Sjeremylt 
923692c2638Sjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields,
924d1bcdac9Sjeremylt                           CeedOperatorField **outputfields) {
92552d6035fSJeremy L Thompson   if (op->composite)
926c042f62fSJeremy L Thompson     // LCOV_EXCL_START
92752d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
928c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
92952d6035fSJeremy L Thompson 
930d1bcdac9Sjeremylt   if (inputfields) *inputfields = op->inputfields;
931d1bcdac9Sjeremylt   if (outputfields) *outputfields = op->outputfields;
932d1bcdac9Sjeremylt   return 0;
933d1bcdac9Sjeremylt }
934d1bcdac9Sjeremylt 
935d1bcdac9Sjeremylt /**
936d1bcdac9Sjeremylt   @brief Get the CeedElemRestriction of a CeedOperatorField
937d1bcdac9Sjeremylt 
938d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
939d1bcdac9Sjeremylt   @param[out] rstr       Variable to store CeedElemRestriction
940d1bcdac9Sjeremylt 
941d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
942d1bcdac9Sjeremylt 
943d1bcdac9Sjeremylt   @ref Advanced
944d1bcdac9Sjeremylt **/
945d1bcdac9Sjeremylt 
946d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
947d1bcdac9Sjeremylt                                         CeedElemRestriction *rstr) {
948fe2413ffSjeremylt   *rstr = opfield->Erestrict;
949d1bcdac9Sjeremylt   return 0;
950d1bcdac9Sjeremylt }
951d1bcdac9Sjeremylt 
952d1bcdac9Sjeremylt /**
953d1bcdac9Sjeremylt   @brief Get the CeedBasis of a CeedOperatorField
954d1bcdac9Sjeremylt 
955d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
956d1bcdac9Sjeremylt   @param[out] basis      Variable to store CeedBasis
957d1bcdac9Sjeremylt 
958d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
959d1bcdac9Sjeremylt 
960d1bcdac9Sjeremylt   @ref Advanced
961d1bcdac9Sjeremylt **/
962d1bcdac9Sjeremylt 
963692c2638Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) {
964fe2413ffSjeremylt   *basis = opfield->basis;
965d1bcdac9Sjeremylt   return 0;
966d1bcdac9Sjeremylt }
967d1bcdac9Sjeremylt 
968d1bcdac9Sjeremylt /**
969d1bcdac9Sjeremylt   @brief Get the CeedVector of a CeedOperatorField
970d1bcdac9Sjeremylt 
971d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
972d1bcdac9Sjeremylt   @param[out] vec        Variable to store CeedVector
973d1bcdac9Sjeremylt 
974d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
975d1bcdac9Sjeremylt 
976d1bcdac9Sjeremylt   @ref Advanced
977d1bcdac9Sjeremylt **/
978d1bcdac9Sjeremylt 
979692c2638Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) {
980fe2413ffSjeremylt   *vec = opfield->vec;
981d1bcdac9Sjeremylt   return 0;
982d1bcdac9Sjeremylt }
983d1bcdac9Sjeremylt 
984d1bcdac9Sjeremylt /**
985b11c1e72Sjeremylt   @brief Destroy a CeedOperator
986d7b241e6Sjeremylt 
987d7b241e6Sjeremylt   @param op CeedOperator to destroy
988b11c1e72Sjeremylt 
989b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
990dfdf5a53Sjeremylt 
991dfdf5a53Sjeremylt   @ref Basic
992b11c1e72Sjeremylt **/
993d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
994d7b241e6Sjeremylt   int ierr;
995d7b241e6Sjeremylt 
996d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
997d7b241e6Sjeremylt   if ((*op)->Destroy) {
998d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
999d7b241e6Sjeremylt   }
1000fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1001fe2413ffSjeremylt   // Free fields
10021d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
100352d6035fSJeremy L Thompson     if ((*op)->inputfields[i]) {
100471352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict);
100571352a93Sjeremylt       CeedChk(ierr);
100671352a93Sjeremylt       if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) {
100771352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr);
100871352a93Sjeremylt       }
100971352a93Sjeremylt       if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE &&
101071352a93Sjeremylt           (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) {
101171352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr);
101271352a93Sjeremylt       }
1013fe2413ffSjeremylt       ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr);
1014fe2413ffSjeremylt     }
10151d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
1016d0eb30a5Sjeremylt     if ((*op)->outputfields[i]) {
101771352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict);
101871352a93Sjeremylt       CeedChk(ierr);
101971352a93Sjeremylt       if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) {
102071352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr);
102171352a93Sjeremylt       }
102271352a93Sjeremylt       if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE &&
102371352a93Sjeremylt           (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) {
102471352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr);
102571352a93Sjeremylt       }
1026fe2413ffSjeremylt       ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr);
1027fe2413ffSjeremylt     }
102852d6035fSJeremy L Thompson   // Destroy suboperators
10291d102b48SJeremy L Thompson   for (int i=0; i<(*op)->numsub; i++)
103052d6035fSJeremy L Thompson     if ((*op)->suboperators[i]) {
103152d6035fSJeremy L Thompson       ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr);
103252d6035fSJeremy L Thompson     }
1033d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1034d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1035d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1036fe2413ffSjeremylt 
10375107b09fSJeremy L Thompson   // Destroy fallback
10385107b09fSJeremy L Thompson   if ((*op)->opfallback) {
10395107b09fSJeremy L Thompson     ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr);
10405107b09fSJeremy L Thompson     ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr);
10415107b09fSJeremy L Thompson     ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr);
10425107b09fSJeremy L Thompson     ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr);
10435107b09fSJeremy L Thompson   }
10445107b09fSJeremy L Thompson 
1045fe2413ffSjeremylt   ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr);
1046fe2413ffSjeremylt   ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr);
104752d6035fSJeremy L Thompson   ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr);
1048d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1049d7b241e6Sjeremylt   return 0;
1050d7b241e6Sjeremylt }
1051d7b241e6Sjeremylt 
1052d7b241e6Sjeremylt /// @}
1053