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