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/ceed.h> 18 #include <ceed/backend.h> 19 #include <ceed-impl.h> 20 #include <stdbool.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 /// @file 25 /// Implementation of CeedOperator interfaces 26 27 /// ---------------------------------------------------------------------------- 28 /// CeedOperator Library Internal Functions 29 /// ---------------------------------------------------------------------------- 30 /// @addtogroup CeedOperatorDeveloper 31 /// @{ 32 33 /** 34 @brief Check if a CeedOperator Field matches the QFunction Field 35 36 @param[in] ceed Ceed object for error handling 37 @param[in] qf_field QFunction Field matching Operator Field 38 @param[in] r Operator Field ElemRestriction 39 @param[in] b Operator Field Basis 40 41 @return An error code: 0 - success, otherwise - failure 42 43 @ref Developer 44 **/ 45 static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, 46 CeedElemRestriction r, CeedBasis b) { 47 int ierr; 48 CeedEvalMode eval_mode = qf_field->eval_mode; 49 CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size; 50 // Restriction 51 if (r != CEED_ELEMRESTRICTION_NONE) { 52 if (eval_mode == CEED_EVAL_WEIGHT) { 53 // LCOV_EXCL_START 54 return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 55 "CEED_ELEMRESTRICTION_NONE should be used " 56 "for a field with eval mode CEED_EVAL_WEIGHT"); 57 // LCOV_EXCL_STOP 58 } 59 ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp); 60 CeedChk(ierr); 61 } 62 if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) { 63 // LCOV_EXCL_START 64 return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 65 "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 66 "must be used together."); 67 // LCOV_EXCL_STOP 68 } 69 // Basis 70 if (b != CEED_BASIS_COLLOCATED) { 71 if (eval_mode == CEED_EVAL_NONE) 72 // LCOV_EXCL_START 73 return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 74 "Field '%s' configured with CEED_EVAL_NONE must " 75 "be used with CEED_BASIS_COLLOCATED", 76 // LCOV_EXCL_STOP 77 qf_field->field_name); 78 ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 79 ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 80 if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 81 // LCOV_EXCL_START 82 return CeedError(ceed, CEED_ERROR_DIMENSION, 83 "Field '%s' of size %d and EvalMode %s: ElemRestriction " 84 "has %d components, but Basis has %d components", 85 qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 86 restr_num_comp, 87 num_comp); 88 // LCOV_EXCL_STOP 89 } 90 } 91 // Field size 92 switch(eval_mode) { 93 case CEED_EVAL_NONE: 94 if (size != restr_num_comp) 95 // LCOV_EXCL_START 96 return CeedError(ceed, CEED_ERROR_DIMENSION, 97 "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 98 qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 99 restr_num_comp); 100 // LCOV_EXCL_STOP 101 break; 102 case CEED_EVAL_INTERP: 103 if (size != num_comp) 104 // LCOV_EXCL_START 105 return CeedError(ceed, CEED_ERROR_DIMENSION, 106 "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 107 qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 108 num_comp); 109 // LCOV_EXCL_STOP 110 break; 111 case CEED_EVAL_GRAD: 112 if (size != num_comp * dim) 113 // LCOV_EXCL_START 114 return CeedError(ceed, CEED_ERROR_DIMENSION, 115 "Field '%s' of size %d and EvalMode %s in %d dimensions: " 116 "ElemRestriction/Basis has %d components", 117 qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 118 num_comp); 119 // LCOV_EXCL_STOP 120 break; 121 case CEED_EVAL_WEIGHT: 122 // No additional checks required 123 break; 124 case CEED_EVAL_DIV: 125 // Not implemented 126 break; 127 case CEED_EVAL_CURL: 128 // Not implemented 129 break; 130 } 131 return CEED_ERROR_SUCCESS; 132 } 133 134 /** 135 @brief View a field of a CeedOperator 136 137 @param[in] field Operator field to view 138 @param[in] qf_field QFunction field (carries field name) 139 @param[in] field_number Number of field being viewed 140 @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 141 @param[in] input true for an input field; false for output field 142 @param[in] stream Stream to view to, e.g., stdout 143 144 @return An error code: 0 - success, otherwise - failure 145 146 @ref Utility 147 **/ 148 static int CeedOperatorFieldView(CeedOperatorField field, 149 CeedQFunctionField qf_field, 150 CeedInt field_number, bool sub, bool input, 151 FILE *stream) { 152 const char *pre = sub ? " " : ""; 153 const char *in_out = input ? "Input" : "Output"; 154 155 fprintf(stream, "%s %s Field [%d]:\n" 156 "%s Name: \"%s\"\n", 157 pre, in_out, field_number, pre, qf_field->field_name); 158 159 if (field->basis == CEED_BASIS_COLLOCATED) 160 fprintf(stream, "%s Collocated basis\n", pre); 161 162 if (field->vec == CEED_VECTOR_ACTIVE) 163 fprintf(stream, "%s Active vector\n", pre); 164 else if (field->vec == CEED_VECTOR_NONE) 165 fprintf(stream, "%s No vector\n", pre); 166 return CEED_ERROR_SUCCESS; 167 } 168 169 /** 170 @brief View a single CeedOperator 171 172 @param[in] op CeedOperator to view 173 @param[in] sub Boolean flag for sub-operator 174 @param[in] stream Stream to write; typically stdout/stderr or a file 175 176 @return Error code: 0 - success, otherwise - failure 177 178 @ref Utility 179 **/ 180 int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 181 int ierr; 182 const char *pre = sub ? " " : ""; 183 184 CeedInt total_fields = 0; 185 ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 186 187 fprintf(stream, "%s %d Field%s\n", pre, total_fields, 188 total_fields>1 ? "s" : ""); 189 190 fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 191 op->qf->num_input_fields>1 ? "s" : ""); 192 for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 193 ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 194 i, sub, 1, stream); CeedChk(ierr); 195 } 196 197 fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 198 op->qf->num_output_fields>1 ? "s" : ""); 199 for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 200 ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 201 i, sub, 0, stream); CeedChk(ierr); 202 } 203 return CEED_ERROR_SUCCESS; 204 } 205 206 /** 207 @brief Find the active vector basis for a non-composite CeedOperator 208 209 @param[in] op CeedOperator to find active basis for 210 @param[out] active_basis Basis for active input vector or NULL for composite operator 211 212 @return An error code: 0 - success, otherwise - failure 213 214 @ ref Developer 215 **/ 216 int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) { 217 *active_basis = NULL; 218 if (op->is_composite) return CEED_ERROR_SUCCESS; 219 for (int i = 0; i < op->qf->num_input_fields; i++) 220 if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 221 *active_basis = op->input_fields[i]->basis; 222 break; 223 } 224 225 if (!*active_basis) { 226 // LCOV_EXCL_START 227 int ierr; 228 Ceed ceed; 229 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 230 return CeedError(ceed, CEED_ERROR_MINOR, 231 "No active CeedBasis found"); 232 // LCOV_EXCL_STOP 233 } 234 return CEED_ERROR_SUCCESS; 235 } 236 237 /** 238 @brief Find the active vector ElemRestriction for a non-composite CeedOperator 239 240 @param[in] op CeedOperator to find active basis for 241 @param[out] active_rstr ElemRestriction for active input vector or NULL for composite operator 242 243 @return An error code: 0 - success, otherwise - failure 244 245 @ref Utility 246 **/ 247 int CeedOperatorGetActiveElemRestriction(CeedOperator op, 248 CeedElemRestriction *active_rstr) { 249 *active_rstr = NULL; 250 if (op->is_composite) return CEED_ERROR_SUCCESS; 251 for (int i = 0; i < op->qf->num_input_fields; i++) 252 if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 253 *active_rstr = op->input_fields[i]->elem_restr; 254 break; 255 } 256 257 if (!*active_rstr) { 258 // LCOV_EXCL_START 259 int ierr; 260 Ceed ceed; 261 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 262 return CeedError(ceed, CEED_ERROR_INCOMPLETE, 263 "No active CeedElemRestriction found"); 264 // LCOV_EXCL_STOP 265 } 266 return CEED_ERROR_SUCCESS; 267 } 268 269 /** 270 @brief Set QFunctionContext field value of the specified type. 271 For composite operators, the value is set in all 272 sub-operator QFunctionContexts that have a matching `field_name`. 273 A non-zero error code is returned for single operators 274 that do not have a matching field of the same type or composite 275 operators that do not have any field of a matching type. 276 277 @param op CeedOperator 278 @param field_label Label of field to set 279 @param field_type Type of field to set 280 @param value Value to set 281 282 @return An error code: 0 - success, otherwise - failure 283 284 @ref User 285 **/ 286 static int CeedOperatorContextSetGeneric(CeedOperator op, 287 CeedContextFieldLabel field_label, CeedContextFieldType field_type, 288 void *value) { 289 int ierr; 290 291 if (!field_label) 292 // LCOV_EXCL_START 293 return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 294 "Invalid field label"); 295 // LCOV_EXCL_STOP 296 297 bool is_composite = false; 298 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 299 if (is_composite) { 300 CeedInt num_sub; 301 CeedOperator *sub_operators; 302 303 ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 304 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 305 if (num_sub != field_label->num_sub_labels) 306 // LCOV_EXCL_START 307 return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 308 "ContextLabel does not correspond to composite operator.\n" 309 "Use CeedOperatorGetContextFieldLabel()."); 310 // LCOV_EXCL_STOP 311 312 for (CeedInt i = 0; i < num_sub; i++) { 313 // Try every sub-operator, ok if some sub-operators do not have field 314 if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) { 315 ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx, 316 field_label->sub_labels[i], 317 field_type, value); CeedChk(ierr); 318 } 319 } 320 } else { 321 if (!op->qf->ctx) 322 // LCOV_EXCL_START 323 return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 324 "QFunction does not have context data"); 325 // LCOV_EXCL_STOP 326 327 ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label, 328 field_type, value); CeedChk(ierr); 329 } 330 331 return CEED_ERROR_SUCCESS; 332 } 333 334 /// @} 335 336 /// ---------------------------------------------------------------------------- 337 /// CeedOperator Backend API 338 /// ---------------------------------------------------------------------------- 339 /// @addtogroup CeedOperatorBackend 340 /// @{ 341 342 /** 343 @brief Get the number of arguments associated with a CeedOperator 344 345 @param op CeedOperator 346 @param[out] num_args Variable to store vector number of arguments 347 348 @return An error code: 0 - success, otherwise - failure 349 350 @ref Backend 351 **/ 352 353 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 354 if (op->is_composite) 355 // LCOV_EXCL_START 356 return CeedError(op->ceed, CEED_ERROR_MINOR, 357 "Not defined for composite operators"); 358 // LCOV_EXCL_STOP 359 360 *num_args = op->num_fields; 361 return CEED_ERROR_SUCCESS; 362 } 363 364 /** 365 @brief Get the setup status of a CeedOperator 366 367 @param op CeedOperator 368 @param[out] is_setup_done Variable to store setup status 369 370 @return An error code: 0 - success, otherwise - failure 371 372 @ref Backend 373 **/ 374 375 int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 376 *is_setup_done = op->is_backend_setup; 377 return CEED_ERROR_SUCCESS; 378 } 379 380 /** 381 @brief Get the QFunction associated with a CeedOperator 382 383 @param op CeedOperator 384 @param[out] qf Variable to store QFunction 385 386 @return An error code: 0 - success, otherwise - failure 387 388 @ref Backend 389 **/ 390 391 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 392 if (op->is_composite) 393 // LCOV_EXCL_START 394 return CeedError(op->ceed, CEED_ERROR_MINOR, 395 "Not defined for composite operator"); 396 // LCOV_EXCL_STOP 397 398 *qf = op->qf; 399 return CEED_ERROR_SUCCESS; 400 } 401 402 /** 403 @brief Get a boolean value indicating if the CeedOperator is composite 404 405 @param op CeedOperator 406 @param[out] is_composite Variable to store composite status 407 408 @return An error code: 0 - success, otherwise - failure 409 410 @ref Backend 411 **/ 412 413 int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 414 *is_composite = op->is_composite; 415 return CEED_ERROR_SUCCESS; 416 } 417 418 /** 419 @brief Get the number of sub_operators associated with a CeedOperator 420 421 @param op CeedOperator 422 @param[out] num_suboperators Variable to store number of sub_operators 423 424 @return An error code: 0 - success, otherwise - failure 425 426 @ref Backend 427 **/ 428 429 int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 430 if (!op->is_composite) 431 // LCOV_EXCL_START 432 return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 433 // LCOV_EXCL_STOP 434 435 *num_suboperators = op->num_suboperators; 436 return CEED_ERROR_SUCCESS; 437 } 438 439 /** 440 @brief Get the list of sub_operators associated with a CeedOperator 441 442 @param op CeedOperator 443 @param[out] sub_operators Variable to store list of sub_operators 444 445 @return An error code: 0 - success, otherwise - failure 446 447 @ref Backend 448 **/ 449 450 int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 451 if (!op->is_composite) 452 // LCOV_EXCL_START 453 return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 454 // LCOV_EXCL_STOP 455 456 *sub_operators = op->sub_operators; 457 return CEED_ERROR_SUCCESS; 458 } 459 460 /** 461 @brief Get the backend data of a CeedOperator 462 463 @param op CeedOperator 464 @param[out] data Variable to store data 465 466 @return An error code: 0 - success, otherwise - failure 467 468 @ref Backend 469 **/ 470 471 int CeedOperatorGetData(CeedOperator op, void *data) { 472 *(void **)data = op->data; 473 return CEED_ERROR_SUCCESS; 474 } 475 476 /** 477 @brief Set the backend data of a CeedOperator 478 479 @param[out] op CeedOperator 480 @param data Data to set 481 482 @return An error code: 0 - success, otherwise - failure 483 484 @ref Backend 485 **/ 486 487 int CeedOperatorSetData(CeedOperator op, void *data) { 488 op->data = data; 489 return CEED_ERROR_SUCCESS; 490 } 491 492 /** 493 @brief Increment the reference counter for a CeedOperator 494 495 @param op CeedOperator to increment the reference counter 496 497 @return An error code: 0 - success, otherwise - failure 498 499 @ref Backend 500 **/ 501 int CeedOperatorReference(CeedOperator op) { 502 op->ref_count++; 503 return CEED_ERROR_SUCCESS; 504 } 505 506 /** 507 @brief Set the setup flag of a CeedOperator to True 508 509 @param op CeedOperator 510 511 @return An error code: 0 - success, otherwise - failure 512 513 @ref Backend 514 **/ 515 516 int CeedOperatorSetSetupDone(CeedOperator op) { 517 op->is_backend_setup = true; 518 return CEED_ERROR_SUCCESS; 519 } 520 521 /// @} 522 523 /// ---------------------------------------------------------------------------- 524 /// CeedOperator Public API 525 /// ---------------------------------------------------------------------------- 526 /// @addtogroup CeedOperatorUser 527 /// @{ 528 529 /** 530 @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 531 CeedElemRestriction can be associated with CeedQFunction fields with 532 \ref CeedOperatorSetField. 533 534 @param ceed A Ceed object where the CeedOperator will be created 535 @param qf QFunction defining the action of the operator at quadrature points 536 @param dqf QFunction defining the action of the Jacobian of @a qf (or 537 @ref CEED_QFUNCTION_NONE) 538 @param dqfT QFunction defining the action of the transpose of the Jacobian 539 of @a qf (or @ref CEED_QFUNCTION_NONE) 540 @param[out] op Address of the variable where the newly created 541 CeedOperator will be stored 542 543 @return An error code: 0 - success, otherwise - failure 544 545 @ref User 546 */ 547 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 548 CeedQFunction dqfT, CeedOperator *op) { 549 int ierr; 550 551 if (!ceed->OperatorCreate) { 552 Ceed delegate; 553 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 554 555 if (!delegate) 556 // LCOV_EXCL_START 557 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 558 "Backend does not support OperatorCreate"); 559 // LCOV_EXCL_STOP 560 561 ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 562 return CEED_ERROR_SUCCESS; 563 } 564 565 if (!qf || qf == CEED_QFUNCTION_NONE) 566 // LCOV_EXCL_START 567 return CeedError(ceed, CEED_ERROR_MINOR, 568 "Operator must have a valid QFunction."); 569 // LCOV_EXCL_STOP 570 ierr = CeedCalloc(1, op); CeedChk(ierr); 571 (*op)->ceed = ceed; 572 ierr = CeedReference(ceed); CeedChk(ierr); 573 (*op)->ref_count = 1; 574 (*op)->qf = qf; 575 ierr = CeedQFunctionReference(qf); CeedChk(ierr); 576 if (dqf && dqf != CEED_QFUNCTION_NONE) { 577 (*op)->dqf = dqf; 578 ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 579 } 580 if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 581 (*op)->dqfT = dqfT; 582 ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 583 } 584 ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled); 585 CeedChk(ierr); 586 ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr); 587 ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr); 588 ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 589 return CEED_ERROR_SUCCESS; 590 } 591 592 /** 593 @brief Create an operator that composes the action of several operators 594 595 @param ceed A Ceed object where the CeedOperator will be created 596 @param[out] op Address of the variable where the newly created 597 Composite CeedOperator will be stored 598 599 @return An error code: 0 - success, otherwise - failure 600 601 @ref User 602 */ 603 int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 604 int ierr; 605 606 if (!ceed->CompositeOperatorCreate) { 607 Ceed delegate; 608 ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 609 610 if (delegate) { 611 ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 612 return CEED_ERROR_SUCCESS; 613 } 614 } 615 616 ierr = CeedCalloc(1, op); CeedChk(ierr); 617 (*op)->ceed = ceed; 618 ierr = CeedReference(ceed); CeedChk(ierr); 619 (*op)->is_composite = true; 620 ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr); 621 622 if (ceed->CompositeOperatorCreate) { 623 ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 624 } 625 return CEED_ERROR_SUCCESS; 626 } 627 628 /** 629 @brief Copy the pointer to a CeedOperator. Both pointers should 630 be destroyed with `CeedOperatorDestroy()`; 631 Note: If `*op_copy` is non-NULL, then it is assumed that 632 `*op_copy` is a pointer to a CeedOperator. This 633 CeedOperator will be destroyed if `*op_copy` is the only 634 reference to this CeedOperator. 635 636 @param op CeedOperator to copy reference to 637 @param[out] op_copy Variable to store copied reference 638 639 @return An error code: 0 - success, otherwise - failure 640 641 @ref User 642 **/ 643 int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 644 int ierr; 645 646 ierr = CeedOperatorReference(op); CeedChk(ierr); 647 ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 648 *op_copy = op; 649 return CEED_ERROR_SUCCESS; 650 } 651 652 /** 653 @brief Provide a field to a CeedOperator for use by its CeedQFunction 654 655 This function is used to specify both active and passive fields to a 656 CeedOperator. For passive fields, a vector @arg v must be provided. Passive 657 fields can inputs or outputs (updated in-place when operator is applied). 658 659 Active fields must be specified using this function, but their data (in a 660 CeedVector) is passed in CeedOperatorApply(). There can be at most one active 661 input and at most one active output. 662 663 @param op CeedOperator on which to provide the field 664 @param field_name Name of the field (to be matched with the name used by 665 CeedQFunction) 666 @param r CeedElemRestriction 667 @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 668 if collocated with quadrature points 669 @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 670 if field is active or @ref CEED_VECTOR_NONE if using 671 @ref CEED_EVAL_WEIGHT in the QFunction 672 673 @return An error code: 0 - success, otherwise - failure 674 675 @ref User 676 **/ 677 int CeedOperatorSetField(CeedOperator op, const char *field_name, 678 CeedElemRestriction r, CeedBasis b, CeedVector v) { 679 int ierr; 680 if (op->is_composite) 681 // LCOV_EXCL_START 682 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 683 "Cannot add field to composite operator."); 684 // LCOV_EXCL_STOP 685 if (op->is_immutable) 686 // LCOV_EXCL_START 687 return CeedError(op->ceed, CEED_ERROR_MAJOR, 688 "Operator cannot be changed after set as immutable"); 689 // LCOV_EXCL_STOP 690 if (!r) 691 // LCOV_EXCL_START 692 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 693 "ElemRestriction r for field \"%s\" must be non-NULL.", 694 field_name); 695 // LCOV_EXCL_STOP 696 if (!b) 697 // LCOV_EXCL_START 698 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 699 "Basis b for field \"%s\" must be non-NULL.", 700 field_name); 701 // LCOV_EXCL_STOP 702 if (!v) 703 // LCOV_EXCL_START 704 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 705 "Vector v for field \"%s\" must be non-NULL.", 706 field_name); 707 // LCOV_EXCL_STOP 708 709 CeedInt num_elem; 710 ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 711 if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 712 op->num_elem != num_elem) 713 // LCOV_EXCL_START 714 return CeedError(op->ceed, CEED_ERROR_DIMENSION, 715 "ElemRestriction with %d elements incompatible with prior " 716 "%d elements", num_elem, op->num_elem); 717 // LCOV_EXCL_STOP 718 719 CeedInt num_qpts = 0; 720 if (b != CEED_BASIS_COLLOCATED) { 721 ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 722 if (op->num_qpts && op->num_qpts != num_qpts) 723 // LCOV_EXCL_START 724 return CeedError(op->ceed, CEED_ERROR_DIMENSION, 725 "Basis with %d quadrature points " 726 "incompatible with prior %d points", num_qpts, 727 op->num_qpts); 728 // LCOV_EXCL_STOP 729 } 730 CeedQFunctionField qf_field; 731 CeedOperatorField *op_field; 732 for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 733 if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 734 qf_field = op->qf->input_fields[i]; 735 op_field = &op->input_fields[i]; 736 goto found; 737 } 738 } 739 for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 740 if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 741 qf_field = op->qf->output_fields[i]; 742 op_field = &op->output_fields[i]; 743 goto found; 744 } 745 } 746 // LCOV_EXCL_START 747 return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 748 "QFunction has no knowledge of field '%s'", 749 field_name); 750 // LCOV_EXCL_STOP 751 found: 752 ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 753 ierr = CeedCalloc(1, op_field); CeedChk(ierr); 754 755 (*op_field)->vec = v; 756 if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 757 ierr = CeedVectorReference(v); CeedChk(ierr); 758 } 759 760 (*op_field)->elem_restr = r; 761 ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 762 if (r != CEED_ELEMRESTRICTION_NONE) { 763 op->num_elem = num_elem; 764 op->has_restriction = true; // Restriction set, but num_elem may be 0 765 } 766 767 (*op_field)->basis = b; 768 if (b != CEED_BASIS_COLLOCATED) { 769 if (!op->num_qpts) { 770 ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 771 } 772 ierr = CeedBasisReference(b); CeedChk(ierr); 773 } 774 775 op->num_fields += 1; 776 ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name); 777 CeedChk(ierr); 778 return CEED_ERROR_SUCCESS; 779 } 780 781 /** 782 @brief Get the CeedOperatorFields of a CeedOperator 783 784 Note: Calling this function asserts that setup is complete 785 and sets the CeedOperator as immutable. 786 787 @param op CeedOperator 788 @param[out] num_input_fields Variable to store number of input fields 789 @param[out] input_fields Variable to store input_fields 790 @param[out] num_output_fields Variable to store number of output fields 791 @param[out] output_fields Variable to store output_fields 792 793 @return An error code: 0 - success, otherwise - failure 794 795 @ref Advanced 796 **/ 797 int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields, 798 CeedOperatorField **input_fields, 799 CeedInt *num_output_fields, 800 CeedOperatorField **output_fields) { 801 int ierr; 802 803 if (op->is_composite) 804 // LCOV_EXCL_START 805 return CeedError(op->ceed, CEED_ERROR_MINOR, 806 "Not defined for composite operator"); 807 // LCOV_EXCL_STOP 808 ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 809 810 if (num_input_fields) *num_input_fields = op->qf->num_input_fields; 811 if (input_fields) *input_fields = op->input_fields; 812 if (num_output_fields) *num_output_fields = op->qf->num_output_fields; 813 if (output_fields) *output_fields = op->output_fields; 814 return CEED_ERROR_SUCCESS; 815 } 816 817 /** 818 @brief Get the name of a CeedOperatorField 819 820 @param op_field CeedOperatorField 821 @param[out] field_name Variable to store the field name 822 823 @return An error code: 0 - success, otherwise - failure 824 825 @ref Advanced 826 **/ 827 int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) { 828 *field_name = (char *)op_field->field_name; 829 return CEED_ERROR_SUCCESS; 830 } 831 832 /** 833 @brief Get the CeedElemRestriction of a CeedOperatorField 834 835 @param op_field CeedOperatorField 836 @param[out] rstr Variable to store CeedElemRestriction 837 838 @return An error code: 0 - success, otherwise - failure 839 840 @ref Advanced 841 **/ 842 int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 843 CeedElemRestriction *rstr) { 844 *rstr = op_field->elem_restr; 845 return CEED_ERROR_SUCCESS; 846 } 847 848 /** 849 @brief Get the CeedBasis of a CeedOperatorField 850 851 @param op_field CeedOperatorField 852 @param[out] basis Variable to store CeedBasis 853 854 @return An error code: 0 - success, otherwise - failure 855 856 @ref Advanced 857 **/ 858 int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 859 *basis = op_field->basis; 860 return CEED_ERROR_SUCCESS; 861 } 862 863 /** 864 @brief Get the CeedVector of a CeedOperatorField 865 866 @param op_field CeedOperatorField 867 @param[out] vec Variable to store CeedVector 868 869 @return An error code: 0 - success, otherwise - failure 870 871 @ref Advanced 872 **/ 873 int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 874 *vec = op_field->vec; 875 return CEED_ERROR_SUCCESS; 876 } 877 878 /** 879 @brief Add a sub-operator to a composite CeedOperator 880 881 @param[out] composite_op Composite CeedOperator 882 @param sub_op Sub-operator CeedOperator 883 884 @return An error code: 0 - success, otherwise - failure 885 886 @ref User 887 */ 888 int CeedCompositeOperatorAddSub(CeedOperator composite_op, 889 CeedOperator sub_op) { 890 int ierr; 891 892 if (!composite_op->is_composite) 893 // LCOV_EXCL_START 894 return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 895 "CeedOperator is not a composite operator"); 896 // LCOV_EXCL_STOP 897 898 if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 899 // LCOV_EXCL_START 900 return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 901 "Cannot add additional sub_operators"); 902 // LCOV_EXCL_STOP 903 if (composite_op->is_immutable) 904 // LCOV_EXCL_START 905 return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 906 "Operator cannot be changed after set as immutable"); 907 // LCOV_EXCL_STOP 908 909 composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 910 ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 911 composite_op->num_suboperators++; 912 return CEED_ERROR_SUCCESS; 913 } 914 915 /** 916 @brief Check if a CeedOperator is ready to be used. 917 918 @param[in] op CeedOperator to check 919 920 @return An error code: 0 - success, otherwise - failure 921 922 @ref User 923 **/ 924 int CeedOperatorCheckReady(CeedOperator op) { 925 int ierr; 926 Ceed ceed; 927 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 928 929 if (op->is_interface_setup) 930 return CEED_ERROR_SUCCESS; 931 932 CeedQFunction qf = op->qf; 933 if (op->is_composite) { 934 if (!op->num_suboperators) 935 // LCOV_EXCL_START 936 return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 937 // LCOV_EXCL_STOP 938 for (CeedInt i = 0; i < op->num_suboperators; i++) { 939 ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr); 940 } 941 } else { 942 if (op->num_fields == 0) 943 // LCOV_EXCL_START 944 return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 945 // LCOV_EXCL_STOP 946 if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 947 // LCOV_EXCL_START 948 return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 949 // LCOV_EXCL_STOP 950 if (!op->has_restriction) 951 // LCOV_EXCL_START 952 return CeedError(ceed, CEED_ERROR_INCOMPLETE, 953 "At least one restriction required"); 954 // LCOV_EXCL_STOP 955 if (op->num_qpts == 0) 956 // LCOV_EXCL_START 957 return CeedError(ceed, CEED_ERROR_INCOMPLETE, 958 "At least one non-collocated basis is required " 959 "or the number of quadrature points must be set"); 960 // LCOV_EXCL_STOP 961 } 962 963 // Flag as immutable and ready 964 op->is_interface_setup = true; 965 if (op->qf && op->qf != CEED_QFUNCTION_NONE) 966 // LCOV_EXCL_START 967 op->qf->is_immutable = true; 968 // LCOV_EXCL_STOP 969 if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 970 // LCOV_EXCL_START 971 op->dqf->is_immutable = true; 972 // LCOV_EXCL_STOP 973 if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 974 // LCOV_EXCL_START 975 op->dqfT->is_immutable = true; 976 // LCOV_EXCL_STOP 977 return CEED_ERROR_SUCCESS; 978 } 979 980 /** 981 @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions. 982 When `reuse_assembly_data = false` (default), the CeedQFunction associated 983 with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*` 984 function is called. 985 When `reuse_assembly_data = true`, the CeedQFunction associated with 986 this CeedOperator is reused between calls to 987 `CeedOperatorSetQFunctionAssemblyDataUpdated`. 988 989 @param[in] op CeedOperator 990 @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 991 992 @return An error code: 0 - success, otherwise - failure 993 994 @ref Advanced 995 **/ 996 int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, 997 bool reuse_assembly_data) { 998 int ierr; 999 bool is_composite; 1000 1001 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1002 if (is_composite) { 1003 for (CeedInt i = 0; i < op->num_suboperators; i++) { 1004 ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], 1005 reuse_assembly_data); CeedChk(ierr); 1006 } 1007 } else { 1008 ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data); 1009 CeedChk(ierr); 1010 } 1011 1012 return CEED_ERROR_SUCCESS; 1013 } 1014 1015 /** 1016 @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly. 1017 1018 @param[in] op CeedOperator 1019 @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 1020 1021 @return An error code: 0 - success, otherwise - failure 1022 1023 @ref Advanced 1024 **/ 1025 int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, 1026 bool needs_data_update) { 1027 int ierr; 1028 bool is_composite; 1029 1030 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1031 if (is_composite) { 1032 for (CeedInt i = 0; i < op->num_suboperators; i++) { 1033 ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i], 1034 needs_data_update); CeedChk(ierr); 1035 } 1036 } else { 1037 ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled, 1038 needs_data_update); 1039 CeedChk(ierr); 1040 } 1041 1042 return CEED_ERROR_SUCCESS; 1043 } 1044 1045 /** 1046 @brief Set the number of quadrature points associated with a CeedOperator. 1047 This should be used when creating a CeedOperator where every 1048 field has a collocated basis. This function cannot be used for 1049 composite CeedOperators. 1050 1051 @param op CeedOperator 1052 @param num_qpts Number of quadrature points to set 1053 1054 @return An error code: 0 - success, otherwise - failure 1055 1056 @ref Advanced 1057 **/ 1058 int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 1059 if (op->is_composite) 1060 // LCOV_EXCL_START 1061 return CeedError(op->ceed, CEED_ERROR_MINOR, 1062 "Not defined for composite operator"); 1063 // LCOV_EXCL_STOP 1064 if (op->num_qpts) 1065 // LCOV_EXCL_START 1066 return CeedError(op->ceed, CEED_ERROR_MINOR, 1067 "Number of quadrature points already defined"); 1068 // LCOV_EXCL_STOP 1069 if (op->is_immutable) 1070 // LCOV_EXCL_START 1071 return CeedError(op->ceed, CEED_ERROR_MAJOR, 1072 "Operator cannot be changed after set as immutable"); 1073 // LCOV_EXCL_STOP 1074 1075 op->num_qpts = num_qpts; 1076 return CEED_ERROR_SUCCESS; 1077 } 1078 1079 /** 1080 @brief View a CeedOperator 1081 1082 @param[in] op CeedOperator to view 1083 @param[in] stream Stream to write; typically stdout/stderr or a file 1084 1085 @return Error code: 0 - success, otherwise - failure 1086 1087 @ref User 1088 **/ 1089 int CeedOperatorView(CeedOperator op, FILE *stream) { 1090 int ierr; 1091 1092 if (op->is_composite) { 1093 fprintf(stream, "Composite CeedOperator\n"); 1094 1095 for (CeedInt i=0; i<op->num_suboperators; i++) { 1096 fprintf(stream, " SubOperator [%d]:\n", i); 1097 ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 1098 CeedChk(ierr); 1099 } 1100 } else { 1101 fprintf(stream, "CeedOperator\n"); 1102 ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 1103 } 1104 return CEED_ERROR_SUCCESS; 1105 } 1106 1107 /** 1108 @brief Get the Ceed associated with a CeedOperator 1109 1110 @param op CeedOperator 1111 @param[out] ceed Variable to store Ceed 1112 1113 @return An error code: 0 - success, otherwise - failure 1114 1115 @ref Advanced 1116 **/ 1117 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1118 *ceed = op->ceed; 1119 return CEED_ERROR_SUCCESS; 1120 } 1121 1122 /** 1123 @brief Get the number of elements associated with a CeedOperator 1124 1125 @param op CeedOperator 1126 @param[out] num_elem Variable to store number of elements 1127 1128 @return An error code: 0 - success, otherwise - failure 1129 1130 @ref Advanced 1131 **/ 1132 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 1133 if (op->is_composite) 1134 // LCOV_EXCL_START 1135 return CeedError(op->ceed, CEED_ERROR_MINOR, 1136 "Not defined for composite operator"); 1137 // LCOV_EXCL_STOP 1138 1139 *num_elem = op->num_elem; 1140 return CEED_ERROR_SUCCESS; 1141 } 1142 1143 /** 1144 @brief Get the number of quadrature points associated with a CeedOperator 1145 1146 @param op CeedOperator 1147 @param[out] num_qpts Variable to store vector number of quadrature points 1148 1149 @return An error code: 0 - success, otherwise - failure 1150 1151 @ref Advanced 1152 **/ 1153 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 1154 if (op->is_composite) 1155 // LCOV_EXCL_START 1156 return CeedError(op->ceed, CEED_ERROR_MINOR, 1157 "Not defined for composite operator"); 1158 // LCOV_EXCL_STOP 1159 1160 *num_qpts = op->num_qpts; 1161 return CEED_ERROR_SUCCESS; 1162 } 1163 1164 /** 1165 @brief Get label for a registered QFunctionContext field, or `NULL` if no 1166 field has been registered with this `field_name`. 1167 1168 @param[in] op CeedOperator 1169 @param[in] field_name Name of field to retrieve label 1170 @param[out] field_label Variable to field label 1171 1172 @return An error code: 0 - success, otherwise - failure 1173 1174 @ref User 1175 **/ 1176 int CeedOperatorContextGetFieldLabel(CeedOperator op, 1177 const char *field_name, 1178 CeedContextFieldLabel *field_label) { 1179 int ierr; 1180 1181 bool is_composite; 1182 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1183 if (is_composite) { 1184 // Check if composite label already created 1185 for (CeedInt i=0; i<op->num_context_labels; i++) { 1186 if (!strcmp(op->context_labels[i]->name, field_name)) { 1187 *field_label = op->context_labels[i]; 1188 return CEED_ERROR_SUCCESS; 1189 } 1190 } 1191 1192 // Create composite label if needed 1193 CeedInt num_sub; 1194 CeedOperator *sub_operators; 1195 CeedContextFieldLabel new_field_label; 1196 1197 ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr); 1198 ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 1199 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1200 ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr); 1201 new_field_label->num_sub_labels = num_sub; 1202 1203 bool label_found = false; 1204 for (CeedInt i=0; i<num_sub; i++) { 1205 if (sub_operators[i]->qf->ctx) { 1206 CeedContextFieldLabel new_field_label_i; 1207 ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, 1208 &new_field_label_i); CeedChk(ierr); 1209 if (new_field_label_i) { 1210 label_found = true; 1211 new_field_label->sub_labels[i] = new_field_label_i; 1212 new_field_label->name = new_field_label_i->name; 1213 new_field_label->description = new_field_label_i->description; 1214 if (new_field_label->type && 1215 new_field_label->type != new_field_label_i->type) { 1216 // LCOV_EXCL_START 1217 ierr = CeedFree(&new_field_label); CeedChk(ierr); 1218 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1219 "Incompatible field types on sub-operator contexts. " 1220 "%s != %s", 1221 CeedContextFieldTypes[new_field_label->type], 1222 CeedContextFieldTypes[new_field_label_i->type]); 1223 // LCOV_EXCL_STOP 1224 } else { 1225 new_field_label->type = new_field_label_i->type; 1226 } 1227 if (new_field_label->num_values != 0 && 1228 new_field_label->num_values != new_field_label_i->num_values) { 1229 // LCOV_EXCL_START 1230 ierr = CeedFree(&new_field_label); CeedChk(ierr); 1231 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1232 "Incompatible field number of values on sub-operator" 1233 " contexts. %ld != %ld", 1234 new_field_label->num_values, new_field_label_i->num_values); 1235 // LCOV_EXCL_STOP 1236 } else { 1237 new_field_label->num_values = new_field_label_i->num_values; 1238 } 1239 } 1240 } 1241 } 1242 if (!label_found) { 1243 // LCOV_EXCL_START 1244 ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr); 1245 ierr = CeedFree(&new_field_label); CeedChk(ierr); 1246 *field_label = NULL; 1247 // LCOV_EXCL_STOP 1248 } else { 1249 // Move new composite label to operator 1250 if (op->num_context_labels == 0) { 1251 ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr); 1252 op->max_context_labels = 1; 1253 } else if (op->num_context_labels == op->max_context_labels) { 1254 ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels); 1255 CeedChk(ierr); 1256 op->max_context_labels *= 2; 1257 } 1258 op->context_labels[op->num_context_labels] = new_field_label; 1259 *field_label = new_field_label; 1260 op->num_context_labels++; 1261 } 1262 1263 return CEED_ERROR_SUCCESS; 1264 } else { 1265 return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label); 1266 } 1267 } 1268 1269 /** 1270 @brief Set QFunctionContext field holding a double precision value. 1271 For composite operators, the value is set in all 1272 sub-operator QFunctionContexts that have a matching `field_name`. 1273 1274 @param op CeedOperator 1275 @param field_label Label of field to register 1276 @param values Values to set 1277 1278 @return An error code: 0 - success, otherwise - failure 1279 1280 @ref User 1281 **/ 1282 int CeedOperatorContextSetDouble(CeedOperator op, 1283 CeedContextFieldLabel field_label, 1284 double *values) { 1285 return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, 1286 values); 1287 } 1288 1289 /** 1290 @brief Set QFunctionContext field holding an int32 value. 1291 For composite operators, the value is set in all 1292 sub-operator QFunctionContexts that have a matching `field_name`. 1293 1294 @param op CeedOperator 1295 @param field_label Label of field to set 1296 @param values Values to set 1297 1298 @return An error code: 0 - success, otherwise - failure 1299 1300 @ref User 1301 **/ 1302 int CeedOperatorContextSetInt32(CeedOperator op, 1303 CeedContextFieldLabel field_label, 1304 int *values) { 1305 return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, 1306 values); 1307 } 1308 1309 /** 1310 @brief Apply CeedOperator to a vector 1311 1312 This computes the action of the operator on the specified (active) input, 1313 yielding its (active) output. All inputs and outputs must be specified using 1314 CeedOperatorSetField(). 1315 1316 Note: Calling this function asserts that setup is complete 1317 and sets the CeedOperator as immutable. 1318 1319 @param op CeedOperator to apply 1320 @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 1321 there are no active inputs 1322 @param[out] out CeedVector to store result of applying operator (must be 1323 distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 1324 active outputs 1325 @param request Address of CeedRequest for non-blocking completion, else 1326 @ref CEED_REQUEST_IMMEDIATE 1327 1328 @return An error code: 0 - success, otherwise - failure 1329 1330 @ref User 1331 **/ 1332 int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1333 CeedRequest *request) { 1334 int ierr; 1335 ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1336 1337 if (op->num_elem) { 1338 // Standard Operator 1339 if (op->Apply) { 1340 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1341 } else { 1342 // Zero all output vectors 1343 CeedQFunction qf = op->qf; 1344 for (CeedInt i=0; i<qf->num_output_fields; i++) { 1345 CeedVector vec = op->output_fields[i]->vec; 1346 if (vec == CEED_VECTOR_ACTIVE) 1347 vec = out; 1348 if (vec != CEED_VECTOR_NONE) { 1349 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1350 } 1351 } 1352 // Apply 1353 ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1354 } 1355 } else if (op->is_composite) { 1356 // Composite Operator 1357 if (op->ApplyComposite) { 1358 ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1359 } else { 1360 CeedInt num_suboperators; 1361 ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1362 CeedOperator *sub_operators; 1363 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1364 1365 // Zero all output vectors 1366 if (out != CEED_VECTOR_NONE) { 1367 ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1368 } 1369 for (CeedInt i=0; i<num_suboperators; i++) { 1370 for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 1371 CeedVector vec = sub_operators[i]->output_fields[j]->vec; 1372 if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1373 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1374 } 1375 } 1376 } 1377 // Apply 1378 for (CeedInt i=0; i<op->num_suboperators; i++) { 1379 ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 1380 CeedChk(ierr); 1381 } 1382 } 1383 } 1384 return CEED_ERROR_SUCCESS; 1385 } 1386 1387 /** 1388 @brief Apply CeedOperator to a vector and add result to output vector 1389 1390 This computes the action of the operator on the specified (active) input, 1391 yielding its (active) output. All inputs and outputs must be specified using 1392 CeedOperatorSetField(). 1393 1394 @param op CeedOperator to apply 1395 @param[in] in CeedVector containing input state or NULL if there are no 1396 active inputs 1397 @param[out] out CeedVector to sum in result of applying operator (must be 1398 distinct from @a in) or NULL if there are no active outputs 1399 @param request Address of CeedRequest for non-blocking completion, else 1400 @ref CEED_REQUEST_IMMEDIATE 1401 1402 @return An error code: 0 - success, otherwise - failure 1403 1404 @ref User 1405 **/ 1406 int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1407 CeedRequest *request) { 1408 int ierr; 1409 ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1410 1411 if (op->num_elem) { 1412 // Standard Operator 1413 ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1414 } else if (op->is_composite) { 1415 // Composite Operator 1416 if (op->ApplyAddComposite) { 1417 ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1418 } else { 1419 CeedInt num_suboperators; 1420 ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1421 CeedOperator *sub_operators; 1422 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1423 1424 for (CeedInt i=0; i<num_suboperators; i++) { 1425 ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 1426 CeedChk(ierr); 1427 } 1428 } 1429 } 1430 return CEED_ERROR_SUCCESS; 1431 } 1432 1433 /** 1434 @brief Destroy a CeedOperator 1435 1436 @param op CeedOperator to destroy 1437 1438 @return An error code: 0 - success, otherwise - failure 1439 1440 @ref User 1441 **/ 1442 int CeedOperatorDestroy(CeedOperator *op) { 1443 int ierr; 1444 1445 if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 1446 if ((*op)->Destroy) { 1447 ierr = (*op)->Destroy(*op); CeedChk(ierr); 1448 } 1449 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1450 // Free fields 1451 for (CeedInt i=0; i<(*op)->num_fields; i++) 1452 if ((*op)->input_fields[i]) { 1453 if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 1454 ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 1455 CeedChk(ierr); 1456 } 1457 if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1458 ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 1459 } 1460 if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 1461 (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 1462 ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 1463 } 1464 ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 1465 ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 1466 } 1467 for (CeedInt i=0; i<(*op)->num_fields; i++) 1468 if ((*op)->output_fields[i]) { 1469 ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 1470 CeedChk(ierr); 1471 if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1472 ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 1473 } 1474 if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 1475 (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 1476 ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 1477 } 1478 ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 1479 ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 1480 } 1481 // Destroy sub_operators 1482 for (CeedInt i=0; i<(*op)->num_suboperators; i++) 1483 if ((*op)->sub_operators[i]) { 1484 ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 1485 } 1486 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1487 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1488 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1489 // Destroy any composite labels 1490 for (CeedInt i=0; i<(*op)->num_context_labels; i++) { 1491 ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr); 1492 ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr); 1493 } 1494 ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr); 1495 1496 // Destroy fallback 1497 if ((*op)->op_fallback) { 1498 ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 1499 ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 1500 ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 1501 ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 1502 } 1503 1504 // Destroy QF assembly cache 1505 ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr); 1506 1507 ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 1508 ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 1509 ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 1510 ierr = CeedFree(op); CeedChk(ierr); 1511 return CEED_ERROR_SUCCESS; 1512 } 1513 1514 /// @} 1515