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 // LCOV_EXCL_START 54 return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 55 // LCOV_EXCL_STOP 56 57 ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 58 return 0; 59 } 60 61 ierr = CeedCalloc(1,op); CeedChk(ierr); 62 (*op)->ceed = ceed; 63 ceed->refcount++; 64 (*op)->refcount = 1; 65 if (qf == CEED_QFUNCTION_NONE) 66 // LCOV_EXCL_START 67 return CeedError(ceed, 1, "Operator must have a valid QFunction."); 68 // LCOV_EXCL_STOP 69 (*op)->qf = qf; 70 qf->refcount++; 71 if (dqf && dqf != CEED_QFUNCTION_NONE) { 72 (*op)->dqf = dqf; 73 dqf->refcount++; 74 } 75 if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 76 (*op)->dqfT = dqfT; 77 dqfT->refcount++; 78 } 79 ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 80 ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 81 ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 82 return 0; 83 } 84 85 /** 86 @brief Create an operator that composes the action of several operators 87 88 @param ceed A Ceed object where the CeedOperator will be created 89 @param[out] op Address of the variable where the newly created 90 Composite CeedOperator will be stored 91 92 @return An error code: 0 - success, otherwise - failure 93 94 @ref Basic 95 */ 96 int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 97 int ierr; 98 99 if (!ceed->CompositeOperatorCreate) { 100 Ceed delegate; 101 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 102 103 if (!delegate) 104 // LCOV_EXCL_START 105 return CeedError(ceed, 1, "Backend does not support " 106 "CompositeOperatorCreate"); 107 // LCOV_EXCL_STOP 108 109 ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 110 return 0; 111 } 112 113 ierr = CeedCalloc(1,op); CeedChk(ierr); 114 (*op)->ceed = ceed; 115 ceed->refcount++; 116 (*op)->composite = true; 117 ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 118 ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 119 return 0; 120 } 121 122 /** 123 @brief Provide a field to a CeedOperator for use by its CeedQFunction 124 125 This function is used to specify both active and passive fields to a 126 CeedOperator. For passive fields, a vector @arg v must be provided. Passive 127 fields can inputs or outputs (updated in-place when operator is applied). 128 129 Active fields must be specified using this function, but their data (in a 130 CeedVector) is passed in CeedOperatorApply(). There can be at most one active 131 input and at most one active output. 132 133 @param op CeedOperator on which to provide the field 134 @param fieldname Name of the field (to be matched with the name used by 135 CeedQFunction) 136 @param r CeedElemRestriction 137 @param lmode CeedTransposeMode which specifies the ordering of the 138 components of the l-vector used by this CeedOperatorField, 139 CEED_NOTRANSPOSE indicates the component is the 140 outermost index and CEED_TRANSPOSE indicates the component 141 is the innermost index in ordering of the l-vector 142 @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 143 if collocated with quadrature points 144 @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 145 if field is active or CEED_VECTOR_NONE if using 146 CEED_EVAL_WEIGHT in the QFunction 147 148 @return An error code: 0 - success, otherwise - failure 149 150 @ref Basic 151 **/ 152 int CeedOperatorSetField(CeedOperator op, const char *fieldname, 153 CeedElemRestriction r, CeedTransposeMode lmode, 154 CeedBasis b, CeedVector v) { 155 int ierr; 156 if (op->composite) 157 // LCOV_EXCL_START 158 return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 159 // LCOV_EXCL_STOP 160 if (!r) 161 // LCOV_EXCL_START 162 return CeedError(op->ceed, 1, 163 "ElemRestriction r for field \"%s\" must be non-NULL.", 164 fieldname); 165 // LCOV_EXCL_STOP 166 if (!b) 167 // LCOV_EXCL_START 168 return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.", 169 fieldname); 170 // LCOV_EXCL_STOP 171 if (!v) 172 // LCOV_EXCL_START 173 return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.", 174 fieldname); 175 // LCOV_EXCL_STOP 176 177 CeedInt numelements; 178 ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 179 if (op->hasrestriction && op->numelements != numelements) 180 // LCOV_EXCL_START 181 return CeedError(op->ceed, 1, 182 "ElemRestriction with %d elements incompatible with prior " 183 "%d elements", numelements, op->numelements); 184 // LCOV_EXCL_STOP 185 op->numelements = numelements; 186 op->hasrestriction = true; // Restriction set, but numelements may be 0 187 188 if (b != CEED_BASIS_COLLOCATED) { 189 CeedInt numqpoints; 190 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 191 if (op->numqpoints && op->numqpoints != numqpoints) 192 // LCOV_EXCL_START 193 return CeedError(op->ceed, 1, "Basis with %d quadrature points " 194 "incompatible with prior %d points", numqpoints, 195 op->numqpoints); 196 // LCOV_EXCL_STOP 197 op->numqpoints = numqpoints; 198 } 199 CeedOperatorField *ofield; 200 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 201 if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 202 ofield = &op->inputfields[i]; 203 goto found; 204 } 205 } 206 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 207 if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 208 ofield = &op->outputfields[i]; 209 goto found; 210 } 211 } 212 // LCOV_EXCL_START 213 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 214 fieldname); 215 // LCOV_EXCL_STOP 216 found: 217 ierr = CeedCalloc(1, ofield); CeedChk(ierr); 218 (*ofield)->Erestrict = r; 219 r->refcount += 1; 220 (*ofield)->lmode = lmode; 221 (*ofield)->basis = b; 222 if (b != CEED_BASIS_COLLOCATED) 223 b->refcount += 1; 224 (*ofield)->vec = v; 225 if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) 226 v->refcount += 1; 227 op->nfields += 1; 228 return 0; 229 } 230 231 /** 232 @brief Add a sub-operator to a composite CeedOperator 233 234 @param[out] compositeop Address of the composite CeedOperator 235 @param subop Address of the sub-operator CeedOperator 236 237 @return An error code: 0 - success, otherwise - failure 238 239 @ref Basic 240 */ 241 int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 242 if (!compositeop->composite) 243 // LCOV_EXCL_START 244 return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite " 245 "operator"); 246 // LCOV_EXCL_STOP 247 248 if (compositeop->numsub == CEED_COMPOSITE_MAX) 249 // LCOV_EXCL_START 250 return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators"); 251 // LCOV_EXCL_STOP 252 253 compositeop->suboperators[compositeop->numsub] = subop; 254 subop->refcount++; 255 compositeop->numsub++; 256 return 0; 257 } 258 259 /** 260 @brief Assemble a linear CeedQFunction associated with a CeedOperator 261 262 This returns a CeedVector containing a matrix at each quadrature point 263 providing the action of the CeedQFunction associated with the CeedOperator. 264 The vector 'assembled' is of shape 265 [num_elements, num_input_fields, num_output_fields, num_quad_points] 266 and contains column-major matrices representing the action of the 267 CeedQFunction for a corresponding quadrature point on an element. Inputs and 268 outputs are in the order provided by the user when adding CeedOperator fields. 269 For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 270 'v', provided in that order, would result in an assembled QFunction that 271 consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 272 on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 273 274 @param op CeedOperator to assemble CeedQFunction 275 @param[out] assembled CeedVector to store assembled CeedQFunction at 276 quadrature points 277 @param[out] rstr CeedElemRestriction for CeedVector containing assembled 278 CeedQFunction 279 @param request Address of CeedRequest for non-blocking completion, else 280 CEED_REQUEST_IMMEDIATE 281 282 @return An error code: 0 - success, otherwise - failure 283 284 @ref Basic 285 **/ 286 int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled, 287 CeedElemRestriction *rstr, 288 CeedRequest *request) { 289 int ierr; 290 Ceed ceed = op->ceed; 291 CeedQFunction qf = op->qf; 292 293 if (op->composite) { 294 // LCOV_EXCL_START 295 return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator"); 296 // LCOV_EXCL_STOP 297 } else { 298 if (op->nfields == 0) 299 // LCOV_EXCL_START 300 return CeedError(ceed, 1, "No operator fields set"); 301 // LCOV_EXCL_STOP 302 if (op->nfields < qf->numinputfields + qf->numoutputfields) 303 // LCOV_EXCL_START 304 return CeedError( ceed, 1, "Not all operator fields set"); 305 // LCOV_EXCL_STOP 306 if (!op->hasrestriction) 307 // LCOV_EXCL_START 308 return CeedError(ceed, 1, "At least one restriction required"); 309 // LCOV_EXCL_STOP 310 if (op->numqpoints == 0) 311 // LCOV_EXCL_START 312 return CeedError(ceed, 1, "At least one non-collocated basis required"); 313 // LCOV_EXCL_STOP 314 } 315 ierr = op->AssembleLinearQFunction(op, assembled, rstr, request); 316 CeedChk(ierr); 317 return 0; 318 } 319 320 /** 321 @brief Assemble the diagonal of a square linear Operator 322 323 This returns a CeedVector containing the diagonal of a linear CeedOperator. 324 325 @param op CeedOperator to assemble CeedQFunction 326 @param[out] assembled CeedVector to store assembled CeedOperator diagonal 327 @param request Address of CeedRequest for non-blocking completion, else 328 CEED_REQUEST_IMMEDIATE 329 330 @return An error code: 0 - success, otherwise - failure 331 332 @ref Basic 333 **/ 334 int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled, 335 CeedRequest *request) { 336 int ierr; 337 Ceed ceed = op->ceed; 338 CeedQFunction qf = op->qf; 339 340 if (op->composite) { 341 // LCOV_EXCL_START 342 return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator"); 343 // LCOV_EXCL_STOP 344 } else { 345 if (op->nfields == 0) 346 // LCOV_EXCL_START 347 return CeedError(ceed, 1, "No operator fields set"); 348 // LCOV_EXCL_STOP 349 if (op->nfields < qf->numinputfields + qf->numoutputfields) 350 // LCOV_EXCL_START 351 return CeedError( ceed, 1, "Not all operator fields set"); 352 // LCOV_EXCL_STOP 353 if (!op->hasrestriction) 354 // LCOV_EXCL_START 355 return CeedError(ceed, 1, "At least one restriction required"); 356 // LCOV_EXCL_STOP 357 if (op->numqpoints == 0) 358 // LCOV_EXCL_START 359 return CeedError(ceed, 1, "At least one non-collocated basis required"); 360 // LCOV_EXCL_STOP 361 } 362 363 // Use backend version, if available 364 if (op->AssembleLinearDiagonal) { 365 ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr); 366 return 0; 367 } 368 369 // Assemble QFunction 370 CeedVector assembledqf; 371 CeedElemRestriction rstr; 372 ierr = CeedOperatorAssembleLinearQFunction(op, &assembledqf, &rstr, request); 373 CeedChk(ierr); 374 ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr); 375 376 // Determine active input basis 377 CeedInt numemodein = 0, ncomp, dim = 1; 378 CeedEvalMode *emodein = NULL; 379 CeedBasis basisin = NULL; 380 CeedElemRestriction rstrin = NULL; 381 for (CeedInt i=0; i<qf->numinputfields; i++) 382 if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 383 ierr = CeedOperatorFieldGetBasis(op->inputfields[i], &basisin); 384 CeedChk(ierr); 385 ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr); 386 ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 387 ierr = CeedOperatorFieldGetElemRestriction(op->inputfields[i], &rstrin); 388 CeedChk(ierr); 389 CeedEvalMode emode; 390 ierr = CeedQFunctionFieldGetEvalMode(qf->inputfields[i], &emode); 391 CeedChk(ierr); 392 switch (emode) { 393 case CEED_EVAL_NONE: 394 case CEED_EVAL_INTERP: 395 ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 396 emodein[numemodein] = emode; 397 numemodein += 1; 398 break; 399 case CEED_EVAL_GRAD: 400 ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 401 for (CeedInt d=0; d<dim; d++) 402 emodein[numemodein+d] = emode; 403 numemodein += dim; 404 break; 405 case CEED_EVAL_WEIGHT: 406 case CEED_EVAL_DIV: 407 case CEED_EVAL_CURL: 408 break; // Caught by QF Assembly 409 } 410 } 411 412 // Determine active output basis 413 CeedInt numemodeout = 0; 414 CeedEvalMode *emodeout = NULL; 415 CeedBasis basisout = NULL; 416 CeedElemRestriction rstrout = NULL; 417 CeedTransposeMode lmodeout = CEED_NOTRANSPOSE; 418 for (CeedInt i=0; i<qf->numoutputfields; i++) 419 if (op->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 420 ierr = CeedOperatorFieldGetBasis(op->outputfields[i], &basisout); 421 CeedChk(ierr); 422 ierr = CeedOperatorFieldGetElemRestriction(op->outputfields[i], &rstrout); 423 CeedChk(ierr); 424 ierr = CeedOperatorFieldGetLMode(op->outputfields[i], &lmodeout); 425 CeedChk(ierr); 426 CeedEvalMode emode; 427 ierr = CeedQFunctionFieldGetEvalMode(qf->outputfields[i], &emode); 428 CeedChk(ierr); 429 switch (emode) { 430 case CEED_EVAL_NONE: 431 case CEED_EVAL_INTERP: 432 ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 433 emodeout[numemodeout] = emode; 434 numemodeout += 1; 435 break; 436 case CEED_EVAL_GRAD: 437 ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 438 for (CeedInt d=0; d<dim; d++) 439 emodeout[numemodeout+d] = emode; 440 numemodeout += dim; 441 break; 442 case CEED_EVAL_WEIGHT: 443 case CEED_EVAL_DIV: 444 case CEED_EVAL_CURL: 445 break; // Caught by QF Assembly 446 } 447 } 448 449 // Create diagonal vector 450 CeedVector elemdiag; 451 ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag); 452 CeedChk(ierr); 453 454 // Assemble element operator diagonals 455 CeedScalar *elemdiagarray, *assembledqfarray; 456 ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr); 457 ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray); 458 CeedChk(ierr); 459 ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray); 460 CeedChk(ierr); 461 CeedInt nelem, nnodes, nqpts; 462 ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 463 ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr); 464 ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 465 // Compute the diagonal of B^T D B 466 // Each node, qpt pair 467 for (CeedInt n=0; n<nnodes; n++) 468 for (CeedInt q=0; q<nqpts; q++) { 469 CeedInt dout = -1; 470 // Each basis eval mode pair 471 for (CeedInt eout=0; eout<numemodeout; eout++) { 472 CeedScalar bt = 1.0; 473 if (emodeout[eout] == CEED_EVAL_GRAD) 474 dout += 1; 475 ierr = CeedBasisGetValue(basisout, emodeout[eout], q, n, dout, &bt); 476 CeedChk(ierr); 477 CeedInt din = -1; 478 for (CeedInt ein=0; ein<numemodein; ein++) { 479 CeedScalar b = 0.0; 480 if (emodein[ein] == CEED_EVAL_GRAD) 481 din += 1; 482 ierr = CeedBasisGetValue(basisin, emodein[ein], q, n, din, &b); 483 CeedChk(ierr); 484 // Each element and component 485 for (CeedInt e=0; e<nelem; e++) 486 for (CeedInt cout=0; cout<ncomp; cout++) { 487 CeedScalar db = 0.0; 488 for (CeedInt cin=0; cin<ncomp; cin++) 489 db += assembledqfarray[((((e*numemodein+ein)*ncomp+cin)* 490 numemodeout+eout)*ncomp+cout)*nqpts+q]*b; 491 elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt * db; 492 } 493 } 494 } 495 } 496 497 ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr); 498 ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr); 499 500 // Assemble local operator diagonal 501 ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr); 502 ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag, 503 *assembled, request); CeedChk(ierr); 504 505 // Cleanup 506 ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 507 ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr); 508 ierr = CeedFree(&emodein); CeedChk(ierr); 509 ierr = CeedFree(&emodeout); CeedChk(ierr); 510 511 return 0; 512 } 513 514 /** 515 @brief Apply CeedOperator to a vector 516 517 This computes the action of the operator on the specified (active) input, 518 yielding its (active) output. All inputs and outputs must be specified using 519 CeedOperatorSetField(). 520 521 @param op CeedOperator to apply 522 @param[in] in CeedVector containing input state or NULL if there are no 523 active inputs 524 @param[out] out CeedVector to store result of applying operator (must be 525 distinct from @a in) or NULL if there are no active outputs 526 @param request Address of CeedRequest for non-blocking completion, else 527 CEED_REQUEST_IMMEDIATE 528 529 @return An error code: 0 - success, otherwise - failure 530 531 @ref Basic 532 **/ 533 int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 534 CeedRequest *request) { 535 int ierr; 536 Ceed ceed = op->ceed; 537 CeedQFunction qf = op->qf; 538 539 if (op->composite) { 540 if (!op->numsub) 541 // LCOV_EXCL_START 542 return CeedError(ceed, 1, "No suboperators set"); 543 // LCOV_EXCL_STOP 544 } else { 545 if (op->nfields == 0) 546 // LCOV_EXCL_START 547 return CeedError(ceed, 1, "No operator fields set"); 548 // LCOV_EXCL_STOP 549 if (op->nfields < qf->numinputfields + qf->numoutputfields) 550 // LCOV_EXCL_START 551 return CeedError(ceed, 1, "Not all operator fields set"); 552 // LCOV_EXCL_STOP 553 if (!op->hasrestriction) 554 // LCOV_EXCL_START 555 return CeedError(ceed, 1,"At least one restriction required"); 556 // LCOV_EXCL_STOP 557 if (op->numqpoints == 0) 558 // LCOV_EXCL_START 559 return CeedError(ceed, 1,"At least one non-collocated basis required"); 560 // LCOV_EXCL_STOP 561 } 562 if (op->numelements || op->composite) { 563 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 564 } 565 return 0; 566 } 567 568 /** 569 @brief Get the Ceed associated with a CeedOperator 570 571 @param op CeedOperator 572 @param[out] ceed Variable to store Ceed 573 574 @return An error code: 0 - success, otherwise - failure 575 576 @ref Advanced 577 **/ 578 579 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 580 *ceed = op->ceed; 581 return 0; 582 } 583 584 /** 585 @brief Get the number of elements associated with a CeedOperator 586 587 @param op CeedOperator 588 @param[out] numelem Variable to store number of elements 589 590 @return An error code: 0 - success, otherwise - failure 591 592 @ref Advanced 593 **/ 594 595 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 596 if (op->composite) 597 // LCOV_EXCL_START 598 return CeedError(op->ceed, 1, "Not defined for composite operator"); 599 // LCOV_EXCL_STOP 600 601 *numelem = op->numelements; 602 return 0; 603 } 604 605 /** 606 @brief Get the number of quadrature points associated with a CeedOperator 607 608 @param op CeedOperator 609 @param[out] numqpts Variable to store vector number of quadrature points 610 611 @return An error code: 0 - success, otherwise - failure 612 613 @ref Advanced 614 **/ 615 616 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 617 if (op->composite) 618 // LCOV_EXCL_START 619 return CeedError(op->ceed, 1, "Not defined for composite operator"); 620 // LCOV_EXCL_STOP 621 622 *numqpts = op->numqpoints; 623 return 0; 624 } 625 626 /** 627 @brief Get the number of arguments associated with a CeedOperator 628 629 @param op CeedOperator 630 @param[out] numargs Variable to store vector number of arguments 631 632 @return An error code: 0 - success, otherwise - failure 633 634 @ref Advanced 635 **/ 636 637 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 638 if (op->composite) 639 // LCOV_EXCL_START 640 return CeedError(op->ceed, 1, "Not defined for composite operators"); 641 // LCOV_EXCL_STOP 642 643 *numargs = op->nfields; 644 return 0; 645 } 646 647 /** 648 @brief Get the setup status of a CeedOperator 649 650 @param op CeedOperator 651 @param[out] setupdone Variable to store setup status 652 653 @return An error code: 0 - success, otherwise - failure 654 655 @ref Advanced 656 **/ 657 658 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 659 *setupdone = op->setupdone; 660 return 0; 661 } 662 663 /** 664 @brief Get the QFunction associated with a CeedOperator 665 666 @param op CeedOperator 667 @param[out] qf Variable to store QFunction 668 669 @return An error code: 0 - success, otherwise - failure 670 671 @ref Advanced 672 **/ 673 674 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 675 if (op->composite) 676 // LCOV_EXCL_START 677 return CeedError(op->ceed, 1, "Not defined for composite operator"); 678 // LCOV_EXCL_STOP 679 680 *qf = op->qf; 681 return 0; 682 } 683 684 /** 685 @brief Get the number of suboperators associated with a CeedOperator 686 687 @param op CeedOperator 688 @param[out] numsub Variable to store number of suboperators 689 690 @return An error code: 0 - success, otherwise - failure 691 692 @ref Advanced 693 **/ 694 695 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 696 if (!op->composite) 697 // LCOV_EXCL_START 698 return CeedError(op->ceed, 1, "Not a composite operator"); 699 // LCOV_EXCL_STOP 700 701 *numsub = op->numsub; 702 return 0; 703 } 704 705 /** 706 @brief Get the list of suboperators associated with a CeedOperator 707 708 @param op CeedOperator 709 @param[out] suboperators Variable to store list of suboperators 710 711 @return An error code: 0 - success, otherwise - failure 712 713 @ref Advanced 714 **/ 715 716 int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 717 if (!op->composite) 718 // LCOV_EXCL_START 719 return CeedError(op->ceed, 1, "Not a composite operator"); 720 // LCOV_EXCL_STOP 721 722 *suboperators = op->suboperators; 723 return 0; 724 } 725 726 /** 727 @brief Set the backend data of a CeedOperator 728 729 @param[out] op CeedOperator 730 @param data Data to set 731 732 @return An error code: 0 - success, otherwise - failure 733 734 @ref Advanced 735 **/ 736 737 int CeedOperatorSetData(CeedOperator op, void **data) { 738 op->data = *data; 739 return 0; 740 } 741 742 /** 743 @brief Get the backend data of a CeedOperator 744 745 @param op CeedOperator 746 @param[out] data Variable to store data 747 748 @return An error code: 0 - success, otherwise - failure 749 750 @ref Advanced 751 **/ 752 753 int CeedOperatorGetData(CeedOperator op, void **data) { 754 *data = op->data; 755 return 0; 756 } 757 758 /** 759 @brief Set the setup flag of a CeedOperator to True 760 761 @param op CeedOperator 762 763 @return An error code: 0 - success, otherwise - failure 764 765 @ref Advanced 766 **/ 767 768 int CeedOperatorSetSetupDone(CeedOperator op) { 769 op->setupdone = 1; 770 return 0; 771 } 772 773 /** 774 @brief Get the CeedOperatorFields of a CeedOperator 775 776 @param op CeedOperator 777 @param[out] inputfields Variable to store inputfields 778 @param[out] outputfields Variable to store outputfields 779 780 @return An error code: 0 - success, otherwise - failure 781 782 @ref Advanced 783 **/ 784 785 int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 786 CeedOperatorField **outputfields) { 787 if (op->composite) 788 // LCOV_EXCL_START 789 return CeedError(op->ceed, 1, "Not defined for composite operator"); 790 // LCOV_EXCL_STOP 791 792 if (inputfields) *inputfields = op->inputfields; 793 if (outputfields) *outputfields = op->outputfields; 794 return 0; 795 } 796 797 /** 798 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 799 800 @param opfield CeedOperatorField 801 @param[out] lmode Variable to store CeedTransposeMode 802 803 @return An error code: 0 - success, otherwise - failure 804 805 @ref Advanced 806 **/ 807 808 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 809 CeedTransposeMode *lmode) { 810 *lmode = opfield->lmode; 811 return 0; 812 } 813 814 /** 815 @brief Get the CeedElemRestriction of a CeedOperatorField 816 817 @param opfield CeedOperatorField 818 @param[out] rstr Variable to store CeedElemRestriction 819 820 @return An error code: 0 - success, otherwise - failure 821 822 @ref Advanced 823 **/ 824 825 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 826 CeedElemRestriction *rstr) { 827 *rstr = opfield->Erestrict; 828 return 0; 829 } 830 831 /** 832 @brief Get the CeedBasis of a CeedOperatorField 833 834 @param opfield CeedOperatorField 835 @param[out] basis Variable to store CeedBasis 836 837 @return An error code: 0 - success, otherwise - failure 838 839 @ref Advanced 840 **/ 841 842 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 843 *basis = opfield->basis; 844 return 0; 845 } 846 847 /** 848 @brief Get the CeedVector of a CeedOperatorField 849 850 @param opfield CeedOperatorField 851 @param[out] vec Variable to store CeedVector 852 853 @return An error code: 0 - success, otherwise - failure 854 855 @ref Advanced 856 **/ 857 858 int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 859 *vec = opfield->vec; 860 return 0; 861 } 862 863 /** 864 @brief Destroy a CeedOperator 865 866 @param op CeedOperator to destroy 867 868 @return An error code: 0 - success, otherwise - failure 869 870 @ref Basic 871 **/ 872 int CeedOperatorDestroy(CeedOperator *op) { 873 int ierr; 874 875 if (!*op || --(*op)->refcount > 0) return 0; 876 if ((*op)->Destroy) { 877 ierr = (*op)->Destroy(*op); CeedChk(ierr); 878 } 879 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 880 // Free fields 881 for (int i=0; i<(*op)->nfields; i++) 882 if ((*op)->inputfields[i]) { 883 ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 884 CeedChk(ierr); 885 if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 886 ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 887 } 888 if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 889 (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 890 ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 891 } 892 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 893 } 894 for (int i=0; i<(*op)->nfields; i++) 895 if ((*op)->outputfields[i]) { 896 ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 897 CeedChk(ierr); 898 if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 899 ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 900 } 901 if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 902 (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 903 ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 904 } 905 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 906 } 907 // Destroy suboperators 908 for (int i=0; i<(*op)->numsub; i++) 909 if ((*op)->suboperators[i]) { 910 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 911 } 912 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 913 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 914 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 915 916 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 917 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 918 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 919 ierr = CeedFree(op); CeedChk(ierr); 920 return 0; 921 } 922 923 /// @} 924