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