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