xref: /libCEED/interface/ceed-qfunction.c (revision 4ce2993fee6e7bc9b86526ee90098d0dc489fc60)
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 <string.h>
19 
20 /// @file
21 /// Implementation of public CeedQFunction interfaces
22 ///
23 /// @addtogroup CeedQFunction
24 /// @{
25 
26 /**
27   @brief Create a CeedQFunction for evaluating interior (volumetric) terms.
28 
29   @param ceed       A Ceed object where the CeedQFunction will be created
30   @param vlength    Vector length.  Caller must ensure that number of quadrature
31                     points is a multiple of vlength.
32   @param f          Function pointer to evaluate action at quadrature points.
33                     See below.
34   @param focca      OCCA identifier "file.c:function_name" for definition of `f`
35   @param[out] qf    Address of the variable where the newly created
36                      CeedQFunction will be stored
37 
38   @return An error code: 0 - success, otherwise - failure
39 
40   The arguments of the call-back 'function' are:
41 
42    1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in
43               the CeedQFunction, set by calling CeedQFunctionSetContext
44 
45    2. [CeedInt nq][in] - number of quadrature points to process
46 
47    3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user
48 
49    4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user
50 
51   @ref Basic
52 **/
53 int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
54                                 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*),
55                                 const char *focca, CeedQFunction *qf) {
56   int ierr;
57   char *focca_copy;
58 
59   if (!ceed->QFunctionCreate) {
60     Ceed delegate;
61     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
62 
63     if (!delegate)
64     return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
65 
66     ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr);
67     return 0;
68   }
69 
70   ierr = CeedCalloc(1,qf); CeedChk(ierr);
71   (*qf)->ceed = ceed;
72   ceed->refcount++;
73   (*qf)->refcount = 1;
74   (*qf)->vlength = vlength;
75   (*qf)->function = f;
76   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
77   strcpy(focca_copy, focca);
78   (*qf)->focca = focca_copy;
79   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
80   return 0;
81 }
82 
83 /**
84   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
85 
86   @param f          CeedQFunctionField
87   @param fieldname  Name of QFunction field
88   @param ncomp      Number of components per quadrature node
89   @param emode      \ref CEED_EVAL_NONE to use values directly,
90                       \ref CEED_EVAL_INTERP to use interpolated values,
91                       \ref CEED_EVAL_GRAD to use gradients.
92 
93   @return An error code: 0 - success, otherwise - failure
94 
95   @ref Developer
96 **/
97 static int CeedQFunctionFieldSet(struct CeedQFunctionField *f,
98                                  const char *fieldname, CeedInt ncomp,
99                                  CeedEvalMode emode) {
100   size_t len = strlen(fieldname);
101   char *tmp;
102   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
103   memcpy(tmp, fieldname, len+1);
104   f->fieldname = tmp;
105   f->ncomp = ncomp;
106   f->emode = emode;
107   return 0;
108 }
109 
110 /**
111   @brief Add a CeedQFunction input
112 
113   @param qf         CeedQFunction
114   @param fieldname  Name of QFunction field
115   @param ncomp      Number of components per quadrature node
116   @param emode      \ref CEED_EVAL_NONE to use values directly,
117                       \ref CEED_EVAL_INTERP to use interpolated values,
118                       \ref CEED_EVAL_GRAD to use gradients.
119 
120   @return An error code: 0 - success, otherwise - failure
121 
122   @ref Basic
123 **/
124 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
125                           CeedInt ncomp, CeedEvalMode emode) {
126   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
127                                    fieldname, ncomp, emode); CeedChk(ierr);
128   return 0;
129 }
130 
131 /**
132   @brief Add a CeedQFunction output
133 
134   @param qf         CeedQFunction
135   @param fieldname  Name of QFunction field
136   @param ncomp      Number of components per quadrature node
137   @param emode      \ref CEED_EVAL_NONE to use values directly,
138                       \ref CEED_EVAL_INTERP to use interpolated values,
139                       \ref CEED_EVAL_GRAD to use gradients.
140 
141   @return An error code: 0 - success, otherwise - failure
142 
143   @ref Basic
144 **/
145 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
146                            CeedInt ncomp, CeedEvalMode emode) {
147   if (emode == CEED_EVAL_WEIGHT)
148     return CeedError(qf->ceed, 1,
149                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
150   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
151                                    fieldname, ncomp, emode); CeedChk(ierr);
152   return 0;
153 }
154 
155 /**
156   @brief Get the Ceed associated with a CeedQFunction
157 
158   @param qf              CeedQFunction
159   @param[out] ceed       Variable to store Ceed
160 
161   @return An error code: 0 - success, otherwise - failure
162 
163   @ref Utility
164 **/
165 
166 int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
167   *ceed = qf->ceed;
168   return 0;
169 }
170 
171 /**
172   @brief Get the vector length of a CeedQFunction
173 
174   @param qf              CeedQFunction
175   @param[out] veclength  Variable to store vector length
176 
177   @return An error code: 0 - success, otherwise - failure
178 
179   @ref Utility
180 **/
181 
182 int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) {
183   *vlength = qf->vlength;
184   return 0;
185 }
186 
187 /**
188   @brief Get the number of inputs and outputs to a CeedQFunction
189 
190   @param qf              CeedQFunction
191   @param[out] numinput   Variable to store number of input fields
192   @param[out] numoutput  Variable to store number of output fields
193 
194   @return An error code: 0 - success, otherwise - failure
195 
196   @ref Utility
197 **/
198 
199 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
200                             CeedInt *numoutput) {
201   if (numinput) *numinput = qf->numinputfields;
202   if (numoutput) *numoutput = qf->numoutputfields;
203   return 0;
204 }
205 
206 /**
207   @brief Get the FOCCA string for a CeedQFunction
208 
209   @param qf              CeedQFunction
210   @param[out] focca      Variable to store focca string
211 
212   @return An error code: 0 - success, otherwise - failure
213 
214   @ref Utility
215 **/
216 
217 int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) {
218   *focca = (char*) qf->focca;
219   return 0;
220 }
221 
222 /**
223   @brief Get global context size for a CeedQFunction
224 
225   @param qf              CeedQFunction
226   @param[out] ctxsize    Variable to store size of context data values
227 
228   @return An error code: 0 - success, otherwise - failure
229 
230   @ref Utility
231 **/
232 
233 int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) {
234   *ctxsize = qf->ctxsize;
235   return 0;
236 }
237 
238 /**
239   @brief Get global context for a CeedQFunction
240 
241   @param qf              CeedQFunction
242   @param[out] ctx        Variable to store context data values
243 
244   @return An error code: 0 - success, otherwise - failure
245 
246   @ref Utility
247 **/
248 
249 int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) {
250   *ctx = qf->ctx;
251   return 0;
252 }
253 
254 /**
255   @brief Get backend data of a CeedQFunction
256 
257   @param qf              CeedQFunction
258   @param[out] data       Variable to store data
259 
260   @return An error code: 0 - success, otherwise - failure
261 
262   @ref Utility
263 **/
264 
265 int CeedQFunctionGetData(CeedQFunction qf, void* *data) {
266   *data = qf->data;
267   return 0;
268 }
269 
270 /**
271   @brief Set global context for a CeedQFunction
272 
273   @param qf       CeedQFunction
274   @param ctx      Context data to set
275   @param ctxsize  Size of context data values
276 
277   @return An error code: 0 - success, otherwise - failure
278 
279   @ref Basic
280 **/
281 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
282   qf->ctx = ctx;
283   qf->ctxsize = ctxsize;
284   return 0;
285 }
286 
287 /**
288   @brief Apply the action of a CeedQFunction
289 
290   @param qf      CeedQFunction
291   @param Q       Number of quadrature points
292   @param[in] u   Array of input data arrays
293   @param[out] v  Array of output data arrays
294 
295   @return An error code: 0 - success, otherwise - failure
296 
297   @ref Advanced
298 **/
299 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
300                        const CeedScalar *const *u,
301                        CeedScalar *const *v) {
302   int ierr;
303   if (!qf->Apply)
304     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
305   if (Q % qf->vlength)
306     return CeedError(qf->ceed, 2,
307                      "Number of quadrature points %d must be a multiple of %d",
308                      Q, qf->vlength);
309   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
310   return 0;
311 }
312 
313 /**
314   @brief Destroy a CeedQFunction
315 
316   @param qf CeedQFunction to destroy
317 
318   @return An error code: 0 - success, otherwise - failure
319 
320   @ref Basic
321 **/
322 int CeedQFunctionDestroy(CeedQFunction *qf) {
323   int ierr;
324 
325   if (!*qf || --(*qf)->refcount > 0) return 0;
326   // Free field names
327   for (int i=0; i<(*qf)->numinputfields; i++) {
328     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
329   }
330   for (int i=0; i<(*qf)->numoutputfields; i++) {
331     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
332   }
333   if ((*qf)->Destroy) {
334     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
335   }
336   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
337   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
338   ierr = CeedFree(qf); CeedChk(ierr);
339   return 0;
340 }
341 
342 /// @}
343