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