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