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