xref: /libCEED/interface/ceed-operator.c (revision 23617272b99b7e9f8a74525161c55d44882cf4b4)
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 /**
28b11c1e72Sjeremylt   @brief Create an operator from element restriction, basis, and QFunction
29d7b241e6Sjeremylt 
30b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
31d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
32d7b241e6Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
33d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
34d7b241e6Sjeremylt                    of @a qf (or NULL)
35b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
36b11c1e72Sjeremylt                      CeedOperator will be stored
37b11c1e72Sjeremylt 
38b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
39dfdf5a53Sjeremylt 
40dfdf5a53Sjeremylt   @ref Basic
41d7b241e6Sjeremylt  */
42d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
43d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
44d7b241e6Sjeremylt   int ierr;
45d7b241e6Sjeremylt 
465fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
475fe0d4faSjeremylt     Ceed delegate;
485fe0d4faSjeremylt     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
495fe0d4faSjeremylt 
505fe0d4faSjeremylt     if (!delegate)
515fe0d4faSjeremylt       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
525fe0d4faSjeremylt 
535fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
545fe0d4faSjeremylt     return 0;
555fe0d4faSjeremylt   }
565fe0d4faSjeremylt 
57d7b241e6Sjeremylt   ierr = CeedCalloc(1,op); CeedChk(ierr);
58d7b241e6Sjeremylt   (*op)->ceed = ceed;
59d7b241e6Sjeremylt   ceed->refcount++;
60d7b241e6Sjeremylt   (*op)->refcount = 1;
61d7b241e6Sjeremylt   (*op)->qf = qf;
62d7b241e6Sjeremylt   qf->refcount++;
63d7b241e6Sjeremylt   (*op)->dqf = dqf;
64d7b241e6Sjeremylt   if (dqf) dqf->refcount++;
65d7b241e6Sjeremylt   (*op)->dqfT = dqfT;
66d7b241e6Sjeremylt   if (dqfT) dqfT->refcount++;
67d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
68d7b241e6Sjeremylt   return 0;
69d7b241e6Sjeremylt }
70d7b241e6Sjeremylt 
71d7b241e6Sjeremylt /**
72b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
73d7b241e6Sjeremylt 
74d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
75d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
76d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
77d7b241e6Sjeremylt 
78d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
79d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
80d7b241e6Sjeremylt   input and at most one active output.
81d7b241e6Sjeremylt 
82b11c1e72Sjeremylt   @param op         Ceedoperator on which to provide the field
83b11c1e72Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by CeedQFunction)
84b11c1e72Sjeremylt   @param r          CeedElemRestriction
85783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
86b11c1e72Sjeremylt                       if collocated with quadrature points
87b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
88b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
89b11c1e72Sjeremylt                       CEED_EVAL_WEIGHT in the qfunction
90b11c1e72Sjeremylt 
91b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
92dfdf5a53Sjeremylt 
93dfdf5a53Sjeremylt   @ref Basic
94b11c1e72Sjeremylt **/
95d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
96d7b241e6Sjeremylt                          CeedElemRestriction r, CeedBasis b,
97d7b241e6Sjeremylt                          CeedVector v) {
98d7b241e6Sjeremylt   int ierr;
99d7b241e6Sjeremylt   CeedInt numelements;
100d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
101d7b241e6Sjeremylt   if (op->numelements && op->numelements != numelements)
102d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
103d7b241e6Sjeremylt                      "ElemRestriction with %d elements incompatible with prior %d elements",
104d7b241e6Sjeremylt                      numelements, op->numelements);
105d7b241e6Sjeremylt   op->numelements = numelements;
106d7b241e6Sjeremylt 
107783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
108d7b241e6Sjeremylt     CeedInt numqpoints;
109d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
110d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
111d7b241e6Sjeremylt       return CeedError(op->ceed, 1,
112d7b241e6Sjeremylt                        "Basis with %d quadrature points incompatible with prior %d points",
113d7b241e6Sjeremylt                        numqpoints, op->numqpoints);
114d7b241e6Sjeremylt     op->numqpoints = numqpoints;
115d7b241e6Sjeremylt   }
116d7b241e6Sjeremylt   struct CeedOperatorField *ofield;
117d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
118d7b241e6Sjeremylt     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
119d7b241e6Sjeremylt       ofield = &op->inputfields[i];
120d7b241e6Sjeremylt       goto found;
121d7b241e6Sjeremylt     }
122d7b241e6Sjeremylt   }
123d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
124d7b241e6Sjeremylt     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
125d7b241e6Sjeremylt       ofield = &op->outputfields[i];
126d7b241e6Sjeremylt       goto found;
127d7b241e6Sjeremylt     }
128d7b241e6Sjeremylt   }
129d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
130d7b241e6Sjeremylt                    fieldname);
131d7b241e6Sjeremylt found:
132d7b241e6Sjeremylt   ofield->Erestrict = r;
133d7b241e6Sjeremylt   ofield->basis = b;
134d7b241e6Sjeremylt   ofield->vec = v;
135d7b241e6Sjeremylt   op->nfields += 1;
136d7b241e6Sjeremylt   return 0;
137d7b241e6Sjeremylt }
138d7b241e6Sjeremylt 
139d7b241e6Sjeremylt /**
140b11c1e72Sjeremylt   @brief Apply CeedOperator to a vector
141d7b241e6Sjeremylt 
142d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
143d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
144d7b241e6Sjeremylt   CeedOperatorSetField().
145d7b241e6Sjeremylt 
146d7b241e6Sjeremylt   @param op        CeedOperator to apply
147b11c1e72Sjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
148b11c1e72Sjeremylt                      active inputs
149b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
150d7b241e6Sjeremylt                      distinct from @a in) or NULL if there are no active outputs
151d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
152d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
153b11c1e72Sjeremylt 
154b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
155dfdf5a53Sjeremylt 
156dfdf5a53Sjeremylt   @ref Basic
157b11c1e72Sjeremylt **/
158d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in,
159d7b241e6Sjeremylt                       CeedVector out, CeedRequest *request) {
160d7b241e6Sjeremylt   int ierr;
161d7b241e6Sjeremylt   Ceed ceed = op->ceed;
162d7b241e6Sjeremylt   CeedQFunction qf = op->qf;
163d7b241e6Sjeremylt 
164d7b241e6Sjeremylt   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
165d7b241e6Sjeremylt   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
166d7b241e6Sjeremylt           ceed, 1, "Not all operator fields set");
167d7b241e6Sjeremylt   if (op->numelements == 0) return CeedError(ceed, 1,
168d7b241e6Sjeremylt                                      "At least one restriction required");
169d7b241e6Sjeremylt   if (op->numqpoints == 0) return CeedError(ceed, 1,
170783c99b3SValeria Barra                                     "At least one non-collocated basis required");
171d7b241e6Sjeremylt   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
172d7b241e6Sjeremylt   return 0;
173d7b241e6Sjeremylt }
174d7b241e6Sjeremylt 
175d7b241e6Sjeremylt /**
1764ce2993fSjeremylt   @brief Get the Ceed associated with a CeedOperator
1774ce2993fSjeremylt 
1784ce2993fSjeremylt   @param op              CeedOperator
1794ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
1804ce2993fSjeremylt 
1814ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
1824ce2993fSjeremylt 
183*23617272Sjeremylt   @ref Advanced
1844ce2993fSjeremylt **/
1854ce2993fSjeremylt 
1864ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
1874ce2993fSjeremylt   *ceed = op->ceed;
1884ce2993fSjeremylt   return 0;
1894ce2993fSjeremylt }
1904ce2993fSjeremylt 
1914ce2993fSjeremylt /**
1924ce2993fSjeremylt   @brief Get the number of elements associated with a CeedOperator
1934ce2993fSjeremylt 
1944ce2993fSjeremylt   @param op              CeedOperator
1954ce2993fSjeremylt   @param[out] numelem    Variable to store number of elements
1964ce2993fSjeremylt 
1974ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
1984ce2993fSjeremylt 
199*23617272Sjeremylt   @ref Advanced
2004ce2993fSjeremylt **/
2014ce2993fSjeremylt 
2024ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
2034ce2993fSjeremylt   *numelem = op->numelements;
2044ce2993fSjeremylt   return 0;
2054ce2993fSjeremylt }
2064ce2993fSjeremylt 
2074ce2993fSjeremylt /**
2084ce2993fSjeremylt   @brief Get the number of quadrature points associated with a CeedOperator
2094ce2993fSjeremylt 
2104ce2993fSjeremylt   @param op              CeedOperator
2114ce2993fSjeremylt   @param[out] numqpts    Variable to store vector number of quadrature points
2124ce2993fSjeremylt 
2134ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2144ce2993fSjeremylt 
215*23617272Sjeremylt   @ref Advanced
2164ce2993fSjeremylt **/
2174ce2993fSjeremylt 
2184ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
2194ce2993fSjeremylt   *numqpts = op->numqpoints;
2204ce2993fSjeremylt   return 0;
2214ce2993fSjeremylt }
2224ce2993fSjeremylt 
2234ce2993fSjeremylt /**
2244ce2993fSjeremylt   @brief Get the number of arguments associated with a CeedOperator
2254ce2993fSjeremylt 
2264ce2993fSjeremylt   @param op              CeedOperator
2274ce2993fSjeremylt   @param[out] numargs    Variable to store vector number of arguments
2284ce2993fSjeremylt 
2294ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2304ce2993fSjeremylt 
231*23617272Sjeremylt   @ref Advanced
2324ce2993fSjeremylt **/
2334ce2993fSjeremylt 
2344ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
2354ce2993fSjeremylt   *numargs = op->nfields;
2364ce2993fSjeremylt   return 0;
2374ce2993fSjeremylt }
2384ce2993fSjeremylt 
2394ce2993fSjeremylt /**
2404ce2993fSjeremylt   @brief Get the setup status of a CeedOperator
2414ce2993fSjeremylt 
2424ce2993fSjeremylt   @param op              CeedOperator
2434ce2993fSjeremylt   @param[out] numelem    Variable to store setup status
2444ce2993fSjeremylt 
2454ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2464ce2993fSjeremylt 
247*23617272Sjeremylt   @ref Advanced
2484ce2993fSjeremylt **/
2494ce2993fSjeremylt 
2504ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
2514ce2993fSjeremylt   *setupdone = op->setupdone;
2524ce2993fSjeremylt   return 0;
2534ce2993fSjeremylt }
2544ce2993fSjeremylt 
2554ce2993fSjeremylt /**
2564ce2993fSjeremylt   @brief Get the QFunction associated with a CeedOperator
2574ce2993fSjeremylt 
2584ce2993fSjeremylt   @param op              CeedOperator
2594ce2993fSjeremylt   @param[out] qf         Variable to store qfunction
2604ce2993fSjeremylt 
2614ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2624ce2993fSjeremylt 
263*23617272Sjeremylt   @ref Advanced
2644ce2993fSjeremylt **/
2654ce2993fSjeremylt 
2664ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
2674ce2993fSjeremylt   *qf = op->qf;
2684ce2993fSjeremylt   return 0;
2694ce2993fSjeremylt }
2704ce2993fSjeremylt 
2714ce2993fSjeremylt /**
2724ce2993fSjeremylt   @brief Get the backend data of a CeedOperator
2734ce2993fSjeremylt 
2744ce2993fSjeremylt   @param op              CeedOperator
2754ce2993fSjeremylt   @param[out] data       Variable to store data
2764ce2993fSjeremylt 
2774ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2784ce2993fSjeremylt 
279*23617272Sjeremylt   @ref Advanced
2804ce2993fSjeremylt **/
2814ce2993fSjeremylt 
2824ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void* *data) {
2834ce2993fSjeremylt   *data = op->data;
2844ce2993fSjeremylt   return 0;
2854ce2993fSjeremylt }
2864ce2993fSjeremylt 
2874ce2993fSjeremylt /**
2884ce2993fSjeremylt   @brief Set the setup flag of a CeedOperator to True
2894ce2993fSjeremylt 
2904ce2993fSjeremylt   @param op              CeedOperator
2914ce2993fSjeremylt 
2924ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2934ce2993fSjeremylt 
294*23617272Sjeremylt   @ref Advanced
2954ce2993fSjeremylt **/
2964ce2993fSjeremylt 
2974ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) {
2984ce2993fSjeremylt   op->setupdone = 1;
2994ce2993fSjeremylt   return 0;
3004ce2993fSjeremylt }
3014ce2993fSjeremylt 
3024ce2993fSjeremylt /**
303b11c1e72Sjeremylt   @brief Destroy a CeedOperator
304d7b241e6Sjeremylt 
305d7b241e6Sjeremylt   @param op CeedOperator to destroy
306b11c1e72Sjeremylt 
307b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
308dfdf5a53Sjeremylt 
309dfdf5a53Sjeremylt   @ref Basic
310b11c1e72Sjeremylt **/
311d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
312d7b241e6Sjeremylt   int ierr;
313d7b241e6Sjeremylt 
314d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
315d7b241e6Sjeremylt   if ((*op)->Destroy) {
316d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
317d7b241e6Sjeremylt   }
318d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
319d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
320d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
321d7b241e6Sjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
322d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
323d7b241e6Sjeremylt   return 0;
324d7b241e6Sjeremylt }
325d7b241e6Sjeremylt 
326d7b241e6Sjeremylt /// @}
327