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 #include <math.h> 21 22 /// @file 23 /// Implementation of public CeedOperator interfaces 24 /// 25 /// @addtogroup CeedOperator 26 /// @{ 27 28 /** 29 @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 30 CeedElemRestriction can be associated with CeedQFunction fields with 31 \ref CeedOperatorSetField. 32 33 @param ceed A Ceed object where the CeedOperator will be created 34 @param qf QFunction defining the action of the operator at quadrature points 35 @param dqf QFunction defining the action of the Jacobian of @a qf (or 36 CEED_QFUNCTION_NONE) 37 @param dqfT QFunction defining the action of the transpose of the Jacobian 38 of @a qf (or CEED_QFUNCTION_NONE) 39 @param[out] op Address of the variable where the newly created 40 CeedOperator will be stored 41 42 @return An error code: 0 - success, otherwise - failure 43 44 @ref Basic 45 */ 46 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 47 CeedQFunction dqfT, CeedOperator *op) { 48 int ierr; 49 50 if (!ceed->OperatorCreate) { 51 Ceed delegate; 52 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 53 54 if (!delegate) 55 // LCOV_EXCL_START 56 return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 57 // LCOV_EXCL_STOP 58 59 ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 60 return 0; 61 } 62 63 ierr = CeedCalloc(1, op); CeedChk(ierr); 64 (*op)->ceed = ceed; 65 ceed->refcount++; 66 (*op)->refcount = 1; 67 if (qf == CEED_QFUNCTION_NONE) 68 // LCOV_EXCL_START 69 return CeedError(ceed, 1, "Operator must have a valid QFunction."); 70 // LCOV_EXCL_STOP 71 (*op)->qf = qf; 72 qf->refcount++; 73 if (dqf && dqf != CEED_QFUNCTION_NONE) { 74 (*op)->dqf = dqf; 75 dqf->refcount++; 76 } 77 if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 78 (*op)->dqfT = dqfT; 79 dqfT->refcount++; 80 } 81 ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 82 ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 83 ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 84 return 0; 85 } 86 87 /** 88 @brief Create an operator that composes the action of several operators 89 90 @param ceed A Ceed object where the CeedOperator will be created 91 @param[out] op Address of the variable where the newly created 92 Composite CeedOperator will be stored 93 94 @return An error code: 0 - success, otherwise - failure 95 96 @ref Basic 97 */ 98 int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 99 int ierr; 100 101 if (!ceed->CompositeOperatorCreate) { 102 Ceed delegate; 103 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 104 105 if (delegate) { 106 ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 107 return 0; 108 } 109 } 110 111 ierr = CeedCalloc(1, op); CeedChk(ierr); 112 (*op)->ceed = ceed; 113 ceed->refcount++; 114 (*op)->composite = true; 115 ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 116 117 if (ceed->CompositeOperatorCreate) { 118 ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 119 } 120 return 0; 121 } 122 123 /** 124 @brief Provide a field to a CeedOperator for use by its CeedQFunction 125 126 This function is used to specify both active and passive fields to a 127 CeedOperator. For passive fields, a vector @arg v must be provided. Passive 128 fields can inputs or outputs (updated in-place when operator is applied). 129 130 Active fields must be specified using this function, but their data (in a 131 CeedVector) is passed in CeedOperatorApply(). There can be at most one active 132 input and at most one active output. 133 134 @param op CeedOperator on which to provide the field 135 @param fieldname Name of the field (to be matched with the name used by 136 CeedQFunction) 137 @param r CeedElemRestriction 138 @param lmode CeedTransposeMode which specifies the ordering of the 139 components of the l-vector used by this CeedOperatorField, 140 CEED_NOTRANSPOSE indicates the component is the 141 outermost index and CEED_TRANSPOSE indicates the component 142 is the innermost index in ordering of the l-vector 143 @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 144 if collocated with quadrature points 145 @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 146 if field is active or CEED_VECTOR_NONE if using 147 CEED_EVAL_WEIGHT in the QFunction 148 149 @return An error code: 0 - success, otherwise - failure 150 151 @ref Basic 152 **/ 153 int CeedOperatorSetField(CeedOperator op, const char *fieldname, 154 CeedElemRestriction r, CeedTransposeMode lmode, 155 CeedBasis b, CeedVector v) { 156 int ierr; 157 if (op->composite) 158 // LCOV_EXCL_START 159 return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 160 // LCOV_EXCL_STOP 161 if (!r) 162 // LCOV_EXCL_START 163 return CeedError(op->ceed, 1, 164 "ElemRestriction r for field \"%s\" must be non-NULL.", 165 fieldname); 166 // LCOV_EXCL_STOP 167 if (!b) 168 // LCOV_EXCL_START 169 return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.", 170 fieldname); 171 // LCOV_EXCL_STOP 172 if (!v) 173 // LCOV_EXCL_START 174 return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.", 175 fieldname); 176 // LCOV_EXCL_STOP 177 178 CeedInt numelements; 179 ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 180 if (op->hasrestriction && op->numelements != numelements) 181 // LCOV_EXCL_START 182 return CeedError(op->ceed, 1, 183 "ElemRestriction with %d elements incompatible with prior " 184 "%d elements", numelements, op->numelements); 185 // LCOV_EXCL_STOP 186 op->numelements = numelements; 187 op->hasrestriction = true; // Restriction set, but numelements may be 0 188 189 if (b != CEED_BASIS_COLLOCATED) { 190 CeedInt numqpoints; 191 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 192 if (op->numqpoints && op->numqpoints != numqpoints) 193 // LCOV_EXCL_START 194 return CeedError(op->ceed, 1, "Basis with %d quadrature points " 195 "incompatible with prior %d points", numqpoints, 196 op->numqpoints); 197 // LCOV_EXCL_STOP 198 op->numqpoints = numqpoints; 199 } 200 CeedOperatorField *ofield; 201 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 202 if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 203 ofield = &op->inputfields[i]; 204 goto found; 205 } 206 } 207 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 208 if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 209 ofield = &op->outputfields[i]; 210 goto found; 211 } 212 } 213 // LCOV_EXCL_START 214 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 215 fieldname); 216 // LCOV_EXCL_STOP 217 found: 218 ierr = CeedCalloc(1, ofield); CeedChk(ierr); 219 (*ofield)->Erestrict = r; 220 r->refcount += 1; 221 (*ofield)->lmode = lmode; 222 (*ofield)->basis = b; 223 if (b != CEED_BASIS_COLLOCATED) 224 b->refcount += 1; 225 (*ofield)->vec = v; 226 if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) 227 v->refcount += 1; 228 op->nfields += 1; 229 return 0; 230 } 231 232 /** 233 @brief Add a sub-operator to a composite CeedOperator 234 235 @param[out] compositeop Composite CeedOperator 236 @param subop Sub-operator CeedOperator 237 238 @return An error code: 0 - success, otherwise - failure 239 240 @ref Basic 241 */ 242 int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 243 if (!compositeop->composite) 244 // LCOV_EXCL_START 245 return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite " 246 "operator"); 247 // LCOV_EXCL_STOP 248 249 if (compositeop->numsub == CEED_COMPOSITE_MAX) 250 // LCOV_EXCL_START 251 return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators"); 252 // LCOV_EXCL_STOP 253 254 compositeop->suboperators[compositeop->numsub] = subop; 255 subop->refcount++; 256 compositeop->numsub++; 257 return 0; 258 } 259 260 /** 261 @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced 262 CeedOperator functionality 263 264 @param op CeedOperator to create fallback for 265 266 @return An error code: 0 - success, otherwise - failure 267 268 @ref Developer 269 **/ 270 int CeedOperatorCreateFallback(CeedOperator op) { 271 int ierr; 272 273 // Fallback Ceed 274 const char *resource, *fallbackresource; 275 ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 276 ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 277 CeedChk(ierr); 278 if (!strcmp(resource, fallbackresource)) 279 // LCOV_EXCL_START 280 return CeedError(op->ceed, 1, "Backend %s cannot create an operator" 281 "fallback to resource %s", resource, fallbackresource); 282 // LCOV_EXCL_STOP 283 284 Ceed ceedref; 285 ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr); 286 ceedref->opfallbackparent = op->ceed; 287 op->ceed->opfallbackceed = ceedref; 288 289 // Clone Op 290 CeedOperator opref; 291 ierr = CeedCalloc(1, &opref); CeedChk(ierr); 292 memcpy(opref, op, sizeof(*opref)); CeedChk(ierr); 293 opref->data = NULL; 294 opref->setupdone = 0; 295 opref->ceed = ceedref; 296 ierr = ceedref->OperatorCreate(opref); CeedChk(ierr); 297 op->opfallback = opref; 298 299 // Clone QF 300 CeedQFunction qfref; 301 ierr = CeedCalloc(1, &qfref); CeedChk(ierr); 302 memcpy(qfref, (op->qf), sizeof(*qfref)); CeedChk(ierr); 303 qfref->data = NULL; 304 qfref->ceed = ceedref; 305 ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr); 306 opref->qf = qfref; 307 op->qffallback = qfref; 308 309 return 0; 310 } 311 312 /** 313 @brief Check if a CeedOperator is ready to be used. 314 315 @param[in] ceed Ceed object for error handling 316 @param[in] op CeedOperator to check 317 318 @return An error code: 0 - success, otherwise - failure 319 320 @ref Basic 321 **/ 322 static int CeedOperatorCheckReady(Ceed ceed, CeedOperator op) { 323 CeedQFunction qf = op->qf; 324 325 if (op->composite) { 326 if (!op->numsub) 327 // LCOV_EXCL_START 328 return CeedError(ceed, 1, "No suboperators set"); 329 // LCOV_EXCL_STOP 330 } else { 331 if (op->nfields == 0) 332 // LCOV_EXCL_START 333 return CeedError(ceed, 1, "No operator fields set"); 334 // LCOV_EXCL_STOP 335 if (op->nfields < qf->numinputfields + qf->numoutputfields) 336 // LCOV_EXCL_START 337 return CeedError(ceed, 1, "Not all operator fields set"); 338 // LCOV_EXCL_STOP 339 if (!op->hasrestriction) 340 // LCOV_EXCL_START 341 return CeedError(ceed, 1,"At least one restriction required"); 342 // LCOV_EXCL_STOP 343 if (op->numqpoints == 0) 344 // LCOV_EXCL_START 345 return CeedError(ceed, 1,"At least one non-collocated basis required"); 346 // LCOV_EXCL_STOP 347 } 348 349 return 0; 350 } 351 352 /** 353 @brief Assemble a linear CeedQFunction associated with a CeedOperator 354 355 This returns a CeedVector containing a matrix at each quadrature point 356 providing the action of the CeedQFunction associated with the CeedOperator. 357 The vector 'assembled' is of shape 358 [num_elements, num_input_fields, num_output_fields, num_quad_points] 359 and contains column-major matrices representing the action of the 360 CeedQFunction for a corresponding quadrature point on an element. Inputs and 361 outputs are in the order provided by the user when adding CeedOperator fields. 362 For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 363 'v', provided in that order, would result in an assembled QFunction that 364 consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 365 on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 366 367 @param op CeedOperator to assemble CeedQFunction 368 @param[out] assembled CeedVector to store assembled CeedQFunction at 369 quadrature points 370 @param[out] rstr CeedElemRestriction for CeedVector containing assembled 371 CeedQFunction 372 @param request Address of CeedRequest for non-blocking completion, else 373 CEED_REQUEST_IMMEDIATE 374 375 @return An error code: 0 - success, otherwise - failure 376 377 @ref Basic 378 **/ 379 int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled, 380 CeedElemRestriction *rstr, 381 CeedRequest *request) { 382 int ierr; 383 Ceed ceed = op->ceed; 384 ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 385 386 // Backend version 387 if (op->AssembleLinearQFunction) { 388 ierr = op->AssembleLinearQFunction(op, assembled, rstr, request); 389 CeedChk(ierr); 390 } else { 391 // Fallback to reference Ceed 392 if (!op->opfallback) { 393 ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 394 } 395 // Assemble 396 ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled, 397 rstr, request); CeedChk(ierr); 398 } 399 400 return 0; 401 } 402 403 /** 404 @brief Assemble the diagonal of a square linear Operator 405 406 This returns a CeedVector containing the diagonal of a linear CeedOperator. 407 408 @param op CeedOperator to assemble CeedQFunction 409 @param[out] assembled CeedVector to store assembled CeedOperator diagonal 410 @param request Address of CeedRequest for non-blocking completion, else 411 CEED_REQUEST_IMMEDIATE 412 413 @return An error code: 0 - success, otherwise - failure 414 415 @ref Basic 416 **/ 417 int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled, 418 CeedRequest *request) { 419 int ierr; 420 Ceed ceed = op->ceed; 421 ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 422 423 // Use backend version, if available 424 if (op->AssembleLinearDiagonal) { 425 ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr); 426 } else { 427 // Fallback to reference Ceed 428 if (!op->opfallback) { 429 ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 430 } 431 // Assemble 432 ierr = op->opfallback->AssembleLinearDiagonal(op->opfallback, assembled, 433 request); CeedChk(ierr); 434 } 435 436 return 0; 437 } 438 439 /** 440 @brief Build a FDM based approximate inverse for each element for a 441 CeedOperator 442 443 This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 444 Method based approximate inverse. This function obtains the simultaneous 445 diagonalization for the 1D mass and Laplacian operators, 446 M = V^T V, K = V^T S V. 447 The assembled QFunction is used to modify the eigenvalues from simultaneous 448 diagonalization and obtain an approximate inverse of the form 449 V^T S^hat V. The CeedOperator must be linear and non-composite. The 450 associated CeedQFunction must therefore also be linear. 451 452 @param op CeedOperator to create element inverses 453 @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 454 for each element 455 @param[out] qdata CeedVector to hold qdata for fdminv 456 @param request Address of CeedRequest for non-blocking completion, else 457 CEED_REQUEST_IMMEDIATE 458 459 @return An error code: 0 - success, otherwise - failure 460 461 @ref Advanced 462 **/ 463 int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 464 CeedRequest *request) { 465 int ierr; 466 Ceed ceed = op->ceed; 467 ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 468 469 // Use backend version, if available 470 if (op->CreateFDMElementInverse) { 471 ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr); 472 } else { 473 // Fallback to reference Ceed 474 if (!op->opfallback) { 475 ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 476 } 477 // Assemble 478 ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv, 479 request); CeedChk(ierr); 480 } 481 482 return 0; 483 } 484 485 486 /** 487 @brief Apply CeedOperator to a vector 488 489 This computes the action of the operator on the specified (active) input, 490 yielding its (active) output. All inputs and outputs must be specified using 491 CeedOperatorSetField(). 492 493 @param op CeedOperator to apply 494 @param[in] in CeedVector containing input state or CEED_VECTOR_NONE if 495 there are no active inputs 496 @param[out] out CeedVector to store result of applying operator (must be 497 distinct from @a in) or CEED_VECTOR_NONE if there are no 498 active outputs 499 @param request Address of CeedRequest for non-blocking completion, else 500 CEED_REQUEST_IMMEDIATE 501 502 @return An error code: 0 - success, otherwise - failure 503 504 @ref Basic 505 **/ 506 int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 507 CeedRequest *request) { 508 int ierr; 509 Ceed ceed = op->ceed; 510 ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 511 512 if (op->numelements) { 513 // Standard Operator 514 if (op->Apply) { 515 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 516 } else { 517 // Zero all output vectors 518 CeedQFunction qf = op->qf; 519 for (CeedInt i=0; i<qf->numoutputfields; i++) { 520 CeedVector vec = op->outputfields[i]->vec; 521 if (vec == CEED_VECTOR_ACTIVE) 522 vec = out; 523 if (vec != CEED_VECTOR_NONE) { 524 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 525 } 526 } 527 // Apply 528 ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 529 } 530 } else if (op->composite) { 531 // Composite Operator 532 if (op->ApplyComposite) { 533 ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 534 } else { 535 CeedInt numsub; 536 ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 537 CeedOperator *suboperators; 538 ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 539 540 // Zero all output vectors 541 if (out != CEED_VECTOR_NONE) { 542 ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 543 } 544 for (CeedInt i=0; i<numsub; i++) { 545 for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 546 CeedVector vec = suboperators[i]->outputfields[j]->vec; 547 if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 548 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 549 } 550 } 551 } 552 // Apply 553 for (CeedInt i=0; i<op->numsub; i++) { 554 ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 555 CeedChk(ierr); 556 } 557 } 558 } 559 560 return 0; 561 } 562 563 /** 564 @brief Apply CeedOperator to a vector and add result to output vector 565 566 This computes the action of the operator on the specified (active) input, 567 yielding its (active) output. All inputs and outputs must be specified using 568 CeedOperatorSetField(). 569 570 @param op CeedOperator to apply 571 @param[in] in CeedVector containing input state or NULL if there are no 572 active inputs 573 @param[out] out CeedVector to sum in result of applying operator (must be 574 distinct from @a in) or NULL if there are no active outputs 575 @param request Address of CeedRequest for non-blocking completion, else 576 CEED_REQUEST_IMMEDIATE 577 578 @return An error code: 0 - success, otherwise - failure 579 580 @ref Basic 581 **/ 582 int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 583 CeedRequest *request) { 584 int ierr; 585 Ceed ceed = op->ceed; 586 ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 587 588 if (op->numelements) { 589 // Standard Operator 590 ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 591 } else if (op->composite) { 592 // Composite Operator 593 if (op->ApplyAddComposite) { 594 ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 595 } else { 596 CeedInt numsub; 597 ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 598 CeedOperator *suboperators; 599 ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 600 601 for (CeedInt i=0; i<numsub; i++) { 602 ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 603 CeedChk(ierr); 604 } 605 } 606 } 607 608 return 0; 609 } 610 611 /** 612 @brief Get the Ceed associated with a CeedOperator 613 614 @param op CeedOperator 615 @param[out] ceed Variable to store Ceed 616 617 @return An error code: 0 - success, otherwise - failure 618 619 @ref Advanced 620 **/ 621 622 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 623 *ceed = op->ceed; 624 return 0; 625 } 626 627 /** 628 @brief Get the number of elements associated with a CeedOperator 629 630 @param op CeedOperator 631 @param[out] numelem Variable to store number of elements 632 633 @return An error code: 0 - success, otherwise - failure 634 635 @ref Advanced 636 **/ 637 638 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 639 if (op->composite) 640 // LCOV_EXCL_START 641 return CeedError(op->ceed, 1, "Not defined for composite operator"); 642 // LCOV_EXCL_STOP 643 644 *numelem = op->numelements; 645 return 0; 646 } 647 648 /** 649 @brief Get the number of quadrature points associated with a CeedOperator 650 651 @param op CeedOperator 652 @param[out] numqpts Variable to store vector number of quadrature points 653 654 @return An error code: 0 - success, otherwise - failure 655 656 @ref Advanced 657 **/ 658 659 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 660 if (op->composite) 661 // LCOV_EXCL_START 662 return CeedError(op->ceed, 1, "Not defined for composite operator"); 663 // LCOV_EXCL_STOP 664 665 *numqpts = op->numqpoints; 666 return 0; 667 } 668 669 /** 670 @brief Get the number of arguments associated with a CeedOperator 671 672 @param op CeedOperator 673 @param[out] numargs Variable to store vector number of arguments 674 675 @return An error code: 0 - success, otherwise - failure 676 677 @ref Advanced 678 **/ 679 680 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 681 if (op->composite) 682 // LCOV_EXCL_START 683 return CeedError(op->ceed, 1, "Not defined for composite operators"); 684 // LCOV_EXCL_STOP 685 686 *numargs = op->nfields; 687 return 0; 688 } 689 690 /** 691 @brief Get the setup status of a CeedOperator 692 693 @param op CeedOperator 694 @param[out] setupdone Variable to store setup status 695 696 @return An error code: 0 - success, otherwise - failure 697 698 @ref Advanced 699 **/ 700 701 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 702 *setupdone = op->setupdone; 703 return 0; 704 } 705 706 /** 707 @brief Get the QFunction associated with a CeedOperator 708 709 @param op CeedOperator 710 @param[out] qf Variable to store QFunction 711 712 @return An error code: 0 - success, otherwise - failure 713 714 @ref Advanced 715 **/ 716 717 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 718 if (op->composite) 719 // LCOV_EXCL_START 720 return CeedError(op->ceed, 1, "Not defined for composite operator"); 721 // LCOV_EXCL_STOP 722 723 *qf = op->qf; 724 return 0; 725 } 726 727 /** 728 @brief Get the number of suboperators associated with a CeedOperator 729 730 @param op CeedOperator 731 @param[out] numsub Variable to store number of suboperators 732 733 @return An error code: 0 - success, otherwise - failure 734 735 @ref Advanced 736 **/ 737 738 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 739 if (!op->composite) 740 // LCOV_EXCL_START 741 return CeedError(op->ceed, 1, "Not a composite operator"); 742 // LCOV_EXCL_STOP 743 744 *numsub = op->numsub; 745 return 0; 746 } 747 748 /** 749 @brief Get the list of suboperators associated with a CeedOperator 750 751 @param op CeedOperator 752 @param[out] suboperators Variable to store list of suboperators 753 754 @return An error code: 0 - success, otherwise - failure 755 756 @ref Advanced 757 **/ 758 759 int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 760 if (!op->composite) 761 // LCOV_EXCL_START 762 return CeedError(op->ceed, 1, "Not a composite operator"); 763 // LCOV_EXCL_STOP 764 765 *suboperators = op->suboperators; 766 return 0; 767 } 768 769 /** 770 @brief Set the backend data of a CeedOperator 771 772 @param[out] op CeedOperator 773 @param data Data to set 774 775 @return An error code: 0 - success, otherwise - failure 776 777 @ref Advanced 778 **/ 779 780 int CeedOperatorSetData(CeedOperator op, void **data) { 781 op->data = *data; 782 return 0; 783 } 784 785 /** 786 @brief Get the backend data of a CeedOperator 787 788 @param op CeedOperator 789 @param[out] data Variable to store data 790 791 @return An error code: 0 - success, otherwise - failure 792 793 @ref Advanced 794 **/ 795 796 int CeedOperatorGetData(CeedOperator op, void **data) { 797 *data = op->data; 798 return 0; 799 } 800 801 /** 802 @brief Set the setup flag of a CeedOperator to True 803 804 @param op CeedOperator 805 806 @return An error code: 0 - success, otherwise - failure 807 808 @ref Advanced 809 **/ 810 811 int CeedOperatorSetSetupDone(CeedOperator op) { 812 op->setupdone = 1; 813 return 0; 814 } 815 816 /** 817 @brief View a field of a CeedOperator 818 819 @param[in] field Operator field to view 820 @param[in] fieldnumber Number of field being viewed 821 @param[in] stream Stream to view to, e.g., stdout 822 823 @return An error code: 0 - success, otherwise - failure 824 825 @ref Utility 826 **/ 827 static int CeedOperatorFieldView(CeedOperatorField field, 828 CeedQFunctionField qffield, 829 CeedInt fieldnumber, bool sub, bool in, 830 FILE *stream) { 831 const char *pre = sub ? " " : ""; 832 const char *inout = in ? "Input" : "Output"; 833 834 fprintf(stream, "%s %s Field [%d]:\n" 835 "%s Name: \"%s\"\n" 836 "%s Lmode: \"%s\"\n", 837 pre, inout, fieldnumber, pre, qffield->fieldname, 838 pre, CeedTransposeModes[field->lmode]); 839 840 if (field->basis == CEED_BASIS_COLLOCATED) 841 fprintf(stream, "%s Collocated basis\n", pre); 842 843 if (field->vec == CEED_VECTOR_ACTIVE) 844 fprintf(stream, "%s Active vector\n", pre); 845 else if (field->vec == CEED_VECTOR_NONE) 846 fprintf(stream, "%s No vector\n", pre); 847 848 return 0; 849 } 850 851 /** 852 @brief View a single CeedOperator 853 854 @param[in] op CeedOperator to view 855 @param[in] stream Stream to write; typically stdout/stderr or a file 856 857 @return Error code: 0 - success, otherwise - failure 858 859 @ref Utility 860 **/ 861 int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 862 int ierr; 863 const char *pre = sub ? " " : ""; 864 865 CeedInt totalfields; 866 ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 867 868 fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 869 870 fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 871 op->qf->numinputfields>1 ? "s" : ""); 872 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 873 ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 874 i, sub, 1, stream); CeedChk(ierr); 875 } 876 877 fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 878 op->qf->numoutputfields>1 ? "s" : ""); 879 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 880 ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 881 i, sub, 0, stream); CeedChk(ierr); 882 } 883 884 return 0; 885 } 886 887 /** 888 @brief View a CeedOperator 889 890 @param[in] op CeedOperator to view 891 @param[in] stream Stream to write; typically stdout/stderr or a file 892 893 @return Error code: 0 - success, otherwise - failure 894 895 @ref Utility 896 **/ 897 int CeedOperatorView(CeedOperator op, FILE *stream) { 898 int ierr; 899 900 if (op->composite) { 901 fprintf(stream, "Composite CeedOperator\n"); 902 903 for (CeedInt i=0; i<op->numsub; i++) { 904 fprintf(stream, " SubOperator [%d]:\n", i); 905 ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 906 CeedChk(ierr); 907 } 908 } else { 909 fprintf(stream, "CeedOperator\n"); 910 ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 911 } 912 913 return 0; 914 } 915 916 /** 917 @brief Get the CeedOperatorFields of a CeedOperator 918 919 @param op CeedOperator 920 @param[out] inputfields Variable to store inputfields 921 @param[out] outputfields Variable to store outputfields 922 923 @return An error code: 0 - success, otherwise - failure 924 925 @ref Advanced 926 **/ 927 928 int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 929 CeedOperatorField **outputfields) { 930 if (op->composite) 931 // LCOV_EXCL_START 932 return CeedError(op->ceed, 1, "Not defined for composite operator"); 933 // LCOV_EXCL_STOP 934 935 if (inputfields) *inputfields = op->inputfields; 936 if (outputfields) *outputfields = op->outputfields; 937 return 0; 938 } 939 940 /** 941 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 942 943 @param opfield CeedOperatorField 944 @param[out] lmode Variable to store CeedTransposeMode 945 946 @return An error code: 0 - success, otherwise - failure 947 948 @ref Advanced 949 **/ 950 951 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 952 CeedTransposeMode *lmode) { 953 *lmode = opfield->lmode; 954 return 0; 955 } 956 957 /** 958 @brief Get the CeedElemRestriction of a CeedOperatorField 959 960 @param opfield CeedOperatorField 961 @param[out] rstr Variable to store CeedElemRestriction 962 963 @return An error code: 0 - success, otherwise - failure 964 965 @ref Advanced 966 **/ 967 968 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 969 CeedElemRestriction *rstr) { 970 *rstr = opfield->Erestrict; 971 return 0; 972 } 973 974 /** 975 @brief Get the CeedBasis of a CeedOperatorField 976 977 @param opfield CeedOperatorField 978 @param[out] basis Variable to store CeedBasis 979 980 @return An error code: 0 - success, otherwise - failure 981 982 @ref Advanced 983 **/ 984 985 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 986 *basis = opfield->basis; 987 return 0; 988 } 989 990 /** 991 @brief Get the CeedVector of a CeedOperatorField 992 993 @param opfield CeedOperatorField 994 @param[out] vec Variable to store CeedVector 995 996 @return An error code: 0 - success, otherwise - failure 997 998 @ref Advanced 999 **/ 1000 1001 int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 1002 *vec = opfield->vec; 1003 return 0; 1004 } 1005 1006 /** 1007 @brief Destroy a CeedOperator 1008 1009 @param op CeedOperator to destroy 1010 1011 @return An error code: 0 - success, otherwise - failure 1012 1013 @ref Basic 1014 **/ 1015 int CeedOperatorDestroy(CeedOperator *op) { 1016 int ierr; 1017 1018 if (!*op || --(*op)->refcount > 0) return 0; 1019 if ((*op)->Destroy) { 1020 ierr = (*op)->Destroy(*op); CeedChk(ierr); 1021 } 1022 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1023 // Free fields 1024 for (int i=0; i<(*op)->nfields; i++) 1025 if ((*op)->inputfields[i]) { 1026 ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 1027 CeedChk(ierr); 1028 if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 1029 ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 1030 } 1031 if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 1032 (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 1033 ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 1034 } 1035 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 1036 } 1037 for (int i=0; i<(*op)->nfields; i++) 1038 if ((*op)->outputfields[i]) { 1039 ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 1040 CeedChk(ierr); 1041 if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 1042 ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 1043 } 1044 if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 1045 (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 1046 ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 1047 } 1048 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1049 } 1050 // Destroy suboperators 1051 for (int i=0; i<(*op)->numsub; i++) 1052 if ((*op)->suboperators[i]) { 1053 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 1054 } 1055 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1056 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1057 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1058 1059 // Destroy fallback 1060 if ((*op)->opfallback) { 1061 ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 1062 ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 1063 ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 1064 ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 1065 } 1066 1067 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1068 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 1069 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1070 ierr = CeedFree(op); CeedChk(ierr); 1071 return 0; 1072 } 1073 1074 /// @} 1075