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