xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision d7b241e67f6e33d9b297db3da3be4f167f32bbee)
1*d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2*d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3*d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4*d7b241e6Sjeremylt //
5*d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6*d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7*d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8*d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9*d7b241e6Sjeremylt //
10*d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12*d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13*d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14*d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15*d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16*d7b241e6Sjeremylt 
17*d7b241e6Sjeremylt #include <ceed-impl.h>
18*d7b241e6Sjeremylt #include <string.h>
19*d7b241e6Sjeremylt 
20*d7b241e6Sjeremylt /**
21*d7b241e6Sjeremylt   @file
22*d7b241e6Sjeremylt   Implementation of public CeedQFunction interfaces
23*d7b241e6Sjeremylt 
24*d7b241e6Sjeremylt   @defgroup CeedQFunction CeedQFunction: independent operations at quadrature points
25*d7b241e6Sjeremylt   @{
26*d7b241e6Sjeremylt  */
27*d7b241e6Sjeremylt 
28*d7b241e6Sjeremylt /**
29*d7b241e6Sjeremylt   @brief Create a CeedQFunction for evaluating interior (volumetric) terms.
30*d7b241e6Sjeremylt 
31*d7b241e6Sjeremylt   @param ceed       Ceed library context
32*d7b241e6Sjeremylt   @param vlength    Vector length.  Caller must ensure that number of quadrature
33*d7b241e6Sjeremylt                     points is a multiple of vlength.
34*d7b241e6Sjeremylt   @param f          Function pointer to evaluate action at quadrature points.
35*d7b241e6Sjeremylt                     See below.
36*d7b241e6Sjeremylt   @param focca      OCCA identifier "file.c:function_name" for definition of `f`
37*d7b241e6Sjeremylt   @param qf         constructed QFunction
38*d7b241e6Sjeremylt   @return 0 on success, otherwise failure
39*d7b241e6Sjeremylt 
40*d7b241e6Sjeremylt   The arguments of the call-back 'function' are:
41*d7b241e6Sjeremylt 
42*d7b241e6Sjeremylt    1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in
43*d7b241e6Sjeremylt               the CeedQFunction, set by calling CeedQFunctionSetContext
44*d7b241e6Sjeremylt 
45*d7b241e6Sjeremylt    2. [CeedInt nq][in] - number of quadrature points to process
46*d7b241e6Sjeremylt 
47*d7b241e6Sjeremylt    3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user
48*d7b241e6Sjeremylt 
49*d7b241e6Sjeremylt    4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user
50*d7b241e6Sjeremylt 
51*d7b241e6Sjeremylt */
52*d7b241e6Sjeremylt int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vlength,
53*d7b241e6Sjeremylt                                 int (*f)(void*, CeedInt, const CeedScalar *const*, CeedScalar *const*),
54*d7b241e6Sjeremylt                                 const char *focca, CeedQFunction *qf) {
55*d7b241e6Sjeremylt   int ierr;
56*d7b241e6Sjeremylt   char *focca_copy;
57*d7b241e6Sjeremylt 
58*d7b241e6Sjeremylt   if (!ceed->QFunctionCreate)
59*d7b241e6Sjeremylt     return CeedError(ceed, 1, "Backend does not support QFunctionCreate");
60*d7b241e6Sjeremylt   ierr = CeedCalloc(1,qf); CeedChk(ierr);
61*d7b241e6Sjeremylt   (*qf)->ceed = ceed;
62*d7b241e6Sjeremylt   ceed->refcount++;
63*d7b241e6Sjeremylt   (*qf)->refcount = 1;
64*d7b241e6Sjeremylt   (*qf)->vlength = vlength;
65*d7b241e6Sjeremylt   (*qf)->function = f;
66*d7b241e6Sjeremylt   ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr);
67*d7b241e6Sjeremylt   strcpy(focca_copy, focca);
68*d7b241e6Sjeremylt   (*qf)->focca = focca_copy;
69*d7b241e6Sjeremylt   ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr);
70*d7b241e6Sjeremylt   return 0;
71*d7b241e6Sjeremylt }
72*d7b241e6Sjeremylt 
73*d7b241e6Sjeremylt static int CeedQFunctionFieldSet(struct CeedQFunctionField *f,
74*d7b241e6Sjeremylt                                  const char *fieldname, CeedInt ncomp,
75*d7b241e6Sjeremylt                                  CeedEvalMode emode) {
76*d7b241e6Sjeremylt   size_t len = strlen(fieldname);
77*d7b241e6Sjeremylt   char *tmp;
78*d7b241e6Sjeremylt   int ierr =  CeedCalloc(len+1, &tmp); CeedChk(ierr);
79*d7b241e6Sjeremylt   memcpy(tmp, fieldname, len+1);
80*d7b241e6Sjeremylt   f->fieldname = tmp;
81*d7b241e6Sjeremylt   f->ncomp = ncomp;
82*d7b241e6Sjeremylt   f->emode = emode;
83*d7b241e6Sjeremylt   return 0;
84*d7b241e6Sjeremylt }
85*d7b241e6Sjeremylt 
86*d7b241e6Sjeremylt int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname,
87*d7b241e6Sjeremylt                           CeedInt ncomp, CeedEvalMode emode) {
88*d7b241e6Sjeremylt   int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++],
89*d7b241e6Sjeremylt                                    fieldname, ncomp, emode); CeedChk(ierr);
90*d7b241e6Sjeremylt   return 0;
91*d7b241e6Sjeremylt }
92*d7b241e6Sjeremylt 
93*d7b241e6Sjeremylt int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname,
94*d7b241e6Sjeremylt                            CeedInt ncomp, CeedEvalMode emode) {
95*d7b241e6Sjeremylt   if (emode == CEED_EVAL_WEIGHT)
96*d7b241e6Sjeremylt     return CeedError(qf->ceed, 1,
97*d7b241e6Sjeremylt                      "Cannot create qfunction output with CEED_EVAL_WEIGHT");
98*d7b241e6Sjeremylt   int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++],
99*d7b241e6Sjeremylt                                    fieldname, ncomp, emode); CeedChk(ierr);
100*d7b241e6Sjeremylt   return 0;
101*d7b241e6Sjeremylt }
102*d7b241e6Sjeremylt 
103*d7b241e6Sjeremylt int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput,
104*d7b241e6Sjeremylt                             CeedInt *numoutput) {
105*d7b241e6Sjeremylt   CeedInt nin = 0, nout = 0;
106*d7b241e6Sjeremylt   for (CeedInt i=0; i<qf->numinputfields; i++) {
107*d7b241e6Sjeremylt     CeedEvalMode emode = qf->inputfields[i].emode;
108*d7b241e6Sjeremylt     if (emode == CEED_EVAL_NONE) nin++;  // Colocated field is input directly
109*d7b241e6Sjeremylt     if (emode & CEED_EVAL_INTERP) nin++; // Interpolate to quadrature points
110*d7b241e6Sjeremylt     if (emode & CEED_EVAL_GRAD) nin++;   // Gradients at quadrature points
111*d7b241e6Sjeremylt   }
112*d7b241e6Sjeremylt   for (CeedInt i=0; i<qf->numoutputfields; i++) {
113*d7b241e6Sjeremylt     CeedEvalMode emode = qf->outputfields[i].emode;
114*d7b241e6Sjeremylt     if (emode == CEED_EVAL_NONE) nout++;
115*d7b241e6Sjeremylt     if (emode & CEED_EVAL_INTERP) nout++;
116*d7b241e6Sjeremylt     if (emode & CEED_EVAL_GRAD) nout++;
117*d7b241e6Sjeremylt   }
118*d7b241e6Sjeremylt   if (numinput) *numinput = nin;
119*d7b241e6Sjeremylt   if (numoutput) *numoutput = nout;
120*d7b241e6Sjeremylt   return 0;
121*d7b241e6Sjeremylt }
122*d7b241e6Sjeremylt 
123*d7b241e6Sjeremylt /**
124*d7b241e6Sjeremylt   Set global context for a quadrature function
125*d7b241e6Sjeremylt  */
126*d7b241e6Sjeremylt int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) {
127*d7b241e6Sjeremylt   qf->ctx = ctx;
128*d7b241e6Sjeremylt   qf->ctxsize = ctxsize;
129*d7b241e6Sjeremylt   return 0;
130*d7b241e6Sjeremylt }
131*d7b241e6Sjeremylt 
132*d7b241e6Sjeremylt /** Apply the action of a CeedQFunction
133*d7b241e6Sjeremylt  */
134*d7b241e6Sjeremylt int CeedQFunctionApply(CeedQFunction qf, CeedInt Q,
135*d7b241e6Sjeremylt                        const CeedScalar *const *u,
136*d7b241e6Sjeremylt                        CeedScalar *const *v) {
137*d7b241e6Sjeremylt   int ierr;
138*d7b241e6Sjeremylt   if (!qf->Apply)
139*d7b241e6Sjeremylt     return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply");
140*d7b241e6Sjeremylt   if (Q % qf->vlength)
141*d7b241e6Sjeremylt     return CeedError(qf->ceed, 2,
142*d7b241e6Sjeremylt                      "Number of quadrature points %d must be a multiple of %d",
143*d7b241e6Sjeremylt                      Q, qf->vlength);
144*d7b241e6Sjeremylt   ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr);
145*d7b241e6Sjeremylt   return 0;
146*d7b241e6Sjeremylt }
147*d7b241e6Sjeremylt 
148*d7b241e6Sjeremylt /** Destroy a CeedQFunction
149*d7b241e6Sjeremylt  */
150*d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
151*d7b241e6Sjeremylt   int ierr;
152*d7b241e6Sjeremylt 
153*d7b241e6Sjeremylt   if (!*qf || --(*qf)->refcount > 0) return 0;
154*d7b241e6Sjeremylt   // Free field names
155*d7b241e6Sjeremylt   for (int i=0; i<(*qf)->numinputfields; i++) {
156*d7b241e6Sjeremylt     ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr);
157*d7b241e6Sjeremylt   }
158*d7b241e6Sjeremylt   for (int i=0; i<(*qf)->numoutputfields; i++) {
159*d7b241e6Sjeremylt     ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr);
160*d7b241e6Sjeremylt   }
161*d7b241e6Sjeremylt   if ((*qf)->Destroy) {
162*d7b241e6Sjeremylt     ierr = (*qf)->Destroy(*qf); CeedChk(ierr);
163*d7b241e6Sjeremylt   }
164*d7b241e6Sjeremylt   ierr = CeedFree(&(*qf)->focca); CeedChk(ierr);
165*d7b241e6Sjeremylt   ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr);
166*d7b241e6Sjeremylt   ierr = CeedFree(qf); CeedChk(ierr);
167*d7b241e6Sjeremylt   return 0;
168*d7b241e6Sjeremylt }
169*d7b241e6Sjeremylt 
170*d7b241e6Sjeremylt /// @}
171