xref: /libCEED/interface/ceed-qfunction.c (revision 069aeaba34b4b3cfb8ce3ee7622d1de203dfbf5c)
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 
671dfeef1dSjeremylt     ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf);
681dfeef1dSjeremylt     CeedChk(ierr);
695fe0d4faSjeremylt     return 0;
705fe0d4faSjeremylt   }
715fe0d4faSjeremylt 
72d7b241e6Sjeremylt   ierr = CeedCalloc(1,qf); CeedChk(ierr);
73d7b241e6Sjeremylt   (*qf)->ceed = ceed;
74d7b241e6Sjeremylt   ceed->refcount++;
75d7b241e6Sjeremylt   (*qf)->refcount = 1;
76d7b241e6Sjeremylt   (*qf)->vlength = vlength;
77d7b241e6Sjeremylt   (*qf)->function = f;
78d7b241e6Sjeremylt   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
79d7b241e6Sjeremylt   strcpy(focca_copy, focca);
80d7b241e6Sjeremylt   (*qf)->focca = focca_copy;
81fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*qf)->inputfields); CeedChk(ierr);
82fe2413ffSjeremylt   ierr = CeedCalloc(16, &(*qf)->outputfields); CeedChk(ierr);
83d7b241e6Sjeremylt   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
84d7b241e6Sjeremylt   return 0;
85d7b241e6Sjeremylt }
86d7b241e6Sjeremylt 
87b11c1e72Sjeremylt /**
88a0a97fcfSJed Brown   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
89b11c1e72Sjeremylt 
90b11c1e72Sjeremylt   @param f          CeedQFunctionField
91b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
92b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
93b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
94b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
95b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
96b11c1e72Sjeremylt 
97b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
98dfdf5a53Sjeremylt 
99dfdf5a53Sjeremylt   @ref Developer
100b11c1e72Sjeremylt **/
101fe2413ffSjeremylt static int CeedQFunctionFieldSet(CeedQFunctionField *f,const char *fieldname,
102fe2413ffSjeremylt                                  CeedInt ncomp, CeedEvalMode emode) {
103d7b241e6Sjeremylt   size_t len = strlen(fieldname);
104d7b241e6Sjeremylt   char *tmp;
105fe2413ffSjeremylt   int ierr;
106fe2413ffSjeremylt   ierr = CeedCalloc(1,f); CeedChk(ierr);
107fe2413ffSjeremylt 
108fe2413ffSjeremylt   ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr);
109d7b241e6Sjeremylt   memcpy(tmp, fieldname, len+1);
110fe2413ffSjeremylt   (*f)->fieldname = tmp;
111fe2413ffSjeremylt   (*f)->ncomp = ncomp;
112fe2413ffSjeremylt   (*f)->emode = emode;
113d7b241e6Sjeremylt   return 0;
114d7b241e6Sjeremylt }
115d7b241e6Sjeremylt 
116b11c1e72Sjeremylt /**
117a0a97fcfSJed Brown   @brief Add a CeedQFunction input
118b11c1e72Sjeremylt 
119b11c1e72Sjeremylt   @param qf         CeedQFunction
120b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
121b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
122b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
123b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
124b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
125b11c1e72Sjeremylt 
126b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
127dfdf5a53Sjeremylt 
128dfdf5a53Sjeremylt   @ref Basic
129b11c1e72Sjeremylt **/
130d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
131d7b241e6Sjeremylt                           CeedInt ncomp, CeedEvalMode emode) {
132fe2413ffSjeremylt   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields],
133fe2413ffSjeremylt                                    fieldname, ncomp, emode);
134fe2413ffSjeremylt   CeedChk(ierr);
135fe2413ffSjeremylt   qf->numinputfields++;
136d7b241e6Sjeremylt   return 0;
137d7b241e6Sjeremylt }
138d7b241e6Sjeremylt 
139b11c1e72Sjeremylt /**
140a0a97fcfSJed Brown   @brief Add a CeedQFunction output
141b11c1e72Sjeremylt 
142b11c1e72Sjeremylt   @param qf         CeedQFunction
143b11c1e72Sjeremylt   @param fieldname  Name of QFunction field
144b11c1e72Sjeremylt   @param ncomp      Number of components per quadrature node
145b11c1e72Sjeremylt   @param emode      \ref CEED_EVAL_NONE to use values directly,
146b11c1e72Sjeremylt                       \ref CEED_EVAL_INTERP to use interpolated values,
147b11c1e72Sjeremylt                       \ref CEED_EVAL_GRAD to use gradients.
148b11c1e72Sjeremylt 
149b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
150dfdf5a53Sjeremylt 
151dfdf5a53Sjeremylt   @ref Basic
152b11c1e72Sjeremylt **/
153d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
154d7b241e6Sjeremylt                            CeedInt ncomp, CeedEvalMode emode) {
155d7b241e6Sjeremylt   if (emode == CEED_EVAL_WEIGHT)
156d7b241e6Sjeremylt     return CeedError(qf->ceed, 1,
157d7b241e6Sjeremylt                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
158fe2413ffSjeremylt   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields],
159fe2413ffSjeremylt                                    fieldname, ncomp, emode);
160fe2413ffSjeremylt   CeedChk(ierr);
161fe2413ffSjeremylt   qf->numoutputfields++;
162d7b241e6Sjeremylt   return 0;
163d7b241e6Sjeremylt }
164d7b241e6Sjeremylt 
165dfdf5a53Sjeremylt /**
1664ce2993fSjeremylt   @brief Get the Ceed associated with a CeedQFunction
1674ce2993fSjeremylt 
1684ce2993fSjeremylt   @param qf              CeedQFunction
1694ce2993fSjeremylt   @param[out] ceed       Variable to store Ceed
1704ce2993fSjeremylt 
1714ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
1724ce2993fSjeremylt 
17323617272Sjeremylt   @ref Advanced
1744ce2993fSjeremylt **/
1754ce2993fSjeremylt 
1764ce2993fSjeremylt int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
1774ce2993fSjeremylt   *ceed = qf->ceed;
1784ce2993fSjeremylt   return 0;
1794ce2993fSjeremylt }
1804ce2993fSjeremylt 
1814ce2993fSjeremylt /**
1824ce2993fSjeremylt   @brief Get the vector length of a CeedQFunction
1834ce2993fSjeremylt 
1844ce2993fSjeremylt   @param qf              CeedQFunction
1854ce2993fSjeremylt   @param[out] veclength  Variable to store vector length
1864ce2993fSjeremylt 
1874ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
1884ce2993fSjeremylt 
18923617272Sjeremylt   @ref Advanced
1904ce2993fSjeremylt **/
1914ce2993fSjeremylt 
1924ce2993fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) {
1934ce2993fSjeremylt   *vlength = qf->vlength;
1944ce2993fSjeremylt   return 0;
1954ce2993fSjeremylt }
1964ce2993fSjeremylt 
1974ce2993fSjeremylt /**
198dfdf5a53Sjeremylt   @brief Get the number of inputs and outputs to a CeedQFunction
199dfdf5a53Sjeremylt 
200dfdf5a53Sjeremylt   @param qf              CeedQFunction
2014ce2993fSjeremylt   @param[out] numinput   Variable to store number of input fields
2024ce2993fSjeremylt   @param[out] numoutput  Variable to store number of output fields
203dfdf5a53Sjeremylt 
204dfdf5a53Sjeremylt   @return An error code: 0 - success, otherwise - failure
205dfdf5a53Sjeremylt 
20623617272Sjeremylt   @ref Advanced
207dfdf5a53Sjeremylt **/
208dfdf5a53Sjeremylt 
209d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
210d7b241e6Sjeremylt                             CeedInt *numoutput) {
2111a4ead9bSjeremylt   if (numinput) *numinput = qf->numinputfields;
2121a4ead9bSjeremylt   if (numoutput) *numoutput = qf->numoutputfields;
213d7b241e6Sjeremylt   return 0;
214d7b241e6Sjeremylt }
215d7b241e6Sjeremylt 
216d7b241e6Sjeremylt /**
2174ce2993fSjeremylt   @brief Get the FOCCA string for a CeedQFunction
2184ce2993fSjeremylt 
2194ce2993fSjeremylt   @param qf              CeedQFunction
2204ce2993fSjeremylt   @param[out] focca      Variable to store focca string
2214ce2993fSjeremylt 
2224ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2234ce2993fSjeremylt 
22423617272Sjeremylt   @ref Advanced
2254ce2993fSjeremylt **/
2264ce2993fSjeremylt 
2274ce2993fSjeremylt int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) {
2284ce2993fSjeremylt   *focca = (char*) qf->focca;
2294ce2993fSjeremylt   return 0;
2304ce2993fSjeremylt }
2314ce2993fSjeremylt 
2324ce2993fSjeremylt /**
233fe2413ffSjeremylt   @brief Get the User Function for a CeedQFunction
234fe2413ffSjeremylt 
235fe2413ffSjeremylt   @param qf              CeedQFunction
236fe2413ffSjeremylt   @param[out] f          Variable to store user function
237fe2413ffSjeremylt 
238fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
239fe2413ffSjeremylt 
240fe2413ffSjeremylt   @ref Advanced
241fe2413ffSjeremylt **/
242fe2413ffSjeremylt 
24328d161eeSjeremylt int CeedQFunctionGetUserFunction(CeedQFunction qf, int (**f)()) {
24428d161eeSjeremylt   *f = (int (*)())qf->function;
245fe2413ffSjeremylt   return 0;
246fe2413ffSjeremylt }
247fe2413ffSjeremylt 
248fe2413ffSjeremylt /**
2494ce2993fSjeremylt   @brief Get global context size for a CeedQFunction
2504ce2993fSjeremylt 
2514ce2993fSjeremylt   @param qf              CeedQFunction
2524ce2993fSjeremylt   @param[out] ctxsize    Variable to store size of context data values
2534ce2993fSjeremylt 
2544ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2554ce2993fSjeremylt 
25623617272Sjeremylt   @ref Advanced
2574ce2993fSjeremylt **/
2584ce2993fSjeremylt 
2594ce2993fSjeremylt int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) {
260*069aeabaSjeremylt   if (qf->fortranstatus) {
261*069aeabaSjeremylt     fContext *fctx = qf->ctx;
262*069aeabaSjeremylt     *ctxsize = fctx->innerctxsize;
263*069aeabaSjeremylt   } else {
2644ce2993fSjeremylt     *ctxsize = qf->ctxsize;
265*069aeabaSjeremylt   }
2664ce2993fSjeremylt   return 0;
2674ce2993fSjeremylt }
2684ce2993fSjeremylt 
2694ce2993fSjeremylt /**
2704ce2993fSjeremylt   @brief Get global context for a CeedQFunction
2714ce2993fSjeremylt 
2724ce2993fSjeremylt   @param qf              CeedQFunction
2734ce2993fSjeremylt   @param[out] ctx        Variable to store context data values
2744ce2993fSjeremylt 
2754ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
2764ce2993fSjeremylt 
27723617272Sjeremylt   @ref Advanced
2784ce2993fSjeremylt **/
2794ce2993fSjeremylt 
2804ce2993fSjeremylt int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) {
2814ce2993fSjeremylt   *ctx = qf->ctx;
2824ce2993fSjeremylt   return 0;
2834ce2993fSjeremylt }
2844ce2993fSjeremylt 
2854ce2993fSjeremylt /**
286418fb8c2Sjeremylt   @brief Determine if Fortran interface was used
287418fb8c2Sjeremylt 
288418fb8c2Sjeremylt   @param qf                  CeedQFunction
289418fb8c2Sjeremylt   @param[out] fortranstatus  Variable to store Fortran status
290418fb8c2Sjeremylt 
291418fb8c2Sjeremylt   @return An error code: 0 - success, otherwise - failure
292418fb8c2Sjeremylt 
293418fb8c2Sjeremylt   @ref Advanced
294418fb8c2Sjeremylt **/
295418fb8c2Sjeremylt 
296418fb8c2Sjeremylt int CeedQFunctionGetFortranStatus(CeedQFunction qf, bool *fortranstatus) {
297418fb8c2Sjeremylt   *fortranstatus = qf->fortranstatus;
298418fb8c2Sjeremylt   return 0;
299418fb8c2Sjeremylt }
300418fb8c2Sjeremylt 
301418fb8c2Sjeremylt /**
302*069aeabaSjeremylt   @brief Get Fortran global context for a CeedQFunction
303*069aeabaSjeremylt 
304*069aeabaSjeremylt   @param qf              CeedQFunction
305*069aeabaSjeremylt   @param[out] ctx        Variable to store context data values
306*069aeabaSjeremylt 
307*069aeabaSjeremylt   @return An error code: 0 - success, otherwise - failure
308*069aeabaSjeremylt 
309*069aeabaSjeremylt   @ref Advanced
310*069aeabaSjeremylt **/
311*069aeabaSjeremylt 
312*069aeabaSjeremylt int CeedQFunctionGetFortranContext(CeedQFunction qf, void* *ctx) {
313*069aeabaSjeremylt   if (!qf->fortranstatus)
314*069aeabaSjeremylt     return CeedError(qf->ceed, 1,
315*069aeabaSjeremylt                      "QFunction was not set using Fortran");
316*069aeabaSjeremylt 
317*069aeabaSjeremylt   fContext *fctx = qf->ctx;
318*069aeabaSjeremylt  *ctx = fctx->innerctx;
319*069aeabaSjeremylt   return 0;
320*069aeabaSjeremylt }
321*069aeabaSjeremylt 
322*069aeabaSjeremylt /**
3234ce2993fSjeremylt   @brief Get backend data of a CeedQFunction
3244ce2993fSjeremylt 
3254ce2993fSjeremylt   @param qf              CeedQFunction
3264ce2993fSjeremylt   @param[out] data       Variable to store data
3274ce2993fSjeremylt 
3284ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
3294ce2993fSjeremylt 
33023617272Sjeremylt   @ref Advanced
3314ce2993fSjeremylt **/
3324ce2993fSjeremylt 
3334ce2993fSjeremylt int CeedQFunctionGetData(CeedQFunction qf, void* *data) {
3344ce2993fSjeremylt   *data = qf->data;
3354ce2993fSjeremylt   return 0;
3364ce2993fSjeremylt }
3374ce2993fSjeremylt 
3384ce2993fSjeremylt /**
339fe2413ffSjeremylt   @brief Set backend data of a CeedQFunction
340fe2413ffSjeremylt 
341fe2413ffSjeremylt   @param[out] qf         CeedQFunction
342fe2413ffSjeremylt   @param data            Data to set
343fe2413ffSjeremylt 
344fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
345fe2413ffSjeremylt 
346fe2413ffSjeremylt   @ref Advanced
347fe2413ffSjeremylt **/
348fe2413ffSjeremylt 
349fe2413ffSjeremylt int CeedQFunctionSetData(CeedQFunction qf, void* *data) {
350fe2413ffSjeremylt   qf->data = *data;
351fe2413ffSjeremylt   return 0;
352fe2413ffSjeremylt }
353fe2413ffSjeremylt 
354fe2413ffSjeremylt /**
3554ce2993fSjeremylt   @brief Set global context for a CeedQFunction
356b11c1e72Sjeremylt 
357b11c1e72Sjeremylt   @param qf       CeedQFunction
358b11c1e72Sjeremylt   @param ctx      Context data to set
359b11c1e72Sjeremylt   @param ctxsize  Size of context data values
360b11c1e72Sjeremylt 
361b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
362dfdf5a53Sjeremylt 
363dfdf5a53Sjeremylt   @ref Basic
364b11c1e72Sjeremylt **/
365d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
366d7b241e6Sjeremylt   qf->ctx = ctx;
367d7b241e6Sjeremylt   qf->ctxsize = ctxsize;
368d7b241e6Sjeremylt   return 0;
369d7b241e6Sjeremylt }
370d7b241e6Sjeremylt 
371b11c1e72Sjeremylt /**
372b11c1e72Sjeremylt   @brief Apply the action of a CeedQFunction
373b11c1e72Sjeremylt 
374b11c1e72Sjeremylt   @param qf      CeedQFunction
375b11c1e72Sjeremylt   @param Q       Number of quadrature points
376b11c1e72Sjeremylt   @param[in] u   Array of input data arrays
377b11c1e72Sjeremylt   @param[out] v  Array of output data arrays
378b11c1e72Sjeremylt 
379b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
380dfdf5a53Sjeremylt 
381dfdf5a53Sjeremylt   @ref Advanced
382b11c1e72Sjeremylt **/
383d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
384aedaa0e5Sjeremylt                        CeedVector* u, CeedVector* v) {
385d7b241e6Sjeremylt   int ierr;
386d7b241e6Sjeremylt   if (!qf->Apply)
387d7b241e6Sjeremylt     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
388d7b241e6Sjeremylt   if (Q % qf->vlength)
389d7b241e6Sjeremylt     return CeedError(qf->ceed, 2,
390d7b241e6Sjeremylt                      "Number of quadrature points %d must be a multiple of %d",
391d7b241e6Sjeremylt                      Q, qf->vlength);
392d7b241e6Sjeremylt   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
393d7b241e6Sjeremylt   return 0;
394d7b241e6Sjeremylt }
395d7b241e6Sjeremylt 
396b11c1e72Sjeremylt /**
397d1bcdac9Sjeremylt   @brief Get the CeedQFunctionFields of a CeedQFunction
398d1bcdac9Sjeremylt 
399d1bcdac9Sjeremylt   @param qf                 CeedQFunction
400d1bcdac9Sjeremylt   @param[out] inputfields   Variable to store inputfields
401d1bcdac9Sjeremylt   @param[out] outputfields  Variable to store outputfields
402d1bcdac9Sjeremylt 
403d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
404d1bcdac9Sjeremylt 
405d1bcdac9Sjeremylt   @ref Advanced
406d1bcdac9Sjeremylt **/
407d1bcdac9Sjeremylt 
408d1bcdac9Sjeremylt int CeedQFunctionGetFields(CeedQFunction qf,
409d1bcdac9Sjeremylt                            CeedQFunctionField* *inputfields,
410d1bcdac9Sjeremylt                            CeedQFunctionField* *outputfields) {
411d1bcdac9Sjeremylt   if (inputfields) *inputfields = qf->inputfields;
412d1bcdac9Sjeremylt   if (outputfields) *outputfields = qf->outputfields;
413d1bcdac9Sjeremylt   return 0;
414d1bcdac9Sjeremylt }
415d1bcdac9Sjeremylt 
416d1bcdac9Sjeremylt /**
417fe2413ffSjeremylt   @brief Get the name of a CeedQFunctionField
418fe2413ffSjeremylt 
419fe2413ffSjeremylt   @param qffield         CeedQFunctionField
420fe2413ffSjeremylt   @param[out] fieldname  Variable to store the field name
421fe2413ffSjeremylt 
422fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
423fe2413ffSjeremylt 
424fe2413ffSjeremylt   @ref Advanced
425fe2413ffSjeremylt **/
426fe2413ffSjeremylt 
427fe2413ffSjeremylt int CeedQFunctionFieldGetName(CeedQFunctionField qffield,
428fe2413ffSjeremylt                               char* *fieldname) {
429fe2413ffSjeremylt   *fieldname = (char *)qffield->fieldname;
430fe2413ffSjeremylt   return 0;
431fe2413ffSjeremylt }
432fe2413ffSjeremylt 
433fe2413ffSjeremylt /**
434d1bcdac9Sjeremylt   @brief Get the number of components of a CeedQFunctionField
435d1bcdac9Sjeremylt 
436d1bcdac9Sjeremylt   @param qffield         CeedQFunctionField
437d1bcdac9Sjeremylt   @param[out] numcomp    Variable to store the number of components
438d1bcdac9Sjeremylt 
439d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
440d1bcdac9Sjeremylt 
441d1bcdac9Sjeremylt   @ref Advanced
442d1bcdac9Sjeremylt **/
443d1bcdac9Sjeremylt 
444d1bcdac9Sjeremylt int CeedQFunctionFieldGetNumComponents(CeedQFunctionField qffield,
445d1bcdac9Sjeremylt                                        CeedInt *numcomp) {
446fe2413ffSjeremylt   *numcomp = qffield->ncomp;
447d1bcdac9Sjeremylt   return 0;
448d1bcdac9Sjeremylt }
449d1bcdac9Sjeremylt 
450d1bcdac9Sjeremylt /**
451d1bcdac9Sjeremylt   @brief Get the CeedEvalMode of a CeedQFunctionField
452d1bcdac9Sjeremylt 
453d1bcdac9Sjeremylt   @param qffield         CeedQFunctionField
454d1bcdac9Sjeremylt   @param[out] vec        Variable to store the number of components
455d1bcdac9Sjeremylt 
456d1bcdac9Sjeremylt   @return An error code: 0 - success, otherwise - failure
457d1bcdac9Sjeremylt 
458d1bcdac9Sjeremylt   @ref Advanced
459d1bcdac9Sjeremylt **/
460d1bcdac9Sjeremylt 
461d1bcdac9Sjeremylt int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qffield,
462d1bcdac9Sjeremylt                                   CeedEvalMode *emode) {
463fe2413ffSjeremylt   *emode = qffield->emode;
464d1bcdac9Sjeremylt   return 0;
465d1bcdac9Sjeremylt }
466d1bcdac9Sjeremylt 
467d1bcdac9Sjeremylt /**
468b11c1e72Sjeremylt   @brief Destroy a CeedQFunction
469b11c1e72Sjeremylt 
470b11c1e72Sjeremylt   @param qf CeedQFunction to destroy
471b11c1e72Sjeremylt 
472b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
473dfdf5a53Sjeremylt 
474dfdf5a53Sjeremylt   @ref Basic
475b11c1e72Sjeremylt **/
476d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
477d7b241e6Sjeremylt   int ierr;
478d7b241e6Sjeremylt 
479d7b241e6Sjeremylt   if (!*qf || --(*qf)->refcount > 0) return 0;
480fe2413ffSjeremylt   // Backend destroy
481d7b241e6Sjeremylt   if ((*qf)->Destroy) {
482d7b241e6Sjeremylt     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
483d7b241e6Sjeremylt   }
484fe2413ffSjeremylt   // Free fields
485fe2413ffSjeremylt   for (int i=0; i<(*qf)->numinputfields; i++) {
486fe2413ffSjeremylt     ierr = CeedFree(&(*(*qf)->inputfields[i]).fieldname); CeedChk(ierr);
487fe2413ffSjeremylt     ierr = CeedFree(&(*qf)->inputfields[i]); CeedChk(ierr);
488fe2413ffSjeremylt   }
489fe2413ffSjeremylt   for (int i=0; i<(*qf)->numoutputfields; i++) {
490fe2413ffSjeremylt     ierr = CeedFree(&(*(*qf)->outputfields[i]).fieldname); CeedChk(ierr);
491fe2413ffSjeremylt     ierr = CeedFree(&(*qf)->outputfields[i]); CeedChk(ierr);
492fe2413ffSjeremylt   }
493fe2413ffSjeremylt   ierr = CeedFree(&(*qf)->inputfields); CeedChk(ierr);
494fe2413ffSjeremylt   ierr = CeedFree(&(*qf)->outputfields); CeedChk(ierr);
495fe2413ffSjeremylt 
496d7b241e6Sjeremylt   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
497d7b241e6Sjeremylt   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
498d7b241e6Sjeremylt   ierr = CeedFree(qf); CeedChk(ierr);
499d7b241e6Sjeremylt   return 0;
500d7b241e6Sjeremylt }
501d7b241e6Sjeremylt 
502d7b241e6Sjeremylt /// @}
503