xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision 4ce2993fee6e7bc9b86526ee90098d0dc489fc60)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d7b241e6Sjeremylt #include <string.h>
19d7b241e6Sjeremylt 
20dfdf5a53Sjeremylt /// @file
21dfdf5a53Sjeremylt /// Implementation of public CeedQFunction interfaces
22dfdf5a53Sjeremylt ///
23dfdf5a53Sjeremylt /// @addtogroup CeedQFunction
24dfdf5a53Sjeremylt /// @{
25d7b241e6Sjeremylt 
26d7b241e6Sjeremylt /**
27d7b241e6Sjeremylt   @brief Create a CeedQFunction for evaluating interior (volumetric) terms.
28d7b241e6Sjeremylt 
29b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedQFunction will be created
30d7b241e6Sjeremylt   @param vlength    Vector length.  Caller must ensure that number of quadrature
31d7b241e6Sjeremylt                     points is a multiple of vlength.
32d7b241e6Sjeremylt   @param f          Function pointer to evaluate action at quadrature points.
33d7b241e6Sjeremylt                     See below.
34d7b241e6Sjeremylt   @param focca      OCCA identifier "file.c:function_name" for definition of `f`
35b11c1e72Sjeremylt   @param[out] qf    Address of the variable where the newly created
36b11c1e72Sjeremylt                      CeedQFunction will be stored
37b11c1e72Sjeremylt 
38b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
39d7b241e6Sjeremylt 
40d7b241e6Sjeremylt   The arguments of the call-back 'function' are:
41d7b241e6Sjeremylt 
42d7b241e6Sjeremylt    1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in
43d7b241e6Sjeremylt               the CeedQFunction, set by calling CeedQFunctionSetContext
44d7b241e6Sjeremylt 
45d7b241e6Sjeremylt    2. [CeedInt nq][in] - number of quadrature points to process
46d7b241e6Sjeremylt 
47d7b241e6Sjeremylt    3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user
48d7b241e6Sjeremylt 
49d7b241e6Sjeremylt    4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user
50d7b241e6Sjeremylt 
51dfdf5a53Sjeremylt   @ref Basic
52dfdf5a53Sjeremylt **/
53d7b241e6Sjeremylt int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
54d7b241e6Sjeremylt                                 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*),
55d7b241e6Sjeremylt                                 const char *focca, CeedQFunction *qf) {
56d7b241e6Sjeremylt   int ierr;
57d7b241e6Sjeremylt   char *focca_copy;
58d7b241e6Sjeremylt 
595fe0d4faSjeremylt   if (!ceed->QFunctionCreate) {
605fe0d4faSjeremylt     Ceed delegate;
615fe0d4faSjeremylt     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
625fe0d4faSjeremylt 
635fe0d4faSjeremylt     if (!delegate)
64d7b241e6Sjeremylt     return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
655fe0d4faSjeremylt 
665fe0d4faSjeremylt     ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr);
675fe0d4faSjeremylt     return 0;
685fe0d4faSjeremylt   }
695fe0d4faSjeremylt 
70d7b241e6Sjeremylt   ierr = CeedCalloc(1,qf); CeedChk(ierr);
71d7b241e6Sjeremylt   (*qf)->ceed = ceed;
72d7b241e6Sjeremylt   ceed->refcount++;
73d7b241e6Sjeremylt   (*qf)->refcount = 1;
74d7b241e6Sjeremylt   (*qf)->vlength = vlength;
75d7b241e6Sjeremylt   (*qf)->function = f;
76d7b241e6Sjeremylt   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
77d7b241e6Sjeremylt   strcpy(focca_copy, focca);
78d7b241e6Sjeremylt   (*qf)->focca = focca_copy;
79d7b241e6Sjeremylt   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
80d7b241e6Sjeremylt   return 0;
81d7b241e6Sjeremylt }
82d7b241e6Sjeremylt 
83b11c1e72Sjeremylt /**
84a0a97fcfSJed Brown   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
85b11c1e72Sjeremylt 
86b11c1e72Sjeremylt   @param f          CeedQFunctionField
87b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
88b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
89b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
90b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
91b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
92b11c1e72Sjeremylt 
93b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
94dfdf5a53Sjeremylt 
95dfdf5a53Sjeremylt   @ref Developer
96b11c1e72Sjeremylt **/
97d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f,
98d7b241e6Sjeremylt                                  const char *fieldname, CeedInt ncomp,
99d7b241e6Sjeremylt                                  CeedEvalMode emode) {
100d7b241e6Sjeremylt   size_t len = strlen(fieldname);
101d7b241e6Sjeremylt   char *tmp;
102d7b241e6Sjeremylt   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
103d7b241e6Sjeremylt   memcpy(tmp, fieldname, len+1);
104d7b241e6Sjeremylt   f->fieldname = tmp;
105d7b241e6Sjeremylt   f->ncomp = ncomp;
106d7b241e6Sjeremylt   f->emode = emode;
107d7b241e6Sjeremylt   return 0;
108d7b241e6Sjeremylt }
109d7b241e6Sjeremylt 
110b11c1e72Sjeremylt /**
111a0a97fcfSJed Brown   @brief Add a CeedQFunction input
112b11c1e72Sjeremylt 
113b11c1e72Sjeremylt   @param qf         CeedQFunction
114b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
115b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
116b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
117b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
118b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
119b11c1e72Sjeremylt 
120b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
121dfdf5a53Sjeremylt 
122dfdf5a53Sjeremylt   @ref Basic
123b11c1e72Sjeremylt **/
124d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
125d7b241e6Sjeremylt                           CeedInt ncomp, CeedEvalMode emode) {
126d7b241e6Sjeremylt   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
127d7b241e6Sjeremylt                                    fieldname, ncomp, emode); CeedChk(ierr);
128d7b241e6Sjeremylt   return 0;
129d7b241e6Sjeremylt }
130d7b241e6Sjeremylt 
131b11c1e72Sjeremylt /**
132a0a97fcfSJed Brown   @brief Add a CeedQFunction output
133b11c1e72Sjeremylt 
134b11c1e72Sjeremylt   @param qf         CeedQFunction
135b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
136b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
137b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
138b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
139b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
140b11c1e72Sjeremylt 
141b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
142dfdf5a53Sjeremylt 
143dfdf5a53Sjeremylt   @ref Basic
144b11c1e72Sjeremylt **/
145d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
146d7b241e6Sjeremylt                            CeedInt ncomp, CeedEvalMode emode) {
147d7b241e6Sjeremylt   if (emode == CEED_EVAL_WEIGHT)
148d7b241e6Sjeremylt     return CeedError(qf->ceed, 1,
149d7b241e6Sjeremylt                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
150d7b241e6Sjeremylt   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
151d7b241e6Sjeremylt                                    fieldname, ncomp, emode); CeedChk(ierr);
152d7b241e6Sjeremylt   return 0;
153d7b241e6Sjeremylt }
154d7b241e6Sjeremylt 
155dfdf5a53Sjeremylt /**
156*4ce2993fSjeremylt   @brief Get the Ceed associated with a CeedQFunction
157*4ce2993fSjeremylt 
158*4ce2993fSjeremylt   @param qf              CeedQFunction
159*4ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
160*4ce2993fSjeremylt 
161*4ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
162*4ce2993fSjeremylt 
163*4ce2993fSjeremylt   @ref Utility
164*4ce2993fSjeremylt **/
165*4ce2993fSjeremylt 
166*4ce2993fSjeremylt int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
167*4ce2993fSjeremylt   *ceed = qf->ceed;
168*4ce2993fSjeremylt   return 0;
169*4ce2993fSjeremylt }
170*4ce2993fSjeremylt 
171*4ce2993fSjeremylt /**
172*4ce2993fSjeremylt   @brief Get the vector length of a CeedQFunction
173*4ce2993fSjeremylt 
174*4ce2993fSjeremylt   @param qf              CeedQFunction
175*4ce2993fSjeremylt   @param[out] veclength  Variable to store vector length
176*4ce2993fSjeremylt 
177*4ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
178*4ce2993fSjeremylt 
179*4ce2993fSjeremylt   @ref Utility
180*4ce2993fSjeremylt **/
181*4ce2993fSjeremylt 
182*4ce2993fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) {
183*4ce2993fSjeremylt   *vlength = qf->vlength;
184*4ce2993fSjeremylt   return 0;
185*4ce2993fSjeremylt }
186*4ce2993fSjeremylt 
187*4ce2993fSjeremylt /**
188dfdf5a53Sjeremylt   @brief Get the number of inputs and outputs to a CeedQFunction
189dfdf5a53Sjeremylt 
190dfdf5a53Sjeremylt   @param qf              CeedQFunction
191*4ce2993fSjeremylt   @param[out] numinput   Variable to store number of input fields
192*4ce2993fSjeremylt   @param[out] numoutput  Variable to store number of output fields
193dfdf5a53Sjeremylt 
194dfdf5a53Sjeremylt   @return An error code: 0 - success, otherwise - failure
195dfdf5a53Sjeremylt 
196dfdf5a53Sjeremylt   @ref Utility
197dfdf5a53Sjeremylt **/
198dfdf5a53Sjeremylt 
199d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
200d7b241e6Sjeremylt                             CeedInt *numoutput) {
2011a4ead9bSjeremylt   if (numinput) *numinput = qf->numinputfields;
2021a4ead9bSjeremylt   if (numoutput) *numoutput = qf->numoutputfields;
203d7b241e6Sjeremylt   return 0;
204d7b241e6Sjeremylt }
205d7b241e6Sjeremylt 
206d7b241e6Sjeremylt /**
207*4ce2993fSjeremylt   @brief Get the FOCCA string for a CeedQFunction
208*4ce2993fSjeremylt 
209*4ce2993fSjeremylt   @param qf              CeedQFunction
210*4ce2993fSjeremylt   @param[out] focca      Variable to store focca string
211*4ce2993fSjeremylt 
212*4ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
213*4ce2993fSjeremylt 
214*4ce2993fSjeremylt   @ref Utility
215*4ce2993fSjeremylt **/
216*4ce2993fSjeremylt 
217*4ce2993fSjeremylt int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) {
218*4ce2993fSjeremylt   *focca = (char*) qf->focca;
219*4ce2993fSjeremylt   return 0;
220*4ce2993fSjeremylt }
221*4ce2993fSjeremylt 
222*4ce2993fSjeremylt /**
223*4ce2993fSjeremylt   @brief Get global context size for a CeedQFunction
224*4ce2993fSjeremylt 
225*4ce2993fSjeremylt   @param qf              CeedQFunction
226*4ce2993fSjeremylt   @param[out] ctxsize    Variable to store size of context data values
227*4ce2993fSjeremylt 
228*4ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
229*4ce2993fSjeremylt 
230*4ce2993fSjeremylt   @ref Utility
231*4ce2993fSjeremylt **/
232*4ce2993fSjeremylt 
233*4ce2993fSjeremylt int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) {
234*4ce2993fSjeremylt   *ctxsize = qf->ctxsize;
235*4ce2993fSjeremylt   return 0;
236*4ce2993fSjeremylt }
237*4ce2993fSjeremylt 
238*4ce2993fSjeremylt /**
239*4ce2993fSjeremylt   @brief Get global context for a CeedQFunction
240*4ce2993fSjeremylt 
241*4ce2993fSjeremylt   @param qf              CeedQFunction
242*4ce2993fSjeremylt   @param[out] ctx        Variable to store context data values
243*4ce2993fSjeremylt 
244*4ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
245*4ce2993fSjeremylt 
246*4ce2993fSjeremylt   @ref Utility
247*4ce2993fSjeremylt **/
248*4ce2993fSjeremylt 
249*4ce2993fSjeremylt int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) {
250*4ce2993fSjeremylt   *ctx = qf->ctx;
251*4ce2993fSjeremylt   return 0;
252*4ce2993fSjeremylt }
253*4ce2993fSjeremylt 
254*4ce2993fSjeremylt /**
255*4ce2993fSjeremylt   @brief Get backend data of a CeedQFunction
256*4ce2993fSjeremylt 
257*4ce2993fSjeremylt   @param qf              CeedQFunction
258*4ce2993fSjeremylt   @param[out] data       Variable to store data
259*4ce2993fSjeremylt 
260*4ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
261*4ce2993fSjeremylt 
262*4ce2993fSjeremylt   @ref Utility
263*4ce2993fSjeremylt **/
264*4ce2993fSjeremylt 
265*4ce2993fSjeremylt int CeedQFunctionGetData(CeedQFunction qf, void* *data) {
266*4ce2993fSjeremylt   *data = qf->data;
267*4ce2993fSjeremylt   return 0;
268*4ce2993fSjeremylt }
269*4ce2993fSjeremylt 
270*4ce2993fSjeremylt /**
271*4ce2993fSjeremylt   @brief Set global context for a CeedQFunction
272b11c1e72Sjeremylt 
273b11c1e72Sjeremylt   @param qf       CeedQFunction
274b11c1e72Sjeremylt   @param ctx      Context data to set
275b11c1e72Sjeremylt   @param ctxsize  Size of context data values
276b11c1e72Sjeremylt 
277b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
278dfdf5a53Sjeremylt 
279dfdf5a53Sjeremylt   @ref Basic
280b11c1e72Sjeremylt **/
281d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
282d7b241e6Sjeremylt   qf->ctx = ctx;
283d7b241e6Sjeremylt   qf->ctxsize = ctxsize;
284d7b241e6Sjeremylt   return 0;
285d7b241e6Sjeremylt }
286d7b241e6Sjeremylt 
287b11c1e72Sjeremylt /**
288b11c1e72Sjeremylt   @brief Apply the action of a CeedQFunction
289b11c1e72Sjeremylt 
290b11c1e72Sjeremylt   @param qf      CeedQFunction
291b11c1e72Sjeremylt   @param Q       Number of quadrature points
292b11c1e72Sjeremylt   @param[in] u   Array of input data arrays
293b11c1e72Sjeremylt   @param[out] v  Array of output data arrays
294b11c1e72Sjeremylt 
295b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
296dfdf5a53Sjeremylt 
297dfdf5a53Sjeremylt   @ref Advanced
298b11c1e72Sjeremylt **/
299d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
300d7b241e6Sjeremylt                        const CeedScalar *const *u,
301d7b241e6Sjeremylt                        CeedScalar *const *v) {
302d7b241e6Sjeremylt   int ierr;
303d7b241e6Sjeremylt   if (!qf->Apply)
304d7b241e6Sjeremylt     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
305d7b241e6Sjeremylt   if (Q % qf->vlength)
306d7b241e6Sjeremylt     return CeedError(qf->ceed, 2,
307d7b241e6Sjeremylt                      "Number of quadrature points %d must be a multiple of %d",
308d7b241e6Sjeremylt                      Q, qf->vlength);
309d7b241e6Sjeremylt   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
310d7b241e6Sjeremylt   return 0;
311d7b241e6Sjeremylt }
312d7b241e6Sjeremylt 
313b11c1e72Sjeremylt /**
314b11c1e72Sjeremylt   @brief Destroy a CeedQFunction
315b11c1e72Sjeremylt 
316b11c1e72Sjeremylt   @param qf CeedQFunction to destroy
317b11c1e72Sjeremylt 
318b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
319dfdf5a53Sjeremylt 
320dfdf5a53Sjeremylt   @ref Basic
321b11c1e72Sjeremylt **/
322d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
323d7b241e6Sjeremylt   int ierr;
324d7b241e6Sjeremylt 
325d7b241e6Sjeremylt   if (!*qf || --(*qf)->refcount > 0) return 0;
326d7b241e6Sjeremylt   // Free field names
327d7b241e6Sjeremylt   for (int i=0; i<(*qf)->numinputfields; i++) {
328d7b241e6Sjeremylt     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
329d7b241e6Sjeremylt   }
330d7b241e6Sjeremylt   for (int i=0; i<(*qf)->numoutputfields; i++) {
331d7b241e6Sjeremylt     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
332d7b241e6Sjeremylt   }
333d7b241e6Sjeremylt   if ((*qf)->Destroy) {
334d7b241e6Sjeremylt     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
335d7b241e6Sjeremylt   }
336d7b241e6Sjeremylt   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
337d7b241e6Sjeremylt   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
338d7b241e6Sjeremylt   ierr = CeedFree(qf); CeedChk(ierr);
339d7b241e6Sjeremylt   return 0;
340d7b241e6Sjeremylt }
341d7b241e6Sjeremylt 
342d7b241e6Sjeremylt /// @}
343