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 175*381e6593SJeremy L Thompson CeedInt num_elem, num_qpts; 176*381e6593SJeremy L Thompson ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChk(ierr); 177*381e6593SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &num_qpts); CeedChk(ierr); 178*381e6593SJeremy L Thompson 17978464608Sjeremylt CeedInt total_fields = 0; 18078464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 181*381e6593SJeremy L Thompson fprintf(stream, "%s %d elements with %d quadrature points each\n", 182*381e6593SJeremy L Thompson pre, num_elem, num_qpts); 1837a982d89SJeremy L. Thompson 18478464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 18578464608Sjeremylt total_fields>1 ? "s" : ""); 1867a982d89SJeremy L. Thompson 187d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 188d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 189d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 190d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 1917a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 1927a982d89SJeremy L. Thompson } 1937a982d89SJeremy L. Thompson 194d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 195d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 196d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 197d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 1987a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 1997a982d89SJeremy L. Thompson } 200e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2017a982d89SJeremy L. Thompson } 2027a982d89SJeremy L. Thompson 203d99fa3c5SJeremy L Thompson /** 2040f60e0a8SJeremy L Thompson @brief Find the active vector basis for a non-composite CeedOperator 205eaf62fffSJeremy L Thompson 206eaf62fffSJeremy L Thompson @param[in] op CeedOperator to find active basis for 2070f60e0a8SJeremy L Thompson @param[out] active_basis Basis for active input vector or NULL for composite operator 208eaf62fffSJeremy L Thompson 209eaf62fffSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 210eaf62fffSJeremy L Thompson 211eaf62fffSJeremy L Thompson @ ref Developer 212eaf62fffSJeremy L Thompson **/ 213eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) { 214eaf62fffSJeremy L Thompson *active_basis = NULL; 2150f60e0a8SJeremy L Thompson if (op->is_composite) return CEED_ERROR_SUCCESS; 216eaf62fffSJeremy L Thompson for (int i = 0; i < op->qf->num_input_fields; i++) 217eaf62fffSJeremy L Thompson if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 218eaf62fffSJeremy L Thompson *active_basis = op->input_fields[i]->basis; 219eaf62fffSJeremy L Thompson break; 220eaf62fffSJeremy L Thompson } 221eaf62fffSJeremy L Thompson 222eaf62fffSJeremy L Thompson if (!*active_basis) { 223eaf62fffSJeremy L Thompson // LCOV_EXCL_START 224eaf62fffSJeremy L Thompson int ierr; 225eaf62fffSJeremy L Thompson Ceed ceed; 226eaf62fffSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 227eaf62fffSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 228eaf62fffSJeremy L Thompson "No active CeedBasis found"); 229eaf62fffSJeremy L Thompson // LCOV_EXCL_STOP 230eaf62fffSJeremy L Thompson } 231eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 232eaf62fffSJeremy L Thompson } 233eaf62fffSJeremy L Thompson 234eaf62fffSJeremy L Thompson /** 2350f60e0a8SJeremy L Thompson @brief Find the active vector ElemRestriction for a non-composite CeedOperator 236e2f04181SAndrew T. Barker 237e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 2380f60e0a8SJeremy L Thompson @param[out] active_rstr ElemRestriction for active input vector or NULL for composite operator 239e2f04181SAndrew T. Barker 240e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 241e2f04181SAndrew T. Barker 242e2f04181SAndrew T. Barker @ref Utility 243e2f04181SAndrew T. Barker **/ 244eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op, 245d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 246d1d35e2fSjeremylt *active_rstr = NULL; 2470f60e0a8SJeremy L Thompson if (op->is_composite) return CEED_ERROR_SUCCESS; 248d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 249d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 250d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 251e2f04181SAndrew T. Barker break; 252e2f04181SAndrew T. Barker } 253e2f04181SAndrew T. Barker 254d1d35e2fSjeremylt if (!*active_rstr) { 255e2f04181SAndrew T. Barker // LCOV_EXCL_START 256e2f04181SAndrew T. Barker int ierr; 257e2f04181SAndrew T. Barker Ceed ceed; 258e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 259e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 260eaf62fffSJeremy L Thompson "No active CeedElemRestriction found"); 261e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 262e2f04181SAndrew T. Barker } 263e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 264e2f04181SAndrew T. Barker } 265e2f04181SAndrew T. Barker 266d8dd9a91SJeremy L Thompson /** 267d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field value of the specified type. 268d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 269d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 270d8dd9a91SJeremy L Thompson A non-zero error code is returned for single operators 271d8dd9a91SJeremy L Thompson that do not have a matching field of the same type or composite 272d8dd9a91SJeremy L Thompson operators that do not have any field of a matching type. 273d8dd9a91SJeremy L Thompson 274d8dd9a91SJeremy L Thompson @param op CeedOperator 2753668ca4bSJeremy L Thompson @param field_label Label of field to set 276d8dd9a91SJeremy L Thompson @param field_type Type of field to set 277d8dd9a91SJeremy L Thompson @param value Value to set 278d8dd9a91SJeremy L Thompson 279d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 280d8dd9a91SJeremy L Thompson 281d8dd9a91SJeremy L Thompson @ref User 282d8dd9a91SJeremy L Thompson **/ 283d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op, 2843668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, CeedContextFieldType field_type, 2853668ca4bSJeremy L Thompson void *value) { 286d8dd9a91SJeremy L Thompson int ierr; 287d8dd9a91SJeremy L Thompson 2883668ca4bSJeremy L Thompson if (!field_label) 2893668ca4bSJeremy L Thompson // LCOV_EXCL_START 2903668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 2913668ca4bSJeremy L Thompson "Invalid field label"); 2923668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 2933668ca4bSJeremy L Thompson 2943668ca4bSJeremy L Thompson bool is_composite = false; 295d8dd9a91SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 296d8dd9a91SJeremy L Thompson if (is_composite) { 297d8dd9a91SJeremy L Thompson CeedInt num_sub; 298d8dd9a91SJeremy L Thompson CeedOperator *sub_operators; 299d8dd9a91SJeremy L Thompson 300d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 301d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 3023668ca4bSJeremy L Thompson if (num_sub != field_label->num_sub_labels) 3033668ca4bSJeremy L Thompson // LCOV_EXCL_START 3043668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 3053668ca4bSJeremy L Thompson "ContextLabel does not correspond to composite operator.\n" 3063668ca4bSJeremy L Thompson "Use CeedOperatorGetContextFieldLabel()."); 3073668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 308d8dd9a91SJeremy L Thompson 309d8dd9a91SJeremy L Thompson for (CeedInt i = 0; i < num_sub; i++) { 310d8dd9a91SJeremy L Thompson // Try every sub-operator, ok if some sub-operators do not have field 3113668ca4bSJeremy L Thompson if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) { 3123668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx, 3133668ca4bSJeremy L Thompson field_label->sub_labels[i], 3143668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 315d8dd9a91SJeremy L Thompson } 316d8dd9a91SJeremy L Thompson } 317d8dd9a91SJeremy L Thompson } else { 318d8dd9a91SJeremy L Thompson if (!op->qf->ctx) 319d8dd9a91SJeremy L Thompson // LCOV_EXCL_START 320d8dd9a91SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 321d8dd9a91SJeremy L Thompson "QFunction does not have context data"); 322d8dd9a91SJeremy L Thompson // LCOV_EXCL_STOP 323d8dd9a91SJeremy L Thompson 3243668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label, 3253668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 326d8dd9a91SJeremy L Thompson } 327d8dd9a91SJeremy L Thompson 328d8dd9a91SJeremy L Thompson return CEED_ERROR_SUCCESS; 329d8dd9a91SJeremy L Thompson } 330d8dd9a91SJeremy L Thompson 3317a982d89SJeremy L. Thompson /// @} 3327a982d89SJeremy L. Thompson 3337a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3347a982d89SJeremy L. Thompson /// CeedOperator Backend API 3357a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3367a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 3377a982d89SJeremy L. Thompson /// @{ 3387a982d89SJeremy L. Thompson 3397a982d89SJeremy L. Thompson /** 3407a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 3417a982d89SJeremy L. Thompson 3427a982d89SJeremy L. Thompson @param op CeedOperator 343d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 3447a982d89SJeremy L. Thompson 3457a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3467a982d89SJeremy L. Thompson 3477a982d89SJeremy L. Thompson @ref Backend 3487a982d89SJeremy L. Thompson **/ 3497a982d89SJeremy L. Thompson 350d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 351f04ea552SJeremy L Thompson if (op->is_composite) 3527a982d89SJeremy L. Thompson // LCOV_EXCL_START 353e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 354e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 3557a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3567a982d89SJeremy L. Thompson 357d1d35e2fSjeremylt *num_args = op->num_fields; 358e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3597a982d89SJeremy L. Thompson } 3607a982d89SJeremy L. Thompson 3617a982d89SJeremy L. Thompson /** 3627a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 3637a982d89SJeremy L. Thompson 3647a982d89SJeremy L. Thompson @param op CeedOperator 365d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 3667a982d89SJeremy L. Thompson 3677a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3687a982d89SJeremy L. Thompson 3697a982d89SJeremy L. Thompson @ref Backend 3707a982d89SJeremy L. Thompson **/ 3717a982d89SJeremy L. Thompson 372d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 373f04ea552SJeremy L Thompson *is_setup_done = op->is_backend_setup; 374e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3757a982d89SJeremy L. Thompson } 3767a982d89SJeremy L. Thompson 3777a982d89SJeremy L. Thompson /** 3787a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 3797a982d89SJeremy L. Thompson 3807a982d89SJeremy L. Thompson @param op CeedOperator 3817a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 3827a982d89SJeremy L. Thompson 3837a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3847a982d89SJeremy L. Thompson 3857a982d89SJeremy L. Thompson @ref Backend 3867a982d89SJeremy L. Thompson **/ 3877a982d89SJeremy L. Thompson 3887a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 389f04ea552SJeremy L Thompson if (op->is_composite) 3907a982d89SJeremy L. Thompson // LCOV_EXCL_START 391e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 392e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 3937a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3947a982d89SJeremy L. Thompson 3957a982d89SJeremy L. Thompson *qf = op->qf; 396e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3977a982d89SJeremy L. Thompson } 3987a982d89SJeremy L. Thompson 3997a982d89SJeremy L. Thompson /** 400c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 401c04a41a7SJeremy L Thompson 402c04a41a7SJeremy L Thompson @param op CeedOperator 403d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 404c04a41a7SJeremy L Thompson 405c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 406c04a41a7SJeremy L Thompson 407c04a41a7SJeremy L Thompson @ref Backend 408c04a41a7SJeremy L Thompson **/ 409c04a41a7SJeremy L Thompson 410d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 411f04ea552SJeremy L Thompson *is_composite = op->is_composite; 412e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 413c04a41a7SJeremy L Thompson } 414c04a41a7SJeremy L Thompson 415c04a41a7SJeremy L Thompson /** 416d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 4177a982d89SJeremy L. Thompson 4187a982d89SJeremy L. Thompson @param op CeedOperator 419d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 4207a982d89SJeremy L. Thompson 4217a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4227a982d89SJeremy L. Thompson 4237a982d89SJeremy L. Thompson @ref Backend 4247a982d89SJeremy L. Thompson **/ 4257a982d89SJeremy L. Thompson 426d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 427f04ea552SJeremy L Thompson if (!op->is_composite) 4287a982d89SJeremy L. Thompson // LCOV_EXCL_START 429e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4307a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4317a982d89SJeremy L. Thompson 432d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 433e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4347a982d89SJeremy L. Thompson } 4357a982d89SJeremy L. Thompson 4367a982d89SJeremy L. Thompson /** 437d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 4387a982d89SJeremy L. Thompson 4397a982d89SJeremy L. Thompson @param op CeedOperator 440d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 4417a982d89SJeremy L. Thompson 4427a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4437a982d89SJeremy L. Thompson 4447a982d89SJeremy L. Thompson @ref Backend 4457a982d89SJeremy L. Thompson **/ 4467a982d89SJeremy L. Thompson 447d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 448f04ea552SJeremy L Thompson if (!op->is_composite) 4497a982d89SJeremy L. Thompson // LCOV_EXCL_START 450e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4517a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4527a982d89SJeremy L. Thompson 453d1d35e2fSjeremylt *sub_operators = op->sub_operators; 454e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4557a982d89SJeremy L. Thompson } 4567a982d89SJeremy L. Thompson 4577a982d89SJeremy L. Thompson /** 4587a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 4597a982d89SJeremy L. Thompson 4607a982d89SJeremy L. Thompson @param op CeedOperator 4617a982d89SJeremy L. Thompson @param[out] data Variable to store data 4627a982d89SJeremy L. Thompson 4637a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4647a982d89SJeremy L. Thompson 4657a982d89SJeremy L. Thompson @ref Backend 4667a982d89SJeremy L. Thompson **/ 4677a982d89SJeremy L. Thompson 468777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 469777ff853SJeremy L Thompson *(void **)data = op->data; 470e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4717a982d89SJeremy L. Thompson } 4727a982d89SJeremy L. Thompson 4737a982d89SJeremy L. Thompson /** 4747a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 4757a982d89SJeremy L. Thompson 4767a982d89SJeremy L. Thompson @param[out] op CeedOperator 4777a982d89SJeremy L. Thompson @param data Data to set 4787a982d89SJeremy L. Thompson 4797a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4807a982d89SJeremy L. Thompson 4817a982d89SJeremy L. Thompson @ref Backend 4827a982d89SJeremy L. Thompson **/ 4837a982d89SJeremy L. Thompson 484777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 485777ff853SJeremy L Thompson op->data = data; 486e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4877a982d89SJeremy L. Thompson } 4887a982d89SJeremy L. Thompson 4897a982d89SJeremy L. Thompson /** 49034359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 49134359f16Sjeremylt 49234359f16Sjeremylt @param op CeedOperator to increment the reference counter 49334359f16Sjeremylt 49434359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 49534359f16Sjeremylt 49634359f16Sjeremylt @ref Backend 49734359f16Sjeremylt **/ 4989560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 49934359f16Sjeremylt op->ref_count++; 50034359f16Sjeremylt return CEED_ERROR_SUCCESS; 50134359f16Sjeremylt } 50234359f16Sjeremylt 50334359f16Sjeremylt /** 5047a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 5057a982d89SJeremy L. Thompson 5067a982d89SJeremy L. Thompson @param op CeedOperator 5077a982d89SJeremy L. Thompson 5087a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5097a982d89SJeremy L. Thompson 5107a982d89SJeremy L. Thompson @ref Backend 5117a982d89SJeremy L. Thompson **/ 5127a982d89SJeremy L. Thompson 5137a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 514f04ea552SJeremy L Thompson op->is_backend_setup = true; 515e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5167a982d89SJeremy L. Thompson } 5177a982d89SJeremy L. Thompson 5187a982d89SJeremy L. Thompson /// @} 5197a982d89SJeremy L. Thompson 5207a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5217a982d89SJeremy L. Thompson /// CeedOperator Public API 5227a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5237a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 524dfdf5a53Sjeremylt /// @{ 525d7b241e6Sjeremylt 526d7b241e6Sjeremylt /** 5270219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 5280219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 5290219ea01SJeremy L Thompson \ref CeedOperatorSetField. 530d7b241e6Sjeremylt 531b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 532d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 53334138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 5344cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 535d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 5364cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 537b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 538b11c1e72Sjeremylt CeedOperator will be stored 539b11c1e72Sjeremylt 540b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 541dfdf5a53Sjeremylt 5427a982d89SJeremy L. Thompson @ref User 543d7b241e6Sjeremylt */ 544d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 545d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 546d7b241e6Sjeremylt int ierr; 547d7b241e6Sjeremylt 5485fe0d4faSjeremylt if (!ceed->OperatorCreate) { 5495fe0d4faSjeremylt Ceed delegate; 550aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 5515fe0d4faSjeremylt 5525fe0d4faSjeremylt if (!delegate) 553c042f62fSJeremy L Thompson // LCOV_EXCL_START 554e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 555e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 556c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 5575fe0d4faSjeremylt 5585fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 559e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5605fe0d4faSjeremylt } 5615fe0d4faSjeremylt 562b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 563b3b7035fSJeremy L Thompson // LCOV_EXCL_START 564e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 565e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 566b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 567d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 568d7b241e6Sjeremylt (*op)->ceed = ceed; 5699560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 570d1d35e2fSjeremylt (*op)->ref_count = 1; 571d7b241e6Sjeremylt (*op)->qf = qf; 5722b104005SJeremy L Thompson (*op)->input_size = -1; 5732b104005SJeremy L Thompson (*op)->output_size = -1; 5749560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 575442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 576d7b241e6Sjeremylt (*op)->dqf = dqf; 5779560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 578442e7f0bSjeremylt } 579442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 580d7b241e6Sjeremylt (*op)->dqfT = dqfT; 5819560d06aSjeremylt ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 582442e7f0bSjeremylt } 583480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled); 584480fae85SJeremy L Thompson CeedChk(ierr); 585bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr); 586bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr); 587d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 588e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 589d7b241e6Sjeremylt } 590d7b241e6Sjeremylt 591d7b241e6Sjeremylt /** 59252d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 59352d6035fSJeremy L Thompson 59452d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 59552d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 59652d6035fSJeremy L Thompson Composite CeedOperator will be stored 59752d6035fSJeremy L Thompson 59852d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 59952d6035fSJeremy L Thompson 6007a982d89SJeremy L. Thompson @ref User 60152d6035fSJeremy L Thompson */ 60252d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 60352d6035fSJeremy L Thompson int ierr; 60452d6035fSJeremy L Thompson 60552d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 60652d6035fSJeremy L Thompson Ceed delegate; 607aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 60852d6035fSJeremy L Thompson 609250756a7Sjeremylt if (delegate) { 61052d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 611e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 61252d6035fSJeremy L Thompson } 613250756a7Sjeremylt } 61452d6035fSJeremy L Thompson 61552d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 61652d6035fSJeremy L Thompson (*op)->ceed = ceed; 6179560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 618f04ea552SJeremy L Thompson (*op)->is_composite = true; 619bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr); 6202b104005SJeremy L Thompson (*op)->input_size = -1; 6212b104005SJeremy L Thompson (*op)->output_size = -1; 622250756a7Sjeremylt 623250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 62452d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 625250756a7Sjeremylt } 626e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 62752d6035fSJeremy L Thompson } 62852d6035fSJeremy L Thompson 62952d6035fSJeremy L Thompson /** 6309560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 6319560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 6329560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 6339560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 6349560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 6359560d06aSjeremylt reference to this CeedOperator. 6369560d06aSjeremylt 6379560d06aSjeremylt @param op CeedOperator to copy reference to 6389560d06aSjeremylt @param[out] op_copy Variable to store copied reference 6399560d06aSjeremylt 6409560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 6419560d06aSjeremylt 6429560d06aSjeremylt @ref User 6439560d06aSjeremylt **/ 6449560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 6459560d06aSjeremylt int ierr; 6469560d06aSjeremylt 6479560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 6489560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 6499560d06aSjeremylt *op_copy = op; 6509560d06aSjeremylt return CEED_ERROR_SUCCESS; 6519560d06aSjeremylt } 6529560d06aSjeremylt 6539560d06aSjeremylt /** 654b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 655d7b241e6Sjeremylt 656d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 657d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 658d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 659d7b241e6Sjeremylt 660d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 661d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 662979e564eSJames Wright input CeedVector and at most one active output CeedVector passed to 663979e564eSJames Wright CeedOperatorApply(). 664d7b241e6Sjeremylt 6658c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 666d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 6678795c945Sjeremylt CeedQFunction) 668b11c1e72Sjeremylt @param r CeedElemRestriction 6694cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 670b11c1e72Sjeremylt if collocated with quadrature points 6714cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 6724cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 6734cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 674b11c1e72Sjeremylt 675b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 676dfdf5a53Sjeremylt 6777a982d89SJeremy L. Thompson @ref User 678b11c1e72Sjeremylt **/ 679d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 680a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 681d7b241e6Sjeremylt int ierr; 682f04ea552SJeremy L Thompson if (op->is_composite) 683c042f62fSJeremy L Thompson // LCOV_EXCL_START 684e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 685e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 686c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 687f04ea552SJeremy L Thompson if (op->is_immutable) 688f04ea552SJeremy L Thompson // LCOV_EXCL_START 689f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 690f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 691f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 6928b067b84SJed Brown if (!r) 693c042f62fSJeremy L Thompson // LCOV_EXCL_START 694e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 695c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 696d1d35e2fSjeremylt field_name); 697c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6988b067b84SJed Brown if (!b) 699c042f62fSJeremy L Thompson // LCOV_EXCL_START 700e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 701e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 702d1d35e2fSjeremylt field_name); 703c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 7048b067b84SJed Brown if (!v) 705c042f62fSJeremy L Thompson // LCOV_EXCL_START 706e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 707e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 708d1d35e2fSjeremylt field_name); 709c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 71052d6035fSJeremy L Thompson 711d1d35e2fSjeremylt CeedInt num_elem; 712d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 713d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 714d1d35e2fSjeremylt op->num_elem != num_elem) 715c042f62fSJeremy L Thompson // LCOV_EXCL_START 716e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 7171d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 718d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 719c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 720d7b241e6Sjeremylt 72178464608Sjeremylt CeedInt num_qpts = 0; 722e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 723d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 724d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 725c042f62fSJeremy L Thompson // LCOV_EXCL_START 726e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 727e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 728d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 729d1d35e2fSjeremylt op->num_qpts); 730c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 731d7b241e6Sjeremylt } 732d1d35e2fSjeremylt CeedQFunctionField qf_field; 733d1d35e2fSjeremylt CeedOperatorField *op_field; 7342b104005SJeremy L Thompson bool is_input = true; 735d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 736d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 737d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 738d1d35e2fSjeremylt op_field = &op->input_fields[i]; 739d7b241e6Sjeremylt goto found; 740d7b241e6Sjeremylt } 741d7b241e6Sjeremylt } 7422b104005SJeremy L Thompson is_input = false; 743d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 744d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 745d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 746d1d35e2fSjeremylt op_field = &op->output_fields[i]; 747d7b241e6Sjeremylt goto found; 748d7b241e6Sjeremylt } 749d7b241e6Sjeremylt } 750c042f62fSJeremy L Thompson // LCOV_EXCL_START 751e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 752e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 753d1d35e2fSjeremylt field_name); 754c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 755d7b241e6Sjeremylt found: 756d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 757d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 758e15f9bd0SJeremy L Thompson 7592b104005SJeremy L Thompson if (v == CEED_VECTOR_ACTIVE) { 7602b104005SJeremy L Thompson CeedSize l_size; 7612b104005SJeremy L Thompson ierr = CeedElemRestrictionGetLVectorSize(r, &l_size); CeedChk(ierr); 7622b104005SJeremy L Thompson if (is_input) { 7632b104005SJeremy L Thompson if (op->input_size == -1) op->input_size = l_size; 7642b104005SJeremy L Thompson if (l_size != op->input_size) 7652b104005SJeremy L Thompson // LCOV_EXCL_START 7662b104005SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 7672b104005SJeremy L Thompson "LVector size %td does not match previous size %td", 7682b104005SJeremy L Thompson l_size, op->input_size); 7692b104005SJeremy L Thompson // LCOV_EXCL_STOP 7702b104005SJeremy L Thompson } else { 7712b104005SJeremy L Thompson if (op->output_size == -1) op->output_size = l_size; 7722b104005SJeremy L Thompson if (l_size != op->output_size) 7732b104005SJeremy L Thompson // LCOV_EXCL_START 7742b104005SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 7752b104005SJeremy L Thompson "LVector size %td does not match previous size %td", 7762b104005SJeremy L Thompson l_size, op->output_size); 7772b104005SJeremy L Thompson // LCOV_EXCL_STOP 7782b104005SJeremy L Thompson } 7792b104005SJeremy L Thompson } 7802b104005SJeremy L Thompson 781d1d35e2fSjeremylt (*op_field)->vec = v; 782e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 7839560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 784e15f9bd0SJeremy L Thompson } 785e15f9bd0SJeremy L Thompson 786d1d35e2fSjeremylt (*op_field)->elem_restr = r; 7879560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 788e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 789d1d35e2fSjeremylt op->num_elem = num_elem; 790d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 791e15f9bd0SJeremy L Thompson } 792d99fa3c5SJeremy L Thompson 793d1d35e2fSjeremylt (*op_field)->basis = b; 794e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 795cd4dfc48Sjeremylt if (!op->num_qpts) { 796cd4dfc48Sjeremylt ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 797cd4dfc48Sjeremylt } 7989560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 799e15f9bd0SJeremy L Thompson } 800e15f9bd0SJeremy L Thompson 801d1d35e2fSjeremylt op->num_fields += 1; 802f7e22acaSJeremy L Thompson ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name); 803f7e22acaSJeremy L Thompson CeedChk(ierr); 804e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 805d7b241e6Sjeremylt } 806d7b241e6Sjeremylt 807d7b241e6Sjeremylt /** 80843bbe138SJeremy L Thompson @brief Get the CeedOperatorFields of a CeedOperator 80943bbe138SJeremy L Thompson 810f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 811f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 812f04ea552SJeremy L Thompson 81343bbe138SJeremy L Thompson @param op CeedOperator 814f74ec584SJeremy L Thompson @param[out] num_input_fields Variable to store number of input fields 81543bbe138SJeremy L Thompson @param[out] input_fields Variable to store input_fields 816f74ec584SJeremy L Thompson @param[out] num_output_fields Variable to store number of output fields 81743bbe138SJeremy L Thompson @param[out] output_fields Variable to store output_fields 81843bbe138SJeremy L Thompson 81943bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 82043bbe138SJeremy L Thompson 821e9b533fbSJeremy L Thompson @ref Advanced 82243bbe138SJeremy L Thompson **/ 82343bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields, 82443bbe138SJeremy L Thompson CeedOperatorField **input_fields, 82543bbe138SJeremy L Thompson CeedInt *num_output_fields, 82643bbe138SJeremy L Thompson CeedOperatorField **output_fields) { 827f04ea552SJeremy L Thompson int ierr; 828f04ea552SJeremy L Thompson 829f04ea552SJeremy L Thompson if (op->is_composite) 83043bbe138SJeremy L Thompson // LCOV_EXCL_START 83143bbe138SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 83243bbe138SJeremy L Thompson "Not defined for composite operator"); 83343bbe138SJeremy L Thompson // LCOV_EXCL_STOP 834f04ea552SJeremy L Thompson ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 83543bbe138SJeremy L Thompson 83643bbe138SJeremy L Thompson if (num_input_fields) *num_input_fields = op->qf->num_input_fields; 83743bbe138SJeremy L Thompson if (input_fields) *input_fields = op->input_fields; 83843bbe138SJeremy L Thompson if (num_output_fields) *num_output_fields = op->qf->num_output_fields; 83943bbe138SJeremy L Thompson if (output_fields) *output_fields = op->output_fields; 84043bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 84143bbe138SJeremy L Thompson } 84243bbe138SJeremy L Thompson 84343bbe138SJeremy L Thompson /** 84428567f8fSJeremy L Thompson @brief Get the name of a CeedOperatorField 84528567f8fSJeremy L Thompson 84628567f8fSJeremy L Thompson @param op_field CeedOperatorField 84728567f8fSJeremy L Thompson @param[out] field_name Variable to store the field name 84828567f8fSJeremy L Thompson 84928567f8fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 85028567f8fSJeremy L Thompson 851e9b533fbSJeremy L Thompson @ref Advanced 85228567f8fSJeremy L Thompson **/ 85328567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) { 85428567f8fSJeremy L Thompson *field_name = (char *)op_field->field_name; 85528567f8fSJeremy L Thompson return CEED_ERROR_SUCCESS; 85628567f8fSJeremy L Thompson } 85728567f8fSJeremy L Thompson 85828567f8fSJeremy L Thompson /** 85943bbe138SJeremy L Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 86043bbe138SJeremy L Thompson 86143bbe138SJeremy L Thompson @param op_field CeedOperatorField 86243bbe138SJeremy L Thompson @param[out] rstr Variable to store CeedElemRestriction 86343bbe138SJeremy L Thompson 86443bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 86543bbe138SJeremy L Thompson 866e9b533fbSJeremy L Thompson @ref Advanced 86743bbe138SJeremy L Thompson **/ 86843bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 86943bbe138SJeremy L Thompson CeedElemRestriction *rstr) { 87043bbe138SJeremy L Thompson *rstr = op_field->elem_restr; 87143bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 87243bbe138SJeremy L Thompson } 87343bbe138SJeremy L Thompson 87443bbe138SJeremy L Thompson /** 87543bbe138SJeremy L Thompson @brief Get the CeedBasis of a CeedOperatorField 87643bbe138SJeremy L Thompson 87743bbe138SJeremy L Thompson @param op_field CeedOperatorField 87843bbe138SJeremy L Thompson @param[out] basis Variable to store CeedBasis 87943bbe138SJeremy L Thompson 88043bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 88143bbe138SJeremy L Thompson 882e9b533fbSJeremy L Thompson @ref Advanced 88343bbe138SJeremy L Thompson **/ 88443bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 88543bbe138SJeremy L Thompson *basis = op_field->basis; 88643bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 88743bbe138SJeremy L Thompson } 88843bbe138SJeremy L Thompson 88943bbe138SJeremy L Thompson /** 89043bbe138SJeremy L Thompson @brief Get the CeedVector of a CeedOperatorField 89143bbe138SJeremy L Thompson 89243bbe138SJeremy L Thompson @param op_field CeedOperatorField 89343bbe138SJeremy L Thompson @param[out] vec Variable to store CeedVector 89443bbe138SJeremy L Thompson 89543bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 89643bbe138SJeremy L Thompson 897e9b533fbSJeremy L Thompson @ref Advanced 89843bbe138SJeremy L Thompson **/ 89943bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 90043bbe138SJeremy L Thompson *vec = op_field->vec; 90143bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 90243bbe138SJeremy L Thompson } 90343bbe138SJeremy L Thompson 90443bbe138SJeremy L Thompson /** 90552d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 906288c0443SJeremy L Thompson 907d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 908d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 90952d6035fSJeremy L Thompson 91052d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 91152d6035fSJeremy L Thompson 9127a982d89SJeremy L. Thompson @ref User 91352d6035fSJeremy L Thompson */ 914d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 915d1d35e2fSjeremylt CeedOperator sub_op) { 91634359f16Sjeremylt int ierr; 91734359f16Sjeremylt 918f04ea552SJeremy L Thompson if (!composite_op->is_composite) 919c042f62fSJeremy L Thompson // LCOV_EXCL_START 920d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 921e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 922c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 92352d6035fSJeremy L Thompson 924d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 925c042f62fSJeremy L Thompson // LCOV_EXCL_START 926d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 9272b104005SJeremy L Thompson "Cannot add additional sub-operators"); 928c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 929f04ea552SJeremy L Thompson if (composite_op->is_immutable) 930f04ea552SJeremy L Thompson // LCOV_EXCL_START 931f04ea552SJeremy L Thompson return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 932f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 933f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 93452d6035fSJeremy L Thompson 9352b104005SJeremy L Thompson { 9362b104005SJeremy L Thompson CeedSize input_size, output_size; 9372b104005SJeremy L Thompson ierr = CeedOperatorGetActiveVectorLengths(sub_op, &input_size, &output_size); 9382b104005SJeremy L Thompson CeedChk(ierr); 9392b104005SJeremy L Thompson if (composite_op->input_size == -1) composite_op->input_size = input_size; 9402b104005SJeremy L Thompson if (composite_op->output_size == -1) composite_op->output_size = output_size; 9412b104005SJeremy L Thompson // Note, a size of -1 means no active vector restriction set, so no incompatibility 9422b104005SJeremy L Thompson if ((input_size != -1 && input_size != composite_op->input_size) || 9432b104005SJeremy L Thompson (output_size != -1 && output_size != composite_op->output_size)) 9442b104005SJeremy L Thompson // LCOV_EXCL_START 9452b104005SJeremy L Thompson return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 9462b104005SJeremy L Thompson "Sub-operators must have compatible dimensions; " 9472b104005SJeremy L Thompson "composite operator of shape (%td, %td) not compatible with " 9482b104005SJeremy L Thompson "sub-operator of shape (%td, %td)", 9492b104005SJeremy L Thompson composite_op->input_size, composite_op->output_size, input_size, output_size); 9502b104005SJeremy L Thompson // LCOV_EXCL_STOP 9512b104005SJeremy L Thompson } 9522b104005SJeremy L Thompson 953d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 9549560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 955d1d35e2fSjeremylt composite_op->num_suboperators++; 956e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 95752d6035fSJeremy L Thompson } 95852d6035fSJeremy L Thompson 95952d6035fSJeremy L Thompson /** 9604db537f9SJeremy L Thompson @brief Check if a CeedOperator is ready to be used. 9614db537f9SJeremy L Thompson 9624db537f9SJeremy L Thompson @param[in] op CeedOperator to check 9634db537f9SJeremy L Thompson 9644db537f9SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9654db537f9SJeremy L Thompson 9664db537f9SJeremy L Thompson @ref User 9674db537f9SJeremy L Thompson **/ 9684db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) { 9694db537f9SJeremy L Thompson int ierr; 9704db537f9SJeremy L Thompson Ceed ceed; 9714db537f9SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 9724db537f9SJeremy L Thompson 9734db537f9SJeremy L Thompson if (op->is_interface_setup) 9744db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 9754db537f9SJeremy L Thompson 9764db537f9SJeremy L Thompson CeedQFunction qf = op->qf; 9774db537f9SJeremy L Thompson if (op->is_composite) { 9784db537f9SJeremy L Thompson if (!op->num_suboperators) 9794db537f9SJeremy L Thompson // LCOV_EXCL_START 9804db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 9814db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9824db537f9SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 9834db537f9SJeremy L Thompson ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr); 9844db537f9SJeremy L Thompson } 9852b104005SJeremy L Thompson // Sub-operators could be modified after adding to composite operator 9862b104005SJeremy L Thompson // Need to verify no lvec incompatibility from any changes 9872b104005SJeremy L Thompson CeedSize input_size, output_size; 9882b104005SJeremy L Thompson ierr = CeedOperatorGetActiveVectorLengths(op, &input_size, &output_size); 9892b104005SJeremy L Thompson CeedChk(ierr); 9904db537f9SJeremy L Thompson } else { 9914db537f9SJeremy L Thompson if (op->num_fields == 0) 9924db537f9SJeremy L Thompson // LCOV_EXCL_START 9934db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 9944db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9954db537f9SJeremy L Thompson if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 9964db537f9SJeremy L Thompson // LCOV_EXCL_START 9974db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 9984db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9994db537f9SJeremy L Thompson if (!op->has_restriction) 10004db537f9SJeremy L Thompson // LCOV_EXCL_START 10014db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 10024db537f9SJeremy L Thompson "At least one restriction required"); 10034db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10044db537f9SJeremy L Thompson if (op->num_qpts == 0) 10054db537f9SJeremy L Thompson // LCOV_EXCL_START 10064db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 10074db537f9SJeremy L Thompson "At least one non-collocated basis is required " 10084db537f9SJeremy L Thompson "or the number of quadrature points must be set"); 10094db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10104db537f9SJeremy L Thompson } 10114db537f9SJeremy L Thompson 10124db537f9SJeremy L Thompson // Flag as immutable and ready 10134db537f9SJeremy L Thompson op->is_interface_setup = true; 10144db537f9SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 10154db537f9SJeremy L Thompson // LCOV_EXCL_START 10164db537f9SJeremy L Thompson op->qf->is_immutable = true; 10174db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10184db537f9SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 10194db537f9SJeremy L Thompson // LCOV_EXCL_START 10204db537f9SJeremy L Thompson op->dqf->is_immutable = true; 10214db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10224db537f9SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 10234db537f9SJeremy L Thompson // LCOV_EXCL_START 10244db537f9SJeremy L Thompson op->dqfT->is_immutable = true; 10254db537f9SJeremy L Thompson // LCOV_EXCL_STOP 10264db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 10274db537f9SJeremy L Thompson } 10284db537f9SJeremy L Thompson 10294db537f9SJeremy L Thompson /** 1030c9366a6bSJeremy L Thompson @brief Get vector lengths for the active input and/or output vectors of a CeedOperator. 1031c9366a6bSJeremy L Thompson Note: Lengths of -1 indicate that the CeedOperator does not have an 1032c9366a6bSJeremy L Thompson active input and/or output. 1033c9366a6bSJeremy L Thompson 1034c9366a6bSJeremy L Thompson @param[in] op CeedOperator 1035c9366a6bSJeremy L Thompson @param[out] input_size Variable to store active input vector length, or NULL 1036c9366a6bSJeremy L Thompson @param[out] output_size Variable to store active output vector length, or NULL 1037c9366a6bSJeremy L Thompson 1038c9366a6bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1039c9366a6bSJeremy L Thompson 1040c9366a6bSJeremy L Thompson @ref User 1041c9366a6bSJeremy L Thompson **/ 1042c9366a6bSJeremy L Thompson int CeedOperatorGetActiveVectorLengths(CeedOperator op, CeedSize *input_size, 1043c9366a6bSJeremy L Thompson CeedSize *output_size) { 1044c9366a6bSJeremy L Thompson int ierr; 1045c9366a6bSJeremy L Thompson bool is_composite; 1046c9366a6bSJeremy L Thompson 10472b104005SJeremy L Thompson if (input_size) *input_size = op->input_size; 10482b104005SJeremy L Thompson if (output_size) *output_size = op->output_size; 1049c9366a6bSJeremy L Thompson 1050c9366a6bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 10512b104005SJeremy L Thompson if (is_composite && (op->input_size == -1 || op->output_size == -1)) { 1052c9366a6bSJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1053c9366a6bSJeremy L Thompson CeedSize sub_input_size, sub_output_size; 1054c9366a6bSJeremy L Thompson ierr = CeedOperatorGetActiveVectorLengths(op->sub_operators[i], 10552b104005SJeremy L Thompson &sub_input_size, &sub_output_size); CeedChk(ierr); 10562b104005SJeremy L Thompson if (op->input_size == -1) op->input_size = sub_input_size; 10572b104005SJeremy L Thompson if (op->output_size == -1) op->output_size = sub_output_size; 10582b104005SJeremy L Thompson // Note, a size of -1 means no active vector restriction set, so no incompatibility 10592b104005SJeremy L Thompson if ((sub_input_size != -1 && sub_input_size != op->input_size) || 10602b104005SJeremy L Thompson (sub_output_size != -1 && sub_output_size != op->output_size)) 10612b104005SJeremy L Thompson // LCOV_EXCL_START 10622b104005SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 10632b104005SJeremy L Thompson "Sub-operators must have compatible dimensions; " 10642b104005SJeremy L Thompson "composite operator of shape (%td, %td) not compatible with " 10652b104005SJeremy L Thompson "sub-operator of shape (%td, %td)", 10662b104005SJeremy L Thompson op->input_size, op->output_size, input_size, output_size); 10672b104005SJeremy L Thompson // LCOV_EXCL_STOP 1068c9366a6bSJeremy L Thompson } 1069c9366a6bSJeremy L Thompson } 1070c9366a6bSJeremy L Thompson 1071c9366a6bSJeremy L Thompson return CEED_ERROR_SUCCESS; 1072c9366a6bSJeremy L Thompson } 1073c9366a6bSJeremy L Thompson 1074c9366a6bSJeremy L Thompson /** 1075beecbf24SJeremy L Thompson @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions. 1076beecbf24SJeremy L Thompson When `reuse_assembly_data = false` (default), the CeedQFunction associated 1077beecbf24SJeremy L Thompson with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*` 1078beecbf24SJeremy L Thompson function is called. 1079beecbf24SJeremy L Thompson When `reuse_assembly_data = true`, the CeedQFunction associated with 1080beecbf24SJeremy L Thompson this CeedOperator is reused between calls to 1081beecbf24SJeremy L Thompson `CeedOperatorSetQFunctionAssemblyDataUpdated`. 10828b919e6bSJeremy L Thompson 1083beecbf24SJeremy L Thompson @param[in] op CeedOperator 1084beecbf24SJeremy L Thompson @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 10858b919e6bSJeremy L Thompson 10868b919e6bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10878b919e6bSJeremy L Thompson 10888b919e6bSJeremy L Thompson @ref Advanced 10898b919e6bSJeremy L Thompson **/ 1090beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, 1091beecbf24SJeremy L Thompson bool reuse_assembly_data) { 10928b919e6bSJeremy L Thompson int ierr; 10938b919e6bSJeremy L Thompson bool is_composite; 10948b919e6bSJeremy L Thompson 10958b919e6bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 10968b919e6bSJeremy L Thompson if (is_composite) { 10978b919e6bSJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1098beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], 1099beecbf24SJeremy L Thompson reuse_assembly_data); CeedChk(ierr); 11008b919e6bSJeremy L Thompson } 11018b919e6bSJeremy L Thompson } else { 1102beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data); 1103beecbf24SJeremy L Thompson CeedChk(ierr); 1104beecbf24SJeremy L Thompson } 1105beecbf24SJeremy L Thompson 1106beecbf24SJeremy L Thompson return CEED_ERROR_SUCCESS; 1107beecbf24SJeremy L Thompson } 1108beecbf24SJeremy L Thompson 1109beecbf24SJeremy L Thompson /** 1110beecbf24SJeremy L Thompson @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly. 1111beecbf24SJeremy L Thompson 1112beecbf24SJeremy L Thompson @param[in] op CeedOperator 11136e15d496SJeremy L Thompson @param[in] needs_data_update Boolean flag setting assembly data reuse 1114beecbf24SJeremy L Thompson 1115beecbf24SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1116beecbf24SJeremy L Thompson 1117beecbf24SJeremy L Thompson @ref Advanced 1118beecbf24SJeremy L Thompson **/ 1119beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, 1120beecbf24SJeremy L Thompson bool needs_data_update) { 1121beecbf24SJeremy L Thompson int ierr; 1122beecbf24SJeremy L Thompson bool is_composite; 1123beecbf24SJeremy L Thompson 1124beecbf24SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1125beecbf24SJeremy L Thompson if (is_composite) { 1126beecbf24SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1127beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i], 1128beecbf24SJeremy L Thompson needs_data_update); CeedChk(ierr); 1129beecbf24SJeremy L Thompson } 1130beecbf24SJeremy L Thompson } else { 1131beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled, 1132beecbf24SJeremy L Thompson needs_data_update); 11338b919e6bSJeremy L Thompson CeedChk(ierr); 11348b919e6bSJeremy L Thompson } 11358b919e6bSJeremy L Thompson 11368b919e6bSJeremy L Thompson return CEED_ERROR_SUCCESS; 11378b919e6bSJeremy L Thompson } 11388b919e6bSJeremy L Thompson 11398b919e6bSJeremy L Thompson /** 1140cd4dfc48Sjeremylt @brief Set the number of quadrature points associated with a CeedOperator. 1141cd4dfc48Sjeremylt This should be used when creating a CeedOperator where every 1142cd4dfc48Sjeremylt field has a collocated basis. This function cannot be used for 1143cd4dfc48Sjeremylt composite CeedOperators. 1144cd4dfc48Sjeremylt 1145cd4dfc48Sjeremylt @param op CeedOperator 1146cd4dfc48Sjeremylt @param num_qpts Number of quadrature points to set 1147cd4dfc48Sjeremylt 1148cd4dfc48Sjeremylt @return An error code: 0 - success, otherwise - failure 1149cd4dfc48Sjeremylt 1150e9b533fbSJeremy L Thompson @ref Advanced 1151cd4dfc48Sjeremylt **/ 1152cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 1153f04ea552SJeremy L Thompson if (op->is_composite) 1154cd4dfc48Sjeremylt // LCOV_EXCL_START 1155cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1156cd4dfc48Sjeremylt "Not defined for composite operator"); 1157cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1158cd4dfc48Sjeremylt if (op->num_qpts) 1159cd4dfc48Sjeremylt // LCOV_EXCL_START 1160cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1161cd4dfc48Sjeremylt "Number of quadrature points already defined"); 1162cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1163f04ea552SJeremy L Thompson if (op->is_immutable) 1164f04ea552SJeremy L Thompson // LCOV_EXCL_START 1165f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 1166f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 1167f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 1168cd4dfc48Sjeremylt 1169cd4dfc48Sjeremylt op->num_qpts = num_qpts; 1170cd4dfc48Sjeremylt return CEED_ERROR_SUCCESS; 1171cd4dfc48Sjeremylt } 1172cd4dfc48Sjeremylt 1173cd4dfc48Sjeremylt /** 11747a982d89SJeremy L. Thompson @brief View a CeedOperator 11757a982d89SJeremy L. Thompson 11767a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 11777a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 11787a982d89SJeremy L. Thompson 11797a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 11807a982d89SJeremy L. Thompson 11817a982d89SJeremy L. Thompson @ref User 11827a982d89SJeremy L. Thompson **/ 11837a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 11847a982d89SJeremy L. Thompson int ierr; 11857a982d89SJeremy L. Thompson 1186f04ea552SJeremy L Thompson if (op->is_composite) { 11877a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 11887a982d89SJeremy L. Thompson 1189d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 11907a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 1191d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 11927a982d89SJeremy L. Thompson CeedChk(ierr); 11937a982d89SJeremy L. Thompson } 11947a982d89SJeremy L. Thompson } else { 11957a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 11967a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 11977a982d89SJeremy L. Thompson } 1198e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11997a982d89SJeremy L. Thompson } 12003bd813ffSjeremylt 12013bd813ffSjeremylt /** 1202b7c9bbdaSJeremy L Thompson @brief Get the Ceed associated with a CeedOperator 1203b7c9bbdaSJeremy L Thompson 1204b7c9bbdaSJeremy L Thompson @param op CeedOperator 1205b7c9bbdaSJeremy L Thompson @param[out] ceed Variable to store Ceed 1206b7c9bbdaSJeremy L Thompson 1207b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1208b7c9bbdaSJeremy L Thompson 1209b7c9bbdaSJeremy L Thompson @ref Advanced 1210b7c9bbdaSJeremy L Thompson **/ 1211b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1212b7c9bbdaSJeremy L Thompson *ceed = op->ceed; 1213b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1214b7c9bbdaSJeremy L Thompson } 1215b7c9bbdaSJeremy L Thompson 1216b7c9bbdaSJeremy L Thompson /** 1217b7c9bbdaSJeremy L Thompson @brief Get the number of elements associated with a CeedOperator 1218b7c9bbdaSJeremy L Thompson 1219b7c9bbdaSJeremy L Thompson @param op CeedOperator 1220b7c9bbdaSJeremy L Thompson @param[out] num_elem Variable to store number of elements 1221b7c9bbdaSJeremy L Thompson 1222b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1223b7c9bbdaSJeremy L Thompson 1224b7c9bbdaSJeremy L Thompson @ref Advanced 1225b7c9bbdaSJeremy L Thompson **/ 1226b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 1227b7c9bbdaSJeremy L Thompson if (op->is_composite) 1228b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1229b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1230b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1231b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1232b7c9bbdaSJeremy L Thompson 1233b7c9bbdaSJeremy L Thompson *num_elem = op->num_elem; 1234b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1235b7c9bbdaSJeremy L Thompson } 1236b7c9bbdaSJeremy L Thompson 1237b7c9bbdaSJeremy L Thompson /** 1238b7c9bbdaSJeremy L Thompson @brief Get the number of quadrature points associated with a CeedOperator 1239b7c9bbdaSJeremy L Thompson 1240b7c9bbdaSJeremy L Thompson @param op CeedOperator 1241b7c9bbdaSJeremy L Thompson @param[out] num_qpts Variable to store vector number of quadrature points 1242b7c9bbdaSJeremy L Thompson 1243b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1244b7c9bbdaSJeremy L Thompson 1245b7c9bbdaSJeremy L Thompson @ref Advanced 1246b7c9bbdaSJeremy L Thompson **/ 1247b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 1248b7c9bbdaSJeremy L Thompson if (op->is_composite) 1249b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1250b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1251b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1252b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1253b7c9bbdaSJeremy L Thompson 1254b7c9bbdaSJeremy L Thompson *num_qpts = op->num_qpts; 1255b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1256b7c9bbdaSJeremy L Thompson } 1257b7c9bbdaSJeremy L Thompson 1258b7c9bbdaSJeremy L Thompson /** 12596e15d496SJeremy L Thompson @brief Estimate number of FLOPs required to apply CeedOperator on the active vector 12606e15d496SJeremy L Thompson 12616e15d496SJeremy L Thompson @param op Operator to estimate FLOPs for 12626e15d496SJeremy L Thompson @param flops Address of variable to hold FLOPs estimate 12636e15d496SJeremy L Thompson 12646e15d496SJeremy L Thompson @ref Backend 12656e15d496SJeremy L Thompson **/ 12669d36ca50SJeremy L Thompson int CeedOperatorGetFlopsEstimate(CeedOperator op, CeedSize *flops) { 12676e15d496SJeremy L Thompson int ierr; 12686e15d496SJeremy L Thompson bool is_composite; 12696e15d496SJeremy L Thompson ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12706e15d496SJeremy L Thompson 12716e15d496SJeremy L Thompson *flops = 0; 12726e15d496SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 12736e15d496SJeremy L Thompson if (is_composite) { 12746e15d496SJeremy L Thompson CeedInt num_suboperators; 12756e15d496SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 12766e15d496SJeremy L Thompson CeedOperator *sub_operators; 12776e15d496SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 12786e15d496SJeremy L Thompson 12796e15d496SJeremy L Thompson // FLOPs for each suboperator 12806e15d496SJeremy L Thompson for (CeedInt i = 0; i < num_suboperators; i++) { 12819d36ca50SJeremy L Thompson CeedSize suboperator_flops; 12826e15d496SJeremy L Thompson ierr = CeedOperatorGetFlopsEstimate(sub_operators[i], &suboperator_flops); 12836e15d496SJeremy L Thompson CeedChk(ierr); 12846e15d496SJeremy L Thompson *flops += suboperator_flops; 12856e15d496SJeremy L Thompson } 12866e15d496SJeremy L Thompson } else { 12876e15d496SJeremy L Thompson CeedInt num_input_fields, num_output_fields; 12886e15d496SJeremy L Thompson CeedOperatorField *input_fields, *output_fields; 12896e15d496SJeremy L Thompson 12906e15d496SJeremy L Thompson ierr = CeedOperatorGetFields(op, &num_input_fields, &input_fields, 12916e15d496SJeremy L Thompson &num_output_fields, &output_fields); CeedChk(ierr); 12926e15d496SJeremy L Thompson 12936e15d496SJeremy L Thompson CeedInt num_elem = 0; 12946e15d496SJeremy L Thompson ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChk(ierr); 12956e15d496SJeremy L Thompson // Input FLOPs 12966e15d496SJeremy L Thompson for (CeedInt i = 0; i < num_input_fields; i++) { 12976e15d496SJeremy L Thompson if (input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 12989d36ca50SJeremy L Thompson CeedSize restr_flops, basis_flops; 12996e15d496SJeremy L Thompson 13006e15d496SJeremy L Thompson ierr = CeedElemRestrictionGetFlopsEstimate(input_fields[i]->elem_restr, 13016e15d496SJeremy L Thompson CEED_NOTRANSPOSE, &restr_flops); CeedChk(ierr); 13026e15d496SJeremy L Thompson *flops += restr_flops; 13036e15d496SJeremy L Thompson ierr = CeedBasisGetFlopsEstimate(input_fields[i]->basis, CEED_NOTRANSPOSE, 13046e15d496SJeremy L Thompson op->qf->input_fields[i]->eval_mode, &basis_flops); CeedChk(ierr); 13056e15d496SJeremy L Thompson *flops += basis_flops * num_elem; 13066e15d496SJeremy L Thompson } 13076e15d496SJeremy L Thompson } 13086e15d496SJeremy L Thompson // QF FLOPs 13099d36ca50SJeremy L Thompson CeedInt num_qpts; 13109d36ca50SJeremy L Thompson CeedSize qf_flops; 13116e15d496SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &num_qpts); CeedChk(ierr); 13126e15d496SJeremy L Thompson ierr = CeedQFunctionGetFlopsEstimate(op->qf, &qf_flops); CeedChk(ierr); 13136e15d496SJeremy L Thompson *flops += num_elem * num_qpts * qf_flops; 13146e15d496SJeremy L Thompson // Output FLOPs 13156e15d496SJeremy L Thompson for (CeedInt i = 0; i < num_output_fields; i++) { 13166e15d496SJeremy L Thompson if (output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 13179d36ca50SJeremy L Thompson CeedSize restr_flops, basis_flops; 13186e15d496SJeremy L Thompson 13196e15d496SJeremy L Thompson ierr = CeedElemRestrictionGetFlopsEstimate(output_fields[i]->elem_restr, 13206e15d496SJeremy L Thompson CEED_TRANSPOSE, &restr_flops); CeedChk(ierr); 13216e15d496SJeremy L Thompson *flops += restr_flops; 13226e15d496SJeremy L Thompson ierr = CeedBasisGetFlopsEstimate(output_fields[i]->basis, CEED_TRANSPOSE, 13236e15d496SJeremy L Thompson op->qf->output_fields[i]->eval_mode, &basis_flops); CeedChk(ierr); 13246e15d496SJeremy L Thompson *flops += basis_flops * num_elem; 13256e15d496SJeremy L Thompson } 13266e15d496SJeremy L Thompson } 13276e15d496SJeremy L Thompson } 13286e15d496SJeremy L Thompson 13296e15d496SJeremy L Thompson return CEED_ERROR_SUCCESS; 13306e15d496SJeremy L Thompson } 13316e15d496SJeremy L Thompson 13326e15d496SJeremy L Thompson /** 13333668ca4bSJeremy L Thompson @brief Get label for a registered QFunctionContext field, or `NULL` if no 13343668ca4bSJeremy L Thompson field has been registered with this `field_name`. 13353668ca4bSJeremy L Thompson 13363668ca4bSJeremy L Thompson @param[in] op CeedOperator 13373668ca4bSJeremy L Thompson @param[in] field_name Name of field to retrieve label 13383668ca4bSJeremy L Thompson @param[out] field_label Variable to field label 13393668ca4bSJeremy L Thompson 13403668ca4bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13413668ca4bSJeremy L Thompson 13423668ca4bSJeremy L Thompson @ref User 13433668ca4bSJeremy L Thompson **/ 13443668ca4bSJeremy L Thompson int CeedOperatorContextGetFieldLabel(CeedOperator op, 13453668ca4bSJeremy L Thompson const char *field_name, 13463668ca4bSJeremy L Thompson CeedContextFieldLabel *field_label) { 13473668ca4bSJeremy L Thompson int ierr; 13483668ca4bSJeremy L Thompson 13493668ca4bSJeremy L Thompson bool is_composite; 13503668ca4bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 13513668ca4bSJeremy L Thompson if (is_composite) { 13523668ca4bSJeremy L Thompson // Check if composite label already created 13533668ca4bSJeremy L Thompson for (CeedInt i=0; i<op->num_context_labels; i++) { 13543668ca4bSJeremy L Thompson if (!strcmp(op->context_labels[i]->name, field_name)) { 13553668ca4bSJeremy L Thompson *field_label = op->context_labels[i]; 13563668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 13573668ca4bSJeremy L Thompson } 13583668ca4bSJeremy L Thompson } 13593668ca4bSJeremy L Thompson 13603668ca4bSJeremy L Thompson // Create composite label if needed 13613668ca4bSJeremy L Thompson CeedInt num_sub; 13623668ca4bSJeremy L Thompson CeedOperator *sub_operators; 13633668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label; 13643668ca4bSJeremy L Thompson 13653668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr); 13663668ca4bSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 13673668ca4bSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 13683668ca4bSJeremy L Thompson ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr); 13693668ca4bSJeremy L Thompson new_field_label->num_sub_labels = num_sub; 13703668ca4bSJeremy L Thompson 13713668ca4bSJeremy L Thompson bool label_found = false; 13723668ca4bSJeremy L Thompson for (CeedInt i=0; i<num_sub; i++) { 13733668ca4bSJeremy L Thompson if (sub_operators[i]->qf->ctx) { 13743668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label_i; 13753668ca4bSJeremy L Thompson ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, 13763668ca4bSJeremy L Thompson &new_field_label_i); CeedChk(ierr); 13773668ca4bSJeremy L Thompson if (new_field_label_i) { 13783668ca4bSJeremy L Thompson label_found = true; 13793668ca4bSJeremy L Thompson new_field_label->sub_labels[i] = new_field_label_i; 13803668ca4bSJeremy L Thompson new_field_label->name = new_field_label_i->name; 13813668ca4bSJeremy L Thompson new_field_label->description = new_field_label_i->description; 13827bfe0f0eSJeremy L Thompson if (new_field_label->type && 13837bfe0f0eSJeremy L Thompson new_field_label->type != new_field_label_i->type) { 13847bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 13857bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 13867bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 13877bfe0f0eSJeremy L Thompson "Incompatible field types on sub-operator contexts. " 13887bfe0f0eSJeremy L Thompson "%s != %s", 13897bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label->type], 13907bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label_i->type]); 13917bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 13927bfe0f0eSJeremy L Thompson } else { 13937bfe0f0eSJeremy L Thompson new_field_label->type = new_field_label_i->type; 13947bfe0f0eSJeremy L Thompson } 13957bfe0f0eSJeremy L Thompson if (new_field_label->num_values != 0 && 13967bfe0f0eSJeremy L Thompson new_field_label->num_values != new_field_label_i->num_values) { 13977bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 13987bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 13997bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 14007bfe0f0eSJeremy L Thompson "Incompatible field number of values on sub-operator" 14017bfe0f0eSJeremy L Thompson " contexts. %ld != %ld", 14027bfe0f0eSJeremy L Thompson new_field_label->num_values, new_field_label_i->num_values); 14037bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 14047bfe0f0eSJeremy L Thompson } else { 14057bfe0f0eSJeremy L Thompson new_field_label->num_values = new_field_label_i->num_values; 14067bfe0f0eSJeremy L Thompson } 14073668ca4bSJeremy L Thompson } 14083668ca4bSJeremy L Thompson } 14093668ca4bSJeremy L Thompson } 14103668ca4bSJeremy L Thompson if (!label_found) { 14113668ca4bSJeremy L Thompson // LCOV_EXCL_START 1412a48e5f43SJeremy L Thompson ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr); 14133668ca4bSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 14143668ca4bSJeremy L Thompson *field_label = NULL; 14153668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 14163668ca4bSJeremy L Thompson } else { 14173668ca4bSJeremy L Thompson // Move new composite label to operator 14183668ca4bSJeremy L Thompson if (op->num_context_labels == 0) { 14193668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr); 14203668ca4bSJeremy L Thompson op->max_context_labels = 1; 14213668ca4bSJeremy L Thompson } else if (op->num_context_labels == op->max_context_labels) { 14223668ca4bSJeremy L Thompson ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels); 14233668ca4bSJeremy L Thompson CeedChk(ierr); 14243668ca4bSJeremy L Thompson op->max_context_labels *= 2; 14253668ca4bSJeremy L Thompson } 14263668ca4bSJeremy L Thompson op->context_labels[op->num_context_labels] = new_field_label; 14273668ca4bSJeremy L Thompson *field_label = new_field_label; 14283668ca4bSJeremy L Thompson op->num_context_labels++; 14293668ca4bSJeremy L Thompson } 14303668ca4bSJeremy L Thompson 14313668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 14323668ca4bSJeremy L Thompson } else { 14333668ca4bSJeremy L Thompson return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label); 14343668ca4bSJeremy L Thompson } 14353668ca4bSJeremy L Thompson } 14363668ca4bSJeremy L Thompson 14373668ca4bSJeremy L Thompson /** 1438d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding a double precision value. 1439d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1440d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1441d8dd9a91SJeremy L Thompson 1442d8dd9a91SJeremy L Thompson @param op CeedOperator 14433668ca4bSJeremy L Thompson @param field_label Label of field to register 14447bfe0f0eSJeremy L Thompson @param values Values to set 1445d8dd9a91SJeremy L Thompson 1446d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1447d8dd9a91SJeremy L Thompson 1448d8dd9a91SJeremy L Thompson @ref User 1449d8dd9a91SJeremy L Thompson **/ 14503668ca4bSJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op, 14513668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 14527bfe0f0eSJeremy L Thompson double *values) { 14533668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, 14547bfe0f0eSJeremy L Thompson values); 1455d8dd9a91SJeremy L Thompson } 1456d8dd9a91SJeremy L Thompson 1457d8dd9a91SJeremy L Thompson /** 1458d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding an int32 value. 1459d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1460d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1461d8dd9a91SJeremy L Thompson 1462d8dd9a91SJeremy L Thompson @param op CeedOperator 14633668ca4bSJeremy L Thompson @param field_label Label of field to set 14647bfe0f0eSJeremy L Thompson @param values Values to set 1465d8dd9a91SJeremy L Thompson 1466d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1467d8dd9a91SJeremy L Thompson 1468d8dd9a91SJeremy L Thompson @ref User 1469d8dd9a91SJeremy L Thompson **/ 14703668ca4bSJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op, 14713668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 14727bfe0f0eSJeremy L Thompson int *values) { 14733668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, 14747bfe0f0eSJeremy L Thompson values); 1475d8dd9a91SJeremy L Thompson } 1476d8dd9a91SJeremy L Thompson 1477d8dd9a91SJeremy L Thompson /** 14783bd813ffSjeremylt @brief Apply CeedOperator to a vector 1479d7b241e6Sjeremylt 1480d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 1481d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 1482d7b241e6Sjeremylt CeedOperatorSetField(). 1483d7b241e6Sjeremylt 1484f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 1485f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 1486f04ea552SJeremy L Thompson 1487d7b241e6Sjeremylt @param op CeedOperator to apply 14884cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 148934138859Sjeremylt there are no active inputs 1490b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 14914cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 149234138859Sjeremylt active outputs 1493d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 14944cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1495b11c1e72Sjeremylt 1496b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1497dfdf5a53Sjeremylt 14987a982d89SJeremy L. Thompson @ref User 1499b11c1e72Sjeremylt **/ 1500692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1501692c2638Sjeremylt CeedRequest *request) { 1502d7b241e6Sjeremylt int ierr; 1503e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1504d7b241e6Sjeremylt 1505d1d35e2fSjeremylt if (op->num_elem) { 1506250756a7Sjeremylt // Standard Operator 1507cae8b89aSjeremylt if (op->Apply) { 1508250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1509cae8b89aSjeremylt } else { 1510cae8b89aSjeremylt // Zero all output vectors 1511250756a7Sjeremylt CeedQFunction qf = op->qf; 1512d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 1513d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 1514cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 1515cae8b89aSjeremylt vec = out; 1516cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 1517cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1518cae8b89aSjeremylt } 1519cae8b89aSjeremylt } 1520250756a7Sjeremylt // Apply 1521250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1522250756a7Sjeremylt } 1523f04ea552SJeremy L Thompson } else if (op->is_composite) { 1524250756a7Sjeremylt // Composite Operator 1525250756a7Sjeremylt if (op->ApplyComposite) { 1526250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1527250756a7Sjeremylt } else { 1528d1d35e2fSjeremylt CeedInt num_suboperators; 1529d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1530d1d35e2fSjeremylt CeedOperator *sub_operators; 1531d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1532250756a7Sjeremylt 1533250756a7Sjeremylt // Zero all output vectors 1534250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 1535cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1536cae8b89aSjeremylt } 1537d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1538d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 1539d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 1540250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1541250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1542250756a7Sjeremylt } 1543250756a7Sjeremylt } 1544250756a7Sjeremylt } 1545250756a7Sjeremylt // Apply 1546d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 1547d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 1548cae8b89aSjeremylt CeedChk(ierr); 1549cae8b89aSjeremylt } 1550cae8b89aSjeremylt } 1551250756a7Sjeremylt } 1552e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1553cae8b89aSjeremylt } 1554cae8b89aSjeremylt 1555cae8b89aSjeremylt /** 1556cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 1557cae8b89aSjeremylt 1558cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 1559cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 1560cae8b89aSjeremylt CeedOperatorSetField(). 1561cae8b89aSjeremylt 1562cae8b89aSjeremylt @param op CeedOperator to apply 1563cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 1564cae8b89aSjeremylt active inputs 1565cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 1566cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 1567cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 15684cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1569cae8b89aSjeremylt 1570cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 1571cae8b89aSjeremylt 15727a982d89SJeremy L. Thompson @ref User 1573cae8b89aSjeremylt **/ 1574cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1575cae8b89aSjeremylt CeedRequest *request) { 1576cae8b89aSjeremylt int ierr; 1577e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1578cae8b89aSjeremylt 1579d1d35e2fSjeremylt if (op->num_elem) { 1580250756a7Sjeremylt // Standard Operator 1581250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1582f04ea552SJeremy L Thompson } else if (op->is_composite) { 1583250756a7Sjeremylt // Composite Operator 1584250756a7Sjeremylt if (op->ApplyAddComposite) { 1585250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1586cae8b89aSjeremylt } else { 1587d1d35e2fSjeremylt CeedInt num_suboperators; 1588d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1589d1d35e2fSjeremylt CeedOperator *sub_operators; 1590d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1591250756a7Sjeremylt 1592d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1593d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 1594cae8b89aSjeremylt CeedChk(ierr); 15951d7d2407SJeremy L Thompson } 1596250756a7Sjeremylt } 1597250756a7Sjeremylt } 1598e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1599d7b241e6Sjeremylt } 1600d7b241e6Sjeremylt 1601d7b241e6Sjeremylt /** 1602b11c1e72Sjeremylt @brief Destroy a CeedOperator 1603d7b241e6Sjeremylt 1604d7b241e6Sjeremylt @param op CeedOperator to destroy 1605b11c1e72Sjeremylt 1606b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1607dfdf5a53Sjeremylt 16087a982d89SJeremy L. Thompson @ref User 1609b11c1e72Sjeremylt **/ 1610d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1611d7b241e6Sjeremylt int ierr; 1612d7b241e6Sjeremylt 1613d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 1614d7b241e6Sjeremylt if ((*op)->Destroy) { 1615d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1616d7b241e6Sjeremylt } 1617fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1618fe2413ffSjeremylt // Free fields 16193668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1620d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 1621d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 1622d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 162371352a93Sjeremylt CeedChk(ierr); 162415910d16Sjeremylt } 1625d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1626d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 162771352a93Sjeremylt } 1628d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 1629d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 1630d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 163171352a93Sjeremylt } 1632d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 1633d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 1634fe2413ffSjeremylt } 16353668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1636d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 1637d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 163871352a93Sjeremylt CeedChk(ierr); 1639d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1640d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 164171352a93Sjeremylt } 1642d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 1643d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 1644d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 164571352a93Sjeremylt } 1646d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 1647d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 1648fe2413ffSjeremylt } 1649d1d35e2fSjeremylt // Destroy sub_operators 16503668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_suboperators; i++) 1651d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 1652d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 165352d6035fSJeremy L Thompson } 1654d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1655d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1656d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 16573668ca4bSJeremy L Thompson // Destroy any composite labels 16583668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_context_labels; i++) { 16593668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr); 16603668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr); 16613668ca4bSJeremy L Thompson } 16623668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr); 1663fe2413ffSjeremylt 16645107b09fSJeremy L Thompson // Destroy fallback 1665d1d35e2fSjeremylt if ((*op)->op_fallback) { 1666d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 1667d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 1668d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 1669d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 16705107b09fSJeremy L Thompson } 16715107b09fSJeremy L Thompson 167270a7ffb3SJeremy L Thompson // Destroy QF assembly cache 1673480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr); 167470a7ffb3SJeremy L Thompson 1675d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 1676d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 1677d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 1678d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1679e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1680d7b241e6Sjeremylt } 1681d7b241e6Sjeremylt 1682d7b241e6Sjeremylt /// @} 1683