xref: /libCEED/interface/ceed-operator.c (revision 73d2608534f156b5cd04d2be8b81b970eca98867)
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 lmode      CeedTransposeMode which specifies the ordering of the
86                       components of the l-vector used by this CeedOperatorField,
87                       CEED_NOTRANSPOSE indicates the component is the
88                       outermost index and CEED_TRANSPOSE indicates the component
89                       is the innermost index in ordering of the l-vector
90   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
91                       if collocated with quadrature points
92   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
93                       if field is active or CEED_VECTOR_NONE if using
94                       CEED_EVAL_WEIGHT in the qfunction
95 
96   @return An error code: 0 - success, otherwise - failure
97 
98   @ref Basic
99 **/
100 int CeedOperatorSetField(CeedOperator op, const char *fieldname,
101                          CeedElemRestriction r, CeedTransposeMode lmode,
102                          CeedBasis b, CeedVector v) {
103   int ierr;
104   CeedInt numelements;
105   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
106   if (op->numelements && op->numelements != numelements)
107     return CeedError(op->ceed, 1,
108                      "ElemRestriction with %d elements incompatible with prior %d elements",
109                      numelements, op->numelements);
110   op->numelements = numelements;
111 
112   if (b != CEED_BASIS_COLLOCATED) {
113     CeedInt numqpoints;
114     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
115     if (op->numqpoints && op->numqpoints != numqpoints)
116       return CeedError(op->ceed, 1,
117                        "Basis with %d quadrature points incompatible with prior %d points",
118                        numqpoints, op->numqpoints);
119     op->numqpoints = numqpoints;
120   }
121   CeedOperatorField *ofield;
122   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
123     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
124       ofield = &op->inputfields[i];
125       goto found;
126     }
127   }
128   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
129     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
130       ofield = &op->outputfields[i];
131       goto found;
132     }
133   }
134   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
135                    fieldname);
136 found:
137   ofield->Erestrict = r;
138   ofield->lmode = lmode;
139   ofield->basis = b;
140   ofield->vec = v;
141   op->nfields += 1;
142   return 0;
143 }
144 
145 /**
146   @brief Apply CeedOperator to a vector
147 
148   This computes the action of the operator on the specified (active) input,
149   yielding its (active) output.  All inputs and outputs must be specified using
150   CeedOperatorSetField().
151 
152   @param op        CeedOperator to apply
153   @param[in] in    CeedVector containing input state or NULL if there are no
154                      active inputs
155   @param[out] out  CeedVector to store result of applying operator (must be
156                      distinct from @a in) or NULL if there are no active outputs
157   @param request   Address of CeedRequest for non-blocking completion, else
158                      CEED_REQUEST_IMMEDIATE
159 
160   @return An error code: 0 - success, otherwise - failure
161 
162   @ref Basic
163 **/
164 int CeedOperatorApply(CeedOperator op, CeedVector in,
165                       CeedVector out, CeedRequest *request) {
166   int ierr;
167   Ceed ceed = op->ceed;
168   CeedQFunction qf = op->qf;
169 
170   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
171   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
172           ceed, 1, "Not all operator fields set");
173   if (op->numelements == 0) return CeedError(ceed, 1,
174                                      "At least one restriction required");
175   if (op->numqpoints == 0) return CeedError(ceed, 1,
176                                     "At least one non-collocated basis required");
177   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
178   return 0;
179 }
180 
181 /**
182   @brief Get the Ceed associated with a CeedOperator
183 
184   @param op              CeedOperator
185   @param[out] ceed       Variable to store Ceed
186 
187   @return An error code: 0 - success, otherwise - failure
188 
189   @ref Advanced
190 **/
191 
192 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
193   *ceed = op->ceed;
194   return 0;
195 }
196 
197 /**
198   @brief Get the number of elements associated with a CeedOperator
199 
200   @param op              CeedOperator
201   @param[out] numelem    Variable to store number of elements
202 
203   @return An error code: 0 - success, otherwise - failure
204 
205   @ref Advanced
206 **/
207 
208 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) {
209   *numelem = op->numelements;
210   return 0;
211 }
212 
213 /**
214   @brief Get the number of quadrature points associated with a CeedOperator
215 
216   @param op              CeedOperator
217   @param[out] numqpts    Variable to store vector number of quadrature points
218 
219   @return An error code: 0 - success, otherwise - failure
220 
221   @ref Advanced
222 **/
223 
224 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) {
225   *numqpts = op->numqpoints;
226   return 0;
227 }
228 
229 /**
230   @brief Get the number of arguments associated with a CeedOperator
231 
232   @param op              CeedOperator
233   @param[out] numargs    Variable to store vector number of arguments
234 
235   @return An error code: 0 - success, otherwise - failure
236 
237   @ref Advanced
238 **/
239 
240 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) {
241   *numargs = op->nfields;
242   return 0;
243 }
244 
245 /**
246   @brief Get the setup status of a CeedOperator
247 
248   @param op              CeedOperator
249   @param[out] numelem    Variable to store setup status
250 
251   @return An error code: 0 - success, otherwise - failure
252 
253   @ref Advanced
254 **/
255 
256 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) {
257   *setupdone = op->setupdone;
258   return 0;
259 }
260 
261 /**
262   @brief Get the QFunction associated with a CeedOperator
263 
264   @param op              CeedOperator
265   @param[out] qf         Variable to store qfunction
266 
267   @return An error code: 0 - success, otherwise - failure
268 
269   @ref Advanced
270 **/
271 
272 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
273   *qf = op->qf;
274   return 0;
275 }
276 
277 /**
278   @brief Get the backend data of a CeedOperator
279 
280   @param op              CeedOperator
281   @param[out] data       Variable to store data
282 
283   @return An error code: 0 - success, otherwise - failure
284 
285   @ref Advanced
286 **/
287 
288 int CeedOperatorGetData(CeedOperator op, void* *data) {
289   *data = op->data;
290   return 0;
291 }
292 
293 /**
294   @brief Set the setup flag of a CeedOperator to True
295 
296   @param op              CeedOperator
297 
298   @return An error code: 0 - success, otherwise - failure
299 
300   @ref Advanced
301 **/
302 
303 int CeedOperatorSetSetupDone(CeedOperator op) {
304   op->setupdone = 1;
305   return 0;
306 }
307 
308 /**
309   @brief Get the CeedOperatorFields of a CeedOperator
310 
311   @param op                 CeedOperator
312   @param[out] inputfields   Variable to store inputfields
313   @param[out] outputfields  Variable to store outputfields
314 
315   @return An error code: 0 - success, otherwise - failure
316 
317   @ref Advanced
318 **/
319 
320 int CeedOperatorGetFields(CeedOperator op,
321                           CeedOperatorField* *inputfields,
322                           CeedOperatorField* *outputfields) {
323   if (inputfields) *inputfields = op->inputfields;
324   if (outputfields) *outputfields = op->outputfields;
325   return 0;
326 }
327 
328 /**
329   @brief Get the L vector CeedTransposeMode of a CeedOperatorField
330 
331   @param opfield         CeedOperatorField
332   @param[out] lmode      Variable to store CeedTransposeMode
333 
334   @return An error code: 0 - success, otherwise - failure
335 
336   @ref Advanced
337 **/
338 
339 int CeedOperatorFieldGetLMode(CeedOperatorField opfield,
340                               CeedTransposeMode *lmode) {
341   *lmode = (&opfield)->lmode;
342   return 0;
343 }/**
344   @brief Get the CeedElemRestriction of a CeedOperatorField
345 
346   @param opfield         CeedOperatorField
347   @param[out] rstr       Variable to store CeedElemRestriction
348 
349   @return An error code: 0 - success, otherwise - failure
350 
351   @ref Advanced
352 **/
353 
354 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield,
355                                         CeedElemRestriction *rstr) {
356   *rstr = (&opfield)->Erestrict;
357   return 0;
358 }
359 
360 /**
361   @brief Get the CeedBasis of a CeedOperatorField
362 
363   @param opfield         CeedOperatorField
364   @param[out] basis      Variable to store CeedBasis
365 
366   @return An error code: 0 - success, otherwise - failure
367 
368   @ref Advanced
369 **/
370 
371 int CeedOperatorFieldGetBasis(CeedOperatorField opfield,
372                               CeedBasis *basis) {
373   *basis = (&opfield)->basis;
374   return 0;
375 }
376 
377 /**
378   @brief Get the CeedVector of a CeedOperatorField
379 
380   @param opfield         CeedOperatorField
381   @param[out] vec        Variable to store CeedVector
382 
383   @return An error code: 0 - success, otherwise - failure
384 
385   @ref Advanced
386 **/
387 
388 int CeedOperatorFieldGetVector(CeedOperatorField opfield,
389                                CeedVector *vec) {
390   *vec = (&opfield)->vec;
391   return 0;
392 }
393 
394 /**
395   @brief Destroy a CeedOperator
396 
397   @param op CeedOperator to destroy
398 
399   @return An error code: 0 - success, otherwise - failure
400 
401   @ref Basic
402 **/
403 int CeedOperatorDestroy(CeedOperator *op) {
404   int ierr;
405 
406   if (!*op || --(*op)->refcount > 0) return 0;
407   if ((*op)->Destroy) {
408     ierr = (*op)->Destroy(*op); CeedChk(ierr);
409   }
410   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
411   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
412   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
413   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
414   ierr = CeedFree(op); CeedChk(ierr);
415   return 0;
416 }
417 
418 /// @}
419