xref: /libCEED/interface/ceed-qfunction.c (revision 856142e1b942abfda690c8495da63ec0cf28a439)
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 CeedQFunction interfaces
23 ///
24 /// @addtogroup CeedQFunction
25 /// @{
26 
27 /**
28   @brief Create a CeedQFunction for evaluating interior (volumetric) terms.
29 
30   @param ceed       A Ceed object where the CeedQFunction will be created
31   @param vlength    Vector length.  Caller must ensure that number of quadrature
32                     points is a multiple of vlength.
33   @param f          Function pointer to evaluate action at quadrature points.
34                     See \ref CeedQFunctionUser.
35   @param focca      OCCA identifier "file.c:function_name" for definition of `f`
36   @param[out] qf    Address of the variable where the newly created
37                      CeedQFunction will be stored
38 
39   @return An error code: 0 - success, otherwise - failure
40 
41   See \ref CeedQFunctionUser for details on the call-back function @a f's arguments.
42 
43   @ref Basic
44 **/
45 int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
46                                 CeedQFunctionUser f,
47                                 const char *focca, CeedQFunction *qf) {
48   int ierr;
49   char *focca_copy;
50 
51   if (!ceed->QFunctionCreate) {
52     Ceed delegate;
53     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
54 
55     if (!delegate)
56       return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
57 
58     ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf);
59     CeedChk(ierr);
60     return 0;
61   }
62 
63   ierr = CeedCalloc(1,qf); CeedChk(ierr);
64   (*qf)->ceed = ceed;
65   ceed->refcount++;
66   (*qf)->refcount = 1;
67   (*qf)->vlength = vlength;
68   (*qf)->function = f;
69   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
70   strcpy(focca_copy, focca);
71   (*qf)->focca = focca_copy;
72   ierr = CeedCalloc(16, &(*qf)->inputfields); CeedChk(ierr);
73   ierr = CeedCalloc(16, &(*qf)->outputfields); CeedChk(ierr);
74   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
75   return 0;
76 }
77 
78 /**
79   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
80 
81   @param f          CeedQFunctionField
82   @param fieldname  Name of QFunction field
83   @param ncomp      Number of components per quadrature node
84   @param emode      \ref CEED_EVAL_NONE to use values directly,
85                       \ref CEED_EVAL_INTERP to use interpolated values,
86                       \ref CEED_EVAL_GRAD to use gradients.
87 
88   @return An error code: 0 - success, otherwise - failure
89 
90   @ref Developer
91 **/
92 static int CeedQFunctionFieldSet(CeedQFunctionField *f,const char *fieldname,
93                                  CeedInt ncomp, CeedEvalMode emode) {
94   size_t len = strlen(fieldname);
95   char *tmp;
96   int ierr;
97   ierr = CeedCalloc(1,f); CeedChk(ierr);
98 
99   ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr);
100   memcpy(tmp, fieldname, len+1);
101   (*f)->fieldname = tmp;
102   (*f)->ncomp = ncomp;
103   (*f)->emode = emode;
104   return 0;
105 }
106 
107 /**
108   @brief Add a CeedQFunction input
109 
110   @param qf         CeedQFunction
111   @param fieldname  Name of QFunction field
112   @param ncomp      Number of components per quadrature node
113   @param emode      \ref CEED_EVAL_NONE to use values directly,
114                       \ref CEED_EVAL_INTERP to use interpolated values,
115                       \ref CEED_EVAL_GRAD to use gradients.
116 
117   @return An error code: 0 - success, otherwise - failure
118 
119   @ref Basic
120 **/
121 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
122                           CeedInt ncomp, CeedEvalMode emode) {
123   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields],
124                                    fieldname, ncomp, emode);
125   CeedChk(ierr);
126   qf->numinputfields++;
127   return 0;
128 }
129 
130 /**
131   @brief Add a CeedQFunction output
132 
133   @param qf         CeedQFunction
134   @param fieldname  Name of QFunction field
135   @param ncomp      Number of components per quadrature node
136   @param emode      \ref CEED_EVAL_NONE to use values directly,
137                       \ref CEED_EVAL_INTERP to use interpolated values,
138                       \ref CEED_EVAL_GRAD to use gradients.
139 
140   @return An error code: 0 - success, otherwise - failure
141 
142   @ref Basic
143 **/
144 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
145                            CeedInt ncomp, CeedEvalMode emode) {
146   if (emode == CEED_EVAL_WEIGHT)
147     return CeedError(qf->ceed, 1,
148                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
149   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields],
150                                    fieldname, ncomp, emode);
151   CeedChk(ierr);
152   qf->numoutputfields++;
153   return 0;
154 }
155 
156 /**
157   @brief Get the Ceed associated with a CeedQFunction
158 
159   @param qf              CeedQFunction
160   @param[out] ceed       Variable to store Ceed
161 
162   @return An error code: 0 - success, otherwise - failure
163 
164   @ref Advanced
165 **/
166 
167 int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
168   *ceed = qf->ceed;
169   return 0;
170 }
171 
172 /**
173   @brief Get the vector length of a CeedQFunction
174 
175   @param qf              CeedQFunction
176   @param[out] veclength  Variable to store vector length
177 
178   @return An error code: 0 - success, otherwise - failure
179 
180   @ref Advanced
181 **/
182 
183 int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) {
184   *vlength = qf->vlength;
185   return 0;
186 }
187 
188 /**
189   @brief Get the number of inputs and outputs to a CeedQFunction
190 
191   @param qf              CeedQFunction
192   @param[out] numinput   Variable to store number of input fields
193   @param[out] numoutput  Variable to store number of output fields
194 
195   @return An error code: 0 - success, otherwise - failure
196 
197   @ref Advanced
198 **/
199 
200 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
201                             CeedInt *numoutput) {
202   if (numinput) *numinput = qf->numinputfields;
203   if (numoutput) *numoutput = qf->numoutputfields;
204   return 0;
205 }
206 
207 /**
208   @brief Get the FOCCA string for a CeedQFunction
209 
210   @param qf              CeedQFunction
211   @param[out] focca      Variable to store focca string
212 
213   @return An error code: 0 - success, otherwise - failure
214 
215   @ref Advanced
216 **/
217 
218 int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) {
219   *focca = (char*) qf->focca;
220   return 0;
221 }
222 
223 /**
224   @brief Get the User Function for a CeedQFunction
225 
226   @param qf              CeedQFunction
227   @param[out] f          Variable to store user function
228 
229   @return An error code: 0 - success, otherwise - failure
230 
231   @ref Advanced
232 **/
233 
234 int CeedQFunctionGetUserFunction(CeedQFunction qf, int (**f)()) {
235   *f = (int (*)())qf->function;
236   return 0;
237 }
238 
239 /**
240   @brief Get global context size for a CeedQFunction
241 
242   @param qf              CeedQFunction
243   @param[out] ctxsize    Variable to store size of context data values
244 
245   @return An error code: 0 - success, otherwise - failure
246 
247   @ref Advanced
248 **/
249 
250 int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) {
251   if (qf->fortranstatus) {
252     fContext *fctx = qf->ctx;
253     *ctxsize = fctx->innerctxsize;
254   } else {
255     *ctxsize = qf->ctxsize;
256   }
257   return 0;
258 }
259 
260 /**
261   @brief Get global context for a CeedQFunction
262 
263   @param qf              CeedQFunction
264   @param[out] ctx        Variable to store context data values
265 
266   @return An error code: 0 - success, otherwise - failure
267 
268   @ref Advanced
269 **/
270 
271 int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) {
272   *ctx = qf->ctx;
273   return 0;
274 }
275 
276 /**
277   @brief Determine if Fortran interface was used
278 
279   @param qf                  CeedQFunction
280   @param[out] fortranstatus  Variable to store Fortran status
281 
282   @return An error code: 0 - success, otherwise - failure
283 
284   @ref Advanced
285 **/
286 
287 int CeedQFunctionGetFortranStatus(CeedQFunction qf, bool *fortranstatus) {
288   *fortranstatus = qf->fortranstatus;
289   return 0;
290 }
291 
292 /**
293   @brief Get true user context for a CeedQFunction
294 
295   @param qf              CeedQFunction
296   @param[out] ctx        Variable to store context data values
297 
298   @return An error code: 0 - success, otherwise - failure
299 
300   @ref Advanced
301 **/
302 
303 int CeedQFunctionGetInnerContext(CeedQFunction qf, void* *ctx) {
304   if (qf->fortranstatus) {
305     fContext *fctx = qf->ctx;
306     *ctx = fctx->innerctx;
307   } else {
308     *ctx = qf->ctx;
309   }
310 
311 
312   return 0;
313 }
314 
315 /**
316   @brief Get backend data of a CeedQFunction
317 
318   @param qf              CeedQFunction
319   @param[out] data       Variable to store data
320 
321   @return An error code: 0 - success, otherwise - failure
322 
323   @ref Advanced
324 **/
325 
326 int CeedQFunctionGetData(CeedQFunction qf, void* *data) {
327   *data = qf->data;
328   return 0;
329 }
330 
331 /**
332   @brief Set backend data of a CeedQFunction
333 
334   @param[out] qf         CeedQFunction
335   @param data            Data to set
336 
337   @return An error code: 0 - success, otherwise - failure
338 
339   @ref Advanced
340 **/
341 
342 int CeedQFunctionSetData(CeedQFunction qf, void* *data) {
343   qf->data = *data;
344   return 0;
345 }
346 
347 /**
348   @brief Set global context for a CeedQFunction
349 
350   @param qf       CeedQFunction
351   @param ctx      Context data to set
352   @param ctxsize  Size of context data values
353 
354   @return An error code: 0 - success, otherwise - failure
355 
356   @ref Basic
357 **/
358 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
359   qf->ctx = ctx;
360   qf->ctxsize = ctxsize;
361   return 0;
362 }
363 
364 /**
365   @brief Apply the action of a CeedQFunction
366 
367   @param qf      CeedQFunction
368   @param Q       Number of quadrature points
369   @param[in] u   Array of input data arrays
370   @param[out] v  Array of output data arrays
371 
372   @return An error code: 0 - success, otherwise - failure
373 
374   @ref Advanced
375 **/
376 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
377                        CeedVector* u, CeedVector* v) {
378   int ierr;
379   if (!qf->Apply)
380     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
381   if (Q % qf->vlength)
382     return CeedError(qf->ceed, 2,
383                      "Number of quadrature points %d must be a multiple of %d",
384                      Q, qf->vlength);
385   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
386   return 0;
387 }
388 
389 /**
390   @brief Get the CeedQFunctionFields of a CeedQFunction
391 
392   @param qf                 CeedQFunction
393   @param[out] inputfields   Variable to store inputfields
394   @param[out] outputfields  Variable to store outputfields
395 
396   @return An error code: 0 - success, otherwise - failure
397 
398   @ref Advanced
399 **/
400 
401 int CeedQFunctionGetFields(CeedQFunction qf,
402                            CeedQFunctionField* *inputfields,
403                            CeedQFunctionField* *outputfields) {
404   if (inputfields) *inputfields = qf->inputfields;
405   if (outputfields) *outputfields = qf->outputfields;
406   return 0;
407 }
408 
409 /**
410   @brief Get the name of a CeedQFunctionField
411 
412   @param qffield         CeedQFunctionField
413   @param[out] fieldname  Variable to store the field name
414 
415   @return An error code: 0 - success, otherwise - failure
416 
417   @ref Advanced
418 **/
419 
420 int CeedQFunctionFieldGetName(CeedQFunctionField qffield,
421                               char* *fieldname) {
422   *fieldname = (char *)qffield->fieldname;
423   return 0;
424 }
425 
426 /**
427   @brief Get the number of components of a CeedQFunctionField
428 
429   @param qffield         CeedQFunctionField
430   @param[out] numcomp    Variable to store the number of components
431 
432   @return An error code: 0 - success, otherwise - failure
433 
434   @ref Advanced
435 **/
436 
437 int CeedQFunctionFieldGetNumComponents(CeedQFunctionField qffield,
438                                        CeedInt *numcomp) {
439   *numcomp = qffield->ncomp;
440   return 0;
441 }
442 
443 /**
444   @brief Get the CeedEvalMode of a CeedQFunctionField
445 
446   @param qffield         CeedQFunctionField
447   @param[out] vec        Variable to store the number of components
448 
449   @return An error code: 0 - success, otherwise - failure
450 
451   @ref Advanced
452 **/
453 
454 int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qffield,
455                                   CeedEvalMode *emode) {
456   *emode = qffield->emode;
457   return 0;
458 }
459 
460 /**
461   @brief Destroy a CeedQFunction
462 
463   @param qf CeedQFunction to destroy
464 
465   @return An error code: 0 - success, otherwise - failure
466 
467   @ref Basic
468 **/
469 int CeedQFunctionDestroy(CeedQFunction *qf) {
470   int ierr;
471 
472   if (!*qf || --(*qf)->refcount > 0) return 0;
473   // Backend destroy
474   if ((*qf)->Destroy) {
475     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
476   }
477   // Free fields
478   for (int i=0; i<(*qf)->numinputfields; i++) {
479     ierr = CeedFree(&(*(*qf)->inputfields[i]).fieldname); CeedChk(ierr);
480     ierr = CeedFree(&(*qf)->inputfields[i]); CeedChk(ierr);
481   }
482   for (int i=0; i<(*qf)->numoutputfields; i++) {
483     ierr = CeedFree(&(*(*qf)->outputfields[i]).fieldname); CeedChk(ierr);
484     ierr = CeedFree(&(*qf)->outputfields[i]); CeedChk(ierr);
485   }
486   ierr = CeedFree(&(*qf)->inputfields); CeedChk(ierr);
487   ierr = CeedFree(&(*qf)->outputfields); CeedChk(ierr);
488 
489   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
490   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
491   ierr = CeedFree(qf); CeedChk(ierr);
492   return 0;
493 }
494 
495 /// @}
496