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