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