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