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