xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision d1bcdac99090efedac6b43fd437855ade149b9cc)
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 = ceed->QFunctionCreate(*qf); CeedChk(ierr);
81   return 0;
82 }
83 
84 /**
85   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
86 
87   @param f          CeedQFunctionField
88   @param fieldname  Name of QFunction field
89   @param ncomp      Number of components per quadrature node
90   @param emode      \ref CEED_EVAL_NONE to use values directly,
91                       \ref CEED_EVAL_INTERP to use interpolated values,
92                       \ref CEED_EVAL_GRAD to use gradients.
93 
94   @return An error code: 0 - success, otherwise - failure
95 
96   @ref Developer
97 **/
98 static int CeedQFunctionFieldSet(CeedQFunctionField *f,
99                                  const char *fieldname, CeedInt ncomp,
100                                  CeedEvalMode emode) {
101   size_t len = strlen(fieldname);
102   char *tmp;
103   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
104   memcpy(tmp, fieldname, len+1);
105   f->fieldname = tmp;
106   f->ncomp = ncomp;
107   f->emode = emode;
108   return 0;
109 }
110 
111 /**
112   @brief Add a CeedQFunction input
113 
114   @param qf         CeedQFunction
115   @param fieldname  Name of QFunction field
116   @param ncomp      Number of components per quadrature node
117   @param emode      \ref CEED_EVAL_NONE to use values directly,
118                       \ref CEED_EVAL_INTERP to use interpolated values,
119                       \ref CEED_EVAL_GRAD to use gradients.
120 
121   @return An error code: 0 - success, otherwise - failure
122 
123   @ref Basic
124 **/
125 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
126                           CeedInt ncomp, CeedEvalMode emode) {
127   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
128                                    fieldname, ncomp, emode); CeedChk(ierr);
129   return 0;
130 }
131 
132 /**
133   @brief Add a CeedQFunction output
134 
135   @param qf         CeedQFunction
136   @param fieldname  Name of QFunction field
137   @param ncomp      Number of components per quadrature node
138   @param emode      \ref CEED_EVAL_NONE to use values directly,
139                       \ref CEED_EVAL_INTERP to use interpolated values,
140                       \ref CEED_EVAL_GRAD to use gradients.
141 
142   @return An error code: 0 - success, otherwise - failure
143 
144   @ref Basic
145 **/
146 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
147                            CeedInt ncomp, CeedEvalMode emode) {
148   if (emode == CEED_EVAL_WEIGHT)
149     return CeedError(qf->ceed, 1,
150                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
151   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
152                                    fieldname, ncomp, emode); CeedChk(ierr);
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 global context size for a CeedQFunction
225 
226   @param qf              CeedQFunction
227   @param[out] ctxsize    Variable to store size of context data values
228 
229   @return An error code: 0 - success, otherwise - failure
230 
231   @ref Advanced
232 **/
233 
234 int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) {
235   *ctxsize = qf->ctxsize;
236   return 0;
237 }
238 
239 /**
240   @brief Get global context for a CeedQFunction
241 
242   @param qf              CeedQFunction
243   @param[out] ctx        Variable to store context data values
244 
245   @return An error code: 0 - success, otherwise - failure
246 
247   @ref Advanced
248 **/
249 
250 int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) {
251   *ctx = qf->ctx;
252   return 0;
253 }
254 
255 /**
256   @brief Get backend data of a CeedQFunction
257 
258   @param qf              CeedQFunction
259   @param[out] data       Variable to store data
260 
261   @return An error code: 0 - success, otherwise - failure
262 
263   @ref Advanced
264 **/
265 
266 int CeedQFunctionGetData(CeedQFunction qf, void* *data) {
267   *data = qf->data;
268   return 0;
269 }
270 
271 /**
272   @brief Set global context for a CeedQFunction
273 
274   @param qf       CeedQFunction
275   @param ctx      Context data to set
276   @param ctxsize  Size of context data values
277 
278   @return An error code: 0 - success, otherwise - failure
279 
280   @ref Basic
281 **/
282 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
283   qf->ctx = ctx;
284   qf->ctxsize = ctxsize;
285   return 0;
286 }
287 
288 /**
289   @brief Apply the action of a CeedQFunction
290 
291   @param qf      CeedQFunction
292   @param Q       Number of quadrature points
293   @param[in] u   Array of input data arrays
294   @param[out] v  Array of output data arrays
295 
296   @return An error code: 0 - success, otherwise - failure
297 
298   @ref Advanced
299 **/
300 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
301                        const CeedScalar *const *u,
302                        CeedScalar *const *v) {
303   int ierr;
304   if (!qf->Apply)
305     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
306   if (Q % qf->vlength)
307     return CeedError(qf->ceed, 2,
308                      "Number of quadrature points %d must be a multiple of %d",
309                      Q, qf->vlength);
310   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
311   return 0;
312 }
313 
314 /**
315   @brief Get the CeedQFunctionFields of a CeedQFunction
316 
317   @param qf                 CeedQFunction
318   @param[out] inputfields   Variable to store inputfields
319   @param[out] outputfields  Variable to store outputfields
320 
321   @return An error code: 0 - success, otherwise - failure
322 
323   @ref Advanced
324 **/
325 
326 int CeedQFunctionGetFields(CeedQFunction qf,
327                            CeedQFunctionField* *inputfields,
328                            CeedQFunctionField* *outputfields) {
329   if (inputfields) *inputfields = qf->inputfields;
330   if (outputfields) *outputfields = qf->outputfields;
331   return 0;
332 }
333 
334 /**
335   @brief Get the number of components of a CeedQFunctionField
336 
337   @param qffield         CeedQFunctionField
338   @param[out] numcomp    Variable to store the number of components
339 
340   @return An error code: 0 - success, otherwise - failure
341 
342   @ref Advanced
343 **/
344 
345 int CeedQFunctionFieldGetNumComponents(CeedQFunctionField qffield,
346                                        CeedInt *numcomp) {
347   *numcomp = (&qffield)->ncomp;
348   return 0;
349 }
350 
351 /**
352   @brief Get the CeedEvalMode of a CeedQFunctionField
353 
354   @param qffield         CeedQFunctionField
355   @param[out] vec        Variable to store the number of components
356 
357   @return An error code: 0 - success, otherwise - failure
358 
359   @ref Advanced
360 **/
361 
362 int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qffield,
363                                CeedEvalMode *emode) {
364   *emode = (&qffield)->emode;
365   return 0;
366 }
367 
368 /**
369   @brief Destroy a CeedQFunction
370 
371   @param qf CeedQFunction to destroy
372 
373   @return An error code: 0 - success, otherwise - failure
374 
375   @ref Basic
376 **/
377 int CeedQFunctionDestroy(CeedQFunction *qf) {
378   int ierr;
379 
380   if (!*qf || --(*qf)->refcount > 0) return 0;
381   // Free field names
382   for (int i=0; i<(*qf)->numinputfields; i++) {
383     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
384   }
385   for (int i=0; i<(*qf)->numoutputfields; i++) {
386     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
387   }
388   if ((*qf)->Destroy) {
389     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
390   }
391   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
392   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
393   ierr = CeedFree(qf); CeedChk(ierr);
394   return 0;
395 }
396 
397 /// @}
398