xref: /libCEED/interface/ceed-operator.c (revision b7ec98d8959851803d838dd4fd11ad111e0096dd)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt #include <string.h>
20d7b241e6Sjeremylt 
21dfdf5a53Sjeremylt /// @file
22dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces
23dfdf5a53Sjeremylt ///
24dfdf5a53Sjeremylt /// @addtogroup CeedOperator
25dfdf5a53Sjeremylt ///   @{
26d7b241e6Sjeremylt 
27d7b241e6Sjeremylt /**
280219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
290219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
300219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
31d7b241e6Sjeremylt 
32b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
33d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
34d7b241e6Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
35d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
36d7b241e6Sjeremylt                    of @a qf (or NULL)
37b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
38b11c1e72Sjeremylt                      CeedOperator will be stored
39b11c1e72Sjeremylt 
40b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
41dfdf5a53Sjeremylt 
42dfdf5a53Sjeremylt   @ref Basic
43d7b241e6Sjeremylt  */
44d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
45d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
46d7b241e6Sjeremylt   int ierr;
47d7b241e6Sjeremylt 
485fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
495fe0d4faSjeremylt     Ceed delegate;
50aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
515fe0d4faSjeremylt 
525fe0d4faSjeremylt     if (!delegate)
53c042f62fSJeremy L Thompson       // LCOV_EXCL_START
545fe0d4faSjeremylt       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
55c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
565fe0d4faSjeremylt 
575fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
585fe0d4faSjeremylt     return 0;
595fe0d4faSjeremylt   }
605fe0d4faSjeremylt 
61d7b241e6Sjeremylt   ierr = CeedCalloc(1,op); CeedChk(ierr);
62d7b241e6Sjeremylt   (*op)->ceed = ceed;
63d7b241e6Sjeremylt   ceed->refcount++;
64d7b241e6Sjeremylt   (*op)->refcount = 1;
65d7b241e6Sjeremylt   (*op)->qf = qf;
66d7b241e6Sjeremylt   qf->refcount++;
67d7b241e6Sjeremylt   (*op)->dqf = dqf;
68d7b241e6Sjeremylt   if (dqf) dqf->refcount++;
69d7b241e6Sjeremylt   (*op)->dqfT = dqfT;
70d7b241e6Sjeremylt   if (dqfT) dqfT->refcount++;
71fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr);
72fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr);
73d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
74d7b241e6Sjeremylt   return 0;
75d7b241e6Sjeremylt }
76d7b241e6Sjeremylt 
77d7b241e6Sjeremylt /**
7852d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
7952d6035fSJeremy L Thompson 
8052d6035fSJeremy L Thompson   @param ceed    A Ceed object where the CeedOperator will be created
8152d6035fSJeremy L Thompson   @param[out] op Address of the variable where the newly created
8252d6035fSJeremy L Thompson                      Composite CeedOperator will be stored
8352d6035fSJeremy L Thompson 
8452d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8552d6035fSJeremy L Thompson 
8652d6035fSJeremy L Thompson   @ref Basic
8752d6035fSJeremy L Thompson  */
8852d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
8952d6035fSJeremy L Thompson   int ierr;
9052d6035fSJeremy L Thompson 
9152d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
9252d6035fSJeremy L Thompson     Ceed delegate;
93aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
9452d6035fSJeremy L Thompson 
9552d6035fSJeremy L Thompson     if (!delegate)
96c042f62fSJeremy L Thompson       // LCOV_EXCL_START
971d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
981d102b48SJeremy L Thompson                        "CompositeOperatorCreate");
99c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
10052d6035fSJeremy L Thompson 
10152d6035fSJeremy L Thompson     ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
10252d6035fSJeremy L Thompson     return 0;
10352d6035fSJeremy L Thompson   }
10452d6035fSJeremy L Thompson 
10552d6035fSJeremy L Thompson   ierr = CeedCalloc(1,op); CeedChk(ierr);
10652d6035fSJeremy L Thompson   (*op)->ceed = ceed;
10752d6035fSJeremy L Thompson   ceed->refcount++;
10852d6035fSJeremy L Thompson   (*op)->composite = true;
10952d6035fSJeremy L Thompson   ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr);
11052d6035fSJeremy L Thompson   ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
11152d6035fSJeremy L Thompson   return 0;
11252d6035fSJeremy L Thompson }
11352d6035fSJeremy L Thompson 
11452d6035fSJeremy L Thompson /**
115b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
116d7b241e6Sjeremylt 
117d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
118d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
119d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
120d7b241e6Sjeremylt 
121d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
122d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
123d7b241e6Sjeremylt   input and at most one active output.
124d7b241e6Sjeremylt 
1258c91a0c9SJeremy L Thompson   @param op         CeedOperator on which to provide the field
1268795c945Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by
1278795c945Sjeremylt                       CeedQFunction)
128b11c1e72Sjeremylt   @param r          CeedElemRestriction
129b0e29e78Sjeremylt   @param lmode      CeedTransposeMode which specifies the ordering of the
130b0e29e78Sjeremylt                       components of the l-vector used by this CeedOperatorField,
131b0e29e78Sjeremylt                       CEED_NOTRANSPOSE indicates the component is the
132b0e29e78Sjeremylt                       outermost index and CEED_TRANSPOSE indicates the component
133b0e29e78Sjeremylt                       is the innermost index in ordering of the l-vector
134783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
135b11c1e72Sjeremylt                       if collocated with quadrature points
136b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
137b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
1388c91a0c9SJeremy L Thompson                       CEED_EVAL_WEIGHT in the QFunction
139b11c1e72Sjeremylt 
140b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
141dfdf5a53Sjeremylt 
142dfdf5a53Sjeremylt   @ref Basic
143b11c1e72Sjeremylt **/
144d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
1454dccadb6Sjeremylt                          CeedElemRestriction r, CeedTransposeMode lmode,
1464dccadb6Sjeremylt                          CeedBasis b, CeedVector v) {
147d7b241e6Sjeremylt   int ierr;
14852d6035fSJeremy L Thompson   if (op->composite)
149c042f62fSJeremy L Thompson     // LCOV_EXCL_START
15052d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Cannot add field to composite operator.");
151c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1528b067b84SJed Brown   if (!r)
153c042f62fSJeremy L Thompson     // LCOV_EXCL_START
154c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1,
155c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
156c042f62fSJeremy L Thompson                      fieldname);
157c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1588b067b84SJed Brown   if (!b)
159c042f62fSJeremy L Thompson     // LCOV_EXCL_START
160c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.",
161c042f62fSJeremy L Thompson                      fieldname);
162c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
1638b067b84SJed Brown   if (!v)
164c042f62fSJeremy L Thompson     // LCOV_EXCL_START
165c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.",
166c042f62fSJeremy L Thompson                      fieldname);
167c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
16852d6035fSJeremy L Thompson 
169d7b241e6Sjeremylt   CeedInt numelements;
170d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
171d7b241e6Sjeremylt   if (op->numelements && op->numelements != numelements)
172c042f62fSJeremy L Thompson     // LCOV_EXCL_START
173d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
1741d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
1751d102b48SJeremy L Thompson                      "%d elements", numelements, op->numelements);
176c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
177d7b241e6Sjeremylt   op->numelements = numelements;
178d7b241e6Sjeremylt 
179783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
180d7b241e6Sjeremylt     CeedInt numqpoints;
181d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
182d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
183c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1841d102b48SJeremy L Thompson       return CeedError(op->ceed, 1, "Basis with %d quadrature points "
1851d102b48SJeremy L Thompson                        "incompatible with prior %d points", numqpoints,
1861d102b48SJeremy L Thompson                        op->numqpoints);
187c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
188d7b241e6Sjeremylt     op->numqpoints = numqpoints;
189d7b241e6Sjeremylt   }
190d1bcdac9Sjeremylt   CeedOperatorField *ofield;
191d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
192fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) {
193d7b241e6Sjeremylt       ofield = &op->inputfields[i];
194d7b241e6Sjeremylt       goto found;
195d7b241e6Sjeremylt     }
196d7b241e6Sjeremylt   }
197d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
198fe2413ffSjeremylt     if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) {
199d7b241e6Sjeremylt       ofield = &op->outputfields[i];
200d7b241e6Sjeremylt       goto found;
201d7b241e6Sjeremylt     }
202d7b241e6Sjeremylt   }
203c042f62fSJeremy L Thompson   // LCOV_EXCL_START
204d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
205d7b241e6Sjeremylt                    fieldname);
206c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
207d7b241e6Sjeremylt found:
208fe2413ffSjeremylt   ierr = CeedCalloc(1, ofield); CeedChk(ierr);
209fe2413ffSjeremylt   (*ofield)->Erestrict = r;
21071352a93Sjeremylt   r->refcount += 1;
211fe2413ffSjeremylt   (*ofield)->lmode = lmode;
212fe2413ffSjeremylt   (*ofield)->basis = b;
21371352a93Sjeremylt   if (b != CEED_BASIS_COLLOCATED)
21471352a93Sjeremylt     b->refcount += 1;
215fe2413ffSjeremylt   (*ofield)->vec = v;
21671352a93Sjeremylt   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE)
21771352a93Sjeremylt     v->refcount += 1;
218d7b241e6Sjeremylt   op->nfields += 1;
219d7b241e6Sjeremylt   return 0;
220d7b241e6Sjeremylt }
221d7b241e6Sjeremylt 
222d7b241e6Sjeremylt /**
22352d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
224288c0443SJeremy L Thompson 
225288c0443SJeremy L Thompson   @param[out] compositeop Address of the composite CeedOperator
226288c0443SJeremy L Thompson   @param      subop       Address of the sub-operator CeedOperator
22752d6035fSJeremy L Thompson 
22852d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22952d6035fSJeremy L Thompson 
23052d6035fSJeremy L Thompson   @ref Basic
23152d6035fSJeremy L Thompson  */
23252d6035fSJeremy L Thompson int CeedCompositeOperatorAddSub(CeedOperator compositeop,
23352d6035fSJeremy L Thompson                                 CeedOperator subop) {
23452d6035fSJeremy L Thompson   if (!compositeop->composite)
235c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2361d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite "
2371d102b48SJeremy L Thompson                      "operator");
238c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
23952d6035fSJeremy L Thompson 
24052d6035fSJeremy L Thompson   if (compositeop->numsub == CEED_COMPOSITE_MAX)
241c042f62fSJeremy L Thompson     // LCOV_EXCL_START
2421d102b48SJeremy L Thompson     return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators");
243c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
24452d6035fSJeremy L Thompson 
24552d6035fSJeremy L Thompson   compositeop->suboperators[compositeop->numsub] = subop;
24652d6035fSJeremy L Thompson   subop->refcount++;
24752d6035fSJeremy L Thompson   compositeop->numsub++;
24852d6035fSJeremy L Thompson   return 0;
24952d6035fSJeremy L Thompson }
25052d6035fSJeremy L Thompson 
25152d6035fSJeremy L Thompson /**
2521d102b48SJeremy L Thompson   @brief Assemble a linear CeedQFunction associated with a CeedOperator
2531d102b48SJeremy L Thompson 
2541d102b48SJeremy L Thompson   This returns a CeedVector containing a matrix at each quadrature point
2551d102b48SJeremy L Thompson     providing the action of the CeedQFunction associated with the CeedOperator.
2561d102b48SJeremy L Thompson     The vector 'assembled' is of shape
2571d102b48SJeremy L Thompson       [num_elements, num_input_fields, num_output_fields, num_quad_points]
2581d102b48SJeremy L Thompson     and contains column-major matrices representing the action of the
2591d102b48SJeremy L Thompson     CeedQFunction for a corresponding quadrature point on an element. Inputs and
2601d102b48SJeremy L Thompson     outputs are in the order provided by the user when adding CeedOperator fields.
2611d102b48SJeremy L Thompson     For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and
2621d102b48SJeremy L Thompson     'v', provided in that order, would result in an assembled QFunction that
2631d102b48SJeremy L Thompson     consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting
2641d102b48SJeremy L Thompson     on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v].
2651d102b48SJeremy L Thompson 
2661d102b48SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
2671d102b48SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedQFunction at
2681d102b48SJeremy L Thompson                           quadrature points
2691d102b48SJeremy L Thompson   @param[out] rstr      CeedElemRestriction for CeedVector containing assembled
2701d102b48SJeremy L Thompson                           CeedQFunction
2711d102b48SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
2721d102b48SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
2731d102b48SJeremy L Thompson 
2741d102b48SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2751d102b48SJeremy L Thompson 
276*b7ec98d8SJeremy L Thompson   @ref Basic
2771d102b48SJeremy L Thompson **/
2781d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled,
2791d102b48SJeremy L Thompson     CeedElemRestriction *rstr, CeedRequest *request) {
2801d102b48SJeremy L Thompson   int ierr;
2811d102b48SJeremy L Thompson   Ceed ceed = op->ceed;
2821d102b48SJeremy L Thompson   CeedQFunction qf = op->qf;
2831d102b48SJeremy L Thompson 
2841d102b48SJeremy L Thompson   if (op->composite) {
285138d4072Sjeremylt     // LCOV_EXCL_START
2861d102b48SJeremy L Thompson     return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator");
287138d4072Sjeremylt     // LCOV_EXCL_STOP
2881d102b48SJeremy L Thompson   } else {
2891d102b48SJeremy L Thompson     if (op->nfields == 0)
290138d4072Sjeremylt       // LCOV_EXCL_START
2911d102b48SJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
292138d4072Sjeremylt       // LCOV_EXCL_STOP
2931d102b48SJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
294138d4072Sjeremylt       // LCOV_EXCL_START
2951d102b48SJeremy L Thompson       return CeedError( ceed, 1, "Not all operator fields set");
296138d4072Sjeremylt     // LCOV_EXCL_STOP
2971d102b48SJeremy L Thompson     if (op->numelements == 0)
298138d4072Sjeremylt       // LCOV_EXCL_START
2991d102b48SJeremy L Thompson       return CeedError(ceed, 1, "At least one restriction required");
300138d4072Sjeremylt     // LCOV_EXCL_STOP
3011d102b48SJeremy L Thompson     if (op->numqpoints == 0)
302138d4072Sjeremylt       // LCOV_EXCL_START
3031d102b48SJeremy L Thompson       return CeedError(ceed, 1, "At least one non-collocated basis required");
304138d4072Sjeremylt     // LCOV_EXCL_STOP
3051d102b48SJeremy L Thompson   }
3061d102b48SJeremy L Thompson   ierr = op->AssembleLinearQFunction(op, assembled, rstr, request);
3071d102b48SJeremy L Thompson   CeedChk(ierr);
3081d102b48SJeremy L Thompson   return 0;
3091d102b48SJeremy L Thompson }
3101d102b48SJeremy L Thompson 
3111d102b48SJeremy L Thompson /**
312*b7ec98d8SJeremy L Thompson   @brief Assemble the diagonal of a square linear Operator
313*b7ec98d8SJeremy L Thompson 
314*b7ec98d8SJeremy L Thompson   This returns a CeedVector containing the diagonal of a linear CeedOperator.
315*b7ec98d8SJeremy L Thompson 
316*b7ec98d8SJeremy L Thompson   @param op             CeedOperator to assemble CeedQFunction
317*b7ec98d8SJeremy L Thompson   @param[out] assembled CeedVector to store assembled CeedOperator diagonal
318*b7ec98d8SJeremy L Thompson   @param request        Address of CeedRequest for non-blocking completion, else
319*b7ec98d8SJeremy L Thompson                           CEED_REQUEST_IMMEDIATE
320*b7ec98d8SJeremy L Thompson 
321*b7ec98d8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
322*b7ec98d8SJeremy L Thompson 
323*b7ec98d8SJeremy L Thompson   @ref Basic
324*b7ec98d8SJeremy L Thompson **/
325*b7ec98d8SJeremy L Thompson int CeedOperatorAssembleLinearDiagonal(CeedOperator op,
326*b7ec98d8SJeremy L Thompson     CeedVector *assembled, CeedRequest *request) {
327*b7ec98d8SJeremy L Thompson   int ierr;
328*b7ec98d8SJeremy L Thompson   Ceed ceed = op->ceed;
329*b7ec98d8SJeremy L Thompson   CeedQFunction qf = op->qf;
330*b7ec98d8SJeremy L Thompson 
331*b7ec98d8SJeremy L Thompson   if (op->composite) {
332*b7ec98d8SJeremy L Thompson     // LCOV_EXCL_START
333*b7ec98d8SJeremy L Thompson     return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator");
334*b7ec98d8SJeremy L Thompson   // LCOV_EXCL_STOP
335*b7ec98d8SJeremy L Thompson   } else {
336*b7ec98d8SJeremy L Thompson     if (op->nfields == 0)
337*b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
338*b7ec98d8SJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
339*b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
340*b7ec98d8SJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
341*b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
342*b7ec98d8SJeremy L Thompson       return CeedError( ceed, 1, "Not all operator fields set");
343*b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
344*b7ec98d8SJeremy L Thompson     if (op->numelements == 0)
345*b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
346*b7ec98d8SJeremy L Thompson       return CeedError(ceed, 1, "At least one restriction required");
347*b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
348*b7ec98d8SJeremy L Thompson     if (op->numqpoints == 0)
349*b7ec98d8SJeremy L Thompson       // LCOV_EXCL_START
350*b7ec98d8SJeremy L Thompson       return CeedError(ceed, 1, "At least one non-collocated basis required");
351*b7ec98d8SJeremy L Thompson     // LCOV_EXCL_STOP
352*b7ec98d8SJeremy L Thompson   }
353*b7ec98d8SJeremy L Thompson 
354*b7ec98d8SJeremy L Thompson   // Use backend version, if available
355*b7ec98d8SJeremy L Thompson   if (op->AssembleLinearDiagonal) {
356*b7ec98d8SJeremy L Thompson     ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr);
357*b7ec98d8SJeremy L Thompson     return 0;
358*b7ec98d8SJeremy L Thompson   }
359*b7ec98d8SJeremy L Thompson 
360*b7ec98d8SJeremy L Thompson   // Assemble QFunction
361*b7ec98d8SJeremy L Thompson   CeedVector assembledqf;
362*b7ec98d8SJeremy L Thompson   CeedElemRestriction rstr;
363*b7ec98d8SJeremy L Thompson   ierr = CeedOperatorAssembleLinearQFunction(op,  &assembledqf, &rstr, request);
364*b7ec98d8SJeremy L Thompson   CeedChk(ierr);
365*b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr);
366*b7ec98d8SJeremy L Thompson 
367*b7ec98d8SJeremy L Thompson   // Determine active input basis
368*b7ec98d8SJeremy L Thompson   CeedInt numemodein = 0, ncomp, dim;
369*b7ec98d8SJeremy L Thompson   CeedEvalMode *emodein = NULL;
370*b7ec98d8SJeremy L Thompson   CeedBasis basisin;
371*b7ec98d8SJeremy L Thompson   CeedElemRestriction rstrin;
372*b7ec98d8SJeremy L Thompson   for (CeedInt i=0; i<qf->numinputfields; i++)
373*b7ec98d8SJeremy L Thompson     if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) {
374*b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetBasis(op->inputfields[i], &basisin);
375*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
376*b7ec98d8SJeremy L Thompson       ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr);
377*b7ec98d8SJeremy L Thompson       ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr);
378*b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetElemRestriction(op->inputfields[i], &rstrin);
379*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
380*b7ec98d8SJeremy L Thompson       CeedEvalMode emode;
381*b7ec98d8SJeremy L Thompson       ierr = CeedQFunctionFieldGetEvalMode(qf->inputfields[i], &emode);
382*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
383*b7ec98d8SJeremy L Thompson       switch (emode) {
384*b7ec98d8SJeremy L Thompson       case CEED_EVAL_NONE:
385*b7ec98d8SJeremy L Thompson       case CEED_EVAL_INTERP:
386*b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr);
387*b7ec98d8SJeremy L Thompson         emodein[numemodein] = emode;
388*b7ec98d8SJeremy L Thompson         numemodein += 1;
389*b7ec98d8SJeremy L Thompson         break;
390*b7ec98d8SJeremy L Thompson       case CEED_EVAL_GRAD:
391*b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr);
392*b7ec98d8SJeremy L Thompson         for (CeedInt d=0; d<dim; d++)
393*b7ec98d8SJeremy L Thompson           emodein[numemodein+d] = emode;
394*b7ec98d8SJeremy L Thompson         numemodein += dim;
395*b7ec98d8SJeremy L Thompson         break;
396*b7ec98d8SJeremy L Thompson       case CEED_EVAL_WEIGHT:
397*b7ec98d8SJeremy L Thompson       case CEED_EVAL_DIV:
398*b7ec98d8SJeremy L Thompson       case CEED_EVAL_CURL:
399*b7ec98d8SJeremy L Thompson         break; // Caught by QF Assembly
400*b7ec98d8SJeremy L Thompson       }
401*b7ec98d8SJeremy L Thompson     }
402*b7ec98d8SJeremy L Thompson 
403*b7ec98d8SJeremy L Thompson   // Determine active output basis
404*b7ec98d8SJeremy L Thompson   CeedInt numemodeout = 0;
405*b7ec98d8SJeremy L Thompson   CeedEvalMode *emodeout = NULL;
406*b7ec98d8SJeremy L Thompson   CeedBasis basisout;
407*b7ec98d8SJeremy L Thompson   CeedElemRestriction rstrout;
408*b7ec98d8SJeremy L Thompson   CeedTransposeMode lmodeout;
409*b7ec98d8SJeremy L Thompson   for (CeedInt i=0; i<qf->numoutputfields; i++)
410*b7ec98d8SJeremy L Thompson     if (op->outputfields[i]->vec == CEED_VECTOR_ACTIVE) {
411*b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetBasis(op->outputfields[i], &basisout);
412*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
413*b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetElemRestriction(op->outputfields[i], &rstrout);
414*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
415*b7ec98d8SJeremy L Thompson       ierr = CeedOperatorFieldGetLMode(op->outputfields[i], &lmodeout);
416*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
417*b7ec98d8SJeremy L Thompson       CeedEvalMode emode;
418*b7ec98d8SJeremy L Thompson       ierr = CeedQFunctionFieldGetEvalMode(qf->outputfields[i], &emode);
419*b7ec98d8SJeremy L Thompson       CeedChk(ierr);
420*b7ec98d8SJeremy L Thompson       switch (emode) {
421*b7ec98d8SJeremy L Thompson       case CEED_EVAL_NONE:
422*b7ec98d8SJeremy L Thompson       case CEED_EVAL_INTERP:
423*b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr);
424*b7ec98d8SJeremy L Thompson         emodeout[numemodeout] = emode;
425*b7ec98d8SJeremy L Thompson         numemodeout += 1;
426*b7ec98d8SJeremy L Thompson         break;
427*b7ec98d8SJeremy L Thompson       case CEED_EVAL_GRAD:
428*b7ec98d8SJeremy L Thompson         ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr);
429*b7ec98d8SJeremy L Thompson         for (CeedInt d=0; d<dim; d++)
430*b7ec98d8SJeremy L Thompson           emodeout[numemodeout+d] = emode;
431*b7ec98d8SJeremy L Thompson         numemodeout += dim;
432*b7ec98d8SJeremy L Thompson         break;
433*b7ec98d8SJeremy L Thompson       case CEED_EVAL_WEIGHT:
434*b7ec98d8SJeremy L Thompson       case CEED_EVAL_DIV:
435*b7ec98d8SJeremy L Thompson       case CEED_EVAL_CURL:
436*b7ec98d8SJeremy L Thompson         break; // Caught by QF Assembly
437*b7ec98d8SJeremy L Thompson       }
438*b7ec98d8SJeremy L Thompson     }
439*b7ec98d8SJeremy L Thompson 
440*b7ec98d8SJeremy L Thompson   // Create diagonal vector
441*b7ec98d8SJeremy L Thompson   CeedVector elemdiag;
442*b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag);
443*b7ec98d8SJeremy L Thompson   CeedChk(ierr);
444*b7ec98d8SJeremy L Thompson 
445*b7ec98d8SJeremy L Thompson   // Assemble element operator diagonals
446*b7ec98d8SJeremy L Thompson   CeedScalar *elemdiagarray, *assembledqfarray;
447*b7ec98d8SJeremy L Thompson   ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr);
448*b7ec98d8SJeremy L Thompson   ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray);
449*b7ec98d8SJeremy L Thompson   CeedChk(ierr);
450*b7ec98d8SJeremy L Thompson   ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray);
451*b7ec98d8SJeremy L Thompson   CeedChk(ierr);
452*b7ec98d8SJeremy L Thompson   CeedInt nelem, nnodes, nqpts;
453*b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr);
454*b7ec98d8SJeremy L Thompson   ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr);
455*b7ec98d8SJeremy L Thompson   ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr);
456*b7ec98d8SJeremy L Thompson   // Compute the diagonal of B^T D B
457*b7ec98d8SJeremy L Thompson   // Each node, qpt pair
458*b7ec98d8SJeremy L Thompson   for (CeedInt n=0; n<nnodes; n++)
459*b7ec98d8SJeremy L Thompson     for (CeedInt q=0; q<nqpts; q++) {
460*b7ec98d8SJeremy L Thompson       CeedInt dout = -1;
461*b7ec98d8SJeremy L Thompson       // Each basis eval mode pair
462*b7ec98d8SJeremy L Thompson       for (CeedInt eout=0; eout<numemodeout; eout++) {
463*b7ec98d8SJeremy L Thompson         CeedScalar bt = 1.0;
464*b7ec98d8SJeremy L Thompson         if (emodeout[eout] == CEED_EVAL_GRAD)
465*b7ec98d8SJeremy L Thompson           dout += 1;
466*b7ec98d8SJeremy L Thompson         ierr = CeedBasisGetValue(basisout, emodeout[eout], q, n, dout, &bt);
467*b7ec98d8SJeremy L Thompson         CeedChk(ierr);
468*b7ec98d8SJeremy L Thompson         CeedInt din = -1;
469*b7ec98d8SJeremy L Thompson         for (CeedInt ein=0; ein<numemodein; ein++) {
470*b7ec98d8SJeremy L Thompson           CeedScalar b = 0.0;
471*b7ec98d8SJeremy L Thompson           if (emodein[ein] == CEED_EVAL_GRAD)
472*b7ec98d8SJeremy L Thompson             din += 1;
473*b7ec98d8SJeremy L Thompson           ierr = CeedBasisGetValue(basisin, emodein[ein], q, n, din, &b);
474*b7ec98d8SJeremy L Thompson           CeedChk(ierr);
475*b7ec98d8SJeremy L Thompson           // Each element and component
476*b7ec98d8SJeremy L Thompson           for (CeedInt e=0; e<nelem; e++)
477*b7ec98d8SJeremy L Thompson             for (CeedInt cout=0; cout<ncomp; cout++) {
478*b7ec98d8SJeremy L Thompson               CeedScalar db = 0.0;
479*b7ec98d8SJeremy L Thompson               for (CeedInt cin=0; cin<ncomp; cin++)
480*b7ec98d8SJeremy L Thompson                 db += assembledqfarray[((((e*numemodein+ein)*ncomp+cin)*
481*b7ec98d8SJeremy L Thompson                                        numemodeout+eout)*ncomp+cout)*nqpts+q]*b;
482*b7ec98d8SJeremy L Thompson               elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt * db;
483*b7ec98d8SJeremy L Thompson             }
484*b7ec98d8SJeremy L Thompson         }
485*b7ec98d8SJeremy L Thompson       }
486*b7ec98d8SJeremy L Thompson     }
487*b7ec98d8SJeremy L Thompson 
488*b7ec98d8SJeremy L Thompson   ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr);
489*b7ec98d8SJeremy L Thompson   ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr);
490*b7ec98d8SJeremy L Thompson 
491*b7ec98d8SJeremy L Thompson   // Assemble local operator diagonal
492*b7ec98d8SJeremy L Thompson   ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr);
493*b7ec98d8SJeremy L Thompson   ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag,
494*b7ec98d8SJeremy L Thompson                                   *assembled, request); CeedChk(ierr);
495*b7ec98d8SJeremy L Thompson 
496*b7ec98d8SJeremy L Thompson   // Cleanup
497*b7ec98d8SJeremy L Thompson   ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr);
498*b7ec98d8SJeremy L Thompson   ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr);
499*b7ec98d8SJeremy L Thompson   ierr = CeedFree(&emodein); CeedChk(ierr);
500*b7ec98d8SJeremy L Thompson   ierr = CeedFree(&emodeout); CeedChk(ierr);
501*b7ec98d8SJeremy L Thompson 
502*b7ec98d8SJeremy L Thompson   return 0;
503*b7ec98d8SJeremy L Thompson }
504*b7ec98d8SJeremy L Thompson 
505*b7ec98d8SJeremy L Thompson /**
506b11c1e72Sjeremylt   @brief Apply CeedOperator to a vector
507d7b241e6Sjeremylt 
508d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
509d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
510d7b241e6Sjeremylt   CeedOperatorSetField().
511d7b241e6Sjeremylt 
512d7b241e6Sjeremylt   @param op        CeedOperator to apply
513b11c1e72Sjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
514b11c1e72Sjeremylt                      active inputs
515b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
516d7b241e6Sjeremylt                      distinct from @a in) or NULL if there are no active outputs
517d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
518d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
519b11c1e72Sjeremylt 
520b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
521dfdf5a53Sjeremylt 
522dfdf5a53Sjeremylt   @ref Basic
523b11c1e72Sjeremylt **/
524d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in,
525d7b241e6Sjeremylt                       CeedVector out, CeedRequest *request) {
526d7b241e6Sjeremylt   int ierr;
527d7b241e6Sjeremylt   Ceed ceed = op->ceed;
528d7b241e6Sjeremylt   CeedQFunction qf = op->qf;
529d7b241e6Sjeremylt 
53052d6035fSJeremy L Thompson   if (op->composite) {
531c042f62fSJeremy L Thompson     if (!op->numsub)
532c042f62fSJeremy L Thompson       // LCOV_EXCL_START
533c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "No suboperators set");
534c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
53552d6035fSJeremy L Thompson   } else {
536c042f62fSJeremy L Thompson     if (op->nfields == 0)
537c042f62fSJeremy L Thompson       // LCOV_EXCL_START
538c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "No operator fields set");
539c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
540c042f62fSJeremy L Thompson     if (op->nfields < qf->numinputfields + qf->numoutputfields)
541c042f62fSJeremy L Thompson       // LCOV_EXCL_START
542c042f62fSJeremy L Thompson       return CeedError(ceed, 1, "Not all operator fields set");
543c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
544c042f62fSJeremy L Thompson     if (op->numelements == 0)
545c042f62fSJeremy L Thompson       // LCOV_EXCL_START
546c042f62fSJeremy L Thompson       return CeedError(ceed, 1,"At least one restriction required");
547c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
548c042f62fSJeremy L Thompson     if (op->numqpoints == 0)
549c042f62fSJeremy L Thompson       // LCOV_EXCL_START
550c042f62fSJeremy L Thompson       return CeedError(ceed, 1,"At least one non-collocated basis required");
551c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
55252d6035fSJeremy L Thompson   }
553d7b241e6Sjeremylt   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
554d7b241e6Sjeremylt   return 0;
555d7b241e6Sjeremylt }
556d7b241e6Sjeremylt 
557d7b241e6Sjeremylt /**
5584ce2993fSjeremylt   @brief Get the Ceed associated with a CeedOperator
5594ce2993fSjeremylt 
5604ce2993fSjeremylt   @param op              CeedOperator
5614ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
5624ce2993fSjeremylt 
5634ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5644ce2993fSjeremylt 
56523617272Sjeremylt   @ref Advanced
5664ce2993fSjeremylt **/
5674ce2993fSjeremylt 
5684ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
5694ce2993fSjeremylt   *ceed = op->ceed;
5704ce2993fSjeremylt   return 0;
5714ce2993fSjeremylt }
5724ce2993fSjeremylt 
5734ce2993fSjeremylt /**
5744ce2993fSjeremylt   @brief Get the number of elements associated with a CeedOperator
5754ce2993fSjeremylt 
5764ce2993fSjeremylt   @param op              CeedOperator
5774ce2993fSjeremylt   @param[out] numelem    Variable to store number of elements
5784ce2993fSjeremylt 
5794ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5804ce2993fSjeremylt 
58123617272Sjeremylt   @ref Advanced
5824ce2993fSjeremylt **/
5834ce2993fSjeremylt 
5844ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
58552d6035fSJeremy L Thompson   if (op->composite)
586c042f62fSJeremy L Thompson     // LCOV_EXCL_START
58752d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
588c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
58952d6035fSJeremy L Thompson 
5904ce2993fSjeremylt   *numelem = op->numelements;
5914ce2993fSjeremylt   return 0;
5924ce2993fSjeremylt }
5934ce2993fSjeremylt 
5944ce2993fSjeremylt /**
5954ce2993fSjeremylt   @brief Get the number of quadrature points associated with a CeedOperator
5964ce2993fSjeremylt 
5974ce2993fSjeremylt   @param op              CeedOperator
5984ce2993fSjeremylt   @param[out] numqpts    Variable to store vector number of quadrature points
5994ce2993fSjeremylt 
6004ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6014ce2993fSjeremylt 
60223617272Sjeremylt   @ref Advanced
6034ce2993fSjeremylt **/
6044ce2993fSjeremylt 
6054ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
60652d6035fSJeremy L Thompson   if (op->composite)
607c042f62fSJeremy L Thompson     // LCOV_EXCL_START
60852d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
609c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
61052d6035fSJeremy L Thompson 
6114ce2993fSjeremylt   *numqpts = op->numqpoints;
6124ce2993fSjeremylt   return 0;
6134ce2993fSjeremylt }
6144ce2993fSjeremylt 
6154ce2993fSjeremylt /**
6164ce2993fSjeremylt   @brief Get the number of arguments associated with a CeedOperator
6174ce2993fSjeremylt 
6184ce2993fSjeremylt   @param op              CeedOperator
6194ce2993fSjeremylt   @param[out] numargs    Variable to store vector number of arguments
6204ce2993fSjeremylt 
6214ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6224ce2993fSjeremylt 
62323617272Sjeremylt   @ref Advanced
6244ce2993fSjeremylt **/
6254ce2993fSjeremylt 
6264ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
62752d6035fSJeremy L Thompson   if (op->composite)
628c042f62fSJeremy L Thompson     // LCOV_EXCL_START
62952d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operators");
630c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
631c042f62fSJeremy L Thompson 
6324ce2993fSjeremylt   *numargs = op->nfields;
6334ce2993fSjeremylt   return 0;
6344ce2993fSjeremylt }
6354ce2993fSjeremylt 
6364ce2993fSjeremylt /**
6374ce2993fSjeremylt   @brief Get the setup status of a CeedOperator
6384ce2993fSjeremylt 
6394ce2993fSjeremylt   @param op             CeedOperator
640288c0443SJeremy L Thompson   @param[out] setupdone Variable to store setup status
6414ce2993fSjeremylt 
6424ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6434ce2993fSjeremylt 
64423617272Sjeremylt   @ref Advanced
6454ce2993fSjeremylt **/
6464ce2993fSjeremylt 
6474ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
6484ce2993fSjeremylt   *setupdone = op->setupdone;
6494ce2993fSjeremylt   return 0;
6504ce2993fSjeremylt }
6514ce2993fSjeremylt 
6524ce2993fSjeremylt /**
6534ce2993fSjeremylt   @brief Get the QFunction associated with a CeedOperator
6544ce2993fSjeremylt 
6554ce2993fSjeremylt   @param op              CeedOperator
6568c91a0c9SJeremy L Thompson   @param[out] qf         Variable to store QFunction
6574ce2993fSjeremylt 
6584ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6594ce2993fSjeremylt 
66023617272Sjeremylt   @ref Advanced
6614ce2993fSjeremylt **/
6624ce2993fSjeremylt 
6634ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
66452d6035fSJeremy L Thompson   if (op->composite)
665c042f62fSJeremy L Thompson     // LCOV_EXCL_START
66652d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
667c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
66852d6035fSJeremy L Thompson 
6694ce2993fSjeremylt   *qf = op->qf;
6704ce2993fSjeremylt   return 0;
6714ce2993fSjeremylt }
6724ce2993fSjeremylt 
6734ce2993fSjeremylt /**
67452d6035fSJeremy L Thompson   @brief Get the number of suboperators associated with a CeedOperator
67552d6035fSJeremy L Thompson 
67652d6035fSJeremy L Thompson   @param op              CeedOperator
67752d6035fSJeremy L Thompson   @param[out] numsub     Variable to store number of suboperators
67852d6035fSJeremy L Thompson 
67952d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
68052d6035fSJeremy L Thompson 
68152d6035fSJeremy L Thompson   @ref Advanced
68252d6035fSJeremy L Thompson **/
68352d6035fSJeremy L Thompson 
68452d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) {
685c042f62fSJeremy L Thompson   if (!op->composite)
686c042f62fSJeremy L Thompson     // LCOV_EXCL_START
687c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
688c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
68952d6035fSJeremy L Thompson 
69052d6035fSJeremy L Thompson   *numsub = op->numsub;
69152d6035fSJeremy L Thompson   return 0;
69252d6035fSJeremy L Thompson }
69352d6035fSJeremy L Thompson 
69452d6035fSJeremy L Thompson /**
69552d6035fSJeremy L Thompson   @brief Get the list of suboperators associated with a CeedOperator
69652d6035fSJeremy L Thompson 
69752d6035fSJeremy L Thompson   @param op                CeedOperator
69852d6035fSJeremy L Thompson   @param[out] suboperators Variable to store list of suboperators
69952d6035fSJeremy L Thompson 
70052d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
70152d6035fSJeremy L Thompson 
70252d6035fSJeremy L Thompson   @ref Advanced
70352d6035fSJeremy L Thompson **/
70452d6035fSJeremy L Thompson 
70552d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator* *suboperators) {
706c042f62fSJeremy L Thompson   if (!op->composite)
707c042f62fSJeremy L Thompson     // LCOV_EXCL_START
708c042f62fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not a composite operator");
709c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
71052d6035fSJeremy L Thompson 
71152d6035fSJeremy L Thompson   *suboperators = op->suboperators;
71252d6035fSJeremy L Thompson   return 0;
71352d6035fSJeremy L Thompson }
71452d6035fSJeremy L Thompson 
71552d6035fSJeremy L Thompson /**
716fe2413ffSjeremylt   @brief Set the backend data of a CeedOperator
717fe2413ffSjeremylt 
718fe2413ffSjeremylt   @param[out] op         CeedOperator
719fe2413ffSjeremylt   @param data            Data to set
720fe2413ffSjeremylt 
721fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
722fe2413ffSjeremylt 
723fe2413ffSjeremylt   @ref Advanced
724fe2413ffSjeremylt **/
725fe2413ffSjeremylt 
726fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void* *data) {
727fe2413ffSjeremylt   op->data = *data;
728fe2413ffSjeremylt   return 0;
729fe2413ffSjeremylt }
730fe2413ffSjeremylt 
731fe2413ffSjeremylt /**
7324ce2993fSjeremylt   @brief Get the backend data of a CeedOperator
7334ce2993fSjeremylt 
7344ce2993fSjeremylt   @param op              CeedOperator
7354ce2993fSjeremylt   @param[out] data       Variable to store data
7364ce2993fSjeremylt 
7374ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7384ce2993fSjeremylt 
73923617272Sjeremylt   @ref Advanced
7404ce2993fSjeremylt **/
7414ce2993fSjeremylt 
7424ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void* *data) {
7434ce2993fSjeremylt   *data = op->data;
7444ce2993fSjeremylt   return 0;
7454ce2993fSjeremylt }
7464ce2993fSjeremylt 
7474ce2993fSjeremylt /**
7484ce2993fSjeremylt   @brief Set the setup flag of a CeedOperator to True
7494ce2993fSjeremylt 
7504ce2993fSjeremylt   @param op              CeedOperator
7514ce2993fSjeremylt 
7524ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
7534ce2993fSjeremylt 
75423617272Sjeremylt   @ref Advanced
7554ce2993fSjeremylt **/
7564ce2993fSjeremylt 
7574ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) {
7584ce2993fSjeremylt   op->setupdone = 1;
7594ce2993fSjeremylt   return 0;
7604ce2993fSjeremylt }
7614ce2993fSjeremylt 
7624ce2993fSjeremylt /**
763d1bcdac9Sjeremylt   @brief Get the CeedOperatorFields of a CeedOperator
764d1bcdac9Sjeremylt 
765d1bcdac9Sjeremylt   @param op                 CeedOperator
766d1bcdac9Sjeremylt   @param[out] inputfields   Variable to store inputfields
767d1bcdac9Sjeremylt   @param[out] outputfields  Variable to store outputfields
768d1bcdac9Sjeremylt 
769d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
770d1bcdac9Sjeremylt 
771d1bcdac9Sjeremylt   @ref Advanced
772d1bcdac9Sjeremylt **/
773d1bcdac9Sjeremylt 
774d1bcdac9Sjeremylt int CeedOperatorGetFields(CeedOperator op,
775d1bcdac9Sjeremylt                           CeedOperatorField* *inputfields,
776d1bcdac9Sjeremylt                           CeedOperatorField* *outputfields) {
77752d6035fSJeremy L Thompson   if (op->composite)
778c042f62fSJeremy L Thompson     // LCOV_EXCL_START
77952d6035fSJeremy L Thompson     return CeedError(op->ceed, 1, "Not defined for composite operator");
780c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
78152d6035fSJeremy L Thompson 
782d1bcdac9Sjeremylt   if (inputfields) *inputfields = op->inputfields;
783d1bcdac9Sjeremylt   if (outputfields) *outputfields = op->outputfields;
784d1bcdac9Sjeremylt   return 0;
785d1bcdac9Sjeremylt }
786d1bcdac9Sjeremylt 
787d1bcdac9Sjeremylt /**
7884dccadb6Sjeremylt   @brief Get the L vector CeedTransposeMode of a CeedOperatorField
7894dccadb6Sjeremylt 
7904dccadb6Sjeremylt   @param opfield         CeedOperatorField
7914dccadb6Sjeremylt   @param[out] lmode      Variable to store CeedTransposeMode
7924dccadb6Sjeremylt 
7934dccadb6Sjeremylt   @return An error code: 0 - success, otherwise - failure
7944dccadb6Sjeremylt 
7954dccadb6Sjeremylt   @ref Advanced
7964dccadb6Sjeremylt **/
7974dccadb6Sjeremylt 
7984dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield,
7994dccadb6Sjeremylt                               CeedTransposeMode *lmode) {
800fe2413ffSjeremylt   *lmode = opfield->lmode;
8014dccadb6Sjeremylt   return 0;
8022b8e417aSjeremylt }
8032b8e417aSjeremylt 
8042b8e417aSjeremylt /**
805d1bcdac9Sjeremylt   @brief Get the CeedElemRestriction of a CeedOperatorField
806d1bcdac9Sjeremylt 
807d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
808d1bcdac9Sjeremylt   @param[out] rstr       Variable to store CeedElemRestriction
809d1bcdac9Sjeremylt 
810d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
811d1bcdac9Sjeremylt 
812d1bcdac9Sjeremylt   @ref Advanced
813d1bcdac9Sjeremylt **/
814d1bcdac9Sjeremylt 
815d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
816d1bcdac9Sjeremylt                                         CeedElemRestriction *rstr) {
817fe2413ffSjeremylt   *rstr = opfield->Erestrict;
818d1bcdac9Sjeremylt   return 0;
819d1bcdac9Sjeremylt }
820d1bcdac9Sjeremylt 
821d1bcdac9Sjeremylt /**
822d1bcdac9Sjeremylt   @brief Get the CeedBasis of a CeedOperatorField
823d1bcdac9Sjeremylt 
824d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
825d1bcdac9Sjeremylt   @param[out] basis      Variable to store CeedBasis
826d1bcdac9Sjeremylt 
827d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
828d1bcdac9Sjeremylt 
829d1bcdac9Sjeremylt   @ref Advanced
830d1bcdac9Sjeremylt **/
831d1bcdac9Sjeremylt 
832d1bcdac9Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield,
833d1bcdac9Sjeremylt                               CeedBasis *basis) {
834fe2413ffSjeremylt   *basis = opfield->basis;
835d1bcdac9Sjeremylt   return 0;
836d1bcdac9Sjeremylt }
837d1bcdac9Sjeremylt 
838d1bcdac9Sjeremylt /**
839d1bcdac9Sjeremylt   @brief Get the CeedVector of a CeedOperatorField
840d1bcdac9Sjeremylt 
841d1bcdac9Sjeremylt   @param opfield         CeedOperatorField
842d1bcdac9Sjeremylt   @param[out] vec        Variable to store CeedVector
843d1bcdac9Sjeremylt 
844d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
845d1bcdac9Sjeremylt 
846d1bcdac9Sjeremylt   @ref Advanced
847d1bcdac9Sjeremylt **/
848d1bcdac9Sjeremylt 
849d1bcdac9Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield,
850d1bcdac9Sjeremylt                                CeedVector *vec) {
851fe2413ffSjeremylt   *vec = opfield->vec;
852d1bcdac9Sjeremylt   return 0;
853d1bcdac9Sjeremylt }
854d1bcdac9Sjeremylt 
855d1bcdac9Sjeremylt /**
856b11c1e72Sjeremylt   @brief Destroy a CeedOperator
857d7b241e6Sjeremylt 
858d7b241e6Sjeremylt   @param op CeedOperator to destroy
859b11c1e72Sjeremylt 
860b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
861dfdf5a53Sjeremylt 
862dfdf5a53Sjeremylt   @ref Basic
863b11c1e72Sjeremylt **/
864d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
865d7b241e6Sjeremylt   int ierr;
866d7b241e6Sjeremylt 
867d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
868d7b241e6Sjeremylt   if ((*op)->Destroy) {
869d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
870d7b241e6Sjeremylt   }
871fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
872fe2413ffSjeremylt   // Free fields
8731d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
87452d6035fSJeremy L Thompson     if ((*op)->inputfields[i]) {
87571352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict);
87671352a93Sjeremylt       CeedChk(ierr);
87771352a93Sjeremylt       if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) {
87871352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr);
87971352a93Sjeremylt       }
88071352a93Sjeremylt       if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE &&
88171352a93Sjeremylt           (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) {
88271352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr);
88371352a93Sjeremylt       }
884fe2413ffSjeremylt       ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr);
885fe2413ffSjeremylt     }
8861d102b48SJeremy L Thompson   for (int i=0; i<(*op)->nfields; i++)
887d0eb30a5Sjeremylt     if ((*op)->outputfields[i]) {
88871352a93Sjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict);
88971352a93Sjeremylt       CeedChk(ierr);
89071352a93Sjeremylt       if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) {
89171352a93Sjeremylt         ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr);
89271352a93Sjeremylt       }
89371352a93Sjeremylt       if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE &&
89471352a93Sjeremylt           (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) {
89571352a93Sjeremylt         ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr);
89671352a93Sjeremylt       }
897fe2413ffSjeremylt       ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr);
898fe2413ffSjeremylt     }
89952d6035fSJeremy L Thompson   // Destroy suboperators
9001d102b48SJeremy L Thompson   for (int i=0; i<(*op)->numsub; i++)
90152d6035fSJeremy L Thompson     if ((*op)->suboperators[i]) {
90252d6035fSJeremy L Thompson       ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr);
90352d6035fSJeremy L Thompson     }
904d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
905d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
906d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
907fe2413ffSjeremylt 
908fe2413ffSjeremylt   ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr);
909fe2413ffSjeremylt   ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr);
91052d6035fSJeremy L Thompson   ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr);
911d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
912d7b241e6Sjeremylt   return 0;
913d7b241e6Sjeremylt }
914d7b241e6Sjeremylt 
915d7b241e6Sjeremylt /// @}
916