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