xref: /libCEED/interface/ceed-operator.c (revision d863ab9ba6a0d47c58445a35d35b36efba07fc93)
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   struct 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 Utility
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 Utility
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 Utility
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 Utility
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 Utility
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 Utility
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 Utility
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 Utility
295 **/
296 
297 int CeedOperatorSetSetupDone(CeedOperator op) {
298   op->setupdone = 1;
299   return 0;
300 }
301 
302 /**
303   @brief Destroy a CeedOperator
304 
305   @param op CeedOperator to destroy
306 
307   @return An error code: 0 - success, otherwise - failure
308 
309   @ref Basic
310 **/
311 int CeedOperatorDestroy(CeedOperator *op) {
312   int ierr;
313 
314   if (!*op || --(*op)->refcount > 0) return 0;
315   if ((*op)->Destroy) {
316     ierr = (*op)->Destroy(*op); CeedChk(ierr);
317   }
318   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
319   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
320   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
321   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
322   ierr = CeedFree(op); CeedChk(ierr);
323   return 0;
324 }
325 
326 /// @}
327