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->numelements && 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 179 if (b != CEED_BASIS_COLLOCATED) { 180 CeedInt numqpoints; 181 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 182 if (op->numqpoints && op->numqpoints != numqpoints) 183 // LCOV_EXCL_START 184 return CeedError(op->ceed, 1, "Basis with %d quadrature points " 185 "incompatible with prior %d points", numqpoints, 186 op->numqpoints); 187 // LCOV_EXCL_STOP 188 op->numqpoints = numqpoints; 189 } 190 CeedOperatorField *ofield; 191 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 192 if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 193 ofield = &op->inputfields[i]; 194 goto found; 195 } 196 } 197 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 198 if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 199 ofield = &op->outputfields[i]; 200 goto found; 201 } 202 } 203 // LCOV_EXCL_START 204 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 205 fieldname); 206 // LCOV_EXCL_STOP 207 found: 208 ierr = CeedCalloc(1, ofield); CeedChk(ierr); 209 (*ofield)->Erestrict = r; 210 r->refcount += 1; 211 (*ofield)->lmode = lmode; 212 (*ofield)->basis = b; 213 if (b != CEED_BASIS_COLLOCATED) 214 b->refcount += 1; 215 (*ofield)->vec = v; 216 if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) 217 v->refcount += 1; 218 op->nfields += 1; 219 return 0; 220 } 221 222 /** 223 @brief Add a sub-operator to a composite CeedOperator 224 225 @param[out] compositeop Address of the composite CeedOperator 226 @param subop Address of the sub-operator CeedOperator 227 228 @return An error code: 0 - success, otherwise - failure 229 230 @ref Basic 231 */ 232 int CeedCompositeOperatorAddSub(CeedOperator compositeop, 233 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->numelements == 0) 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->numelements == 0) 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, 526 CeedVector out, 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->numelements == 0) 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 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 555 return 0; 556 } 557 558 /** 559 @brief Get the Ceed associated with a CeedOperator 560 561 @param op CeedOperator 562 @param[out] ceed Variable to store Ceed 563 564 @return An error code: 0 - success, otherwise - failure 565 566 @ref Advanced 567 **/ 568 569 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 570 *ceed = op->ceed; 571 return 0; 572 } 573 574 /** 575 @brief Get the number of elements associated with a CeedOperator 576 577 @param op CeedOperator 578 @param[out] numelem Variable to store number of elements 579 580 @return An error code: 0 - success, otherwise - failure 581 582 @ref Advanced 583 **/ 584 585 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 586 if (op->composite) 587 // LCOV_EXCL_START 588 return CeedError(op->ceed, 1, "Not defined for composite operator"); 589 // LCOV_EXCL_STOP 590 591 *numelem = op->numelements; 592 return 0; 593 } 594 595 /** 596 @brief Get the number of quadrature points associated with a CeedOperator 597 598 @param op CeedOperator 599 @param[out] numqpts Variable to store vector number of quadrature points 600 601 @return An error code: 0 - success, otherwise - failure 602 603 @ref Advanced 604 **/ 605 606 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 607 if (op->composite) 608 // LCOV_EXCL_START 609 return CeedError(op->ceed, 1, "Not defined for composite operator"); 610 // LCOV_EXCL_STOP 611 612 *numqpts = op->numqpoints; 613 return 0; 614 } 615 616 /** 617 @brief Get the number of arguments associated with a CeedOperator 618 619 @param op CeedOperator 620 @param[out] numargs Variable to store vector number of arguments 621 622 @return An error code: 0 - success, otherwise - failure 623 624 @ref Advanced 625 **/ 626 627 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 628 if (op->composite) 629 // LCOV_EXCL_START 630 return CeedError(op->ceed, 1, "Not defined for composite operators"); 631 // LCOV_EXCL_STOP 632 633 *numargs = op->nfields; 634 return 0; 635 } 636 637 /** 638 @brief Get the setup status of a CeedOperator 639 640 @param op CeedOperator 641 @param[out] setupdone Variable to store setup status 642 643 @return An error code: 0 - success, otherwise - failure 644 645 @ref Advanced 646 **/ 647 648 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 649 *setupdone = op->setupdone; 650 return 0; 651 } 652 653 /** 654 @brief Get the QFunction associated with a CeedOperator 655 656 @param op CeedOperator 657 @param[out] qf Variable to store QFunction 658 659 @return An error code: 0 - success, otherwise - failure 660 661 @ref Advanced 662 **/ 663 664 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 665 if (op->composite) 666 // LCOV_EXCL_START 667 return CeedError(op->ceed, 1, "Not defined for composite operator"); 668 // LCOV_EXCL_STOP 669 670 *qf = op->qf; 671 return 0; 672 } 673 674 /** 675 @brief Get the number of suboperators associated with a CeedOperator 676 677 @param op CeedOperator 678 @param[out] numsub Variable to store number of suboperators 679 680 @return An error code: 0 - success, otherwise - failure 681 682 @ref Advanced 683 **/ 684 685 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 686 if (!op->composite) 687 // LCOV_EXCL_START 688 return CeedError(op->ceed, 1, "Not a composite operator"); 689 // LCOV_EXCL_STOP 690 691 *numsub = op->numsub; 692 return 0; 693 } 694 695 /** 696 @brief Get the list of suboperators associated with a CeedOperator 697 698 @param op CeedOperator 699 @param[out] suboperators Variable to store list of suboperators 700 701 @return An error code: 0 - success, otherwise - failure 702 703 @ref Advanced 704 **/ 705 706 int CeedOperatorGetSubList(CeedOperator op, CeedOperator* *suboperators) { 707 if (!op->composite) 708 // LCOV_EXCL_START 709 return CeedError(op->ceed, 1, "Not a composite operator"); 710 // LCOV_EXCL_STOP 711 712 *suboperators = op->suboperators; 713 return 0; 714 } 715 716 /** 717 @brief Set the backend data of a CeedOperator 718 719 @param[out] op CeedOperator 720 @param data Data to set 721 722 @return An error code: 0 - success, otherwise - failure 723 724 @ref Advanced 725 **/ 726 727 int CeedOperatorSetData(CeedOperator op, void* *data) { 728 op->data = *data; 729 return 0; 730 } 731 732 /** 733 @brief Get the backend data of a CeedOperator 734 735 @param op CeedOperator 736 @param[out] data Variable to store data 737 738 @return An error code: 0 - success, otherwise - failure 739 740 @ref Advanced 741 **/ 742 743 int CeedOperatorGetData(CeedOperator op, void* *data) { 744 *data = op->data; 745 return 0; 746 } 747 748 /** 749 @brief Set the setup flag of a CeedOperator to True 750 751 @param op CeedOperator 752 753 @return An error code: 0 - success, otherwise - failure 754 755 @ref Advanced 756 **/ 757 758 int CeedOperatorSetSetupDone(CeedOperator op) { 759 op->setupdone = 1; 760 return 0; 761 } 762 763 /** 764 @brief Get the CeedOperatorFields of a CeedOperator 765 766 @param op CeedOperator 767 @param[out] inputfields Variable to store inputfields 768 @param[out] outputfields Variable to store outputfields 769 770 @return An error code: 0 - success, otherwise - failure 771 772 @ref Advanced 773 **/ 774 775 int CeedOperatorGetFields(CeedOperator op, 776 CeedOperatorField* *inputfields, 777 CeedOperatorField* *outputfields) { 778 if (op->composite) 779 // LCOV_EXCL_START 780 return CeedError(op->ceed, 1, "Not defined for composite operator"); 781 // LCOV_EXCL_STOP 782 783 if (inputfields) *inputfields = op->inputfields; 784 if (outputfields) *outputfields = op->outputfields; 785 return 0; 786 } 787 788 /** 789 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 790 791 @param opfield CeedOperatorField 792 @param[out] lmode Variable to store CeedTransposeMode 793 794 @return An error code: 0 - success, otherwise - failure 795 796 @ref Advanced 797 **/ 798 799 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 800 CeedTransposeMode *lmode) { 801 *lmode = opfield->lmode; 802 return 0; 803 } 804 805 /** 806 @brief Get the CeedElemRestriction of a CeedOperatorField 807 808 @param opfield CeedOperatorField 809 @param[out] rstr Variable to store CeedElemRestriction 810 811 @return An error code: 0 - success, otherwise - failure 812 813 @ref Advanced 814 **/ 815 816 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 817 CeedElemRestriction *rstr) { 818 *rstr = opfield->Erestrict; 819 return 0; 820 } 821 822 /** 823 @brief Get the CeedBasis of a CeedOperatorField 824 825 @param opfield CeedOperatorField 826 @param[out] basis Variable to store CeedBasis 827 828 @return An error code: 0 - success, otherwise - failure 829 830 @ref Advanced 831 **/ 832 833 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, 834 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, 851 CeedVector *vec) { 852 *vec = opfield->vec; 853 return 0; 854 } 855 856 /** 857 @brief Destroy a CeedOperator 858 859 @param op CeedOperator to destroy 860 861 @return An error code: 0 - success, otherwise - failure 862 863 @ref Basic 864 **/ 865 int CeedOperatorDestroy(CeedOperator *op) { 866 int ierr; 867 868 if (!*op || --(*op)->refcount > 0) return 0; 869 if ((*op)->Destroy) { 870 ierr = (*op)->Destroy(*op); CeedChk(ierr); 871 } 872 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 873 // Free fields 874 for (int i=0; i<(*op)->nfields; i++) 875 if ((*op)->inputfields[i]) { 876 ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 877 CeedChk(ierr); 878 if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 879 ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 880 } 881 if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 882 (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 883 ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 884 } 885 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 886 } 887 for (int i=0; i<(*op)->nfields; i++) 888 if ((*op)->outputfields[i]) { 889 ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 890 CeedChk(ierr); 891 if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 892 ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 893 } 894 if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 895 (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 896 ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 897 } 898 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 899 } 900 // Destroy suboperators 901 for (int i=0; i<(*op)->numsub; i++) 902 if ((*op)->suboperators[i]) { 903 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 904 } 905 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 906 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 907 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 908 909 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 910 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 911 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 912 ierr = CeedFree(op); CeedChk(ierr); 913 return 0; 914 } 915 916 /// @} 917