xref: /libCEED/interface/ceed-operator.c (revision 4ce2993fee6e7bc9b86526ee90098d0dc489fc60)
1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3 // reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 #include <ceed-impl.h>
18 #include <string.h>
19 
20 /// @file
21 /// Implementation of public CeedOperator interfaces
22 ///
23 /// @addtogroup CeedOperator
24 ///   @{
25 
26 /**
27   @brief Create an operator from element restriction, basis, and QFunction
28 
29   @param ceed    A Ceed object where the CeedOperator will be created
30   @param qf      QFunction defining the action of the operator at quadrature points
31   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
32   @param dqfT    QFunction defining the action of the transpose of the Jacobian
33                    of @a qf (or NULL)
34   @param[out] op Address of the variable where the newly created
35                      CeedOperator will be stored
36 
37   @return An error code: 0 - success, otherwise - failure
38 
39   @ref Basic
40  */
41 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
42                        CeedQFunction dqfT, CeedOperator *op) {
43   int ierr;
44 
45   if (!ceed->OperatorCreate) {
46     Ceed delegate;
47     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
48 
49     if (!delegate)
50       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
51 
52     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
53     return 0;
54   }
55 
56   ierr = CeedCalloc(1,op); CeedChk(ierr);
57   (*op)->ceed = ceed;
58   ceed->refcount++;
59   (*op)->refcount = 1;
60   (*op)->qf = qf;
61   qf->refcount++;
62   (*op)->dqf = dqf;
63   if (dqf) dqf->refcount++;
64   (*op)->dqfT = dqfT;
65   if (dqfT) dqfT->refcount++;
66   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
67   return 0;
68 }
69 
70 /**
71   @brief Provide a field to a CeedOperator for use by its CeedQFunction
72 
73   This function is used to specify both active and passive fields to a
74   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
75   fields can inputs or outputs (updated in-place when operator is applied).
76 
77   Active fields must be specified using this function, but their data (in a
78   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
79   input and at most one active output.
80 
81   @param op         Ceedoperator on which to provide the field
82   @param fieldname  Name of the field (to be matched with the name used by CeedQFunction)
83   @param r          CeedElemRestriction
84   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
85                       if collocated with quadrature points
86   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
87                       if field is active or CEED_VECTOR_NONE if using
88                       CEED_EVAL_WEIGHT in the qfunction
89 
90   @return An error code: 0 - success, otherwise - failure
91 
92   @ref Basic
93 **/
94 int CeedOperatorSetField(CeedOperator op, const char *fieldname,
95                          CeedElemRestriction r, CeedBasis b,
96                          CeedVector v) {
97   int ierr;
98   CeedInt numelements;
99   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
100   if (op->numelements && op->numelements != numelements)
101     return CeedError(op->ceed, 1,
102                      "ElemRestriction with %d elements incompatible with prior %d elements",
103                      numelements, op->numelements);
104   op->numelements = numelements;
105 
106   if (b != CEED_BASIS_COLLOCATED) {
107     CeedInt numqpoints;
108     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
109     if (op->numqpoints && op->numqpoints != numqpoints)
110       return CeedError(op->ceed, 1,
111                        "Basis with %d quadrature points incompatible with prior %d points",
112                        numqpoints, op->numqpoints);
113     op->numqpoints = numqpoints;
114   }
115   struct CeedOperatorField *ofield;
116   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
117     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
118       ofield = &op->inputfields[i];
119       goto found;
120     }
121   }
122   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
123     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
124       ofield = &op->outputfields[i];
125       goto found;
126     }
127   }
128   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
129                    fieldname);
130 found:
131   ofield->Erestrict = r;
132   ofield->basis = b;
133   ofield->vec = v;
134   op->nfields += 1;
135   return 0;
136 }
137 
138 /**
139   @brief Apply CeedOperator to a vector
140 
141   This computes the action of the operator on the specified (active) input,
142   yielding its (active) output.  All inputs and outputs must be specified using
143   CeedOperatorSetField().
144 
145   @param op        CeedOperator to apply
146   @param[in] in    CeedVector containing input state or NULL if there are no
147                      active inputs
148   @param[out] out  CeedVector to store result of applying operator (must be
149                      distinct from @a in) or NULL if there are no active outputs
150   @param request   Address of CeedRequest for non-blocking completion, else
151                      CEED_REQUEST_IMMEDIATE
152 
153   @return An error code: 0 - success, otherwise - failure
154 
155   @ref Basic
156 **/
157 int CeedOperatorApply(CeedOperator op, CeedVector in,
158                       CeedVector out, CeedRequest *request) {
159   int ierr;
160   Ceed ceed = op->ceed;
161   CeedQFunction qf = op->qf;
162 
163   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
164   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
165           ceed, 1, "Not all operator fields set");
166   if (op->numelements == 0) return CeedError(ceed, 1,
167                                      "At least one restriction required");
168   if (op->numqpoints == 0) return CeedError(ceed, 1,
169                                     "At least one non-collocated basis required");
170   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
171   return 0;
172 }
173 
174 /**
175   @brief Get the Ceed associated with a CeedOperator
176 
177   @param op              CeedOperator
178   @param[out] ceed       Variable to store Ceed
179 
180   @return An error code: 0 - success, otherwise - failure
181 
182   @ref Utility
183 **/
184 
185 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
186   *ceed = op->ceed;
187   return 0;
188 }
189 
190 /**
191   @brief Get the number of elements associated with a CeedOperator
192 
193   @param op              CeedOperator
194   @param[out] numelem    Variable to store number of elements
195 
196   @return An error code: 0 - success, otherwise - failure
197 
198   @ref Utility
199 **/
200 
201 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
202   *numelem = op->numelements;
203   return 0;
204 }
205 
206 /**
207   @brief Get the number of quadrature points associated with a CeedOperator
208 
209   @param op              CeedOperator
210   @param[out] numqpts    Variable to store vector number of quadrature points
211 
212   @return An error code: 0 - success, otherwise - failure
213 
214   @ref Utility
215 **/
216 
217 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
218   *numqpts = op->numqpoints;
219   return 0;
220 }
221 
222 /**
223   @brief Get the number of arguments associated with a CeedOperator
224 
225   @param op              CeedOperator
226   @param[out] numargs    Variable to store vector number of arguments
227 
228   @return An error code: 0 - success, otherwise - failure
229 
230   @ref Utility
231 **/
232 
233 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
234   *numargs = op->nfields;
235   return 0;
236 }
237 
238 /**
239   @brief Get the setup status of a CeedOperator
240 
241   @param op              CeedOperator
242   @param[out] numelem    Variable to store setup status
243 
244   @return An error code: 0 - success, otherwise - failure
245 
246   @ref Utility
247 **/
248 
249 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
250   *setupdone = op->setupdone;
251   return 0;
252 }
253 
254 /**
255   @brief Get the QFunction associated with a CeedOperator
256 
257   @param op              CeedOperator
258   @param[out] qf         Variable to store qfunction
259 
260   @return An error code: 0 - success, otherwise - failure
261 
262   @ref Utility
263 **/
264 
265 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
266   *qf = op->qf;
267   return 0;
268 }
269 
270 /**
271   @brief Get the backend data of a CeedOperator
272 
273   @param op              CeedOperator
274   @param[out] data       Variable to store data
275 
276   @return An error code: 0 - success, otherwise - failure
277 
278   @ref Utility
279 **/
280 
281 int CeedOperatorGetData(CeedOperator op, void* *data) {
282   *data = op->data;
283   return 0;
284 }
285 
286 /**
287   @brief Set the setup flag of a CeedOperator to True
288 
289   @param op              CeedOperator
290 
291   @return An error code: 0 - success, otherwise - failure
292 
293   @ref Utility
294 **/
295 
296 int CeedOperatorSetSetupDone(CeedOperator op) {
297   op->setupdone = 1;
298   return 0;
299 }
300 
301 /**
302   @brief Destroy a CeedOperator
303 
304   @param op CeedOperator to destroy
305 
306   @return An error code: 0 - success, otherwise - failure
307 
308   @ref Basic
309 **/
310 int CeedOperatorDestroy(CeedOperator *op) {
311   int ierr;
312 
313   if (!*op || --(*op)->refcount > 0) return 0;
314   if ((*op)->Destroy) {
315     ierr = (*op)->Destroy(*op); CeedChk(ierr);
316   }
317   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
318   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
319   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
320   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
321   ierr = CeedFree(op); CeedChk(ierr);
322   return 0;
323 }
324 
325 /// @}
326