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 = CeedCalloc(16, &(*qf)->inputfields); CeedChk(ierr); 81 ierr = CeedCalloc(16, &(*qf)->outputfields); CeedChk(ierr); 82 ierr = ceed->QFunctionCreate(*qf); CeedChk(ierr); 83 return 0; 84 } 85 86 /** 87 @brief Set a CeedQFunction field, used by CeedQFunctionAddInput/Output 88 89 @param f CeedQFunctionField 90 @param fieldname Name of QFunction field 91 @param ncomp Number of components per quadrature node 92 @param emode \ref CEED_EVAL_NONE to use values directly, 93 \ref CEED_EVAL_INTERP to use interpolated values, 94 \ref CEED_EVAL_GRAD to use gradients. 95 96 @return An error code: 0 - success, otherwise - failure 97 98 @ref Developer 99 **/ 100 static int CeedQFunctionFieldSet(CeedQFunctionField *f,const char *fieldname, 101 CeedInt ncomp, CeedEvalMode emode) { 102 size_t len = strlen(fieldname); 103 char *tmp; 104 int ierr; 105 ierr = CeedCalloc(1,f); CeedChk(ierr); 106 107 ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 108 memcpy(tmp, fieldname, len+1); 109 (*f)->fieldname = tmp; 110 (*f)->ncomp = ncomp; 111 (*f)->emode = emode; 112 return 0; 113 } 114 115 /** 116 @brief Add a CeedQFunction input 117 118 @param qf CeedQFunction 119 @param fieldname Name of QFunction field 120 @param ncomp Number of components per quadrature node 121 @param emode \ref CEED_EVAL_NONE to use values directly, 122 \ref CEED_EVAL_INTERP to use interpolated values, 123 \ref CEED_EVAL_GRAD to use gradients. 124 125 @return An error code: 0 - success, otherwise - failure 126 127 @ref Basic 128 **/ 129 int CeedQFunctionAddInput(CeedQFunction qf, const char *fieldname, 130 CeedInt ncomp, CeedEvalMode emode) { 131 int ierr = CeedQFunctionFieldSet(&qf->inputfields[qf->numinputfields], 132 fieldname, ncomp, emode); 133 CeedChk(ierr); 134 qf->numinputfields++; 135 return 0; 136 } 137 138 /** 139 @brief Add a CeedQFunction output 140 141 @param qf CeedQFunction 142 @param fieldname Name of QFunction field 143 @param ncomp Number of components per quadrature node 144 @param emode \ref CEED_EVAL_NONE to use values directly, 145 \ref CEED_EVAL_INTERP to use interpolated values, 146 \ref CEED_EVAL_GRAD to use gradients. 147 148 @return An error code: 0 - success, otherwise - failure 149 150 @ref Basic 151 **/ 152 int CeedQFunctionAddOutput(CeedQFunction qf, const char *fieldname, 153 CeedInt ncomp, CeedEvalMode emode) { 154 if (emode == CEED_EVAL_WEIGHT) 155 return CeedError(qf->ceed, 1, 156 "Cannot create qfunction output with CEED_EVAL_WEIGHT"); 157 int ierr = CeedQFunctionFieldSet(&qf->outputfields[qf->numoutputfields], 158 fieldname, ncomp, emode); 159 CeedChk(ierr); 160 qf->numoutputfields++; 161 return 0; 162 } 163 164 /** 165 @brief Get the Ceed associated with a CeedQFunction 166 167 @param qf CeedQFunction 168 @param[out] ceed Variable to store Ceed 169 170 @return An error code: 0 - success, otherwise - failure 171 172 @ref Advanced 173 **/ 174 175 int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) { 176 *ceed = qf->ceed; 177 return 0; 178 } 179 180 /** 181 @brief Get the vector length of a CeedQFunction 182 183 @param qf CeedQFunction 184 @param[out] veclength Variable to store vector length 185 186 @return An error code: 0 - success, otherwise - failure 187 188 @ref Advanced 189 **/ 190 191 int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vlength) { 192 *vlength = qf->vlength; 193 return 0; 194 } 195 196 /** 197 @brief Get the number of inputs and outputs to a CeedQFunction 198 199 @param qf CeedQFunction 200 @param[out] numinput Variable to store number of input fields 201 @param[out] numoutput Variable to store number of output fields 202 203 @return An error code: 0 - success, otherwise - failure 204 205 @ref Advanced 206 **/ 207 208 int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *numinput, 209 CeedInt *numoutput) { 210 if (numinput) *numinput = qf->numinputfields; 211 if (numoutput) *numoutput = qf->numoutputfields; 212 return 0; 213 } 214 215 /** 216 @brief Get the FOCCA string for a CeedQFunction 217 218 @param qf CeedQFunction 219 @param[out] focca Variable to store focca string 220 221 @return An error code: 0 - success, otherwise - failure 222 223 @ref Advanced 224 **/ 225 226 int CeedQFunctionGetFOCCA(CeedQFunction qf, char* *focca) { 227 *focca = (char*) qf->focca; 228 return 0; 229 } 230 231 /** 232 @brief Get the User Function for a CeedQFunction 233 234 @param qf CeedQFunction 235 @param[out] f Variable to store user function 236 237 @return An error code: 0 - success, otherwise - failure 238 239 @ref Advanced 240 **/ 241 242 int CeedQFunctionGetUserFunction(CeedQFunction qf, int (**f)()) { 243 *f = (int (*)())qf->function; 244 return 0; 245 } 246 247 /** 248 @brief Get global context size for a CeedQFunction 249 250 @param qf CeedQFunction 251 @param[out] ctxsize Variable to store size of context data values 252 253 @return An error code: 0 - success, otherwise - failure 254 255 @ref Advanced 256 **/ 257 258 int CeedQFunctionGetContextSize(CeedQFunction qf, size_t *ctxsize) { 259 *ctxsize = qf->ctxsize; 260 return 0; 261 } 262 263 /** 264 @brief Get global context for a CeedQFunction 265 266 @param qf CeedQFunction 267 @param[out] ctx Variable to store context data values 268 269 @return An error code: 0 - success, otherwise - failure 270 271 @ref Advanced 272 **/ 273 274 int CeedQFunctionGetContext(CeedQFunction qf, void* *ctx) { 275 *ctx = qf->ctx; 276 return 0; 277 } 278 279 /** 280 @brief Get backend data of a CeedQFunction 281 282 @param qf CeedQFunction 283 @param[out] data Variable to store data 284 285 @return An error code: 0 - success, otherwise - failure 286 287 @ref Advanced 288 **/ 289 290 int CeedQFunctionGetData(CeedQFunction qf, void* *data) { 291 *data = qf->data; 292 return 0; 293 } 294 295 /** 296 @brief Set backend data of a CeedQFunction 297 298 @param[out] qf CeedQFunction 299 @param data Data to set 300 301 @return An error code: 0 - success, otherwise - failure 302 303 @ref Advanced 304 **/ 305 306 int CeedQFunctionSetData(CeedQFunction qf, void* *data) { 307 qf->data = *data; 308 return 0; 309 } 310 311 /** 312 @brief Set global context for a CeedQFunction 313 314 @param qf CeedQFunction 315 @param ctx Context data to set 316 @param ctxsize Size of context data values 317 318 @return An error code: 0 - success, otherwise - failure 319 320 @ref Basic 321 **/ 322 int CeedQFunctionSetContext(CeedQFunction qf, void *ctx, size_t ctxsize) { 323 qf->ctx = ctx; 324 qf->ctxsize = ctxsize; 325 return 0; 326 } 327 328 /** 329 @brief Apply the action of a CeedQFunction 330 331 @param qf CeedQFunction 332 @param Q Number of quadrature points 333 @param[in] u Array of input data arrays 334 @param[out] v Array of output data arrays 335 336 @return An error code: 0 - success, otherwise - failure 337 338 @ref Advanced 339 **/ 340 int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, 341 const CeedScalar *const *u, 342 CeedScalar *const *v) { 343 int ierr; 344 if (!qf->Apply) 345 return CeedError(qf->ceed, 1, "Backend does not support QFunctionApply"); 346 if (Q % qf->vlength) 347 return CeedError(qf->ceed, 2, 348 "Number of quadrature points %d must be a multiple of %d", 349 Q, qf->vlength); 350 ierr = qf->Apply(qf, Q, u, v); CeedChk(ierr); 351 return 0; 352 } 353 354 /** 355 @brief Get the CeedQFunctionFields of a CeedQFunction 356 357 @param qf CeedQFunction 358 @param[out] inputfields Variable to store inputfields 359 @param[out] outputfields Variable to store outputfields 360 361 @return An error code: 0 - success, otherwise - failure 362 363 @ref Advanced 364 **/ 365 366 int CeedQFunctionGetFields(CeedQFunction qf, 367 CeedQFunctionField* *inputfields, 368 CeedQFunctionField* *outputfields) { 369 if (inputfields) *inputfields = qf->inputfields; 370 if (outputfields) *outputfields = qf->outputfields; 371 return 0; 372 } 373 374 /** 375 @brief Get the name of a CeedQFunctionField 376 377 @param qffield CeedQFunctionField 378 @param[out] fieldname Variable to store the field name 379 380 @return An error code: 0 - success, otherwise - failure 381 382 @ref Advanced 383 **/ 384 385 int CeedQFunctionFieldGetName(CeedQFunctionField qffield, 386 char* *fieldname) { 387 *fieldname = (char *)qffield->fieldname; 388 return 0; 389 } 390 391 /** 392 @brief Get the number of components of a CeedQFunctionField 393 394 @param qffield CeedQFunctionField 395 @param[out] numcomp Variable to store the number of components 396 397 @return An error code: 0 - success, otherwise - failure 398 399 @ref Advanced 400 **/ 401 402 int CeedQFunctionFieldGetNumComponents(CeedQFunctionField qffield, 403 CeedInt *numcomp) { 404 *numcomp = qffield->ncomp; 405 return 0; 406 } 407 408 /** 409 @brief Get the CeedEvalMode of a CeedQFunctionField 410 411 @param qffield CeedQFunctionField 412 @param[out] vec Variable to store the number of components 413 414 @return An error code: 0 - success, otherwise - failure 415 416 @ref Advanced 417 **/ 418 419 int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qffield, 420 CeedEvalMode *emode) { 421 *emode = qffield->emode; 422 return 0; 423 } 424 425 /** 426 @brief Destroy a CeedQFunction 427 428 @param qf CeedQFunction to destroy 429 430 @return An error code: 0 - success, otherwise - failure 431 432 @ref Basic 433 **/ 434 int CeedQFunctionDestroy(CeedQFunction *qf) { 435 int ierr; 436 437 if (!*qf || --(*qf)->refcount > 0) return 0; 438 // Backend destroy 439 if ((*qf)->Destroy) { 440 ierr = (*qf)->Destroy(*qf); CeedChk(ierr); 441 } 442 // Free fields 443 for (int i=0; i<(*qf)->numinputfields; i++) { 444 ierr = CeedFree(&(*(*qf)->inputfields[i]).fieldname); CeedChk(ierr); 445 ierr = CeedFree(&(*qf)->inputfields[i]); CeedChk(ierr); 446 } 447 for (int i=0; i<(*qf)->numoutputfields; i++) { 448 ierr = CeedFree(&(*(*qf)->outputfields[i]).fieldname); CeedChk(ierr); 449 ierr = CeedFree(&(*qf)->outputfields[i]); CeedChk(ierr); 450 } 451 ierr = CeedFree(&(*qf)->inputfields); CeedChk(ierr); 452 ierr = CeedFree(&(*qf)->outputfields); CeedChk(ierr); 453 454 ierr = CeedFree(&(*qf)->focca); CeedChk(ierr); 455 ierr = CeedDestroy(&(*qf)->ceed); CeedChk(ierr); 456 ierr = CeedFree(qf); CeedChk(ierr); 457 return 0; 458 } 459 460 /// @} 461