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 if (!r) 145 return CeedError(op->ceed, 1, "ElemRestriction r for field \"%s\" must be non-NULL.", fieldname); 146 if (!b) 147 return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.", fieldname); 148 if (!v) 149 return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.", fieldname); 150 151 CeedInt numelements; 152 ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 153 if (op->numelements && op->numelements != numelements) 154 return CeedError(op->ceed, 1, 155 "ElemRestriction with %d elements incompatible with prior %d elements", 156 numelements, op->numelements); 157 op->numelements = numelements; 158 159 if (b != CEED_BASIS_COLLOCATED) { 160 CeedInt numqpoints; 161 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 162 if (op->numqpoints && op->numqpoints != numqpoints) 163 return CeedError(op->ceed, 1, 164 "Basis with %d quadrature points incompatible with prior %d points", 165 numqpoints, op->numqpoints); 166 op->numqpoints = numqpoints; 167 } 168 CeedOperatorField *ofield; 169 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 170 if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 171 ofield = &op->inputfields[i]; 172 goto found; 173 } 174 } 175 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 176 if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 177 ofield = &op->outputfields[i]; 178 goto found; 179 } 180 } 181 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 182 fieldname); 183 found: 184 ierr = CeedCalloc(1, ofield); CeedChk(ierr); 185 (*ofield)->Erestrict = r; 186 (*ofield)->lmode = lmode; 187 (*ofield)->basis = b; 188 (*ofield)->vec = v; 189 op->nfields += 1; 190 return 0; 191 } 192 193 /** 194 @brief Add a sub-operator to a composite CeedOperator 195 196 @param[out] compositeop Address of the composite CeedOperator 197 @param subop Address of the sub-operator CeedOperator 198 199 @return An error code: 0 - success, otherwise - failure 200 201 @ref Basic 202 */ 203 int CeedCompositeOperatorAddSub(CeedOperator compositeop, 204 CeedOperator subop) { 205 if (!compositeop->composite) 206 return CeedError(compositeop->ceed, 1, 207 "CeedOperator is not a composite operator"); 208 209 if (compositeop->numsub == CEED_COMPOSITE_MAX) 210 return CeedError(compositeop->ceed, 1, 211 "Cannot add additional suboperators"); 212 213 compositeop->suboperators[compositeop->numsub] = subop; 214 subop->refcount++; 215 compositeop->numsub++; 216 return 0; 217 } 218 219 /** 220 @brief Apply CeedOperator to a vector 221 222 This computes the action of the operator on the specified (active) input, 223 yielding its (active) output. All inputs and outputs must be specified using 224 CeedOperatorSetField(). 225 226 @param op CeedOperator to apply 227 @param[in] in CeedVector containing input state or NULL if there are no 228 active inputs 229 @param[out] out CeedVector to store result of applying operator (must be 230 distinct from @a in) or NULL if there are no active outputs 231 @param request Address of CeedRequest for non-blocking completion, else 232 CEED_REQUEST_IMMEDIATE 233 234 @return An error code: 0 - success, otherwise - failure 235 236 @ref Basic 237 **/ 238 int CeedOperatorApply(CeedOperator op, CeedVector in, 239 CeedVector out, CeedRequest *request) { 240 int ierr; 241 Ceed ceed = op->ceed; 242 CeedQFunction qf = op->qf; 243 244 if (op->composite) { 245 if (!op->numsub) return CeedError(ceed, 1, "No suboperators set"); 246 } else { 247 if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 248 if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 249 ceed, 1, "Not all operator fields set"); 250 if (op->numelements == 0) return CeedError(ceed, 1, 251 "At least one restriction required"); 252 if (op->numqpoints == 0) return CeedError(ceed, 1, 253 "At least one non-collocated basis required"); 254 } 255 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 256 return 0; 257 } 258 259 /** 260 @brief Get the Ceed associated with a CeedOperator 261 262 @param op CeedOperator 263 @param[out] ceed Variable to store Ceed 264 265 @return An error code: 0 - success, otherwise - failure 266 267 @ref Advanced 268 **/ 269 270 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 271 *ceed = op->ceed; 272 return 0; 273 } 274 275 /** 276 @brief Get the number of elements associated with a CeedOperator 277 278 @param op CeedOperator 279 @param[out] numelem Variable to store number of elements 280 281 @return An error code: 0 - success, otherwise - failure 282 283 @ref Advanced 284 **/ 285 286 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 287 if (op->composite) 288 return CeedError(op->ceed, 1, "Not defined for composite operator"); 289 290 *numelem = op->numelements; 291 return 0; 292 } 293 294 /** 295 @brief Get the number of quadrature points associated with a CeedOperator 296 297 @param op CeedOperator 298 @param[out] numqpts Variable to store vector number of quadrature points 299 300 @return An error code: 0 - success, otherwise - failure 301 302 @ref Advanced 303 **/ 304 305 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 306 if (op->composite) 307 return CeedError(op->ceed, 1, "Not defined for composite operator"); 308 309 *numqpts = op->numqpoints; 310 return 0; 311 } 312 313 /** 314 @brief Get the number of arguments associated with a CeedOperator 315 316 @param op CeedOperator 317 @param[out] numargs Variable to store vector number of arguments 318 319 @return An error code: 0 - success, otherwise - failure 320 321 @ref Advanced 322 **/ 323 324 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 325 if (op->composite) 326 return CeedError(op->ceed, 1, "Not defined for composite operators"); 327 *numargs = op->nfields; 328 return 0; 329 } 330 331 /** 332 @brief Get the setup status of a CeedOperator 333 334 @param op CeedOperator 335 @param[out] setupdone Variable to store setup status 336 337 @return An error code: 0 - success, otherwise - failure 338 339 @ref Advanced 340 **/ 341 342 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 343 *setupdone = op->setupdone; 344 return 0; 345 } 346 347 /** 348 @brief Get the QFunction associated with a CeedOperator 349 350 @param op CeedOperator 351 @param[out] qf Variable to store QFunction 352 353 @return An error code: 0 - success, otherwise - failure 354 355 @ref Advanced 356 **/ 357 358 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 359 if (op->composite) 360 return CeedError(op->ceed, 1, "Not defined for composite operator"); 361 362 *qf = op->qf; 363 return 0; 364 } 365 366 /** 367 @brief Get the number of suboperators associated with a CeedOperator 368 369 @param op CeedOperator 370 @param[out] numsub Variable to store number of suboperators 371 372 @return An error code: 0 - success, otherwise - failure 373 374 @ref Advanced 375 **/ 376 377 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 378 Ceed ceed = op->ceed; 379 if (!op->composite) return CeedError(ceed, 1, "Not a composite operator"); 380 381 *numsub = op->numsub; 382 return 0; 383 } 384 385 /** 386 @brief Get the list of suboperators associated with a CeedOperator 387 388 @param op CeedOperator 389 @param[out] suboperators Variable to store list of suboperators 390 391 @return An error code: 0 - success, otherwise - failure 392 393 @ref Advanced 394 **/ 395 396 int CeedOperatorGetSubList(CeedOperator op, CeedOperator* *suboperators) { 397 Ceed ceed = op->ceed; 398 if (!op->composite) return CeedError(ceed, 1, "Not a composite operator"); 399 400 *suboperators = op->suboperators; 401 return 0; 402 } 403 404 /** 405 @brief Set the backend data of a CeedOperator 406 407 @param[out] op CeedOperator 408 @param data Data to set 409 410 @return An error code: 0 - success, otherwise - failure 411 412 @ref Advanced 413 **/ 414 415 int CeedOperatorSetData(CeedOperator op, void* *data) { 416 op->data = *data; 417 return 0; 418 } 419 420 /** 421 @brief Get the backend data of a CeedOperator 422 423 @param op CeedOperator 424 @param[out] data Variable to store data 425 426 @return An error code: 0 - success, otherwise - failure 427 428 @ref Advanced 429 **/ 430 431 int CeedOperatorGetData(CeedOperator op, void* *data) { 432 *data = op->data; 433 return 0; 434 } 435 436 /** 437 @brief Set the setup flag of a CeedOperator to True 438 439 @param op CeedOperator 440 441 @return An error code: 0 - success, otherwise - failure 442 443 @ref Advanced 444 **/ 445 446 int CeedOperatorSetSetupDone(CeedOperator op) { 447 op->setupdone = 1; 448 return 0; 449 } 450 451 /** 452 @brief Get the CeedOperatorFields of a CeedOperator 453 454 @param op CeedOperator 455 @param[out] inputfields Variable to store inputfields 456 @param[out] outputfields Variable to store outputfields 457 458 @return An error code: 0 - success, otherwise - failure 459 460 @ref Advanced 461 **/ 462 463 int CeedOperatorGetFields(CeedOperator op, 464 CeedOperatorField* *inputfields, 465 CeedOperatorField* *outputfields) { 466 if (op->composite) 467 return CeedError(op->ceed, 1, "Not defined for composite operator"); 468 469 if (inputfields) *inputfields = op->inputfields; 470 if (outputfields) *outputfields = op->outputfields; 471 return 0; 472 } 473 474 /** 475 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 476 477 @param opfield CeedOperatorField 478 @param[out] lmode Variable to store CeedTransposeMode 479 480 @return An error code: 0 - success, otherwise - failure 481 482 @ref Advanced 483 **/ 484 485 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 486 CeedTransposeMode *lmode) { 487 *lmode = opfield->lmode; 488 return 0; 489 }/** 490 @brief Get the CeedElemRestriction of a CeedOperatorField 491 492 @param opfield CeedOperatorField 493 @param[out] rstr Variable to store CeedElemRestriction 494 495 @return An error code: 0 - success, otherwise - failure 496 497 @ref Advanced 498 **/ 499 500 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 501 CeedElemRestriction *rstr) { 502 *rstr = opfield->Erestrict; 503 return 0; 504 } 505 506 /** 507 @brief Get the CeedBasis of a CeedOperatorField 508 509 @param opfield CeedOperatorField 510 @param[out] basis Variable to store CeedBasis 511 512 @return An error code: 0 - success, otherwise - failure 513 514 @ref Advanced 515 **/ 516 517 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, 518 CeedBasis *basis) { 519 *basis = opfield->basis; 520 return 0; 521 } 522 523 /** 524 @brief Get the CeedVector of a CeedOperatorField 525 526 @param opfield CeedOperatorField 527 @param[out] vec Variable to store CeedVector 528 529 @return An error code: 0 - success, otherwise - failure 530 531 @ref Advanced 532 **/ 533 534 int CeedOperatorFieldGetVector(CeedOperatorField opfield, 535 CeedVector *vec) { 536 *vec = opfield->vec; 537 return 0; 538 } 539 540 /** 541 @brief Destroy a CeedOperator 542 543 @param op CeedOperator to destroy 544 545 @return An error code: 0 - success, otherwise - failure 546 547 @ref Basic 548 **/ 549 int CeedOperatorDestroy(CeedOperator *op) { 550 int ierr; 551 552 if (!*op || --(*op)->refcount > 0) return 0; 553 if ((*op)->Destroy) { 554 ierr = (*op)->Destroy(*op); CeedChk(ierr); 555 } 556 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 557 // Free fields 558 for (int i=0; i<(*op)->nfields; i++) { 559 if ((*op)->inputfields[i]) { 560 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 561 } 562 } 563 for (int i=0; i<(*op)->nfields; i++) { 564 if ((*op)->outputfields[i]) { 565 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 566 } 567 } 568 // Destroy suboperators 569 for (int i=0; i<(*op)->numsub; i++) { 570 if ((*op)->suboperators[i]) { 571 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 572 } 573 } 574 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 575 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 576 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 577 578 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 579 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 580 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 581 ierr = CeedFree(op); CeedChk(ierr); 582 return 0; 583 } 584 585 /// @} 586