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