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