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 <ceed-backend.h> 19 #include <string.h> 20 21 /// @file 22 /// Implementation of public CeedQFunction interfaces 23 /// 24 /// @addtogroup CeedQFunction 25 /// @{ 26 27 /** 28 @brief Create a CeedQFunction for evaluating interior (volumetric) terms. 29 30 @param ceed A Ceed object where the CeedQFunction will be created 31 @param vlength Vector length. Caller must ensure that number of quadrature 32 points is a multiple of vlength. 33 @param f Function pointer to evaluate action at quadrature points. 34 See below. 35 @param focca OCCA identifier "file.c:function_name" for definition of `f` 36 @param[out] qf Address of the variable where the newly created 37 CeedQFunction will be stored 38 39 @return An error code: 0 - success, otherwise - failure 40 41 The arguments of the call-back 'function' are: 42 43 1. [void *ctx][in/out] - user data, this is the 'ctx' pointer stored in 44 the CeedQFunction, set by calling CeedQFunctionSetContext 45 46 2. [CeedInt nq][in] - number of quadrature points to process 47 48 3. [const CeedScalar *const *u][in] - input fields data at quadrature pts, listed in the order given by the user 49 50 4. [CeedScalar *const *v][out] - output fields data at quadrature points, again listed in order given by the user 51 52 @ref Basic 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 Ceed delegate; 62 ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 63 64 if (!delegate) 65 return CeedError(ceed, 1, "Backend does not support QFunctionCreate"); 66 67 ierr = CeedQFunctionCreateInterior(delegate, vlength, f, focca, qf); CeedChk(ierr); 68 return 0; 69 } 70 71 ierr = CeedCalloc(1,qf); CeedChk(ierr); 72 (*qf)->ceed = ceed; 73 ceed->refcount++; 74 (*qf)->refcount = 1; 75 (*qf)->vlength = vlength; 76 (*qf)->function = f; 77 ierr = CeedCalloc(strlen(focca)+1, &focca_copy); CeedChk(ierr); 78 strcpy(focca_copy, focca); 79 (*qf)->focca = focca_copy; 80 ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 81 return 0; 82 } 83 84 /** 85 @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output 86 87 @param f CeedQFunctionField 88 @param fieldname Name of QFunction field 89 @param ncomp Number of components per quadrature node 90 @param emode \ref CEED_EVAL_NONE to use values directly, 91 \ref CEED_EVAL_INTERP to use interpolated values, 92 \ref CEED_EVAL_GRAD to use gradients. 93 94 @return An error code: 0 - success, otherwise - failure 95 96 @ref Developer 97 **/ 98 static int CeedQFunctionFieldSet(CeedQFunctionField *f, 99 const char *fieldname, CeedInt ncomp, 100 CeedEvalMode emode) { 101 size_t len = strlen(fieldname); 102 char *tmp; 103 int ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 104 memcpy(tmp, fieldname, len+1); 105 f->fieldname = tmp; 106 f->ncomp = ncomp; 107 f->emode = emode; 108 return 0; 109 } 110 111 /** 112 @brief Add a CeedQFunction input 113 114 @param qf CeedQFunction 115 @param fieldname Name of QFunction field 116 @param ncomp Number of components per quadrature node 117 @param emode \ref CEED_EVAL_NONE to use values directly, 118 \ref CEED_EVAL_INTERP to use interpolated values, 119 \ref CEED_EVAL_GRAD to use gradients. 120 121 @return An error code: 0 - success, otherwise - failure 122 123 @ref Basic 124 **/ 125 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 126 CeedInt ncomp, CeedEvalMode emode) { 127 int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields++], 128 fieldname, ncomp, emode); CeedChk(ierr); 129 return 0; 130 } 131 132 /** 133 @brief Add a CeedQFunction output 134 135 @param qf CeedQFunction 136 @param fieldname Name of QFunction field 137 @param ncomp Number of components per quadrature node 138 @param emode \ref CEED_EVAL_NONE to use values directly, 139 \ref CEED_EVAL_INTERP to use interpolated values, 140 \ref CEED_EVAL_GRAD to use gradients. 141 142 @return An error code: 0 - success, otherwise - failure 143 144 @ref Basic 145 **/ 146 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 147 CeedInt ncomp, CeedEvalMode emode) { 148 if (emode == CEED_EVAL_WEIGHT) 149 return CeedError(qf->ceed, 1, 150 "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 151 int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields++], 152 fieldname, ncomp, emode); CeedChk(ierr); 153 return 0; 154 } 155 156 /** 157 @brief Get the Ceed associated with a CeedQFunction 158 159 @param qf CeedQFunction 160 @param[out] ceed Variable to store Ceed 161 162 @return An error code: 0 - success, otherwise - failure 163 164 @ref Advanced 165 **/ 166 167 int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) { 168 *ceed = qf->ceed; 169 return 0; 170 } 171 172 /** 173 @brief Get the vector length of a CeedQFunction 174 175 @param qf CeedQFunction 176 @param[out] veclength Variable to store vector length 177 178 @return An error code: 0 - success, otherwise - failure 179 180 @ref Advanced 181 **/ 182 183 int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) { 184 *vlength = qf->vlength; 185 return 0; 186 } 187 188 /** 189 @brief Get the number of inputs and outputs to a CeedQFunction 190 191 @param qf CeedQFunction 192 @param[out] numinput Variable to store number of input fields 193 @param[out] numoutput Variable to store number of output fields 194 195 @return An error code: 0 - success, otherwise - failure 196 197 @ref Advanced 198 **/ 199 200 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 201 CeedInt *numoutput) { 202 if (numinput) *numinput = qf->numinputfields; 203 if (numoutput) *numoutput = qf->numoutputfields; 204 return 0; 205 } 206 207 /** 208 @brief Get the FOCCA string for a CeedQFunction 209 210 @param qf CeedQFunction 211 @param[out] focca Variable to store focca string 212 213 @return An error code: 0 - success, otherwise - failure 214 215 @ref Advanced 216 **/ 217 218 int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) { 219 *focca = (char*) qf->focca; 220 return 0; 221 } 222 223 /** 224 @brief Get global context size for a CeedQFunction 225 226 @param qf CeedQFunction 227 @param[out] ctxsize Variable to store size of context data values 228 229 @return An error code: 0 - success, otherwise - failure 230 231 @ref Advanced 232 **/ 233 234 int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) { 235 *ctxsize = qf->ctxsize; 236 return 0; 237 } 238 239 /** 240 @brief Get global context for a CeedQFunction 241 242 @param qf CeedQFunction 243 @param[out] ctx Variable to store context data values 244 245 @return An error code: 0 - success, otherwise - failure 246 247 @ref Advanced 248 **/ 249 250 int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) { 251 *ctx = qf->ctx; 252 return 0; 253 } 254 255 /** 256 @brief Get backend data of a CeedQFunction 257 258 @param qf CeedQFunction 259 @param[out] data Variable to store data 260 261 @return An error code: 0 - success, otherwise - failure 262 263 @ref Advanced 264 **/ 265 266 int CeedQFunctionGetData(CeedQFunction qf, void* *data) { 267 *data = qf->data; 268 return 0; 269 } 270 271 /** 272 @brief Set global context for a CeedQFunction 273 274 @param qf CeedQFunction 275 @param ctx Context data to set 276 @param ctxsize Size of context data values 277 278 @return An error code: 0 - success, otherwise - failure 279 280 @ref Basic 281 **/ 282 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 283 qf->ctx = ctx; 284 qf->ctxsize = ctxsize; 285 return 0; 286 } 287 288 /** 289 @brief Apply the action of a CeedQFunction 290 291 @param qf CeedQFunction 292 @param Q Number of quadrature points 293 @param[in] u Array of input data arrays 294 @param[out] v Array of output data arrays 295 296 @return An error code: 0 - success, otherwise - failure 297 298 @ref Advanced 299 **/ 300 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 301 const CeedScalar *const *u, 302 CeedScalar *const *v) { 303 int ierr; 304 if (!qf->Apply) 305 return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 306 if (Q % qf->vlength) 307 return CeedError(qf->ceed, 2, 308 "Number of quadrature points %d must be a multiple of %d", 309 Q, qf->vlength); 310 ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 311 return 0; 312 } 313 314 /** 315 @brief Get the CeedQFunctionFields of a CeedQFunction 316 317 @param qf CeedQFunction 318 @param[out] inputfields Variable to store inputfields 319 @param[out] outputfields Variable to store outputfields 320 321 @return An error code: 0 - success, otherwise - failure 322 323 @ref Advanced 324 **/ 325 326 int CeedQFunctionGetFields(CeedQFunction qf, 327 CeedQFunctionField* *inputfields, 328 CeedQFunctionField* *outputfields) { 329 if (inputfields) *inputfields = qf->inputfields; 330 if (outputfields) *outputfields = qf->outputfields; 331 return 0; 332 } 333 334 /** 335 @brief Get the number of components of a CeedQFunctionField 336 337 @param qffield CeedQFunctionField 338 @param[out] numcomp Variable to store the number of components 339 340 @return An error code: 0 - success, otherwise - failure 341 342 @ref Advanced 343 **/ 344 345 int CeedQFunctionFieldGetNumComponents(CeedQFunctionField qffield, 346 CeedInt *numcomp) { 347 *numcomp = (&qffield)->ncomp; 348 return 0; 349 } 350 351 /** 352 @brief Get the CeedEvalMode of a CeedQFunctionField 353 354 @param qffield CeedQFunctionField 355 @param[out] vec Variable to store the number of components 356 357 @return An error code: 0 - success, otherwise - failure 358 359 @ref Advanced 360 **/ 361 362 int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qffield, 363 CeedEvalMode *emode) { 364 *emode = (&qffield)->emode; 365 return 0; 366 } 367 368 /** 369 @brief Destroy a CeedQFunction 370 371 @param qf CeedQFunction to destroy 372 373 @return An error code: 0 - success, otherwise - failure 374 375 @ref Basic 376 **/ 377 int CeedQFunctionDestroy(CeedQFunction *qf) { 378 int ierr; 379 380 if (!*qf || --(*qf)->refcount > 0) return 0; 381 // Free field names 382 for (int i=0; i<(*qf)->numinputfields; i++) { 383 ierr = CeedFree(&(*qf)->inputfields[i].fieldname); CeedChk(ierr); 384 } 385 for (int i=0; i<(*qf)->numoutputfields; i++) { 386 ierr = CeedFree(&(*qf)->outputfields[i].fieldname); CeedChk(ierr); 387 } 388 if ((*qf)->Destroy) { 389 ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 390 } 391 ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 392 ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 393 ierr = CeedFree(qf); CeedChk(ierr); 394 return 0; 395 } 396 397 /// @} 398