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