1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 17ec3da8bcSJed Brown #include <ceed/ceed.h> 18ec3da8bcSJed Brown #include <ceed/backend.h> 193d576824SJeremy L Thompson #include <ceed-impl.h> 203d576824SJeremy L Thompson #include <stdbool.h> 213d576824SJeremy L Thompson #include <stdio.h> 223d576824SJeremy L Thompson #include <string.h> 23d7b241e6Sjeremylt 24dfdf5a53Sjeremylt /// @file 257a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 267a982d89SJeremy L. Thompson 277a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 287a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 297a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 307a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 317a982d89SJeremy L. Thompson /// @{ 327a982d89SJeremy L. Thompson 337a982d89SJeremy L. Thompson /** 34e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 35e15f9bd0SJeremy L Thompson 36e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 37d1d35e2fSjeremylt @param[in] qf_field QFunction Field matching Operator Field 38e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 39e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 40e15f9bd0SJeremy L Thompson 41e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 42e15f9bd0SJeremy L Thompson 43e15f9bd0SJeremy L Thompson @ref Developer 44e15f9bd0SJeremy L Thompson **/ 45d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, 46e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 47e15f9bd0SJeremy L Thompson int ierr; 48d1d35e2fSjeremylt CeedEvalMode eval_mode = qf_field->eval_mode; 49d1d35e2fSjeremylt CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size; 50e15f9bd0SJeremy L Thompson // Restriction 51e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 52d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { 53e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 54e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 55e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE should be used " 56e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 57e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 58e15f9bd0SJeremy L Thompson } 59d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp); 6078464608Sjeremylt CeedChk(ierr); 61e1e9e29dSJed Brown } 62d1d35e2fSjeremylt if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) { 63e1e9e29dSJed Brown // LCOV_EXCL_START 64e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 65e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 66e1e9e29dSJed Brown "must be used together."); 67e1e9e29dSJed Brown // LCOV_EXCL_STOP 68e1e9e29dSJed Brown } 69e15f9bd0SJeremy L Thompson // Basis 70e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 71d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) 728229195eSjeremylt // LCOV_EXCL_START 73e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 74d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 75d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 768229195eSjeremylt // LCOV_EXCL_STOP 77d1d35e2fSjeremylt qf_field->field_name); 78e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 79d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 80d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 81e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 82e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 83d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 84d1d35e2fSjeremylt "has %d components, but Basis has %d components", 85d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 86d1d35e2fSjeremylt restr_num_comp, 87d1d35e2fSjeremylt num_comp); 88e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 89e15f9bd0SJeremy L Thompson } 90e15f9bd0SJeremy L Thompson } 91e15f9bd0SJeremy L Thompson // Field size 92d1d35e2fSjeremylt switch(eval_mode) { 93e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 94d1d35e2fSjeremylt if (size != restr_num_comp) 95e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 96e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 97e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 98d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 99d1d35e2fSjeremylt restr_num_comp); 100e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 101e15f9bd0SJeremy L Thompson break; 102e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 103d1d35e2fSjeremylt if (size != num_comp) 104e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 105e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 106e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 107d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 108d1d35e2fSjeremylt num_comp); 109e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 110e15f9bd0SJeremy L Thompson break; 111e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 112d1d35e2fSjeremylt if (size != num_comp * dim) 113e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 114e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 115d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 116d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 117d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 118d1d35e2fSjeremylt num_comp); 119e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 120e15f9bd0SJeremy L Thompson break; 121e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 122d1d35e2fSjeremylt // No additional checks required 123e15f9bd0SJeremy L Thompson break; 124e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 125e15f9bd0SJeremy L Thompson // Not implemented 126e15f9bd0SJeremy L Thompson break; 127e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 128e15f9bd0SJeremy L Thompson // Not implemented 129e15f9bd0SJeremy L Thompson break; 130e15f9bd0SJeremy L Thompson } 131e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1327a982d89SJeremy L. Thompson } 1337a982d89SJeremy L. Thompson 1347a982d89SJeremy L. Thompson /** 1357a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 1367a982d89SJeremy L. Thompson 1377a982d89SJeremy L. Thompson @param[in] field Operator field to view 138d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 139d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 1404c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 141d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 1427a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 1437a982d89SJeremy L. Thompson 1447a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1457a982d89SJeremy L. Thompson 1467a982d89SJeremy L. Thompson @ref Utility 1477a982d89SJeremy L. Thompson **/ 1487a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 149d1d35e2fSjeremylt CeedQFunctionField qf_field, 150d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 1517a982d89SJeremy L. Thompson FILE *stream) { 1527a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 153d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 1547a982d89SJeremy L. Thompson 1557a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 1567a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 157d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 1587a982d89SJeremy L. Thompson 1597a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 1607a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 1617a982d89SJeremy L. Thompson 1627a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 1637a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 1647a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 1657a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 166e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1677a982d89SJeremy L. Thompson } 1687a982d89SJeremy L. Thompson 1697a982d89SJeremy L. Thompson /** 1707a982d89SJeremy L. Thompson @brief View a single CeedOperator 1717a982d89SJeremy L. Thompson 1727a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 1737a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 1747a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 1757a982d89SJeremy L. Thompson 1767a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 1777a982d89SJeremy L. Thompson 1787a982d89SJeremy L. Thompson @ref Utility 1797a982d89SJeremy L. Thompson **/ 1807a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 1817a982d89SJeremy L. Thompson int ierr; 1827a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 1837a982d89SJeremy L. Thompson 18478464608Sjeremylt CeedInt total_fields = 0; 18578464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 1867a982d89SJeremy L. Thompson 18778464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 18878464608Sjeremylt total_fields>1 ? "s" : ""); 1897a982d89SJeremy L. Thompson 190d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 191d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 192d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 193d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 1947a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 1957a982d89SJeremy L. Thompson } 1967a982d89SJeremy L. Thompson 197d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 198d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 199d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 200d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 2017a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 2027a982d89SJeremy L. Thompson } 203e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2047a982d89SJeremy L. Thompson } 2057a982d89SJeremy L. Thompson 206d99fa3c5SJeremy L Thompson /** 207eaf62fffSJeremy L Thompson @brief Find the active vector basis for a CeedOperator 208eaf62fffSJeremy L Thompson 209eaf62fffSJeremy L Thompson @param[in] op CeedOperator to find active basis for 210eaf62fffSJeremy L Thompson @param[out] active_basis Basis for active input vector 211eaf62fffSJeremy L Thompson 212eaf62fffSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 213eaf62fffSJeremy L Thompson 214eaf62fffSJeremy L Thompson @ ref Developer 215eaf62fffSJeremy L Thompson **/ 216eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) { 217eaf62fffSJeremy L Thompson *active_basis = NULL; 218eaf62fffSJeremy L Thompson for (int i = 0; i < op->qf->num_input_fields; i++) 219eaf62fffSJeremy L Thompson if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 220eaf62fffSJeremy L Thompson *active_basis = op->input_fields[i]->basis; 221eaf62fffSJeremy L Thompson break; 222eaf62fffSJeremy L Thompson } 223eaf62fffSJeremy L Thompson 224eaf62fffSJeremy L Thompson if (!*active_basis) { 225eaf62fffSJeremy L Thompson // LCOV_EXCL_START 226eaf62fffSJeremy L Thompson int ierr; 227eaf62fffSJeremy L Thompson Ceed ceed; 228eaf62fffSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 229eaf62fffSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 230eaf62fffSJeremy L Thompson "No active CeedBasis found"); 231eaf62fffSJeremy L Thompson // LCOV_EXCL_STOP 232eaf62fffSJeremy L Thompson } 233eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 234eaf62fffSJeremy L Thompson } 235eaf62fffSJeremy L Thompson 236eaf62fffSJeremy L Thompson /** 237e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 238e2f04181SAndrew T. Barker 239e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 240d1d35e2fSjeremylt @param[out] active_rstr ElemRestriction for active input vector 241e2f04181SAndrew T. Barker 242e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 243e2f04181SAndrew T. Barker 244e2f04181SAndrew T. Barker @ref Utility 245e2f04181SAndrew T. Barker **/ 246eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op, 247d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 248d1d35e2fSjeremylt *active_rstr = NULL; 249d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 250d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 251d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 252e2f04181SAndrew T. Barker break; 253e2f04181SAndrew T. Barker } 254e2f04181SAndrew T. Barker 255d1d35e2fSjeremylt if (!*active_rstr) { 256e2f04181SAndrew T. Barker // LCOV_EXCL_START 257e2f04181SAndrew T. Barker int ierr; 258e2f04181SAndrew T. Barker Ceed ceed; 259e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 260e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 261eaf62fffSJeremy L Thompson "No active CeedElemRestriction found"); 262e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 263e2f04181SAndrew T. Barker } 264e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 265e2f04181SAndrew T. Barker } 266e2f04181SAndrew T. Barker 267d8dd9a91SJeremy L Thompson /** 268d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field value of the specified type. 269d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 270d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 271d8dd9a91SJeremy L Thompson A non-zero error code is returned for single operators 272d8dd9a91SJeremy L Thompson that do not have a matching field of the same type or composite 273d8dd9a91SJeremy L Thompson operators that do not have any field of a matching type. 274d8dd9a91SJeremy L Thompson 275d8dd9a91SJeremy L Thompson @param op CeedOperator 2763668ca4bSJeremy L Thompson @param field_label Label of field to set 277d8dd9a91SJeremy L Thompson @param field_type Type of field to set 278d8dd9a91SJeremy L Thompson @param value Value to set 279d8dd9a91SJeremy L Thompson 280d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 281d8dd9a91SJeremy L Thompson 282d8dd9a91SJeremy L Thompson @ref User 283d8dd9a91SJeremy L Thompson **/ 284d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op, 2853668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, CeedContextFieldType field_type, 2863668ca4bSJeremy L Thompson void *value) { 287d8dd9a91SJeremy L Thompson int ierr; 288d8dd9a91SJeremy L Thompson 2893668ca4bSJeremy L Thompson if (!field_label) 2903668ca4bSJeremy L Thompson // LCOV_EXCL_START 2913668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 2923668ca4bSJeremy L Thompson "Invalid field label"); 2933668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 2943668ca4bSJeremy L Thompson 2953668ca4bSJeremy L Thompson bool is_composite = false; 296d8dd9a91SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 297d8dd9a91SJeremy L Thompson if (is_composite) { 298d8dd9a91SJeremy L Thompson CeedInt num_sub; 299d8dd9a91SJeremy L Thompson CeedOperator *sub_operators; 300d8dd9a91SJeremy L Thompson 301d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 302d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 3033668ca4bSJeremy L Thompson if (num_sub != field_label->num_sub_labels) 3043668ca4bSJeremy L Thompson // LCOV_EXCL_START 3053668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 3063668ca4bSJeremy L Thompson "ContextLabel does not correspond to composite operator.\n" 3073668ca4bSJeremy L Thompson "Use CeedOperatorGetContextFieldLabel()."); 3083668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 309d8dd9a91SJeremy L Thompson 310d8dd9a91SJeremy L Thompson for (CeedInt i = 0; i < num_sub; i++) { 311d8dd9a91SJeremy L Thompson // Try every sub-operator, ok if some sub-operators do not have field 3123668ca4bSJeremy L Thompson if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) { 3133668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx, 3143668ca4bSJeremy L Thompson field_label->sub_labels[i], 3153668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 316d8dd9a91SJeremy L Thompson } 317d8dd9a91SJeremy L Thompson } 318d8dd9a91SJeremy L Thompson } else { 319d8dd9a91SJeremy L Thompson if (!op->qf->ctx) 320d8dd9a91SJeremy L Thompson // LCOV_EXCL_START 321d8dd9a91SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 322d8dd9a91SJeremy L Thompson "QFunction does not have context data"); 323d8dd9a91SJeremy L Thompson // LCOV_EXCL_STOP 324d8dd9a91SJeremy L Thompson 3253668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label, 3263668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 327d8dd9a91SJeremy L Thompson } 328d8dd9a91SJeremy L Thompson 329d8dd9a91SJeremy L Thompson return CEED_ERROR_SUCCESS; 330d8dd9a91SJeremy L Thompson } 331d8dd9a91SJeremy L Thompson 3327a982d89SJeremy L. Thompson /// @} 3337a982d89SJeremy L. Thompson 3347a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3357a982d89SJeremy L. Thompson /// CeedOperator Backend API 3367a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3377a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 3387a982d89SJeremy L. Thompson /// @{ 3397a982d89SJeremy L. Thompson 3407a982d89SJeremy L. Thompson /** 3417a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 3427a982d89SJeremy L. Thompson 3437a982d89SJeremy L. Thompson @param op CeedOperator 344d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 3457a982d89SJeremy L. Thompson 3467a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3477a982d89SJeremy L. Thompson 3487a982d89SJeremy L. Thompson @ref Backend 3497a982d89SJeremy L. Thompson **/ 3507a982d89SJeremy L. Thompson 351d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 352f04ea552SJeremy L Thompson if (op->is_composite) 3537a982d89SJeremy L. Thompson // LCOV_EXCL_START 354e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 355e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 3567a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3577a982d89SJeremy L. Thompson 358d1d35e2fSjeremylt *num_args = op->num_fields; 359e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3607a982d89SJeremy L. Thompson } 3617a982d89SJeremy L. Thompson 3627a982d89SJeremy L. Thompson /** 3637a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 3647a982d89SJeremy L. Thompson 3657a982d89SJeremy L. Thompson @param op CeedOperator 366d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 3677a982d89SJeremy L. Thompson 3687a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3697a982d89SJeremy L. Thompson 3707a982d89SJeremy L. Thompson @ref Backend 3717a982d89SJeremy L. Thompson **/ 3727a982d89SJeremy L. Thompson 373d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 374f04ea552SJeremy L Thompson *is_setup_done = op->is_backend_setup; 375e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3767a982d89SJeremy L. Thompson } 3777a982d89SJeremy L. Thompson 3787a982d89SJeremy L. Thompson /** 3797a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 3807a982d89SJeremy L. Thompson 3817a982d89SJeremy L. Thompson @param op CeedOperator 3827a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 3837a982d89SJeremy L. Thompson 3847a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3857a982d89SJeremy L. Thompson 3867a982d89SJeremy L. Thompson @ref Backend 3877a982d89SJeremy L. Thompson **/ 3887a982d89SJeremy L. Thompson 3897a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 390f04ea552SJeremy L Thompson if (op->is_composite) 3917a982d89SJeremy L. Thompson // LCOV_EXCL_START 392e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 393e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 3947a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3957a982d89SJeremy L. Thompson 3967a982d89SJeremy L. Thompson *qf = op->qf; 397e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3987a982d89SJeremy L. Thompson } 3997a982d89SJeremy L. Thompson 4007a982d89SJeremy L. Thompson /** 401c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 402c04a41a7SJeremy L Thompson 403c04a41a7SJeremy L Thompson @param op CeedOperator 404d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 405c04a41a7SJeremy L Thompson 406c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 407c04a41a7SJeremy L Thompson 408c04a41a7SJeremy L Thompson @ref Backend 409c04a41a7SJeremy L Thompson **/ 410c04a41a7SJeremy L Thompson 411d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 412f04ea552SJeremy L Thompson *is_composite = op->is_composite; 413e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 414c04a41a7SJeremy L Thompson } 415c04a41a7SJeremy L Thompson 416c04a41a7SJeremy L Thompson /** 417d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 4187a982d89SJeremy L. Thompson 4197a982d89SJeremy L. Thompson @param op CeedOperator 420d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 4217a982d89SJeremy L. Thompson 4227a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4237a982d89SJeremy L. Thompson 4247a982d89SJeremy L. Thompson @ref Backend 4257a982d89SJeremy L. Thompson **/ 4267a982d89SJeremy L. Thompson 427d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 428f04ea552SJeremy L Thompson if (!op->is_composite) 4297a982d89SJeremy L. Thompson // LCOV_EXCL_START 430e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4317a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4327a982d89SJeremy L. Thompson 433d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 434e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4357a982d89SJeremy L. Thompson } 4367a982d89SJeremy L. Thompson 4377a982d89SJeremy L. Thompson /** 438d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 4397a982d89SJeremy L. Thompson 4407a982d89SJeremy L. Thompson @param op CeedOperator 441d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 4427a982d89SJeremy L. Thompson 4437a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4447a982d89SJeremy L. Thompson 4457a982d89SJeremy L. Thompson @ref Backend 4467a982d89SJeremy L. Thompson **/ 4477a982d89SJeremy L. Thompson 448d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 449f04ea552SJeremy L Thompson if (!op->is_composite) 4507a982d89SJeremy L. Thompson // LCOV_EXCL_START 451e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4527a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4537a982d89SJeremy L. Thompson 454d1d35e2fSjeremylt *sub_operators = op->sub_operators; 455e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4567a982d89SJeremy L. Thompson } 4577a982d89SJeremy L. Thompson 4587a982d89SJeremy L. Thompson /** 4597a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 4607a982d89SJeremy L. Thompson 4617a982d89SJeremy L. Thompson @param op CeedOperator 4627a982d89SJeremy L. Thompson @param[out] data Variable to store data 4637a982d89SJeremy L. Thompson 4647a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4657a982d89SJeremy L. Thompson 4667a982d89SJeremy L. Thompson @ref Backend 4677a982d89SJeremy L. Thompson **/ 4687a982d89SJeremy L. Thompson 469777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 470777ff853SJeremy L Thompson *(void **)data = op->data; 471e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4727a982d89SJeremy L. Thompson } 4737a982d89SJeremy L. Thompson 4747a982d89SJeremy L. Thompson /** 4757a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 4767a982d89SJeremy L. Thompson 4777a982d89SJeremy L. Thompson @param[out] op CeedOperator 4787a982d89SJeremy L. Thompson @param data Data to set 4797a982d89SJeremy L. Thompson 4807a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4817a982d89SJeremy L. Thompson 4827a982d89SJeremy L. Thompson @ref Backend 4837a982d89SJeremy L. Thompson **/ 4847a982d89SJeremy L. Thompson 485777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 486777ff853SJeremy L Thompson op->data = data; 487e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4887a982d89SJeremy L. Thompson } 4897a982d89SJeremy L. Thompson 4907a982d89SJeremy L. Thompson /** 49134359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 49234359f16Sjeremylt 49334359f16Sjeremylt @param op CeedOperator to increment the reference counter 49434359f16Sjeremylt 49534359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 49634359f16Sjeremylt 49734359f16Sjeremylt @ref Backend 49834359f16Sjeremylt **/ 4999560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 50034359f16Sjeremylt op->ref_count++; 50134359f16Sjeremylt return CEED_ERROR_SUCCESS; 50234359f16Sjeremylt } 50334359f16Sjeremylt 50434359f16Sjeremylt /** 5057a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 5067a982d89SJeremy L. Thompson 5077a982d89SJeremy L. Thompson @param op CeedOperator 5087a982d89SJeremy L. Thompson 5097a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5107a982d89SJeremy L. Thompson 5117a982d89SJeremy L. Thompson @ref Backend 5127a982d89SJeremy L. Thompson **/ 5137a982d89SJeremy L. Thompson 5147a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 515f04ea552SJeremy L Thompson op->is_backend_setup = true; 516e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5177a982d89SJeremy L. Thompson } 5187a982d89SJeremy L. Thompson 5197a982d89SJeremy L. Thompson /// @} 5207a982d89SJeremy L. Thompson 5217a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5227a982d89SJeremy L. Thompson /// CeedOperator Public API 5237a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5247a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 525dfdf5a53Sjeremylt /// @{ 526d7b241e6Sjeremylt 527d7b241e6Sjeremylt /** 5280219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 5290219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 5300219ea01SJeremy L Thompson \ref CeedOperatorSetField. 531d7b241e6Sjeremylt 532b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 533d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 53434138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 5354cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 536d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 5374cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 538b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 539b11c1e72Sjeremylt CeedOperator will be stored 540b11c1e72Sjeremylt 541b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 542dfdf5a53Sjeremylt 5437a982d89SJeremy L. Thompson @ref User 544d7b241e6Sjeremylt */ 545d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 546d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 547d7b241e6Sjeremylt int ierr; 548d7b241e6Sjeremylt 5495fe0d4faSjeremylt if (!ceed->OperatorCreate) { 5505fe0d4faSjeremylt Ceed delegate; 551aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 5525fe0d4faSjeremylt 5535fe0d4faSjeremylt if (!delegate) 554c042f62fSJeremy L Thompson // LCOV_EXCL_START 555e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 556e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 557c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 5585fe0d4faSjeremylt 5595fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 560e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5615fe0d4faSjeremylt } 5625fe0d4faSjeremylt 563b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 564b3b7035fSJeremy L Thompson // LCOV_EXCL_START 565e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 566e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 567b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 568d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 569d7b241e6Sjeremylt (*op)->ceed = ceed; 5709560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 571d1d35e2fSjeremylt (*op)->ref_count = 1; 572d7b241e6Sjeremylt (*op)->qf = qf; 5739560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 574442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 575d7b241e6Sjeremylt (*op)->dqf = dqf; 5769560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 577442e7f0bSjeremylt } 578442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 579d7b241e6Sjeremylt (*op)->dqfT = dqfT; 5809560d06aSjeremylt ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 581442e7f0bSjeremylt } 582480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled); 583480fae85SJeremy L Thompson CeedChk(ierr); 584bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr); 585bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr); 586d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 587e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 588d7b241e6Sjeremylt } 589d7b241e6Sjeremylt 590d7b241e6Sjeremylt /** 59152d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 59252d6035fSJeremy L Thompson 59352d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 59452d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 59552d6035fSJeremy L Thompson Composite CeedOperator will be stored 59652d6035fSJeremy L Thompson 59752d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 59852d6035fSJeremy L Thompson 5997a982d89SJeremy L. Thompson @ref User 60052d6035fSJeremy L Thompson */ 60152d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 60252d6035fSJeremy L Thompson int ierr; 60352d6035fSJeremy L Thompson 60452d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 60552d6035fSJeremy L Thompson Ceed delegate; 606aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 60752d6035fSJeremy L Thompson 608250756a7Sjeremylt if (delegate) { 60952d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 610e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 61152d6035fSJeremy L Thompson } 612250756a7Sjeremylt } 61352d6035fSJeremy L Thompson 61452d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 61552d6035fSJeremy L Thompson (*op)->ceed = ceed; 6169560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 617f04ea552SJeremy L Thompson (*op)->is_composite = true; 618bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr); 619250756a7Sjeremylt 620250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 62152d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 622250756a7Sjeremylt } 623e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 62452d6035fSJeremy L Thompson } 62552d6035fSJeremy L Thompson 62652d6035fSJeremy L Thompson /** 6279560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 6289560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 6299560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 6309560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 6319560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 6329560d06aSjeremylt reference to this CeedOperator. 6339560d06aSjeremylt 6349560d06aSjeremylt @param op CeedOperator to copy reference to 6359560d06aSjeremylt @param[out] op_copy Variable to store copied reference 6369560d06aSjeremylt 6379560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 6389560d06aSjeremylt 6399560d06aSjeremylt @ref User 6409560d06aSjeremylt **/ 6419560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 6429560d06aSjeremylt int ierr; 6439560d06aSjeremylt 6449560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 6459560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 6469560d06aSjeremylt *op_copy = op; 6479560d06aSjeremylt return CEED_ERROR_SUCCESS; 6489560d06aSjeremylt } 6499560d06aSjeremylt 6509560d06aSjeremylt /** 651b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 652d7b241e6Sjeremylt 653d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 654d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 655d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 656d7b241e6Sjeremylt 657d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 658d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 659d7b241e6Sjeremylt input and at most one active output. 660d7b241e6Sjeremylt 6618c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 662d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 6638795c945Sjeremylt CeedQFunction) 664b11c1e72Sjeremylt @param r CeedElemRestriction 6654cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 666b11c1e72Sjeremylt if collocated with quadrature points 6674cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 6684cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 6694cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 670b11c1e72Sjeremylt 671b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 672dfdf5a53Sjeremylt 6737a982d89SJeremy L. Thompson @ref User 674b11c1e72Sjeremylt **/ 675d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 676a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 677d7b241e6Sjeremylt int ierr; 678f04ea552SJeremy L Thompson if (op->is_composite) 679c042f62fSJeremy L Thompson // LCOV_EXCL_START 680e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 681e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 682c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 683f04ea552SJeremy L Thompson if (op->is_immutable) 684f04ea552SJeremy L Thompson // LCOV_EXCL_START 685f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 686f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 687f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 6888b067b84SJed Brown if (!r) 689c042f62fSJeremy L Thompson // LCOV_EXCL_START 690e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 691c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 692d1d35e2fSjeremylt field_name); 693c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6948b067b84SJed Brown if (!b) 695c042f62fSJeremy L Thompson // LCOV_EXCL_START 696e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 697e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 698d1d35e2fSjeremylt field_name); 699c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 7008b067b84SJed Brown if (!v) 701c042f62fSJeremy L Thompson // LCOV_EXCL_START 702e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 703e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 704d1d35e2fSjeremylt field_name); 705c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 70652d6035fSJeremy L Thompson 707d1d35e2fSjeremylt CeedInt num_elem; 708d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 709d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 710d1d35e2fSjeremylt op->num_elem != num_elem) 711c042f62fSJeremy L Thompson // LCOV_EXCL_START 712e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 7131d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 714d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 715c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 716d7b241e6Sjeremylt 71778464608Sjeremylt CeedInt num_qpts = 0; 718e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 719d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 720d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 721c042f62fSJeremy L Thompson // LCOV_EXCL_START 722e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 723e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 724d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 725d1d35e2fSjeremylt op->num_qpts); 726c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 727d7b241e6Sjeremylt } 728d1d35e2fSjeremylt CeedQFunctionField qf_field; 729d1d35e2fSjeremylt CeedOperatorField *op_field; 730d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 731d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 732d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 733d1d35e2fSjeremylt op_field = &op->input_fields[i]; 734d7b241e6Sjeremylt goto found; 735d7b241e6Sjeremylt } 736d7b241e6Sjeremylt } 737d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 738d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 739d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 740d1d35e2fSjeremylt op_field = &op->output_fields[i]; 741d7b241e6Sjeremylt goto found; 742d7b241e6Sjeremylt } 743d7b241e6Sjeremylt } 744c042f62fSJeremy L Thompson // LCOV_EXCL_START 745e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 746e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 747d1d35e2fSjeremylt field_name); 748c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 749d7b241e6Sjeremylt found: 750d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 751d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 752e15f9bd0SJeremy L Thompson 753d1d35e2fSjeremylt (*op_field)->vec = v; 754e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 7559560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 756e15f9bd0SJeremy L Thompson } 757e15f9bd0SJeremy L Thompson 758d1d35e2fSjeremylt (*op_field)->elem_restr = r; 7599560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 760e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 761d1d35e2fSjeremylt op->num_elem = num_elem; 762d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 763e15f9bd0SJeremy L Thompson } 764d99fa3c5SJeremy L Thompson 765d1d35e2fSjeremylt (*op_field)->basis = b; 766e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 767cd4dfc48Sjeremylt if (!op->num_qpts) { 768cd4dfc48Sjeremylt ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 769cd4dfc48Sjeremylt } 7709560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 771e15f9bd0SJeremy L Thompson } 772e15f9bd0SJeremy L Thompson 773d1d35e2fSjeremylt op->num_fields += 1; 774f7e22acaSJeremy L Thompson ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name); 775f7e22acaSJeremy L Thompson CeedChk(ierr); 776e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 777d7b241e6Sjeremylt } 778d7b241e6Sjeremylt 779d7b241e6Sjeremylt /** 78043bbe138SJeremy L Thompson @brief Get the CeedOperatorFields of a CeedOperator 78143bbe138SJeremy L Thompson 782f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 783f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 784f04ea552SJeremy L Thompson 78543bbe138SJeremy L Thompson @param op CeedOperator 786f74ec584SJeremy L Thompson @param[out] num_input_fields Variable to store number of input fields 78743bbe138SJeremy L Thompson @param[out] input_fields Variable to store input_fields 788f74ec584SJeremy L Thompson @param[out] num_output_fields Variable to store number of output fields 78943bbe138SJeremy L Thompson @param[out] output_fields Variable to store output_fields 79043bbe138SJeremy L Thompson 79143bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 79243bbe138SJeremy L Thompson 793e9b533fbSJeremy L Thompson @ref Advanced 79443bbe138SJeremy L Thompson **/ 79543bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields, 79643bbe138SJeremy L Thompson CeedOperatorField **input_fields, 79743bbe138SJeremy L Thompson CeedInt *num_output_fields, 79843bbe138SJeremy L Thompson CeedOperatorField **output_fields) { 799f04ea552SJeremy L Thompson int ierr; 800f04ea552SJeremy L Thompson 801f04ea552SJeremy L Thompson if (op->is_composite) 80243bbe138SJeremy L Thompson // LCOV_EXCL_START 80343bbe138SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 80443bbe138SJeremy L Thompson "Not defined for composite operator"); 80543bbe138SJeremy L Thompson // LCOV_EXCL_STOP 806f04ea552SJeremy L Thompson ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 80743bbe138SJeremy L Thompson 80843bbe138SJeremy L Thompson if (num_input_fields) *num_input_fields = op->qf->num_input_fields; 80943bbe138SJeremy L Thompson if (input_fields) *input_fields = op->input_fields; 81043bbe138SJeremy L Thompson if (num_output_fields) *num_output_fields = op->qf->num_output_fields; 81143bbe138SJeremy L Thompson if (output_fields) *output_fields = op->output_fields; 81243bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 81343bbe138SJeremy L Thompson } 81443bbe138SJeremy L Thompson 81543bbe138SJeremy L Thompson /** 81628567f8fSJeremy L Thompson @brief Get the name of a CeedOperatorField 81728567f8fSJeremy L Thompson 81828567f8fSJeremy L Thompson @param op_field CeedOperatorField 81928567f8fSJeremy L Thompson @param[out] field_name Variable to store the field name 82028567f8fSJeremy L Thompson 82128567f8fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 82228567f8fSJeremy L Thompson 823e9b533fbSJeremy L Thompson @ref Advanced 82428567f8fSJeremy L Thompson **/ 82528567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) { 82628567f8fSJeremy L Thompson *field_name = (char *)op_field->field_name; 82728567f8fSJeremy L Thompson return CEED_ERROR_SUCCESS; 82828567f8fSJeremy L Thompson } 82928567f8fSJeremy L Thompson 83028567f8fSJeremy L Thompson /** 83143bbe138SJeremy L Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 83243bbe138SJeremy L Thompson 83343bbe138SJeremy L Thompson @param op_field CeedOperatorField 83443bbe138SJeremy L Thompson @param[out] rstr Variable to store CeedElemRestriction 83543bbe138SJeremy L Thompson 83643bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 83743bbe138SJeremy L Thompson 838e9b533fbSJeremy L Thompson @ref Advanced 83943bbe138SJeremy L Thompson **/ 84043bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 84143bbe138SJeremy L Thompson CeedElemRestriction *rstr) { 84243bbe138SJeremy L Thompson *rstr = op_field->elem_restr; 84343bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 84443bbe138SJeremy L Thompson } 84543bbe138SJeremy L Thompson 84643bbe138SJeremy L Thompson /** 84743bbe138SJeremy L Thompson @brief Get the CeedBasis of a CeedOperatorField 84843bbe138SJeremy L Thompson 84943bbe138SJeremy L Thompson @param op_field CeedOperatorField 85043bbe138SJeremy L Thompson @param[out] basis Variable to store CeedBasis 85143bbe138SJeremy L Thompson 85243bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 85343bbe138SJeremy L Thompson 854e9b533fbSJeremy L Thompson @ref Advanced 85543bbe138SJeremy L Thompson **/ 85643bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 85743bbe138SJeremy L Thompson *basis = op_field->basis; 85843bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 85943bbe138SJeremy L Thompson } 86043bbe138SJeremy L Thompson 86143bbe138SJeremy L Thompson /** 86243bbe138SJeremy L Thompson @brief Get the CeedVector of a CeedOperatorField 86343bbe138SJeremy L Thompson 86443bbe138SJeremy L Thompson @param op_field CeedOperatorField 86543bbe138SJeremy L Thompson @param[out] vec Variable to store CeedVector 86643bbe138SJeremy L Thompson 86743bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 86843bbe138SJeremy L Thompson 869e9b533fbSJeremy L Thompson @ref Advanced 87043bbe138SJeremy L Thompson **/ 87143bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 87243bbe138SJeremy L Thompson *vec = op_field->vec; 87343bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 87443bbe138SJeremy L Thompson } 87543bbe138SJeremy L Thompson 87643bbe138SJeremy L Thompson /** 87752d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 878288c0443SJeremy L Thompson 879d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 880d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 88152d6035fSJeremy L Thompson 88252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 88352d6035fSJeremy L Thompson 8847a982d89SJeremy L. Thompson @ref User 88552d6035fSJeremy L Thompson */ 886d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 887d1d35e2fSjeremylt CeedOperator sub_op) { 88834359f16Sjeremylt int ierr; 88934359f16Sjeremylt 890f04ea552SJeremy L Thompson if (!composite_op->is_composite) 891c042f62fSJeremy L Thompson // LCOV_EXCL_START 892d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 893e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 894c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 89552d6035fSJeremy L Thompson 896d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 897c042f62fSJeremy L Thompson // LCOV_EXCL_START 898d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 899d1d35e2fSjeremylt "Cannot add additional sub_operators"); 900c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 901f04ea552SJeremy L Thompson if (composite_op->is_immutable) 902f04ea552SJeremy L Thompson // LCOV_EXCL_START 903f04ea552SJeremy L Thompson return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 904f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 905f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 90652d6035fSJeremy L Thompson 907d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 9089560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 909d1d35e2fSjeremylt composite_op->num_suboperators++; 910e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 91152d6035fSJeremy L Thompson } 91252d6035fSJeremy L Thompson 91352d6035fSJeremy L Thompson /** 9144db537f9SJeremy L Thompson @brief Check if a CeedOperator is ready to be used. 9154db537f9SJeremy L Thompson 9164db537f9SJeremy L Thompson @param[in] op CeedOperator to check 9174db537f9SJeremy L Thompson 9184db537f9SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9194db537f9SJeremy L Thompson 9204db537f9SJeremy L Thompson @ref User 9214db537f9SJeremy L Thompson **/ 9224db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) { 9234db537f9SJeremy L Thompson int ierr; 9244db537f9SJeremy L Thompson Ceed ceed; 9254db537f9SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 9264db537f9SJeremy L Thompson 9274db537f9SJeremy L Thompson if (op->is_interface_setup) 9284db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 9294db537f9SJeremy L Thompson 9304db537f9SJeremy L Thompson CeedQFunction qf = op->qf; 9314db537f9SJeremy L Thompson if (op->is_composite) { 9324db537f9SJeremy L Thompson if (!op->num_suboperators) 9334db537f9SJeremy L Thompson // LCOV_EXCL_START 9344db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 9354db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9364db537f9SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 9374db537f9SJeremy L Thompson ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr); 9384db537f9SJeremy L Thompson } 9394db537f9SJeremy L Thompson } else { 9404db537f9SJeremy L Thompson if (op->num_fields == 0) 9414db537f9SJeremy L Thompson // LCOV_EXCL_START 9424db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 9434db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9444db537f9SJeremy L Thompson if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 9454db537f9SJeremy L Thompson // LCOV_EXCL_START 9464db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 9474db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9484db537f9SJeremy L Thompson if (!op->has_restriction) 9494db537f9SJeremy L Thompson // LCOV_EXCL_START 9504db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 9514db537f9SJeremy L Thompson "At least one restriction required"); 9524db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9534db537f9SJeremy L Thompson if (op->num_qpts == 0) 9544db537f9SJeremy L Thompson // LCOV_EXCL_START 9554db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 9564db537f9SJeremy L Thompson "At least one non-collocated basis is required " 9574db537f9SJeremy L Thompson "or the number of quadrature points must be set"); 9584db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9594db537f9SJeremy L Thompson } 9604db537f9SJeremy L Thompson 9614db537f9SJeremy L Thompson // Flag as immutable and ready 9624db537f9SJeremy L Thompson op->is_interface_setup = true; 9634db537f9SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 9644db537f9SJeremy L Thompson // LCOV_EXCL_START 9654db537f9SJeremy L Thompson op->qf->is_immutable = true; 9664db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9674db537f9SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 9684db537f9SJeremy L Thompson // LCOV_EXCL_START 9694db537f9SJeremy L Thompson op->dqf->is_immutable = true; 9704db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9714db537f9SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 9724db537f9SJeremy L Thompson // LCOV_EXCL_START 9734db537f9SJeremy L Thompson op->dqfT->is_immutable = true; 9744db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9754db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 9764db537f9SJeremy L Thompson } 9774db537f9SJeremy L Thompson 9784db537f9SJeremy L Thompson /** 979*beecbf24SJeremy L Thompson @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions. 980*beecbf24SJeremy L Thompson When `reuse_assembly_data = false` (default), the CeedQFunction associated 981*beecbf24SJeremy L Thompson with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*` 982*beecbf24SJeremy L Thompson function is called. 983*beecbf24SJeremy L Thompson When `reuse_assembly_data = true`, the CeedQFunction associated with 984*beecbf24SJeremy L Thompson this CeedOperator is reused between calls to 985*beecbf24SJeremy L Thompson `CeedOperatorSetQFunctionAssemblyDataUpdated`. 9868b919e6bSJeremy L Thompson 987*beecbf24SJeremy L Thompson @param[in] op CeedOperator 988*beecbf24SJeremy L Thompson @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 9898b919e6bSJeremy L Thompson 9908b919e6bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9918b919e6bSJeremy L Thompson 9928b919e6bSJeremy L Thompson @ref Advanced 9938b919e6bSJeremy L Thompson **/ 994*beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, 995*beecbf24SJeremy L Thompson bool reuse_assembly_data) { 9968b919e6bSJeremy L Thompson int ierr; 9978b919e6bSJeremy L Thompson bool is_composite; 9988b919e6bSJeremy L Thompson 9998b919e6bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 10008b919e6bSJeremy L Thompson if (is_composite) { 10018b919e6bSJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1002*beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], 1003*beecbf24SJeremy L Thompson reuse_assembly_data); CeedChk(ierr); 10048b919e6bSJeremy L Thompson } 10058b919e6bSJeremy L Thompson } else { 1006*beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data); 1007*beecbf24SJeremy L Thompson CeedChk(ierr); 1008*beecbf24SJeremy L Thompson } 1009*beecbf24SJeremy L Thompson 1010*beecbf24SJeremy L Thompson return CEED_ERROR_SUCCESS; 1011*beecbf24SJeremy L Thompson } 1012*beecbf24SJeremy L Thompson 1013*beecbf24SJeremy L Thompson /** 1014*beecbf24SJeremy L Thompson @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly. 1015*beecbf24SJeremy L Thompson 1016*beecbf24SJeremy L Thompson @param[in] op CeedOperator 1017*beecbf24SJeremy L Thompson @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 1018*beecbf24SJeremy L Thompson 1019*beecbf24SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1020*beecbf24SJeremy L Thompson 1021*beecbf24SJeremy L Thompson @ref Advanced 1022*beecbf24SJeremy L Thompson **/ 1023*beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, 1024*beecbf24SJeremy L Thompson bool needs_data_update) { 1025*beecbf24SJeremy L Thompson int ierr; 1026*beecbf24SJeremy L Thompson bool is_composite; 1027*beecbf24SJeremy L Thompson 1028*beecbf24SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1029*beecbf24SJeremy L Thompson if (is_composite) { 1030*beecbf24SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1031*beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i], 1032*beecbf24SJeremy L Thompson needs_data_update); CeedChk(ierr); 1033*beecbf24SJeremy L Thompson } 1034*beecbf24SJeremy L Thompson } else { 1035*beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled, 1036*beecbf24SJeremy L Thompson needs_data_update); 10378b919e6bSJeremy L Thompson CeedChk(ierr); 10388b919e6bSJeremy L Thompson } 10398b919e6bSJeremy L Thompson 10408b919e6bSJeremy L Thompson return CEED_ERROR_SUCCESS; 10418b919e6bSJeremy L Thompson } 10428b919e6bSJeremy L Thompson 10438b919e6bSJeremy L Thompson /** 1044cd4dfc48Sjeremylt @brief Set the number of quadrature points associated with a CeedOperator. 1045cd4dfc48Sjeremylt This should be used when creating a CeedOperator where every 1046cd4dfc48Sjeremylt field has a collocated basis. This function cannot be used for 1047cd4dfc48Sjeremylt composite CeedOperators. 1048cd4dfc48Sjeremylt 1049cd4dfc48Sjeremylt @param op CeedOperator 1050cd4dfc48Sjeremylt @param num_qpts Number of quadrature points to set 1051cd4dfc48Sjeremylt 1052cd4dfc48Sjeremylt @return An error code: 0 - success, otherwise - failure 1053cd4dfc48Sjeremylt 1054e9b533fbSJeremy L Thompson @ref Advanced 1055cd4dfc48Sjeremylt **/ 1056cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 1057f04ea552SJeremy L Thompson if (op->is_composite) 1058cd4dfc48Sjeremylt // LCOV_EXCL_START 1059cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1060cd4dfc48Sjeremylt "Not defined for composite operator"); 1061cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1062cd4dfc48Sjeremylt if (op->num_qpts) 1063cd4dfc48Sjeremylt // LCOV_EXCL_START 1064cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1065cd4dfc48Sjeremylt "Number of quadrature points already defined"); 1066cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1067f04ea552SJeremy L Thompson if (op->is_immutable) 1068f04ea552SJeremy L Thompson // LCOV_EXCL_START 1069f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 1070f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 1071f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 1072cd4dfc48Sjeremylt 1073cd4dfc48Sjeremylt op->num_qpts = num_qpts; 1074cd4dfc48Sjeremylt return CEED_ERROR_SUCCESS; 1075cd4dfc48Sjeremylt } 1076cd4dfc48Sjeremylt 1077cd4dfc48Sjeremylt /** 10787a982d89SJeremy L. Thompson @brief View a CeedOperator 10797a982d89SJeremy L. Thompson 10807a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 10817a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 10827a982d89SJeremy L. Thompson 10837a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 10847a982d89SJeremy L. Thompson 10857a982d89SJeremy L. Thompson @ref User 10867a982d89SJeremy L. Thompson **/ 10877a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 10887a982d89SJeremy L. Thompson int ierr; 10897a982d89SJeremy L. Thompson 1090f04ea552SJeremy L Thompson if (op->is_composite) { 10917a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 10927a982d89SJeremy L. Thompson 1093d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 10947a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 1095d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 10967a982d89SJeremy L. Thompson CeedChk(ierr); 10977a982d89SJeremy L. Thompson } 10987a982d89SJeremy L. Thompson } else { 10997a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 11007a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 11017a982d89SJeremy L. Thompson } 1102e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11037a982d89SJeremy L. Thompson } 11043bd813ffSjeremylt 11053bd813ffSjeremylt /** 1106b7c9bbdaSJeremy L Thompson @brief Get the Ceed associated with a CeedOperator 1107b7c9bbdaSJeremy L Thompson 1108b7c9bbdaSJeremy L Thompson @param op CeedOperator 1109b7c9bbdaSJeremy L Thompson @param[out] ceed Variable to store Ceed 1110b7c9bbdaSJeremy L Thompson 1111b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1112b7c9bbdaSJeremy L Thompson 1113b7c9bbdaSJeremy L Thompson @ref Advanced 1114b7c9bbdaSJeremy L Thompson **/ 1115b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1116b7c9bbdaSJeremy L Thompson *ceed = op->ceed; 1117b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1118b7c9bbdaSJeremy L Thompson } 1119b7c9bbdaSJeremy L Thompson 1120b7c9bbdaSJeremy L Thompson /** 1121b7c9bbdaSJeremy L Thompson @brief Get the number of elements associated with a CeedOperator 1122b7c9bbdaSJeremy L Thompson 1123b7c9bbdaSJeremy L Thompson @param op CeedOperator 1124b7c9bbdaSJeremy L Thompson @param[out] num_elem Variable to store number of elements 1125b7c9bbdaSJeremy L Thompson 1126b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1127b7c9bbdaSJeremy L Thompson 1128b7c9bbdaSJeremy L Thompson @ref Advanced 1129b7c9bbdaSJeremy L Thompson **/ 1130b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 1131b7c9bbdaSJeremy L Thompson if (op->is_composite) 1132b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1133b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1134b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1135b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1136b7c9bbdaSJeremy L Thompson 1137b7c9bbdaSJeremy L Thompson *num_elem = op->num_elem; 1138b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1139b7c9bbdaSJeremy L Thompson } 1140b7c9bbdaSJeremy L Thompson 1141b7c9bbdaSJeremy L Thompson /** 1142b7c9bbdaSJeremy L Thompson @brief Get the number of quadrature points associated with a CeedOperator 1143b7c9bbdaSJeremy L Thompson 1144b7c9bbdaSJeremy L Thompson @param op CeedOperator 1145b7c9bbdaSJeremy L Thompson @param[out] num_qpts Variable to store vector number of quadrature points 1146b7c9bbdaSJeremy L Thompson 1147b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1148b7c9bbdaSJeremy L Thompson 1149b7c9bbdaSJeremy L Thompson @ref Advanced 1150b7c9bbdaSJeremy L Thompson **/ 1151b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 1152b7c9bbdaSJeremy L Thompson if (op->is_composite) 1153b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1154b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1155b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1156b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1157b7c9bbdaSJeremy L Thompson 1158b7c9bbdaSJeremy L Thompson *num_qpts = op->num_qpts; 1159b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1160b7c9bbdaSJeremy L Thompson } 1161b7c9bbdaSJeremy L Thompson 1162b7c9bbdaSJeremy L Thompson /** 11633668ca4bSJeremy L Thompson @brief Get label for a registered QFunctionContext field, or `NULL` if no 11643668ca4bSJeremy L Thompson field has been registered with this `field_name`. 11653668ca4bSJeremy L Thompson 11663668ca4bSJeremy L Thompson @param[in] op CeedOperator 11673668ca4bSJeremy L Thompson @param[in] field_name Name of field to retrieve label 11683668ca4bSJeremy L Thompson @param[out] field_label Variable to field label 11693668ca4bSJeremy L Thompson 11703668ca4bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11713668ca4bSJeremy L Thompson 11723668ca4bSJeremy L Thompson @ref User 11733668ca4bSJeremy L Thompson **/ 11743668ca4bSJeremy L Thompson int CeedOperatorContextGetFieldLabel(CeedOperator op, 11753668ca4bSJeremy L Thompson const char *field_name, 11763668ca4bSJeremy L Thompson CeedContextFieldLabel *field_label) { 11773668ca4bSJeremy L Thompson int ierr; 11783668ca4bSJeremy L Thompson 11793668ca4bSJeremy L Thompson bool is_composite; 11803668ca4bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 11813668ca4bSJeremy L Thompson if (is_composite) { 11823668ca4bSJeremy L Thompson // Check if composite label already created 11833668ca4bSJeremy L Thompson for (CeedInt i=0; i<op->num_context_labels; i++) { 11843668ca4bSJeremy L Thompson if (!strcmp(op->context_labels[i]->name, field_name)) { 11853668ca4bSJeremy L Thompson *field_label = op->context_labels[i]; 11863668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 11873668ca4bSJeremy L Thompson } 11883668ca4bSJeremy L Thompson } 11893668ca4bSJeremy L Thompson 11903668ca4bSJeremy L Thompson // Create composite label if needed 11913668ca4bSJeremy L Thompson CeedInt num_sub; 11923668ca4bSJeremy L Thompson CeedOperator *sub_operators; 11933668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label; 11943668ca4bSJeremy L Thompson 11953668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr); 11963668ca4bSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 11973668ca4bSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 11983668ca4bSJeremy L Thompson ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr); 11993668ca4bSJeremy L Thompson new_field_label->num_sub_labels = num_sub; 12003668ca4bSJeremy L Thompson 12013668ca4bSJeremy L Thompson bool label_found = false; 12023668ca4bSJeremy L Thompson for (CeedInt i=0; i<num_sub; i++) { 12033668ca4bSJeremy L Thompson if (sub_operators[i]->qf->ctx) { 12043668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label_i; 12053668ca4bSJeremy L Thompson ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, 12063668ca4bSJeremy L Thompson &new_field_label_i); CeedChk(ierr); 12073668ca4bSJeremy L Thompson if (new_field_label_i) { 12083668ca4bSJeremy L Thompson label_found = true; 12093668ca4bSJeremy L Thompson new_field_label->sub_labels[i] = new_field_label_i; 12103668ca4bSJeremy L Thompson new_field_label->name = new_field_label_i->name; 12113668ca4bSJeremy L Thompson new_field_label->description = new_field_label_i->description; 12127bfe0f0eSJeremy L Thompson if (new_field_label->type && 12137bfe0f0eSJeremy L Thompson new_field_label->type != new_field_label_i->type) { 12147bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 12157bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 12167bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 12177bfe0f0eSJeremy L Thompson "Incompatible field types on sub-operator contexts. " 12187bfe0f0eSJeremy L Thompson "%s != %s", 12197bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label->type], 12207bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label_i->type]); 12217bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 12227bfe0f0eSJeremy L Thompson } else { 12237bfe0f0eSJeremy L Thompson new_field_label->type = new_field_label_i->type; 12247bfe0f0eSJeremy L Thompson } 12257bfe0f0eSJeremy L Thompson if (new_field_label->num_values != 0 && 12267bfe0f0eSJeremy L Thompson new_field_label->num_values != new_field_label_i->num_values) { 12277bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 12287bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 12297bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 12307bfe0f0eSJeremy L Thompson "Incompatible field number of values on sub-operator" 12317bfe0f0eSJeremy L Thompson " contexts. %ld != %ld", 12327bfe0f0eSJeremy L Thompson new_field_label->num_values, new_field_label_i->num_values); 12337bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 12347bfe0f0eSJeremy L Thompson } else { 12357bfe0f0eSJeremy L Thompson new_field_label->num_values = new_field_label_i->num_values; 12367bfe0f0eSJeremy L Thompson } 12373668ca4bSJeremy L Thompson } 12383668ca4bSJeremy L Thompson } 12393668ca4bSJeremy L Thompson } 12403668ca4bSJeremy L Thompson if (!label_found) { 12413668ca4bSJeremy L Thompson // LCOV_EXCL_START 1242a48e5f43SJeremy L Thompson ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr); 12433668ca4bSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 12443668ca4bSJeremy L Thompson *field_label = NULL; 12453668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 12463668ca4bSJeremy L Thompson } else { 12473668ca4bSJeremy L Thompson // Move new composite label to operator 12483668ca4bSJeremy L Thompson if (op->num_context_labels == 0) { 12493668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr); 12503668ca4bSJeremy L Thompson op->max_context_labels = 1; 12513668ca4bSJeremy L Thompson } else if (op->num_context_labels == op->max_context_labels) { 12523668ca4bSJeremy L Thompson ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels); 12533668ca4bSJeremy L Thompson CeedChk(ierr); 12543668ca4bSJeremy L Thompson op->max_context_labels *= 2; 12553668ca4bSJeremy L Thompson } 12563668ca4bSJeremy L Thompson op->context_labels[op->num_context_labels] = new_field_label; 12573668ca4bSJeremy L Thompson *field_label = new_field_label; 12583668ca4bSJeremy L Thompson op->num_context_labels++; 12593668ca4bSJeremy L Thompson } 12603668ca4bSJeremy L Thompson 12613668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 12623668ca4bSJeremy L Thompson } else { 12633668ca4bSJeremy L Thompson return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label); 12643668ca4bSJeremy L Thompson } 12653668ca4bSJeremy L Thompson } 12663668ca4bSJeremy L Thompson 12673668ca4bSJeremy L Thompson /** 1268d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding a double precision value. 1269d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1270d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1271d8dd9a91SJeremy L Thompson 1272d8dd9a91SJeremy L Thompson @param op CeedOperator 12733668ca4bSJeremy L Thompson @param field_label Label of field to register 12747bfe0f0eSJeremy L Thompson @param values Values to set 1275d8dd9a91SJeremy L Thompson 1276d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1277d8dd9a91SJeremy L Thompson 1278d8dd9a91SJeremy L Thompson @ref User 1279d8dd9a91SJeremy L Thompson **/ 12803668ca4bSJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op, 12813668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 12827bfe0f0eSJeremy L Thompson double *values) { 12833668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, 12847bfe0f0eSJeremy L Thompson values); 1285d8dd9a91SJeremy L Thompson } 1286d8dd9a91SJeremy L Thompson 1287d8dd9a91SJeremy L Thompson /** 1288d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding an int32 value. 1289d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1290d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1291d8dd9a91SJeremy L Thompson 1292d8dd9a91SJeremy L Thompson @param op CeedOperator 12933668ca4bSJeremy L Thompson @param field_label Label of field to set 12947bfe0f0eSJeremy L Thompson @param values Values to set 1295d8dd9a91SJeremy L Thompson 1296d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1297d8dd9a91SJeremy L Thompson 1298d8dd9a91SJeremy L Thompson @ref User 1299d8dd9a91SJeremy L Thompson **/ 13003668ca4bSJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op, 13013668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 13027bfe0f0eSJeremy L Thompson int *values) { 13033668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, 13047bfe0f0eSJeremy L Thompson values); 1305d8dd9a91SJeremy L Thompson } 1306d8dd9a91SJeremy L Thompson 1307d8dd9a91SJeremy L Thompson /** 13083bd813ffSjeremylt @brief Apply CeedOperator to a vector 1309d7b241e6Sjeremylt 1310d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 1311d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 1312d7b241e6Sjeremylt CeedOperatorSetField(). 1313d7b241e6Sjeremylt 1314f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 1315f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 1316f04ea552SJeremy L Thompson 1317d7b241e6Sjeremylt @param op CeedOperator to apply 13184cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 131934138859Sjeremylt there are no active inputs 1320b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 13214cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 132234138859Sjeremylt active outputs 1323d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 13244cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1325b11c1e72Sjeremylt 1326b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1327dfdf5a53Sjeremylt 13287a982d89SJeremy L. Thompson @ref User 1329b11c1e72Sjeremylt **/ 1330692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1331692c2638Sjeremylt CeedRequest *request) { 1332d7b241e6Sjeremylt int ierr; 1333e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1334d7b241e6Sjeremylt 1335d1d35e2fSjeremylt if (op->num_elem) { 1336250756a7Sjeremylt // Standard Operator 1337cae8b89aSjeremylt if (op->Apply) { 1338250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1339cae8b89aSjeremylt } else { 1340cae8b89aSjeremylt // Zero all output vectors 1341250756a7Sjeremylt CeedQFunction qf = op->qf; 1342d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 1343d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 1344cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 1345cae8b89aSjeremylt vec = out; 1346cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 1347cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1348cae8b89aSjeremylt } 1349cae8b89aSjeremylt } 1350250756a7Sjeremylt // Apply 1351250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1352250756a7Sjeremylt } 1353f04ea552SJeremy L Thompson } else if (op->is_composite) { 1354250756a7Sjeremylt // Composite Operator 1355250756a7Sjeremylt if (op->ApplyComposite) { 1356250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1357250756a7Sjeremylt } else { 1358d1d35e2fSjeremylt CeedInt num_suboperators; 1359d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1360d1d35e2fSjeremylt CeedOperator *sub_operators; 1361d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1362250756a7Sjeremylt 1363250756a7Sjeremylt // Zero all output vectors 1364250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 1365cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1366cae8b89aSjeremylt } 1367d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1368d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 1369d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 1370250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1371250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1372250756a7Sjeremylt } 1373250756a7Sjeremylt } 1374250756a7Sjeremylt } 1375250756a7Sjeremylt // Apply 1376d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 1377d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 1378cae8b89aSjeremylt CeedChk(ierr); 1379cae8b89aSjeremylt } 1380cae8b89aSjeremylt } 1381250756a7Sjeremylt } 1382e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1383cae8b89aSjeremylt } 1384cae8b89aSjeremylt 1385cae8b89aSjeremylt /** 1386cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 1387cae8b89aSjeremylt 1388cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 1389cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 1390cae8b89aSjeremylt CeedOperatorSetField(). 1391cae8b89aSjeremylt 1392cae8b89aSjeremylt @param op CeedOperator to apply 1393cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 1394cae8b89aSjeremylt active inputs 1395cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 1396cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 1397cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 13984cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1399cae8b89aSjeremylt 1400cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 1401cae8b89aSjeremylt 14027a982d89SJeremy L. Thompson @ref User 1403cae8b89aSjeremylt **/ 1404cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1405cae8b89aSjeremylt CeedRequest *request) { 1406cae8b89aSjeremylt int ierr; 1407e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1408cae8b89aSjeremylt 1409d1d35e2fSjeremylt if (op->num_elem) { 1410250756a7Sjeremylt // Standard Operator 1411250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1412f04ea552SJeremy L Thompson } else if (op->is_composite) { 1413250756a7Sjeremylt // Composite Operator 1414250756a7Sjeremylt if (op->ApplyAddComposite) { 1415250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1416cae8b89aSjeremylt } else { 1417d1d35e2fSjeremylt CeedInt num_suboperators; 1418d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1419d1d35e2fSjeremylt CeedOperator *sub_operators; 1420d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1421250756a7Sjeremylt 1422d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1423d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 1424cae8b89aSjeremylt CeedChk(ierr); 14251d7d2407SJeremy L Thompson } 1426250756a7Sjeremylt } 1427250756a7Sjeremylt } 1428e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1429d7b241e6Sjeremylt } 1430d7b241e6Sjeremylt 1431d7b241e6Sjeremylt /** 1432b11c1e72Sjeremylt @brief Destroy a CeedOperator 1433d7b241e6Sjeremylt 1434d7b241e6Sjeremylt @param op CeedOperator to destroy 1435b11c1e72Sjeremylt 1436b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1437dfdf5a53Sjeremylt 14387a982d89SJeremy L. Thompson @ref User 1439b11c1e72Sjeremylt **/ 1440d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1441d7b241e6Sjeremylt int ierr; 1442d7b241e6Sjeremylt 1443d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 1444d7b241e6Sjeremylt if ((*op)->Destroy) { 1445d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1446d7b241e6Sjeremylt } 1447fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1448fe2413ffSjeremylt // Free fields 14493668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1450d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 1451d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 1452d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 145371352a93Sjeremylt CeedChk(ierr); 145415910d16Sjeremylt } 1455d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1456d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 145771352a93Sjeremylt } 1458d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 1459d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 1460d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 146171352a93Sjeremylt } 1462d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 1463d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 1464fe2413ffSjeremylt } 14653668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1466d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 1467d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 146871352a93Sjeremylt CeedChk(ierr); 1469d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1470d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 147171352a93Sjeremylt } 1472d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 1473d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 1474d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 147571352a93Sjeremylt } 1476d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 1477d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 1478fe2413ffSjeremylt } 1479d1d35e2fSjeremylt // Destroy sub_operators 14803668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_suboperators; i++) 1481d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 1482d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 148352d6035fSJeremy L Thompson } 1484d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1485d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1486d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 14873668ca4bSJeremy L Thompson // Destroy any composite labels 14883668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_context_labels; i++) { 14893668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr); 14903668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr); 14913668ca4bSJeremy L Thompson } 14923668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr); 1493fe2413ffSjeremylt 14945107b09fSJeremy L Thompson // Destroy fallback 1495d1d35e2fSjeremylt if ((*op)->op_fallback) { 1496d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 1497d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 1498d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 1499d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 15005107b09fSJeremy L Thompson } 15015107b09fSJeremy L Thompson 150270a7ffb3SJeremy L Thompson // Destroy QF assembly cache 1503480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr); 150470a7ffb3SJeremy L Thompson 1505d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 1506d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 1507d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 1508d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1509e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1510d7b241e6Sjeremylt } 1511d7b241e6Sjeremylt 1512d7b241e6Sjeremylt /// @} 1513