13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3d7b241e6Sjeremylt // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 5d7b241e6Sjeremylt // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 7d7b241e6Sjeremylt 8ec3da8bcSJed Brown #include <ceed/ceed.h> 9ec3da8bcSJed Brown #include <ceed/backend.h> 103d576824SJeremy L Thompson #include <ceed-impl.h> 113d576824SJeremy L Thompson #include <stdbool.h> 123d576824SJeremy L Thompson #include <stdio.h> 133d576824SJeremy L Thompson #include <string.h> 14d7b241e6Sjeremylt 15dfdf5a53Sjeremylt /// @file 167a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 177a982d89SJeremy L. Thompson 187a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 197a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 207a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 217a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 227a982d89SJeremy L. Thompson /// @{ 237a982d89SJeremy L. Thompson 247a982d89SJeremy L. Thompson /** 25e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 26e15f9bd0SJeremy L Thompson 27e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 28d1d35e2fSjeremylt @param[in] qf_field QFunction Field matching Operator Field 29e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 30e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 31e15f9bd0SJeremy L Thompson 32e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 33e15f9bd0SJeremy L Thompson 34e15f9bd0SJeremy L Thompson @ref Developer 35e15f9bd0SJeremy L Thompson **/ 36d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, 37e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 38e15f9bd0SJeremy L Thompson int ierr; 39d1d35e2fSjeremylt CeedEvalMode eval_mode = qf_field->eval_mode; 40d1d35e2fSjeremylt CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size; 41e15f9bd0SJeremy L Thompson // Restriction 42e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 43d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { 44e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 45e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 46e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE should be used " 47e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 48e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 49e15f9bd0SJeremy L Thompson } 50d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp); 5178464608Sjeremylt CeedChk(ierr); 52e1e9e29dSJed Brown } 53d1d35e2fSjeremylt if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) { 54e1e9e29dSJed Brown // LCOV_EXCL_START 55e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 56e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 57e1e9e29dSJed Brown "must be used together."); 58e1e9e29dSJed Brown // LCOV_EXCL_STOP 59e1e9e29dSJed Brown } 60e15f9bd0SJeremy L Thompson // Basis 61e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 62d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) 638229195eSjeremylt // LCOV_EXCL_START 64e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 65d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 66d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 678229195eSjeremylt // LCOV_EXCL_STOP 68d1d35e2fSjeremylt qf_field->field_name); 69e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 70d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 71d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 72e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 73e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 74d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 75d1d35e2fSjeremylt "has %d components, but Basis has %d components", 76d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 77d1d35e2fSjeremylt restr_num_comp, 78d1d35e2fSjeremylt num_comp); 79e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 80e15f9bd0SJeremy L Thompson } 81e15f9bd0SJeremy L Thompson } 82e15f9bd0SJeremy L Thompson // Field size 83d1d35e2fSjeremylt switch(eval_mode) { 84e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 85d1d35e2fSjeremylt if (size != restr_num_comp) 86e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 87e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 88e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 89d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 90d1d35e2fSjeremylt restr_num_comp); 91e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 92e15f9bd0SJeremy L Thompson break; 93e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 94d1d35e2fSjeremylt if (size != 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/Basis has %d components", 98d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 99d1d35e2fSjeremylt num_comp); 100e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 101e15f9bd0SJeremy L Thompson break; 102e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 103d1d35e2fSjeremylt if (size != num_comp * dim) 104e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 105e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 106d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 107d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 108d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 109d1d35e2fSjeremylt num_comp); 110e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 111e15f9bd0SJeremy L Thompson break; 112e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 113d1d35e2fSjeremylt // No additional checks required 114e15f9bd0SJeremy L Thompson break; 115e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 116e15f9bd0SJeremy L Thompson // Not implemented 117e15f9bd0SJeremy L Thompson break; 118e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 119e15f9bd0SJeremy L Thompson // Not implemented 120e15f9bd0SJeremy L Thompson break; 121e15f9bd0SJeremy L Thompson } 122e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1237a982d89SJeremy L. Thompson } 1247a982d89SJeremy L. Thompson 1257a982d89SJeremy L. Thompson /** 1267a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 1277a982d89SJeremy L. Thompson 1287a982d89SJeremy L. Thompson @param[in] field Operator field to view 129d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 130d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 1314c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 132d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 1337a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 1347a982d89SJeremy L. Thompson 1357a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1367a982d89SJeremy L. Thompson 1377a982d89SJeremy L. Thompson @ref Utility 1387a982d89SJeremy L. Thompson **/ 1397a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 140d1d35e2fSjeremylt CeedQFunctionField qf_field, 141d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 1427a982d89SJeremy L. Thompson FILE *stream) { 1437a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 144d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 1457a982d89SJeremy L. Thompson 1467a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 1477a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 148d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 1497a982d89SJeremy L. Thompson 1507a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 1517a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 1527a982d89SJeremy L. Thompson 1537a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 1547a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 1557a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 1567a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 157e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1587a982d89SJeremy L. Thompson } 1597a982d89SJeremy L. Thompson 1607a982d89SJeremy L. Thompson /** 1617a982d89SJeremy L. Thompson @brief View a single CeedOperator 1627a982d89SJeremy L. Thompson 1637a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 1647a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 1657a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 1667a982d89SJeremy L. Thompson 1677a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 1687a982d89SJeremy L. Thompson 1697a982d89SJeremy L. Thompson @ref Utility 1707a982d89SJeremy L. Thompson **/ 1717a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 1727a982d89SJeremy L. Thompson int ierr; 1737a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 1747a982d89SJeremy L. Thompson 17578464608Sjeremylt CeedInt total_fields = 0; 17678464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 1777a982d89SJeremy L. Thompson 17878464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 17978464608Sjeremylt total_fields>1 ? "s" : ""); 1807a982d89SJeremy L. Thompson 181d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 182d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 183d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 184d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 1857a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 1867a982d89SJeremy L. Thompson } 1877a982d89SJeremy L. Thompson 188d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 189d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 190d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 191d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 1927a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 1937a982d89SJeremy L. Thompson } 194e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1957a982d89SJeremy L. Thompson } 1967a982d89SJeremy L. Thompson 197d99fa3c5SJeremy L Thompson /** 1980f60e0a8SJeremy L Thompson @brief Find the active vector basis for a non-composite CeedOperator 199eaf62fffSJeremy L Thompson 200eaf62fffSJeremy L Thompson @param[in] op CeedOperator to find active basis for 2010f60e0a8SJeremy L Thompson @param[out] active_basis Basis for active input vector or NULL for composite operator 202eaf62fffSJeremy L Thompson 203eaf62fffSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 204eaf62fffSJeremy L Thompson 205eaf62fffSJeremy L Thompson @ ref Developer 206eaf62fffSJeremy L Thompson **/ 207eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) { 208eaf62fffSJeremy L Thompson *active_basis = NULL; 2090f60e0a8SJeremy L Thompson if (op->is_composite) return CEED_ERROR_SUCCESS; 210eaf62fffSJeremy L Thompson for (int i = 0; i < op->qf->num_input_fields; i++) 211eaf62fffSJeremy L Thompson if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 212eaf62fffSJeremy L Thompson *active_basis = op->input_fields[i]->basis; 213eaf62fffSJeremy L Thompson break; 214eaf62fffSJeremy L Thompson } 215eaf62fffSJeremy L Thompson 216eaf62fffSJeremy L Thompson if (!*active_basis) { 217eaf62fffSJeremy L Thompson // LCOV_EXCL_START 218eaf62fffSJeremy L Thompson int ierr; 219eaf62fffSJeremy L Thompson Ceed ceed; 220eaf62fffSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 221eaf62fffSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 222eaf62fffSJeremy L Thompson "No active CeedBasis found"); 223eaf62fffSJeremy L Thompson // LCOV_EXCL_STOP 224eaf62fffSJeremy L Thompson } 225eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 226eaf62fffSJeremy L Thompson } 227eaf62fffSJeremy L Thompson 228eaf62fffSJeremy L Thompson /** 2290f60e0a8SJeremy L Thompson @brief Find the active vector ElemRestriction for a non-composite CeedOperator 230e2f04181SAndrew T. Barker 231e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 2320f60e0a8SJeremy L Thompson @param[out] active_rstr ElemRestriction for active input vector or NULL for composite operator 233e2f04181SAndrew T. Barker 234e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 235e2f04181SAndrew T. Barker 236e2f04181SAndrew T. Barker @ref Utility 237e2f04181SAndrew T. Barker **/ 238eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op, 239d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 240d1d35e2fSjeremylt *active_rstr = NULL; 2410f60e0a8SJeremy L Thompson if (op->is_composite) return CEED_ERROR_SUCCESS; 242d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 243d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 244d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 245e2f04181SAndrew T. Barker break; 246e2f04181SAndrew T. Barker } 247e2f04181SAndrew T. Barker 248d1d35e2fSjeremylt if (!*active_rstr) { 249e2f04181SAndrew T. Barker // LCOV_EXCL_START 250e2f04181SAndrew T. Barker int ierr; 251e2f04181SAndrew T. Barker Ceed ceed; 252e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 253e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 254eaf62fffSJeremy L Thompson "No active CeedElemRestriction found"); 255e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 256e2f04181SAndrew T. Barker } 257e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 258e2f04181SAndrew T. Barker } 259e2f04181SAndrew T. Barker 260d8dd9a91SJeremy L Thompson /** 261d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field value of the specified type. 262d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 263d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 264d8dd9a91SJeremy L Thompson A non-zero error code is returned for single operators 265d8dd9a91SJeremy L Thompson that do not have a matching field of the same type or composite 266d8dd9a91SJeremy L Thompson operators that do not have any field of a matching type. 267d8dd9a91SJeremy L Thompson 268d8dd9a91SJeremy L Thompson @param op CeedOperator 2693668ca4bSJeremy L Thompson @param field_label Label of field to set 270d8dd9a91SJeremy L Thompson @param field_type Type of field to set 271d8dd9a91SJeremy L Thompson @param value Value to set 272d8dd9a91SJeremy L Thompson 273d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 274d8dd9a91SJeremy L Thompson 275d8dd9a91SJeremy L Thompson @ref User 276d8dd9a91SJeremy L Thompson **/ 277d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op, 2783668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, CeedContextFieldType field_type, 2793668ca4bSJeremy L Thompson void *value) { 280d8dd9a91SJeremy L Thompson int ierr; 281d8dd9a91SJeremy L Thompson 2823668ca4bSJeremy L Thompson if (!field_label) 2833668ca4bSJeremy L Thompson // LCOV_EXCL_START 2843668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 2853668ca4bSJeremy L Thompson "Invalid field label"); 2863668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 2873668ca4bSJeremy L Thompson 2883668ca4bSJeremy L Thompson bool is_composite = false; 289d8dd9a91SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 290d8dd9a91SJeremy L Thompson if (is_composite) { 291d8dd9a91SJeremy L Thompson CeedInt num_sub; 292d8dd9a91SJeremy L Thompson CeedOperator *sub_operators; 293d8dd9a91SJeremy L Thompson 294d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 295d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2963668ca4bSJeremy L Thompson if (num_sub != field_label->num_sub_labels) 2973668ca4bSJeremy L Thompson // LCOV_EXCL_START 2983668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 2993668ca4bSJeremy L Thompson "ContextLabel does not correspond to composite operator.\n" 3003668ca4bSJeremy L Thompson "Use CeedOperatorGetContextFieldLabel()."); 3013668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 302d8dd9a91SJeremy L Thompson 303d8dd9a91SJeremy L Thompson for (CeedInt i = 0; i < num_sub; i++) { 304d8dd9a91SJeremy L Thompson // Try every sub-operator, ok if some sub-operators do not have field 3053668ca4bSJeremy L Thompson if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) { 3063668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx, 3073668ca4bSJeremy L Thompson field_label->sub_labels[i], 3083668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 309d8dd9a91SJeremy L Thompson } 310d8dd9a91SJeremy L Thompson } 311d8dd9a91SJeremy L Thompson } else { 312d8dd9a91SJeremy L Thompson if (!op->qf->ctx) 313d8dd9a91SJeremy L Thompson // LCOV_EXCL_START 314d8dd9a91SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 315d8dd9a91SJeremy L Thompson "QFunction does not have context data"); 316d8dd9a91SJeremy L Thompson // LCOV_EXCL_STOP 317d8dd9a91SJeremy L Thompson 3183668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label, 3193668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 320d8dd9a91SJeremy L Thompson } 321d8dd9a91SJeremy L Thompson 322d8dd9a91SJeremy L Thompson return CEED_ERROR_SUCCESS; 323d8dd9a91SJeremy L Thompson } 324d8dd9a91SJeremy L Thompson 3257a982d89SJeremy L. Thompson /// @} 3267a982d89SJeremy L. Thompson 3277a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3287a982d89SJeremy L. Thompson /// CeedOperator Backend API 3297a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3307a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 3317a982d89SJeremy L. Thompson /// @{ 3327a982d89SJeremy L. Thompson 3337a982d89SJeremy L. Thompson /** 3347a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 3357a982d89SJeremy L. Thompson 3367a982d89SJeremy L. Thompson @param op CeedOperator 337d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 3387a982d89SJeremy L. Thompson 3397a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3407a982d89SJeremy L. Thompson 3417a982d89SJeremy L. Thompson @ref Backend 3427a982d89SJeremy L. Thompson **/ 3437a982d89SJeremy L. Thompson 344d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 345f04ea552SJeremy L Thompson if (op->is_composite) 3467a982d89SJeremy L. Thompson // LCOV_EXCL_START 347e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 348e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 3497a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3507a982d89SJeremy L. Thompson 351d1d35e2fSjeremylt *num_args = op->num_fields; 352e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3537a982d89SJeremy L. Thompson } 3547a982d89SJeremy L. Thompson 3557a982d89SJeremy L. Thompson /** 3567a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 3577a982d89SJeremy L. Thompson 3587a982d89SJeremy L. Thompson @param op CeedOperator 359d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 3607a982d89SJeremy L. Thompson 3617a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3627a982d89SJeremy L. Thompson 3637a982d89SJeremy L. Thompson @ref Backend 3647a982d89SJeremy L. Thompson **/ 3657a982d89SJeremy L. Thompson 366d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 367f04ea552SJeremy L Thompson *is_setup_done = op->is_backend_setup; 368e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3697a982d89SJeremy L. Thompson } 3707a982d89SJeremy L. Thompson 3717a982d89SJeremy L. Thompson /** 3727a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 3737a982d89SJeremy L. Thompson 3747a982d89SJeremy L. Thompson @param op CeedOperator 3757a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 3767a982d89SJeremy L. Thompson 3777a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3787a982d89SJeremy L. Thompson 3797a982d89SJeremy L. Thompson @ref Backend 3807a982d89SJeremy L. Thompson **/ 3817a982d89SJeremy L. Thompson 3827a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 383f04ea552SJeremy L Thompson if (op->is_composite) 3847a982d89SJeremy L. Thompson // LCOV_EXCL_START 385e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 386e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 3877a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3887a982d89SJeremy L. Thompson 3897a982d89SJeremy L. Thompson *qf = op->qf; 390e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3917a982d89SJeremy L. Thompson } 3927a982d89SJeremy L. Thompson 3937a982d89SJeremy L. Thompson /** 394c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 395c04a41a7SJeremy L Thompson 396c04a41a7SJeremy L Thompson @param op CeedOperator 397d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 398c04a41a7SJeremy L Thompson 399c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 400c04a41a7SJeremy L Thompson 401c04a41a7SJeremy L Thompson @ref Backend 402c04a41a7SJeremy L Thompson **/ 403c04a41a7SJeremy L Thompson 404d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 405f04ea552SJeremy L Thompson *is_composite = op->is_composite; 406e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 407c04a41a7SJeremy L Thompson } 408c04a41a7SJeremy L Thompson 409c04a41a7SJeremy L Thompson /** 410d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 4117a982d89SJeremy L. Thompson 4127a982d89SJeremy L. Thompson @param op CeedOperator 413d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 4147a982d89SJeremy L. Thompson 4157a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4167a982d89SJeremy L. Thompson 4177a982d89SJeremy L. Thompson @ref Backend 4187a982d89SJeremy L. Thompson **/ 4197a982d89SJeremy L. Thompson 420d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 421f04ea552SJeremy L Thompson if (!op->is_composite) 4227a982d89SJeremy L. Thompson // LCOV_EXCL_START 423e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4247a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4257a982d89SJeremy L. Thompson 426d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 427e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4287a982d89SJeremy L. Thompson } 4297a982d89SJeremy L. Thompson 4307a982d89SJeremy L. Thompson /** 431d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 4327a982d89SJeremy L. Thompson 4337a982d89SJeremy L. Thompson @param op CeedOperator 434d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 4357a982d89SJeremy L. Thompson 4367a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4377a982d89SJeremy L. Thompson 4387a982d89SJeremy L. Thompson @ref Backend 4397a982d89SJeremy L. Thompson **/ 4407a982d89SJeremy L. Thompson 441d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 442f04ea552SJeremy L Thompson if (!op->is_composite) 4437a982d89SJeremy L. Thompson // LCOV_EXCL_START 444e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4457a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4467a982d89SJeremy L. Thompson 447d1d35e2fSjeremylt *sub_operators = op->sub_operators; 448e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4497a982d89SJeremy L. Thompson } 4507a982d89SJeremy L. Thompson 4517a982d89SJeremy L. Thompson /** 4527a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 4537a982d89SJeremy L. Thompson 4547a982d89SJeremy L. Thompson @param op CeedOperator 4557a982d89SJeremy L. Thompson @param[out] data Variable to store data 4567a982d89SJeremy L. Thompson 4577a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4587a982d89SJeremy L. Thompson 4597a982d89SJeremy L. Thompson @ref Backend 4607a982d89SJeremy L. Thompson **/ 4617a982d89SJeremy L. Thompson 462777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 463777ff853SJeremy L Thompson *(void **)data = op->data; 464e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4657a982d89SJeremy L. Thompson } 4667a982d89SJeremy L. Thompson 4677a982d89SJeremy L. Thompson /** 4687a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 4697a982d89SJeremy L. Thompson 4707a982d89SJeremy L. Thompson @param[out] op CeedOperator 4717a982d89SJeremy L. Thompson @param data Data to set 4727a982d89SJeremy L. Thompson 4737a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4747a982d89SJeremy L. Thompson 4757a982d89SJeremy L. Thompson @ref Backend 4767a982d89SJeremy L. Thompson **/ 4777a982d89SJeremy L. Thompson 478777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 479777ff853SJeremy L Thompson op->data = data; 480e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4817a982d89SJeremy L. Thompson } 4827a982d89SJeremy L. Thompson 4837a982d89SJeremy L. Thompson /** 48434359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 48534359f16Sjeremylt 48634359f16Sjeremylt @param op CeedOperator to increment the reference counter 48734359f16Sjeremylt 48834359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 48934359f16Sjeremylt 49034359f16Sjeremylt @ref Backend 49134359f16Sjeremylt **/ 4929560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 49334359f16Sjeremylt op->ref_count++; 49434359f16Sjeremylt return CEED_ERROR_SUCCESS; 49534359f16Sjeremylt } 49634359f16Sjeremylt 49734359f16Sjeremylt /** 4987a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 4997a982d89SJeremy L. Thompson 5007a982d89SJeremy L. Thompson @param op CeedOperator 5017a982d89SJeremy L. Thompson 5027a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5037a982d89SJeremy L. Thompson 5047a982d89SJeremy L. Thompson @ref Backend 5057a982d89SJeremy L. Thompson **/ 5067a982d89SJeremy L. Thompson 5077a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 508f04ea552SJeremy L Thompson op->is_backend_setup = true; 509e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5107a982d89SJeremy L. Thompson } 5117a982d89SJeremy L. Thompson 5127a982d89SJeremy L. Thompson /// @} 5137a982d89SJeremy L. Thompson 5147a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5157a982d89SJeremy L. Thompson /// CeedOperator Public API 5167a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5177a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 518dfdf5a53Sjeremylt /// @{ 519d7b241e6Sjeremylt 520d7b241e6Sjeremylt /** 5210219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 5220219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 5230219ea01SJeremy L Thompson \ref CeedOperatorSetField. 524d7b241e6Sjeremylt 525b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 526d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 52734138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 5284cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 529d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 5304cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 531b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 532b11c1e72Sjeremylt CeedOperator will be stored 533b11c1e72Sjeremylt 534b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 535dfdf5a53Sjeremylt 5367a982d89SJeremy L. Thompson @ref User 537d7b241e6Sjeremylt */ 538d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 539d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 540d7b241e6Sjeremylt int ierr; 541d7b241e6Sjeremylt 5425fe0d4faSjeremylt if (!ceed->OperatorCreate) { 5435fe0d4faSjeremylt Ceed delegate; 544aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 5455fe0d4faSjeremylt 5465fe0d4faSjeremylt if (!delegate) 547c042f62fSJeremy L Thompson // LCOV_EXCL_START 548e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 549e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 550c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 5515fe0d4faSjeremylt 5525fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 553e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5545fe0d4faSjeremylt } 5555fe0d4faSjeremylt 556b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 557b3b7035fSJeremy L Thompson // LCOV_EXCL_START 558e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 559e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 560b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 561d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 562d7b241e6Sjeremylt (*op)->ceed = ceed; 5639560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 564d1d35e2fSjeremylt (*op)->ref_count = 1; 565d7b241e6Sjeremylt (*op)->qf = qf; 5662b104005SJeremy L Thompson (*op)->input_size = -1; 5672b104005SJeremy L Thompson (*op)->output_size = -1; 5689560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 569442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 570d7b241e6Sjeremylt (*op)->dqf = dqf; 5719560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 572442e7f0bSjeremylt } 573442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 574d7b241e6Sjeremylt (*op)->dqfT = dqfT; 5759560d06aSjeremylt ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 576442e7f0bSjeremylt } 577480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled); 578480fae85SJeremy L Thompson CeedChk(ierr); 579bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr); 580bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr); 581d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 582e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 583d7b241e6Sjeremylt } 584d7b241e6Sjeremylt 585d7b241e6Sjeremylt /** 58652d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 58752d6035fSJeremy L Thompson 58852d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 58952d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 59052d6035fSJeremy L Thompson Composite CeedOperator will be stored 59152d6035fSJeremy L Thompson 59252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 59352d6035fSJeremy L Thompson 5947a982d89SJeremy L. Thompson @ref User 59552d6035fSJeremy L Thompson */ 59652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 59752d6035fSJeremy L Thompson int ierr; 59852d6035fSJeremy L Thompson 59952d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 60052d6035fSJeremy L Thompson Ceed delegate; 601aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 60252d6035fSJeremy L Thompson 603250756a7Sjeremylt if (delegate) { 60452d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 605e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 60652d6035fSJeremy L Thompson } 607250756a7Sjeremylt } 60852d6035fSJeremy L Thompson 60952d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 61052d6035fSJeremy L Thompson (*op)->ceed = ceed; 6119560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 612f04ea552SJeremy L Thompson (*op)->is_composite = true; 613bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr); 6142b104005SJeremy L Thompson (*op)->input_size = -1; 6152b104005SJeremy L Thompson (*op)->output_size = -1; 616250756a7Sjeremylt 617250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 61852d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 619250756a7Sjeremylt } 620e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 62152d6035fSJeremy L Thompson } 62252d6035fSJeremy L Thompson 62352d6035fSJeremy L Thompson /** 6249560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 6259560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 6269560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 6279560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 6289560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 6299560d06aSjeremylt reference to this CeedOperator. 6309560d06aSjeremylt 6319560d06aSjeremylt @param op CeedOperator to copy reference to 6329560d06aSjeremylt @param[out] op_copy Variable to store copied reference 6339560d06aSjeremylt 6349560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 6359560d06aSjeremylt 6369560d06aSjeremylt @ref User 6379560d06aSjeremylt **/ 6389560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 6399560d06aSjeremylt int ierr; 6409560d06aSjeremylt 6419560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 6429560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 6439560d06aSjeremylt *op_copy = op; 6449560d06aSjeremylt return CEED_ERROR_SUCCESS; 6459560d06aSjeremylt } 6469560d06aSjeremylt 6479560d06aSjeremylt /** 648b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 649d7b241e6Sjeremylt 650d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 651d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 652d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 653d7b241e6Sjeremylt 654d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 655d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 656d7b241e6Sjeremylt input and at most one active output. 657d7b241e6Sjeremylt 6588c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 659d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 6608795c945Sjeremylt CeedQFunction) 661b11c1e72Sjeremylt @param r CeedElemRestriction 6624cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 663b11c1e72Sjeremylt if collocated with quadrature points 6644cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 6654cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 6664cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 667b11c1e72Sjeremylt 668b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 669dfdf5a53Sjeremylt 6707a982d89SJeremy L. Thompson @ref User 671b11c1e72Sjeremylt **/ 672d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 673a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 674d7b241e6Sjeremylt int ierr; 675f04ea552SJeremy L Thompson if (op->is_composite) 676c042f62fSJeremy L Thompson // LCOV_EXCL_START 677e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 678e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 679c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 680f04ea552SJeremy L Thompson if (op->is_immutable) 681f04ea552SJeremy L Thompson // LCOV_EXCL_START 682f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 683f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 684f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 6858b067b84SJed Brown if (!r) 686c042f62fSJeremy L Thompson // LCOV_EXCL_START 687e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 688c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 689d1d35e2fSjeremylt field_name); 690c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6918b067b84SJed Brown if (!b) 692c042f62fSJeremy L Thompson // LCOV_EXCL_START 693e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 694e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 695d1d35e2fSjeremylt field_name); 696c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6978b067b84SJed Brown if (!v) 698c042f62fSJeremy L Thompson // LCOV_EXCL_START 699e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 700e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 701d1d35e2fSjeremylt field_name); 702c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 70352d6035fSJeremy L Thompson 704d1d35e2fSjeremylt CeedInt num_elem; 705d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 706d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 707d1d35e2fSjeremylt op->num_elem != num_elem) 708c042f62fSJeremy L Thompson // LCOV_EXCL_START 709e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 7101d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 711d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 712c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 713d7b241e6Sjeremylt 71478464608Sjeremylt CeedInt num_qpts = 0; 715e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 716d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 717d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 718c042f62fSJeremy L Thompson // LCOV_EXCL_START 719e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 720e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 721d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 722d1d35e2fSjeremylt op->num_qpts); 723c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 724d7b241e6Sjeremylt } 725d1d35e2fSjeremylt CeedQFunctionField qf_field; 726d1d35e2fSjeremylt CeedOperatorField *op_field; 7272b104005SJeremy L Thompson bool is_input = true; 728d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 729d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 730d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 731d1d35e2fSjeremylt op_field = &op->input_fields[i]; 732d7b241e6Sjeremylt goto found; 733d7b241e6Sjeremylt } 734d7b241e6Sjeremylt } 7352b104005SJeremy L Thompson is_input = false; 736d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 737d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 738d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 739d1d35e2fSjeremylt op_field = &op->output_fields[i]; 740d7b241e6Sjeremylt goto found; 741d7b241e6Sjeremylt } 742d7b241e6Sjeremylt } 743c042f62fSJeremy L Thompson // LCOV_EXCL_START 744e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 745e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 746d1d35e2fSjeremylt field_name); 747c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 748d7b241e6Sjeremylt found: 749d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 750d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 751e15f9bd0SJeremy L Thompson 7522b104005SJeremy L Thompson if (v == CEED_VECTOR_ACTIVE) { 7532b104005SJeremy L Thompson CeedSize l_size; 7542b104005SJeremy L Thompson ierr = CeedElemRestrictionGetLVectorSize(r, &l_size); CeedChk(ierr); 7552b104005SJeremy L Thompson if (is_input) { 7562b104005SJeremy L Thompson if (op->input_size == -1) op->input_size = l_size; 7572b104005SJeremy L Thompson if (l_size != op->input_size) 7582b104005SJeremy L Thompson // LCOV_EXCL_START 7592b104005SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 7602b104005SJeremy L Thompson "LVector size %td does not match previous size %td", 7612b104005SJeremy L Thompson l_size, op->input_size); 7622b104005SJeremy L Thompson // LCOV_EXCL_STOP 7632b104005SJeremy L Thompson } else { 7642b104005SJeremy L Thompson if (op->output_size == -1) op->output_size = l_size; 7652b104005SJeremy L Thompson if (l_size != op->output_size) 7662b104005SJeremy L Thompson // LCOV_EXCL_START 7672b104005SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 7682b104005SJeremy L Thompson "LVector size %td does not match previous size %td", 7692b104005SJeremy L Thompson l_size, op->output_size); 7702b104005SJeremy L Thompson // LCOV_EXCL_STOP 7712b104005SJeremy L Thompson } 7722b104005SJeremy L Thompson } 7732b104005SJeremy L Thompson 774d1d35e2fSjeremylt (*op_field)->vec = v; 775e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 7769560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 777e15f9bd0SJeremy L Thompson } 778e15f9bd0SJeremy L Thompson 779d1d35e2fSjeremylt (*op_field)->elem_restr = r; 7809560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 781e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 782d1d35e2fSjeremylt op->num_elem = num_elem; 783d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 784e15f9bd0SJeremy L Thompson } 785d99fa3c5SJeremy L Thompson 786d1d35e2fSjeremylt (*op_field)->basis = b; 787e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 788cd4dfc48Sjeremylt if (!op->num_qpts) { 789cd4dfc48Sjeremylt ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 790cd4dfc48Sjeremylt } 7919560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 792e15f9bd0SJeremy L Thompson } 793e15f9bd0SJeremy L Thompson 794d1d35e2fSjeremylt op->num_fields += 1; 795f7e22acaSJeremy L Thompson ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name); 796f7e22acaSJeremy L Thompson CeedChk(ierr); 797e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 798d7b241e6Sjeremylt } 799d7b241e6Sjeremylt 800d7b241e6Sjeremylt /** 80143bbe138SJeremy L Thompson @brief Get the CeedOperatorFields of a CeedOperator 80243bbe138SJeremy L Thompson 803f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 804f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 805f04ea552SJeremy L Thompson 80643bbe138SJeremy L Thompson @param op CeedOperator 807f74ec584SJeremy L Thompson @param[out] num_input_fields Variable to store number of input fields 80843bbe138SJeremy L Thompson @param[out] input_fields Variable to store input_fields 809f74ec584SJeremy L Thompson @param[out] num_output_fields Variable to store number of output fields 81043bbe138SJeremy L Thompson @param[out] output_fields Variable to store output_fields 81143bbe138SJeremy L Thompson 81243bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 81343bbe138SJeremy L Thompson 814e9b533fbSJeremy L Thompson @ref Advanced 81543bbe138SJeremy L Thompson **/ 81643bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields, 81743bbe138SJeremy L Thompson CeedOperatorField **input_fields, 81843bbe138SJeremy L Thompson CeedInt *num_output_fields, 81943bbe138SJeremy L Thompson CeedOperatorField **output_fields) { 820f04ea552SJeremy L Thompson int ierr; 821f04ea552SJeremy L Thompson 822f04ea552SJeremy L Thompson if (op->is_composite) 82343bbe138SJeremy L Thompson // LCOV_EXCL_START 82443bbe138SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 82543bbe138SJeremy L Thompson "Not defined for composite operator"); 82643bbe138SJeremy L Thompson // LCOV_EXCL_STOP 827f04ea552SJeremy L Thompson ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 82843bbe138SJeremy L Thompson 82943bbe138SJeremy L Thompson if (num_input_fields) *num_input_fields = op->qf->num_input_fields; 83043bbe138SJeremy L Thompson if (input_fields) *input_fields = op->input_fields; 83143bbe138SJeremy L Thompson if (num_output_fields) *num_output_fields = op->qf->num_output_fields; 83243bbe138SJeremy L Thompson if (output_fields) *output_fields = op->output_fields; 83343bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 83443bbe138SJeremy L Thompson } 83543bbe138SJeremy L Thompson 83643bbe138SJeremy L Thompson /** 83728567f8fSJeremy L Thompson @brief Get the name of a CeedOperatorField 83828567f8fSJeremy L Thompson 83928567f8fSJeremy L Thompson @param op_field CeedOperatorField 84028567f8fSJeremy L Thompson @param[out] field_name Variable to store the field name 84128567f8fSJeremy L Thompson 84228567f8fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 84328567f8fSJeremy L Thompson 844e9b533fbSJeremy L Thompson @ref Advanced 84528567f8fSJeremy L Thompson **/ 84628567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) { 84728567f8fSJeremy L Thompson *field_name = (char *)op_field->field_name; 84828567f8fSJeremy L Thompson return CEED_ERROR_SUCCESS; 84928567f8fSJeremy L Thompson } 85028567f8fSJeremy L Thompson 85128567f8fSJeremy L Thompson /** 85243bbe138SJeremy L Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 85343bbe138SJeremy L Thompson 85443bbe138SJeremy L Thompson @param op_field CeedOperatorField 85543bbe138SJeremy L Thompson @param[out] rstr Variable to store CeedElemRestriction 85643bbe138SJeremy L Thompson 85743bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 85843bbe138SJeremy L Thompson 859e9b533fbSJeremy L Thompson @ref Advanced 86043bbe138SJeremy L Thompson **/ 86143bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 86243bbe138SJeremy L Thompson CeedElemRestriction *rstr) { 86343bbe138SJeremy L Thompson *rstr = op_field->elem_restr; 86443bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 86543bbe138SJeremy L Thompson } 86643bbe138SJeremy L Thompson 86743bbe138SJeremy L Thompson /** 86843bbe138SJeremy L Thompson @brief Get the CeedBasis of a CeedOperatorField 86943bbe138SJeremy L Thompson 87043bbe138SJeremy L Thompson @param op_field CeedOperatorField 87143bbe138SJeremy L Thompson @param[out] basis Variable to store CeedBasis 87243bbe138SJeremy L Thompson 87343bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 87443bbe138SJeremy L Thompson 875e9b533fbSJeremy L Thompson @ref Advanced 87643bbe138SJeremy L Thompson **/ 87743bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 87843bbe138SJeremy L Thompson *basis = op_field->basis; 87943bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 88043bbe138SJeremy L Thompson } 88143bbe138SJeremy L Thompson 88243bbe138SJeremy L Thompson /** 88343bbe138SJeremy L Thompson @brief Get the CeedVector of a CeedOperatorField 88443bbe138SJeremy L Thompson 88543bbe138SJeremy L Thompson @param op_field CeedOperatorField 88643bbe138SJeremy L Thompson @param[out] vec Variable to store CeedVector 88743bbe138SJeremy L Thompson 88843bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 88943bbe138SJeremy L Thompson 890e9b533fbSJeremy L Thompson @ref Advanced 89143bbe138SJeremy L Thompson **/ 89243bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 89343bbe138SJeremy L Thompson *vec = op_field->vec; 89443bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 89543bbe138SJeremy L Thompson } 89643bbe138SJeremy L Thompson 89743bbe138SJeremy L Thompson /** 89852d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 899288c0443SJeremy L Thompson 900d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 901d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 90252d6035fSJeremy L Thompson 90352d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 90452d6035fSJeremy L Thompson 9057a982d89SJeremy L. Thompson @ref User 90652d6035fSJeremy L Thompson */ 907d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 908d1d35e2fSjeremylt CeedOperator sub_op) { 90934359f16Sjeremylt int ierr; 91034359f16Sjeremylt 911f04ea552SJeremy L Thompson if (!composite_op->is_composite) 912c042f62fSJeremy L Thompson // LCOV_EXCL_START 913d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 914e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 915c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 91652d6035fSJeremy L Thompson 917d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 918c042f62fSJeremy L Thompson // LCOV_EXCL_START 919d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 9202b104005SJeremy L Thompson "Cannot add additional sub-operators"); 921c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 922f04ea552SJeremy L Thompson if (composite_op->is_immutable) 923f04ea552SJeremy L Thompson // LCOV_EXCL_START 924f04ea552SJeremy L Thompson return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 925f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 926f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 92752d6035fSJeremy L Thompson 9282b104005SJeremy L Thompson { 9292b104005SJeremy L Thompson CeedSize input_size, output_size; 9302b104005SJeremy L Thompson ierr = CeedOperatorGetActiveVectorLengths(sub_op, &input_size, &output_size); 9312b104005SJeremy L Thompson CeedChk(ierr); 9322b104005SJeremy L Thompson if (composite_op->input_size == -1) composite_op->input_size = input_size; 9332b104005SJeremy L Thompson if (composite_op->output_size == -1) composite_op->output_size = output_size; 9342b104005SJeremy L Thompson // Note, a size of -1 means no active vector restriction set, so no incompatibility 9352b104005SJeremy L Thompson if ((input_size != -1 && input_size != composite_op->input_size) || 9362b104005SJeremy L Thompson (output_size != -1 && output_size != composite_op->output_size)) 9372b104005SJeremy L Thompson // LCOV_EXCL_START 9382b104005SJeremy L Thompson return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 9392b104005SJeremy L Thompson "Sub-operators must have compatible dimensions; " 9402b104005SJeremy L Thompson "composite operator of shape (%td, %td) not compatible with " 9412b104005SJeremy L Thompson "sub-operator of shape (%td, %td)", 9422b104005SJeremy L Thompson composite_op->input_size, composite_op->output_size, input_size, output_size); 9432b104005SJeremy L Thompson // LCOV_EXCL_STOP 9442b104005SJeremy L Thompson } 9452b104005SJeremy L Thompson 946d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 9479560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 948d1d35e2fSjeremylt composite_op->num_suboperators++; 949e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 95052d6035fSJeremy L Thompson } 95152d6035fSJeremy L Thompson 95252d6035fSJeremy L Thompson /** 9534db537f9SJeremy L Thompson @brief Check if a CeedOperator is ready to be used. 9544db537f9SJeremy L Thompson 9554db537f9SJeremy L Thompson @param[in] op CeedOperator to check 9564db537f9SJeremy L Thompson 9574db537f9SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9584db537f9SJeremy L Thompson 9594db537f9SJeremy L Thompson @ref User 9604db537f9SJeremy L Thompson **/ 9614db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) { 9624db537f9SJeremy L Thompson int ierr; 9634db537f9SJeremy L Thompson Ceed ceed; 9644db537f9SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 9654db537f9SJeremy L Thompson 9664db537f9SJeremy L Thompson if (op->is_interface_setup) 9674db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 9684db537f9SJeremy L Thompson 9694db537f9SJeremy L Thompson CeedQFunction qf = op->qf; 9704db537f9SJeremy L Thompson if (op->is_composite) { 9714db537f9SJeremy L Thompson if (!op->num_suboperators) 9724db537f9SJeremy L Thompson // LCOV_EXCL_START 9734db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 9744db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9754db537f9SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 9764db537f9SJeremy L Thompson ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr); 9774db537f9SJeremy L Thompson } 9782b104005SJeremy L Thompson // Sub-operators could be modified after adding to composite operator 9792b104005SJeremy L Thompson // Need to verify no lvec incompatibility from any changes 9802b104005SJeremy L Thompson CeedSize input_size, output_size; 9812b104005SJeremy L Thompson ierr = CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size); 9822b104005SJeremy L Thompson CeedChk(ierr); 9834db537f9SJeremy L Thompson } else { 9844db537f9SJeremy L Thompson if (op->num_fields == 0) 9854db537f9SJeremy L Thompson // LCOV_EXCL_START 9864db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 9874db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9884db537f9SJeremy L Thompson if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 9894db537f9SJeremy L Thompson // LCOV_EXCL_START 9904db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 9914db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9924db537f9SJeremy L Thompson if (!op->has_restriction) 9934db537f9SJeremy L Thompson // LCOV_EXCL_START 9944db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 9954db537f9SJeremy L Thompson "At least one restriction required"); 9964db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9974db537f9SJeremy L Thompson if (op->num_qpts == 0) 9984db537f9SJeremy L Thompson // LCOV_EXCL_START 9994db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 10004db537f9SJeremy L Thompson "At least one non-collocated basis is required " 10014db537f9SJeremy L Thompson "or the number of quadrature points must be set"); 10024db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10034db537f9SJeremy L Thompson } 10044db537f9SJeremy L Thompson 10054db537f9SJeremy L Thompson // Flag as immutable and ready 10064db537f9SJeremy L Thompson op->is_interface_setup = true; 10074db537f9SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 10084db537f9SJeremy L Thompson // LCOV_EXCL_START 10094db537f9SJeremy L Thompson op->qf->is_immutable = true; 10104db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10114db537f9SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 10124db537f9SJeremy L Thompson // LCOV_EXCL_START 10134db537f9SJeremy L Thompson op->dqf->is_immutable = true; 10144db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10154db537f9SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 10164db537f9SJeremy L Thompson // LCOV_EXCL_START 10174db537f9SJeremy L Thompson op->dqfT->is_immutable = true; 10184db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10194db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 10204db537f9SJeremy L Thompson } 10214db537f9SJeremy L Thompson 10224db537f9SJeremy L Thompson /** 1023c9366a6bSJeremy L Thompson @brief Get vector lengths for the active input and/or output vectors of a CeedOperator. 1024c9366a6bSJeremy L Thompson Note: Lengths of -1 indicate that the CeedOperator does not have an 1025c9366a6bSJeremy L Thompson active input and/or output. 1026c9366a6bSJeremy L Thompson 1027c9366a6bSJeremy L Thompson @param[in] op CeedOperator 1028c9366a6bSJeremy L Thompson @param[out] input_size Variable to store active input vector length, or NULL 1029c9366a6bSJeremy L Thompson @param[out] output_size Variable to store active output vector length, or NULL 1030c9366a6bSJeremy L Thompson 1031c9366a6bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1032c9366a6bSJeremy L Thompson 1033c9366a6bSJeremy L Thompson @ref User 1034c9366a6bSJeremy L Thompson **/ 1035c9366a6bSJeremy L Thompson int CeedOperatorGetActiveVectorLengths(CeedOperator op, CeedSize *input_size, 1036c9366a6bSJeremy L Thompson CeedSize *output_size) { 1037c9366a6bSJeremy L Thompson int ierr; 1038c9366a6bSJeremy L Thompson bool is_composite; 1039c9366a6bSJeremy L Thompson 10402b104005SJeremy L Thompson if (input_size) *input_size = op->input_size; 10412b104005SJeremy L Thompson if (output_size) *output_size = op->output_size; 1042c9366a6bSJeremy L Thompson 1043c9366a6bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 10442b104005SJeremy L Thompson if (is_composite && (op->input_size == -1 || op->output_size == -1)) { 1045c9366a6bSJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1046c9366a6bSJeremy L Thompson CeedSize sub_input_size, sub_output_size; 1047c9366a6bSJeremy L Thompson ierr = CeedOperatorGetActiveVectorLengths(op->sub_operators[i], 10482b104005SJeremy L Thompson &sub_input_size, &sub_output_size); CeedChk(ierr); 10492b104005SJeremy L Thompson if (op->input_size == -1) op->input_size = sub_input_size; 10502b104005SJeremy L Thompson if (op->output_size == -1) op->output_size = sub_output_size; 10512b104005SJeremy L Thompson // Note, a size of -1 means no active vector restriction set, so no incompatibility 10522b104005SJeremy L Thompson if ((sub_input_size != -1 && sub_input_size != op->input_size) || 10532b104005SJeremy L Thompson (sub_output_size != -1 && sub_output_size != op->output_size)) 10542b104005SJeremy L Thompson // LCOV_EXCL_START 10552b104005SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 10562b104005SJeremy L Thompson "Sub-operators must have compatible dimensions; " 10572b104005SJeremy L Thompson "composite operator of shape (%td, %td) not compatible with " 10582b104005SJeremy L Thompson "sub-operator of shape (%td, %td)", 10592b104005SJeremy L Thompson op->input_size, op->output_size, input_size, output_size); 10602b104005SJeremy L Thompson // LCOV_EXCL_STOP 1061c9366a6bSJeremy L Thompson } 1062c9366a6bSJeremy L Thompson } 1063c9366a6bSJeremy L Thompson 1064c9366a6bSJeremy L Thompson return CEED_ERROR_SUCCESS; 1065c9366a6bSJeremy L Thompson } 1066c9366a6bSJeremy L Thompson 1067c9366a6bSJeremy L Thompson /** 1068beecbf24SJeremy L Thompson @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions. 1069beecbf24SJeremy L Thompson When `reuse_assembly_data = false` (default), the CeedQFunction associated 1070beecbf24SJeremy L Thompson with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*` 1071beecbf24SJeremy L Thompson function is called. 1072beecbf24SJeremy L Thompson When `reuse_assembly_data = true`, the CeedQFunction associated with 1073beecbf24SJeremy L Thompson this CeedOperator is reused between calls to 1074beecbf24SJeremy L Thompson `CeedOperatorSetQFunctionAssemblyDataUpdated`. 10758b919e6bSJeremy L Thompson 1076beecbf24SJeremy L Thompson @param[in] op CeedOperator 1077beecbf24SJeremy L Thompson @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 10788b919e6bSJeremy L Thompson 10798b919e6bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10808b919e6bSJeremy L Thompson 10818b919e6bSJeremy L Thompson @ref Advanced 10828b919e6bSJeremy L Thompson **/ 1083beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, 1084beecbf24SJeremy L Thompson bool reuse_assembly_data) { 10858b919e6bSJeremy L Thompson int ierr; 10868b919e6bSJeremy L Thompson bool is_composite; 10878b919e6bSJeremy L Thompson 10888b919e6bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 10898b919e6bSJeremy L Thompson if (is_composite) { 10908b919e6bSJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1091beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], 1092beecbf24SJeremy L Thompson reuse_assembly_data); CeedChk(ierr); 10938b919e6bSJeremy L Thompson } 10948b919e6bSJeremy L Thompson } else { 1095beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data); 1096beecbf24SJeremy L Thompson CeedChk(ierr); 1097beecbf24SJeremy L Thompson } 1098beecbf24SJeremy L Thompson 1099beecbf24SJeremy L Thompson return CEED_ERROR_SUCCESS; 1100beecbf24SJeremy L Thompson } 1101beecbf24SJeremy L Thompson 1102beecbf24SJeremy L Thompson /** 1103beecbf24SJeremy L Thompson @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly. 1104beecbf24SJeremy L Thompson 1105beecbf24SJeremy L Thompson @param[in] op CeedOperator 1106*6e15d496SJeremy L Thompson @param[in] needs_data_update Boolean flag setting assembly data reuse 1107beecbf24SJeremy L Thompson 1108beecbf24SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1109beecbf24SJeremy L Thompson 1110beecbf24SJeremy L Thompson @ref Advanced 1111beecbf24SJeremy L Thompson **/ 1112beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, 1113beecbf24SJeremy L Thompson bool needs_data_update) { 1114beecbf24SJeremy L Thompson int ierr; 1115beecbf24SJeremy L Thompson bool is_composite; 1116beecbf24SJeremy L Thompson 1117beecbf24SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1118beecbf24SJeremy L Thompson if (is_composite) { 1119beecbf24SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1120beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i], 1121beecbf24SJeremy L Thompson needs_data_update); CeedChk(ierr); 1122beecbf24SJeremy L Thompson } 1123beecbf24SJeremy L Thompson } else { 1124beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled, 1125beecbf24SJeremy L Thompson needs_data_update); 11268b919e6bSJeremy L Thompson CeedChk(ierr); 11278b919e6bSJeremy L Thompson } 11288b919e6bSJeremy L Thompson 11298b919e6bSJeremy L Thompson return CEED_ERROR_SUCCESS; 11308b919e6bSJeremy L Thompson } 11318b919e6bSJeremy L Thompson 11328b919e6bSJeremy L Thompson /** 1133cd4dfc48Sjeremylt @brief Set the number of quadrature points associated with a CeedOperator. 1134cd4dfc48Sjeremylt This should be used when creating a CeedOperator where every 1135cd4dfc48Sjeremylt field has a collocated basis. This function cannot be used for 1136cd4dfc48Sjeremylt composite CeedOperators. 1137cd4dfc48Sjeremylt 1138cd4dfc48Sjeremylt @param op CeedOperator 1139cd4dfc48Sjeremylt @param num_qpts Number of quadrature points to set 1140cd4dfc48Sjeremylt 1141cd4dfc48Sjeremylt @return An error code: 0 - success, otherwise - failure 1142cd4dfc48Sjeremylt 1143e9b533fbSJeremy L Thompson @ref Advanced 1144cd4dfc48Sjeremylt **/ 1145cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 1146f04ea552SJeremy L Thompson if (op->is_composite) 1147cd4dfc48Sjeremylt // LCOV_EXCL_START 1148cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1149cd4dfc48Sjeremylt "Not defined for composite operator"); 1150cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1151cd4dfc48Sjeremylt if (op->num_qpts) 1152cd4dfc48Sjeremylt // LCOV_EXCL_START 1153cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1154cd4dfc48Sjeremylt "Number of quadrature points already defined"); 1155cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1156f04ea552SJeremy L Thompson if (op->is_immutable) 1157f04ea552SJeremy L Thompson // LCOV_EXCL_START 1158f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 1159f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 1160f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 1161cd4dfc48Sjeremylt 1162cd4dfc48Sjeremylt op->num_qpts = num_qpts; 1163cd4dfc48Sjeremylt return CEED_ERROR_SUCCESS; 1164cd4dfc48Sjeremylt } 1165cd4dfc48Sjeremylt 1166cd4dfc48Sjeremylt /** 11677a982d89SJeremy L. Thompson @brief View a CeedOperator 11687a982d89SJeremy L. Thompson 11697a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 11707a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 11717a982d89SJeremy L. Thompson 11727a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 11737a982d89SJeremy L. Thompson 11747a982d89SJeremy L. Thompson @ref User 11757a982d89SJeremy L. Thompson **/ 11767a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 11777a982d89SJeremy L. Thompson int ierr; 11787a982d89SJeremy L. Thompson 1179f04ea552SJeremy L Thompson if (op->is_composite) { 11807a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 11817a982d89SJeremy L. Thompson 1182d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 11837a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 1184d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 11857a982d89SJeremy L. Thompson CeedChk(ierr); 11867a982d89SJeremy L. Thompson } 11877a982d89SJeremy L. Thompson } else { 11887a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 11897a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 11907a982d89SJeremy L. Thompson } 1191e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11927a982d89SJeremy L. Thompson } 11933bd813ffSjeremylt 11943bd813ffSjeremylt /** 1195b7c9bbdaSJeremy L Thompson @brief Get the Ceed associated with a CeedOperator 1196b7c9bbdaSJeremy L Thompson 1197b7c9bbdaSJeremy L Thompson @param op CeedOperator 1198b7c9bbdaSJeremy L Thompson @param[out] ceed Variable to store Ceed 1199b7c9bbdaSJeremy L Thompson 1200b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1201b7c9bbdaSJeremy L Thompson 1202b7c9bbdaSJeremy L Thompson @ref Advanced 1203b7c9bbdaSJeremy L Thompson **/ 1204b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1205b7c9bbdaSJeremy L Thompson *ceed = op->ceed; 1206b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1207b7c9bbdaSJeremy L Thompson } 1208b7c9bbdaSJeremy L Thompson 1209b7c9bbdaSJeremy L Thompson /** 1210b7c9bbdaSJeremy L Thompson @brief Get the number of elements associated with a CeedOperator 1211b7c9bbdaSJeremy L Thompson 1212b7c9bbdaSJeremy L Thompson @param op CeedOperator 1213b7c9bbdaSJeremy L Thompson @param[out] num_elem Variable to store number of elements 1214b7c9bbdaSJeremy L Thompson 1215b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1216b7c9bbdaSJeremy L Thompson 1217b7c9bbdaSJeremy L Thompson @ref Advanced 1218b7c9bbdaSJeremy L Thompson **/ 1219b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 1220b7c9bbdaSJeremy L Thompson if (op->is_composite) 1221b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1222b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1223b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1224b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1225b7c9bbdaSJeremy L Thompson 1226b7c9bbdaSJeremy L Thompson *num_elem = op->num_elem; 1227b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1228b7c9bbdaSJeremy L Thompson } 1229b7c9bbdaSJeremy L Thompson 1230b7c9bbdaSJeremy L Thompson /** 1231b7c9bbdaSJeremy L Thompson @brief Get the number of quadrature points associated with a CeedOperator 1232b7c9bbdaSJeremy L Thompson 1233b7c9bbdaSJeremy L Thompson @param op CeedOperator 1234b7c9bbdaSJeremy L Thompson @param[out] num_qpts Variable to store vector number of quadrature points 1235b7c9bbdaSJeremy L Thompson 1236b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1237b7c9bbdaSJeremy L Thompson 1238b7c9bbdaSJeremy L Thompson @ref Advanced 1239b7c9bbdaSJeremy L Thompson **/ 1240b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 1241b7c9bbdaSJeremy L Thompson if (op->is_composite) 1242b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1243b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1244b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1245b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1246b7c9bbdaSJeremy L Thompson 1247b7c9bbdaSJeremy L Thompson *num_qpts = op->num_qpts; 1248b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1249b7c9bbdaSJeremy L Thompson } 1250b7c9bbdaSJeremy L Thompson 1251b7c9bbdaSJeremy L Thompson /** 1252*6e15d496SJeremy L Thompson @brief Estimate number of FLOPs required to apply CeedOperator on the active vector 1253*6e15d496SJeremy L Thompson 1254*6e15d496SJeremy L Thompson @param op Operator to estimate FLOPs for 1255*6e15d496SJeremy L Thompson @param flops Address of variable to hold FLOPs estimate 1256*6e15d496SJeremy L Thompson 1257*6e15d496SJeremy L Thompson @ref Backend 1258*6e15d496SJeremy L Thompson **/ 1259*6e15d496SJeremy L Thompson int CeedOperatorGetFlopsEstimate(CeedOperator op, CeedInt *flops) { 1260*6e15d496SJeremy L Thompson int ierr; 1261*6e15d496SJeremy L Thompson bool is_composite; 1262*6e15d496SJeremy L Thompson ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1263*6e15d496SJeremy L Thompson 1264*6e15d496SJeremy L Thompson *flops = 0; 1265*6e15d496SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1266*6e15d496SJeremy L Thompson if (is_composite) { 1267*6e15d496SJeremy L Thompson CeedInt num_suboperators; 1268*6e15d496SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1269*6e15d496SJeremy L Thompson CeedOperator *sub_operators; 1270*6e15d496SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1271*6e15d496SJeremy L Thompson 1272*6e15d496SJeremy L Thompson // FLOPs for each suboperator 1273*6e15d496SJeremy L Thompson for (CeedInt i = 0; i < num_suboperators; i++) { 1274*6e15d496SJeremy L Thompson CeedInt suboperator_flops; 1275*6e15d496SJeremy L Thompson ierr = CeedOperatorGetFlopsEstimate(sub_operators[i], &suboperator_flops); 1276*6e15d496SJeremy L Thompson CeedChk(ierr); 1277*6e15d496SJeremy L Thompson *flops += suboperator_flops; 1278*6e15d496SJeremy L Thompson } 1279*6e15d496SJeremy L Thompson } else { 1280*6e15d496SJeremy L Thompson CeedInt num_input_fields, num_output_fields; 1281*6e15d496SJeremy L Thompson CeedOperatorField *input_fields, *output_fields; 1282*6e15d496SJeremy L Thompson 1283*6e15d496SJeremy L Thompson ierr = CeedOperatorGetFields(op, &num_input_fields, &input_fields, 1284*6e15d496SJeremy L Thompson &num_output_fields, &output_fields); CeedChk(ierr); 1285*6e15d496SJeremy L Thompson 1286*6e15d496SJeremy L Thompson CeedInt num_elem = 0; 1287*6e15d496SJeremy L Thompson ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChk(ierr); 1288*6e15d496SJeremy L Thompson // Input FLOPs 1289*6e15d496SJeremy L Thompson for (CeedInt i = 0; i < num_input_fields; i++) { 1290*6e15d496SJeremy L Thompson if (input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 1291*6e15d496SJeremy L Thompson CeedInt restr_flops, basis_flops; 1292*6e15d496SJeremy L Thompson 1293*6e15d496SJeremy L Thompson ierr = CeedElemRestrictionGetFlopsEstimate(input_fields[i]->elem_restr, 1294*6e15d496SJeremy L Thompson CEED_NOTRANSPOSE, &restr_flops); CeedChk(ierr); 1295*6e15d496SJeremy L Thompson *flops += restr_flops; 1296*6e15d496SJeremy L Thompson ierr = CeedBasisGetFlopsEstimate(input_fields[i]->basis, CEED_NOTRANSPOSE, 1297*6e15d496SJeremy L Thompson op->qf->input_fields[i]->eval_mode, &basis_flops); CeedChk(ierr); 1298*6e15d496SJeremy L Thompson *flops += basis_flops * num_elem; 1299*6e15d496SJeremy L Thompson } 1300*6e15d496SJeremy L Thompson } 1301*6e15d496SJeremy L Thompson // QF FLOPs 1302*6e15d496SJeremy L Thompson CeedInt num_qpts, qf_flops; 1303*6e15d496SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &num_qpts); CeedChk(ierr); 1304*6e15d496SJeremy L Thompson ierr = CeedQFunctionGetFlopsEstimate(op->qf, &qf_flops); CeedChk(ierr); 1305*6e15d496SJeremy L Thompson *flops += num_elem * num_qpts * qf_flops; 1306*6e15d496SJeremy L Thompson // Output FLOPs 1307*6e15d496SJeremy L Thompson for (CeedInt i = 0; i < num_output_fields; i++) { 1308*6e15d496SJeremy L Thompson if (output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 1309*6e15d496SJeremy L Thompson CeedInt restr_flops, basis_flops; 1310*6e15d496SJeremy L Thompson 1311*6e15d496SJeremy L Thompson ierr = CeedElemRestrictionGetFlopsEstimate(output_fields[i]->elem_restr, 1312*6e15d496SJeremy L Thompson CEED_TRANSPOSE, &restr_flops); CeedChk(ierr); 1313*6e15d496SJeremy L Thompson *flops += restr_flops; 1314*6e15d496SJeremy L Thompson ierr = CeedBasisGetFlopsEstimate(output_fields[i]->basis, CEED_TRANSPOSE, 1315*6e15d496SJeremy L Thompson op->qf->output_fields[i]->eval_mode, &basis_flops); CeedChk(ierr); 1316*6e15d496SJeremy L Thompson *flops += basis_flops * num_elem; 1317*6e15d496SJeremy L Thompson } 1318*6e15d496SJeremy L Thompson } 1319*6e15d496SJeremy L Thompson } 1320*6e15d496SJeremy L Thompson 1321*6e15d496SJeremy L Thompson return CEED_ERROR_SUCCESS; 1322*6e15d496SJeremy L Thompson } 1323*6e15d496SJeremy L Thompson 1324*6e15d496SJeremy L Thompson /** 13253668ca4bSJeremy L Thompson @brief Get label for a registered QFunctionContext field, or `NULL` if no 13263668ca4bSJeremy L Thompson field has been registered with this `field_name`. 13273668ca4bSJeremy L Thompson 13283668ca4bSJeremy L Thompson @param[in] op CeedOperator 13293668ca4bSJeremy L Thompson @param[in] field_name Name of field to retrieve label 13303668ca4bSJeremy L Thompson @param[out] field_label Variable to field label 13313668ca4bSJeremy L Thompson 13323668ca4bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13333668ca4bSJeremy L Thompson 13343668ca4bSJeremy L Thompson @ref User 13353668ca4bSJeremy L Thompson **/ 13363668ca4bSJeremy L Thompson int CeedOperatorContextGetFieldLabel(CeedOperator op, 13373668ca4bSJeremy L Thompson const char *field_name, 13383668ca4bSJeremy L Thompson CeedContextFieldLabel *field_label) { 13393668ca4bSJeremy L Thompson int ierr; 13403668ca4bSJeremy L Thompson 13413668ca4bSJeremy L Thompson bool is_composite; 13423668ca4bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 13433668ca4bSJeremy L Thompson if (is_composite) { 13443668ca4bSJeremy L Thompson // Check if composite label already created 13453668ca4bSJeremy L Thompson for (CeedInt i=0; i<op->num_context_labels; i++) { 13463668ca4bSJeremy L Thompson if (!strcmp(op->context_labels[i]->name, field_name)) { 13473668ca4bSJeremy L Thompson *field_label = op->context_labels[i]; 13483668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 13493668ca4bSJeremy L Thompson } 13503668ca4bSJeremy L Thompson } 13513668ca4bSJeremy L Thompson 13523668ca4bSJeremy L Thompson // Create composite label if needed 13533668ca4bSJeremy L Thompson CeedInt num_sub; 13543668ca4bSJeremy L Thompson CeedOperator *sub_operators; 13553668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label; 13563668ca4bSJeremy L Thompson 13573668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr); 13583668ca4bSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 13593668ca4bSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 13603668ca4bSJeremy L Thompson ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr); 13613668ca4bSJeremy L Thompson new_field_label->num_sub_labels = num_sub; 13623668ca4bSJeremy L Thompson 13633668ca4bSJeremy L Thompson bool label_found = false; 13643668ca4bSJeremy L Thompson for (CeedInt i=0; i<num_sub; i++) { 13653668ca4bSJeremy L Thompson if (sub_operators[i]->qf->ctx) { 13663668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label_i; 13673668ca4bSJeremy L Thompson ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, 13683668ca4bSJeremy L Thompson &new_field_label_i); CeedChk(ierr); 13693668ca4bSJeremy L Thompson if (new_field_label_i) { 13703668ca4bSJeremy L Thompson label_found = true; 13713668ca4bSJeremy L Thompson new_field_label->sub_labels[i] = new_field_label_i; 13723668ca4bSJeremy L Thompson new_field_label->name = new_field_label_i->name; 13733668ca4bSJeremy L Thompson new_field_label->description = new_field_label_i->description; 13747bfe0f0eSJeremy L Thompson if (new_field_label->type && 13757bfe0f0eSJeremy L Thompson new_field_label->type != new_field_label_i->type) { 13767bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 13777bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 13787bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 13797bfe0f0eSJeremy L Thompson "Incompatible field types on sub-operator contexts. " 13807bfe0f0eSJeremy L Thompson "%s != %s", 13817bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label->type], 13827bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label_i->type]); 13837bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 13847bfe0f0eSJeremy L Thompson } else { 13857bfe0f0eSJeremy L Thompson new_field_label->type = new_field_label_i->type; 13867bfe0f0eSJeremy L Thompson } 13877bfe0f0eSJeremy L Thompson if (new_field_label->num_values != 0 && 13887bfe0f0eSJeremy L Thompson new_field_label->num_values != new_field_label_i->num_values) { 13897bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 13907bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 13917bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 13927bfe0f0eSJeremy L Thompson "Incompatible field number of values on sub-operator" 13937bfe0f0eSJeremy L Thompson " contexts. %ld != %ld", 13947bfe0f0eSJeremy L Thompson new_field_label->num_values, new_field_label_i->num_values); 13957bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 13967bfe0f0eSJeremy L Thompson } else { 13977bfe0f0eSJeremy L Thompson new_field_label->num_values = new_field_label_i->num_values; 13987bfe0f0eSJeremy L Thompson } 13993668ca4bSJeremy L Thompson } 14003668ca4bSJeremy L Thompson } 14013668ca4bSJeremy L Thompson } 14023668ca4bSJeremy L Thompson if (!label_found) { 14033668ca4bSJeremy L Thompson // LCOV_EXCL_START 1404a48e5f43SJeremy L Thompson ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr); 14053668ca4bSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 14063668ca4bSJeremy L Thompson *field_label = NULL; 14073668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 14083668ca4bSJeremy L Thompson } else { 14093668ca4bSJeremy L Thompson // Move new composite label to operator 14103668ca4bSJeremy L Thompson if (op->num_context_labels == 0) { 14113668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr); 14123668ca4bSJeremy L Thompson op->max_context_labels = 1; 14133668ca4bSJeremy L Thompson } else if (op->num_context_labels == op->max_context_labels) { 14143668ca4bSJeremy L Thompson ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels); 14153668ca4bSJeremy L Thompson CeedChk(ierr); 14163668ca4bSJeremy L Thompson op->max_context_labels *= 2; 14173668ca4bSJeremy L Thompson } 14183668ca4bSJeremy L Thompson op->context_labels[op->num_context_labels] = new_field_label; 14193668ca4bSJeremy L Thompson *field_label = new_field_label; 14203668ca4bSJeremy L Thompson op->num_context_labels++; 14213668ca4bSJeremy L Thompson } 14223668ca4bSJeremy L Thompson 14233668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 14243668ca4bSJeremy L Thompson } else { 14253668ca4bSJeremy L Thompson return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label); 14263668ca4bSJeremy L Thompson } 14273668ca4bSJeremy L Thompson } 14283668ca4bSJeremy L Thompson 14293668ca4bSJeremy L Thompson /** 1430d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding a double precision value. 1431d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1432d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1433d8dd9a91SJeremy L Thompson 1434d8dd9a91SJeremy L Thompson @param op CeedOperator 14353668ca4bSJeremy L Thompson @param field_label Label of field to register 14367bfe0f0eSJeremy L Thompson @param values Values to set 1437d8dd9a91SJeremy L Thompson 1438d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1439d8dd9a91SJeremy L Thompson 1440d8dd9a91SJeremy L Thompson @ref User 1441d8dd9a91SJeremy L Thompson **/ 14423668ca4bSJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op, 14433668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 14447bfe0f0eSJeremy L Thompson double *values) { 14453668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, 14467bfe0f0eSJeremy L Thompson values); 1447d8dd9a91SJeremy L Thompson } 1448d8dd9a91SJeremy L Thompson 1449d8dd9a91SJeremy L Thompson /** 1450d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding an int32 value. 1451d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1452d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1453d8dd9a91SJeremy L Thompson 1454d8dd9a91SJeremy L Thompson @param op CeedOperator 14553668ca4bSJeremy L Thompson @param field_label Label of field to set 14567bfe0f0eSJeremy L Thompson @param values Values to set 1457d8dd9a91SJeremy L Thompson 1458d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1459d8dd9a91SJeremy L Thompson 1460d8dd9a91SJeremy L Thompson @ref User 1461d8dd9a91SJeremy L Thompson **/ 14623668ca4bSJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op, 14633668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 14647bfe0f0eSJeremy L Thompson int *values) { 14653668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, 14667bfe0f0eSJeremy L Thompson values); 1467d8dd9a91SJeremy L Thompson } 1468d8dd9a91SJeremy L Thompson 1469d8dd9a91SJeremy L Thompson /** 14703bd813ffSjeremylt @brief Apply CeedOperator to a vector 1471d7b241e6Sjeremylt 1472d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 1473d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 1474d7b241e6Sjeremylt CeedOperatorSetField(). 1475d7b241e6Sjeremylt 1476f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 1477f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 1478f04ea552SJeremy L Thompson 1479d7b241e6Sjeremylt @param op CeedOperator to apply 14804cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 148134138859Sjeremylt there are no active inputs 1482b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 14834cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 148434138859Sjeremylt active outputs 1485d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 14864cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1487b11c1e72Sjeremylt 1488b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1489dfdf5a53Sjeremylt 14907a982d89SJeremy L. Thompson @ref User 1491b11c1e72Sjeremylt **/ 1492692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1493692c2638Sjeremylt CeedRequest *request) { 1494d7b241e6Sjeremylt int ierr; 1495e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1496d7b241e6Sjeremylt 1497d1d35e2fSjeremylt if (op->num_elem) { 1498250756a7Sjeremylt // Standard Operator 1499cae8b89aSjeremylt if (op->Apply) { 1500250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1501cae8b89aSjeremylt } else { 1502cae8b89aSjeremylt // Zero all output vectors 1503250756a7Sjeremylt CeedQFunction qf = op->qf; 1504d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 1505d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 1506cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 1507cae8b89aSjeremylt vec = out; 1508cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 1509cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1510cae8b89aSjeremylt } 1511cae8b89aSjeremylt } 1512250756a7Sjeremylt // Apply 1513250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1514250756a7Sjeremylt } 1515f04ea552SJeremy L Thompson } else if (op->is_composite) { 1516250756a7Sjeremylt // Composite Operator 1517250756a7Sjeremylt if (op->ApplyComposite) { 1518250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1519250756a7Sjeremylt } else { 1520d1d35e2fSjeremylt CeedInt num_suboperators; 1521d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1522d1d35e2fSjeremylt CeedOperator *sub_operators; 1523d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1524250756a7Sjeremylt 1525250756a7Sjeremylt // Zero all output vectors 1526250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 1527cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1528cae8b89aSjeremylt } 1529d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1530d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 1531d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 1532250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1533250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1534250756a7Sjeremylt } 1535250756a7Sjeremylt } 1536250756a7Sjeremylt } 1537250756a7Sjeremylt // Apply 1538d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 1539d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 1540cae8b89aSjeremylt CeedChk(ierr); 1541cae8b89aSjeremylt } 1542cae8b89aSjeremylt } 1543250756a7Sjeremylt } 1544e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1545cae8b89aSjeremylt } 1546cae8b89aSjeremylt 1547cae8b89aSjeremylt /** 1548cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 1549cae8b89aSjeremylt 1550cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 1551cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 1552cae8b89aSjeremylt CeedOperatorSetField(). 1553cae8b89aSjeremylt 1554cae8b89aSjeremylt @param op CeedOperator to apply 1555cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 1556cae8b89aSjeremylt active inputs 1557cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 1558cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 1559cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 15604cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1561cae8b89aSjeremylt 1562cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 1563cae8b89aSjeremylt 15647a982d89SJeremy L. Thompson @ref User 1565cae8b89aSjeremylt **/ 1566cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1567cae8b89aSjeremylt CeedRequest *request) { 1568cae8b89aSjeremylt int ierr; 1569e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1570cae8b89aSjeremylt 1571d1d35e2fSjeremylt if (op->num_elem) { 1572250756a7Sjeremylt // Standard Operator 1573250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1574f04ea552SJeremy L Thompson } else if (op->is_composite) { 1575250756a7Sjeremylt // Composite Operator 1576250756a7Sjeremylt if (op->ApplyAddComposite) { 1577250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1578cae8b89aSjeremylt } else { 1579d1d35e2fSjeremylt CeedInt num_suboperators; 1580d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1581d1d35e2fSjeremylt CeedOperator *sub_operators; 1582d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1583250756a7Sjeremylt 1584d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1585d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 1586cae8b89aSjeremylt CeedChk(ierr); 15871d7d2407SJeremy L Thompson } 1588250756a7Sjeremylt } 1589250756a7Sjeremylt } 1590e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1591d7b241e6Sjeremylt } 1592d7b241e6Sjeremylt 1593d7b241e6Sjeremylt /** 1594b11c1e72Sjeremylt @brief Destroy a CeedOperator 1595d7b241e6Sjeremylt 1596d7b241e6Sjeremylt @param op CeedOperator to destroy 1597b11c1e72Sjeremylt 1598b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1599dfdf5a53Sjeremylt 16007a982d89SJeremy L. Thompson @ref User 1601b11c1e72Sjeremylt **/ 1602d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1603d7b241e6Sjeremylt int ierr; 1604d7b241e6Sjeremylt 1605d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 1606d7b241e6Sjeremylt if ((*op)->Destroy) { 1607d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1608d7b241e6Sjeremylt } 1609fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1610fe2413ffSjeremylt // Free fields 16113668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1612d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 1613d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 1614d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 161571352a93Sjeremylt CeedChk(ierr); 161615910d16Sjeremylt } 1617d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1618d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 161971352a93Sjeremylt } 1620d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 1621d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 1622d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 162371352a93Sjeremylt } 1624d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 1625d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 1626fe2413ffSjeremylt } 16273668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1628d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 1629d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 163071352a93Sjeremylt CeedChk(ierr); 1631d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1632d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 163371352a93Sjeremylt } 1634d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 1635d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 1636d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 163771352a93Sjeremylt } 1638d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 1639d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 1640fe2413ffSjeremylt } 1641d1d35e2fSjeremylt // Destroy sub_operators 16423668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_suboperators; i++) 1643d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 1644d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 164552d6035fSJeremy L Thompson } 1646d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1647d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1648d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 16493668ca4bSJeremy L Thompson // Destroy any composite labels 16503668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_context_labels; i++) { 16513668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr); 16523668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr); 16533668ca4bSJeremy L Thompson } 16543668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr); 1655fe2413ffSjeremylt 16565107b09fSJeremy L Thompson // Destroy fallback 1657d1d35e2fSjeremylt if ((*op)->op_fallback) { 1658d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 1659d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 1660d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 1661d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 16625107b09fSJeremy L Thompson } 16635107b09fSJeremy L Thompson 166470a7ffb3SJeremy L Thompson // Destroy QF assembly cache 1665480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr); 166670a7ffb3SJeremy L Thompson 1667d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 1668d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 1669d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 1670d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1671e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1672d7b241e6Sjeremylt } 1673d7b241e6Sjeremylt 1674d7b241e6Sjeremylt /// @} 1675