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