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