1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3d7b241e6Sjeremylt // 4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 5d7b241e6Sjeremylt // 6*3d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 7d7b241e6Sjeremylt 8ec3da8bcSJed Brown #include <ceed/ceed.h> 9ec3da8bcSJed Brown #include <ceed/backend.h> 103d576824SJeremy L Thompson #include <ceed-impl.h> 113d576824SJeremy L Thompson #include <stdbool.h> 123d576824SJeremy L Thompson #include <stdio.h> 133d576824SJeremy L Thompson #include <string.h> 14d7b241e6Sjeremylt 15dfdf5a53Sjeremylt /// @file 167a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 177a982d89SJeremy L. Thompson 187a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 197a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 207a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 217a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 227a982d89SJeremy L. Thompson /// @{ 237a982d89SJeremy L. Thompson 247a982d89SJeremy L. Thompson /** 25e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 26e15f9bd0SJeremy L Thompson 27e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 28d1d35e2fSjeremylt @param[in] qf_field QFunction Field matching Operator Field 29e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 30e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 31e15f9bd0SJeremy L Thompson 32e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 33e15f9bd0SJeremy L Thompson 34e15f9bd0SJeremy L Thompson @ref Developer 35e15f9bd0SJeremy L Thompson **/ 36d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, 37e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 38e15f9bd0SJeremy L Thompson int ierr; 39d1d35e2fSjeremylt CeedEvalMode eval_mode = qf_field->eval_mode; 40d1d35e2fSjeremylt CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size; 41e15f9bd0SJeremy L Thompson // Restriction 42e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 43d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { 44e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 45e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 46e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE should be used " 47e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 48e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 49e15f9bd0SJeremy L Thompson } 50d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp); 5178464608Sjeremylt CeedChk(ierr); 52e1e9e29dSJed Brown } 53d1d35e2fSjeremylt if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) { 54e1e9e29dSJed Brown // LCOV_EXCL_START 55e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 56e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 57e1e9e29dSJed Brown "must be used together."); 58e1e9e29dSJed Brown // LCOV_EXCL_STOP 59e1e9e29dSJed Brown } 60e15f9bd0SJeremy L Thompson // Basis 61e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 62d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) 638229195eSjeremylt // LCOV_EXCL_START 64e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 65d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 66d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 678229195eSjeremylt // LCOV_EXCL_STOP 68d1d35e2fSjeremylt qf_field->field_name); 69e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 70d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 71d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 72e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 73e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 74d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 75d1d35e2fSjeremylt "has %d components, but Basis has %d components", 76d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 77d1d35e2fSjeremylt restr_num_comp, 78d1d35e2fSjeremylt num_comp); 79e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 80e15f9bd0SJeremy L Thompson } 81e15f9bd0SJeremy L Thompson } 82e15f9bd0SJeremy L Thompson // Field size 83d1d35e2fSjeremylt switch(eval_mode) { 84e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 85d1d35e2fSjeremylt if (size != restr_num_comp) 86e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 87e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 88e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 89d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 90d1d35e2fSjeremylt restr_num_comp); 91e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 92e15f9bd0SJeremy L Thompson break; 93e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 94d1d35e2fSjeremylt if (size != num_comp) 95e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 96e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 97e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 98d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 99d1d35e2fSjeremylt num_comp); 100e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 101e15f9bd0SJeremy L Thompson break; 102e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 103d1d35e2fSjeremylt if (size != num_comp * dim) 104e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 105e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 106d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 107d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 108d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 109d1d35e2fSjeremylt num_comp); 110e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 111e15f9bd0SJeremy L Thompson break; 112e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 113d1d35e2fSjeremylt // No additional checks required 114e15f9bd0SJeremy L Thompson break; 115e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 116e15f9bd0SJeremy L Thompson // Not implemented 117e15f9bd0SJeremy L Thompson break; 118e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 119e15f9bd0SJeremy L Thompson // Not implemented 120e15f9bd0SJeremy L Thompson break; 121e15f9bd0SJeremy L Thompson } 122e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1237a982d89SJeremy L. Thompson } 1247a982d89SJeremy L. Thompson 1257a982d89SJeremy L. Thompson /** 1267a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 1277a982d89SJeremy L. Thompson 1287a982d89SJeremy L. Thompson @param[in] field Operator field to view 129d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 130d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 1314c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 132d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 1337a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 1347a982d89SJeremy L. Thompson 1357a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1367a982d89SJeremy L. Thompson 1377a982d89SJeremy L. Thompson @ref Utility 1387a982d89SJeremy L. Thompson **/ 1397a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 140d1d35e2fSjeremylt CeedQFunctionField qf_field, 141d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 1427a982d89SJeremy L. Thompson FILE *stream) { 1437a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 144d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 1457a982d89SJeremy L. Thompson 1467a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 1477a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 148d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 1497a982d89SJeremy L. Thompson 1507a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 1517a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 1527a982d89SJeremy L. Thompson 1537a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 1547a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 1557a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 1567a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 157e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1587a982d89SJeremy L. Thompson } 1597a982d89SJeremy L. Thompson 1607a982d89SJeremy L. Thompson /** 1617a982d89SJeremy L. Thompson @brief View a single CeedOperator 1627a982d89SJeremy L. Thompson 1637a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 1647a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 1657a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 1667a982d89SJeremy L. Thompson 1677a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 1687a982d89SJeremy L. Thompson 1697a982d89SJeremy L. Thompson @ref Utility 1707a982d89SJeremy L. Thompson **/ 1717a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 1727a982d89SJeremy L. Thompson int ierr; 1737a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 1747a982d89SJeremy L. Thompson 17578464608Sjeremylt CeedInt total_fields = 0; 17678464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 1777a982d89SJeremy L. Thompson 17878464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 17978464608Sjeremylt total_fields>1 ? "s" : ""); 1807a982d89SJeremy L. Thompson 181d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 182d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 183d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 184d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 1857a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 1867a982d89SJeremy L. Thompson } 1877a982d89SJeremy L. Thompson 188d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 189d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 190d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 191d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 1927a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 1937a982d89SJeremy L. Thompson } 194e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1957a982d89SJeremy L. Thompson } 1967a982d89SJeremy L. Thompson 197d99fa3c5SJeremy L Thompson /** 198eaf62fffSJeremy L Thompson @brief Find the active vector basis for a CeedOperator 199eaf62fffSJeremy L Thompson 200eaf62fffSJeremy L Thompson @param[in] op CeedOperator to find active basis for 201eaf62fffSJeremy L Thompson @param[out] active_basis Basis for active input vector 202eaf62fffSJeremy L Thompson 203eaf62fffSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 204eaf62fffSJeremy L Thompson 205eaf62fffSJeremy L Thompson @ ref Developer 206eaf62fffSJeremy L Thompson **/ 207eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) { 208eaf62fffSJeremy L Thompson *active_basis = NULL; 209eaf62fffSJeremy L Thompson for (int i = 0; i < op->qf->num_input_fields; i++) 210eaf62fffSJeremy L Thompson if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 211eaf62fffSJeremy L Thompson *active_basis = op->input_fields[i]->basis; 212eaf62fffSJeremy L Thompson break; 213eaf62fffSJeremy L Thompson } 214eaf62fffSJeremy L Thompson 215eaf62fffSJeremy L Thompson if (!*active_basis) { 216eaf62fffSJeremy L Thompson // LCOV_EXCL_START 217eaf62fffSJeremy L Thompson int ierr; 218eaf62fffSJeremy L Thompson Ceed ceed; 219eaf62fffSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 220eaf62fffSJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 221eaf62fffSJeremy L Thompson "No active CeedBasis found"); 222eaf62fffSJeremy L Thompson // LCOV_EXCL_STOP 223eaf62fffSJeremy L Thompson } 224eaf62fffSJeremy L Thompson return CEED_ERROR_SUCCESS; 225eaf62fffSJeremy L Thompson } 226eaf62fffSJeremy L Thompson 227eaf62fffSJeremy L Thompson /** 228e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 229e2f04181SAndrew T. Barker 230e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 231d1d35e2fSjeremylt @param[out] active_rstr ElemRestriction for active input vector 232e2f04181SAndrew T. Barker 233e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 234e2f04181SAndrew T. Barker 235e2f04181SAndrew T. Barker @ref Utility 236e2f04181SAndrew T. Barker **/ 237eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op, 238d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 239d1d35e2fSjeremylt *active_rstr = NULL; 240d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 241d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 242d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 243e2f04181SAndrew T. Barker break; 244e2f04181SAndrew T. Barker } 245e2f04181SAndrew T. Barker 246d1d35e2fSjeremylt if (!*active_rstr) { 247e2f04181SAndrew T. Barker // LCOV_EXCL_START 248e2f04181SAndrew T. Barker int ierr; 249e2f04181SAndrew T. Barker Ceed ceed; 250e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 251e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 252eaf62fffSJeremy L Thompson "No active CeedElemRestriction found"); 253e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 254e2f04181SAndrew T. Barker } 255e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 256e2f04181SAndrew T. Barker } 257e2f04181SAndrew T. Barker 258d8dd9a91SJeremy L Thompson /** 259d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field value of the specified type. 260d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 261d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 262d8dd9a91SJeremy L Thompson A non-zero error code is returned for single operators 263d8dd9a91SJeremy L Thompson that do not have a matching field of the same type or composite 264d8dd9a91SJeremy L Thompson operators that do not have any field of a matching type. 265d8dd9a91SJeremy L Thompson 266d8dd9a91SJeremy L Thompson @param op CeedOperator 2673668ca4bSJeremy L Thompson @param field_label Label of field to set 268d8dd9a91SJeremy L Thompson @param field_type Type of field to set 269d8dd9a91SJeremy L Thompson @param value Value to set 270d8dd9a91SJeremy L Thompson 271d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 272d8dd9a91SJeremy L Thompson 273d8dd9a91SJeremy L Thompson @ref User 274d8dd9a91SJeremy L Thompson **/ 275d8dd9a91SJeremy L Thompson static int CeedOperatorContextSetGeneric(CeedOperator op, 2763668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, CeedContextFieldType field_type, 2773668ca4bSJeremy L Thompson void *value) { 278d8dd9a91SJeremy L Thompson int ierr; 279d8dd9a91SJeremy L Thompson 2803668ca4bSJeremy L Thompson if (!field_label) 2813668ca4bSJeremy L Thompson // LCOV_EXCL_START 2823668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 2833668ca4bSJeremy L Thompson "Invalid field label"); 2843668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 2853668ca4bSJeremy L Thompson 2863668ca4bSJeremy L Thompson bool is_composite = false; 287d8dd9a91SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 288d8dd9a91SJeremy L Thompson if (is_composite) { 289d8dd9a91SJeremy L Thompson CeedInt num_sub; 290d8dd9a91SJeremy L Thompson CeedOperator *sub_operators; 291d8dd9a91SJeremy L Thompson 292d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 293d8dd9a91SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2943668ca4bSJeremy L Thompson if (num_sub != field_label->num_sub_labels) 2953668ca4bSJeremy L Thompson // LCOV_EXCL_START 2963668ca4bSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 2973668ca4bSJeremy L Thompson "ContextLabel does not correspond to composite operator.\n" 2983668ca4bSJeremy L Thompson "Use CeedOperatorGetContextFieldLabel()."); 2993668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 300d8dd9a91SJeremy L Thompson 301d8dd9a91SJeremy L Thompson for (CeedInt i = 0; i < num_sub; i++) { 302d8dd9a91SJeremy L Thompson // Try every sub-operator, ok if some sub-operators do not have field 3033668ca4bSJeremy L Thompson if (field_label->sub_labels[i] && sub_operators[i]->qf->ctx) { 3043668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(sub_operators[i]->qf->ctx, 3053668ca4bSJeremy L Thompson field_label->sub_labels[i], 3063668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 307d8dd9a91SJeremy L Thompson } 308d8dd9a91SJeremy L Thompson } 309d8dd9a91SJeremy L Thompson } else { 310d8dd9a91SJeremy L Thompson if (!op->qf->ctx) 311d8dd9a91SJeremy L Thompson // LCOV_EXCL_START 312d8dd9a91SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 313d8dd9a91SJeremy L Thompson "QFunction does not have context data"); 314d8dd9a91SJeremy L Thompson // LCOV_EXCL_STOP 315d8dd9a91SJeremy L Thompson 3163668ca4bSJeremy L Thompson ierr = CeedQFunctionContextSetGeneric(op->qf->ctx, field_label, 3173668ca4bSJeremy L Thompson field_type, value); CeedChk(ierr); 318d8dd9a91SJeremy L Thompson } 319d8dd9a91SJeremy L Thompson 320d8dd9a91SJeremy L Thompson return CEED_ERROR_SUCCESS; 321d8dd9a91SJeremy L Thompson } 322d8dd9a91SJeremy L Thompson 3237a982d89SJeremy L. Thompson /// @} 3247a982d89SJeremy L. Thompson 3257a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3267a982d89SJeremy L. Thompson /// CeedOperator Backend API 3277a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3287a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 3297a982d89SJeremy L. Thompson /// @{ 3307a982d89SJeremy L. Thompson 3317a982d89SJeremy L. Thompson /** 3327a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 3337a982d89SJeremy L. Thompson 3347a982d89SJeremy L. Thompson @param op CeedOperator 335d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 3367a982d89SJeremy L. Thompson 3377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3387a982d89SJeremy L. Thompson 3397a982d89SJeremy L. Thompson @ref Backend 3407a982d89SJeremy L. Thompson **/ 3417a982d89SJeremy L. Thompson 342d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 343f04ea552SJeremy L Thompson if (op->is_composite) 3447a982d89SJeremy L. Thompson // LCOV_EXCL_START 345e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 346e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 3477a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3487a982d89SJeremy L. Thompson 349d1d35e2fSjeremylt *num_args = op->num_fields; 350e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3517a982d89SJeremy L. Thompson } 3527a982d89SJeremy L. Thompson 3537a982d89SJeremy L. Thompson /** 3547a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 3557a982d89SJeremy L. Thompson 3567a982d89SJeremy L. Thompson @param op CeedOperator 357d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 3587a982d89SJeremy L. Thompson 3597a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3607a982d89SJeremy L. Thompson 3617a982d89SJeremy L. Thompson @ref Backend 3627a982d89SJeremy L. Thompson **/ 3637a982d89SJeremy L. Thompson 364d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 365f04ea552SJeremy L Thompson *is_setup_done = op->is_backend_setup; 366e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3677a982d89SJeremy L. Thompson } 3687a982d89SJeremy L. Thompson 3697a982d89SJeremy L. Thompson /** 3707a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 3717a982d89SJeremy L. Thompson 3727a982d89SJeremy L. Thompson @param op CeedOperator 3737a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 3747a982d89SJeremy L. Thompson 3757a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3767a982d89SJeremy L. Thompson 3777a982d89SJeremy L. Thompson @ref Backend 3787a982d89SJeremy L. Thompson **/ 3797a982d89SJeremy L. Thompson 3807a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 381f04ea552SJeremy L Thompson if (op->is_composite) 3827a982d89SJeremy L. Thompson // LCOV_EXCL_START 383e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 384e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 3857a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 3867a982d89SJeremy L. Thompson 3877a982d89SJeremy L. Thompson *qf = op->qf; 388e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3897a982d89SJeremy L. Thompson } 3907a982d89SJeremy L. Thompson 3917a982d89SJeremy L. Thompson /** 392c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 393c04a41a7SJeremy L Thompson 394c04a41a7SJeremy L Thompson @param op CeedOperator 395d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 396c04a41a7SJeremy L Thompson 397c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 398c04a41a7SJeremy L Thompson 399c04a41a7SJeremy L Thompson @ref Backend 400c04a41a7SJeremy L Thompson **/ 401c04a41a7SJeremy L Thompson 402d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 403f04ea552SJeremy L Thompson *is_composite = op->is_composite; 404e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 405c04a41a7SJeremy L Thompson } 406c04a41a7SJeremy L Thompson 407c04a41a7SJeremy L Thompson /** 408d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 4097a982d89SJeremy L. Thompson 4107a982d89SJeremy L. Thompson @param op CeedOperator 411d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 4127a982d89SJeremy L. Thompson 4137a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4147a982d89SJeremy L. Thompson 4157a982d89SJeremy L. Thompson @ref Backend 4167a982d89SJeremy L. Thompson **/ 4177a982d89SJeremy L. Thompson 418d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 419f04ea552SJeremy L Thompson if (!op->is_composite) 4207a982d89SJeremy L. Thompson // LCOV_EXCL_START 421e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4227a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4237a982d89SJeremy L. Thompson 424d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 425e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4267a982d89SJeremy L. Thompson } 4277a982d89SJeremy L. Thompson 4287a982d89SJeremy L. Thompson /** 429d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 4307a982d89SJeremy L. Thompson 4317a982d89SJeremy L. Thompson @param op CeedOperator 432d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 4337a982d89SJeremy L. Thompson 4347a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4357a982d89SJeremy L. Thompson 4367a982d89SJeremy L. Thompson @ref Backend 4377a982d89SJeremy L. Thompson **/ 4387a982d89SJeremy L. Thompson 439d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 440f04ea552SJeremy L Thompson if (!op->is_composite) 4417a982d89SJeremy L. Thompson // LCOV_EXCL_START 442e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 4437a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4447a982d89SJeremy L. Thompson 445d1d35e2fSjeremylt *sub_operators = op->sub_operators; 446e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4477a982d89SJeremy L. Thompson } 4487a982d89SJeremy L. Thompson 4497a982d89SJeremy L. Thompson /** 4507a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 4517a982d89SJeremy L. Thompson 4527a982d89SJeremy L. Thompson @param op CeedOperator 4537a982d89SJeremy L. Thompson @param[out] data Variable to store data 4547a982d89SJeremy L. Thompson 4557a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4567a982d89SJeremy L. Thompson 4577a982d89SJeremy L. Thompson @ref Backend 4587a982d89SJeremy L. Thompson **/ 4597a982d89SJeremy L. Thompson 460777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 461777ff853SJeremy L Thompson *(void **)data = op->data; 462e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4637a982d89SJeremy L. Thompson } 4647a982d89SJeremy L. Thompson 4657a982d89SJeremy L. Thompson /** 4667a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 4677a982d89SJeremy L. Thompson 4687a982d89SJeremy L. Thompson @param[out] op CeedOperator 4697a982d89SJeremy L. Thompson @param data Data to set 4707a982d89SJeremy L. Thompson 4717a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4727a982d89SJeremy L. Thompson 4737a982d89SJeremy L. Thompson @ref Backend 4747a982d89SJeremy L. Thompson **/ 4757a982d89SJeremy L. Thompson 476777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 477777ff853SJeremy L Thompson op->data = data; 478e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4797a982d89SJeremy L. Thompson } 4807a982d89SJeremy L. Thompson 4817a982d89SJeremy L. Thompson /** 48234359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 48334359f16Sjeremylt 48434359f16Sjeremylt @param op CeedOperator to increment the reference counter 48534359f16Sjeremylt 48634359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 48734359f16Sjeremylt 48834359f16Sjeremylt @ref Backend 48934359f16Sjeremylt **/ 4909560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 49134359f16Sjeremylt op->ref_count++; 49234359f16Sjeremylt return CEED_ERROR_SUCCESS; 49334359f16Sjeremylt } 49434359f16Sjeremylt 49534359f16Sjeremylt /** 4967a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 4977a982d89SJeremy L. Thompson 4987a982d89SJeremy L. Thompson @param op CeedOperator 4997a982d89SJeremy L. Thompson 5007a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5017a982d89SJeremy L. Thompson 5027a982d89SJeremy L. Thompson @ref Backend 5037a982d89SJeremy L. Thompson **/ 5047a982d89SJeremy L. Thompson 5057a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 506f04ea552SJeremy L Thompson op->is_backend_setup = true; 507e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5087a982d89SJeremy L. Thompson } 5097a982d89SJeremy L. Thompson 5107a982d89SJeremy L. Thompson /// @} 5117a982d89SJeremy L. Thompson 5127a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5137a982d89SJeremy L. Thompson /// CeedOperator Public API 5147a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5157a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 516dfdf5a53Sjeremylt /// @{ 517d7b241e6Sjeremylt 518d7b241e6Sjeremylt /** 5190219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 5200219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 5210219ea01SJeremy L Thompson \ref CeedOperatorSetField. 522d7b241e6Sjeremylt 523b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 524d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 52534138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 5264cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 527d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 5284cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 529b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 530b11c1e72Sjeremylt CeedOperator will be stored 531b11c1e72Sjeremylt 532b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 533dfdf5a53Sjeremylt 5347a982d89SJeremy L. Thompson @ref User 535d7b241e6Sjeremylt */ 536d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 537d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 538d7b241e6Sjeremylt int ierr; 539d7b241e6Sjeremylt 5405fe0d4faSjeremylt if (!ceed->OperatorCreate) { 5415fe0d4faSjeremylt Ceed delegate; 542aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 5435fe0d4faSjeremylt 5445fe0d4faSjeremylt if (!delegate) 545c042f62fSJeremy L Thompson // LCOV_EXCL_START 546e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 547e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 548c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 5495fe0d4faSjeremylt 5505fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 551e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5525fe0d4faSjeremylt } 5535fe0d4faSjeremylt 554b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 555b3b7035fSJeremy L Thompson // LCOV_EXCL_START 556e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 557e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 558b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 559d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 560d7b241e6Sjeremylt (*op)->ceed = ceed; 5619560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 562d1d35e2fSjeremylt (*op)->ref_count = 1; 563d7b241e6Sjeremylt (*op)->qf = qf; 5649560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 565442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 566d7b241e6Sjeremylt (*op)->dqf = dqf; 5679560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 568442e7f0bSjeremylt } 569442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 570d7b241e6Sjeremylt (*op)->dqfT = dqfT; 5719560d06aSjeremylt ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 572442e7f0bSjeremylt } 573480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataCreate(ceed, &(*op)->qf_assembled); 574480fae85SJeremy L Thompson CeedChk(ierr); 575bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->input_fields); CeedChk(ierr); 576bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &(*op)->output_fields); CeedChk(ierr); 577d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 578e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 579d7b241e6Sjeremylt } 580d7b241e6Sjeremylt 581d7b241e6Sjeremylt /** 58252d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 58352d6035fSJeremy L Thompson 58452d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 58552d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 58652d6035fSJeremy L Thompson Composite CeedOperator will be stored 58752d6035fSJeremy L Thompson 58852d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 58952d6035fSJeremy L Thompson 5907a982d89SJeremy L. Thompson @ref User 59152d6035fSJeremy L Thompson */ 59252d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 59352d6035fSJeremy L Thompson int ierr; 59452d6035fSJeremy L Thompson 59552d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 59652d6035fSJeremy L Thompson Ceed delegate; 597aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 59852d6035fSJeremy L Thompson 599250756a7Sjeremylt if (delegate) { 60052d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 601e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 60252d6035fSJeremy L Thompson } 603250756a7Sjeremylt } 60452d6035fSJeremy L Thompson 60552d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 60652d6035fSJeremy L Thompson (*op)->ceed = ceed; 6079560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 608f04ea552SJeremy L Thompson (*op)->is_composite = true; 609bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_COMPOSITE_MAX, &(*op)->sub_operators); CeedChk(ierr); 610250756a7Sjeremylt 611250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 61252d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 613250756a7Sjeremylt } 614e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 61552d6035fSJeremy L Thompson } 61652d6035fSJeremy L Thompson 61752d6035fSJeremy L Thompson /** 6189560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 6199560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 6209560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 6219560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 6229560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 6239560d06aSjeremylt reference to this CeedOperator. 6249560d06aSjeremylt 6259560d06aSjeremylt @param op CeedOperator to copy reference to 6269560d06aSjeremylt @param[out] op_copy Variable to store copied reference 6279560d06aSjeremylt 6289560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 6299560d06aSjeremylt 6309560d06aSjeremylt @ref User 6319560d06aSjeremylt **/ 6329560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 6339560d06aSjeremylt int ierr; 6349560d06aSjeremylt 6359560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 6369560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 6379560d06aSjeremylt *op_copy = op; 6389560d06aSjeremylt return CEED_ERROR_SUCCESS; 6399560d06aSjeremylt } 6409560d06aSjeremylt 6419560d06aSjeremylt /** 642b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 643d7b241e6Sjeremylt 644d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 645d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 646d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 647d7b241e6Sjeremylt 648d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 649d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 650d7b241e6Sjeremylt input and at most one active output. 651d7b241e6Sjeremylt 6528c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 653d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 6548795c945Sjeremylt CeedQFunction) 655b11c1e72Sjeremylt @param r CeedElemRestriction 6564cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 657b11c1e72Sjeremylt if collocated with quadrature points 6584cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 6594cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 6604cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 661b11c1e72Sjeremylt 662b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 663dfdf5a53Sjeremylt 6647a982d89SJeremy L. Thompson @ref User 665b11c1e72Sjeremylt **/ 666d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 667a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 668d7b241e6Sjeremylt int ierr; 669f04ea552SJeremy L Thompson if (op->is_composite) 670c042f62fSJeremy L Thompson // LCOV_EXCL_START 671e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 672e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 673c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 674f04ea552SJeremy L Thompson if (op->is_immutable) 675f04ea552SJeremy L Thompson // LCOV_EXCL_START 676f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 677f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 678f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 6798b067b84SJed Brown if (!r) 680c042f62fSJeremy L Thompson // LCOV_EXCL_START 681e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 682c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 683d1d35e2fSjeremylt field_name); 684c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6858b067b84SJed Brown if (!b) 686c042f62fSJeremy L Thompson // LCOV_EXCL_START 687e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 688e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 689d1d35e2fSjeremylt field_name); 690c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6918b067b84SJed Brown if (!v) 692c042f62fSJeremy L Thompson // LCOV_EXCL_START 693e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 694e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 695d1d35e2fSjeremylt field_name); 696c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 69752d6035fSJeremy L Thompson 698d1d35e2fSjeremylt CeedInt num_elem; 699d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 700d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 701d1d35e2fSjeremylt op->num_elem != num_elem) 702c042f62fSJeremy L Thompson // LCOV_EXCL_START 703e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 7041d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 705d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 706c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 707d7b241e6Sjeremylt 70878464608Sjeremylt CeedInt num_qpts = 0; 709e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 710d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 711d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 712c042f62fSJeremy L Thompson // LCOV_EXCL_START 713e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 714e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 715d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 716d1d35e2fSjeremylt op->num_qpts); 717c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 718d7b241e6Sjeremylt } 719d1d35e2fSjeremylt CeedQFunctionField qf_field; 720d1d35e2fSjeremylt CeedOperatorField *op_field; 721d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 722d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 723d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 724d1d35e2fSjeremylt op_field = &op->input_fields[i]; 725d7b241e6Sjeremylt goto found; 726d7b241e6Sjeremylt } 727d7b241e6Sjeremylt } 728d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 729d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 730d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 731d1d35e2fSjeremylt op_field = &op->output_fields[i]; 732d7b241e6Sjeremylt goto found; 733d7b241e6Sjeremylt } 734d7b241e6Sjeremylt } 735c042f62fSJeremy L Thompson // LCOV_EXCL_START 736e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 737e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 738d1d35e2fSjeremylt field_name); 739c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 740d7b241e6Sjeremylt found: 741d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 742d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 743e15f9bd0SJeremy L Thompson 744d1d35e2fSjeremylt (*op_field)->vec = v; 745e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 7469560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 747e15f9bd0SJeremy L Thompson } 748e15f9bd0SJeremy L Thompson 749d1d35e2fSjeremylt (*op_field)->elem_restr = r; 7509560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 751e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 752d1d35e2fSjeremylt op->num_elem = num_elem; 753d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 754e15f9bd0SJeremy L Thompson } 755d99fa3c5SJeremy L Thompson 756d1d35e2fSjeremylt (*op_field)->basis = b; 757e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 758cd4dfc48Sjeremylt if (!op->num_qpts) { 759cd4dfc48Sjeremylt ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 760cd4dfc48Sjeremylt } 7619560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 762e15f9bd0SJeremy L Thompson } 763e15f9bd0SJeremy L Thompson 764d1d35e2fSjeremylt op->num_fields += 1; 765f7e22acaSJeremy L Thompson ierr = CeedStringAllocCopy(field_name, (char **)&(*op_field)->field_name); 766f7e22acaSJeremy L Thompson CeedChk(ierr); 767e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 768d7b241e6Sjeremylt } 769d7b241e6Sjeremylt 770d7b241e6Sjeremylt /** 77143bbe138SJeremy L Thompson @brief Get the CeedOperatorFields of a CeedOperator 77243bbe138SJeremy L Thompson 773f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 774f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 775f04ea552SJeremy L Thompson 77643bbe138SJeremy L Thompson @param op CeedOperator 777f74ec584SJeremy L Thompson @param[out] num_input_fields Variable to store number of input fields 77843bbe138SJeremy L Thompson @param[out] input_fields Variable to store input_fields 779f74ec584SJeremy L Thompson @param[out] num_output_fields Variable to store number of output fields 78043bbe138SJeremy L Thompson @param[out] output_fields Variable to store output_fields 78143bbe138SJeremy L Thompson 78243bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 78343bbe138SJeremy L Thompson 784e9b533fbSJeremy L Thompson @ref Advanced 78543bbe138SJeremy L Thompson **/ 78643bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields, 78743bbe138SJeremy L Thompson CeedOperatorField **input_fields, 78843bbe138SJeremy L Thompson CeedInt *num_output_fields, 78943bbe138SJeremy L Thompson CeedOperatorField **output_fields) { 790f04ea552SJeremy L Thompson int ierr; 791f04ea552SJeremy L Thompson 792f04ea552SJeremy L Thompson if (op->is_composite) 79343bbe138SJeremy L Thompson // LCOV_EXCL_START 79443bbe138SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 79543bbe138SJeremy L Thompson "Not defined for composite operator"); 79643bbe138SJeremy L Thompson // LCOV_EXCL_STOP 797f04ea552SJeremy L Thompson ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 79843bbe138SJeremy L Thompson 79943bbe138SJeremy L Thompson if (num_input_fields) *num_input_fields = op->qf->num_input_fields; 80043bbe138SJeremy L Thompson if (input_fields) *input_fields = op->input_fields; 80143bbe138SJeremy L Thompson if (num_output_fields) *num_output_fields = op->qf->num_output_fields; 80243bbe138SJeremy L Thompson if (output_fields) *output_fields = op->output_fields; 80343bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 80443bbe138SJeremy L Thompson } 80543bbe138SJeremy L Thompson 80643bbe138SJeremy L Thompson /** 80728567f8fSJeremy L Thompson @brief Get the name of a CeedOperatorField 80828567f8fSJeremy L Thompson 80928567f8fSJeremy L Thompson @param op_field CeedOperatorField 81028567f8fSJeremy L Thompson @param[out] field_name Variable to store the field name 81128567f8fSJeremy L Thompson 81228567f8fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 81328567f8fSJeremy L Thompson 814e9b533fbSJeremy L Thompson @ref Advanced 81528567f8fSJeremy L Thompson **/ 81628567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) { 81728567f8fSJeremy L Thompson *field_name = (char *)op_field->field_name; 81828567f8fSJeremy L Thompson return CEED_ERROR_SUCCESS; 81928567f8fSJeremy L Thompson } 82028567f8fSJeremy L Thompson 82128567f8fSJeremy L Thompson /** 82243bbe138SJeremy L Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 82343bbe138SJeremy L Thompson 82443bbe138SJeremy L Thompson @param op_field CeedOperatorField 82543bbe138SJeremy L Thompson @param[out] rstr Variable to store CeedElemRestriction 82643bbe138SJeremy L Thompson 82743bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 82843bbe138SJeremy L Thompson 829e9b533fbSJeremy L Thompson @ref Advanced 83043bbe138SJeremy L Thompson **/ 83143bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 83243bbe138SJeremy L Thompson CeedElemRestriction *rstr) { 83343bbe138SJeremy L Thompson *rstr = op_field->elem_restr; 83443bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 83543bbe138SJeremy L Thompson } 83643bbe138SJeremy L Thompson 83743bbe138SJeremy L Thompson /** 83843bbe138SJeremy L Thompson @brief Get the CeedBasis of a CeedOperatorField 83943bbe138SJeremy L Thompson 84043bbe138SJeremy L Thompson @param op_field CeedOperatorField 84143bbe138SJeremy L Thompson @param[out] basis Variable to store CeedBasis 84243bbe138SJeremy L Thompson 84343bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 84443bbe138SJeremy L Thompson 845e9b533fbSJeremy L Thompson @ref Advanced 84643bbe138SJeremy L Thompson **/ 84743bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 84843bbe138SJeremy L Thompson *basis = op_field->basis; 84943bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 85043bbe138SJeremy L Thompson } 85143bbe138SJeremy L Thompson 85243bbe138SJeremy L Thompson /** 85343bbe138SJeremy L Thompson @brief Get the CeedVector of a CeedOperatorField 85443bbe138SJeremy L Thompson 85543bbe138SJeremy L Thompson @param op_field CeedOperatorField 85643bbe138SJeremy L Thompson @param[out] vec Variable to store CeedVector 85743bbe138SJeremy L Thompson 85843bbe138SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 85943bbe138SJeremy L Thompson 860e9b533fbSJeremy L Thompson @ref Advanced 86143bbe138SJeremy L Thompson **/ 86243bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 86343bbe138SJeremy L Thompson *vec = op_field->vec; 86443bbe138SJeremy L Thompson return CEED_ERROR_SUCCESS; 86543bbe138SJeremy L Thompson } 86643bbe138SJeremy L Thompson 86743bbe138SJeremy L Thompson /** 86852d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 869288c0443SJeremy L Thompson 870d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 871d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 87252d6035fSJeremy L Thompson 87352d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 87452d6035fSJeremy L Thompson 8757a982d89SJeremy L. Thompson @ref User 87652d6035fSJeremy L Thompson */ 877d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 878d1d35e2fSjeremylt CeedOperator sub_op) { 87934359f16Sjeremylt int ierr; 88034359f16Sjeremylt 881f04ea552SJeremy L Thompson if (!composite_op->is_composite) 882c042f62fSJeremy L Thompson // LCOV_EXCL_START 883d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 884e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 885c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 88652d6035fSJeremy L Thompson 887d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 888c042f62fSJeremy L Thompson // LCOV_EXCL_START 889d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 890d1d35e2fSjeremylt "Cannot add additional sub_operators"); 891c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 892f04ea552SJeremy L Thompson if (composite_op->is_immutable) 893f04ea552SJeremy L Thompson // LCOV_EXCL_START 894f04ea552SJeremy L Thompson return CeedError(composite_op->ceed, CEED_ERROR_MAJOR, 895f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 896f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 89752d6035fSJeremy L Thompson 898d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 8999560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 900d1d35e2fSjeremylt composite_op->num_suboperators++; 901e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 90252d6035fSJeremy L Thompson } 90352d6035fSJeremy L Thompson 90452d6035fSJeremy L Thompson /** 9054db537f9SJeremy L Thompson @brief Check if a CeedOperator is ready to be used. 9064db537f9SJeremy L Thompson 9074db537f9SJeremy L Thompson @param[in] op CeedOperator to check 9084db537f9SJeremy L Thompson 9094db537f9SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9104db537f9SJeremy L Thompson 9114db537f9SJeremy L Thompson @ref User 9124db537f9SJeremy L Thompson **/ 9134db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) { 9144db537f9SJeremy L Thompson int ierr; 9154db537f9SJeremy L Thompson Ceed ceed; 9164db537f9SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 9174db537f9SJeremy L Thompson 9184db537f9SJeremy L Thompson if (op->is_interface_setup) 9194db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 9204db537f9SJeremy L Thompson 9214db537f9SJeremy L Thompson CeedQFunction qf = op->qf; 9224db537f9SJeremy L Thompson if (op->is_composite) { 9234db537f9SJeremy L Thompson if (!op->num_suboperators) 9244db537f9SJeremy L Thompson // LCOV_EXCL_START 9254db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 9264db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9274db537f9SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 9284db537f9SJeremy L Thompson ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr); 9294db537f9SJeremy L Thompson } 9304db537f9SJeremy L Thompson } else { 9314db537f9SJeremy L Thompson if (op->num_fields == 0) 9324db537f9SJeremy L Thompson // LCOV_EXCL_START 9334db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 9344db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9354db537f9SJeremy L Thompson if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 9364db537f9SJeremy L Thompson // LCOV_EXCL_START 9374db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 9384db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9394db537f9SJeremy L Thompson if (!op->has_restriction) 9404db537f9SJeremy L Thompson // LCOV_EXCL_START 9414db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 9424db537f9SJeremy L Thompson "At least one restriction required"); 9434db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9444db537f9SJeremy L Thompson if (op->num_qpts == 0) 9454db537f9SJeremy L Thompson // LCOV_EXCL_START 9464db537f9SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 9474db537f9SJeremy L Thompson "At least one non-collocated basis is required " 9484db537f9SJeremy L Thompson "or the number of quadrature points must be set"); 9494db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9504db537f9SJeremy L Thompson } 9514db537f9SJeremy L Thompson 9524db537f9SJeremy L Thompson // Flag as immutable and ready 9534db537f9SJeremy L Thompson op->is_interface_setup = true; 9544db537f9SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 9554db537f9SJeremy L Thompson // LCOV_EXCL_START 9564db537f9SJeremy L Thompson op->qf->is_immutable = true; 9574db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9584db537f9SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 9594db537f9SJeremy L Thompson // LCOV_EXCL_START 9604db537f9SJeremy L Thompson op->dqf->is_immutable = true; 9614db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9624db537f9SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 9634db537f9SJeremy L Thompson // LCOV_EXCL_START 9644db537f9SJeremy L Thompson op->dqfT->is_immutable = true; 9654db537f9SJeremy L Thompson // LCOV_EXCL_STOP 9664db537f9SJeremy L Thompson return CEED_ERROR_SUCCESS; 9674db537f9SJeremy L Thompson } 9684db537f9SJeremy L Thompson 9694db537f9SJeremy L Thompson /** 970beecbf24SJeremy L Thompson @brief Set reuse of CeedQFunction data in CeedOperatorLinearAssemble* functions. 971beecbf24SJeremy L Thompson When `reuse_assembly_data = false` (default), the CeedQFunction associated 972beecbf24SJeremy L Thompson with this CeedOperator is re-assembled every time a `CeedOperatorLinearAssemble*` 973beecbf24SJeremy L Thompson function is called. 974beecbf24SJeremy L Thompson When `reuse_assembly_data = true`, the CeedQFunction associated with 975beecbf24SJeremy L Thompson this CeedOperator is reused between calls to 976beecbf24SJeremy L Thompson `CeedOperatorSetQFunctionAssemblyDataUpdated`. 9778b919e6bSJeremy L Thompson 978beecbf24SJeremy L Thompson @param[in] op CeedOperator 979beecbf24SJeremy L Thompson @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 9808b919e6bSJeremy L Thompson 9818b919e6bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9828b919e6bSJeremy L Thompson 9838b919e6bSJeremy L Thompson @ref Advanced 9848b919e6bSJeremy L Thompson **/ 985beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyReuse(CeedOperator op, 986beecbf24SJeremy L Thompson bool reuse_assembly_data) { 9878b919e6bSJeremy L Thompson int ierr; 9888b919e6bSJeremy L Thompson bool is_composite; 9898b919e6bSJeremy L Thompson 9908b919e6bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 9918b919e6bSJeremy L Thompson if (is_composite) { 9928b919e6bSJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 993beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyReuse(op->sub_operators[i], 994beecbf24SJeremy L Thompson reuse_assembly_data); CeedChk(ierr); 9958b919e6bSJeremy L Thompson } 9968b919e6bSJeremy L Thompson } else { 997beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetReuse(op->qf_assembled, reuse_assembly_data); 998beecbf24SJeremy L Thompson CeedChk(ierr); 999beecbf24SJeremy L Thompson } 1000beecbf24SJeremy L Thompson 1001beecbf24SJeremy L Thompson return CEED_ERROR_SUCCESS; 1002beecbf24SJeremy L Thompson } 1003beecbf24SJeremy L Thompson 1004beecbf24SJeremy L Thompson /** 1005beecbf24SJeremy L Thompson @brief Mark CeedQFunction data as updated and the CeedQFunction as requiring re-assembly. 1006beecbf24SJeremy L Thompson 1007beecbf24SJeremy L Thompson @param[in] op CeedOperator 1008beecbf24SJeremy L Thompson @param[in] reuse_assembly_data Boolean flag setting assembly data reuse 1009beecbf24SJeremy L Thompson 1010beecbf24SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1011beecbf24SJeremy L Thompson 1012beecbf24SJeremy L Thompson @ref Advanced 1013beecbf24SJeremy L Thompson **/ 1014beecbf24SJeremy L Thompson int CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(CeedOperator op, 1015beecbf24SJeremy L Thompson bool needs_data_update) { 1016beecbf24SJeremy L Thompson int ierr; 1017beecbf24SJeremy L Thompson bool is_composite; 1018beecbf24SJeremy L Thompson 1019beecbf24SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1020beecbf24SJeremy L Thompson if (is_composite) { 1021beecbf24SJeremy L Thompson for (CeedInt i = 0; i < op->num_suboperators; i++) { 1022beecbf24SJeremy L Thompson ierr = CeedOperatorSetQFunctionAssemblyDataUpdateNeeded(op->sub_operators[i], 1023beecbf24SJeremy L Thompson needs_data_update); CeedChk(ierr); 1024beecbf24SJeremy L Thompson } 1025beecbf24SJeremy L Thompson } else { 1026beecbf24SJeremy L Thompson ierr = CeedQFunctionAssemblyDataSetUpdateNeeded(op->qf_assembled, 1027beecbf24SJeremy L Thompson needs_data_update); 10288b919e6bSJeremy L Thompson CeedChk(ierr); 10298b919e6bSJeremy L Thompson } 10308b919e6bSJeremy L Thompson 10318b919e6bSJeremy L Thompson return CEED_ERROR_SUCCESS; 10328b919e6bSJeremy L Thompson } 10338b919e6bSJeremy L Thompson 10348b919e6bSJeremy L Thompson /** 1035cd4dfc48Sjeremylt @brief Set the number of quadrature points associated with a CeedOperator. 1036cd4dfc48Sjeremylt This should be used when creating a CeedOperator where every 1037cd4dfc48Sjeremylt field has a collocated basis. This function cannot be used for 1038cd4dfc48Sjeremylt composite CeedOperators. 1039cd4dfc48Sjeremylt 1040cd4dfc48Sjeremylt @param op CeedOperator 1041cd4dfc48Sjeremylt @param num_qpts Number of quadrature points to set 1042cd4dfc48Sjeremylt 1043cd4dfc48Sjeremylt @return An error code: 0 - success, otherwise - failure 1044cd4dfc48Sjeremylt 1045e9b533fbSJeremy L Thompson @ref Advanced 1046cd4dfc48Sjeremylt **/ 1047cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 1048f04ea552SJeremy L Thompson if (op->is_composite) 1049cd4dfc48Sjeremylt // LCOV_EXCL_START 1050cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1051cd4dfc48Sjeremylt "Not defined for composite operator"); 1052cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1053cd4dfc48Sjeremylt if (op->num_qpts) 1054cd4dfc48Sjeremylt // LCOV_EXCL_START 1055cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 1056cd4dfc48Sjeremylt "Number of quadrature points already defined"); 1057cd4dfc48Sjeremylt // LCOV_EXCL_STOP 1058f04ea552SJeremy L Thompson if (op->is_immutable) 1059f04ea552SJeremy L Thompson // LCOV_EXCL_START 1060f04ea552SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MAJOR, 1061f04ea552SJeremy L Thompson "Operator cannot be changed after set as immutable"); 1062f04ea552SJeremy L Thompson // LCOV_EXCL_STOP 1063cd4dfc48Sjeremylt 1064cd4dfc48Sjeremylt op->num_qpts = num_qpts; 1065cd4dfc48Sjeremylt return CEED_ERROR_SUCCESS; 1066cd4dfc48Sjeremylt } 1067cd4dfc48Sjeremylt 1068cd4dfc48Sjeremylt /** 10697a982d89SJeremy L. Thompson @brief View a CeedOperator 10707a982d89SJeremy L. Thompson 10717a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 10727a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 10737a982d89SJeremy L. Thompson 10747a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 10757a982d89SJeremy L. Thompson 10767a982d89SJeremy L. Thompson @ref User 10777a982d89SJeremy L. Thompson **/ 10787a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 10797a982d89SJeremy L. Thompson int ierr; 10807a982d89SJeremy L. Thompson 1081f04ea552SJeremy L Thompson if (op->is_composite) { 10827a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 10837a982d89SJeremy L. Thompson 1084d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 10857a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 1086d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 10877a982d89SJeremy L. Thompson CeedChk(ierr); 10887a982d89SJeremy L. Thompson } 10897a982d89SJeremy L. Thompson } else { 10907a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 10917a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 10927a982d89SJeremy L. Thompson } 1093e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 10947a982d89SJeremy L. Thompson } 10953bd813ffSjeremylt 10963bd813ffSjeremylt /** 1097b7c9bbdaSJeremy L Thompson @brief Get the Ceed associated with a CeedOperator 1098b7c9bbdaSJeremy L Thompson 1099b7c9bbdaSJeremy L Thompson @param op CeedOperator 1100b7c9bbdaSJeremy L Thompson @param[out] ceed Variable to store Ceed 1101b7c9bbdaSJeremy L Thompson 1102b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1103b7c9bbdaSJeremy L Thompson 1104b7c9bbdaSJeremy L Thompson @ref Advanced 1105b7c9bbdaSJeremy L Thompson **/ 1106b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1107b7c9bbdaSJeremy L Thompson *ceed = op->ceed; 1108b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1109b7c9bbdaSJeremy L Thompson } 1110b7c9bbdaSJeremy L Thompson 1111b7c9bbdaSJeremy L Thompson /** 1112b7c9bbdaSJeremy L Thompson @brief Get the number of elements associated with a CeedOperator 1113b7c9bbdaSJeremy L Thompson 1114b7c9bbdaSJeremy L Thompson @param op CeedOperator 1115b7c9bbdaSJeremy L Thompson @param[out] num_elem Variable to store number of elements 1116b7c9bbdaSJeremy L Thompson 1117b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1118b7c9bbdaSJeremy L Thompson 1119b7c9bbdaSJeremy L Thompson @ref Advanced 1120b7c9bbdaSJeremy L Thompson **/ 1121b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 1122b7c9bbdaSJeremy L Thompson if (op->is_composite) 1123b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1124b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1125b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1126b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1127b7c9bbdaSJeremy L Thompson 1128b7c9bbdaSJeremy L Thompson *num_elem = op->num_elem; 1129b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1130b7c9bbdaSJeremy L Thompson } 1131b7c9bbdaSJeremy L Thompson 1132b7c9bbdaSJeremy L Thompson /** 1133b7c9bbdaSJeremy L Thompson @brief Get the number of quadrature points associated with a CeedOperator 1134b7c9bbdaSJeremy L Thompson 1135b7c9bbdaSJeremy L Thompson @param op CeedOperator 1136b7c9bbdaSJeremy L Thompson @param[out] num_qpts Variable to store vector number of quadrature points 1137b7c9bbdaSJeremy L Thompson 1138b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1139b7c9bbdaSJeremy L Thompson 1140b7c9bbdaSJeremy L Thompson @ref Advanced 1141b7c9bbdaSJeremy L Thompson **/ 1142b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 1143b7c9bbdaSJeremy L Thompson if (op->is_composite) 1144b7c9bbdaSJeremy L Thompson // LCOV_EXCL_START 1145b7c9bbdaSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 1146b7c9bbdaSJeremy L Thompson "Not defined for composite operator"); 1147b7c9bbdaSJeremy L Thompson // LCOV_EXCL_STOP 1148b7c9bbdaSJeremy L Thompson 1149b7c9bbdaSJeremy L Thompson *num_qpts = op->num_qpts; 1150b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1151b7c9bbdaSJeremy L Thompson } 1152b7c9bbdaSJeremy L Thompson 1153b7c9bbdaSJeremy L Thompson /** 11543668ca4bSJeremy L Thompson @brief Get label for a registered QFunctionContext field, or `NULL` if no 11553668ca4bSJeremy L Thompson field has been registered with this `field_name`. 11563668ca4bSJeremy L Thompson 11573668ca4bSJeremy L Thompson @param[in] op CeedOperator 11583668ca4bSJeremy L Thompson @param[in] field_name Name of field to retrieve label 11593668ca4bSJeremy L Thompson @param[out] field_label Variable to field label 11603668ca4bSJeremy L Thompson 11613668ca4bSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11623668ca4bSJeremy L Thompson 11633668ca4bSJeremy L Thompson @ref User 11643668ca4bSJeremy L Thompson **/ 11653668ca4bSJeremy L Thompson int CeedOperatorContextGetFieldLabel(CeedOperator op, 11663668ca4bSJeremy L Thompson const char *field_name, 11673668ca4bSJeremy L Thompson CeedContextFieldLabel *field_label) { 11683668ca4bSJeremy L Thompson int ierr; 11693668ca4bSJeremy L Thompson 11703668ca4bSJeremy L Thompson bool is_composite; 11713668ca4bSJeremy L Thompson ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 11723668ca4bSJeremy L Thompson if (is_composite) { 11733668ca4bSJeremy L Thompson // Check if composite label already created 11743668ca4bSJeremy L Thompson for (CeedInt i=0; i<op->num_context_labels; i++) { 11753668ca4bSJeremy L Thompson if (!strcmp(op->context_labels[i]->name, field_name)) { 11763668ca4bSJeremy L Thompson *field_label = op->context_labels[i]; 11773668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 11783668ca4bSJeremy L Thompson } 11793668ca4bSJeremy L Thompson } 11803668ca4bSJeremy L Thompson 11813668ca4bSJeremy L Thompson // Create composite label if needed 11823668ca4bSJeremy L Thompson CeedInt num_sub; 11833668ca4bSJeremy L Thompson CeedOperator *sub_operators; 11843668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label; 11853668ca4bSJeremy L Thompson 11863668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &new_field_label); CeedChk(ierr); 11873668ca4bSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChk(ierr); 11883668ca4bSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 11893668ca4bSJeremy L Thompson ierr = CeedCalloc(num_sub, &new_field_label->sub_labels); CeedChk(ierr); 11903668ca4bSJeremy L Thompson new_field_label->num_sub_labels = num_sub; 11913668ca4bSJeremy L Thompson 11923668ca4bSJeremy L Thompson bool label_found = false; 11933668ca4bSJeremy L Thompson for (CeedInt i=0; i<num_sub; i++) { 11943668ca4bSJeremy L Thompson if (sub_operators[i]->qf->ctx) { 11953668ca4bSJeremy L Thompson CeedContextFieldLabel new_field_label_i; 11963668ca4bSJeremy L Thompson ierr = CeedQFunctionContextGetFieldLabel(sub_operators[i]->qf->ctx, field_name, 11973668ca4bSJeremy L Thompson &new_field_label_i); CeedChk(ierr); 11983668ca4bSJeremy L Thompson if (new_field_label_i) { 11993668ca4bSJeremy L Thompson label_found = true; 12003668ca4bSJeremy L Thompson new_field_label->sub_labels[i] = new_field_label_i; 12013668ca4bSJeremy L Thompson new_field_label->name = new_field_label_i->name; 12023668ca4bSJeremy L Thompson new_field_label->description = new_field_label_i->description; 12037bfe0f0eSJeremy L Thompson if (new_field_label->type && 12047bfe0f0eSJeremy L Thompson new_field_label->type != new_field_label_i->type) { 12057bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 12067bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 12077bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 12087bfe0f0eSJeremy L Thompson "Incompatible field types on sub-operator contexts. " 12097bfe0f0eSJeremy L Thompson "%s != %s", 12107bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label->type], 12117bfe0f0eSJeremy L Thompson CeedContextFieldTypes[new_field_label_i->type]); 12127bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 12137bfe0f0eSJeremy L Thompson } else { 12147bfe0f0eSJeremy L Thompson new_field_label->type = new_field_label_i->type; 12157bfe0f0eSJeremy L Thompson } 12167bfe0f0eSJeremy L Thompson if (new_field_label->num_values != 0 && 12177bfe0f0eSJeremy L Thompson new_field_label->num_values != new_field_label_i->num_values) { 12187bfe0f0eSJeremy L Thompson // LCOV_EXCL_START 12197bfe0f0eSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 12207bfe0f0eSJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 12217bfe0f0eSJeremy L Thompson "Incompatible field number of values on sub-operator" 12227bfe0f0eSJeremy L Thompson " contexts. %ld != %ld", 12237bfe0f0eSJeremy L Thompson new_field_label->num_values, new_field_label_i->num_values); 12247bfe0f0eSJeremy L Thompson // LCOV_EXCL_STOP 12257bfe0f0eSJeremy L Thompson } else { 12267bfe0f0eSJeremy L Thompson new_field_label->num_values = new_field_label_i->num_values; 12277bfe0f0eSJeremy L Thompson } 12283668ca4bSJeremy L Thompson } 12293668ca4bSJeremy L Thompson } 12303668ca4bSJeremy L Thompson } 12313668ca4bSJeremy L Thompson if (!label_found) { 12323668ca4bSJeremy L Thompson // LCOV_EXCL_START 1233a48e5f43SJeremy L Thompson ierr = CeedFree(&new_field_label->sub_labels); CeedChk(ierr); 12343668ca4bSJeremy L Thompson ierr = CeedFree(&new_field_label); CeedChk(ierr); 12353668ca4bSJeremy L Thompson *field_label = NULL; 12363668ca4bSJeremy L Thompson // LCOV_EXCL_STOP 12373668ca4bSJeremy L Thompson } else { 12383668ca4bSJeremy L Thompson // Move new composite label to operator 12393668ca4bSJeremy L Thompson if (op->num_context_labels == 0) { 12403668ca4bSJeremy L Thompson ierr = CeedCalloc(1, &op->context_labels); CeedChk(ierr); 12413668ca4bSJeremy L Thompson op->max_context_labels = 1; 12423668ca4bSJeremy L Thompson } else if (op->num_context_labels == op->max_context_labels) { 12433668ca4bSJeremy L Thompson ierr = CeedRealloc(2*op->num_context_labels, &op->context_labels); 12443668ca4bSJeremy L Thompson CeedChk(ierr); 12453668ca4bSJeremy L Thompson op->max_context_labels *= 2; 12463668ca4bSJeremy L Thompson } 12473668ca4bSJeremy L Thompson op->context_labels[op->num_context_labels] = new_field_label; 12483668ca4bSJeremy L Thompson *field_label = new_field_label; 12493668ca4bSJeremy L Thompson op->num_context_labels++; 12503668ca4bSJeremy L Thompson } 12513668ca4bSJeremy L Thompson 12523668ca4bSJeremy L Thompson return CEED_ERROR_SUCCESS; 12533668ca4bSJeremy L Thompson } else { 12543668ca4bSJeremy L Thompson return CeedQFunctionContextGetFieldLabel(op->qf->ctx, field_name, field_label); 12553668ca4bSJeremy L Thompson } 12563668ca4bSJeremy L Thompson } 12573668ca4bSJeremy L Thompson 12583668ca4bSJeremy L Thompson /** 1259d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding a double precision value. 1260d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1261d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1262d8dd9a91SJeremy L Thompson 1263d8dd9a91SJeremy L Thompson @param op CeedOperator 12643668ca4bSJeremy L Thompson @param field_label Label of field to register 12657bfe0f0eSJeremy L Thompson @param values Values to set 1266d8dd9a91SJeremy L Thompson 1267d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1268d8dd9a91SJeremy L Thompson 1269d8dd9a91SJeremy L Thompson @ref User 1270d8dd9a91SJeremy L Thompson **/ 12713668ca4bSJeremy L Thompson int CeedOperatorContextSetDouble(CeedOperator op, 12723668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 12737bfe0f0eSJeremy L Thompson double *values) { 12743668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_DOUBLE, 12757bfe0f0eSJeremy L Thompson values); 1276d8dd9a91SJeremy L Thompson } 1277d8dd9a91SJeremy L Thompson 1278d8dd9a91SJeremy L Thompson /** 1279d8dd9a91SJeremy L Thompson @brief Set QFunctionContext field holding an int32 value. 1280d8dd9a91SJeremy L Thompson For composite operators, the value is set in all 1281d8dd9a91SJeremy L Thompson sub-operator QFunctionContexts that have a matching `field_name`. 1282d8dd9a91SJeremy L Thompson 1283d8dd9a91SJeremy L Thompson @param op CeedOperator 12843668ca4bSJeremy L Thompson @param field_label Label of field to set 12857bfe0f0eSJeremy L Thompson @param values Values to set 1286d8dd9a91SJeremy L Thompson 1287d8dd9a91SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1288d8dd9a91SJeremy L Thompson 1289d8dd9a91SJeremy L Thompson @ref User 1290d8dd9a91SJeremy L Thompson **/ 12913668ca4bSJeremy L Thompson int CeedOperatorContextSetInt32(CeedOperator op, 12923668ca4bSJeremy L Thompson CeedContextFieldLabel field_label, 12937bfe0f0eSJeremy L Thompson int *values) { 12943668ca4bSJeremy L Thompson return CeedOperatorContextSetGeneric(op, field_label, CEED_CONTEXT_FIELD_INT32, 12957bfe0f0eSJeremy L Thompson values); 1296d8dd9a91SJeremy L Thompson } 1297d8dd9a91SJeremy L Thompson 1298d8dd9a91SJeremy L Thompson /** 12993bd813ffSjeremylt @brief Apply CeedOperator to a vector 1300d7b241e6Sjeremylt 1301d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 1302d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 1303d7b241e6Sjeremylt CeedOperatorSetField(). 1304d7b241e6Sjeremylt 1305f04ea552SJeremy L Thompson Note: Calling this function asserts that setup is complete 1306f04ea552SJeremy L Thompson and sets the CeedOperator as immutable. 1307f04ea552SJeremy L Thompson 1308d7b241e6Sjeremylt @param op CeedOperator to apply 13094cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 131034138859Sjeremylt there are no active inputs 1311b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 13124cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 131334138859Sjeremylt active outputs 1314d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 13154cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1316b11c1e72Sjeremylt 1317b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1318dfdf5a53Sjeremylt 13197a982d89SJeremy L. Thompson @ref User 1320b11c1e72Sjeremylt **/ 1321692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1322692c2638Sjeremylt CeedRequest *request) { 1323d7b241e6Sjeremylt int ierr; 1324e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1325d7b241e6Sjeremylt 1326d1d35e2fSjeremylt if (op->num_elem) { 1327250756a7Sjeremylt // Standard Operator 1328cae8b89aSjeremylt if (op->Apply) { 1329250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1330cae8b89aSjeremylt } else { 1331cae8b89aSjeremylt // Zero all output vectors 1332250756a7Sjeremylt CeedQFunction qf = op->qf; 1333d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 1334d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 1335cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 1336cae8b89aSjeremylt vec = out; 1337cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 1338cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1339cae8b89aSjeremylt } 1340cae8b89aSjeremylt } 1341250756a7Sjeremylt // Apply 1342250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1343250756a7Sjeremylt } 1344f04ea552SJeremy L Thompson } else if (op->is_composite) { 1345250756a7Sjeremylt // Composite Operator 1346250756a7Sjeremylt if (op->ApplyComposite) { 1347250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1348250756a7Sjeremylt } else { 1349d1d35e2fSjeremylt CeedInt num_suboperators; 1350d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1351d1d35e2fSjeremylt CeedOperator *sub_operators; 1352d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1353250756a7Sjeremylt 1354250756a7Sjeremylt // Zero all output vectors 1355250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 1356cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1357cae8b89aSjeremylt } 1358d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1359d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 1360d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 1361250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1362250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1363250756a7Sjeremylt } 1364250756a7Sjeremylt } 1365250756a7Sjeremylt } 1366250756a7Sjeremylt // Apply 1367d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 1368d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 1369cae8b89aSjeremylt CeedChk(ierr); 1370cae8b89aSjeremylt } 1371cae8b89aSjeremylt } 1372250756a7Sjeremylt } 1373e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1374cae8b89aSjeremylt } 1375cae8b89aSjeremylt 1376cae8b89aSjeremylt /** 1377cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 1378cae8b89aSjeremylt 1379cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 1380cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 1381cae8b89aSjeremylt CeedOperatorSetField(). 1382cae8b89aSjeremylt 1383cae8b89aSjeremylt @param op CeedOperator to apply 1384cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 1385cae8b89aSjeremylt active inputs 1386cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 1387cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 1388cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 13894cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1390cae8b89aSjeremylt 1391cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 1392cae8b89aSjeremylt 13937a982d89SJeremy L. Thompson @ref User 1394cae8b89aSjeremylt **/ 1395cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1396cae8b89aSjeremylt CeedRequest *request) { 1397cae8b89aSjeremylt int ierr; 1398e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1399cae8b89aSjeremylt 1400d1d35e2fSjeremylt if (op->num_elem) { 1401250756a7Sjeremylt // Standard Operator 1402250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1403f04ea552SJeremy L Thompson } else if (op->is_composite) { 1404250756a7Sjeremylt // Composite Operator 1405250756a7Sjeremylt if (op->ApplyAddComposite) { 1406250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1407cae8b89aSjeremylt } else { 1408d1d35e2fSjeremylt CeedInt num_suboperators; 1409d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1410d1d35e2fSjeremylt CeedOperator *sub_operators; 1411d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1412250756a7Sjeremylt 1413d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 1414d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 1415cae8b89aSjeremylt CeedChk(ierr); 14161d7d2407SJeremy L Thompson } 1417250756a7Sjeremylt } 1418250756a7Sjeremylt } 1419e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1420d7b241e6Sjeremylt } 1421d7b241e6Sjeremylt 1422d7b241e6Sjeremylt /** 1423b11c1e72Sjeremylt @brief Destroy a CeedOperator 1424d7b241e6Sjeremylt 1425d7b241e6Sjeremylt @param op CeedOperator to destroy 1426b11c1e72Sjeremylt 1427b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1428dfdf5a53Sjeremylt 14297a982d89SJeremy L. Thompson @ref User 1430b11c1e72Sjeremylt **/ 1431d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1432d7b241e6Sjeremylt int ierr; 1433d7b241e6Sjeremylt 1434d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 1435d7b241e6Sjeremylt if ((*op)->Destroy) { 1436d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1437d7b241e6Sjeremylt } 1438fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1439fe2413ffSjeremylt // Free fields 14403668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1441d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 1442d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 1443d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 144471352a93Sjeremylt CeedChk(ierr); 144515910d16Sjeremylt } 1446d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1447d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 144871352a93Sjeremylt } 1449d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 1450d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 1451d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 145271352a93Sjeremylt } 1453d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 1454d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 1455fe2413ffSjeremylt } 14563668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_fields; i++) 1457d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 1458d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 145971352a93Sjeremylt CeedChk(ierr); 1460d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 1461d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 146271352a93Sjeremylt } 1463d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 1464d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 1465d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 146671352a93Sjeremylt } 1467d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 1468d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 1469fe2413ffSjeremylt } 1470d1d35e2fSjeremylt // Destroy sub_operators 14713668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_suboperators; i++) 1472d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 1473d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 147452d6035fSJeremy L Thompson } 1475d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1476d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1477d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 14783668ca4bSJeremy L Thompson // Destroy any composite labels 14793668ca4bSJeremy L Thompson for (CeedInt i=0; i<(*op)->num_context_labels; i++) { 14803668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]->sub_labels); CeedChk(ierr); 14813668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels[i]); CeedChk(ierr); 14823668ca4bSJeremy L Thompson } 14833668ca4bSJeremy L Thompson ierr = CeedFree(&(*op)->context_labels); CeedChk(ierr); 1484fe2413ffSjeremylt 14855107b09fSJeremy L Thompson // Destroy fallback 1486d1d35e2fSjeremylt if ((*op)->op_fallback) { 1487d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 1488d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 1489d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 1490d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 14915107b09fSJeremy L Thompson } 14925107b09fSJeremy L Thompson 149370a7ffb3SJeremy L Thompson // Destroy QF assembly cache 1494480fae85SJeremy L Thompson ierr = CeedQFunctionAssemblyDataDestroy(&(*op)->qf_assembled); CeedChk(ierr); 149570a7ffb3SJeremy L Thompson 1496d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 1497d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 1498d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 1499d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1500e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1501d7b241e6Sjeremylt } 1502d7b241e6Sjeremylt 1503d7b241e6Sjeremylt /// @} 1504