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