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, FILE *stream) { 789 const char* pre = sub ? " " : ""; 790 791 fprintf(stream, "%s [%d] Operator Field \"%s\"\n" 792 "%s Lmode \"%s\"\n", 793 pre, fieldnumber, qffield->fieldname, 794 pre, CeedTransposeModes[field->lmode]); 795 796 if (field->basis == CEED_BASIS_COLLOCATED) 797 fprintf(stream, "%s Collocated basis\n", pre); 798 799 if (field->vec == CEED_VECTOR_ACTIVE) 800 fprintf(stream, "%s Active vector\n", pre); 801 else if (field->vec == CEED_VECTOR_NONE) 802 fprintf(stream, "%s No vector\n", pre); 803 804 return 0; 805 } 806 807 /** 808 @brief View a single CeedOperator 809 810 @param[in] op CeedOperator to view 811 @param[in] stream Stream to write; typically stdout/stderr or a file 812 813 @return Error code: 0 - success, otherwise - failure 814 815 @ref Utility 816 **/ 817 int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 818 int ierr; 819 const char* pre = sub ? " " : ""; 820 821 CeedInt totalfields; 822 ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 823 fprintf(stream, "%s%d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 824 825 fprintf(stream, "%s%d Input Field%s\n", pre, op->qf->numinputfields, 826 op->qf->numinputfields>1 ? "s" : ""); 827 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 828 ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 829 i, sub, stream); CeedChk(ierr); 830 } 831 832 fprintf(stream, "%s%d Output Field%s\n", pre, op->qf->numoutputfields, 833 op->qf->numoutputfields>1 ? "s" : ""); 834 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 835 ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 836 i, sub, stream); CeedChk(ierr); 837 } 838 839 return 0; 840 } 841 842 /** 843 @brief View a CeedOperator 844 845 @param[in] op CeedOperator to view 846 @param[in] stream Stream to write; typically stdout/stderr or a file 847 848 @return Error code: 0 - success, otherwise - failure 849 850 @ref Utility 851 **/ 852 int CeedOperatorView(CeedOperator op, FILE *stream) { 853 int ierr; 854 855 if (op->composite) { 856 fprintf(stream, "Composite CeedOperator\n"); 857 858 for (CeedInt i=0; i<op->numsub; i++) { 859 fprintf(stream, "SubOperator [%d]\n", i); 860 ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 861 CeedChk(ierr); 862 } 863 } else { 864 fprintf(stream, "CeedOperator\n"); 865 ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 866 } 867 868 return 0; 869 } 870 871 /** 872 @brief Get the CeedOperatorFields of a CeedOperator 873 874 @param op CeedOperator 875 @param[out] inputfields Variable to store inputfields 876 @param[out] outputfields Variable to store outputfields 877 878 @return An error code: 0 - success, otherwise - failure 879 880 @ref Advanced 881 **/ 882 883 int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 884 CeedOperatorField **outputfields) { 885 if (op->composite) 886 // LCOV_EXCL_START 887 return CeedError(op->ceed, 1, "Not defined for composite operator"); 888 // LCOV_EXCL_STOP 889 890 if (inputfields) *inputfields = op->inputfields; 891 if (outputfields) *outputfields = op->outputfields; 892 return 0; 893 } 894 895 /** 896 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 897 898 @param opfield CeedOperatorField 899 @param[out] lmode Variable to store CeedTransposeMode 900 901 @return An error code: 0 - success, otherwise - failure 902 903 @ref Advanced 904 **/ 905 906 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 907 CeedTransposeMode *lmode) { 908 *lmode = opfield->lmode; 909 return 0; 910 } 911 912 /** 913 @brief Get the CeedElemRestriction of a CeedOperatorField 914 915 @param opfield CeedOperatorField 916 @param[out] rstr Variable to store CeedElemRestriction 917 918 @return An error code: 0 - success, otherwise - failure 919 920 @ref Advanced 921 **/ 922 923 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 924 CeedElemRestriction *rstr) { 925 *rstr = opfield->Erestrict; 926 return 0; 927 } 928 929 /** 930 @brief Get the CeedBasis of a CeedOperatorField 931 932 @param opfield CeedOperatorField 933 @param[out] basis Variable to store CeedBasis 934 935 @return An error code: 0 - success, otherwise - failure 936 937 @ref Advanced 938 **/ 939 940 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 941 *basis = opfield->basis; 942 return 0; 943 } 944 945 /** 946 @brief Get the CeedVector of a CeedOperatorField 947 948 @param opfield CeedOperatorField 949 @param[out] vec Variable to store CeedVector 950 951 @return An error code: 0 - success, otherwise - failure 952 953 @ref Advanced 954 **/ 955 956 int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 957 *vec = opfield->vec; 958 return 0; 959 } 960 961 /** 962 @brief Destroy a CeedOperator 963 964 @param op CeedOperator to destroy 965 966 @return An error code: 0 - success, otherwise - failure 967 968 @ref Basic 969 **/ 970 int CeedOperatorDestroy(CeedOperator *op) { 971 int ierr; 972 973 if (!*op || --(*op)->refcount > 0) return 0; 974 if ((*op)->Destroy) { 975 ierr = (*op)->Destroy(*op); CeedChk(ierr); 976 } 977 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 978 // Free fields 979 for (int i=0; i<(*op)->nfields; i++) 980 if ((*op)->inputfields[i]) { 981 ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 982 CeedChk(ierr); 983 if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 984 ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 985 } 986 if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 987 (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 988 ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 989 } 990 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 991 } 992 for (int i=0; i<(*op)->nfields; i++) 993 if ((*op)->outputfields[i]) { 994 ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 995 CeedChk(ierr); 996 if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 997 ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 998 } 999 if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 1000 (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 1001 ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 1002 } 1003 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1004 } 1005 // Destroy suboperators 1006 for (int i=0; i<(*op)->numsub; i++) 1007 if ((*op)->suboperators[i]) { 1008 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 1009 } 1010 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1011 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1012 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1013 1014 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1015 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 1016 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1017 ierr = CeedFree(op); CeedChk(ierr); 1018 return 0; 1019 } 1020 1021 /// @} 1022