xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision 23617272b99b7e9f8a74525161c55d44882cf4b4)
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>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt #include <string.h>
20d7b241e6Sjeremylt 
21dfdf5a53Sjeremylt /// @file
22dfdf5a53Sjeremylt /// Implementation of public CeedQFunction interfaces
23dfdf5a53Sjeremylt ///
24dfdf5a53Sjeremylt /// @addtogroup CeedQFunction
25dfdf5a53Sjeremylt /// @{
26d7b241e6Sjeremylt 
27d7b241e6Sjeremylt /**
28d7b241e6Sjeremylt   @brief Create a CeedQFunction for evaluating interior (volumetric) terms.
29d7b241e6Sjeremylt 
30b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedQFunction will be created
31d7b241e6Sjeremylt   @param vlength    Vector length.  Caller must ensure that number of quadrature
32d7b241e6Sjeremylt                     points is a multiple of vlength.
33d7b241e6Sjeremylt   @param f          Function pointer to evaluate action at quadrature points.
34d7b241e6Sjeremylt                     See below.
35d7b241e6Sjeremylt   @param focca      OCCA identifier "file.c:function_name" for definition of `f`
36b11c1e72Sjeremylt   @param[out] qf    Address of the variable where the newly created
37b11c1e72Sjeremylt                      CeedQFunction will be stored
38b11c1e72Sjeremylt 
39b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
40d7b241e6Sjeremylt 
41d7b241e6Sjeremylt   The arguments of the call-back 'function' are:
42d7b241e6Sjeremylt 
43d7b241e6Sjeremylt    1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in
44d7b241e6Sjeremylt               the CeedQFunction, set by calling CeedQFunctionSetContext
45d7b241e6Sjeremylt 
46d7b241e6Sjeremylt    2. [CeedInt nq][in] - number of quadrature points to process
47d7b241e6Sjeremylt 
48d7b241e6Sjeremylt    3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user
49d7b241e6Sjeremylt 
50d7b241e6Sjeremylt    4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user
51d7b241e6Sjeremylt 
52dfdf5a53Sjeremylt   @ref Basic
53dfdf5a53Sjeremylt **/
54d7b241e6Sjeremylt int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
55d7b241e6Sjeremylt                                 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*),
56d7b241e6Sjeremylt                                 const char *focca, CeedQFunction *qf) {
57d7b241e6Sjeremylt   int ierr;
58d7b241e6Sjeremylt   char *focca_copy;
59d7b241e6Sjeremylt 
605fe0d4faSjeremylt   if (!ceed->QFunctionCreate) {
615fe0d4faSjeremylt     Ceed delegate;
625fe0d4faSjeremylt     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
635fe0d4faSjeremylt 
645fe0d4faSjeremylt     if (!delegate)
65d7b241e6Sjeremylt     return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
665fe0d4faSjeremylt 
675fe0d4faSjeremylt     ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr);
685fe0d4faSjeremylt     return 0;
695fe0d4faSjeremylt   }
705fe0d4faSjeremylt 
71d7b241e6Sjeremylt   ierr = CeedCalloc(1,qf); CeedChk(ierr);
72d7b241e6Sjeremylt   (*qf)->ceed = ceed;
73d7b241e6Sjeremylt   ceed->refcount++;
74d7b241e6Sjeremylt   (*qf)->refcount = 1;
75d7b241e6Sjeremylt   (*qf)->vlength = vlength;
76d7b241e6Sjeremylt   (*qf)->function = f;
77d7b241e6Sjeremylt   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
78d7b241e6Sjeremylt   strcpy(focca_copy, focca);
79d7b241e6Sjeremylt   (*qf)->focca = focca_copy;
80d7b241e6Sjeremylt   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
81d7b241e6Sjeremylt   return 0;
82d7b241e6Sjeremylt }
83d7b241e6Sjeremylt 
84b11c1e72Sjeremylt /**
85a0a97fcfSJed Brown   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
86b11c1e72Sjeremylt 
87b11c1e72Sjeremylt   @param f          CeedQFunctionField
88b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
89b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
90b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
91b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
92b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
93b11c1e72Sjeremylt 
94b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
95dfdf5a53Sjeremylt 
96dfdf5a53Sjeremylt   @ref Developer
97b11c1e72Sjeremylt **/
98d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f,
99d7b241e6Sjeremylt                                  const char *fieldname, CeedInt ncomp,
100d7b241e6Sjeremylt                                  CeedEvalMode emode) {
101d7b241e6Sjeremylt   size_t len = strlen(fieldname);
102d7b241e6Sjeremylt   char *tmp;
103d7b241e6Sjeremylt   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
104d7b241e6Sjeremylt   memcpy(tmp, fieldname, len+1);
105d7b241e6Sjeremylt   f->fieldname = tmp;
106d7b241e6Sjeremylt   f->ncomp = ncomp;
107d7b241e6Sjeremylt   f->emode = emode;
108d7b241e6Sjeremylt   return 0;
109d7b241e6Sjeremylt }
110d7b241e6Sjeremylt 
111b11c1e72Sjeremylt /**
112a0a97fcfSJed Brown   @brief Add a CeedQFunction input
113b11c1e72Sjeremylt 
114b11c1e72Sjeremylt   @param qf         CeedQFunction
115b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
116b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
117b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
118b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
119b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
120b11c1e72Sjeremylt 
121b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
122dfdf5a53Sjeremylt 
123dfdf5a53Sjeremylt   @ref Basic
124b11c1e72Sjeremylt **/
125d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
126d7b241e6Sjeremylt                           CeedInt ncomp, CeedEvalMode emode) {
127d7b241e6Sjeremylt   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
128d7b241e6Sjeremylt                                    fieldname, ncomp, emode); CeedChk(ierr);
129d7b241e6Sjeremylt   return 0;
130d7b241e6Sjeremylt }
131d7b241e6Sjeremylt 
132b11c1e72Sjeremylt /**
133a0a97fcfSJed Brown   @brief Add a CeedQFunction output
134b11c1e72Sjeremylt 
135b11c1e72Sjeremylt   @param qf         CeedQFunction
136b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
137b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
138b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
139b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
140b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
141b11c1e72Sjeremylt 
142b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
143dfdf5a53Sjeremylt 
144dfdf5a53Sjeremylt   @ref Basic
145b11c1e72Sjeremylt **/
146d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
147d7b241e6Sjeremylt                            CeedInt ncomp, CeedEvalMode emode) {
148d7b241e6Sjeremylt   if (emode == CEED_EVAL_WEIGHT)
149d7b241e6Sjeremylt     return CeedError(qf->ceed, 1,
150d7b241e6Sjeremylt                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
151d7b241e6Sjeremylt   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
152d7b241e6Sjeremylt                                    fieldname, ncomp, emode); CeedChk(ierr);
153d7b241e6Sjeremylt   return 0;
154d7b241e6Sjeremylt }
155d7b241e6Sjeremylt 
156dfdf5a53Sjeremylt /**
1574ce2993fSjeremylt   @brief Get the Ceed associated with a CeedQFunction
1584ce2993fSjeremylt 
1594ce2993fSjeremylt   @param qf              CeedQFunction
1604ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
1614ce2993fSjeremylt 
1624ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
1634ce2993fSjeremylt 
164*23617272Sjeremylt   @ref Advanced
1654ce2993fSjeremylt **/
1664ce2993fSjeremylt 
1674ce2993fSjeremylt int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
1684ce2993fSjeremylt   *ceed = qf->ceed;
1694ce2993fSjeremylt   return 0;
1704ce2993fSjeremylt }
1714ce2993fSjeremylt 
1724ce2993fSjeremylt /**
1734ce2993fSjeremylt   @brief Get the vector length of a CeedQFunction
1744ce2993fSjeremylt 
1754ce2993fSjeremylt   @param qf              CeedQFunction
1764ce2993fSjeremylt   @param[out] veclength  Variable to store vector length
1774ce2993fSjeremylt 
1784ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
1794ce2993fSjeremylt 
180*23617272Sjeremylt   @ref Advanced
1814ce2993fSjeremylt **/
1824ce2993fSjeremylt 
1834ce2993fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) {
1844ce2993fSjeremylt   *vlength = qf->vlength;
1854ce2993fSjeremylt   return 0;
1864ce2993fSjeremylt }
1874ce2993fSjeremylt 
1884ce2993fSjeremylt /**
189dfdf5a53Sjeremylt   @brief Get the number of inputs and outputs to a CeedQFunction
190dfdf5a53Sjeremylt 
191dfdf5a53Sjeremylt   @param qf              CeedQFunction
1924ce2993fSjeremylt   @param[out] numinput   Variable to store number of input fields
1934ce2993fSjeremylt   @param[out] numoutput  Variable to store number of output fields
194dfdf5a53Sjeremylt 
195dfdf5a53Sjeremylt   @return An error code: 0 - success, otherwise - failure
196dfdf5a53Sjeremylt 
197*23617272Sjeremylt   @ref Advanced
198dfdf5a53Sjeremylt **/
199dfdf5a53Sjeremylt 
200d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
201d7b241e6Sjeremylt                             CeedInt *numoutput) {
2021a4ead9bSjeremylt   if (numinput) *numinput = qf->numinputfields;
2031a4ead9bSjeremylt   if (numoutput) *numoutput = qf->numoutputfields;
204d7b241e6Sjeremylt   return 0;
205d7b241e6Sjeremylt }
206d7b241e6Sjeremylt 
207d7b241e6Sjeremylt /**
2084ce2993fSjeremylt   @brief Get the FOCCA string for a CeedQFunction
2094ce2993fSjeremylt 
2104ce2993fSjeremylt   @param qf              CeedQFunction
2114ce2993fSjeremylt   @param[out] focca      Variable to store focca string
2124ce2993fSjeremylt 
2134ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2144ce2993fSjeremylt 
215*23617272Sjeremylt   @ref Advanced
2164ce2993fSjeremylt **/
2174ce2993fSjeremylt 
2184ce2993fSjeremylt int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) {
2194ce2993fSjeremylt   *focca = (char*) qf->focca;
2204ce2993fSjeremylt   return 0;
2214ce2993fSjeremylt }
2224ce2993fSjeremylt 
2234ce2993fSjeremylt /**
2244ce2993fSjeremylt   @brief Get global context size for a CeedQFunction
2254ce2993fSjeremylt 
2264ce2993fSjeremylt   @param qf              CeedQFunction
2274ce2993fSjeremylt   @param[out] ctxsize    Variable to store size of context data values
2284ce2993fSjeremylt 
2294ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2304ce2993fSjeremylt 
231*23617272Sjeremylt   @ref Advanced
2324ce2993fSjeremylt **/
2334ce2993fSjeremylt 
2344ce2993fSjeremylt int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) {
2354ce2993fSjeremylt   *ctxsize = qf->ctxsize;
2364ce2993fSjeremylt   return 0;
2374ce2993fSjeremylt }
2384ce2993fSjeremylt 
2394ce2993fSjeremylt /**
2404ce2993fSjeremylt   @brief Get global context for a CeedQFunction
2414ce2993fSjeremylt 
2424ce2993fSjeremylt   @param qf              CeedQFunction
2434ce2993fSjeremylt   @param[out] ctx        Variable to store context data values
2444ce2993fSjeremylt 
2454ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2464ce2993fSjeremylt 
247*23617272Sjeremylt   @ref Advanced
2484ce2993fSjeremylt **/
2494ce2993fSjeremylt 
2504ce2993fSjeremylt int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) {
2514ce2993fSjeremylt   *ctx = qf->ctx;
2524ce2993fSjeremylt   return 0;
2534ce2993fSjeremylt }
2544ce2993fSjeremylt 
2554ce2993fSjeremylt /**
2564ce2993fSjeremylt   @brief Get backend data of a CeedQFunction
2574ce2993fSjeremylt 
2584ce2993fSjeremylt   @param qf              CeedQFunction
2594ce2993fSjeremylt   @param[out] data       Variable to store data
2604ce2993fSjeremylt 
2614ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2624ce2993fSjeremylt 
263*23617272Sjeremylt   @ref Advanced
2644ce2993fSjeremylt **/
2654ce2993fSjeremylt 
2664ce2993fSjeremylt int CeedQFunctionGetData(CeedQFunction qf, void* *data) {
2674ce2993fSjeremylt   *data = qf->data;
2684ce2993fSjeremylt   return 0;
2694ce2993fSjeremylt }
2704ce2993fSjeremylt 
2714ce2993fSjeremylt /**
2724ce2993fSjeremylt   @brief Set global context for a CeedQFunction
273b11c1e72Sjeremylt 
274b11c1e72Sjeremylt   @param qf       CeedQFunction
275b11c1e72Sjeremylt   @param ctx      Context data to set
276b11c1e72Sjeremylt   @param ctxsize  Size of context data values
277b11c1e72Sjeremylt 
278b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
279dfdf5a53Sjeremylt 
280dfdf5a53Sjeremylt   @ref Basic
281b11c1e72Sjeremylt **/
282d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
283d7b241e6Sjeremylt   qf->ctx = ctx;
284d7b241e6Sjeremylt   qf->ctxsize = ctxsize;
285d7b241e6Sjeremylt   return 0;
286d7b241e6Sjeremylt }
287d7b241e6Sjeremylt 
288b11c1e72Sjeremylt /**
289b11c1e72Sjeremylt   @brief Apply the action of a CeedQFunction
290b11c1e72Sjeremylt 
291b11c1e72Sjeremylt   @param qf      CeedQFunction
292b11c1e72Sjeremylt   @param Q       Number of quadrature points
293b11c1e72Sjeremylt   @param[in] u   Array of input data arrays
294b11c1e72Sjeremylt   @param[out] v  Array of output data arrays
295b11c1e72Sjeremylt 
296b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
297dfdf5a53Sjeremylt 
298dfdf5a53Sjeremylt   @ref Advanced
299b11c1e72Sjeremylt **/
300d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
301d7b241e6Sjeremylt                        const CeedScalar *const *u,
302d7b241e6Sjeremylt                        CeedScalar *const *v) {
303d7b241e6Sjeremylt   int ierr;
304d7b241e6Sjeremylt   if (!qf->Apply)
305d7b241e6Sjeremylt     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
306d7b241e6Sjeremylt   if (Q % qf->vlength)
307d7b241e6Sjeremylt     return CeedError(qf->ceed, 2,
308d7b241e6Sjeremylt                      "Number of quadrature points %d must be a multiple of %d",
309d7b241e6Sjeremylt                      Q, qf->vlength);
310d7b241e6Sjeremylt   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
311d7b241e6Sjeremylt   return 0;
312d7b241e6Sjeremylt }
313d7b241e6Sjeremylt 
314b11c1e72Sjeremylt /**
315b11c1e72Sjeremylt   @brief Destroy a CeedQFunction
316b11c1e72Sjeremylt 
317b11c1e72Sjeremylt   @param qf CeedQFunction to destroy
318b11c1e72Sjeremylt 
319b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
320dfdf5a53Sjeremylt 
321dfdf5a53Sjeremylt   @ref Basic
322b11c1e72Sjeremylt **/
323d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
324d7b241e6Sjeremylt   int ierr;
325d7b241e6Sjeremylt 
326d7b241e6Sjeremylt   if (!*qf || --(*qf)->refcount > 0) return 0;
327d7b241e6Sjeremylt   // Free field names
328d7b241e6Sjeremylt   for (int i=0; i<(*qf)->numinputfields; i++) {
329d7b241e6Sjeremylt     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
330d7b241e6Sjeremylt   }
331d7b241e6Sjeremylt   for (int i=0; i<(*qf)->numoutputfields; i++) {
332d7b241e6Sjeremylt     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
333d7b241e6Sjeremylt   }
334d7b241e6Sjeremylt   if ((*qf)->Destroy) {
335d7b241e6Sjeremylt     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
336d7b241e6Sjeremylt   }
337d7b241e6Sjeremylt   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
338d7b241e6Sjeremylt   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
339d7b241e6Sjeremylt   ierr = CeedFree(qf); CeedChk(ierr);
340d7b241e6Sjeremylt   return 0;
341d7b241e6Sjeremylt }
342d7b241e6Sjeremylt 
343d7b241e6Sjeremylt /// @}
344