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 an operator from element restriction, basis, and QFunction 29 30 @param ceed A Ceed object where the CeedOperator will be created 31 @param qf QFunction defining the action of the operator at quadrature points 32 @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 33 @param dqfT QFunction defining the action of the transpose of the Jacobian 34 of @a qf (or NULL) 35 @param[out] op Address of the variable where the newly created 36 CeedOperator will be stored 37 38 @return An error code: 0 - success, otherwise - failure 39 40 @ref Basic 41 */ 42 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 43 CeedQFunction dqfT, CeedOperator *op) { 44 int ierr; 45 46 if (!ceed->OperatorCreate) { 47 Ceed delegate; 48 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 49 50 if (!delegate) 51 return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 52 53 ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 54 return 0; 55 } 56 57 ierr = CeedCalloc(1,op); CeedChk(ierr); 58 (*op)->ceed = ceed; 59 ceed->refcount++; 60 (*op)->refcount = 1; 61 (*op)->qf = qf; 62 qf->refcount++; 63 (*op)->dqf = dqf; 64 if (dqf) dqf->refcount++; 65 (*op)->dqfT = dqfT; 66 if (dqfT) dqfT->refcount++; 67 ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 68 ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 69 ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 70 return 0; 71 } 72 73 /** 74 @brief Create an operator that composes the action of several operators 75 76 @param ceed A Ceed object where the CeedOperator will be created 77 @param[out] op Address of the variable where the newly created 78 Composite CeedOperator will be stored 79 80 @return An error code: 0 - success, otherwise - failure 81 82 @ref Basic 83 */ 84 int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 85 int ierr; 86 87 if (!ceed->CompositeOperatorCreate) { 88 Ceed delegate; 89 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 90 91 if (!delegate) 92 return CeedError(ceed, 1, "Backend does not support \ 93 CompositeOperatorCreate"); 94 95 ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 96 return 0; 97 } 98 99 ierr = CeedCalloc(1,op); CeedChk(ierr); 100 (*op)->ceed = ceed; 101 ceed->refcount++; 102 (*op)->composite = true; 103 ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 104 ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 105 return 0; 106 } 107 108 /** 109 @brief Provide a field to a CeedOperator for use by its CeedQFunction 110 111 This function is used to specify both active and passive fields to a 112 CeedOperator. For passive fields, a vector @arg v must be provided. Passive 113 fields can inputs or outputs (updated in-place when operator is applied). 114 115 Active fields must be specified using this function, but their data (in a 116 CeedVector) is passed in CeedOperatorApply(). There can be at most one active 117 input and at most one active output. 118 119 @param op Ceedoperator on which to provide the field 120 @param fieldname Name of the field (to be matched with the name used by CeedQFunction) 121 @param r CeedElemRestriction 122 @param lmode CeedTransposeMode which specifies the ordering of the 123 components of the l-vector used by this CeedOperatorField, 124 CEED_NOTRANSPOSE indicates the component is the 125 outermost index and CEED_TRANSPOSE indicates the component 126 is the innermost index in ordering of the l-vector 127 @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 128 if collocated with quadrature points 129 @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 130 if field is active or CEED_VECTOR_NONE if using 131 CEED_EVAL_WEIGHT in the qfunction 132 133 @return An error code: 0 - success, otherwise - failure 134 135 @ref Basic 136 **/ 137 int CeedOperatorSetField(CeedOperator op, const char *fieldname, 138 CeedElemRestriction r, CeedTransposeMode lmode, 139 CeedBasis b, CeedVector v) { 140 int ierr; 141 if (op->composite) 142 return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 143 144 CeedInt numelements; 145 ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 146 if (op->numelements && op->numelements != numelements) 147 return CeedError(op->ceed, 1, 148 "ElemRestriction with %d elements incompatible with prior %d elements", 149 numelements, op->numelements); 150 op->numelements = numelements; 151 152 if (b != CEED_BASIS_COLLOCATED) { 153 CeedInt numqpoints; 154 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 155 if (op->numqpoints && op->numqpoints != numqpoints) 156 return CeedError(op->ceed, 1, 157 "Basis with %d quadrature points incompatible with prior %d points", 158 numqpoints, op->numqpoints); 159 op->numqpoints = numqpoints; 160 } 161 CeedOperatorField *ofield; 162 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 163 if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 164 ofield = &op->inputfields[i]; 165 goto found; 166 } 167 } 168 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 169 if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 170 ofield = &op->outputfields[i]; 171 goto found; 172 } 173 } 174 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 175 fieldname); 176 found: 177 ierr = CeedCalloc(1, ofield); CeedChk(ierr); 178 (*ofield)->Erestrict = r; 179 (*ofield)->lmode = lmode; 180 (*ofield)->basis = b; 181 (*ofield)->vec = v; 182 op->nfields += 1; 183 return 0; 184 } 185 186 /** 187 @brief Add a sub-operator to a composite CeedOperator 188 @param[out] op Address of the composite CeedOperator 189 @param op Address of the sub-operator CeedOperator 190 191 @return An error code: 0 - success, otherwise - failure 192 193 @ref Basic 194 */ 195 int CeedCompositeOperatorAddSub(CeedOperator compositeop, 196 CeedOperator subop) { 197 if (!compositeop->composite) 198 return CeedError(compositeop->ceed, 1, 199 "CeedOperator is not a composite operator"); 200 201 if (compositeop->numsub == CEED_COMPOSITE_MAX) 202 return CeedError(compositeop->ceed, 1, 203 "Cannot add additional suboperators"); 204 205 compositeop->suboperators[compositeop->numsub] = subop; 206 subop->refcount++; 207 compositeop->numsub++; 208 return 0; 209 } 210 211 /** 212 @brief Apply CeedOperator to a vector 213 214 This computes the action of the operator on the specified (active) input, 215 yielding its (active) output. All inputs and outputs must be specified using 216 CeedOperatorSetField(). 217 218 @param op CeedOperator to apply 219 @param[in] in CeedVector containing input state or NULL if there are no 220 active inputs 221 @param[out] out CeedVector to store result of applying operator (must be 222 distinct from @a in) or NULL if there are no active outputs 223 @param request Address of CeedRequest for non-blocking completion, else 224 CEED_REQUEST_IMMEDIATE 225 226 @return An error code: 0 - success, otherwise - failure 227 228 @ref Basic 229 **/ 230 int CeedOperatorApply(CeedOperator op, CeedVector in, 231 CeedVector out, CeedRequest *request) { 232 int ierr; 233 Ceed ceed = op->ceed; 234 CeedQFunction qf = op->qf; 235 236 if (op->composite) { 237 if (!op->numsub) return CeedError(ceed, 1, "No suboperators set"); 238 } else { 239 if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 240 if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 241 ceed, 1, "Not all operator fields set"); 242 if (op->numelements == 0) return CeedError(ceed, 1, 243 "At least one restriction required"); 244 if (op->numqpoints == 0) return CeedError(ceed, 1, 245 "At least one non-collocated basis required"); 246 } 247 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 248 return 0; 249 } 250 251 /** 252 @brief Get the Ceed associated with a CeedOperator 253 254 @param op CeedOperator 255 @param[out] ceed Variable to store Ceed 256 257 @return An error code: 0 - success, otherwise - failure 258 259 @ref Advanced 260 **/ 261 262 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 263 *ceed = op->ceed; 264 return 0; 265 } 266 267 /** 268 @brief Get the number of elements associated with a CeedOperator 269 270 @param op CeedOperator 271 @param[out] numelem Variable to store number of elements 272 273 @return An error code: 0 - success, otherwise - failure 274 275 @ref Advanced 276 **/ 277 278 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 279 if (op->composite) 280 return CeedError(op->ceed, 1, "Not defined for composite operator"); 281 282 *numelem = op->numelements; 283 return 0; 284 } 285 286 /** 287 @brief Get the number of quadrature points associated with a CeedOperator 288 289 @param op CeedOperator 290 @param[out] numqpts Variable to store vector number of quadrature points 291 292 @return An error code: 0 - success, otherwise - failure 293 294 @ref Advanced 295 **/ 296 297 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 298 if (op->composite) 299 return CeedError(op->ceed, 1, "Not defined for composite operator"); 300 301 *numqpts = op->numqpoints; 302 return 0; 303 } 304 305 /** 306 @brief Get the number of arguments associated with a CeedOperator 307 308 @param op CeedOperator 309 @param[out] numargs Variable to store vector number of arguments 310 311 @return An error code: 0 - success, otherwise - failure 312 313 @ref Advanced 314 **/ 315 316 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 317 if (op->composite) 318 return CeedError(op->ceed, 1, "Not defined for composite operators"); 319 *numargs = op->nfields; 320 return 0; 321 } 322 323 /** 324 @brief Get the setup status of a CeedOperator 325 326 @param op CeedOperator 327 @param[out] numelem Variable to store setup status 328 329 @return An error code: 0 - success, otherwise - failure 330 331 @ref Advanced 332 **/ 333 334 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 335 *setupdone = op->setupdone; 336 return 0; 337 } 338 339 /** 340 @brief Get the QFunction associated with a CeedOperator 341 342 @param op CeedOperator 343 @param[out] qf Variable to store qfunction 344 345 @return An error code: 0 - success, otherwise - failure 346 347 @ref Advanced 348 **/ 349 350 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 351 if (op->composite) 352 return CeedError(op->ceed, 1, "Not defined for composite operator"); 353 354 *qf = op->qf; 355 return 0; 356 } 357 358 /** 359 @brief Get the number of suboperators associated with a CeedOperator 360 361 @param op CeedOperator 362 @param[out] numsub Variable to store number of suboperators 363 364 @return An error code: 0 - success, otherwise - failure 365 366 @ref Advanced 367 **/ 368 369 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 370 Ceed ceed = op->ceed; 371 if (!op->composite) return CeedError(ceed, 1, "Not a composite operator"); 372 373 *numsub = op->numsub; 374 return 0; 375 } 376 377 /** 378 @brief Get the list of suboperators associated with a CeedOperator 379 380 @param op CeedOperator 381 @param[out] suboperators Variable to store list of suboperators 382 383 @return An error code: 0 - success, otherwise - failure 384 385 @ref Advanced 386 **/ 387 388 int CeedOperatorGetSubList(CeedOperator op, CeedOperator* *suboperators) { 389 Ceed ceed = op->ceed; 390 if (!op->composite) return CeedError(ceed, 1, "Not a composite operator"); 391 392 *suboperators = op->suboperators; 393 return 0; 394 } 395 396 /** 397 @brief Set the backend data of a CeedOperator 398 399 @param[out] op CeedOperator 400 @param data Data to set 401 402 @return An error code: 0 - success, otherwise - failure 403 404 @ref Advanced 405 **/ 406 407 int CeedOperatorSetData(CeedOperator op, void* *data) { 408 op->data = *data; 409 return 0; 410 } 411 412 /** 413 @brief Get the backend data of a CeedOperator 414 415 @param op CeedOperator 416 @param[out] data Variable to store data 417 418 @return An error code: 0 - success, otherwise - failure 419 420 @ref Advanced 421 **/ 422 423 int CeedOperatorGetData(CeedOperator op, void* *data) { 424 *data = op->data; 425 return 0; 426 } 427 428 /** 429 @brief Set the setup flag of a CeedOperator to True 430 431 @param op CeedOperator 432 433 @return An error code: 0 - success, otherwise - failure 434 435 @ref Advanced 436 **/ 437 438 int CeedOperatorSetSetupDone(CeedOperator op) { 439 op->setupdone = 1; 440 return 0; 441 } 442 443 /** 444 @brief Get the CeedOperatorFields of a CeedOperator 445 446 @param op CeedOperator 447 @param[out] inputfields Variable to store inputfields 448 @param[out] outputfields Variable to store outputfields 449 450 @return An error code: 0 - success, otherwise - failure 451 452 @ref Advanced 453 **/ 454 455 int CeedOperatorGetFields(CeedOperator op, 456 CeedOperatorField* *inputfields, 457 CeedOperatorField* *outputfields) { 458 if (op->composite) 459 return CeedError(op->ceed, 1, "Not defined for composite operator"); 460 461 if (inputfields) *inputfields = op->inputfields; 462 if (outputfields) *outputfields = op->outputfields; 463 return 0; 464 } 465 466 /** 467 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 468 469 @param opfield CeedOperatorField 470 @param[out] lmode Variable to store CeedTransposeMode 471 472 @return An error code: 0 - success, otherwise - failure 473 474 @ref Advanced 475 **/ 476 477 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 478 CeedTransposeMode *lmode) { 479 *lmode = opfield->lmode; 480 return 0; 481 }/** 482 @brief Get the CeedElemRestriction of a CeedOperatorField 483 484 @param opfield CeedOperatorField 485 @param[out] rstr Variable to store CeedElemRestriction 486 487 @return An error code: 0 - success, otherwise - failure 488 489 @ref Advanced 490 **/ 491 492 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 493 CeedElemRestriction *rstr) { 494 *rstr = opfield->Erestrict; 495 return 0; 496 } 497 498 /** 499 @brief Get the CeedBasis of a CeedOperatorField 500 501 @param opfield CeedOperatorField 502 @param[out] basis Variable to store CeedBasis 503 504 @return An error code: 0 - success, otherwise - failure 505 506 @ref Advanced 507 **/ 508 509 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, 510 CeedBasis *basis) { 511 *basis = opfield->basis; 512 return 0; 513 } 514 515 /** 516 @brief Get the CeedVector of a CeedOperatorField 517 518 @param opfield CeedOperatorField 519 @param[out] vec Variable to store CeedVector 520 521 @return An error code: 0 - success, otherwise - failure 522 523 @ref Advanced 524 **/ 525 526 int CeedOperatorFieldGetVector(CeedOperatorField opfield, 527 CeedVector *vec) { 528 *vec = opfield->vec; 529 return 0; 530 } 531 532 /** 533 @brief Destroy a CeedOperator 534 535 @param op CeedOperator to destroy 536 537 @return An error code: 0 - success, otherwise - failure 538 539 @ref Basic 540 **/ 541 int CeedOperatorDestroy(CeedOperator *op) { 542 int ierr; 543 544 if (!*op || --(*op)->refcount > 0) return 0; 545 if ((*op)->Destroy) { 546 ierr = (*op)->Destroy(*op); CeedChk(ierr); 547 } 548 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 549 // Free fields 550 for (int i=0; i<(*op)->nfields; i++) { 551 if ((*op)->inputfields[i]) { 552 ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 553 } 554 } 555 for (int i=0; i<(*op)->nfields; i++) { 556 if ((*op)->outputfields[i]) { 557 ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 558 } 559 } 560 // Destroy suboperators 561 for (int i=0; i<(*op)->numsub; i++) { 562 if ((*op)->suboperators[i]) { 563 ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 564 } 565 } 566 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 567 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 568 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 569 570 ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 571 ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 572 ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 573 ierr = CeedFree(op); CeedChk(ierr); 574 return 0; 575 } 576 577 /// @} 578