xref: /libCEED/interface/ceed-qfunction.c (revision d7b241e67f6e33d9b297db3da3be4f167f32bbee)
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       Ceed library context
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 qf         constructed QFunction
38   @return 0 on 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 */
52 int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
53                                 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*),
54                                 const char *focca, CeedQFunction *qf) {
55   int ierr;
56   char *focca_copy;
57 
58   if (!ceed->QFunctionCreate)
59     return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
60   ierr = CeedCalloc(1,qf); CeedChk(ierr);
61   (*qf)->ceed = ceed;
62   ceed->refcount++;
63   (*qf)->refcount = 1;
64   (*qf)->vlength = vlength;
65   (*qf)->function = f;
66   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
67   strcpy(focca_copy, focca);
68   (*qf)->focca = focca_copy;
69   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
70   return 0;
71 }
72 
73 static int CeedQFunctionFieldSet(struct CeedQFunctionField *f,
74                                  const char *fieldname, CeedInt ncomp,
75                                  CeedEvalMode emode) {
76   size_t len = strlen(fieldname);
77   char *tmp;
78   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
79   memcpy(tmp, fieldname, len+1);
80   f->fieldname = tmp;
81   f->ncomp = ncomp;
82   f->emode = emode;
83   return 0;
84 }
85 
86 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
87                           CeedInt ncomp, CeedEvalMode emode) {
88   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
89                                    fieldname, ncomp, emode); CeedChk(ierr);
90   return 0;
91 }
92 
93 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
94                            CeedInt ncomp, CeedEvalMode emode) {
95   if (emode == CEED_EVAL_WEIGHT)
96     return CeedError(qf->ceed, 1,
97                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
98   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
99                                    fieldname, ncomp, emode); CeedChk(ierr);
100   return 0;
101 }
102 
103 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
104                             CeedInt *numoutput) {
105   CeedInt nin = 0, nout = 0;
106   for (CeedInt i=0; i<qf->numinputfields; i++) {
107     CeedEvalMode emode = qf->inputfields[i].emode;
108     if (emode == CEED_EVAL_NONE) nin++;  // Colocated field is input directly
109     if (emode & CEED_EVAL_INTERP) nin++; // Interpolate to quadrature points
110     if (emode & CEED_EVAL_GRAD) nin++;   // Gradients at quadrature points
111   }
112   for (CeedInt i=0; i<qf->numoutputfields; i++) {
113     CeedEvalMode emode = qf->outputfields[i].emode;
114     if (emode == CEED_EVAL_NONE) nout++;
115     if (emode & CEED_EVAL_INTERP) nout++;
116     if (emode & CEED_EVAL_GRAD) nout++;
117   }
118   if (numinput) *numinput = nin;
119   if (numoutput) *numoutput = nout;
120   return 0;
121 }
122 
123 /**
124   Set global context for a quadrature function
125  */
126 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
127   qf->ctx = ctx;
128   qf->ctxsize = ctxsize;
129   return 0;
130 }
131 
132 /** Apply the action of a CeedQFunction
133  */
134 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
135                        const CeedScalar *const *u,
136                        CeedScalar *const *v) {
137   int ierr;
138   if (!qf->Apply)
139     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
140   if (Q % qf->vlength)
141     return CeedError(qf->ceed, 2,
142                      "Number of quadrature points %d must be a multiple of %d",
143                      Q, qf->vlength);
144   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
145   return 0;
146 }
147 
148 /** Destroy a CeedQFunction
149  */
150 int CeedQFunctionDestroy(CeedQFunction *qf) {
151   int ierr;
152 
153   if (!*qf || --(*qf)->refcount > 0) return 0;
154   // Free field names
155   for (int i=0; i<(*qf)->numinputfields; i++) {
156     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
157   }
158   for (int i=0; i<(*qf)->numoutputfields; i++) {
159     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
160   }
161   if ((*qf)->Destroy) {
162     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
163   }
164   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
165   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
166   ierr = CeedFree(qf); CeedChk(ierr);
167   return 0;
168 }
169 
170 /// @}
171