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 48d1d35e2fSjeremylt const char *resource, *fallback_resource; 497a982d89SJeremy L. Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 50d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 517a982d89SJeremy L. Thompson CeedChk(ierr); 52d1d35e2fSjeremylt 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" 56d1d35e2fSjeremylt "fallback to resource %s", resource, fallback_resource); 577a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 587a982d89SJeremy L. Thompson 597a982d89SJeremy L. Thompson // Fallback Ceed 60d1d35e2fSjeremylt Ceed ceed_ref; 61d1d35e2fSjeremylt if (!op->ceed->op_fallback_ceed) { 62d1d35e2fSjeremylt ierr = CeedInit(fallback_resource, &ceed_ref); CeedChk(ierr); 63d1d35e2fSjeremylt ceed_ref->op_fallback_parent = op->ceed; 64d1d35e2fSjeremylt ceed_ref->Error = op->ceed->Error; 65d1d35e2fSjeremylt op->ceed->op_fallback_ceed = ceed_ref; 667a982d89SJeremy L. Thompson } 67d1d35e2fSjeremylt ceed_ref = op->ceed->op_fallback_ceed; 687a982d89SJeremy L. Thompson 697a982d89SJeremy L. Thompson // Clone Op 70d1d35e2fSjeremylt CeedOperator op_ref; 71d1d35e2fSjeremylt ierr = CeedCalloc(1, &op_ref); CeedChk(ierr); 72d1d35e2fSjeremylt memcpy(op_ref, op, sizeof(*op_ref)); 73d1d35e2fSjeremylt op_ref->data = NULL; 74d1d35e2fSjeremylt op_ref->interface_setup = false; 75d1d35e2fSjeremylt op_ref->backend_setup = false; 76d1d35e2fSjeremylt op_ref->ceed = ceed_ref; 77d1d35e2fSjeremylt ierr = ceed_ref->OperatorCreate(op_ref); CeedChk(ierr); 78d1d35e2fSjeremylt op->op_fallback = op_ref; 797a982d89SJeremy L. Thompson 807a982d89SJeremy L. Thompson // Clone QF 81d1d35e2fSjeremylt CeedQFunction qf_ref; 82d1d35e2fSjeremylt ierr = CeedCalloc(1, &qf_ref); CeedChk(ierr); 83d1d35e2fSjeremylt memcpy(qf_ref, (op->qf), sizeof(*qf_ref)); 84d1d35e2fSjeremylt qf_ref->data = NULL; 85d1d35e2fSjeremylt qf_ref->ceed = ceed_ref; 86d1d35e2fSjeremylt ierr = ceed_ref->QFunctionCreate(qf_ref); CeedChk(ierr); 87d1d35e2fSjeremylt op_ref->qf = qf_ref; 88d1d35e2fSjeremylt 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 96d1d35e2fSjeremylt @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 **/ 104d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field, 105e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 106e15f9bd0SJeremy L Thompson int ierr; 107d1d35e2fSjeremylt CeedEvalMode eval_mode = qf_field->eval_mode; 108d1d35e2fSjeremylt 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) { 111d1d35e2fSjeremylt 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 } 118d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp); 119e1e9e29dSJed Brown } 120d1d35e2fSjeremylt 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) { 129d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) 130e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 131d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 132d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 133d1d35e2fSjeremylt qf_field->field_name); 134e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 135d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 136d1d35e2fSjeremylt 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, 139d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 140d1d35e2fSjeremylt "has %d components, but Basis has %d components", 141d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 142d1d35e2fSjeremylt restr_num_comp, 143d1d35e2fSjeremylt num_comp); 144e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 145e15f9bd0SJeremy L Thompson } 146e15f9bd0SJeremy L Thompson } 147e15f9bd0SJeremy L Thompson // Field size 148d1d35e2fSjeremylt switch(eval_mode) { 149e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 150d1d35e2fSjeremylt 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", 154d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 155d1d35e2fSjeremylt restr_num_comp); 156e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 157e15f9bd0SJeremy L Thompson break; 158e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 159d1d35e2fSjeremylt 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", 163d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 164d1d35e2fSjeremylt num_comp); 165e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 166e15f9bd0SJeremy L Thompson break; 167e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 168d1d35e2fSjeremylt if (size != num_comp * dim) 169e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 170e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 171d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 172d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 173d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 174d1d35e2fSjeremylt num_comp); 175e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 176e15f9bd0SJeremy L Thompson break; 177e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 178d1d35e2fSjeremylt // 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 204d1d35e2fSjeremylt 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) { 209d1d35e2fSjeremylt if (!op->num_suboperators) 2107a982d89SJeremy L. Thompson // LCOV_EXCL_START 211d1d35e2fSjeremylt return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 2127a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2137a982d89SJeremy L. Thompson } else { 214d1d35e2fSjeremylt 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 218d1d35e2fSjeremylt 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 222d1d35e2fSjeremylt 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 227d1d35e2fSjeremylt 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 235d1d35e2fSjeremylt op->interface_setup = true; 236e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 237e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 238d1d35e2fSjeremylt 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 242d1d35e2fSjeremylt 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 246d1d35e2fSjeremylt 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 255d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 256d1d35e2fSjeremylt @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 258d1d35e2fSjeremylt @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, 266d1d35e2fSjeremylt CeedQFunctionField qf_field, 267d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 2687a982d89SJeremy L. Thompson FILE *stream) { 2697a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 270d1d35e2fSjeremylt 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", 274d1d35e2fSjeremylt 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 306d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 307d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 308d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 309d1d35e2fSjeremylt 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 313d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 314d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 315d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 316d1d35e2fSjeremylt 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 326d1d35e2fSjeremylt @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, 333d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 334d1d35e2fSjeremylt *active_rstr = NULL; 335d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 336d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 337d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 338e2f04181SAndrew T. Barker break; 339e2f04181SAndrew T. Barker } 340e2f04181SAndrew T. Barker 341d1d35e2fSjeremylt 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 357d1d35e2fSjeremylt @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, 364d1d35e2fSjeremylt CeedBasis *active_basis) { 365d1d35e2fSjeremylt *active_basis = NULL; 366d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 367d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 368d1d35e2fSjeremylt *active_basis = op->input_fields[i]->basis; 369d99fa3c5SJeremy L Thompson break; 370d99fa3c5SJeremy L Thompson } 371d99fa3c5SJeremy L Thompson 372d1d35e2fSjeremylt 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 388d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 389d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 390d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 391d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 392d1d35e2fSjeremylt @param[in] basis_c_to_f Basis for coarse to fine interpolation 393d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 394d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 395d1d35e2fSjeremylt @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 **/ 401d1d35e2fSjeremylt static int CeedOperatorMultigridLevel_Core(CeedOperator op_fine, 402d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 403d1d35e2fSjeremylt CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, 404d1d35e2fSjeremylt CeedOperator *op_restrict) { 405d99fa3c5SJeremy L Thompson int ierr; 406d99fa3c5SJeremy L Thompson Ceed ceed; 407d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 408d99fa3c5SJeremy L Thompson 409d99fa3c5SJeremy L Thompson // Check for composite operator 410d1d35e2fSjeremylt bool is_composite; 411d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op_fine, &is_composite); CeedChk(ierr); 412d1d35e2fSjeremylt 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 419d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, op_fine->qf, op_fine->dqf, op_fine->dqfT, 420d1d35e2fSjeremylt op_coarse); CeedChk(ierr); 421d1d35e2fSjeremylt CeedElemRestriction rstr_fine = NULL; 422d99fa3c5SJeremy L Thompson // -- Clone input fields 423d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_input_fields; i++) { 424d1d35e2fSjeremylt if (op_fine->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 425d1d35e2fSjeremylt rstr_fine = op_fine->input_fields[i]->elem_restr; 426d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 427d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 428d99fa3c5SJeremy L Thompson CeedChk(ierr); 429d99fa3c5SJeremy L Thompson } else { 430d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 431d1d35e2fSjeremylt op_fine->input_fields[i]->elem_restr, 432d1d35e2fSjeremylt op_fine->input_fields[i]->basis, 433d1d35e2fSjeremylt op_fine->input_fields[i]->vec); CeedChk(ierr); 434d99fa3c5SJeremy L Thompson } 435d99fa3c5SJeremy L Thompson } 436d99fa3c5SJeremy L Thompson // -- Clone output fields 437d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_output_fields; i++) { 438d1d35e2fSjeremylt if (op_fine->output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 439d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 440d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 441d99fa3c5SJeremy L Thompson CeedChk(ierr); 442d99fa3c5SJeremy L Thompson } else { 443d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 444d1d35e2fSjeremylt op_fine->output_fields[i]->elem_restr, 445d1d35e2fSjeremylt op_fine->output_fields[i]->basis, 446d1d35e2fSjeremylt op_fine->output_fields[i]->vec); CeedChk(ierr); 447d99fa3c5SJeremy L Thompson } 448d99fa3c5SJeremy L Thompson } 449d99fa3c5SJeremy L Thompson 450d99fa3c5SJeremy L Thompson // Multiplicity vector 451d1d35e2fSjeremylt CeedVector mult_vec, mult_e_vec; 452d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(rstr_fine, &mult_vec, &mult_e_vec); 453d99fa3c5SJeremy L Thompson CeedChk(ierr); 454d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_e_vec, 0.0); CeedChk(ierr); 455d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_NOTRANSPOSE, p_mult_fine, 456d1d35e2fSjeremylt mult_e_vec, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 457d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_vec, 0.0); CeedChk(ierr); 458d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_TRANSPOSE, mult_e_vec, mult_vec, 459d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 460d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_e_vec); CeedChk(ierr); 461d1d35e2fSjeremylt ierr = CeedVectorReciprocal(mult_vec); CeedChk(ierr); 462d99fa3c5SJeremy L Thompson 463d99fa3c5SJeremy L Thompson // Restriction 464d1d35e2fSjeremylt CeedInt num_comp; 465d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_coarse, &num_comp); CeedChk(ierr); 466d1d35e2fSjeremylt CeedQFunction qf_restrict; 467d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_restrict); 468d99fa3c5SJeremy L Thompson CeedChk(ierr); 469d1d35e2fSjeremylt CeedInt *num_comp_r_data; 470d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_r_data); CeedChk(ierr); 471d1d35e2fSjeremylt num_comp_r_data[0] = num_comp; 472d1d35e2fSjeremylt CeedQFunctionContext ctx_r; 473d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_r); CeedChk(ierr); 474d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, 475d1d35e2fSjeremylt sizeof(*num_comp_r_data), num_comp_r_data); 476777ff853SJeremy L Thompson CeedChk(ierr); 477d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_restrict, ctx_r); CeedChk(ierr); 478d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_r); CeedChk(ierr); 479d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "input", num_comp, CEED_EVAL_NONE); 480d99fa3c5SJeremy L Thompson CeedChk(ierr); 481d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "scale", num_comp, CEED_EVAL_NONE); 482d99fa3c5SJeremy L Thompson CeedChk(ierr); 483d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_restrict, "output", num_comp, 484d1d35e2fSjeremylt CEED_EVAL_INTERP); CeedChk(ierr); 485d99fa3c5SJeremy L Thompson 486d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE, 487d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_restrict); 488d99fa3c5SJeremy L Thompson CeedChk(ierr); 489d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "input", rstr_fine, 490d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 491d99fa3c5SJeremy L Thompson CeedChk(ierr); 492d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "scale", rstr_fine, 493d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 494d99fa3c5SJeremy L Thompson CeedChk(ierr); 495d1d35e2fSjeremylt 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 499d1d35e2fSjeremylt CeedQFunction qf_prolong; 500d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_prolong); 501d99fa3c5SJeremy L Thompson CeedChk(ierr); 502d1d35e2fSjeremylt CeedInt *num_comp_p_data; 503d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_p_data); CeedChk(ierr); 504d1d35e2fSjeremylt num_comp_p_data[0] = num_comp; 505d1d35e2fSjeremylt CeedQFunctionContext ctx_p; 506d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_p); CeedChk(ierr); 507d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_p, CEED_MEM_HOST, CEED_OWN_POINTER, 508d1d35e2fSjeremylt sizeof(*num_comp_p_data), num_comp_p_data); 509777ff853SJeremy L Thompson CeedChk(ierr); 510d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_prolong, ctx_p); CeedChk(ierr); 511d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_p); CeedChk(ierr); 512d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "input", num_comp, CEED_EVAL_INTERP); 513d99fa3c5SJeremy L Thompson CeedChk(ierr); 514d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "scale", num_comp, CEED_EVAL_NONE); 515d99fa3c5SJeremy L Thompson CeedChk(ierr); 516d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_prolong, "output", num_comp, CEED_EVAL_NONE); 517d99fa3c5SJeremy L Thompson CeedChk(ierr); 518d99fa3c5SJeremy L Thompson 519d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_prolong, CEED_QFUNCTION_NONE, 520d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_prolong); 521d99fa3c5SJeremy L Thompson CeedChk(ierr); 522d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "input", rstr_coarse, basis_c_to_f, 523d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 524d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "scale", rstr_fine, 525d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 526d99fa3c5SJeremy L Thompson CeedChk(ierr); 527d1d35e2fSjeremylt 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 532d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_vec); CeedChk(ierr); 533d1d35e2fSjeremylt ierr = CeedBasisDestroy(&basis_c_to_f); CeedChk(ierr); 534d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_restrict); CeedChk(ierr); 535d1d35e2fSjeremylt 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 567d1d35e2fSjeremylt @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 574d1d35e2fSjeremylt 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 581d1d35e2fSjeremylt *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 589d1d35e2fSjeremylt @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 596d1d35e2fSjeremylt 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 603d1d35e2fSjeremylt *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 611d1d35e2fSjeremylt @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 618d1d35e2fSjeremylt 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 625d1d35e2fSjeremylt *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 633d1d35e2fSjeremylt @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 640d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 641d1d35e2fSjeremylt *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 671d1d35e2fSjeremylt @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 678d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 679d1d35e2fSjeremylt *is_composite = op->composite; 680e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 681c04a41a7SJeremy L Thompson } 682c04a41a7SJeremy L Thompson 683c04a41a7SJeremy L Thompson /** 684d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 6857a982d89SJeremy L. Thompson 6867a982d89SJeremy L. Thompson @param op CeedOperator 687d1d35e2fSjeremylt @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 694d1d35e2fSjeremylt 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 700d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 701e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7027a982d89SJeremy L. Thompson } 7037a982d89SJeremy L. Thompson 7047a982d89SJeremy L. Thompson /** 705d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 7067a982d89SJeremy L. Thompson 7077a982d89SJeremy L. Thompson @param op CeedOperator 708d1d35e2fSjeremylt @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 715d1d35e2fSjeremylt 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 721d1d35e2fSjeremylt *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 /** 758*34359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 759*34359f16Sjeremylt 760*34359f16Sjeremylt @param op CeedOperator to increment the reference counter 761*34359f16Sjeremylt 762*34359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 763*34359f16Sjeremylt 764*34359f16Sjeremylt @ref Backend 765*34359f16Sjeremylt **/ 766*34359f16Sjeremylt int CeedOperatorIncrementRefCounter(CeedOperator op) { 767*34359f16Sjeremylt op->ref_count++; 768*34359f16Sjeremylt return CEED_ERROR_SUCCESS; 769*34359f16Sjeremylt } 770*34359f16Sjeremylt 771*34359f16Sjeremylt /** 7727a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7737a982d89SJeremy L. Thompson 7747a982d89SJeremy L. Thompson @param op CeedOperator 7757a982d89SJeremy L. Thompson 7767a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7777a982d89SJeremy L. Thompson 7787a982d89SJeremy L. Thompson @ref Backend 7797a982d89SJeremy L. Thompson **/ 7807a982d89SJeremy L. Thompson 7817a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 782d1d35e2fSjeremylt op->backend_setup = true; 783e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7847a982d89SJeremy L. Thompson } 7857a982d89SJeremy L. Thompson 7867a982d89SJeremy L. Thompson /** 7877a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7887a982d89SJeremy L. Thompson 7897a982d89SJeremy L. Thompson @param op CeedOperator 790d1d35e2fSjeremylt @param[out] input_fields Variable to store input_fields 791d1d35e2fSjeremylt @param[out] output_fields Variable to store output_fields 7927a982d89SJeremy L. Thompson 7937a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7947a982d89SJeremy L. Thompson 7957a982d89SJeremy L. Thompson @ref Backend 7967a982d89SJeremy L. Thompson **/ 7977a982d89SJeremy L. Thompson 798d1d35e2fSjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **input_fields, 799d1d35e2fSjeremylt CeedOperatorField **output_fields) { 8007a982d89SJeremy L. Thompson if (op->composite) 8017a982d89SJeremy L. Thompson // LCOV_EXCL_START 802e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 803e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 8047a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 8057a982d89SJeremy L. Thompson 806d1d35e2fSjeremylt if (input_fields) *input_fields = op->input_fields; 807d1d35e2fSjeremylt if (output_fields) *output_fields = op->output_fields; 808e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8097a982d89SJeremy L. Thompson } 8107a982d89SJeremy L. Thompson 8117a982d89SJeremy L. Thompson /** 8127a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 8137a982d89SJeremy L. Thompson 814d1d35e2fSjeremylt @param op_field CeedOperatorField 8157a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 8167a982d89SJeremy L. Thompson 8177a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8187a982d89SJeremy L. Thompson 8197a982d89SJeremy L. Thompson @ref Backend 8207a982d89SJeremy L. Thompson **/ 8217a982d89SJeremy L. Thompson 822d1d35e2fSjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 8237a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 824d1d35e2fSjeremylt *rstr = op_field->elem_restr; 825e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8267a982d89SJeremy L. Thompson } 8277a982d89SJeremy L. Thompson 8287a982d89SJeremy L. Thompson /** 8297a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8307a982d89SJeremy L. Thompson 831d1d35e2fSjeremylt @param op_field CeedOperatorField 8327a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8337a982d89SJeremy L. Thompson 8347a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8357a982d89SJeremy L. Thompson 8367a982d89SJeremy L. Thompson @ref Backend 8377a982d89SJeremy L. Thompson **/ 8387a982d89SJeremy L. Thompson 839d1d35e2fSjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 840d1d35e2fSjeremylt *basis = op_field->basis; 841e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8427a982d89SJeremy L. Thompson } 8437a982d89SJeremy L. Thompson 8447a982d89SJeremy L. Thompson /** 8457a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8467a982d89SJeremy L. Thompson 847d1d35e2fSjeremylt @param op_field CeedOperatorField 8487a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8497a982d89SJeremy L. Thompson 8507a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8517a982d89SJeremy L. Thompson 8527a982d89SJeremy L. Thompson @ref Backend 8537a982d89SJeremy L. Thompson **/ 8547a982d89SJeremy L. Thompson 855d1d35e2fSjeremylt int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 856d1d35e2fSjeremylt *vec = op_field->vec; 857e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8587a982d89SJeremy L. Thompson } 8597a982d89SJeremy L. Thompson 8607a982d89SJeremy L. Thompson /// @} 8617a982d89SJeremy L. Thompson 8627a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8637a982d89SJeremy L. Thompson /// CeedOperator Public API 8647a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8657a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 866dfdf5a53Sjeremylt /// @{ 867d7b241e6Sjeremylt 868d7b241e6Sjeremylt /** 8690219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8700219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8710219ea01SJeremy L Thompson \ref CeedOperatorSetField. 872d7b241e6Sjeremylt 873b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 874d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 87534138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8764cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 877d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8784cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 879b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 880b11c1e72Sjeremylt CeedOperator will be stored 881b11c1e72Sjeremylt 882b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 883dfdf5a53Sjeremylt 8847a982d89SJeremy L. Thompson @ref User 885d7b241e6Sjeremylt */ 886d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 887d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 888d7b241e6Sjeremylt int ierr; 889d7b241e6Sjeremylt 8905fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8915fe0d4faSjeremylt Ceed delegate; 892aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8935fe0d4faSjeremylt 8945fe0d4faSjeremylt if (!delegate) 895c042f62fSJeremy L Thompson // LCOV_EXCL_START 896e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 897e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 898c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8995fe0d4faSjeremylt 9005fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 901e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9025fe0d4faSjeremylt } 9035fe0d4faSjeremylt 904b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 905b3b7035fSJeremy L Thompson // LCOV_EXCL_START 906e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 907e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 908b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 909d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 910d7b241e6Sjeremylt (*op)->ceed = ceed; 911*34359f16Sjeremylt ierr = CeedIncrementRefCounter(ceed); CeedChk(ierr); 912d1d35e2fSjeremylt (*op)->ref_count = 1; 913d7b241e6Sjeremylt (*op)->qf = qf; 914*34359f16Sjeremylt ierr = CeedQFunctionIncrementRefCounter(qf); CeedChk(ierr); 915442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 916d7b241e6Sjeremylt (*op)->dqf = dqf; 917*34359f16Sjeremylt ierr = CeedQFunctionIncrementRefCounter(dqf); CeedChk(ierr); 918442e7f0bSjeremylt } 919442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 920d7b241e6Sjeremylt (*op)->dqfT = dqfT; 921*34359f16Sjeremylt ierr = CeedQFunctionIncrementRefCounter(dqfT); CeedChk(ierr); 922442e7f0bSjeremylt } 923d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr); 924d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr); 925d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 926e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 927d7b241e6Sjeremylt } 928d7b241e6Sjeremylt 929d7b241e6Sjeremylt /** 93052d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 93152d6035fSJeremy L Thompson 93252d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 93352d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 93452d6035fSJeremy L Thompson Composite CeedOperator will be stored 93552d6035fSJeremy L Thompson 93652d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 93752d6035fSJeremy L Thompson 9387a982d89SJeremy L. Thompson @ref User 93952d6035fSJeremy L Thompson */ 94052d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 94152d6035fSJeremy L Thompson int ierr; 94252d6035fSJeremy L Thompson 94352d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 94452d6035fSJeremy L Thompson Ceed delegate; 945aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 94652d6035fSJeremy L Thompson 947250756a7Sjeremylt if (delegate) { 94852d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 949e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 95052d6035fSJeremy L Thompson } 951250756a7Sjeremylt } 95252d6035fSJeremy L Thompson 95352d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 95452d6035fSJeremy L Thompson (*op)->ceed = ceed; 955*34359f16Sjeremylt ierr = CeedIncrementRefCounter(ceed); CeedChk(ierr); 95652d6035fSJeremy L Thompson (*op)->composite = true; 957d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr); 958250756a7Sjeremylt 959250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 96052d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 961250756a7Sjeremylt } 962e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 96352d6035fSJeremy L Thompson } 96452d6035fSJeremy L Thompson 96552d6035fSJeremy L Thompson /** 966b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 967d7b241e6Sjeremylt 968d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 969d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 970d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 971d7b241e6Sjeremylt 972d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 973d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 974d7b241e6Sjeremylt input and at most one active output. 975d7b241e6Sjeremylt 9768c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 977d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 9788795c945Sjeremylt CeedQFunction) 979b11c1e72Sjeremylt @param r CeedElemRestriction 9804cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 981b11c1e72Sjeremylt if collocated with quadrature points 9824cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9834cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9844cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 985b11c1e72Sjeremylt 986b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 987dfdf5a53Sjeremylt 9887a982d89SJeremy L. Thompson @ref User 989b11c1e72Sjeremylt **/ 990d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 991a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 992d7b241e6Sjeremylt int ierr; 99352d6035fSJeremy L Thompson if (op->composite) 994c042f62fSJeremy L Thompson // LCOV_EXCL_START 995e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 996e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 997c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9988b067b84SJed Brown if (!r) 999c042f62fSJeremy L Thompson // LCOV_EXCL_START 1000e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1001c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 1002d1d35e2fSjeremylt field_name); 1003c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10048b067b84SJed Brown if (!b) 1005c042f62fSJeremy L Thompson // LCOV_EXCL_START 1006e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1007e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 1008d1d35e2fSjeremylt field_name); 1009c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10108b067b84SJed Brown if (!v) 1011c042f62fSJeremy L Thompson // LCOV_EXCL_START 1012e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1013e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 1014d1d35e2fSjeremylt field_name); 1015c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 101652d6035fSJeremy L Thompson 1017d1d35e2fSjeremylt CeedInt num_elem; 1018d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 1019d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 1020d1d35e2fSjeremylt op->num_elem != num_elem) 1021c042f62fSJeremy L Thompson // LCOV_EXCL_START 1022e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10231d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1024d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 1025c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1026d7b241e6Sjeremylt 1027d1d35e2fSjeremylt CeedInt num_qpts; 1028e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1029d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 1030d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 1031c042f62fSJeremy L Thompson // LCOV_EXCL_START 1032e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1033e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 1034d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 1035d1d35e2fSjeremylt op->num_qpts); 1036c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1037d7b241e6Sjeremylt } 1038d1d35e2fSjeremylt CeedQFunctionField qf_field; 1039d1d35e2fSjeremylt CeedOperatorField *op_field; 1040d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 1041d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 1042d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 1043d1d35e2fSjeremylt op_field = &op->input_fields[i]; 1044d7b241e6Sjeremylt goto found; 1045d7b241e6Sjeremylt } 1046d7b241e6Sjeremylt } 1047d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 1048d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 1049d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 1050d1d35e2fSjeremylt op_field = &op->output_fields[i]; 1051d7b241e6Sjeremylt goto found; 1052d7b241e6Sjeremylt } 1053d7b241e6Sjeremylt } 1054c042f62fSJeremy L Thompson // LCOV_EXCL_START 1055e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1056e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1057d1d35e2fSjeremylt field_name); 1058c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1059d7b241e6Sjeremylt found: 1060d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 1061d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 1062e15f9bd0SJeremy L Thompson 1063d1d35e2fSjeremylt (*op_field)->vec = v; 1064e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1065*34359f16Sjeremylt ierr = CeedVectorIncrementRefCounter(v); CeedChk(ierr); 1066e15f9bd0SJeremy L Thompson } 1067e15f9bd0SJeremy L Thompson 1068d1d35e2fSjeremylt (*op_field)->elem_restr = r; 1069*34359f16Sjeremylt ierr = CeedElemRestrictionIncrementRefCounter(r); CeedChk(ierr); 1070e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1071d1d35e2fSjeremylt op->num_elem = num_elem; 1072d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 1073e15f9bd0SJeremy L Thompson } 1074d99fa3c5SJeremy L Thompson 1075d1d35e2fSjeremylt (*op_field)->basis = b; 1076e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1077d1d35e2fSjeremylt op->num_qpts = num_qpts; 1078*34359f16Sjeremylt ierr = CeedBasisIncrementRefCounter(b); CeedChk(ierr); 1079e15f9bd0SJeremy L Thompson } 1080e15f9bd0SJeremy L Thompson 1081d1d35e2fSjeremylt op->num_fields += 1; 1082d1d35e2fSjeremylt size_t len = strlen(field_name); 1083d99fa3c5SJeremy L Thompson char *tmp; 1084d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1085d1d35e2fSjeremylt memcpy(tmp, field_name, len+1); 1086d1d35e2fSjeremylt (*op_field)->field_name = tmp; 1087e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1088d7b241e6Sjeremylt } 1089d7b241e6Sjeremylt 1090d7b241e6Sjeremylt /** 109152d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1092288c0443SJeremy L Thompson 1093d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 1094d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 109552d6035fSJeremy L Thompson 109652d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 109752d6035fSJeremy L Thompson 10987a982d89SJeremy L. Thompson @ref User 109952d6035fSJeremy L Thompson */ 1100d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 1101d1d35e2fSjeremylt CeedOperator sub_op) { 1102*34359f16Sjeremylt int ierr; 1103*34359f16Sjeremylt 1104d1d35e2fSjeremylt if (!composite_op->composite) 1105c042f62fSJeremy L Thompson // LCOV_EXCL_START 1106d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 1107e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1108c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 110952d6035fSJeremy L Thompson 1110d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 1111c042f62fSJeremy L Thompson // LCOV_EXCL_START 1112d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 1113d1d35e2fSjeremylt "Cannot add additional sub_operators"); 1114c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 111552d6035fSJeremy L Thompson 1116d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 1117*34359f16Sjeremylt ierr = CeedOperatorIncrementRefCounter(sub_op); CeedChk(ierr); 1118d1d35e2fSjeremylt composite_op->num_suboperators++; 1119e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 112052d6035fSJeremy L Thompson } 112152d6035fSJeremy L Thompson 112252d6035fSJeremy L Thompson /** 11231d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11241d102b48SJeremy L Thompson 11251d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11261d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11271d102b48SJeremy L Thompson The vector 'assembled' is of shape 11281d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11291d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11301d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11311d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11324cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11331d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11341d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11351d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11361d102b48SJeremy L Thompson 11371d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11381d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11391d102b48SJeremy L Thompson quadrature points 11401d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11411d102b48SJeremy L Thompson CeedQFunction 11421d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11434cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11441d102b48SJeremy L Thompson 11451d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11461d102b48SJeremy L Thompson 11477a982d89SJeremy L. Thompson @ref User 11481d102b48SJeremy L Thompson **/ 114980ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11507f823360Sjeremylt CeedElemRestriction *rstr, 11517f823360Sjeremylt CeedRequest *request) { 11521d102b48SJeremy L Thompson int ierr; 1153e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11541d102b48SJeremy L Thompson 11557172caadSjeremylt // Backend version 115680ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1157e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11585107b09fSJeremy L Thompson } else { 11595107b09fSJeremy L Thompson // Fallback to reference Ceed 1160d1d35e2fSjeremylt if (!op->op_fallback) { 11615107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11625107b09fSJeremy L Thompson } 11635107b09fSJeremy L Thompson // Assemble 1164d1d35e2fSjeremylt return CeedOperatorLinearAssembleQFunction(op->op_fallback, assembled, 1165e2f04181SAndrew T. Barker rstr, request); 11665107b09fSJeremy L Thompson } 11671d102b48SJeremy L Thompson } 11681d102b48SJeremy L Thompson 11691d102b48SJeremy L Thompson /** 1170d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1171b7ec98d8SJeremy L Thompson 11729e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1173b7ec98d8SJeremy L Thompson 1174c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1175c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1176d965c7a7SJeremy L Thompson 1177b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1178b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1179b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11804cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1181b7ec98d8SJeremy L Thompson 1182b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1183b7ec98d8SJeremy L Thompson 11847a982d89SJeremy L. Thompson @ref User 1185b7ec98d8SJeremy L Thompson **/ 11862bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11877f823360Sjeremylt CeedRequest *request) { 1188b7ec98d8SJeremy L Thompson int ierr; 1189e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1190b7ec98d8SJeremy L Thompson 1191b7ec98d8SJeremy L Thompson // Use backend version, if available 119280ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1193e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 11949e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11959e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11969e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11979e9210b8SJeremy L Thompson } else { 11989e9210b8SJeremy L Thompson // Fallback to reference Ceed 1199d1d35e2fSjeremylt if (!op->op_fallback) { 12009e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 12019e9210b8SJeremy L Thompson } 12029e9210b8SJeremy L Thompson // Assemble 1203d1d35e2fSjeremylt return CeedOperatorLinearAssembleDiagonal(op->op_fallback, assembled, 1204e2f04181SAndrew T. Barker request); 12059e9210b8SJeremy L Thompson } 12069e9210b8SJeremy L Thompson } 12079e9210b8SJeremy L Thompson 12089e9210b8SJeremy L Thompson /** 12099e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 12109e9210b8SJeremy L Thompson 12119e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 12129e9210b8SJeremy L Thompson 12139e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12149e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12159e9210b8SJeremy L Thompson 12169e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12179e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 12189e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12199e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 12209e9210b8SJeremy L Thompson 12219e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12229e9210b8SJeremy L Thompson 12239e9210b8SJeremy L Thompson @ref User 12249e9210b8SJeremy L Thompson **/ 12259e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12269e9210b8SJeremy L Thompson CeedRequest *request) { 12279e9210b8SJeremy L Thompson int ierr; 1228e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12299e9210b8SJeremy L Thompson 12309e9210b8SJeremy L Thompson // Use backend version, if available 12319e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1232e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12337172caadSjeremylt } else { 12347172caadSjeremylt // Fallback to reference Ceed 1235d1d35e2fSjeremylt if (!op->op_fallback) { 12367172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1237b7ec98d8SJeremy L Thompson } 12387172caadSjeremylt // Assemble 1239d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddDiagonal(op->op_fallback, assembled, 1240e2f04181SAndrew T. Barker request); 1241b7ec98d8SJeremy L Thompson } 1242b7ec98d8SJeremy L Thompson } 1243b7ec98d8SJeremy L Thompson 1244b7ec98d8SJeremy L Thompson /** 1245d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1246d965c7a7SJeremy L Thompson 12479e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1248d965c7a7SJeremy L Thompson CeedOperator. 1249d965c7a7SJeremy L Thompson 1250c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1251c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1252d965c7a7SJeremy L Thompson 1253d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1254d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1255d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1256d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 1257d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1258d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1259d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1260d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1261d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1262d965c7a7SJeremy L Thompson 1263d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1264d965c7a7SJeremy L Thompson 1265d965c7a7SJeremy L Thompson @ref User 1266d965c7a7SJeremy L Thompson **/ 126780ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12682bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1269d965c7a7SJeremy L Thompson int ierr; 1270e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1271d965c7a7SJeremy L Thompson 1272d965c7a7SJeremy L Thompson // Use backend version, if available 127380ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1274e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12759e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12769e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12779e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12789e9210b8SJeremy L Thompson request); 1279d965c7a7SJeremy L Thompson } else { 1280d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1281d1d35e2fSjeremylt if (!op->op_fallback) { 1282d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1283d965c7a7SJeremy L Thompson } 1284d965c7a7SJeremy L Thompson // Assemble 1285d1d35e2fSjeremylt return CeedOperatorLinearAssemblePointBlockDiagonal(op->op_fallback, 1286e2f04181SAndrew T. Barker assembled, request); 12879e9210b8SJeremy L Thompson } 12889e9210b8SJeremy L Thompson } 12899e9210b8SJeremy L Thompson 12909e9210b8SJeremy L Thompson /** 12919e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12929e9210b8SJeremy L Thompson 12939e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12949e9210b8SJeremy L Thompson CeedOperator. 12959e9210b8SJeremy L Thompson 12969e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12979e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12989e9210b8SJeremy L Thompson 12999e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 13009e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 13019e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 1302d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 13039e9210b8SJeremy L Thompson of this vector are derived from the active vector 13049e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 13059e9210b8SJeremy L Thompson [nodes, component out, component in]. 13069e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 13079e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 13089e9210b8SJeremy L Thompson 13099e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13109e9210b8SJeremy L Thompson 13119e9210b8SJeremy L Thompson @ref User 13129e9210b8SJeremy L Thompson **/ 13139e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 13149e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 13159e9210b8SJeremy L Thompson int ierr; 1316e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 13179e9210b8SJeremy L Thompson 13189e9210b8SJeremy L Thompson // Use backend version, if available 13199e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1320e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 13219e9210b8SJeremy L Thompson } else { 13229e9210b8SJeremy L Thompson // Fallback to reference Ceed 1323d1d35e2fSjeremylt if (!op->op_fallback) { 13249e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13259e9210b8SJeremy L Thompson } 13269e9210b8SJeremy L Thompson // Assemble 1327d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->op_fallback, 1328e2f04181SAndrew T. Barker assembled, request); 1329d965c7a7SJeremy L Thompson } 1330e2f04181SAndrew T. Barker } 1331e2f04181SAndrew T. Barker 1332e2f04181SAndrew T. Barker /** 1333e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1334e2f04181SAndrew T. Barker 1335e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1336e2f04181SAndrew T. Barker 1337e2f04181SAndrew T. Barker @ref Developer 1338e2f04181SAndrew T. Barker **/ 1339e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1340e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1341e2f04181SAndrew T. Barker int ierr; 1342e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1343e2f04181SAndrew T. Barker if (op->composite) 1344e2f04181SAndrew T. Barker // LCOV_EXCL_START 1345e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1346e2f04181SAndrew T. Barker "Composite operator not supported"); 1347e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1348e2f04181SAndrew T. Barker 1349d1d35e2fSjeremylt CeedElemRestriction rstr_in; 1350d1d35e2fSjeremylt ierr = CeedOperatorGetActiveElemRestriction(op, &rstr_in); CeedChk(ierr); 1351d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_nodes, num_comp; 1352d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1353d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1354d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr_in, &num_nodes); CeedChk(ierr); 1355d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1356e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1357d1d35e2fSjeremylt ierr = CeedElemRestrictionGetELayout(rstr_in, &layout_er); CeedChk(ierr); 1358e2f04181SAndrew T. Barker 1359d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1360e2f04181SAndrew T. Barker 1361e2f04181SAndrew T. Barker // Determine elem_dof relation 1362e2f04181SAndrew T. Barker CeedVector index_vec; 1363d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_nodes, &index_vec); CeedChk(ierr); 1364e2f04181SAndrew T. Barker CeedScalar *array; 1365e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1366d1d35e2fSjeremylt for (CeedInt i = 0; i < num_nodes; ++i) { 1367e2f04181SAndrew T. Barker array[i] = i; 1368e2f04181SAndrew T. Barker } 1369e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1370e2f04181SAndrew T. Barker CeedVector elem_dof; 1371d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_elem * elem_size * num_comp, &elem_dof); 1372e2f04181SAndrew T. Barker CeedChk(ierr); 1373e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1374d1d35e2fSjeremylt CeedElemRestrictionApply(rstr_in, CEED_NOTRANSPOSE, index_vec, 1375e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1376e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1377e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1378e2f04181SAndrew T. Barker CeedChk(ierr); 1379e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1380e2f04181SAndrew T. Barker 1381e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1382e2f04181SAndrew T. Barker CeedInt count = 0; 1383d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1384d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1385d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1386d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1387d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1388d1d35e2fSjeremylt const CeedInt elem_dof_index_row = (i)*layout_er[0] + 1389d1d35e2fSjeremylt (comp_out)*layout_er[1] + e*layout_er[2]; 1390d1d35e2fSjeremylt const CeedInt elem_dof_index_col = (j)*layout_er[0] + 1391d1d35e2fSjeremylt (comp_in)*layout_er[1] + e*layout_er[2]; 1392e2f04181SAndrew T. Barker 1393d1d35e2fSjeremylt const CeedInt row = elem_dof_a[elem_dof_index_row]; 1394d1d35e2fSjeremylt const CeedInt col = elem_dof_a[elem_dof_index_col]; 1395e2f04181SAndrew T. Barker 1396e2f04181SAndrew T. Barker rows[offset + count] = row; 1397e2f04181SAndrew T. Barker cols[offset + count] = col; 1398e2f04181SAndrew T. Barker count++; 1399e2f04181SAndrew T. Barker } 1400e2f04181SAndrew T. Barker } 1401e2f04181SAndrew T. Barker } 1402e2f04181SAndrew T. Barker } 1403e2f04181SAndrew T. Barker } 1404d1d35e2fSjeremylt if (count != local_num_entries) 1405e2f04181SAndrew T. Barker // LCOV_EXCL_START 1406e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1407e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1408e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1409e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1410e2f04181SAndrew T. Barker 1411e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1412e2f04181SAndrew T. Barker } 1413e2f04181SAndrew T. Barker 1414e2f04181SAndrew T. Barker /** 1415e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1416e2f04181SAndrew T. Barker 1417e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1418e2f04181SAndrew T. Barker 1419e2f04181SAndrew T. Barker @ref Developer 1420e2f04181SAndrew T. Barker **/ 1421e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1422e2f04181SAndrew T. Barker CeedVector values) { 1423e2f04181SAndrew T. Barker int ierr; 1424e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1425e2f04181SAndrew T. Barker if (op->composite) 1426e2f04181SAndrew T. Barker // LCOV_EXCL_START 1427e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1428e2f04181SAndrew T. Barker "Composite operator not supported"); 1429e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1430e2f04181SAndrew T. Barker 1431e2f04181SAndrew T. Barker // Assemble QFunction 1432e2f04181SAndrew T. Barker CeedQFunction qf; 1433e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1434d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 1435d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 1436e2f04181SAndrew T. Barker CeedChk(ierr); 1437d1d35e2fSjeremylt CeedVector assembled_qf; 1438e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1439e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1440d1d35e2fSjeremylt op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1441e2f04181SAndrew T. Barker 1442d1d35e2fSjeremylt CeedInt qf_length; 1443d1d35e2fSjeremylt ierr = CeedVectorGetLength(assembled_qf, &qf_length); CeedChk(ierr); 1444e2f04181SAndrew T. Barker 1445e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1446e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1447e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1448e2f04181SAndrew T. Barker 1449e2f04181SAndrew T. Barker // Determine active input basis 1450d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1451d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChk(ierr); 1452d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, dim = 1; 1453d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 1454d1d35e2fSjeremylt CeedBasis basis_in = NULL; 1455d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 1456d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1457e2f04181SAndrew T. Barker CeedVector vec; 1458e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1459e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1460d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(input_fields[i], &basis_in); 1461e2f04181SAndrew T. Barker CeedChk(ierr); 1462d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChk(ierr); 1463d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in); 1464e2f04181SAndrew T. Barker CeedChk(ierr); 1465d1d35e2fSjeremylt CeedEvalMode eval_mode; 1466d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1467e2f04181SAndrew T. Barker CeedChk(ierr); 1468d1d35e2fSjeremylt switch (eval_mode) { 1469e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1470e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1471d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChk(ierr); 1472d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 1473d1d35e2fSjeremylt num_eval_mode_in += 1; 1474e2f04181SAndrew T. Barker break; 1475e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1476d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChk(ierr); 1477e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1478d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 1479e2f04181SAndrew T. Barker } 1480d1d35e2fSjeremylt num_eval_mode_in += dim; 1481e2f04181SAndrew T. Barker break; 1482e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1483e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1484e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1485e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1486e2f04181SAndrew T. Barker } 1487e2f04181SAndrew T. Barker } 1488e2f04181SAndrew T. Barker } 1489e2f04181SAndrew T. Barker 1490e2f04181SAndrew T. Barker // Determine active output basis 1491d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChk(ierr); 1492d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 1493d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 1494d1d35e2fSjeremylt CeedBasis basis_out = NULL; 1495d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 1496d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 1497e2f04181SAndrew T. Barker CeedVector vec; 1498e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1499e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1500d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(output_fields[i], &basis_out); 1501e2f04181SAndrew T. Barker CeedChk(ierr); 1502d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out); 1503e2f04181SAndrew T. Barker CeedChk(ierr); 1504d1d35e2fSjeremylt CeedEvalMode eval_mode; 1505d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1506e2f04181SAndrew T. Barker CeedChk(ierr); 1507d1d35e2fSjeremylt switch (eval_mode) { 1508e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1509e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1510d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChk(ierr); 1511d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 1512d1d35e2fSjeremylt num_eval_mode_out += 1; 1513e2f04181SAndrew T. Barker break; 1514e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1515d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); CeedChk(ierr); 1516e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1517d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 1518e2f04181SAndrew T. Barker } 1519d1d35e2fSjeremylt num_eval_mode_out += dim; 1520e2f04181SAndrew T. Barker break; 1521e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1522e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1523e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1524e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1525e2f04181SAndrew T. Barker } 1526e2f04181SAndrew T. Barker } 1527e2f04181SAndrew T. Barker } 1528e2f04181SAndrew T. Barker 1529d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_qpts, num_comp; 1530d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1531d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1532d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1533d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); CeedChk(ierr); 1534e2f04181SAndrew T. Barker 1535d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1536e2f04181SAndrew T. Barker 1537e2f04181SAndrew T. Barker // loop over elements and put in data structure 1538d1d35e2fSjeremylt const CeedScalar *interp_in, *grad_in; 1539d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChk(ierr); 1540d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChk(ierr); 1541e2f04181SAndrew T. Barker 1542d1d35e2fSjeremylt const CeedScalar *assembled_qf_array; 1543d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 1544e2f04181SAndrew T. Barker CeedChk(ierr); 1545e2f04181SAndrew T. Barker 1546e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1547e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1548e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1549e2f04181SAndrew T. Barker 1550d1d35e2fSjeremylt // we store B_mat_in, B_mat_out, BTD, elem_mat in row-major order 1551d1d35e2fSjeremylt CeedScalar B_mat_in[(num_qpts * num_eval_mode_in) * elem_size]; 1552d1d35e2fSjeremylt CeedScalar B_mat_out[(num_qpts * num_eval_mode_out) * elem_size]; 1553d1d35e2fSjeremylt CeedScalar D_mat[num_eval_mode_out * num_eval_mode_in * 1554d1d35e2fSjeremylt num_qpts]; // logically 3-tensor 1555d1d35e2fSjeremylt CeedScalar BTD[elem_size * num_qpts*num_eval_mode_in]; 1556d1d35e2fSjeremylt CeedScalar elem_mat[elem_size * elem_size]; 1557e2f04181SAndrew T. Barker int count = 0; 1558e2f04181SAndrew T. Barker CeedScalar *vals; 1559e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1560d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1561d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1562d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1563d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_in) * elem_size; ++ell) { 1564d1d35e2fSjeremylt B_mat_in[ell] = 0.0; 1565e2f04181SAndrew T. Barker } 1566d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_out) * elem_size; ++ell) { 1567d1d35e2fSjeremylt B_mat_out[ell] = 0.0; 1568e2f04181SAndrew T. Barker } 1569e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1570d1d35e2fSjeremylt for (int ell = 0; ell < num_eval_mode_in*num_eval_mode_out*num_qpts; ++ell) { 1571d1d35e2fSjeremylt D_mat[ell] = 0.0; 1572e2f04181SAndrew T. Barker } 1573e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1574d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*elem_size; ++ell) { 1575e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1576e2f04181SAndrew T. Barker } 1577d1d35e2fSjeremylt for (int q = 0; q < num_qpts; ++q) { 1578d1d35e2fSjeremylt for (int n = 0; n < elem_size; ++n) { 1579d1d35e2fSjeremylt CeedInt d_in = -1; 1580d1d35e2fSjeremylt for (int e_in = 0; e_in < num_eval_mode_in; ++e_in) { 1581d1d35e2fSjeremylt const int qq = num_eval_mode_in*q; 1582d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_INTERP) { 1583d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += interp_in[q * elem_size + n]; 1584d1d35e2fSjeremylt } else if (eval_mode_in[e_in] == CEED_EVAL_GRAD) { 1585d1d35e2fSjeremylt d_in += 1; 1586d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += 1587d1d35e2fSjeremylt grad_in[(d_in*num_qpts+q) * elem_size + n]; 1588e2f04181SAndrew T. Barker } else { 1589e2f04181SAndrew T. Barker // LCOV_EXCL_START 1590e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1591e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1592e2f04181SAndrew T. Barker } 1593e2f04181SAndrew T. Barker } 1594d1d35e2fSjeremylt CeedInt d_out = -1; 1595d1d35e2fSjeremylt for (int e_out = 0; e_out < num_eval_mode_out; ++e_out) { 1596d1d35e2fSjeremylt const int qq = num_eval_mode_out*q; 1597d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_INTERP) { 1598d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += interp_in[q * elem_size + n]; 1599d1d35e2fSjeremylt } else if (eval_mode_out[e_out] == CEED_EVAL_GRAD) { 1600d1d35e2fSjeremylt d_out += 1; 1601d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += 1602d1d35e2fSjeremylt grad_in[(d_out*num_qpts+q) * elem_size + n]; 1603e2f04181SAndrew T. Barker } else { 1604e2f04181SAndrew T. Barker // LCOV_EXCL_START 1605e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1606e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1607e2f04181SAndrew T. Barker } 1608e2f04181SAndrew T. Barker } 1609e2f04181SAndrew T. Barker } 1610d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_out; ++ei) { 1611d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_in; ++ej) { 1612d1d35e2fSjeremylt const int eval_mode_index = ((ei*num_comp+comp_in)*num_eval_mode_in+ej)*num_comp 1613d1d35e2fSjeremylt +comp_out; 1614d1d35e2fSjeremylt const int index = q*layout_qf[0] + eval_mode_index*layout_qf[1] + 1615d1d35e2fSjeremylt e*layout_qf[2]; 1616d1d35e2fSjeremylt D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q] += assembled_qf_array[index]; 1617e2f04181SAndrew T. Barker } 1618e2f04181SAndrew T. Barker } 1619e2f04181SAndrew T. Barker } 1620e2f04181SAndrew T. Barker // Compute B^T*D 1621d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*num_qpts*num_eval_mode_in; ++ell) { 1622e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1623e2f04181SAndrew T. Barker } 1624d1d35e2fSjeremylt for (int j = 0; j<elem_size; ++j) { 1625d1d35e2fSjeremylt for (int q = 0; q<num_qpts; ++q) { 1626d1d35e2fSjeremylt int qq = num_eval_mode_out*q; 1627d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_in; ++ei) { 1628d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_out; ++ej) { 1629d1d35e2fSjeremylt BTD[j*(num_qpts*num_eval_mode_in) + (qq+ei)] += 1630d1d35e2fSjeremylt B_mat_out[(qq+ej)*elem_size + j] * D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q]; 1631e2f04181SAndrew T. Barker } 1632e2f04181SAndrew T. Barker } 1633e2f04181SAndrew T. Barker } 1634e2f04181SAndrew T. Barker } 1635e2f04181SAndrew T. Barker 1636d1d35e2fSjeremylt ierr = CeedMatrixMultiply(ceed, BTD, B_mat_in, elem_mat, elem_size, 1637d1d35e2fSjeremylt elem_size, num_qpts*num_eval_mode_in); CeedChk(ierr); 1638e2f04181SAndrew T. Barker 1639e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1640d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1641d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1642d1d35e2fSjeremylt vals[offset + count] = elem_mat[i*elem_size + j]; 1643e2f04181SAndrew T. Barker count++; 1644e2f04181SAndrew T. Barker } 1645e2f04181SAndrew T. Barker } 1646e2f04181SAndrew T. Barker } 1647e2f04181SAndrew T. Barker } 1648e2f04181SAndrew T. Barker } 1649d1d35e2fSjeremylt if (count != local_num_entries) 1650e2f04181SAndrew T. Barker // LCOV_EXCL_START 1651e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1652e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1653e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1654e2f04181SAndrew T. Barker 1655d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(assembled_qf, &assembled_qf_array); 1656e2f04181SAndrew T. Barker CeedChk(ierr); 1657d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChk(ierr); 1658d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChk(ierr); 1659d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChk(ierr); 1660e2f04181SAndrew T. Barker 1661e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1662e2f04181SAndrew T. Barker } 1663e2f04181SAndrew T. Barker 1664e2f04181SAndrew T. Barker /** 1665e2f04181SAndrew T. Barker @ref Utility 1666e2f04181SAndrew T. Barker **/ 1667d1d35e2fSjeremylt int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, 1668d1d35e2fSjeremylt CeedInt *num_entries) { 1669e2f04181SAndrew T. Barker int ierr; 1670e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1671d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_comp; 1672e2f04181SAndrew T. Barker 1673e2f04181SAndrew T. Barker if (op->composite) 1674e2f04181SAndrew T. Barker // LCOV_EXCL_START 1675e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1676e2f04181SAndrew T. Barker "Composite operator not supported"); 1677e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1678e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1679d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChk(ierr); 1680d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); CeedChk(ierr); 1681d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); CeedChk(ierr); 1682d1d35e2fSjeremylt *num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1683e2f04181SAndrew T. Barker 1684e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1685e2f04181SAndrew T. Barker } 1686e2f04181SAndrew T. Barker 1687e2f04181SAndrew T. Barker /** 1688e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1689e2f04181SAndrew T. Barker 1690e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1691e2f04181SAndrew T. Barker 1692d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1693e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1694e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1695e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1696e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1697e2f04181SAndrew T. Barker ordering. 1698e2f04181SAndrew T. Barker 1699e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1700e2f04181SAndrew T. Barker 1701e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1702d1d35e2fSjeremylt @param[out] num_entries Number of entries in coordinate nonzero pattern. 1703e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1704e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1705e2f04181SAndrew T. Barker 1706e2f04181SAndrew T. Barker @ref User 1707e2f04181SAndrew T. Barker **/ 1708e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1709d1d35e2fSjeremylt CeedInt *num_entries, CeedInt **rows, CeedInt **cols) { 1710e2f04181SAndrew T. Barker int ierr; 1711d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1712d1d35e2fSjeremylt CeedOperator *sub_operators; 1713d1d35e2fSjeremylt bool is_composite; 1714e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1715e2f04181SAndrew T. Barker 1716e2f04181SAndrew T. Barker // Use backend version, if available 1717e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1718d1d35e2fSjeremylt return op->LinearAssembleSymbolic(op, num_entries, rows, cols); 1719e2f04181SAndrew T. Barker } else { 1720e2f04181SAndrew T. Barker // Check for valid fallback resource 1721d1d35e2fSjeremylt const char *resource, *fallback_resource; 1722e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1723d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1724d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1725e2f04181SAndrew T. Barker // Fallback to reference Ceed 1726d1d35e2fSjeremylt if (!op->op_fallback) { 1727e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1728e2f04181SAndrew T. Barker } 1729e2f04181SAndrew T. Barker // Assemble 1730d1d35e2fSjeremylt return CeedOperatorLinearAssembleSymbolic(op->op_fallback, num_entries, rows, 1731d1d35e2fSjeremylt cols); 1732e2f04181SAndrew T. Barker } 1733e2f04181SAndrew T. Barker } 1734e2f04181SAndrew T. Barker 1735e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1736e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1737e2f04181SAndrew T. Barker 1738e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1739d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1740d1d35e2fSjeremylt *num_entries = 0; 1741d1d35e2fSjeremylt if (is_composite) { 1742d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1743d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1744d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1745d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1746e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1747d1d35e2fSjeremylt *num_entries += single_entries; 1748e2f04181SAndrew T. Barker } 1749e2f04181SAndrew T. Barker } else { 1750e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1751e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1752d1d35e2fSjeremylt *num_entries += single_entries; 1753e2f04181SAndrew T. Barker } 1754d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, rows); CeedChk(ierr); 1755d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, cols); CeedChk(ierr); 1756e2f04181SAndrew T. Barker 1757e2f04181SAndrew T. Barker // assemble nonzero locations 1758e2f04181SAndrew T. Barker CeedInt offset = 0; 1759d1d35e2fSjeremylt if (is_composite) { 1760d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1761d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1762d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1763d1d35e2fSjeremylt ierr = CeedSingleOperatorAssembleSymbolic(sub_operators[k], offset, *rows, 1764e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1765d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1766d1d35e2fSjeremylt &single_entries); 1767e2f04181SAndrew T. Barker CeedChk(ierr); 1768e2f04181SAndrew T. Barker offset += single_entries; 1769e2f04181SAndrew T. Barker } 1770e2f04181SAndrew T. Barker } else { 1771e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1772e2f04181SAndrew T. Barker CeedChk(ierr); 1773e2f04181SAndrew T. Barker } 1774e2f04181SAndrew T. Barker 1775e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1776e2f04181SAndrew T. Barker } 1777e2f04181SAndrew T. Barker 1778e2f04181SAndrew T. Barker /** 1779e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1780e2f04181SAndrew T. Barker 1781e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1782e2f04181SAndrew T. Barker 1783d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1784e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1785e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1786e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1787e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1788e2f04181SAndrew T. Barker 1789e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1790e2f04181SAndrew T. Barker 1791e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1792e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1793e2f04181SAndrew T. Barker 1794e2f04181SAndrew T. Barker @ref User 1795e2f04181SAndrew T. Barker **/ 1796e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1797e2f04181SAndrew T. Barker int ierr; 1798d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1799d1d35e2fSjeremylt CeedOperator *sub_operators; 1800e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1801e2f04181SAndrew T. Barker 1802e2f04181SAndrew T. Barker // Use backend version, if available 1803e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1804e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1805e2f04181SAndrew T. Barker } else { 1806e2f04181SAndrew T. Barker // Check for valid fallback resource 1807d1d35e2fSjeremylt const char *resource, *fallback_resource; 1808e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1809d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1810d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1811e2f04181SAndrew T. Barker // Fallback to reference Ceed 1812d1d35e2fSjeremylt if (!op->op_fallback) { 1813e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1814e2f04181SAndrew T. Barker } 1815e2f04181SAndrew T. Barker // Assemble 1816d1d35e2fSjeremylt return CeedOperatorLinearAssemble(op->op_fallback, values); 1817e2f04181SAndrew T. Barker } 1818e2f04181SAndrew T. Barker } 1819e2f04181SAndrew T. Barker 1820e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1821e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1822e2f04181SAndrew T. Barker 1823d1d35e2fSjeremylt bool is_composite; 1824d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1825e2f04181SAndrew T. Barker 1826e2f04181SAndrew T. Barker CeedInt offset = 0; 1827d1d35e2fSjeremylt if (is_composite) { 1828d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1829d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1830d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1831d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemble(sub_operators[k], offset, values); 1832e2f04181SAndrew T. Barker CeedChk(ierr); 1833d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1834d1d35e2fSjeremylt &single_entries); 1835e2f04181SAndrew T. Barker CeedChk(ierr); 1836e2f04181SAndrew T. Barker offset += single_entries; 1837e2f04181SAndrew T. Barker } 1838e2f04181SAndrew T. Barker } else { 1839e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1840e2f04181SAndrew T. Barker } 1841e2f04181SAndrew T. Barker 1842e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1843d965c7a7SJeremy L Thompson } 1844d965c7a7SJeremy L Thompson 1845d965c7a7SJeremy L Thompson /** 1846d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1847d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1848d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1849d99fa3c5SJeremy L Thompson 1850d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1851d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1852d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1853d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1854d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1855d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1856d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1857d99fa3c5SJeremy L Thompson 1858d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1859d99fa3c5SJeremy L Thompson 1860d99fa3c5SJeremy L Thompson @ref User 1861d99fa3c5SJeremy L Thompson **/ 1862d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, 1863d1d35e2fSjeremylt CeedVector p_mult_fine, 1864d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1865d1d35e2fSjeremylt CeedOperator *op_coarse, CeedOperator *op_prolong, 1866d1d35e2fSjeremylt CeedOperator *op_restrict) { 1867d99fa3c5SJeremy L Thompson int ierr; 1868d99fa3c5SJeremy L Thompson Ceed ceed; 1869d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1870d99fa3c5SJeremy L Thompson 1871d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1872d1d35e2fSjeremylt CeedBasis basis_fine; 1873d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1874d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1875d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1876d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1877d1d35e2fSjeremylt if (Q_f != Q_c) 1878d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1879e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1880e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1881d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1882d99fa3c5SJeremy L Thompson 1883d99fa3c5SJeremy L Thompson // Coarse to fine basis 1884d1d35e2fSjeremylt CeedInt P_f, P_c, Q = Q_f; 1885d1d35e2fSjeremylt bool is_tensor_f, is_tensor_c; 1886d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_fine, &is_tensor_f); CeedChk(ierr); 1887d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_coarse, &is_tensor_c); CeedChk(ierr); 1888d1d35e2fSjeremylt CeedScalar *interp_c, *interp_f, *interp_c_to_f, *tau; 1889d1d35e2fSjeremylt if (is_tensor_f && is_tensor_c) { 1890d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_f); CeedChk(ierr); 1891d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_coarse, &P_c); CeedChk(ierr); 1892d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis_coarse, &Q); CeedChk(ierr); 1893d1d35e2fSjeremylt } else if (!is_tensor_f && !is_tensor_c) { 1894d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &P_f); CeedChk(ierr); 1895d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_coarse, &P_c); CeedChk(ierr); 1896d99fa3c5SJeremy L Thompson } else { 1897d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1898e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1899e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1900d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1901d99fa3c5SJeremy L Thompson } 1902d99fa3c5SJeremy L Thompson 1903d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_f, &interp_f); CeedChk(ierr); 1904d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_c, &interp_c); CeedChk(ierr); 1905d1d35e2fSjeremylt ierr = CeedCalloc(P_c*P_f, &interp_c_to_f); CeedChk(ierr); 1906d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1907d1d35e2fSjeremylt if (is_tensor_f) { 1908d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp_1d, Q*P_f*sizeof basis_fine->interp_1d[0]); 1909d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp_1d, 1910d1d35e2fSjeremylt Q*P_c*sizeof basis_coarse->interp_1d[0]); 1911d99fa3c5SJeremy L Thompson } else { 1912d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp, Q*P_f*sizeof basis_fine->interp[0]); 1913d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp, Q*P_c*sizeof basis_coarse->interp[0]); 1914d99fa3c5SJeremy L Thompson } 1915d99fa3c5SJeremy L Thompson 1916d1d35e2fSjeremylt // -- QR Factorization, interp_f = Q R 1917d1d35e2fSjeremylt ierr = CeedQRFactorization(ceed, interp_f, tau, Q, P_f); CeedChk(ierr); 1918d99fa3c5SJeremy L Thompson 1919d1d35e2fSjeremylt // -- Apply Qtranspose, interp_c = Qtranspose interp_c 1920d1d35e2fSjeremylt ierr = CeedHouseholderApplyQ(interp_c, interp_f, tau, CEED_TRANSPOSE, 1921d1d35e2fSjeremylt Q, P_c, P_f, P_c, 1); CeedChk(ierr); 1922d99fa3c5SJeremy L Thompson 1923d1d35e2fSjeremylt // -- Apply Rinv, interp_c_to_f = Rinv interp_c 1924d1d35e2fSjeremylt for (CeedInt j=0; j<P_c; j++) { // Column j 1925d1d35e2fSjeremylt 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]; 1926d1d35e2fSjeremylt for (CeedInt i=P_f-2; i>=0; i--) { // Row i 1927d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] = interp_c[j+P_c*i]; 1928d1d35e2fSjeremylt for (CeedInt k=i+1; k<P_f; k++) 1929d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] -= interp_f[k+P_f*i]*interp_c_to_f[j+P_c*k]; 1930d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] /= interp_f[i+P_f*i]; 1931d99fa3c5SJeremy L Thompson } 1932d99fa3c5SJeremy L Thompson } 1933d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1934d1d35e2fSjeremylt ierr = CeedFree(&interp_c); CeedChk(ierr); 1935d1d35e2fSjeremylt ierr = CeedFree(&interp_f); CeedChk(ierr); 1936d99fa3c5SJeremy L Thompson 1937d1d35e2fSjeremylt // Complete with interp_c_to_f versions of code 1938d1d35e2fSjeremylt if (is_tensor_f) { 1939d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateTensorH1(op_fine, p_mult_fine, 1940d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1941d99fa3c5SJeremy L Thompson CeedChk(ierr); 1942d99fa3c5SJeremy L Thompson } else { 1943d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateH1(op_fine, p_mult_fine, 1944d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1945d99fa3c5SJeremy L Thompson CeedChk(ierr); 1946d99fa3c5SJeremy L Thompson } 1947d99fa3c5SJeremy L Thompson 1948d99fa3c5SJeremy L Thompson // Cleanup 1949d1d35e2fSjeremylt ierr = CeedFree(&interp_c_to_f); CeedChk(ierr); 1950e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1951d99fa3c5SJeremy L Thompson } 1952d99fa3c5SJeremy L Thompson 1953d99fa3c5SJeremy L Thompson /** 1954d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1955d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1956d99fa3c5SJeremy L Thompson 1957d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1958d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1959d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1960d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1961d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 1962d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1963d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1964d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1965d99fa3c5SJeremy L Thompson 1966d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1967d99fa3c5SJeremy L Thompson 1968d99fa3c5SJeremy L Thompson @ref User 1969d99fa3c5SJeremy L Thompson **/ 1970d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, 1971d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1972d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, 1973d1d35e2fSjeremylt CeedOperator *op_prolong, CeedOperator *op_restrict) { 1974d99fa3c5SJeremy L Thompson int ierr; 1975d99fa3c5SJeremy L Thompson Ceed ceed; 1976d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1977d99fa3c5SJeremy L Thompson 1978d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1979d1d35e2fSjeremylt CeedBasis basis_fine; 1980d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1981d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1982d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1983d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1984d1d35e2fSjeremylt if (Q_f != Q_c) 1985d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1986e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1987e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1988d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1989d99fa3c5SJeremy L Thompson 1990d99fa3c5SJeremy L Thompson // Coarse to fine basis 1991d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c; 1992d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 1993d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 1994d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_1d_f); CeedChk(ierr); 1995d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 1996d99fa3c5SJeremy L Thompson CeedChk(ierr); 1997d1d35e2fSjeremylt P_1d_c = dim == 1 ? num_nodes_c : 1998d1d35e2fSjeremylt dim == 2 ? sqrt(num_nodes_c) : 1999d1d35e2fSjeremylt cbrt(num_nodes_c); 2000d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2001d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_ref); CeedChk(ierr); 2002d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_weight); CeedChk(ierr); 2003d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f*P_1d_c*dim, &grad); CeedChk(ierr); 2004d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2005d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, 2006d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2007d99fa3c5SJeremy L Thompson CeedChk(ierr); 2008d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2009d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2010d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2011d99fa3c5SJeremy L Thompson 2012d99fa3c5SJeremy L Thompson // Core code 2013d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2014d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2015d1d35e2fSjeremylt op_prolong, op_restrict); 2016d99fa3c5SJeremy L Thompson CeedChk(ierr); 2017e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2018d99fa3c5SJeremy L Thompson } 2019d99fa3c5SJeremy L Thompson 2020d99fa3c5SJeremy L Thompson /** 2021d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 2022d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 2023d99fa3c5SJeremy L Thompson 2024d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 2025d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 2026d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 2027d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2028d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2029d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2030d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2031d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2032d99fa3c5SJeremy L Thompson 2033d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2034d99fa3c5SJeremy L Thompson 2035d99fa3c5SJeremy L Thompson @ref User 2036d99fa3c5SJeremy L Thompson **/ 2037d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, 2038d1d35e2fSjeremylt CeedVector p_mult_fine, 2039d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, 2040d1d35e2fSjeremylt CeedBasis basis_coarse, 2041d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, 2042d1d35e2fSjeremylt CeedOperator *op_coarse, 2043d1d35e2fSjeremylt CeedOperator *op_prolong, 2044d1d35e2fSjeremylt CeedOperator *op_restrict) { 2045d99fa3c5SJeremy L Thompson int ierr; 2046d99fa3c5SJeremy L Thompson Ceed ceed; 2047d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2048d99fa3c5SJeremy L Thompson 2049d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2050d1d35e2fSjeremylt CeedBasis basis_fine; 2051d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2052d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2053d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2054d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2055d1d35e2fSjeremylt if (Q_f != Q_c) 2056d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2057e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2058e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2059d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2060d99fa3c5SJeremy L Thompson 2061d99fa3c5SJeremy L Thompson // Coarse to fine basis 2062d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2063d1d35e2fSjeremylt ierr = CeedBasisGetTopology(basis_fine, &topo); CeedChk(ierr); 2064d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, num_nodes_f; 2065d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2066d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2067d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &num_nodes_f); CeedChk(ierr); 2068d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2069d99fa3c5SJeremy L Thompson CeedChk(ierr); 2070d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2071d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_ref); CeedChk(ierr); 2072d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_weight); CeedChk(ierr); 2073d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f*num_nodes_c*dim, &grad); CeedChk(ierr); 2074d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2075d1d35e2fSjeremylt ierr = CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, 2076d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2077d99fa3c5SJeremy L Thompson CeedChk(ierr); 2078d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2079d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2080d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2081d99fa3c5SJeremy L Thompson 2082d99fa3c5SJeremy L Thompson // Core code 2083d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2084d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2085d1d35e2fSjeremylt op_prolong, op_restrict); 2086d99fa3c5SJeremy L Thompson CeedChk(ierr); 2087e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2088d99fa3c5SJeremy L Thompson } 2089d99fa3c5SJeremy L Thompson 2090d99fa3c5SJeremy L Thompson /** 20913bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 20923bd813ffSjeremylt CeedOperator 20933bd813ffSjeremylt 20943bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 20953bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 20963bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 20973bd813ffSjeremylt M = V^T V, K = V^T S V. 20983bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 20993bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 21003bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 21013bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 21023bd813ffSjeremylt 21033bd813ffSjeremylt @param op CeedOperator to create element inverses 2104d1d35e2fSjeremylt @param[out] fdm_inv CeedOperator to apply the action of a FDM based inverse 21053bd813ffSjeremylt for each element 21063bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 21074cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 21083bd813ffSjeremylt 21093bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 21103bd813ffSjeremylt 21117a982d89SJeremy L. Thompson @ref Backend 21123bd813ffSjeremylt **/ 2113d1d35e2fSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdm_inv, 21143bd813ffSjeremylt CeedRequest *request) { 21153bd813ffSjeremylt int ierr; 2116e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 21173bd813ffSjeremylt 2118713f43c3Sjeremylt // Use backend version, if available 2119713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2120d1d35e2fSjeremylt ierr = op->CreateFDMElementInverse(op, fdm_inv, request); CeedChk(ierr); 2121713f43c3Sjeremylt } else { 2122713f43c3Sjeremylt // Fallback to reference Ceed 2123d1d35e2fSjeremylt if (!op->op_fallback) { 2124713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 21253bd813ffSjeremylt } 2126713f43c3Sjeremylt // Assemble 2127d1d35e2fSjeremylt ierr = op->op_fallback->CreateFDMElementInverse(op->op_fallback, fdm_inv, 21283bd813ffSjeremylt request); CeedChk(ierr); 21293bd813ffSjeremylt } 2130e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21313bd813ffSjeremylt } 21323bd813ffSjeremylt 21337a982d89SJeremy L. Thompson /** 21347a982d89SJeremy L. Thompson @brief View a CeedOperator 21357a982d89SJeremy L. Thompson 21367a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 21377a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 21387a982d89SJeremy L. Thompson 21397a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 21407a982d89SJeremy L. Thompson 21417a982d89SJeremy L. Thompson @ref User 21427a982d89SJeremy L. Thompson **/ 21437a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 21447a982d89SJeremy L. Thompson int ierr; 21457a982d89SJeremy L. Thompson 21467a982d89SJeremy L. Thompson if (op->composite) { 21477a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21487a982d89SJeremy L. Thompson 2149d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 21507a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 2151d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 21527a982d89SJeremy L. Thompson CeedChk(ierr); 21537a982d89SJeremy L. Thompson } 21547a982d89SJeremy L. Thompson } else { 21557a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21567a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21577a982d89SJeremy L. Thompson } 2158e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21597a982d89SJeremy L. Thompson } 21603bd813ffSjeremylt 21613bd813ffSjeremylt /** 21623bd813ffSjeremylt @brief Apply CeedOperator to a vector 2163d7b241e6Sjeremylt 2164d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2165d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2166d7b241e6Sjeremylt CeedOperatorSetField(). 2167d7b241e6Sjeremylt 2168d7b241e6Sjeremylt @param op CeedOperator to apply 21694cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 217034138859Sjeremylt there are no active inputs 2171b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21724cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 217334138859Sjeremylt active outputs 2174d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21754cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2176b11c1e72Sjeremylt 2177b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2178dfdf5a53Sjeremylt 21797a982d89SJeremy L. Thompson @ref User 2180b11c1e72Sjeremylt **/ 2181692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2182692c2638Sjeremylt CeedRequest *request) { 2183d7b241e6Sjeremylt int ierr; 2184e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2185d7b241e6Sjeremylt 2186d1d35e2fSjeremylt if (op->num_elem) { 2187250756a7Sjeremylt // Standard Operator 2188cae8b89aSjeremylt if (op->Apply) { 2189250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2190cae8b89aSjeremylt } else { 2191cae8b89aSjeremylt // Zero all output vectors 2192250756a7Sjeremylt CeedQFunction qf = op->qf; 2193d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 2194d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 2195cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2196cae8b89aSjeremylt vec = out; 2197cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2198cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2199cae8b89aSjeremylt } 2200cae8b89aSjeremylt } 2201250756a7Sjeremylt // Apply 2202250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2203250756a7Sjeremylt } 2204250756a7Sjeremylt } else if (op->composite) { 2205250756a7Sjeremylt // Composite Operator 2206250756a7Sjeremylt if (op->ApplyComposite) { 2207250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2208250756a7Sjeremylt } else { 2209d1d35e2fSjeremylt CeedInt num_suboperators; 2210d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2211d1d35e2fSjeremylt CeedOperator *sub_operators; 2212d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2213250756a7Sjeremylt 2214250756a7Sjeremylt // Zero all output vectors 2215250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2216cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2217cae8b89aSjeremylt } 2218d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2219d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 2220d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 2221250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2222250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2223250756a7Sjeremylt } 2224250756a7Sjeremylt } 2225250756a7Sjeremylt } 2226250756a7Sjeremylt // Apply 2227d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 2228d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 2229cae8b89aSjeremylt CeedChk(ierr); 2230cae8b89aSjeremylt } 2231cae8b89aSjeremylt } 2232250756a7Sjeremylt } 2233e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2234cae8b89aSjeremylt } 2235cae8b89aSjeremylt 2236cae8b89aSjeremylt /** 2237cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2238cae8b89aSjeremylt 2239cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2240cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2241cae8b89aSjeremylt CeedOperatorSetField(). 2242cae8b89aSjeremylt 2243cae8b89aSjeremylt @param op CeedOperator to apply 2244cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2245cae8b89aSjeremylt active inputs 2246cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2247cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2248cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22494cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2250cae8b89aSjeremylt 2251cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2252cae8b89aSjeremylt 22537a982d89SJeremy L. Thompson @ref User 2254cae8b89aSjeremylt **/ 2255cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2256cae8b89aSjeremylt CeedRequest *request) { 2257cae8b89aSjeremylt int ierr; 2258e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2259cae8b89aSjeremylt 2260d1d35e2fSjeremylt if (op->num_elem) { 2261250756a7Sjeremylt // Standard Operator 2262250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2263250756a7Sjeremylt } else if (op->composite) { 2264250756a7Sjeremylt // Composite Operator 2265250756a7Sjeremylt if (op->ApplyAddComposite) { 2266250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2267cae8b89aSjeremylt } else { 2268d1d35e2fSjeremylt CeedInt num_suboperators; 2269d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2270d1d35e2fSjeremylt CeedOperator *sub_operators; 2271d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2272250756a7Sjeremylt 2273d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2274d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 2275cae8b89aSjeremylt CeedChk(ierr); 22761d7d2407SJeremy L Thompson } 2277250756a7Sjeremylt } 2278250756a7Sjeremylt } 2279e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2280d7b241e6Sjeremylt } 2281d7b241e6Sjeremylt 2282d7b241e6Sjeremylt /** 2283b11c1e72Sjeremylt @brief Destroy a CeedOperator 2284d7b241e6Sjeremylt 2285d7b241e6Sjeremylt @param op CeedOperator to destroy 2286b11c1e72Sjeremylt 2287b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2288dfdf5a53Sjeremylt 22897a982d89SJeremy L. Thompson @ref User 2290b11c1e72Sjeremylt **/ 2291d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2292d7b241e6Sjeremylt int ierr; 2293d7b241e6Sjeremylt 2294d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 2295d7b241e6Sjeremylt if ((*op)->Destroy) { 2296d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2297d7b241e6Sjeremylt } 2298fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2299fe2413ffSjeremylt // Free fields 2300d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2301d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 2302d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 2303d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 230471352a93Sjeremylt CeedChk(ierr); 230515910d16Sjeremylt } 2306d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2307d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 230871352a93Sjeremylt } 2309d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 2310d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 2311d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 231271352a93Sjeremylt } 2313d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 2314d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 2315fe2413ffSjeremylt } 2316d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2317d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 2318d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 231971352a93Sjeremylt CeedChk(ierr); 2320d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2321d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 232271352a93Sjeremylt } 2323d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 2324d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 2325d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 232671352a93Sjeremylt } 2327d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 2328d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 2329fe2413ffSjeremylt } 2330d1d35e2fSjeremylt // Destroy sub_operators 2331d1d35e2fSjeremylt for (int i=0; i<(*op)->num_suboperators; i++) 2332d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 2333d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 233452d6035fSJeremy L Thompson } 2335e15f9bd0SJeremy L Thompson if ((*op)->qf) 2336e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2337d1d35e2fSjeremylt (*op)->qf->operators_set--; 2338e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2339d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2340e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2341e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2342d1d35e2fSjeremylt (*op)->dqf->operators_set--; 2343e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2344d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2345e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2346e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2347d1d35e2fSjeremylt (*op)->dqfT->operators_set--; 2348e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2349d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2350fe2413ffSjeremylt 23515107b09fSJeremy L Thompson // Destroy fallback 2352d1d35e2fSjeremylt if ((*op)->op_fallback) { 2353d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 2354d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 2355d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 2356d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 23575107b09fSJeremy L Thompson } 23585107b09fSJeremy L Thompson 2359d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 2360d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 2361d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 2362d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2363e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2364d7b241e6Sjeremylt } 2365d7b241e6Sjeremylt 2366d7b241e6Sjeremylt /// @} 2367