xref: /libCEED/interface/ceed-qfunction.c (revision 4b8bea3b15f6e9705ea378b18162a3dbd250c6ec)
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 <string.h>
19 
20 /// @file
21 /// Implementation of public CeedQFunction interfaces
22 ///
23 /// @addtogroup CeedQFunction
24 /// @{
25 
26 /**
27   @brief Create a CeedQFunction for evaluating interior (volumetric) terms.
28 
29   @param ceed       A Ceed object where the CeedQFunction will be created
30   @param vlength    Vector length.  Caller must ensure that number of quadrature
31                     points is a multiple of vlength.
32   @param f          Function pointer to evaluate action at quadrature points.
33                     See below.
34   @param focca      OCCA identifier "file.c:function_name" for definition of `f`
35   @param[out] qf    Address of the variable where the newly created
36                      CeedQFunction will be stored
37 
38   @return An error code: 0 - success, otherwise - failure
39 
40   The arguments of the call-back 'function' are:
41 
42    1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in
43               the CeedQFunction, set by calling CeedQFunctionSetContext
44 
45    2. [CeedInt nq][in] - number of quadrature points to process
46 
47    3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user
48 
49    4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user
50 
51   @ref Basic
52 **/
53 int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
54                                 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*),
55                                 const char *focca, CeedQFunction *qf) {
56   int ierr;
57   char *focca_copy;
58 
59   if (!ceed->QFunctionCreate)
60     return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
61   ierr = CeedCalloc(1,qf); CeedChk(ierr);
62   (*qf)->ceed = ceed;
63   ceed->refcount++;
64   (*qf)->refcount = 1;
65   (*qf)->vlength = vlength;
66   (*qf)->function = f;
67   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
68   strcpy(focca_copy, focca);
69   (*qf)->focca = focca_copy;
70   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
71   return 0;
72 }
73 
74 /**
75   @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output
76 
77   @param f          CeedQFunctionField
78   @param fieldname  Name of QFunction field
79   @param ncomp      Number of components per quadrature node
80   @param emode      \ref CEED_EVAL_NONE to use values directly,
81                       \ref CEED_EVAL_INTERP to use interpolated values,
82                       \ref CEED_EVAL_GRAD to use gradients.
83 
84   @return An error code: 0 - success, otherwise - failure
85 
86   @ref Developer
87 **/
88 static int CeedQFunctionFieldSet(struct CeedQFunctionField *f,
89                                  const char *fieldname, CeedInt ncomp,
90                                  CeedEvalMode emode) {
91   size_t len = strlen(fieldname);
92   char *tmp;
93   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
94   memcpy(tmp, fieldname, len+1);
95   f->fieldname = tmp;
96   f->ncomp = ncomp;
97   f->emode = emode;
98   return 0;
99 }
100 
101 /**
102   @brief Add a CeedQFunction input
103 
104   @param qf         CeedQFunction
105   @param fieldname  Name of QFunction field
106   @param ncomp      Number of components per quadrature node
107   @param emode      \ref CEED_EVAL_NONE to use values directly,
108                       \ref CEED_EVAL_INTERP to use interpolated values,
109                       \ref CEED_EVAL_GRAD to use gradients.
110 
111   @return An error code: 0 - success, otherwise - failure
112 
113   @ref Basic
114 **/
115 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
116                           CeedInt ncomp, CeedEvalMode emode) {
117   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
118                                    fieldname, ncomp, emode); CeedChk(ierr);
119   return 0;
120 }
121 
122 /**
123   @brief Add a CeedQFunction output
124 
125   @param qf         CeedQFunction
126   @param fieldname  Name of QFunction field
127   @param ncomp      Number of components per quadrature node
128   @param emode      \ref CEED_EVAL_NONE to use values directly,
129                       \ref CEED_EVAL_INTERP to use interpolated values,
130                       \ref CEED_EVAL_GRAD to use gradients.
131 
132   @return An error code: 0 - success, otherwise - failure
133 
134   @ref Basic
135 **/
136 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
137                            CeedInt ncomp, CeedEvalMode emode) {
138   if (emode == CEED_EVAL_WEIGHT)
139     return CeedError(qf->ceed, 1,
140                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
141   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
142                                    fieldname, ncomp, emode); CeedChk(ierr);
143   return 0;
144 }
145 
146 /**
147   @brief Get the number of inputs and outputs to a CeedQFunction
148 
149   @param qf              CeedQFunction
150   @param[out] numinput   Number of input fields
151   @param[out] numoutput  Number of output fields
152 
153   @return An error code: 0 - success, otherwise - failure
154 
155   @ref Utility
156 **/
157 
158 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
159                             CeedInt *numoutput) {
160   CeedInt nin = 0, nout = 0;
161   for (CeedInt i=0; i<qf->numinputfields; i++) {
162     CeedEvalMode emode = qf->inputfields[i].emode;
163     if (emode == CEED_EVAL_NONE) nin++;  // Colocated field is input directly
164     if (emode & CEED_EVAL_INTERP) nin++; // Interpolate to quadrature points
165     if (emode & CEED_EVAL_GRAD) nin++;   // Gradients at quadrature points
166   }
167   for (CeedInt i=0; i<qf->numoutputfields; i++) {
168     CeedEvalMode emode = qf->outputfields[i].emode;
169     if (emode == CEED_EVAL_NONE) nout++;
170     if (emode & CEED_EVAL_INTERP) nout++;
171     if (emode & CEED_EVAL_GRAD) nout++;
172   }
173   if (numinput) *numinput = nin;
174   if (numoutput) *numoutput = nout;
175   return 0;
176 }
177 
178 /**
179   @brief Set global context for a quadrature function
180 
181   @param qf       CeedQFunction
182   @param ctx      Context data to set
183   @param ctxsize  Size of context data values
184 
185   @return An error code: 0 - success, otherwise - failure
186 
187   @ref Basic
188 **/
189 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
190   qf->ctx = ctx;
191   qf->ctxsize = ctxsize;
192   return 0;
193 }
194 
195 /**
196   @brief Apply the action of a CeedQFunction
197 
198   @param qf      CeedQFunction
199   @param Q       Number of quadrature points
200   @param[in] u   Array of input data arrays
201   @param[out] v  Array of output data arrays
202 
203   @return An error code: 0 - success, otherwise - failure
204 
205   @ref Advanced
206 **/
207 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
208                        const CeedScalar *const *u,
209                        CeedScalar *const *v) {
210   int ierr;
211   if (!qf->Apply)
212     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
213   if (Q % qf->vlength)
214     return CeedError(qf->ceed, 2,
215                      "Number of quadrature points %d must be a multiple of %d",
216                      Q, qf->vlength);
217   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
218   return 0;
219 }
220 
221 /**
222   @brief Destroy a CeedQFunction
223 
224   @param qf CeedQFunction to destroy
225 
226   @return An error code: 0 - success, otherwise - failure
227 
228   @ref Basic
229 **/
230 int CeedQFunctionDestroy(CeedQFunction *qf) {
231   int ierr;
232 
233   if (!*qf || --(*qf)->refcount > 0) return 0;
234   // Free field names
235   for (int i=0; i<(*qf)->numinputfields; i++) {
236     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
237   }
238   for (int i=0; i<(*qf)->numoutputfields; i++) {
239     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
240   }
241   if ((*qf)->Destroy) {
242     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
243   }
244   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
245   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
246   ierr = CeedFree(qf); CeedChk(ierr);
247   return 0;
248 }
249 
250 /// @}
251