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