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 CeedOperator interfaces 23 /// 24 /// @addtogroup CeedOperator 25 /// @{ 26 27 /** 28 @brief Create an operator from element restriction, basis, and QFunction 29 30 @param ceed A Ceed object where the CeedOperator will be created 31 @param qf QFunction defining the action of the operator at quadrature points 32 @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 33 @param dqfT QFunction defining the action of the transpose of the Jacobian 34 of @a qf (or NULL) 35 @param[out] op Address of the variable where the newly created 36 CeedOperator will be stored 37 38 @return An error code: 0 - success, otherwise - failure 39 40 @ref Basic 41 */ 42 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 43 CeedQFunction dqfT, CeedOperator *op) { 44 int ierr; 45 46 if (!ceed->OperatorCreate) { 47 Ceed delegate; 48 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 49 50 if (!delegate) 51 return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 52 53 ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 54 return 0; 55 } 56 57 ierr = CeedCalloc(1,op); CeedChk(ierr); 58 (*op)->ceed = ceed; 59 ceed->refcount++; 60 (*op)->refcount = 1; 61 (*op)->qf = qf; 62 qf->refcount++; 63 (*op)->dqf = dqf; 64 if (dqf) dqf->refcount++; 65 (*op)->dqfT = dqfT; 66 if (dqfT) dqfT->refcount++; 67 ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 68 ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 69 ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 70 return 0; 71 } 72 73 /** 74 @brief Create an operator that composes the action of several operators 75 76 @param ceed A Ceed object where the CeedOperator will be created 77 @param[out] op Address of the variable where the newly created 78 Composite CeedOperator will be stored 79 80 @return An error code: 0 - success, otherwise - failure 81 82 @ref Basic 83 */ 84 int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 85 int ierr; 86 87 if (!ceed->CompositeOperatorCreate) { 88 Ceed delegate; 89 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 90 91 if (!delegate) 92 return CeedError(ceed, 1, "Backend does not support \ 93 CompositeOperatorCreate"); 94 95 ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 96 return 0; 97 } 98 99 ierr = CeedCalloc(1,op); CeedChk(ierr); 100 (*op)->ceed = ceed; 101 ceed->refcount++; 102 (*op)->composite = true; 103 ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 104 ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 105 return 0; 106 } 107 108 /** 109 @brief Provide a field to a CeedOperator for use by its CeedQFunction 110 111 This function is used to specify both active and passive fields to a 112 CeedOperator. For passive fields, a vector @arg v must be provided. Passive 113 fields can inputs or outputs (updated in-place when operator is applied). 114 115 Active fields must be specified using this function, but their data (in a 116 CeedVector) is passed in CeedOperatorApply(). There can be at most one active 117 input and at most one active output. 118 119 @param op CeedOperator on which to provide the field 120 @param fieldname Name of the field (to be matched with the name used by 121 CeedQFunction) 122 @param r CeedElemRestriction 123 @param lmode CeedTransposeMode which specifies the ordering of the 124 components of the l-vector used by this CeedOperatorField, 125 CEED_NOTRANSPOSE indicates the component is the 126 outermost index and CEED_TRANSPOSE indicates the component 127 is the innermost index in ordering of the l-vector 128 @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 129 if collocated with quadrature points 130 @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 131 if field is active or CEED_VECTOR_NONE if using 132 CEED_EVAL_WEIGHT in the QFunction 133 134 @return An error code: 0 - success, otherwise - failure 135 136 @ref Basic 137 **/ 138 int CeedOperatorSetField(CeedOperator op, const char *fieldname, 139 CeedElemRestriction r, CeedTransposeMode lmode, 140 CeedBasis b, CeedVector v) { 141 int ierr; 142 if (op->composite) 143 return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 144 145 CeedInt numelements; 146 ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 147 if (op->numelements && op->numelements != numelements) 148 return CeedError(op->ceed, 1, 149 "ElemRestriction with %d elements incompatible with prior %d elements", 150 numelements, op->numelements); 151 op->numelements = numelements; 152 153 if (b != CEED_BASIS_COLLOCATED) { 154 CeedInt numqpoints; 155 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 156 if (op->numqpoints && op->numqpoints != numqpoints) 157 return CeedError(op->ceed, 1, 158 "Basis with %d quadrature points incompatible with prior %d points", 159 numqpoints, op->numqpoints); 160 op->numqpoints = numqpoints; 161 } 162 CeedOperatorField *ofield; 163 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 164 if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 165 ofield = &op->inputfields[i]; 166 goto found; 167 } 168 } 169 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 170 if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 171 ofield = &op->outputfields[i]; 172 goto found; 173 } 174 } 175 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 176 fieldname); 177 found: 178 ierr = CeedCalloc(1, ofield); CeedChk(ierr); 179 (*ofield)->Erestrict = r; 180 (*ofield)->lmode = lmode; 181 (*ofield)->basis = b; 182 (*ofield)->vec = v; 183 op->nfields += 1; 184 return 0; 185 } 186 187 /** 188 @brief Add a sub-operator to a composite CeedOperator 189 @param[out] op Address of the composite CeedOperator 190 @param op Address of the sub-operator CeedOperator 191 192 @return An error code: 0 - success, otherwise - failure 193 194 @ref Basic 195 */ 196 int CeedCompositeOperatorAddSub(CeedOperator compositeop, 197 CeedOperator subop) { 198 if (!compositeop->composite) 199 return CeedError(compositeop->ceed, 1, 200 "CeedOperator is not a composite operator"); 201 202 if (compositeop->numsub == CEED_COMPOSITE_MAX) 203 return CeedError(compositeop->ceed, 1, 204 "Cannot add additional suboperators"); 205 206 compositeop->suboperators[compositeop->numsub] = subop; 207 subop->refcount++; 208 compositeop->numsub++; 209 return 0; 210 } 211 212 /** 213 @brief Apply CeedOperator to a vector 214 215 This computes the action of the operator on the specified (active) input, 216 yielding its (active) output. All inputs and outputs must be specified using 217 CeedOperatorSetField(). 218 219 @param op CeedOperator to apply 220 @param[in] in CeedVector containing input state or NULL if there are no 221 active inputs 222 @param[out] out CeedVector to store result of applying operator (must be 223 distinct from @a in) or NULL if there are no active outputs 224 @param request Address of CeedRequest for non-blocking completion, else 225 CEED_REQUEST_IMMEDIATE 226 227 @return An error code: 0 - success, otherwise - failure 228 229 @ref Basic 230 **/ 231 int CeedOperatorApply(CeedOperator op, CeedVector in, 232 CeedVector out, CeedRequest *request) { 233 int ierr; 234 Ceed ceed = op->ceed; 235 CeedQFunction qf = op->qf; 236 237 if (op->composite) { 238 if (!op->numsub) return CeedError(ceed, 1, "No suboperators set"); 239 } else { 240 if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 241 if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 242 ceed, 1, "Not all operator fields set"); 243 if (op->numelements == 0) return CeedError(ceed, 1, 244 "At least one restriction required"); 245 if (op->numqpoints == 0) return CeedError(ceed, 1, 246 "At least one non-collocated basis required"); 247 } 248 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 249 return 0; 250 } 251 252 /** 253 @brief Get the Ceed associated with a CeedOperator 254 255 @param op CeedOperator 256 @param[out] ceed Variable to store Ceed 257 258 @return An error code: 0 - success, otherwise - failure 259 260 @ref Advanced 261 **/ 262 263 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 264 *ceed = op->ceed; 265 return 0; 266 } 267 268 /** 269 @brief Get the number of elements associated with a CeedOperator 270 271 @param op CeedOperator 272 @param[out] numelem Variable to store number of elements 273 274 @return An error code: 0 - success, otherwise - failure 275 276 @ref Advanced 277 **/ 278 279 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 280 if (op->composite) 281 return CeedError(op->ceed, 1, "Not defined for composite operator"); 282 283 *numelem = op->numelements; 284 return 0; 285 } 286 287 /** 288 @brief Get the number of quadrature points associated with a CeedOperator 289 290 @param op CeedOperator 291 @param[out] numqpts Variable to store vector number of quadrature points 292 293 @return An error code: 0 - success, otherwise - failure 294 295 @ref Advanced 296 **/ 297 298 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 299 if (op->composite) 300 return CeedError(op->ceed, 1, "Not defined for composite operator"); 301 302 *numqpts = op->numqpoints; 303 return 0; 304 } 305 306 /** 307 @brief Get the number of arguments associated with a CeedOperator 308 309 @param op CeedOperator 310 @param[out] numargs Variable to store vector number of arguments 311 312 @return An error code: 0 - success, otherwise - failure 313 314 @ref Advanced 315 **/ 316 317 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 318 if (op->composite) 319 return CeedError(op->ceed, 1, "Not defined for composite operators"); 320 *numargs = op->nfields; 321 return 0; 322 } 323 324 /** 325 @brief Get the setup status of a CeedOperator 326 327 @param op CeedOperator 328 @param[out] numelem Variable to store setup status 329 330 @return An error code: 0 - success, otherwise - failure 331 332 @ref Advanced 333 **/ 334 335 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 336 *setupdone = op->setupdone; 337 return 0; 338 } 339 340 /** 341 @brief Get the QFunction associated with a CeedOperator 342 343 @param op CeedOperator 344 @param[out] qf Variable to store QFunction 345 346 @return An error code: 0 - success, otherwise - failure 347 348 @ref Advanced 349 **/ 350 351 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 352 if (op->composite) 353 return CeedError(op->ceed, 1, "Not defined for composite operator"); 354 355 *qf = op->qf; 356 return 0; 357 } 358 359 /** 360 @brief Get the number of suboperators associated with a CeedOperator 361 362 @param op CeedOperator 363 @param[out] numsub Variable to store number of suboperators 364 365 @return An error code: 0 - success, otherwise - failure 366 367 @ref Advanced 368 **/ 369 370 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 371 Ceed ceed = op->ceed; 372 if (!op->composite) return CeedError(ceed, 1, "Not a composite operator"); 373 374 *numsub = op->numsub; 375 return 0; 376 } 377 378 /** 379 @brief Get the list of suboperators associated with a CeedOperator 380 381 @param op CeedOperator 382 @param[out] suboperators Variable to store list of suboperators 383 384 @return An error code: 0 - success, otherwise - failure 385 386 @ref Advanced 387 **/ 388 389 int CeedOperatorGetSubList(CeedOperator op, CeedOperator* *suboperators) { 390 Ceed ceed = op->ceed; 391 if (!op->composite) return CeedError(ceed, 1, "Not a composite operator"); 392 393 *suboperators = op->suboperators; 394 return 0; 395 } 396 397 /** 398 @brief Set the backend data of a CeedOperator 399 400 @param[out] op CeedOperator 401 @param data Data to set 402 403 @return An error code: 0 - success, otherwise - failure 404 405 @ref Advanced 406 **/ 407 408 int CeedOperatorSetData(CeedOperator op, void* *data) { 409 op->data = *data; 410 return 0; 411 } 412 413 /** 414 @brief Get the backend data of a CeedOperator 415 416 @param op CeedOperator 417 @param[out] data Variable to store data 418 419 @return An error code: 0 - success, otherwise - failure 420 421 @ref Advanced 422 **/ 423 424 int CeedOperatorGetData(CeedOperator op, void* *data) { 425 *data = op->data; 426 return 0; 427 } 428 429 /** 430 @brief Set the setup flag of a CeedOperator to True 431 432 @param op CeedOperator 433 434 @return An error code: 0 - success, otherwise - failure 435 436 @ref Advanced 437 **/ 438 439 int CeedOperatorSetSetupDone(CeedOperator op) { 440 op->setupdone = 1; 441 return 0; 442 } 443 444 /** 445 @brief Get the CeedOperatorFields of a CeedOperator 446 447 @param op CeedOperator 448 @param[out] inputfields Variable to store inputfields 449 @param[out] outputfields Variable to store outputfields 450 451 @return An error code: 0 - success, otherwise - failure 452 453 @ref Advanced 454 **/ 455 456 int CeedOperatorGetFields(CeedOperator op, 457 CeedOperatorField* *inputfields, 458 CeedOperatorField* *outputfields) { 459 if (op->composite) 460 return CeedError(op->ceed, 1, "Not defined for composite operator"); 461 462 if (inputfields) *inputfields = op->inputfields; 463 if (outputfields) *outputfields = op->outputfields; 464 return 0; 465 } 466 467 /** 468 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 469 470 @param opfield CeedOperatorField 471 @param[out] lmode Variable to store CeedTransposeMode 472 473 @return An error code: 0 - success, otherwise - failure 474 475 @ref Advanced 476 **/ 477 478 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 479 CeedTransposeMode *lmode) { 480 *lmode = opfield->lmode; 481 return 0; 482 }/** 483 @brief Get the CeedElemRestriction of a CeedOperatorField 484 485 @param opfield CeedOperatorField 486 @param[out] rstr Variable to store CeedElemRestriction 487 488 @return An error code: 0 - success, otherwise - failure 489 490 @ref Advanced 491 **/ 492 493 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 494 CeedElemRestriction *rstr) { 495 *rstr = opfield->Erestrict; 496 return 0; 497 } 498 499 /** 500 @brief Get the CeedBasis of a CeedOperatorField 501 502 @param opfield CeedOperatorField 503 @param[out] basis Variable to store CeedBasis 504 505 @return An error code: 0 - success, otherwise - failure 506 507 @ref Advanced 508 **/ 509 510 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, 511 CeedBasis *basis) { 512 *basis = opfield->basis; 513 return 0; 514 } 515 516 /** 517 @brief Get the CeedVector of a CeedOperatorField 518 519 @param opfield CeedOperatorField 520 @param[out] vec Variable to store CeedVector 521 522 @return An error code: 0 - success, otherwise - failure 523 524 @ref Advanced 525 **/ 526 527 int CeedOperatorFieldGetVector(CeedOperatorField opfield, 528 CeedVector *vec) { 529 *vec = opfield->vec; 530 return 0; 531 } 532 533 /** 534 @brief Destroy a CeedOperator 535 536 @param op CeedOperator to destroy 537 538 @return An error code: 0 - success, otherwise - failure 539 540 @ref Basic 541 **/ 542 int CeedOperatorDestroy(CeedOperator *op) { 543 int ierr; 544 545 if (!*op || --(*op)->refcount > 0) return 0; 546 if ((*op)->Destroy) { 547 ierr = (*op)->Destroy(*op); CeedChk(ierr); 548 } 549 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 550 // Free fields 551 for (int i=0; i<(*op)->nfields; i++) { 552 if ((*op)->inputfields[i]) { 553 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 554 } 555 } 556 for (int i=0; i<(*op)->nfields; i++) { 557 if ((*op)->outputfields[i]) { 558 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 559 } 560 } 561 // Destroy suboperators 562 for (int i=0; i<(*op)->numsub; i++) { 563 if ((*op)->suboperators[i]) { 564 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 565 } 566 } 567 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 568 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 569 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 570 571 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 572 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 573 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 574 ierr = CeedFree(op); CeedChk(ierr); 575 return 0; 576 } 577 578 /// @} 579