xref: /libCEED/interface/ceed-operator.c (revision d1bcdac99090efedac6b43fd437855ade149b9cc)
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 <ceed-backend.h>
19 #include <string.h>
20 
21 /// @file
22 /// Implementation of public CeedOperator interfaces
23 ///
24 /// @addtogroup CeedOperator
25 ///   @{
26 
27 /**
28   @brief Create an operator from element restriction, basis, and QFunction
29 
30   @param ceed    A Ceed object where the CeedOperator will be created
31   @param qf      QFunction defining the action of the operator at quadrature points
32   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
33   @param dqfT    QFunction defining the action of the transpose of the Jacobian
34                    of @a qf (or NULL)
35   @param[out] op Address of the variable where the newly created
36                      CeedOperator will be stored
37 
38   @return An error code: 0 - success, otherwise - failure
39 
40   @ref Basic
41  */
42 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
43                        CeedQFunction dqfT, CeedOperator *op) {
44   int ierr;
45 
46   if (!ceed->OperatorCreate) {
47     Ceed delegate;
48     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
49 
50     if (!delegate)
51       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
52 
53     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
54     return 0;
55   }
56 
57   ierr = CeedCalloc(1,op); CeedChk(ierr);
58   (*op)->ceed = ceed;
59   ceed->refcount++;
60   (*op)->refcount = 1;
61   (*op)->qf = qf;
62   qf->refcount++;
63   (*op)->dqf = dqf;
64   if (dqf) dqf->refcount++;
65   (*op)->dqfT = dqfT;
66   if (dqfT) dqfT->refcount++;
67   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
68   return 0;
69 }
70 
71 /**
72   @brief Provide a field to a CeedOperator for use by its CeedQFunction
73 
74   This function is used to specify both active and passive fields to a
75   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
76   fields can inputs or outputs (updated in-place when operator is applied).
77 
78   Active fields must be specified using this function, but their data (in a
79   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
80   input and at most one active output.
81 
82   @param op         Ceedoperator on which to provide the field
83   @param fieldname  Name of the field (to be matched with the name used by CeedQFunction)
84   @param r          CeedElemRestriction
85   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
86                       if collocated with quadrature points
87   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
88                       if field is active or CEED_VECTOR_NONE if using
89                       CEED_EVAL_WEIGHT in the qfunction
90 
91   @return An error code: 0 - success, otherwise - failure
92 
93   @ref Basic
94 **/
95 int CeedOperatorSetField(CeedOperator op, const char *fieldname,
96                          CeedElemRestriction r, CeedBasis b,
97                          CeedVector v) {
98   int ierr;
99   CeedInt numelements;
100   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
101   if (op->numelements && op->numelements != numelements)
102     return CeedError(op->ceed, 1,
103                      "ElemRestriction with %d elements incompatible with prior %d elements",
104                      numelements, op->numelements);
105   op->numelements = numelements;
106 
107   if (b != CEED_BASIS_COLLOCATED) {
108     CeedInt numqpoints;
109     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
110     if (op->numqpoints && op->numqpoints != numqpoints)
111       return CeedError(op->ceed, 1,
112                        "Basis with %d quadrature points incompatible with prior %d points",
113                        numqpoints, op->numqpoints);
114     op->numqpoints = numqpoints;
115   }
116   CeedOperatorField *ofield;
117   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
118     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
119       ofield = &op->inputfields[i];
120       goto found;
121     }
122   }
123   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
124     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
125       ofield = &op->outputfields[i];
126       goto found;
127     }
128   }
129   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
130                    fieldname);
131 found:
132   ofield->Erestrict = r;
133   ofield->basis = b;
134   ofield->vec = v;
135   op->nfields += 1;
136   return 0;
137 }
138 
139 /**
140   @brief Apply CeedOperator to a vector
141 
142   This computes the action of the operator on the specified (active) input,
143   yielding its (active) output.  All inputs and outputs must be specified using
144   CeedOperatorSetField().
145 
146   @param op        CeedOperator to apply
147   @param[in] in    CeedVector containing input state or NULL if there are no
148                      active inputs
149   @param[out] out  CeedVector to store result of applying operator (must be
150                      distinct from @a in) or NULL if there are no active outputs
151   @param request   Address of CeedRequest for non-blocking completion, else
152                      CEED_REQUEST_IMMEDIATE
153 
154   @return An error code: 0 - success, otherwise - failure
155 
156   @ref Basic
157 **/
158 int CeedOperatorApply(CeedOperator op, CeedVector in,
159                       CeedVector out, CeedRequest *request) {
160   int ierr;
161   Ceed ceed = op->ceed;
162   CeedQFunction qf = op->qf;
163 
164   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
165   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
166           ceed, 1, "Not all operator fields set");
167   if (op->numelements == 0) return CeedError(ceed, 1,
168                                      "At least one restriction required");
169   if (op->numqpoints == 0) return CeedError(ceed, 1,
170                                     "At least one non-collocated basis required");
171   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
172   return 0;
173 }
174 
175 /**
176   @brief Get the Ceed associated with a CeedOperator
177 
178   @param op              CeedOperator
179   @param[out] ceed       Variable to store Ceed
180 
181   @return An error code: 0 - success, otherwise - failure
182 
183   @ref Advanced
184 **/
185 
186 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
187   *ceed = op->ceed;
188   return 0;
189 }
190 
191 /**
192   @brief Get the number of elements associated with a CeedOperator
193 
194   @param op              CeedOperator
195   @param[out] numelem    Variable to store number of elements
196 
197   @return An error code: 0 - success, otherwise - failure
198 
199   @ref Advanced
200 **/
201 
202 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
203   *numelem = op->numelements;
204   return 0;
205 }
206 
207 /**
208   @brief Get the number of quadrature points associated with a CeedOperator
209 
210   @param op              CeedOperator
211   @param[out] numqpts    Variable to store vector number of quadrature points
212 
213   @return An error code: 0 - success, otherwise - failure
214 
215   @ref Advanced
216 **/
217 
218 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
219   *numqpts = op->numqpoints;
220   return 0;
221 }
222 
223 /**
224   @brief Get the number of arguments associated with a CeedOperator
225 
226   @param op              CeedOperator
227   @param[out] numargs    Variable to store vector number of arguments
228 
229   @return An error code: 0 - success, otherwise - failure
230 
231   @ref Advanced
232 **/
233 
234 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
235   *numargs = op->nfields;
236   return 0;
237 }
238 
239 /**
240   @brief Get the setup status of a CeedOperator
241 
242   @param op              CeedOperator
243   @param[out] numelem    Variable to store setup status
244 
245   @return An error code: 0 - success, otherwise - failure
246 
247   @ref Advanced
248 **/
249 
250 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
251   *setupdone = op->setupdone;
252   return 0;
253 }
254 
255 /**
256   @brief Get the QFunction associated with a CeedOperator
257 
258   @param op              CeedOperator
259   @param[out] qf         Variable to store qfunction
260 
261   @return An error code: 0 - success, otherwise - failure
262 
263   @ref Advanced
264 **/
265 
266 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
267   *qf = op->qf;
268   return 0;
269 }
270 
271 /**
272   @brief Get the backend data of a CeedOperator
273 
274   @param op              CeedOperator
275   @param[out] data       Variable to store data
276 
277   @return An error code: 0 - success, otherwise - failure
278 
279   @ref Advanced
280 **/
281 
282 int CeedOperatorGetData(CeedOperator op, void* *data) {
283   *data = op->data;
284   return 0;
285 }
286 
287 /**
288   @brief Set the setup flag of a CeedOperator to True
289 
290   @param op              CeedOperator
291 
292   @return An error code: 0 - success, otherwise - failure
293 
294   @ref Advanced
295 **/
296 
297 int CeedOperatorSetSetupDone(CeedOperator op) {
298   op->setupdone = 1;
299   return 0;
300 }
301 
302 /**
303   @brief Get the CeedOperatorFields of a CeedOperator
304 
305   @param op                 CeedOperator
306   @param[out] inputfields   Variable to store inputfields
307   @param[out] outputfields  Variable to store outputfields
308 
309   @return An error code: 0 - success, otherwise - failure
310 
311   @ref Advanced
312 **/
313 
314 int CeedOperatorGetFields(CeedOperator op,
315                           CeedOperatorField* *inputfields,
316                           CeedOperatorField* *outputfields) {
317   if (inputfields) *inputfields = op->inputfields;
318   if (outputfields) *outputfields = op->outputfields;
319   return 0;
320 }
321 
322 /**
323   @brief Get the CeedElemRestriction of a CeedOperatorField
324 
325   @param opfield         CeedOperatorField
326   @param[out] rstr       Variable to store CeedElemRestriction
327 
328   @return An error code: 0 - success, otherwise - failure
329 
330   @ref Advanced
331 **/
332 
333 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
334                                         CeedElemRestriction *rstr) {
335   *rstr = (&opfield)->Erestrict;
336   return 0;
337 }
338 
339 /**
340   @brief Get the CeedBasis of a CeedOperatorField
341 
342   @param opfield         CeedOperatorField
343   @param[out] basis      Variable to store CeedBasis
344 
345   @return An error code: 0 - success, otherwise - failure
346 
347   @ref Advanced
348 **/
349 
350 int CeedOperatorFieldGetBasis(CeedOperatorField opfield,
351                               CeedBasis *basis) {
352   *basis = (&opfield)->basis;
353   return 0;
354 }
355 
356 /**
357   @brief Get the CeedVector of a CeedOperatorField
358 
359   @param opfield         CeedOperatorField
360   @param[out] vec        Variable to store CeedVector
361 
362   @return An error code: 0 - success, otherwise - failure
363 
364   @ref Advanced
365 **/
366 
367 int CeedOperatorFieldGetVector(CeedOperatorField opfield,
368                                CeedVector *vec) {
369   *vec = (&opfield)->vec;
370   return 0;
371 }
372 
373 /**
374   @brief Destroy a CeedOperator
375 
376   @param op CeedOperator to destroy
377 
378   @return An error code: 0 - success, otherwise - failure
379 
380   @ref Basic
381 **/
382 int CeedOperatorDestroy(CeedOperator *op) {
383   int ierr;
384 
385   if (!*op || --(*op)->refcount > 0) return 0;
386   if ((*op)->Destroy) {
387     ierr = (*op)->Destroy(*op); CeedChk(ierr);
388   }
389   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
390   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
391   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
392   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
393   ierr = CeedFree(op); CeedChk(ierr);
394   return 0;
395 }
396 
397 /// @}
398