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