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