1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 17ec3da8bcSJed Brown #include <ceed/ceed.h> 18ec3da8bcSJed Brown #include <ceed/backend.h> 193d576824SJeremy L Thompson #include <ceed-impl.h> 203bd813ffSjeremylt #include <math.h> 213d576824SJeremy L Thompson #include <stdbool.h> 223d576824SJeremy L Thompson #include <stdio.h> 233d576824SJeremy L Thompson #include <string.h> 24d7b241e6Sjeremylt 25dfdf5a53Sjeremylt /// @file 267a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 277a982d89SJeremy L. Thompson 287a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 297a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 307a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 317a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 327a982d89SJeremy L. Thompson /// @{ 337a982d89SJeremy L. Thompson 347a982d89SJeremy L. Thompson /** 357a982d89SJeremy L. Thompson @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced 367a982d89SJeremy L. Thompson CeedOperator functionality 377a982d89SJeremy L. Thompson 387a982d89SJeremy L. Thompson @param op CeedOperator to create fallback for 397a982d89SJeremy L. Thompson 407a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 417a982d89SJeremy L. Thompson 427a982d89SJeremy L. Thompson @ref Developer 437a982d89SJeremy L. Thompson **/ 447a982d89SJeremy L. Thompson int CeedOperatorCreateFallback(CeedOperator op) { 457a982d89SJeremy L. Thompson int ierr; 467a982d89SJeremy L. Thompson 477a982d89SJeremy L. Thompson // Fallback Ceed 48*d1d35e2fSjeremylt const char *resource, *fallback_resource; 497a982d89SJeremy L. Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 50*d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 517a982d89SJeremy L. Thompson CeedChk(ierr); 52*d1d35e2fSjeremylt if (!strcmp(resource, fallback_resource)) 537a982d89SJeremy L. Thompson // LCOV_EXCL_START 54e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 55e15f9bd0SJeremy L Thompson "Backend %s cannot create an operator" 56*d1d35e2fSjeremylt "fallback to resource %s", resource, fallback_resource); 577a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 587a982d89SJeremy L. Thompson 597a982d89SJeremy L. Thompson // Fallback Ceed 60*d1d35e2fSjeremylt Ceed ceed_ref; 61*d1d35e2fSjeremylt if (!op->ceed->op_fallback_ceed) { 62*d1d35e2fSjeremylt ierr = CeedInit(fallback_resource, &ceed_ref); CeedChk(ierr); 63*d1d35e2fSjeremylt ceed_ref->op_fallback_parent = op->ceed; 64*d1d35e2fSjeremylt ceed_ref->Error = op->ceed->Error; 65*d1d35e2fSjeremylt op->ceed->op_fallback_ceed = ceed_ref; 667a982d89SJeremy L. Thompson } 67*d1d35e2fSjeremylt ceed_ref = op->ceed->op_fallback_ceed; 687a982d89SJeremy L. Thompson 697a982d89SJeremy L. Thompson // Clone Op 70*d1d35e2fSjeremylt CeedOperator op_ref; 71*d1d35e2fSjeremylt ierr = CeedCalloc(1, &op_ref); CeedChk(ierr); 72*d1d35e2fSjeremylt memcpy(op_ref, op, sizeof(*op_ref)); 73*d1d35e2fSjeremylt op_ref->data = NULL; 74*d1d35e2fSjeremylt op_ref->interface_setup = false; 75*d1d35e2fSjeremylt op_ref->backend_setup = false; 76*d1d35e2fSjeremylt op_ref->ceed = ceed_ref; 77*d1d35e2fSjeremylt ierr = ceed_ref->OperatorCreate(op_ref); CeedChk(ierr); 78*d1d35e2fSjeremylt op->op_fallback = op_ref; 797a982d89SJeremy L. Thompson 807a982d89SJeremy L. Thompson // Clone QF 81*d1d35e2fSjeremylt CeedQFunction qf_ref; 82*d1d35e2fSjeremylt ierr = CeedCalloc(1, &qf_ref); CeedChk(ierr); 83*d1d35e2fSjeremylt memcpy(qf_ref, (op->qf), sizeof(*qf_ref)); 84*d1d35e2fSjeremylt qf_ref->data = NULL; 85*d1d35e2fSjeremylt qf_ref->ceed = ceed_ref; 86*d1d35e2fSjeremylt ierr = ceed_ref->QFunctionCreate(qf_ref); CeedChk(ierr); 87*d1d35e2fSjeremylt op_ref->qf = qf_ref; 88*d1d35e2fSjeremylt op->qf_fallback = qf_ref; 89e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 90e15f9bd0SJeremy L Thompson } 917a982d89SJeremy L. Thompson 92e15f9bd0SJeremy L Thompson /** 93e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 94e15f9bd0SJeremy L Thompson 95e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 96*d1d35e2fSjeremylt @param[in] qf_field QFunction Field matching Operator Field 97e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 98e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 99e15f9bd0SJeremy L Thompson 100e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 101e15f9bd0SJeremy L Thompson 102e15f9bd0SJeremy L Thompson @ref Developer 103e15f9bd0SJeremy L Thompson **/ 104*d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, 105e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 106e15f9bd0SJeremy L Thompson int ierr; 107*d1d35e2fSjeremylt CeedEvalMode eval_mode = qf_field->eval_mode; 108*d1d35e2fSjeremylt CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size; 109e15f9bd0SJeremy L Thompson // Restriction 110e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 111*d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { 112e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 113e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 114e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE should be used " 115e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 116e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 117e15f9bd0SJeremy L Thompson } 118*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp); 119e1e9e29dSJed Brown } 120*d1d35e2fSjeremylt if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) { 121e1e9e29dSJed Brown // LCOV_EXCL_START 122e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 123e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 124e1e9e29dSJed Brown "must be used together."); 125e1e9e29dSJed Brown // LCOV_EXCL_STOP 126e1e9e29dSJed Brown } 127e15f9bd0SJeremy L Thompson // Basis 128e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 129*d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) 130e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 131*d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 132*d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 133*d1d35e2fSjeremylt qf_field->field_name); 134e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 135*d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 136*d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 137e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 138e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 139*d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 140*d1d35e2fSjeremylt "has %d components, but Basis has %d components", 141*d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 142*d1d35e2fSjeremylt restr_num_comp, 143*d1d35e2fSjeremylt num_comp); 144e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 145e15f9bd0SJeremy L Thompson } 146e15f9bd0SJeremy L Thompson } 147e15f9bd0SJeremy L Thompson // Field size 148*d1d35e2fSjeremylt switch(eval_mode) { 149e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 150*d1d35e2fSjeremylt if (size != restr_num_comp) 151e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 152e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 153e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 154*d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 155*d1d35e2fSjeremylt restr_num_comp); 156e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 157e15f9bd0SJeremy L Thompson break; 158e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 159*d1d35e2fSjeremylt if (size != num_comp) 160e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 161e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 162e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 163*d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 164*d1d35e2fSjeremylt num_comp); 165e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 166e15f9bd0SJeremy L Thompson break; 167e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 168*d1d35e2fSjeremylt if (size != num_comp * dim) 169e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 170e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 171*d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 172*d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 173*d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 174*d1d35e2fSjeremylt num_comp); 175e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 176e15f9bd0SJeremy L Thompson break; 177e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 178*d1d35e2fSjeremylt // No additional checks required 179e15f9bd0SJeremy L Thompson break; 180e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 181e15f9bd0SJeremy L Thompson // Not implemented 182e15f9bd0SJeremy L Thompson break; 183e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 184e15f9bd0SJeremy L Thompson // Not implemented 185e15f9bd0SJeremy L Thompson break; 186e15f9bd0SJeremy L Thompson } 187e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1887a982d89SJeremy L. Thompson } 1897a982d89SJeremy L. Thompson 1907a982d89SJeremy L. Thompson /** 1917a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 1927a982d89SJeremy L. Thompson 1937a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 1947a982d89SJeremy L. Thompson 1957a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1967a982d89SJeremy L. Thompson 1977a982d89SJeremy L. Thompson @ref Developer 1987a982d89SJeremy L. Thompson **/ 199e2f04181SAndrew T. Barker static int CeedOperatorCheckReady(CeedOperator op) { 200e2f04181SAndrew T. Barker int ierr; 201e2f04181SAndrew T. Barker Ceed ceed; 202e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 203e2f04181SAndrew T. Barker 204*d1d35e2fSjeremylt if (op->interface_setup) 205e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2067a982d89SJeremy L. Thompson 207e15f9bd0SJeremy L Thompson CeedQFunction qf = op->qf; 2087a982d89SJeremy L. Thompson if (op->composite) { 209*d1d35e2fSjeremylt if (!op->num_suboperators) 2107a982d89SJeremy L. Thompson // LCOV_EXCL_START 211*d1d35e2fSjeremylt return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 2127a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2137a982d89SJeremy L. Thompson } else { 214*d1d35e2fSjeremylt if (op->num_fields == 0) 2157a982d89SJeremy L. Thompson // LCOV_EXCL_START 216e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 2177a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 218*d1d35e2fSjeremylt if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 2197a982d89SJeremy L. Thompson // LCOV_EXCL_START 220e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 2217a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 222*d1d35e2fSjeremylt if (!op->has_restriction) 2237a982d89SJeremy L. Thompson // LCOV_EXCL_START 224e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 225e15f9bd0SJeremy L Thompson "At least one restriction required"); 2267a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 227*d1d35e2fSjeremylt if (op->num_qpts == 0) 2287a982d89SJeremy L. Thompson // LCOV_EXCL_START 229e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 230e15f9bd0SJeremy L Thompson "At least one non-collocated basis required"); 2317a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2327a982d89SJeremy L. Thompson } 2337a982d89SJeremy L. Thompson 234e15f9bd0SJeremy L Thompson // Flag as immutable and ready 235*d1d35e2fSjeremylt op->interface_setup = true; 236e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 237e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 238*d1d35e2fSjeremylt op->qf->operators_set++; 239e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 240e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 241e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 242*d1d35e2fSjeremylt op->dqf->operators_set++; 243e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 244e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 245e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 246*d1d35e2fSjeremylt op->dqfT->operators_set++; 247e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 248e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2497a982d89SJeremy L. Thompson } 2507a982d89SJeremy L. Thompson 2517a982d89SJeremy L. Thompson /** 2527a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2537a982d89SJeremy L. Thompson 2547a982d89SJeremy L. Thompson @param[in] field Operator field to view 255*d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 256*d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 2574c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 258*d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 2597a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2607a982d89SJeremy L. Thompson 2617a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2627a982d89SJeremy L. Thompson 2637a982d89SJeremy L. Thompson @ref Utility 2647a982d89SJeremy L. Thompson **/ 2657a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 266*d1d35e2fSjeremylt CeedQFunctionField qf_field, 267*d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 2687a982d89SJeremy L. Thompson FILE *stream) { 2697a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 270*d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 2717a982d89SJeremy L. Thompson 2727a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2737a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 274*d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 2757a982d89SJeremy L. Thompson 2767a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2777a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2787a982d89SJeremy L. Thompson 2797a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2807a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2817a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2827a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 283e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2847a982d89SJeremy L. Thompson } 2857a982d89SJeremy L. Thompson 2867a982d89SJeremy L. Thompson /** 2877a982d89SJeremy L. Thompson @brief View a single CeedOperator 2887a982d89SJeremy L. Thompson 2897a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2907a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2917a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2927a982d89SJeremy L. Thompson 2937a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2947a982d89SJeremy L. Thompson 2957a982d89SJeremy L. Thompson @ref Utility 2967a982d89SJeremy L. Thompson **/ 2977a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 2987a982d89SJeremy L. Thompson int ierr; 2997a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 3007a982d89SJeremy L. Thompson 3017a982d89SJeremy L. Thompson CeedInt totalfields; 3027a982d89SJeremy L. Thompson ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 3037a982d89SJeremy L. Thompson 3047a982d89SJeremy L. Thompson fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 3057a982d89SJeremy L. Thompson 306*d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 307*d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 308*d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 309*d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 3107a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 3117a982d89SJeremy L. Thompson } 3127a982d89SJeremy L. Thompson 313*d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 314*d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 315*d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 316*d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 3177a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 3187a982d89SJeremy L. Thompson } 319e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3207a982d89SJeremy L. Thompson } 3217a982d89SJeremy L. Thompson 322d99fa3c5SJeremy L Thompson /** 323e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 324e2f04181SAndrew T. Barker 325e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 326*d1d35e2fSjeremylt @param[out] active_rstr ElemRestriction for active input vector 327e2f04181SAndrew T. Barker 328e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 329e2f04181SAndrew T. Barker 330e2f04181SAndrew T. Barker @ref Utility 331e2f04181SAndrew T. Barker **/ 332e2f04181SAndrew T. Barker static int CeedOperatorGetActiveElemRestriction(CeedOperator op, 333*d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 334*d1d35e2fSjeremylt *active_rstr = NULL; 335*d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 336*d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 337*d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 338e2f04181SAndrew T. Barker break; 339e2f04181SAndrew T. Barker } 340e2f04181SAndrew T. Barker 341*d1d35e2fSjeremylt if (!*active_rstr) { 342e2f04181SAndrew T. Barker // LCOV_EXCL_START 343e2f04181SAndrew T. Barker int ierr; 344e2f04181SAndrew T. Barker Ceed ceed; 345e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 346e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 347e2f04181SAndrew T. Barker "No active ElemRestriction found!"); 348e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 349e2f04181SAndrew T. Barker } 350e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 351e2f04181SAndrew T. Barker } 352e2f04181SAndrew T. Barker 353e2f04181SAndrew T. Barker /** 354d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 355d99fa3c5SJeremy L Thompson 356d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 357*d1d35e2fSjeremylt @param[out] active_basis Basis for active input vector 358d99fa3c5SJeremy L Thompson 359d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 360d99fa3c5SJeremy L Thompson 361d99fa3c5SJeremy L Thompson @ ref Developer 362d99fa3c5SJeremy L Thompson **/ 363d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 364*d1d35e2fSjeremylt CeedBasis *active_basis) { 365*d1d35e2fSjeremylt *active_basis = NULL; 366*d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 367*d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 368*d1d35e2fSjeremylt *active_basis = op->input_fields[i]->basis; 369d99fa3c5SJeremy L Thompson break; 370d99fa3c5SJeremy L Thompson } 371d99fa3c5SJeremy L Thompson 372*d1d35e2fSjeremylt if (!*active_basis) { 373d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 374d99fa3c5SJeremy L Thompson int ierr; 375d99fa3c5SJeremy L Thompson Ceed ceed; 376d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 377e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 378d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 379d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 380d99fa3c5SJeremy L Thompson } 381e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 382d99fa3c5SJeremy L Thompson } 383d99fa3c5SJeremy L Thompson 384d99fa3c5SJeremy L Thompson /** 385d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 386d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 387d99fa3c5SJeremy L Thompson 388*d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 389*d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 390*d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 391*d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 392*d1d35e2fSjeremylt @param[in] basis_c_to_f Basis for coarse to fine interpolation 393*d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 394*d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 395*d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 396d99fa3c5SJeremy L Thompson 397d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 398d99fa3c5SJeremy L Thompson 399d99fa3c5SJeremy L Thompson @ref Developer 400d99fa3c5SJeremy L Thompson **/ 401*d1d35e2fSjeremylt static int CeedOperatorMultigridLevel_Core(CeedOperator op_fine, 402*d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 403*d1d35e2fSjeremylt CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, 404*d1d35e2fSjeremylt CeedOperator *op_restrict) { 405d99fa3c5SJeremy L Thompson int ierr; 406d99fa3c5SJeremy L Thompson Ceed ceed; 407*d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 408d99fa3c5SJeremy L Thompson 409d99fa3c5SJeremy L Thompson // Check for composite operator 410*d1d35e2fSjeremylt bool is_composite; 411*d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op_fine, &is_composite); CeedChk(ierr); 412*d1d35e2fSjeremylt if (is_composite) 413d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 414e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 415d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 416d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 417d99fa3c5SJeremy L Thompson 418d99fa3c5SJeremy L Thompson // Coarse Grid 419*d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, op_fine->qf, op_fine->dqf, op_fine->dqfT, 420*d1d35e2fSjeremylt op_coarse); CeedChk(ierr); 421*d1d35e2fSjeremylt CeedElemRestriction rstr_fine = NULL; 422d99fa3c5SJeremy L Thompson // -- Clone input fields 423*d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_input_fields; i++) { 424*d1d35e2fSjeremylt if (op_fine->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 425*d1d35e2fSjeremylt rstr_fine = op_fine->input_fields[i]->elem_restr; 426*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 427*d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 428d99fa3c5SJeremy L Thompson CeedChk(ierr); 429d99fa3c5SJeremy L Thompson } else { 430*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 431*d1d35e2fSjeremylt op_fine->input_fields[i]->elem_restr, 432*d1d35e2fSjeremylt op_fine->input_fields[i]->basis, 433*d1d35e2fSjeremylt op_fine->input_fields[i]->vec); CeedChk(ierr); 434d99fa3c5SJeremy L Thompson } 435d99fa3c5SJeremy L Thompson } 436d99fa3c5SJeremy L Thompson // -- Clone output fields 437*d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_output_fields; i++) { 438*d1d35e2fSjeremylt if (op_fine->output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 439*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 440*d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 441d99fa3c5SJeremy L Thompson CeedChk(ierr); 442d99fa3c5SJeremy L Thompson } else { 443*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 444*d1d35e2fSjeremylt op_fine->output_fields[i]->elem_restr, 445*d1d35e2fSjeremylt op_fine->output_fields[i]->basis, 446*d1d35e2fSjeremylt op_fine->output_fields[i]->vec); CeedChk(ierr); 447d99fa3c5SJeremy L Thompson } 448d99fa3c5SJeremy L Thompson } 449d99fa3c5SJeremy L Thompson 450d99fa3c5SJeremy L Thompson // Multiplicity vector 451*d1d35e2fSjeremylt CeedVector mult_vec, mult_e_vec; 452*d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(rstr_fine, &mult_vec, &mult_e_vec); 453d99fa3c5SJeremy L Thompson CeedChk(ierr); 454*d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_e_vec, 0.0); CeedChk(ierr); 455*d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_NOTRANSPOSE, p_mult_fine, 456*d1d35e2fSjeremylt mult_e_vec, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 457*d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_vec, 0.0); CeedChk(ierr); 458*d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_TRANSPOSE, mult_e_vec, mult_vec, 459d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 460*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_e_vec); CeedChk(ierr); 461*d1d35e2fSjeremylt ierr = CeedVectorReciprocal(mult_vec); CeedChk(ierr); 462d99fa3c5SJeremy L Thompson 463d99fa3c5SJeremy L Thompson // Restriction 464*d1d35e2fSjeremylt CeedInt num_comp; 465*d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_coarse, &num_comp); CeedChk(ierr); 466*d1d35e2fSjeremylt CeedQFunction qf_restrict; 467*d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_restrict); 468d99fa3c5SJeremy L Thompson CeedChk(ierr); 469*d1d35e2fSjeremylt CeedInt *num_comp_r_data; 470*d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_r_data); CeedChk(ierr); 471*d1d35e2fSjeremylt num_comp_r_data[0] = num_comp; 472*d1d35e2fSjeremylt CeedQFunctionContext ctx_r; 473*d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_r); CeedChk(ierr); 474*d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, 475*d1d35e2fSjeremylt sizeof(*num_comp_r_data), num_comp_r_data); 476777ff853SJeremy L Thompson CeedChk(ierr); 477*d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_restrict, ctx_r); CeedChk(ierr); 478*d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_r); CeedChk(ierr); 479*d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "input", num_comp, CEED_EVAL_NONE); 480d99fa3c5SJeremy L Thompson CeedChk(ierr); 481*d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "scale", num_comp, CEED_EVAL_NONE); 482d99fa3c5SJeremy L Thompson CeedChk(ierr); 483*d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_restrict, "output", num_comp, 484*d1d35e2fSjeremylt CEED_EVAL_INTERP); CeedChk(ierr); 485d99fa3c5SJeremy L Thompson 486*d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE, 487*d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_restrict); 488d99fa3c5SJeremy L Thompson CeedChk(ierr); 489*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "input", rstr_fine, 490d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 491d99fa3c5SJeremy L Thompson CeedChk(ierr); 492*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "scale", rstr_fine, 493*d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 494d99fa3c5SJeremy L Thompson CeedChk(ierr); 495*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "output", rstr_coarse, basis_c_to_f, 496d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 497d99fa3c5SJeremy L Thompson 498d99fa3c5SJeremy L Thompson // Prolongation 499*d1d35e2fSjeremylt CeedQFunction qf_prolong; 500*d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_prolong); 501d99fa3c5SJeremy L Thompson CeedChk(ierr); 502*d1d35e2fSjeremylt CeedInt *num_comp_p_data; 503*d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_p_data); CeedChk(ierr); 504*d1d35e2fSjeremylt num_comp_p_data[0] = num_comp; 505*d1d35e2fSjeremylt CeedQFunctionContext ctx_p; 506*d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_p); CeedChk(ierr); 507*d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_p, CEED_MEM_HOST, CEED_OWN_POINTER, 508*d1d35e2fSjeremylt sizeof(*num_comp_p_data), num_comp_p_data); 509777ff853SJeremy L Thompson CeedChk(ierr); 510*d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_prolong, ctx_p); CeedChk(ierr); 511*d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_p); CeedChk(ierr); 512*d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "input", num_comp, CEED_EVAL_INTERP); 513d99fa3c5SJeremy L Thompson CeedChk(ierr); 514*d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "scale", num_comp, CEED_EVAL_NONE); 515d99fa3c5SJeremy L Thompson CeedChk(ierr); 516*d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_prolong, "output", num_comp, CEED_EVAL_NONE); 517d99fa3c5SJeremy L Thompson CeedChk(ierr); 518d99fa3c5SJeremy L Thompson 519*d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_prolong, CEED_QFUNCTION_NONE, 520*d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_prolong); 521d99fa3c5SJeremy L Thompson CeedChk(ierr); 522*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "input", rstr_coarse, basis_c_to_f, 523d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 524*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "scale", rstr_fine, 525*d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 526d99fa3c5SJeremy L Thompson CeedChk(ierr); 527*d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "output", rstr_fine, 528d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 529d99fa3c5SJeremy L Thompson CeedChk(ierr); 530d99fa3c5SJeremy L Thompson 531d99fa3c5SJeremy L Thompson // Cleanup 532*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_vec); CeedChk(ierr); 533*d1d35e2fSjeremylt ierr = CeedBasisDestroy(&basis_c_to_f); CeedChk(ierr); 534*d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_restrict); CeedChk(ierr); 535*d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_prolong); CeedChk(ierr); 536e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 537d99fa3c5SJeremy L Thompson } 538d99fa3c5SJeremy L Thompson 5397a982d89SJeremy L. Thompson /// @} 5407a982d89SJeremy L. Thompson 5417a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5427a982d89SJeremy L. Thompson /// CeedOperator Backend API 5437a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5447a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5457a982d89SJeremy L. Thompson /// @{ 5467a982d89SJeremy L. Thompson 5477a982d89SJeremy L. Thompson /** 5487a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5497a982d89SJeremy L. Thompson 5507a982d89SJeremy L. Thompson @param op CeedOperator 5517a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5527a982d89SJeremy L. Thompson 5537a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5547a982d89SJeremy L. Thompson 5557a982d89SJeremy L. Thompson @ref Backend 5567a982d89SJeremy L. Thompson **/ 5577a982d89SJeremy L. Thompson 5587a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5597a982d89SJeremy L. Thompson *ceed = op->ceed; 560e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5617a982d89SJeremy L. Thompson } 5627a982d89SJeremy L. Thompson 5637a982d89SJeremy L. Thompson /** 5647a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5657a982d89SJeremy L. Thompson 5667a982d89SJeremy L. Thompson @param op CeedOperator 567*d1d35e2fSjeremylt @param[out] num_elem Variable to store number of elements 5687a982d89SJeremy L. Thompson 5697a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5707a982d89SJeremy L. Thompson 5717a982d89SJeremy L. Thompson @ref Backend 5727a982d89SJeremy L. Thompson **/ 5737a982d89SJeremy L. Thompson 574*d1d35e2fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 5757a982d89SJeremy L. Thompson if (op->composite) 5767a982d89SJeremy L. Thompson // LCOV_EXCL_START 577e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 578e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5797a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5807a982d89SJeremy L. Thompson 581*d1d35e2fSjeremylt *num_elem = op->num_elem; 582e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5837a982d89SJeremy L. Thompson } 5847a982d89SJeremy L. Thompson 5857a982d89SJeremy L. Thompson /** 5867a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5877a982d89SJeremy L. Thompson 5887a982d89SJeremy L. Thompson @param op CeedOperator 589*d1d35e2fSjeremylt @param[out] num_qpts Variable to store vector number of quadrature points 5907a982d89SJeremy L. Thompson 5917a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5927a982d89SJeremy L. Thompson 5937a982d89SJeremy L. Thompson @ref Backend 5947a982d89SJeremy L. Thompson **/ 5957a982d89SJeremy L. Thompson 596*d1d35e2fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 5977a982d89SJeremy L. Thompson if (op->composite) 5987a982d89SJeremy L. Thompson // LCOV_EXCL_START 599e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 600e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6017a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6027a982d89SJeremy L. Thompson 603*d1d35e2fSjeremylt *num_qpts = op->num_qpts; 604e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6057a982d89SJeremy L. Thompson } 6067a982d89SJeremy L. Thompson 6077a982d89SJeremy L. Thompson /** 6087a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 6097a982d89SJeremy L. Thompson 6107a982d89SJeremy L. Thompson @param op CeedOperator 611*d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 6127a982d89SJeremy L. Thompson 6137a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6147a982d89SJeremy L. Thompson 6157a982d89SJeremy L. Thompson @ref Backend 6167a982d89SJeremy L. Thompson **/ 6177a982d89SJeremy L. Thompson 618*d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 6197a982d89SJeremy L. Thompson if (op->composite) 6207a982d89SJeremy L. Thompson // LCOV_EXCL_START 621e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 622e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6237a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6247a982d89SJeremy L. Thompson 625*d1d35e2fSjeremylt *num_args = op->num_fields; 626e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6277a982d89SJeremy L. Thompson } 6287a982d89SJeremy L. Thompson 6297a982d89SJeremy L. Thompson /** 6307a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6317a982d89SJeremy L. Thompson 6327a982d89SJeremy L. Thompson @param op CeedOperator 633*d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 6347a982d89SJeremy L. Thompson 6357a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6367a982d89SJeremy L. Thompson 6377a982d89SJeremy L. Thompson @ref Backend 6387a982d89SJeremy L. Thompson **/ 6397a982d89SJeremy L. Thompson 640*d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 641*d1d35e2fSjeremylt *is_setup_done = op->backend_setup; 642e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6437a982d89SJeremy L. Thompson } 6447a982d89SJeremy L. Thompson 6457a982d89SJeremy L. Thompson /** 6467a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6477a982d89SJeremy L. Thompson 6487a982d89SJeremy L. Thompson @param op CeedOperator 6497a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6507a982d89SJeremy L. Thompson 6517a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6527a982d89SJeremy L. Thompson 6537a982d89SJeremy L. Thompson @ref Backend 6547a982d89SJeremy L. Thompson **/ 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6577a982d89SJeremy L. Thompson if (op->composite) 6587a982d89SJeremy L. Thompson // LCOV_EXCL_START 659e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 660e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6617a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6627a982d89SJeremy L. Thompson 6637a982d89SJeremy L. Thompson *qf = op->qf; 664e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6657a982d89SJeremy L. Thompson } 6667a982d89SJeremy L. Thompson 6677a982d89SJeremy L. Thompson /** 668c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 669c04a41a7SJeremy L Thompson 670c04a41a7SJeremy L Thompson @param op CeedOperator 671*d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 672c04a41a7SJeremy L Thompson 673c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 674c04a41a7SJeremy L Thompson 675c04a41a7SJeremy L Thompson @ref Backend 676c04a41a7SJeremy L Thompson **/ 677c04a41a7SJeremy L Thompson 678*d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 679*d1d35e2fSjeremylt *is_composite = op->composite; 680e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 681c04a41a7SJeremy L Thompson } 682c04a41a7SJeremy L Thompson 683c04a41a7SJeremy L Thompson /** 684*d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 6857a982d89SJeremy L. Thompson 6867a982d89SJeremy L. Thompson @param op CeedOperator 687*d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 6887a982d89SJeremy L. Thompson 6897a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6907a982d89SJeremy L. Thompson 6917a982d89SJeremy L. Thompson @ref Backend 6927a982d89SJeremy L. Thompson **/ 6937a982d89SJeremy L. Thompson 694*d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 6957a982d89SJeremy L. Thompson if (!op->composite) 6967a982d89SJeremy L. Thompson // LCOV_EXCL_START 697e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6987a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6997a982d89SJeremy L. Thompson 700*d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 701e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7027a982d89SJeremy L. Thompson } 7037a982d89SJeremy L. Thompson 7047a982d89SJeremy L. Thompson /** 705*d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 7067a982d89SJeremy L. Thompson 7077a982d89SJeremy L. Thompson @param op CeedOperator 708*d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 7097a982d89SJeremy L. Thompson 7107a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7117a982d89SJeremy L. Thompson 7127a982d89SJeremy L. Thompson @ref Backend 7137a982d89SJeremy L. Thompson **/ 7147a982d89SJeremy L. Thompson 715*d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 7167a982d89SJeremy L. Thompson if (!op->composite) 7177a982d89SJeremy L. Thompson // LCOV_EXCL_START 718e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7197a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7207a982d89SJeremy L. Thompson 721*d1d35e2fSjeremylt *sub_operators = op->sub_operators; 722e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7237a982d89SJeremy L. Thompson } 7247a982d89SJeremy L. Thompson 7257a982d89SJeremy L. Thompson /** 7267a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7277a982d89SJeremy L. Thompson 7287a982d89SJeremy L. Thompson @param op CeedOperator 7297a982d89SJeremy L. Thompson @param[out] data Variable to store data 7307a982d89SJeremy L. Thompson 7317a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7327a982d89SJeremy L. Thompson 7337a982d89SJeremy L. Thompson @ref Backend 7347a982d89SJeremy L. Thompson **/ 7357a982d89SJeremy L. Thompson 736777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 737777ff853SJeremy L Thompson *(void **)data = op->data; 738e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7397a982d89SJeremy L. Thompson } 7407a982d89SJeremy L. Thompson 7417a982d89SJeremy L. Thompson /** 7427a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7437a982d89SJeremy L. Thompson 7447a982d89SJeremy L. Thompson @param[out] op CeedOperator 7457a982d89SJeremy L. Thompson @param data Data to set 7467a982d89SJeremy L. Thompson 7477a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7487a982d89SJeremy L. Thompson 7497a982d89SJeremy L. Thompson @ref Backend 7507a982d89SJeremy L. Thompson **/ 7517a982d89SJeremy L. Thompson 752777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 753777ff853SJeremy L Thompson op->data = data; 754e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7557a982d89SJeremy L. Thompson } 7567a982d89SJeremy L. Thompson 7577a982d89SJeremy L. Thompson /** 7587a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7597a982d89SJeremy L. Thompson 7607a982d89SJeremy L. Thompson @param op CeedOperator 7617a982d89SJeremy L. Thompson 7627a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7637a982d89SJeremy L. Thompson 7647a982d89SJeremy L. Thompson @ref Backend 7657a982d89SJeremy L. Thompson **/ 7667a982d89SJeremy L. Thompson 7677a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 768*d1d35e2fSjeremylt op->backend_setup = true; 769e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7707a982d89SJeremy L. Thompson } 7717a982d89SJeremy L. Thompson 7727a982d89SJeremy L. Thompson /** 7737a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7747a982d89SJeremy L. Thompson 7757a982d89SJeremy L. Thompson @param op CeedOperator 776*d1d35e2fSjeremylt @param[out] input_fields Variable to store input_fields 777*d1d35e2fSjeremylt @param[out] output_fields Variable to store output_fields 7787a982d89SJeremy L. Thompson 7797a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7807a982d89SJeremy L. Thompson 7817a982d89SJeremy L. Thompson @ref Backend 7827a982d89SJeremy L. Thompson **/ 7837a982d89SJeremy L. Thompson 784*d1d35e2fSjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **input_fields, 785*d1d35e2fSjeremylt CeedOperatorField **output_fields) { 7867a982d89SJeremy L. Thompson if (op->composite) 7877a982d89SJeremy L. Thompson // LCOV_EXCL_START 788e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 789e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 7907a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7917a982d89SJeremy L. Thompson 792*d1d35e2fSjeremylt if (input_fields) *input_fields = op->input_fields; 793*d1d35e2fSjeremylt if (output_fields) *output_fields = op->output_fields; 794e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7957a982d89SJeremy L. Thompson } 7967a982d89SJeremy L. Thompson 7977a982d89SJeremy L. Thompson /** 7987a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 7997a982d89SJeremy L. Thompson 800*d1d35e2fSjeremylt @param op_field CeedOperatorField 8017a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 8027a982d89SJeremy L. Thompson 8037a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8047a982d89SJeremy L. Thompson 8057a982d89SJeremy L. Thompson @ref Backend 8067a982d89SJeremy L. Thompson **/ 8077a982d89SJeremy L. Thompson 808*d1d35e2fSjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 8097a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 810*d1d35e2fSjeremylt *rstr = op_field->elem_restr; 811e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8127a982d89SJeremy L. Thompson } 8137a982d89SJeremy L. Thompson 8147a982d89SJeremy L. Thompson /** 8157a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8167a982d89SJeremy L. Thompson 817*d1d35e2fSjeremylt @param op_field CeedOperatorField 8187a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8197a982d89SJeremy L. Thompson 8207a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8217a982d89SJeremy L. Thompson 8227a982d89SJeremy L. Thompson @ref Backend 8237a982d89SJeremy L. Thompson **/ 8247a982d89SJeremy L. Thompson 825*d1d35e2fSjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 826*d1d35e2fSjeremylt *basis = op_field->basis; 827e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8287a982d89SJeremy L. Thompson } 8297a982d89SJeremy L. Thompson 8307a982d89SJeremy L. Thompson /** 8317a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8327a982d89SJeremy L. Thompson 833*d1d35e2fSjeremylt @param op_field CeedOperatorField 8347a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8357a982d89SJeremy L. Thompson 8367a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8377a982d89SJeremy L. Thompson 8387a982d89SJeremy L. Thompson @ref Backend 8397a982d89SJeremy L. Thompson **/ 8407a982d89SJeremy L. Thompson 841*d1d35e2fSjeremylt int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 842*d1d35e2fSjeremylt *vec = op_field->vec; 843e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8447a982d89SJeremy L. Thompson } 8457a982d89SJeremy L. Thompson 8467a982d89SJeremy L. Thompson /// @} 8477a982d89SJeremy L. Thompson 8487a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8497a982d89SJeremy L. Thompson /// CeedOperator Public API 8507a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8517a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 852dfdf5a53Sjeremylt /// @{ 853d7b241e6Sjeremylt 854d7b241e6Sjeremylt /** 8550219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8560219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8570219ea01SJeremy L Thompson \ref CeedOperatorSetField. 858d7b241e6Sjeremylt 859b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 860d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 86134138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8624cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 863d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8644cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 865b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 866b11c1e72Sjeremylt CeedOperator will be stored 867b11c1e72Sjeremylt 868b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 869dfdf5a53Sjeremylt 8707a982d89SJeremy L. Thompson @ref User 871d7b241e6Sjeremylt */ 872d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 873d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 874d7b241e6Sjeremylt int ierr; 875d7b241e6Sjeremylt 8765fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8775fe0d4faSjeremylt Ceed delegate; 878aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8795fe0d4faSjeremylt 8805fe0d4faSjeremylt if (!delegate) 881c042f62fSJeremy L Thompson // LCOV_EXCL_START 882e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 883e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 884c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8855fe0d4faSjeremylt 8865fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 887e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8885fe0d4faSjeremylt } 8895fe0d4faSjeremylt 890b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 891b3b7035fSJeremy L Thompson // LCOV_EXCL_START 892e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 893e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 894b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 895d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 896d7b241e6Sjeremylt (*op)->ceed = ceed; 897*d1d35e2fSjeremylt ceed->ref_count++; 898*d1d35e2fSjeremylt (*op)->ref_count = 1; 899d7b241e6Sjeremylt (*op)->qf = qf; 900*d1d35e2fSjeremylt qf->ref_count++; 901442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 902d7b241e6Sjeremylt (*op)->dqf = dqf; 903*d1d35e2fSjeremylt dqf->ref_count++; 904442e7f0bSjeremylt } 905442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 906d7b241e6Sjeremylt (*op)->dqfT = dqfT; 907*d1d35e2fSjeremylt dqfT->ref_count++; 908442e7f0bSjeremylt } 909*d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr); 910*d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr); 911d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 912e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 913d7b241e6Sjeremylt } 914d7b241e6Sjeremylt 915d7b241e6Sjeremylt /** 91652d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 91752d6035fSJeremy L Thompson 91852d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 91952d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 92052d6035fSJeremy L Thompson Composite CeedOperator will be stored 92152d6035fSJeremy L Thompson 92252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 92352d6035fSJeremy L Thompson 9247a982d89SJeremy L. Thompson @ref User 92552d6035fSJeremy L Thompson */ 92652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 92752d6035fSJeremy L Thompson int ierr; 92852d6035fSJeremy L Thompson 92952d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 93052d6035fSJeremy L Thompson Ceed delegate; 931aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 93252d6035fSJeremy L Thompson 933250756a7Sjeremylt if (delegate) { 93452d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 935e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 93652d6035fSJeremy L Thompson } 937250756a7Sjeremylt } 93852d6035fSJeremy L Thompson 93952d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 94052d6035fSJeremy L Thompson (*op)->ceed = ceed; 941*d1d35e2fSjeremylt ceed->ref_count++; 94252d6035fSJeremy L Thompson (*op)->composite = true; 943*d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr); 944250756a7Sjeremylt 945250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 94652d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 947250756a7Sjeremylt } 948e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 94952d6035fSJeremy L Thompson } 95052d6035fSJeremy L Thompson 95152d6035fSJeremy L Thompson /** 952b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 953d7b241e6Sjeremylt 954d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 955d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 956d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 957d7b241e6Sjeremylt 958d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 959d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 960d7b241e6Sjeremylt input and at most one active output. 961d7b241e6Sjeremylt 9628c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 963*d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 9648795c945Sjeremylt CeedQFunction) 965b11c1e72Sjeremylt @param r CeedElemRestriction 9664cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 967b11c1e72Sjeremylt if collocated with quadrature points 9684cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9694cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9704cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 971b11c1e72Sjeremylt 972b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 973dfdf5a53Sjeremylt 9747a982d89SJeremy L. Thompson @ref User 975b11c1e72Sjeremylt **/ 976*d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 977a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 978d7b241e6Sjeremylt int ierr; 97952d6035fSJeremy L Thompson if (op->composite) 980c042f62fSJeremy L Thompson // LCOV_EXCL_START 981e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 982e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 983c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9848b067b84SJed Brown if (!r) 985c042f62fSJeremy L Thompson // LCOV_EXCL_START 986e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 987c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 988*d1d35e2fSjeremylt field_name); 989c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9908b067b84SJed Brown if (!b) 991c042f62fSJeremy L Thompson // LCOV_EXCL_START 992e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 993e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 994*d1d35e2fSjeremylt field_name); 995c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9968b067b84SJed Brown if (!v) 997c042f62fSJeremy L Thompson // LCOV_EXCL_START 998e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 999e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 1000*d1d35e2fSjeremylt field_name); 1001c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 100252d6035fSJeremy L Thompson 1003*d1d35e2fSjeremylt CeedInt num_elem; 1004*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 1005*d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 1006*d1d35e2fSjeremylt op->num_elem != num_elem) 1007c042f62fSJeremy L Thompson // LCOV_EXCL_START 1008e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10091d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1010*d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 1011c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1012d7b241e6Sjeremylt 1013*d1d35e2fSjeremylt CeedInt num_qpts; 1014e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1015*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 1016*d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 1017c042f62fSJeremy L Thompson // LCOV_EXCL_START 1018e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1019e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 1020*d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 1021*d1d35e2fSjeremylt op->num_qpts); 1022c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1023d7b241e6Sjeremylt } 1024*d1d35e2fSjeremylt CeedQFunctionField qf_field; 1025*d1d35e2fSjeremylt CeedOperatorField *op_field; 1026*d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 1027*d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 1028*d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 1029*d1d35e2fSjeremylt op_field = &op->input_fields[i]; 1030d7b241e6Sjeremylt goto found; 1031d7b241e6Sjeremylt } 1032d7b241e6Sjeremylt } 1033*d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 1034*d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 1035*d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 1036*d1d35e2fSjeremylt op_field = &op->output_fields[i]; 1037d7b241e6Sjeremylt goto found; 1038d7b241e6Sjeremylt } 1039d7b241e6Sjeremylt } 1040c042f62fSJeremy L Thompson // LCOV_EXCL_START 1041e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1042e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1043*d1d35e2fSjeremylt field_name); 1044c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1045d7b241e6Sjeremylt found: 1046*d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 1047*d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 1048e15f9bd0SJeremy L Thompson 1049*d1d35e2fSjeremylt (*op_field)->vec = v; 1050e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1051*d1d35e2fSjeremylt v->ref_count += 1; 1052e15f9bd0SJeremy L Thompson } 1053e15f9bd0SJeremy L Thompson 1054*d1d35e2fSjeremylt (*op_field)->elem_restr = r; 1055*d1d35e2fSjeremylt r->ref_count += 1; 1056e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1057*d1d35e2fSjeremylt op->num_elem = num_elem; 1058*d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 1059e15f9bd0SJeremy L Thompson } 1060d99fa3c5SJeremy L Thompson 1061*d1d35e2fSjeremylt (*op_field)->basis = b; 1062e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1063*d1d35e2fSjeremylt op->num_qpts = num_qpts; 1064*d1d35e2fSjeremylt b->ref_count += 1; 1065e15f9bd0SJeremy L Thompson } 1066e15f9bd0SJeremy L Thompson 1067*d1d35e2fSjeremylt op->num_fields += 1; 1068*d1d35e2fSjeremylt size_t len = strlen(field_name); 1069d99fa3c5SJeremy L Thompson char *tmp; 1070d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1071*d1d35e2fSjeremylt memcpy(tmp, field_name, len+1); 1072*d1d35e2fSjeremylt (*op_field)->field_name = tmp; 1073e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1074d7b241e6Sjeremylt } 1075d7b241e6Sjeremylt 1076d7b241e6Sjeremylt /** 107752d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1078288c0443SJeremy L Thompson 1079*d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 1080*d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 108152d6035fSJeremy L Thompson 108252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 108352d6035fSJeremy L Thompson 10847a982d89SJeremy L. Thompson @ref User 108552d6035fSJeremy L Thompson */ 1086*d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 1087*d1d35e2fSjeremylt CeedOperator sub_op) { 1088*d1d35e2fSjeremylt if (!composite_op->composite) 1089c042f62fSJeremy L Thompson // LCOV_EXCL_START 1090*d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 1091e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1092c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 109352d6035fSJeremy L Thompson 1094*d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 1095c042f62fSJeremy L Thompson // LCOV_EXCL_START 1096*d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 1097*d1d35e2fSjeremylt "Cannot add additional sub_operators"); 1098c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 109952d6035fSJeremy L Thompson 1100*d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 1101*d1d35e2fSjeremylt sub_op->ref_count++; 1102*d1d35e2fSjeremylt composite_op->num_suboperators++; 1103e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 110452d6035fSJeremy L Thompson } 110552d6035fSJeremy L Thompson 110652d6035fSJeremy L Thompson /** 11071d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11081d102b48SJeremy L Thompson 11091d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11101d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11111d102b48SJeremy L Thompson The vector 'assembled' is of shape 11121d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11131d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11141d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11151d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11164cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11171d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11181d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11191d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11201d102b48SJeremy L Thompson 11211d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11221d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11231d102b48SJeremy L Thompson quadrature points 11241d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11251d102b48SJeremy L Thompson CeedQFunction 11261d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11274cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11281d102b48SJeremy L Thompson 11291d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11301d102b48SJeremy L Thompson 11317a982d89SJeremy L. Thompson @ref User 11321d102b48SJeremy L Thompson **/ 113380ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11347f823360Sjeremylt CeedElemRestriction *rstr, 11357f823360Sjeremylt CeedRequest *request) { 11361d102b48SJeremy L Thompson int ierr; 1137e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11381d102b48SJeremy L Thompson 11397172caadSjeremylt // Backend version 114080ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1141e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11425107b09fSJeremy L Thompson } else { 11435107b09fSJeremy L Thompson // Fallback to reference Ceed 1144*d1d35e2fSjeremylt if (!op->op_fallback) { 11455107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11465107b09fSJeremy L Thompson } 11475107b09fSJeremy L Thompson // Assemble 1148*d1d35e2fSjeremylt return CeedOperatorLinearAssembleQFunction(op->op_fallback, assembled, 1149e2f04181SAndrew T. Barker rstr, request); 11505107b09fSJeremy L Thompson } 11511d102b48SJeremy L Thompson } 11521d102b48SJeremy L Thompson 11531d102b48SJeremy L Thompson /** 1154d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1155b7ec98d8SJeremy L Thompson 11569e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1157b7ec98d8SJeremy L Thompson 1158c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1159c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1160d965c7a7SJeremy L Thompson 1161b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1162b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1163b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11644cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1165b7ec98d8SJeremy L Thompson 1166b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1167b7ec98d8SJeremy L Thompson 11687a982d89SJeremy L. Thompson @ref User 1169b7ec98d8SJeremy L Thompson **/ 11702bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11717f823360Sjeremylt CeedRequest *request) { 1172b7ec98d8SJeremy L Thompson int ierr; 1173e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1174b7ec98d8SJeremy L Thompson 1175b7ec98d8SJeremy L Thompson // Use backend version, if available 117680ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1177e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 11789e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11799e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11809e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11819e9210b8SJeremy L Thompson } else { 11829e9210b8SJeremy L Thompson // Fallback to reference Ceed 1183*d1d35e2fSjeremylt if (!op->op_fallback) { 11849e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11859e9210b8SJeremy L Thompson } 11869e9210b8SJeremy L Thompson // Assemble 1187*d1d35e2fSjeremylt return CeedOperatorLinearAssembleDiagonal(op->op_fallback, assembled, 1188e2f04181SAndrew T. Barker request); 11899e9210b8SJeremy L Thompson } 11909e9210b8SJeremy L Thompson } 11919e9210b8SJeremy L Thompson 11929e9210b8SJeremy L Thompson /** 11939e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 11949e9210b8SJeremy L Thompson 11959e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 11969e9210b8SJeremy L Thompson 11979e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 11989e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 11999e9210b8SJeremy L Thompson 12009e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12019e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 12029e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12039e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 12049e9210b8SJeremy L Thompson 12059e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12069e9210b8SJeremy L Thompson 12079e9210b8SJeremy L Thompson @ref User 12089e9210b8SJeremy L Thompson **/ 12099e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12109e9210b8SJeremy L Thompson CeedRequest *request) { 12119e9210b8SJeremy L Thompson int ierr; 1212e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12139e9210b8SJeremy L Thompson 12149e9210b8SJeremy L Thompson // Use backend version, if available 12159e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1216e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12177172caadSjeremylt } else { 12187172caadSjeremylt // Fallback to reference Ceed 1219*d1d35e2fSjeremylt if (!op->op_fallback) { 12207172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1221b7ec98d8SJeremy L Thompson } 12227172caadSjeremylt // Assemble 1223*d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddDiagonal(op->op_fallback, assembled, 1224e2f04181SAndrew T. Barker request); 1225b7ec98d8SJeremy L Thompson } 1226b7ec98d8SJeremy L Thompson } 1227b7ec98d8SJeremy L Thompson 1228b7ec98d8SJeremy L Thompson /** 1229d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1230d965c7a7SJeremy L Thompson 12319e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1232d965c7a7SJeremy L Thompson CeedOperator. 1233d965c7a7SJeremy L Thompson 1234c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1235c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1236d965c7a7SJeremy L Thompson 1237d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1238d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1239d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1240*d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 1241d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1242d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1243d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1244d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1245d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1246d965c7a7SJeremy L Thompson 1247d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1248d965c7a7SJeremy L Thompson 1249d965c7a7SJeremy L Thompson @ref User 1250d965c7a7SJeremy L Thompson **/ 125180ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12522bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1253d965c7a7SJeremy L Thompson int ierr; 1254e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1255d965c7a7SJeremy L Thompson 1256d965c7a7SJeremy L Thompson // Use backend version, if available 125780ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1258e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12599e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12609e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12619e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12629e9210b8SJeremy L Thompson request); 1263d965c7a7SJeremy L Thompson } else { 1264d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1265*d1d35e2fSjeremylt if (!op->op_fallback) { 1266d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1267d965c7a7SJeremy L Thompson } 1268d965c7a7SJeremy L Thompson // Assemble 1269*d1d35e2fSjeremylt return CeedOperatorLinearAssemblePointBlockDiagonal(op->op_fallback, 1270e2f04181SAndrew T. Barker assembled, request); 12719e9210b8SJeremy L Thompson } 12729e9210b8SJeremy L Thompson } 12739e9210b8SJeremy L Thompson 12749e9210b8SJeremy L Thompson /** 12759e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12769e9210b8SJeremy L Thompson 12779e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12789e9210b8SJeremy L Thompson CeedOperator. 12799e9210b8SJeremy L Thompson 12809e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12819e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12829e9210b8SJeremy L Thompson 12839e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12849e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 12859e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 1286*d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 12879e9210b8SJeremy L Thompson of this vector are derived from the active vector 12889e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 12899e9210b8SJeremy L Thompson [nodes, component out, component in]. 12909e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12919e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 12929e9210b8SJeremy L Thompson 12939e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12949e9210b8SJeremy L Thompson 12959e9210b8SJeremy L Thompson @ref User 12969e9210b8SJeremy L Thompson **/ 12979e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 12989e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 12999e9210b8SJeremy L Thompson int ierr; 1300e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 13019e9210b8SJeremy L Thompson 13029e9210b8SJeremy L Thompson // Use backend version, if available 13039e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1304e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 13059e9210b8SJeremy L Thompson } else { 13069e9210b8SJeremy L Thompson // Fallback to reference Ceed 1307*d1d35e2fSjeremylt if (!op->op_fallback) { 13089e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13099e9210b8SJeremy L Thompson } 13109e9210b8SJeremy L Thompson // Assemble 1311*d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->op_fallback, 1312e2f04181SAndrew T. Barker assembled, request); 1313d965c7a7SJeremy L Thompson } 1314e2f04181SAndrew T. Barker } 1315e2f04181SAndrew T. Barker 1316e2f04181SAndrew T. Barker /** 1317e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1318e2f04181SAndrew T. Barker 1319e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1320e2f04181SAndrew T. Barker 1321e2f04181SAndrew T. Barker @ref Developer 1322e2f04181SAndrew T. Barker **/ 1323e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1324e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1325e2f04181SAndrew T. Barker int ierr; 1326e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1327e2f04181SAndrew T. Barker if (op->composite) 1328e2f04181SAndrew T. Barker // LCOV_EXCL_START 1329e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1330e2f04181SAndrew T. Barker "Composite operator not supported"); 1331e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1332e2f04181SAndrew T. Barker 1333*d1d35e2fSjeremylt CeedElemRestriction rstr_in; 1334*d1d35e2fSjeremylt ierr = CeedOperatorGetActiveElemRestriction(op, &rstr_in); CeedChk(ierr); 1335*d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_nodes, num_comp; 1336*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1337*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1338*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr_in, &num_nodes); CeedChk(ierr); 1339*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1340e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1341*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetELayout(rstr_in, &layout_er); CeedChk(ierr); 1342e2f04181SAndrew T. Barker 1343*d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1344e2f04181SAndrew T. Barker 1345e2f04181SAndrew T. Barker // Determine elem_dof relation 1346e2f04181SAndrew T. Barker CeedVector index_vec; 1347*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_nodes, &index_vec); CeedChk(ierr); 1348e2f04181SAndrew T. Barker CeedScalar *array; 1349e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1350*d1d35e2fSjeremylt for (CeedInt i = 0; i < num_nodes; ++i) { 1351e2f04181SAndrew T. Barker array[i] = i; 1352e2f04181SAndrew T. Barker } 1353e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1354e2f04181SAndrew T. Barker CeedVector elem_dof; 1355*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_elem * elem_size * num_comp, &elem_dof); 1356e2f04181SAndrew T. Barker CeedChk(ierr); 1357e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1358*d1d35e2fSjeremylt CeedElemRestrictionApply(rstr_in, CEED_NOTRANSPOSE, index_vec, 1359e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1360e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1361e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1362e2f04181SAndrew T. Barker CeedChk(ierr); 1363e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1364e2f04181SAndrew T. Barker 1365e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1366e2f04181SAndrew T. Barker CeedInt count = 0; 1367*d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1368*d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1369*d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1370*d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1371*d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1372*d1d35e2fSjeremylt const CeedInt elem_dof_index_row = (i)*layout_er[0] + 1373*d1d35e2fSjeremylt (comp_out)*layout_er[1] + e*layout_er[2]; 1374*d1d35e2fSjeremylt const CeedInt elem_dof_index_col = (j)*layout_er[0] + 1375*d1d35e2fSjeremylt (comp_in)*layout_er[1] + e*layout_er[2]; 1376e2f04181SAndrew T. Barker 1377*d1d35e2fSjeremylt const CeedInt row = elem_dof_a[elem_dof_index_row]; 1378*d1d35e2fSjeremylt const CeedInt col = elem_dof_a[elem_dof_index_col]; 1379e2f04181SAndrew T. Barker 1380e2f04181SAndrew T. Barker rows[offset + count] = row; 1381e2f04181SAndrew T. Barker cols[offset + count] = col; 1382e2f04181SAndrew T. Barker count++; 1383e2f04181SAndrew T. Barker } 1384e2f04181SAndrew T. Barker } 1385e2f04181SAndrew T. Barker } 1386e2f04181SAndrew T. Barker } 1387e2f04181SAndrew T. Barker } 1388*d1d35e2fSjeremylt if (count != local_num_entries) 1389e2f04181SAndrew T. Barker // LCOV_EXCL_START 1390e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1391e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1392e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1393e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1394e2f04181SAndrew T. Barker 1395e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1396e2f04181SAndrew T. Barker } 1397e2f04181SAndrew T. Barker 1398e2f04181SAndrew T. Barker /** 1399e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1400e2f04181SAndrew T. Barker 1401e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1402e2f04181SAndrew T. Barker 1403e2f04181SAndrew T. Barker @ref Developer 1404e2f04181SAndrew T. Barker **/ 1405e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1406e2f04181SAndrew T. Barker CeedVector values) { 1407e2f04181SAndrew T. Barker int ierr; 1408e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1409e2f04181SAndrew T. Barker if (op->composite) 1410e2f04181SAndrew T. Barker // LCOV_EXCL_START 1411e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1412e2f04181SAndrew T. Barker "Composite operator not supported"); 1413e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1414e2f04181SAndrew T. Barker 1415e2f04181SAndrew T. Barker // Assemble QFunction 1416e2f04181SAndrew T. Barker CeedQFunction qf; 1417e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1418*d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 1419*d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 1420e2f04181SAndrew T. Barker CeedChk(ierr); 1421*d1d35e2fSjeremylt CeedVector assembled_qf; 1422e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1423e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1424*d1d35e2fSjeremylt op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1425e2f04181SAndrew T. Barker 1426*d1d35e2fSjeremylt CeedInt qf_length; 1427*d1d35e2fSjeremylt ierr = CeedVectorGetLength(assembled_qf, &qf_length); CeedChk(ierr); 1428e2f04181SAndrew T. Barker 1429e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1430e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1431e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1432e2f04181SAndrew T. Barker 1433e2f04181SAndrew T. Barker // Determine active input basis 1434*d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1435*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChk(ierr); 1436*d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, dim = 1; 1437*d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 1438*d1d35e2fSjeremylt CeedBasis basis_in = NULL; 1439*d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 1440*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1441e2f04181SAndrew T. Barker CeedVector vec; 1442e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1443e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1444*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(input_fields[i], &basis_in); 1445e2f04181SAndrew T. Barker CeedChk(ierr); 1446*d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChk(ierr); 1447*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in); 1448e2f04181SAndrew T. Barker CeedChk(ierr); 1449*d1d35e2fSjeremylt CeedEvalMode eval_mode; 1450*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1451e2f04181SAndrew T. Barker CeedChk(ierr); 1452*d1d35e2fSjeremylt switch (eval_mode) { 1453e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1454e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1455*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChk(ierr); 1456*d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 1457*d1d35e2fSjeremylt num_eval_mode_in += 1; 1458e2f04181SAndrew T. Barker break; 1459e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1460*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChk(ierr); 1461e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1462*d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 1463e2f04181SAndrew T. Barker } 1464*d1d35e2fSjeremylt num_eval_mode_in += dim; 1465e2f04181SAndrew T. Barker break; 1466e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1467e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1468e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1469e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1470e2f04181SAndrew T. Barker } 1471e2f04181SAndrew T. Barker } 1472e2f04181SAndrew T. Barker } 1473e2f04181SAndrew T. Barker 1474e2f04181SAndrew T. Barker // Determine active output basis 1475*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChk(ierr); 1476*d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 1477*d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 1478*d1d35e2fSjeremylt CeedBasis basis_out = NULL; 1479*d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 1480*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 1481e2f04181SAndrew T. Barker CeedVector vec; 1482e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1483e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1484*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(output_fields[i], &basis_out); 1485e2f04181SAndrew T. Barker CeedChk(ierr); 1486*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out); 1487e2f04181SAndrew T. Barker CeedChk(ierr); 1488*d1d35e2fSjeremylt CeedEvalMode eval_mode; 1489*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1490e2f04181SAndrew T. Barker CeedChk(ierr); 1491*d1d35e2fSjeremylt switch (eval_mode) { 1492e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1493e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1494*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChk(ierr); 1495*d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 1496*d1d35e2fSjeremylt num_eval_mode_out += 1; 1497e2f04181SAndrew T. Barker break; 1498e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1499*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); CeedChk(ierr); 1500e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1501*d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 1502e2f04181SAndrew T. Barker } 1503*d1d35e2fSjeremylt num_eval_mode_out += dim; 1504e2f04181SAndrew T. Barker break; 1505e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1506e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1507e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1508e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1509e2f04181SAndrew T. Barker } 1510e2f04181SAndrew T. Barker } 1511e2f04181SAndrew T. Barker } 1512e2f04181SAndrew T. Barker 1513*d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_qpts, num_comp; 1514*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1515*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1516*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1517*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); CeedChk(ierr); 1518e2f04181SAndrew T. Barker 1519*d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1520e2f04181SAndrew T. Barker 1521e2f04181SAndrew T. Barker // loop over elements and put in data structure 1522*d1d35e2fSjeremylt const CeedScalar *interp_in, *grad_in; 1523*d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChk(ierr); 1524*d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChk(ierr); 1525e2f04181SAndrew T. Barker 1526*d1d35e2fSjeremylt const CeedScalar *assembled_qf_array; 1527*d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 1528e2f04181SAndrew T. Barker CeedChk(ierr); 1529e2f04181SAndrew T. Barker 1530e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1531e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1532e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1533e2f04181SAndrew T. Barker 1534*d1d35e2fSjeremylt // we store B_mat_in, B_mat_out, BTD, elem_mat in row-major order 1535*d1d35e2fSjeremylt CeedScalar B_mat_in[(num_qpts * num_eval_mode_in) * elem_size]; 1536*d1d35e2fSjeremylt CeedScalar B_mat_out[(num_qpts * num_eval_mode_out) * elem_size]; 1537*d1d35e2fSjeremylt CeedScalar D_mat[num_eval_mode_out * num_eval_mode_in * 1538*d1d35e2fSjeremylt num_qpts]; // logically 3-tensor 1539*d1d35e2fSjeremylt CeedScalar BTD[elem_size * num_qpts*num_eval_mode_in]; 1540*d1d35e2fSjeremylt CeedScalar elem_mat[elem_size * elem_size]; 1541e2f04181SAndrew T. Barker int count = 0; 1542e2f04181SAndrew T. Barker CeedScalar *vals; 1543e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1544*d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1545*d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1546*d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1547*d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_in) * elem_size; ++ell) { 1548*d1d35e2fSjeremylt B_mat_in[ell] = 0.0; 1549e2f04181SAndrew T. Barker } 1550*d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_out) * elem_size; ++ell) { 1551*d1d35e2fSjeremylt B_mat_out[ell] = 0.0; 1552e2f04181SAndrew T. Barker } 1553e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1554*d1d35e2fSjeremylt for (int ell = 0; ell < num_eval_mode_in*num_eval_mode_out*num_qpts; ++ell) { 1555*d1d35e2fSjeremylt D_mat[ell] = 0.0; 1556e2f04181SAndrew T. Barker } 1557e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1558*d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*elem_size; ++ell) { 1559e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1560e2f04181SAndrew T. Barker } 1561*d1d35e2fSjeremylt for (int q = 0; q < num_qpts; ++q) { 1562*d1d35e2fSjeremylt for (int n = 0; n < elem_size; ++n) { 1563*d1d35e2fSjeremylt CeedInt d_in = -1; 1564*d1d35e2fSjeremylt for (int e_in = 0; e_in < num_eval_mode_in; ++e_in) { 1565*d1d35e2fSjeremylt const int qq = num_eval_mode_in*q; 1566*d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_INTERP) { 1567*d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += interp_in[q * elem_size + n]; 1568*d1d35e2fSjeremylt } else if (eval_mode_in[e_in] == CEED_EVAL_GRAD) { 1569*d1d35e2fSjeremylt d_in += 1; 1570*d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += 1571*d1d35e2fSjeremylt grad_in[(d_in*num_qpts+q) * elem_size + n]; 1572e2f04181SAndrew T. Barker } else { 1573e2f04181SAndrew T. Barker // LCOV_EXCL_START 1574e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1575e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1576e2f04181SAndrew T. Barker } 1577e2f04181SAndrew T. Barker } 1578*d1d35e2fSjeremylt CeedInt d_out = -1; 1579*d1d35e2fSjeremylt for (int e_out = 0; e_out < num_eval_mode_out; ++e_out) { 1580*d1d35e2fSjeremylt const int qq = num_eval_mode_out*q; 1581*d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_INTERP) { 1582*d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += interp_in[q * elem_size + n]; 1583*d1d35e2fSjeremylt } else if (eval_mode_out[e_out] == CEED_EVAL_GRAD) { 1584*d1d35e2fSjeremylt d_out += 1; 1585*d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += 1586*d1d35e2fSjeremylt grad_in[(d_out*num_qpts+q) * elem_size + n]; 1587e2f04181SAndrew T. Barker } else { 1588e2f04181SAndrew T. Barker // LCOV_EXCL_START 1589e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1590e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1591e2f04181SAndrew T. Barker } 1592e2f04181SAndrew T. Barker } 1593e2f04181SAndrew T. Barker } 1594*d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_out; ++ei) { 1595*d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_in; ++ej) { 1596*d1d35e2fSjeremylt const int eval_mode_index = ((ei*num_comp+comp_in)*num_eval_mode_in+ej)*num_comp 1597*d1d35e2fSjeremylt +comp_out; 1598*d1d35e2fSjeremylt const int index = q*layout_qf[0] + eval_mode_index*layout_qf[1] + 1599*d1d35e2fSjeremylt e*layout_qf[2]; 1600*d1d35e2fSjeremylt D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q] += assembled_qf_array[index]; 1601e2f04181SAndrew T. Barker } 1602e2f04181SAndrew T. Barker } 1603e2f04181SAndrew T. Barker } 1604e2f04181SAndrew T. Barker // Compute B^T*D 1605*d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*num_qpts*num_eval_mode_in; ++ell) { 1606e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1607e2f04181SAndrew T. Barker } 1608*d1d35e2fSjeremylt for (int j = 0; j<elem_size; ++j) { 1609*d1d35e2fSjeremylt for (int q = 0; q<num_qpts; ++q) { 1610*d1d35e2fSjeremylt int qq = num_eval_mode_out*q; 1611*d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_in; ++ei) { 1612*d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_out; ++ej) { 1613*d1d35e2fSjeremylt BTD[j*(num_qpts*num_eval_mode_in) + (qq+ei)] += 1614*d1d35e2fSjeremylt B_mat_out[(qq+ej)*elem_size + j] * D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q]; 1615e2f04181SAndrew T. Barker } 1616e2f04181SAndrew T. Barker } 1617e2f04181SAndrew T. Barker } 1618e2f04181SAndrew T. Barker } 1619e2f04181SAndrew T. Barker 1620*d1d35e2fSjeremylt ierr = CeedMatrixMultiply(ceed, BTD, B_mat_in, elem_mat, elem_size, 1621*d1d35e2fSjeremylt elem_size, num_qpts*num_eval_mode_in); CeedChk(ierr); 1622e2f04181SAndrew T. Barker 1623e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1624*d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1625*d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1626*d1d35e2fSjeremylt vals[offset + count] = elem_mat[i*elem_size + j]; 1627e2f04181SAndrew T. Barker count++; 1628e2f04181SAndrew T. Barker } 1629e2f04181SAndrew T. Barker } 1630e2f04181SAndrew T. Barker } 1631e2f04181SAndrew T. Barker } 1632e2f04181SAndrew T. Barker } 1633*d1d35e2fSjeremylt if (count != local_num_entries) 1634e2f04181SAndrew T. Barker // LCOV_EXCL_START 1635e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1636e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1637e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1638e2f04181SAndrew T. Barker 1639*d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(assembled_qf, &assembled_qf_array); 1640e2f04181SAndrew T. Barker CeedChk(ierr); 1641*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChk(ierr); 1642*d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChk(ierr); 1643*d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChk(ierr); 1644e2f04181SAndrew T. Barker 1645e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1646e2f04181SAndrew T. Barker } 1647e2f04181SAndrew T. Barker 1648e2f04181SAndrew T. Barker /** 1649e2f04181SAndrew T. Barker @ref Utility 1650e2f04181SAndrew T. Barker **/ 1651*d1d35e2fSjeremylt int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, 1652*d1d35e2fSjeremylt CeedInt *num_entries) { 1653e2f04181SAndrew T. Barker int ierr; 1654e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1655*d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_comp; 1656e2f04181SAndrew T. Barker 1657e2f04181SAndrew T. Barker if (op->composite) 1658e2f04181SAndrew T. Barker // LCOV_EXCL_START 1659e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1660e2f04181SAndrew T. Barker "Composite operator not supported"); 1661e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1662e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1663*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChk(ierr); 1664*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); CeedChk(ierr); 1665*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); CeedChk(ierr); 1666*d1d35e2fSjeremylt *num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1667e2f04181SAndrew T. Barker 1668e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1669e2f04181SAndrew T. Barker } 1670e2f04181SAndrew T. Barker 1671e2f04181SAndrew T. Barker /** 1672e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1673e2f04181SAndrew T. Barker 1674e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1675e2f04181SAndrew T. Barker 1676*d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1677e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1678e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1679e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1680e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1681e2f04181SAndrew T. Barker ordering. 1682e2f04181SAndrew T. Barker 1683e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1684e2f04181SAndrew T. Barker 1685e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1686*d1d35e2fSjeremylt @param[out] num_entries Number of entries in coordinate nonzero pattern. 1687e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1688e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1689e2f04181SAndrew T. Barker 1690e2f04181SAndrew T. Barker @ref User 1691e2f04181SAndrew T. Barker **/ 1692e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1693*d1d35e2fSjeremylt CeedInt *num_entries, CeedInt **rows, CeedInt **cols) { 1694e2f04181SAndrew T. Barker int ierr; 1695*d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1696*d1d35e2fSjeremylt CeedOperator *sub_operators; 1697*d1d35e2fSjeremylt bool is_composite; 1698e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1699e2f04181SAndrew T. Barker 1700e2f04181SAndrew T. Barker // Use backend version, if available 1701e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1702*d1d35e2fSjeremylt return op->LinearAssembleSymbolic(op, num_entries, rows, cols); 1703e2f04181SAndrew T. Barker } else { 1704e2f04181SAndrew T. Barker // Check for valid fallback resource 1705*d1d35e2fSjeremylt const char *resource, *fallback_resource; 1706e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1707*d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1708*d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1709e2f04181SAndrew T. Barker // Fallback to reference Ceed 1710*d1d35e2fSjeremylt if (!op->op_fallback) { 1711e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1712e2f04181SAndrew T. Barker } 1713e2f04181SAndrew T. Barker // Assemble 1714*d1d35e2fSjeremylt return CeedOperatorLinearAssembleSymbolic(op->op_fallback, num_entries, rows, 1715*d1d35e2fSjeremylt cols); 1716e2f04181SAndrew T. Barker } 1717e2f04181SAndrew T. Barker } 1718e2f04181SAndrew T. Barker 1719e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1720e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1721e2f04181SAndrew T. Barker 1722e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1723*d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1724*d1d35e2fSjeremylt *num_entries = 0; 1725*d1d35e2fSjeremylt if (is_composite) { 1726*d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1727*d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1728*d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1729*d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1730e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1731*d1d35e2fSjeremylt *num_entries += single_entries; 1732e2f04181SAndrew T. Barker } 1733e2f04181SAndrew T. Barker } else { 1734e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1735e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1736*d1d35e2fSjeremylt *num_entries += single_entries; 1737e2f04181SAndrew T. Barker } 1738*d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, rows); CeedChk(ierr); 1739*d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, cols); CeedChk(ierr); 1740e2f04181SAndrew T. Barker 1741e2f04181SAndrew T. Barker // assemble nonzero locations 1742e2f04181SAndrew T. Barker CeedInt offset = 0; 1743*d1d35e2fSjeremylt if (is_composite) { 1744*d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1745*d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1746*d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1747*d1d35e2fSjeremylt ierr = CeedSingleOperatorAssembleSymbolic(sub_operators[k], offset, *rows, 1748e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1749*d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1750*d1d35e2fSjeremylt &single_entries); 1751e2f04181SAndrew T. Barker CeedChk(ierr); 1752e2f04181SAndrew T. Barker offset += single_entries; 1753e2f04181SAndrew T. Barker } 1754e2f04181SAndrew T. Barker } else { 1755e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1756e2f04181SAndrew T. Barker CeedChk(ierr); 1757e2f04181SAndrew T. Barker } 1758e2f04181SAndrew T. Barker 1759e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1760e2f04181SAndrew T. Barker } 1761e2f04181SAndrew T. Barker 1762e2f04181SAndrew T. Barker /** 1763e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1764e2f04181SAndrew T. Barker 1765e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1766e2f04181SAndrew T. Barker 1767*d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1768e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1769e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1770e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1771e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1772e2f04181SAndrew T. Barker 1773e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1774e2f04181SAndrew T. Barker 1775e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1776e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1777e2f04181SAndrew T. Barker 1778e2f04181SAndrew T. Barker @ref User 1779e2f04181SAndrew T. Barker **/ 1780e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1781e2f04181SAndrew T. Barker int ierr; 1782*d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1783*d1d35e2fSjeremylt CeedOperator *sub_operators; 1784e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1785e2f04181SAndrew T. Barker 1786e2f04181SAndrew T. Barker // Use backend version, if available 1787e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1788e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1789e2f04181SAndrew T. Barker } else { 1790e2f04181SAndrew T. Barker // Check for valid fallback resource 1791*d1d35e2fSjeremylt const char *resource, *fallback_resource; 1792e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1793*d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1794*d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1795e2f04181SAndrew T. Barker // Fallback to reference Ceed 1796*d1d35e2fSjeremylt if (!op->op_fallback) { 1797e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1798e2f04181SAndrew T. Barker } 1799e2f04181SAndrew T. Barker // Assemble 1800*d1d35e2fSjeremylt return CeedOperatorLinearAssemble(op->op_fallback, values); 1801e2f04181SAndrew T. Barker } 1802e2f04181SAndrew T. Barker } 1803e2f04181SAndrew T. Barker 1804e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1805e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1806e2f04181SAndrew T. Barker 1807*d1d35e2fSjeremylt bool is_composite; 1808*d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1809e2f04181SAndrew T. Barker 1810e2f04181SAndrew T. Barker CeedInt offset = 0; 1811*d1d35e2fSjeremylt if (is_composite) { 1812*d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1813*d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1814*d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1815*d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemble(sub_operators[k], offset, values); 1816e2f04181SAndrew T. Barker CeedChk(ierr); 1817*d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1818*d1d35e2fSjeremylt &single_entries); 1819e2f04181SAndrew T. Barker CeedChk(ierr); 1820e2f04181SAndrew T. Barker offset += single_entries; 1821e2f04181SAndrew T. Barker } 1822e2f04181SAndrew T. Barker } else { 1823e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1824e2f04181SAndrew T. Barker } 1825e2f04181SAndrew T. Barker 1826e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1827d965c7a7SJeremy L Thompson } 1828d965c7a7SJeremy L Thompson 1829d965c7a7SJeremy L Thompson /** 1830d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1831d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1832d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1833d99fa3c5SJeremy L Thompson 1834*d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1835*d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1836*d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1837*d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1838*d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1839*d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1840*d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1841d99fa3c5SJeremy L Thompson 1842d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1843d99fa3c5SJeremy L Thompson 1844d99fa3c5SJeremy L Thompson @ref User 1845d99fa3c5SJeremy L Thompson **/ 1846*d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, 1847*d1d35e2fSjeremylt CeedVector p_mult_fine, 1848*d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1849*d1d35e2fSjeremylt CeedOperator *op_coarse, CeedOperator *op_prolong, 1850*d1d35e2fSjeremylt CeedOperator *op_restrict) { 1851d99fa3c5SJeremy L Thompson int ierr; 1852d99fa3c5SJeremy L Thompson Ceed ceed; 1853*d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1854d99fa3c5SJeremy L Thompson 1855d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1856*d1d35e2fSjeremylt CeedBasis basis_fine; 1857*d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1858*d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1859*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1860*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1861*d1d35e2fSjeremylt if (Q_f != Q_c) 1862d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1863e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1864e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1865d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1866d99fa3c5SJeremy L Thompson 1867d99fa3c5SJeremy L Thompson // Coarse to fine basis 1868*d1d35e2fSjeremylt CeedInt P_f, P_c, Q = Q_f; 1869*d1d35e2fSjeremylt bool is_tensor_f, is_tensor_c; 1870*d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_fine, &is_tensor_f); CeedChk(ierr); 1871*d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_coarse, &is_tensor_c); CeedChk(ierr); 1872*d1d35e2fSjeremylt CeedScalar *interp_c, *interp_f, *interp_c_to_f, *tau; 1873*d1d35e2fSjeremylt if (is_tensor_f && is_tensor_c) { 1874*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_f); CeedChk(ierr); 1875*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_coarse, &P_c); CeedChk(ierr); 1876*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis_coarse, &Q); CeedChk(ierr); 1877*d1d35e2fSjeremylt } else if (!is_tensor_f && !is_tensor_c) { 1878*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &P_f); CeedChk(ierr); 1879*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_coarse, &P_c); CeedChk(ierr); 1880d99fa3c5SJeremy L Thompson } else { 1881d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1882e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1883e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1884d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1885d99fa3c5SJeremy L Thompson } 1886d99fa3c5SJeremy L Thompson 1887*d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_f, &interp_f); CeedChk(ierr); 1888*d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_c, &interp_c); CeedChk(ierr); 1889*d1d35e2fSjeremylt ierr = CeedCalloc(P_c*P_f, &interp_c_to_f); CeedChk(ierr); 1890d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1891*d1d35e2fSjeremylt if (is_tensor_f) { 1892*d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp_1d, Q*P_f*sizeof basis_fine->interp_1d[0]); 1893*d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp_1d, 1894*d1d35e2fSjeremylt Q*P_c*sizeof basis_coarse->interp_1d[0]); 1895d99fa3c5SJeremy L Thompson } else { 1896*d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp, Q*P_f*sizeof basis_fine->interp[0]); 1897*d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp, Q*P_c*sizeof basis_coarse->interp[0]); 1898d99fa3c5SJeremy L Thompson } 1899d99fa3c5SJeremy L Thompson 1900*d1d35e2fSjeremylt // -- QR Factorization, interp_f = Q R 1901*d1d35e2fSjeremylt ierr = CeedQRFactorization(ceed, interp_f, tau, Q, P_f); CeedChk(ierr); 1902d99fa3c5SJeremy L Thompson 1903*d1d35e2fSjeremylt // -- Apply Qtranspose, interp_c = Qtranspose interp_c 1904*d1d35e2fSjeremylt ierr = CeedHouseholderApplyQ(interp_c, interp_f, tau, CEED_TRANSPOSE, 1905*d1d35e2fSjeremylt Q, P_c, P_f, P_c, 1); CeedChk(ierr); 1906d99fa3c5SJeremy L Thompson 1907*d1d35e2fSjeremylt // -- Apply Rinv, interp_c_to_f = Rinv interp_c 1908*d1d35e2fSjeremylt for (CeedInt j=0; j<P_c; j++) { // Column j 1909*d1d35e2fSjeremylt interp_c_to_f[j+P_c*(P_f-1)] = interp_c[j+P_c*(P_f-1)]/interp_f[P_f*P_f-1]; 1910*d1d35e2fSjeremylt for (CeedInt i=P_f-2; i>=0; i--) { // Row i 1911*d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] = interp_c[j+P_c*i]; 1912*d1d35e2fSjeremylt for (CeedInt k=i+1; k<P_f; k++) 1913*d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] -= interp_f[k+P_f*i]*interp_c_to_f[j+P_c*k]; 1914*d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] /= interp_f[i+P_f*i]; 1915d99fa3c5SJeremy L Thompson } 1916d99fa3c5SJeremy L Thompson } 1917d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1918*d1d35e2fSjeremylt ierr = CeedFree(&interp_c); CeedChk(ierr); 1919*d1d35e2fSjeremylt ierr = CeedFree(&interp_f); CeedChk(ierr); 1920d99fa3c5SJeremy L Thompson 1921*d1d35e2fSjeremylt // Complete with interp_c_to_f versions of code 1922*d1d35e2fSjeremylt if (is_tensor_f) { 1923*d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateTensorH1(op_fine, p_mult_fine, 1924*d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1925d99fa3c5SJeremy L Thompson CeedChk(ierr); 1926d99fa3c5SJeremy L Thompson } else { 1927*d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateH1(op_fine, p_mult_fine, 1928*d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1929d99fa3c5SJeremy L Thompson CeedChk(ierr); 1930d99fa3c5SJeremy L Thompson } 1931d99fa3c5SJeremy L Thompson 1932d99fa3c5SJeremy L Thompson // Cleanup 1933*d1d35e2fSjeremylt ierr = CeedFree(&interp_c_to_f); CeedChk(ierr); 1934e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1935d99fa3c5SJeremy L Thompson } 1936d99fa3c5SJeremy L Thompson 1937d99fa3c5SJeremy L Thompson /** 1938d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1939d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1940d99fa3c5SJeremy L Thompson 1941*d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1942*d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1943*d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1944*d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1945*d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 1946*d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1947*d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1948*d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1949d99fa3c5SJeremy L Thompson 1950d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1951d99fa3c5SJeremy L Thompson 1952d99fa3c5SJeremy L Thompson @ref User 1953d99fa3c5SJeremy L Thompson **/ 1954*d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, 1955*d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1956*d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, 1957*d1d35e2fSjeremylt CeedOperator *op_prolong, CeedOperator *op_restrict) { 1958d99fa3c5SJeremy L Thompson int ierr; 1959d99fa3c5SJeremy L Thompson Ceed ceed; 1960*d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1961d99fa3c5SJeremy L Thompson 1962d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1963*d1d35e2fSjeremylt CeedBasis basis_fine; 1964*d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1965*d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1966*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1967*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1968*d1d35e2fSjeremylt if (Q_f != Q_c) 1969d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1970e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1971e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1972d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1973d99fa3c5SJeremy L Thompson 1974d99fa3c5SJeremy L Thompson // Coarse to fine basis 1975*d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c; 1976*d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 1977*d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 1978*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_1d_f); CeedChk(ierr); 1979*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 1980d99fa3c5SJeremy L Thompson CeedChk(ierr); 1981*d1d35e2fSjeremylt P_1d_c = dim == 1 ? num_nodes_c : 1982*d1d35e2fSjeremylt dim == 2 ? sqrt(num_nodes_c) : 1983*d1d35e2fSjeremylt cbrt(num_nodes_c); 1984*d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 1985*d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_ref); CeedChk(ierr); 1986*d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_weight); CeedChk(ierr); 1987*d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f*P_1d_c*dim, &grad); CeedChk(ierr); 1988*d1d35e2fSjeremylt CeedBasis basis_c_to_f; 1989*d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, 1990*d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 1991d99fa3c5SJeremy L Thompson CeedChk(ierr); 1992*d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 1993*d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 1994d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1995d99fa3c5SJeremy L Thompson 1996d99fa3c5SJeremy L Thompson // Core code 1997*d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 1998*d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 1999*d1d35e2fSjeremylt op_prolong, op_restrict); 2000d99fa3c5SJeremy L Thompson CeedChk(ierr); 2001e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2002d99fa3c5SJeremy L Thompson } 2003d99fa3c5SJeremy L Thompson 2004d99fa3c5SJeremy L Thompson /** 2005d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 2006d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 2007d99fa3c5SJeremy L Thompson 2008*d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 2009*d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 2010*d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 2011*d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2012*d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2013*d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2014*d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2015*d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2016d99fa3c5SJeremy L Thompson 2017d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2018d99fa3c5SJeremy L Thompson 2019d99fa3c5SJeremy L Thompson @ref User 2020d99fa3c5SJeremy L Thompson **/ 2021*d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, 2022*d1d35e2fSjeremylt CeedVector p_mult_fine, 2023*d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, 2024*d1d35e2fSjeremylt CeedBasis basis_coarse, 2025*d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, 2026*d1d35e2fSjeremylt CeedOperator *op_coarse, 2027*d1d35e2fSjeremylt CeedOperator *op_prolong, 2028*d1d35e2fSjeremylt CeedOperator *op_restrict) { 2029d99fa3c5SJeremy L Thompson int ierr; 2030d99fa3c5SJeremy L Thompson Ceed ceed; 2031*d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2032d99fa3c5SJeremy L Thompson 2033d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2034*d1d35e2fSjeremylt CeedBasis basis_fine; 2035*d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2036*d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2037*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2038*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2039*d1d35e2fSjeremylt if (Q_f != Q_c) 2040d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2041e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2042e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2043d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2044d99fa3c5SJeremy L Thompson 2045d99fa3c5SJeremy L Thompson // Coarse to fine basis 2046d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2047*d1d35e2fSjeremylt ierr = CeedBasisGetTopology(basis_fine, &topo); CeedChk(ierr); 2048*d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, num_nodes_f; 2049*d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2050*d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2051*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &num_nodes_f); CeedChk(ierr); 2052*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2053d99fa3c5SJeremy L Thompson CeedChk(ierr); 2054*d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2055*d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_ref); CeedChk(ierr); 2056*d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_weight); CeedChk(ierr); 2057*d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f*num_nodes_c*dim, &grad); CeedChk(ierr); 2058*d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2059*d1d35e2fSjeremylt ierr = CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, 2060*d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2061d99fa3c5SJeremy L Thompson CeedChk(ierr); 2062*d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2063*d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2064d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2065d99fa3c5SJeremy L Thompson 2066d99fa3c5SJeremy L Thompson // Core code 2067*d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2068*d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2069*d1d35e2fSjeremylt op_prolong, op_restrict); 2070d99fa3c5SJeremy L Thompson CeedChk(ierr); 2071e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2072d99fa3c5SJeremy L Thompson } 2073d99fa3c5SJeremy L Thompson 2074d99fa3c5SJeremy L Thompson /** 20753bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 20763bd813ffSjeremylt CeedOperator 20773bd813ffSjeremylt 20783bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 20793bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 20803bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 20813bd813ffSjeremylt M = V^T V, K = V^T S V. 20823bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 20833bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 20843bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 20853bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 20863bd813ffSjeremylt 20873bd813ffSjeremylt @param op CeedOperator to create element inverses 2088*d1d35e2fSjeremylt @param[out] fdm_inv CeedOperator to apply the action of a FDM based inverse 20893bd813ffSjeremylt for each element 20903bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 20914cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 20923bd813ffSjeremylt 20933bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 20943bd813ffSjeremylt 20957a982d89SJeremy L. Thompson @ref Backend 20963bd813ffSjeremylt **/ 2097*d1d35e2fSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdm_inv, 20983bd813ffSjeremylt CeedRequest *request) { 20993bd813ffSjeremylt int ierr; 2100e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 21013bd813ffSjeremylt 2102713f43c3Sjeremylt // Use backend version, if available 2103713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2104*d1d35e2fSjeremylt ierr = op->CreateFDMElementInverse(op, fdm_inv, request); CeedChk(ierr); 2105713f43c3Sjeremylt } else { 2106713f43c3Sjeremylt // Fallback to reference Ceed 2107*d1d35e2fSjeremylt if (!op->op_fallback) { 2108713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 21093bd813ffSjeremylt } 2110713f43c3Sjeremylt // Assemble 2111*d1d35e2fSjeremylt ierr = op->op_fallback->CreateFDMElementInverse(op->op_fallback, fdm_inv, 21123bd813ffSjeremylt request); CeedChk(ierr); 21133bd813ffSjeremylt } 2114e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21153bd813ffSjeremylt } 21163bd813ffSjeremylt 21177a982d89SJeremy L. Thompson /** 21187a982d89SJeremy L. Thompson @brief View a CeedOperator 21197a982d89SJeremy L. Thompson 21207a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 21217a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 21227a982d89SJeremy L. Thompson 21237a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 21247a982d89SJeremy L. Thompson 21257a982d89SJeremy L. Thompson @ref User 21267a982d89SJeremy L. Thompson **/ 21277a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 21287a982d89SJeremy L. Thompson int ierr; 21297a982d89SJeremy L. Thompson 21307a982d89SJeremy L. Thompson if (op->composite) { 21317a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21327a982d89SJeremy L. Thompson 2133*d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 21347a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 2135*d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 21367a982d89SJeremy L. Thompson CeedChk(ierr); 21377a982d89SJeremy L. Thompson } 21387a982d89SJeremy L. Thompson } else { 21397a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21407a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21417a982d89SJeremy L. Thompson } 2142e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21437a982d89SJeremy L. Thompson } 21443bd813ffSjeremylt 21453bd813ffSjeremylt /** 21463bd813ffSjeremylt @brief Apply CeedOperator to a vector 2147d7b241e6Sjeremylt 2148d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2149d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2150d7b241e6Sjeremylt CeedOperatorSetField(). 2151d7b241e6Sjeremylt 2152d7b241e6Sjeremylt @param op CeedOperator to apply 21534cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 215434138859Sjeremylt there are no active inputs 2155b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21564cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 215734138859Sjeremylt active outputs 2158d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21594cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2160b11c1e72Sjeremylt 2161b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2162dfdf5a53Sjeremylt 21637a982d89SJeremy L. Thompson @ref User 2164b11c1e72Sjeremylt **/ 2165692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2166692c2638Sjeremylt CeedRequest *request) { 2167d7b241e6Sjeremylt int ierr; 2168e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2169d7b241e6Sjeremylt 2170*d1d35e2fSjeremylt if (op->num_elem) { 2171250756a7Sjeremylt // Standard Operator 2172cae8b89aSjeremylt if (op->Apply) { 2173250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2174cae8b89aSjeremylt } else { 2175cae8b89aSjeremylt // Zero all output vectors 2176250756a7Sjeremylt CeedQFunction qf = op->qf; 2177*d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 2178*d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 2179cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2180cae8b89aSjeremylt vec = out; 2181cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2182cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2183cae8b89aSjeremylt } 2184cae8b89aSjeremylt } 2185250756a7Sjeremylt // Apply 2186250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2187250756a7Sjeremylt } 2188250756a7Sjeremylt } else if (op->composite) { 2189250756a7Sjeremylt // Composite Operator 2190250756a7Sjeremylt if (op->ApplyComposite) { 2191250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2192250756a7Sjeremylt } else { 2193*d1d35e2fSjeremylt CeedInt num_suboperators; 2194*d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2195*d1d35e2fSjeremylt CeedOperator *sub_operators; 2196*d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2197250756a7Sjeremylt 2198250756a7Sjeremylt // Zero all output vectors 2199250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2200cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2201cae8b89aSjeremylt } 2202*d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2203*d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 2204*d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 2205250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2206250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2207250756a7Sjeremylt } 2208250756a7Sjeremylt } 2209250756a7Sjeremylt } 2210250756a7Sjeremylt // Apply 2211*d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 2212*d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 2213cae8b89aSjeremylt CeedChk(ierr); 2214cae8b89aSjeremylt } 2215cae8b89aSjeremylt } 2216250756a7Sjeremylt } 2217e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2218cae8b89aSjeremylt } 2219cae8b89aSjeremylt 2220cae8b89aSjeremylt /** 2221cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2222cae8b89aSjeremylt 2223cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2224cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2225cae8b89aSjeremylt CeedOperatorSetField(). 2226cae8b89aSjeremylt 2227cae8b89aSjeremylt @param op CeedOperator to apply 2228cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2229cae8b89aSjeremylt active inputs 2230cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2231cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2232cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22334cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2234cae8b89aSjeremylt 2235cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2236cae8b89aSjeremylt 22377a982d89SJeremy L. Thompson @ref User 2238cae8b89aSjeremylt **/ 2239cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2240cae8b89aSjeremylt CeedRequest *request) { 2241cae8b89aSjeremylt int ierr; 2242e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2243cae8b89aSjeremylt 2244*d1d35e2fSjeremylt if (op->num_elem) { 2245250756a7Sjeremylt // Standard Operator 2246250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2247250756a7Sjeremylt } else if (op->composite) { 2248250756a7Sjeremylt // Composite Operator 2249250756a7Sjeremylt if (op->ApplyAddComposite) { 2250250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2251cae8b89aSjeremylt } else { 2252*d1d35e2fSjeremylt CeedInt num_suboperators; 2253*d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2254*d1d35e2fSjeremylt CeedOperator *sub_operators; 2255*d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2256250756a7Sjeremylt 2257*d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2258*d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 2259cae8b89aSjeremylt CeedChk(ierr); 22601d7d2407SJeremy L Thompson } 2261250756a7Sjeremylt } 2262250756a7Sjeremylt } 2263e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2264d7b241e6Sjeremylt } 2265d7b241e6Sjeremylt 2266d7b241e6Sjeremylt /** 2267b11c1e72Sjeremylt @brief Destroy a CeedOperator 2268d7b241e6Sjeremylt 2269d7b241e6Sjeremylt @param op CeedOperator to destroy 2270b11c1e72Sjeremylt 2271b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2272dfdf5a53Sjeremylt 22737a982d89SJeremy L. Thompson @ref User 2274b11c1e72Sjeremylt **/ 2275d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2276d7b241e6Sjeremylt int ierr; 2277d7b241e6Sjeremylt 2278*d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 2279d7b241e6Sjeremylt if ((*op)->Destroy) { 2280d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2281d7b241e6Sjeremylt } 2282fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2283fe2413ffSjeremylt // Free fields 2284*d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2285*d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 2286*d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 2287*d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 228871352a93Sjeremylt CeedChk(ierr); 228915910d16Sjeremylt } 2290*d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2291*d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 229271352a93Sjeremylt } 2293*d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 2294*d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 2295*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 229671352a93Sjeremylt } 2297*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 2298*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 2299fe2413ffSjeremylt } 2300*d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2301*d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 2302*d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 230371352a93Sjeremylt CeedChk(ierr); 2304*d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2305*d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 230671352a93Sjeremylt } 2307*d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 2308*d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 2309*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 231071352a93Sjeremylt } 2311*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 2312*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 2313fe2413ffSjeremylt } 2314*d1d35e2fSjeremylt // Destroy sub_operators 2315*d1d35e2fSjeremylt for (int i=0; i<(*op)->num_suboperators; i++) 2316*d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 2317*d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 231852d6035fSJeremy L Thompson } 2319e15f9bd0SJeremy L Thompson if ((*op)->qf) 2320e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2321*d1d35e2fSjeremylt (*op)->qf->operators_set--; 2322e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2323d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2324e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2325e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2326*d1d35e2fSjeremylt (*op)->dqf->operators_set--; 2327e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2328d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2329e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2330e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2331*d1d35e2fSjeremylt (*op)->dqfT->operators_set--; 2332e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2333d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2334fe2413ffSjeremylt 23355107b09fSJeremy L Thompson // Destroy fallback 2336*d1d35e2fSjeremylt if ((*op)->op_fallback) { 2337*d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 2338*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 2339*d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 2340*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 23415107b09fSJeremy L Thompson } 23425107b09fSJeremy L Thompson 2343*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 2344*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 2345*d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 2346d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2347e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2348d7b241e6Sjeremylt } 2349d7b241e6Sjeremylt 2350d7b241e6Sjeremylt /// @} 2351