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 reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions. 980 When `reuse_assembly_data = false` (default), the CeedQFunction associated 981 with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*` 982 function is called. 983 When `reuse_assembly_data = true`, the CeedQFunction associated with 984 this CeedOperator is reused between calls to 985 `CeedOperatorSetQFunctionAssemblyDataUpdated`. 986 987 @param[in] op CeedOperator 988 @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 989 990 @return An error code: 0 - success, otherwise - failure 991 992 @ref Advanced 993 **/ 994 int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, 995 bool reuse_assembly_data) { 996 int ierr; 997 bool is_composite; 998 999 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1000 if (is_composite) { 1001 for (CeedInt i = 0; i < op->num_suboperators; i++) { 1002 ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], 1003 reuse_assembly_data); CeedChk(ierr); 1004 } 1005 } else { 1006 ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data); 1007 CeedChk(ierr); 1008 } 1009 1010 return CEED_ERROR_SUCCESS; 1011 } 1012 1013 /** 1014 @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly. 1015 1016 @param[in] op CeedOperator 1017 @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 1018 1019 @return An error code: 0 - success, otherwise - failure 1020 1021 @ref Advanced 1022 **/ 1023 int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, 1024 bool needs_data_update) { 1025 int ierr; 1026 bool is_composite; 1027 1028 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1029 if (is_composite) { 1030 for (CeedInt i = 0; i < op->num_suboperators; i++) { 1031 ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i], 1032 needs_data_update); CeedChk(ierr); 1033 } 1034 } else { 1035 ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled, 1036 needs_data_update); 1037 CeedChk(ierr); 1038 } 1039 1040 return CEED_ERROR_SUCCESS; 1041 } 1042 1043 /** 1044 @brief Set the number of quadrature points associated with a CeedOperator. 1045 This should be used when creating a CeedOperator where every 1046 field has a collocated basis. This function cannot be used for 1047 composite CeedOperators. 1048 1049 @param op CeedOperator 1050 @param num_qpts Number of quadrature points to set 1051 1052 @return An error code: 0 - success, otherwise - failure 1053 1054 @ref Advanced 1055 **/ 1056 int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 1057 if (op->is_composite) 1058 // LCOV_EXCL_START 1059 return CeedError(op->ceed, CEED_ERROR_MINOR, 1060 "Not defined for composite operator"); 1061 // LCOV_EXCL_STOP 1062 if (op->num_qpts) 1063 // LCOV_EXCL_START 1064 return CeedError(op->ceed, CEED_ERROR_MINOR, 1065 "Number of quadrature points already defined"); 1066 // LCOV_EXCL_STOP 1067 if (op->is_immutable) 1068 // LCOV_EXCL_START 1069 return CeedError(op->ceed, CEED_ERROR_MAJOR, 1070 "Operator cannot be changed after set as immutable"); 1071 // LCOV_EXCL_STOP 1072 1073 op->num_qpts = num_qpts; 1074 return CEED_ERROR_SUCCESS; 1075 } 1076 1077 /** 1078 @brief View a CeedOperator 1079 1080 @param[in] op CeedOperator to view 1081 @param[in] stream Stream to write; typically stdout/stderr or a file 1082 1083 @return Error code: 0 - success, otherwise - failure 1084 1085 @ref User 1086 **/ 1087 int CeedOperatorView(CeedOperator op, FILE *stream) { 1088 int ierr; 1089 1090 if (op->is_composite) { 1091 fprintf(stream, "Composite CeedOperator\n"); 1092 1093 for (CeedInt i=0; i<op->num_suboperators; i++) { 1094 fprintf(stream, " SubOperator [%d]:\n", i); 1095 ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 1096 CeedChk(ierr); 1097 } 1098 } else { 1099 fprintf(stream, "CeedOperator\n"); 1100 ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 1101 } 1102 return CEED_ERROR_SUCCESS; 1103 } 1104 1105 /** 1106 @brief Get the Ceed associated with a CeedOperator 1107 1108 @param op CeedOperator 1109 @param[out] ceed Variable to store Ceed 1110 1111 @return An error code: 0 - success, otherwise - failure 1112 1113 @ref Advanced 1114 **/ 1115 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1116 *ceed = op->ceed; 1117 return CEED_ERROR_SUCCESS; 1118 } 1119 1120 /** 1121 @brief Get the number of elements associated with a CeedOperator 1122 1123 @param op CeedOperator 1124 @param[out] num_elem Variable to store number of elements 1125 1126 @return An error code: 0 - success, otherwise - failure 1127 1128 @ref Advanced 1129 **/ 1130 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 1131 if (op->is_composite) 1132 // LCOV_EXCL_START 1133 return CeedError(op->ceed, CEED_ERROR_MINOR, 1134 "Not defined for composite operator"); 1135 // LCOV_EXCL_STOP 1136 1137 *num_elem = op->num_elem; 1138 return CEED_ERROR_SUCCESS; 1139 } 1140 1141 /** 1142 @brief Get the number of quadrature points associated with a CeedOperator 1143 1144 @param op CeedOperator 1145 @param[out] num_qpts Variable to store vector number of quadrature points 1146 1147 @return An error code: 0 - success, otherwise - failure 1148 1149 @ref Advanced 1150 **/ 1151 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 1152 if (op->is_composite) 1153 // LCOV_EXCL_START 1154 return CeedError(op->ceed, CEED_ERROR_MINOR, 1155 "Not defined for composite operator"); 1156 // LCOV_EXCL_STOP 1157 1158 *num_qpts = op->num_qpts; 1159 return CEED_ERROR_SUCCESS; 1160 } 1161 1162 /** 1163 @brief Get label for a registered QFunctionContext field, or `NULL` if no 1164 field has been registered with this `field_name`. 1165 1166 @param[in] op CeedOperator 1167 @param[in] field_name Name of field to retrieve label 1168 @param[out] field_label Variable to field label 1169 1170 @return An error code: 0 - success, otherwise - failure 1171 1172 @ref User 1173 **/ 1174 int CeedOperatorContextGetFieldLabel(CeedOperator op, 1175 const char *field_name, 1176 CeedContextFieldLabel *field_label) { 1177 int ierr; 1178 1179 bool is_composite; 1180 ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1181 if (is_composite) { 1182 // Check if composite label already created 1183 for (CeedInt i=0; i<op->num_context_labels; i++) { 1184 if (!strcmp(op->context_labels[i]->name, field_name)) { 1185 *field_label = op->context_labels[i]; 1186 return CEED_ERROR_SUCCESS; 1187 } 1188 } 1189 1190 // Create composite label if needed 1191 CeedInt num_sub; 1192 CeedOperator *sub_operators; 1193 CeedContextFieldLabel new_field_label; 1194 1195 ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr); 1196 ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 1197 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1198 ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr); 1199 new_field_label->num_sub_labels = num_sub; 1200 1201 bool label_found = false; 1202 for (CeedInt i=0; i<num_sub; i++) { 1203 if (sub_operators[i]->qf->ctx) { 1204 CeedContextFieldLabel new_field_label_i; 1205 ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, 1206 &new_field_label_i); CeedChk(ierr); 1207 if (new_field_label_i) { 1208 label_found = true; 1209 new_field_label->sub_labels[i] = new_field_label_i; 1210 new_field_label->name = new_field_label_i->name; 1211 new_field_label->description = new_field_label_i->description; 1212 if (new_field_label->type && 1213 new_field_label->type != new_field_label_i->type) { 1214 // LCOV_EXCL_START 1215 ierr = CeedFree(&new_field_label); CeedChk(ierr); 1216 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1217 "Incompatible field types on sub-operator contexts. " 1218 "%s != %s", 1219 CeedContextFieldTypes[new_field_label->type], 1220 CeedContextFieldTypes[new_field_label_i->type]); 1221 // LCOV_EXCL_STOP 1222 } else { 1223 new_field_label->type = new_field_label_i->type; 1224 } 1225 if (new_field_label->num_values != 0 && 1226 new_field_label->num_values != new_field_label_i->num_values) { 1227 // LCOV_EXCL_START 1228 ierr = CeedFree(&new_field_label); CeedChk(ierr); 1229 return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1230 "Incompatible field number of values on sub-operator" 1231 " contexts. %ld != %ld", 1232 new_field_label->num_values, new_field_label_i->num_values); 1233 // LCOV_EXCL_STOP 1234 } else { 1235 new_field_label->num_values = new_field_label_i->num_values; 1236 } 1237 } 1238 } 1239 } 1240 if (!label_found) { 1241 // LCOV_EXCL_START 1242 ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr); 1243 ierr = CeedFree(&new_field_label); CeedChk(ierr); 1244 *field_label = NULL; 1245 // LCOV_EXCL_STOP 1246 } else { 1247 // Move new composite label to operator 1248 if (op->num_context_labels == 0) { 1249 ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr); 1250 op->max_context_labels = 1; 1251 } else if (op->num_context_labels == op->max_context_labels) { 1252 ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels); 1253 CeedChk(ierr); 1254 op->max_context_labels *= 2; 1255 } 1256 op->context_labels[op->num_context_labels] = new_field_label; 1257 *field_label = new_field_label; 1258 op->num_context_labels++; 1259 } 1260 1261 return CEED_ERROR_SUCCESS; 1262 } else { 1263 return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label); 1264 } 1265 } 1266 1267 /** 1268 @brief Set QFunctionContext field holding a double precision value. 1269 For composite operators, the value is set in all 1270 sub-operator QFunctionContexts that have a matching `field_name`. 1271 1272 @param op CeedOperator 1273 @param field_label Label of field to register 1274 @param values Values to set 1275 1276 @return An error code: 0 - success, otherwise - failure 1277 1278 @ref User 1279 **/ 1280 int CeedOperatorContextSetDouble(CeedOperator op, 1281 CeedContextFieldLabel field_label, 1282 double *values) { 1283 return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, 1284 values); 1285 } 1286 1287 /** 1288 @brief Set QFunctionContext field holding an int32 value. 1289 For composite operators, the value is set in all 1290 sub-operator QFunctionContexts that have a matching `field_name`. 1291 1292 @param op CeedOperator 1293 @param field_label Label of field to set 1294 @param values Values to set 1295 1296 @return An error code: 0 - success, otherwise - failure 1297 1298 @ref User 1299 **/ 1300 int CeedOperatorContextSetInt32(CeedOperator op, 1301 CeedContextFieldLabel field_label, 1302 int *values) { 1303 return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, 1304 values); 1305 } 1306 1307 /** 1308 @brief Apply CeedOperator to a vector 1309 1310 This computes the action of the operator on the specified (active) input, 1311 yielding its (active) output. All inputs and outputs must be specified using 1312 CeedOperatorSetField(). 1313 1314 Note: Calling this function asserts that setup is complete 1315 and sets the CeedOperator as immutable. 1316 1317 @param op CeedOperator to apply 1318 @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 1319 there are no active inputs 1320 @param[out] out CeedVector to store result of applying operator (must be 1321 distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 1322 active outputs 1323 @param request Address of CeedRequest for non-blocking completion, else 1324 @ref CEED_REQUEST_IMMEDIATE 1325 1326 @return An error code: 0 - success, otherwise - failure 1327 1328 @ref User 1329 **/ 1330 int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1331 CeedRequest *request) { 1332 int ierr; 1333 ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1334 1335 if (op->num_elem) { 1336 // Standard Operator 1337 if (op->Apply) { 1338 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1339 } else { 1340 // Zero all output vectors 1341 CeedQFunction qf = op->qf; 1342 for (CeedInt i=0; i<qf->num_output_fields; i++) { 1343 CeedVector vec = op->output_fields[i]->vec; 1344 if (vec == CEED_VECTOR_ACTIVE) 1345 vec = out; 1346 if (vec != CEED_VECTOR_NONE) { 1347 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1348 } 1349 } 1350 // Apply 1351 ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1352 } 1353 } else if (op->is_composite) { 1354 // Composite Operator 1355 if (op->ApplyComposite) { 1356 ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1357 } else { 1358 CeedInt num_suboperators; 1359 ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1360 CeedOperator *sub_operators; 1361 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1362 1363 // Zero all output vectors 1364 if (out != CEED_VECTOR_NONE) { 1365 ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1366 } 1367 for (CeedInt i=0; i<num_suboperators; i++) { 1368 for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 1369 CeedVector vec = sub_operators[i]->output_fields[j]->vec; 1370 if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1371 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1372 } 1373 } 1374 } 1375 // Apply 1376 for (CeedInt i=0; i<op->num_suboperators; i++) { 1377 ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 1378 CeedChk(ierr); 1379 } 1380 } 1381 } 1382 return CEED_ERROR_SUCCESS; 1383 } 1384 1385 /** 1386 @brief Apply CeedOperator to a vector and add result to output vector 1387 1388 This computes the action of the operator on the specified (active) input, 1389 yielding its (active) output. All inputs and outputs must be specified using 1390 CeedOperatorSetField(). 1391 1392 @param op CeedOperator to apply 1393 @param[in] in CeedVector containing input state or NULL if there are no 1394 active inputs 1395 @param[out] out CeedVector to sum in result of applying operator (must be 1396 distinct from @a in) or NULL if there are no active outputs 1397 @param request Address of CeedRequest for non-blocking completion, else 1398 @ref CEED_REQUEST_IMMEDIATE 1399 1400 @return An error code: 0 - success, otherwise - failure 1401 1402 @ref User 1403 **/ 1404 int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1405 CeedRequest *request) { 1406 int ierr; 1407 ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1408 1409 if (op->num_elem) { 1410 // Standard Operator 1411 ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1412 } else if (op->is_composite) { 1413 // Composite Operator 1414 if (op->ApplyAddComposite) { 1415 ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1416 } else { 1417 CeedInt num_suboperators; 1418 ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1419 CeedOperator *sub_operators; 1420 ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1421 1422 for (CeedInt i=0; i<num_suboperators; i++) { 1423 ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 1424 CeedChk(ierr); 1425 } 1426 } 1427 } 1428 return CEED_ERROR_SUCCESS; 1429 } 1430 1431 /** 1432 @brief Destroy a CeedOperator 1433 1434 @param op CeedOperator to destroy 1435 1436 @return An error code: 0 - success, otherwise - failure 1437 1438 @ref User 1439 **/ 1440 int CeedOperatorDestroy(CeedOperator *op) { 1441 int ierr; 1442 1443 if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 1444 if ((*op)->Destroy) { 1445 ierr = (*op)->Destroy(*op); CeedChk(ierr); 1446 } 1447 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1448 // Free fields 1449 for (CeedInt i=0; i<(*op)->num_fields; i++) 1450 if ((*op)->input_fields[i]) { 1451 if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 1452 ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 1453 CeedChk(ierr); 1454 } 1455 if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1456 ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 1457 } 1458 if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 1459 (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 1460 ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 1461 } 1462 ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 1463 ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 1464 } 1465 for (CeedInt i=0; i<(*op)->num_fields; i++) 1466 if ((*op)->output_fields[i]) { 1467 ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 1468 CeedChk(ierr); 1469 if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1470 ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 1471 } 1472 if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 1473 (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 1474 ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 1475 } 1476 ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 1477 ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 1478 } 1479 // Destroy sub_operators 1480 for (CeedInt i=0; i<(*op)->num_suboperators; i++) 1481 if ((*op)->sub_operators[i]) { 1482 ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 1483 } 1484 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1485 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1486 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1487 // Destroy any composite labels 1488 for (CeedInt i=0; i<(*op)->num_context_labels; i++) { 1489 ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr); 1490 ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr); 1491 } 1492 ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr); 1493 1494 // Destroy fallback 1495 if ((*op)->op_fallback) { 1496 ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 1497 ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 1498 ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 1499 ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 1500 } 1501 1502 // Destroy QF assembly cache 1503 ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr); 1504 1505 ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 1506 ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 1507 ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 1508 ierr = CeedFree(op); CeedChk(ierr); 1509 return CEED_ERROR_SUCCESS; 1510 } 1511 1512 /// @} 1513