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 /** 75834359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 75934359f16Sjeremylt 76034359f16Sjeremylt @param op CeedOperator to increment the reference counter 76134359f16Sjeremylt 76234359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 76334359f16Sjeremylt 76434359f16Sjeremylt @ref Backend 76534359f16Sjeremylt **/ 766*9560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 76734359f16Sjeremylt op->ref_count++; 76834359f16Sjeremylt return CEED_ERROR_SUCCESS; 76934359f16Sjeremylt } 77034359f16Sjeremylt 77134359f16Sjeremylt /** 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*9560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 912d1d35e2fSjeremylt (*op)->ref_count = 1; 913d7b241e6Sjeremylt (*op)->qf = qf; 914*9560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 915442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 916d7b241e6Sjeremylt (*op)->dqf = dqf; 917*9560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 918442e7f0bSjeremylt } 919442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 920d7b241e6Sjeremylt (*op)->dqfT = dqfT; 921*9560d06aSjeremylt ierr = CeedQFunctionReference(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*9560d06aSjeremylt ierr = CeedReference(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 /** 966*9560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 967*9560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 968*9560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 969*9560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 970*9560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 971*9560d06aSjeremylt reference to this CeedOperator. 972*9560d06aSjeremylt 973*9560d06aSjeremylt @param op CeedOperator to copy reference to 974*9560d06aSjeremylt @param[out] op_copy Variable to store copied reference 975*9560d06aSjeremylt 976*9560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 977*9560d06aSjeremylt 978*9560d06aSjeremylt @ref User 979*9560d06aSjeremylt **/ 980*9560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 981*9560d06aSjeremylt int ierr; 982*9560d06aSjeremylt 983*9560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 984*9560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 985*9560d06aSjeremylt *op_copy = op; 986*9560d06aSjeremylt return CEED_ERROR_SUCCESS; 987*9560d06aSjeremylt } 988*9560d06aSjeremylt 989*9560d06aSjeremylt /** 990b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 991d7b241e6Sjeremylt 992d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 993d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 994d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 995d7b241e6Sjeremylt 996d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 997d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 998d7b241e6Sjeremylt input and at most one active output. 999d7b241e6Sjeremylt 10008c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 1001d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 10028795c945Sjeremylt CeedQFunction) 1003b11c1e72Sjeremylt @param r CeedElemRestriction 10044cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 1005b11c1e72Sjeremylt if collocated with quadrature points 10064cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 10074cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 10084cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 1009b11c1e72Sjeremylt 1010b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1011dfdf5a53Sjeremylt 10127a982d89SJeremy L. Thompson @ref User 1013b11c1e72Sjeremylt **/ 1014d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 1015a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 1016d7b241e6Sjeremylt int ierr; 101752d6035fSJeremy L Thompson if (op->composite) 1018c042f62fSJeremy L Thompson // LCOV_EXCL_START 1019e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1020e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 1021c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10228b067b84SJed Brown if (!r) 1023c042f62fSJeremy L Thompson // LCOV_EXCL_START 1024e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1025c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 1026d1d35e2fSjeremylt field_name); 1027c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10288b067b84SJed Brown if (!b) 1029c042f62fSJeremy L Thompson // LCOV_EXCL_START 1030e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1031e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 1032d1d35e2fSjeremylt field_name); 1033c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10348b067b84SJed Brown if (!v) 1035c042f62fSJeremy L Thompson // LCOV_EXCL_START 1036e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1037e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 1038d1d35e2fSjeremylt field_name); 1039c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 104052d6035fSJeremy L Thompson 1041d1d35e2fSjeremylt CeedInt num_elem; 1042d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 1043d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 1044d1d35e2fSjeremylt op->num_elem != num_elem) 1045c042f62fSJeremy L Thompson // LCOV_EXCL_START 1046e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10471d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1048d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 1049c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1050d7b241e6Sjeremylt 1051d1d35e2fSjeremylt CeedInt num_qpts; 1052e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1053d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 1054d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 1055c042f62fSJeremy L Thompson // LCOV_EXCL_START 1056e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1057e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 1058d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 1059d1d35e2fSjeremylt op->num_qpts); 1060c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1061d7b241e6Sjeremylt } 1062d1d35e2fSjeremylt CeedQFunctionField qf_field; 1063d1d35e2fSjeremylt CeedOperatorField *op_field; 1064d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 1065d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 1066d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 1067d1d35e2fSjeremylt op_field = &op->input_fields[i]; 1068d7b241e6Sjeremylt goto found; 1069d7b241e6Sjeremylt } 1070d7b241e6Sjeremylt } 1071d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 1072d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 1073d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 1074d1d35e2fSjeremylt op_field = &op->output_fields[i]; 1075d7b241e6Sjeremylt goto found; 1076d7b241e6Sjeremylt } 1077d7b241e6Sjeremylt } 1078c042f62fSJeremy L Thompson // LCOV_EXCL_START 1079e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1080e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1081d1d35e2fSjeremylt field_name); 1082c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1083d7b241e6Sjeremylt found: 1084d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 1085d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 1086e15f9bd0SJeremy L Thompson 1087d1d35e2fSjeremylt (*op_field)->vec = v; 1088e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1089*9560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 1090e15f9bd0SJeremy L Thompson } 1091e15f9bd0SJeremy L Thompson 1092d1d35e2fSjeremylt (*op_field)->elem_restr = r; 1093*9560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 1094e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1095d1d35e2fSjeremylt op->num_elem = num_elem; 1096d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 1097e15f9bd0SJeremy L Thompson } 1098d99fa3c5SJeremy L Thompson 1099d1d35e2fSjeremylt (*op_field)->basis = b; 1100e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1101d1d35e2fSjeremylt op->num_qpts = num_qpts; 1102*9560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 1103e15f9bd0SJeremy L Thompson } 1104e15f9bd0SJeremy L Thompson 1105d1d35e2fSjeremylt op->num_fields += 1; 1106d1d35e2fSjeremylt size_t len = strlen(field_name); 1107d99fa3c5SJeremy L Thompson char *tmp; 1108d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1109d1d35e2fSjeremylt memcpy(tmp, field_name, len+1); 1110d1d35e2fSjeremylt (*op_field)->field_name = tmp; 1111e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1112d7b241e6Sjeremylt } 1113d7b241e6Sjeremylt 1114d7b241e6Sjeremylt /** 111552d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1116288c0443SJeremy L Thompson 1117d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 1118d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 111952d6035fSJeremy L Thompson 112052d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 112152d6035fSJeremy L Thompson 11227a982d89SJeremy L. Thompson @ref User 112352d6035fSJeremy L Thompson */ 1124d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 1125d1d35e2fSjeremylt CeedOperator sub_op) { 112634359f16Sjeremylt int ierr; 112734359f16Sjeremylt 1128d1d35e2fSjeremylt if (!composite_op->composite) 1129c042f62fSJeremy L Thompson // LCOV_EXCL_START 1130d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 1131e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1132c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 113352d6035fSJeremy L Thompson 1134d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 1135c042f62fSJeremy L Thompson // LCOV_EXCL_START 1136d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 1137d1d35e2fSjeremylt "Cannot add additional sub_operators"); 1138c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 113952d6035fSJeremy L Thompson 1140d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 1141*9560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 1142d1d35e2fSjeremylt composite_op->num_suboperators++; 1143e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 114452d6035fSJeremy L Thompson } 114552d6035fSJeremy L Thompson 114652d6035fSJeremy L Thompson /** 11471d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11481d102b48SJeremy L Thompson 11491d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11501d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11511d102b48SJeremy L Thompson The vector 'assembled' is of shape 11521d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11531d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11541d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11551d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11564cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11571d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11581d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11591d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11601d102b48SJeremy L Thompson 11611d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11621d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11631d102b48SJeremy L Thompson quadrature points 11641d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11651d102b48SJeremy L Thompson CeedQFunction 11661d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11674cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11681d102b48SJeremy L Thompson 11691d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11701d102b48SJeremy L Thompson 11717a982d89SJeremy L. Thompson @ref User 11721d102b48SJeremy L Thompson **/ 117380ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11747f823360Sjeremylt CeedElemRestriction *rstr, 11757f823360Sjeremylt CeedRequest *request) { 11761d102b48SJeremy L Thompson int ierr; 1177e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11781d102b48SJeremy L Thompson 11797172caadSjeremylt // Backend version 118080ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1181e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11825107b09fSJeremy L Thompson } else { 11835107b09fSJeremy L Thompson // Fallback to reference Ceed 1184d1d35e2fSjeremylt if (!op->op_fallback) { 11855107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11865107b09fSJeremy L Thompson } 11875107b09fSJeremy L Thompson // Assemble 1188d1d35e2fSjeremylt return CeedOperatorLinearAssembleQFunction(op->op_fallback, assembled, 1189e2f04181SAndrew T. Barker rstr, request); 11905107b09fSJeremy L Thompson } 11911d102b48SJeremy L Thompson } 11921d102b48SJeremy L Thompson 11931d102b48SJeremy L Thompson /** 1194d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1195b7ec98d8SJeremy L Thompson 11969e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1197b7ec98d8SJeremy L Thompson 1198c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1199c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1200d965c7a7SJeremy L Thompson 1201b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1202b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1203b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12044cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1205b7ec98d8SJeremy L Thompson 1206b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1207b7ec98d8SJeremy L Thompson 12087a982d89SJeremy L. Thompson @ref User 1209b7ec98d8SJeremy L Thompson **/ 12102bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 12117f823360Sjeremylt CeedRequest *request) { 1212b7ec98d8SJeremy L Thompson int ierr; 1213e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1214b7ec98d8SJeremy L Thompson 1215b7ec98d8SJeremy L Thompson // Use backend version, if available 121680ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1217e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 12189e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 12199e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12209e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 12219e9210b8SJeremy L Thompson } else { 12229e9210b8SJeremy L Thompson // Fallback to reference Ceed 1223d1d35e2fSjeremylt if (!op->op_fallback) { 12249e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 12259e9210b8SJeremy L Thompson } 12269e9210b8SJeremy L Thompson // Assemble 1227d1d35e2fSjeremylt return CeedOperatorLinearAssembleDiagonal(op->op_fallback, assembled, 1228e2f04181SAndrew T. Barker request); 12299e9210b8SJeremy L Thompson } 12309e9210b8SJeremy L Thompson } 12319e9210b8SJeremy L Thompson 12329e9210b8SJeremy L Thompson /** 12339e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 12349e9210b8SJeremy L Thompson 12359e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 12369e9210b8SJeremy L Thompson 12379e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12389e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12399e9210b8SJeremy L Thompson 12409e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12419e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 12429e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12439e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 12449e9210b8SJeremy L Thompson 12459e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12469e9210b8SJeremy L Thompson 12479e9210b8SJeremy L Thompson @ref User 12489e9210b8SJeremy L Thompson **/ 12499e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12509e9210b8SJeremy L Thompson CeedRequest *request) { 12519e9210b8SJeremy L Thompson int ierr; 1252e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12539e9210b8SJeremy L Thompson 12549e9210b8SJeremy L Thompson // Use backend version, if available 12559e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1256e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12577172caadSjeremylt } else { 12587172caadSjeremylt // Fallback to reference Ceed 1259d1d35e2fSjeremylt if (!op->op_fallback) { 12607172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1261b7ec98d8SJeremy L Thompson } 12627172caadSjeremylt // Assemble 1263d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddDiagonal(op->op_fallback, assembled, 1264e2f04181SAndrew T. Barker request); 1265b7ec98d8SJeremy L Thompson } 1266b7ec98d8SJeremy L Thompson } 1267b7ec98d8SJeremy L Thompson 1268b7ec98d8SJeremy L Thompson /** 1269d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1270d965c7a7SJeremy L Thompson 12719e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1272d965c7a7SJeremy L Thompson CeedOperator. 1273d965c7a7SJeremy L Thompson 1274c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1275c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1276d965c7a7SJeremy L Thompson 1277d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1278d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1279d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1280d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 1281d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1282d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1283d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1284d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1285d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1286d965c7a7SJeremy L Thompson 1287d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1288d965c7a7SJeremy L Thompson 1289d965c7a7SJeremy L Thompson @ref User 1290d965c7a7SJeremy L Thompson **/ 129180ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12922bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1293d965c7a7SJeremy L Thompson int ierr; 1294e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1295d965c7a7SJeremy L Thompson 1296d965c7a7SJeremy L Thompson // Use backend version, if available 129780ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1298e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12999e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 13009e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 13019e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 13029e9210b8SJeremy L Thompson request); 1303d965c7a7SJeremy L Thompson } else { 1304d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1305d1d35e2fSjeremylt if (!op->op_fallback) { 1306d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1307d965c7a7SJeremy L Thompson } 1308d965c7a7SJeremy L Thompson // Assemble 1309d1d35e2fSjeremylt return CeedOperatorLinearAssemblePointBlockDiagonal(op->op_fallback, 1310e2f04181SAndrew T. Barker assembled, request); 13119e9210b8SJeremy L Thompson } 13129e9210b8SJeremy L Thompson } 13139e9210b8SJeremy L Thompson 13149e9210b8SJeremy L Thompson /** 13159e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 13169e9210b8SJeremy L Thompson 13179e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 13189e9210b8SJeremy L Thompson CeedOperator. 13199e9210b8SJeremy L Thompson 13209e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 13219e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 13229e9210b8SJeremy L Thompson 13239e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 13249e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 13259e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 1326d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 13279e9210b8SJeremy L Thompson of this vector are derived from the active vector 13289e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 13299e9210b8SJeremy L Thompson [nodes, component out, component in]. 13309e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 13319e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 13329e9210b8SJeremy L Thompson 13339e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13349e9210b8SJeremy L Thompson 13359e9210b8SJeremy L Thompson @ref User 13369e9210b8SJeremy L Thompson **/ 13379e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 13389e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 13399e9210b8SJeremy L Thompson int ierr; 1340e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 13419e9210b8SJeremy L Thompson 13429e9210b8SJeremy L Thompson // Use backend version, if available 13439e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1344e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 13459e9210b8SJeremy L Thompson } else { 13469e9210b8SJeremy L Thompson // Fallback to reference Ceed 1347d1d35e2fSjeremylt if (!op->op_fallback) { 13489e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13499e9210b8SJeremy L Thompson } 13509e9210b8SJeremy L Thompson // Assemble 1351d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->op_fallback, 1352e2f04181SAndrew T. Barker assembled, request); 1353d965c7a7SJeremy L Thompson } 1354e2f04181SAndrew T. Barker } 1355e2f04181SAndrew T. Barker 1356e2f04181SAndrew T. Barker /** 1357e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1358e2f04181SAndrew T. Barker 1359e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1360e2f04181SAndrew T. Barker 1361e2f04181SAndrew T. Barker @ref Developer 1362e2f04181SAndrew T. Barker **/ 1363e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1364e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1365e2f04181SAndrew T. Barker int ierr; 1366e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1367e2f04181SAndrew T. Barker if (op->composite) 1368e2f04181SAndrew T. Barker // LCOV_EXCL_START 1369e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1370e2f04181SAndrew T. Barker "Composite operator not supported"); 1371e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1372e2f04181SAndrew T. Barker 1373d1d35e2fSjeremylt CeedElemRestriction rstr_in; 1374d1d35e2fSjeremylt ierr = CeedOperatorGetActiveElemRestriction(op, &rstr_in); CeedChk(ierr); 1375d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_nodes, num_comp; 1376d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1377d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1378d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr_in, &num_nodes); CeedChk(ierr); 1379d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1380e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1381d1d35e2fSjeremylt ierr = CeedElemRestrictionGetELayout(rstr_in, &layout_er); CeedChk(ierr); 1382e2f04181SAndrew T. Barker 1383d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1384e2f04181SAndrew T. Barker 1385e2f04181SAndrew T. Barker // Determine elem_dof relation 1386e2f04181SAndrew T. Barker CeedVector index_vec; 1387d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_nodes, &index_vec); CeedChk(ierr); 1388e2f04181SAndrew T. Barker CeedScalar *array; 1389e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1390d1d35e2fSjeremylt for (CeedInt i = 0; i < num_nodes; ++i) { 1391e2f04181SAndrew T. Barker array[i] = i; 1392e2f04181SAndrew T. Barker } 1393e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1394e2f04181SAndrew T. Barker CeedVector elem_dof; 1395d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_elem * elem_size * num_comp, &elem_dof); 1396e2f04181SAndrew T. Barker CeedChk(ierr); 1397e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1398d1d35e2fSjeremylt CeedElemRestrictionApply(rstr_in, CEED_NOTRANSPOSE, index_vec, 1399e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1400e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1401e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1402e2f04181SAndrew T. Barker CeedChk(ierr); 1403e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1404e2f04181SAndrew T. Barker 1405e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1406e2f04181SAndrew T. Barker CeedInt count = 0; 1407d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1408d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1409d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1410d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1411d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1412d1d35e2fSjeremylt const CeedInt elem_dof_index_row = (i)*layout_er[0] + 1413d1d35e2fSjeremylt (comp_out)*layout_er[1] + e*layout_er[2]; 1414d1d35e2fSjeremylt const CeedInt elem_dof_index_col = (j)*layout_er[0] + 1415d1d35e2fSjeremylt (comp_in)*layout_er[1] + e*layout_er[2]; 1416e2f04181SAndrew T. Barker 1417d1d35e2fSjeremylt const CeedInt row = elem_dof_a[elem_dof_index_row]; 1418d1d35e2fSjeremylt const CeedInt col = elem_dof_a[elem_dof_index_col]; 1419e2f04181SAndrew T. Barker 1420e2f04181SAndrew T. Barker rows[offset + count] = row; 1421e2f04181SAndrew T. Barker cols[offset + count] = col; 1422e2f04181SAndrew T. Barker count++; 1423e2f04181SAndrew T. Barker } 1424e2f04181SAndrew T. Barker } 1425e2f04181SAndrew T. Barker } 1426e2f04181SAndrew T. Barker } 1427e2f04181SAndrew T. Barker } 1428d1d35e2fSjeremylt if (count != local_num_entries) 1429e2f04181SAndrew T. Barker // LCOV_EXCL_START 1430e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1431e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1432e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1433e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1434e2f04181SAndrew T. Barker 1435e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1436e2f04181SAndrew T. Barker } 1437e2f04181SAndrew T. Barker 1438e2f04181SAndrew T. Barker /** 1439e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1440e2f04181SAndrew T. Barker 1441e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1442e2f04181SAndrew T. Barker 1443e2f04181SAndrew T. Barker @ref Developer 1444e2f04181SAndrew T. Barker **/ 1445e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1446e2f04181SAndrew T. Barker CeedVector values) { 1447e2f04181SAndrew T. Barker int ierr; 1448e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1449e2f04181SAndrew T. Barker if (op->composite) 1450e2f04181SAndrew T. Barker // LCOV_EXCL_START 1451e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1452e2f04181SAndrew T. Barker "Composite operator not supported"); 1453e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1454e2f04181SAndrew T. Barker 1455e2f04181SAndrew T. Barker // Assemble QFunction 1456e2f04181SAndrew T. Barker CeedQFunction qf; 1457e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1458d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 1459d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 1460e2f04181SAndrew T. Barker CeedChk(ierr); 1461d1d35e2fSjeremylt CeedVector assembled_qf; 1462e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1463e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1464d1d35e2fSjeremylt op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1465e2f04181SAndrew T. Barker 1466d1d35e2fSjeremylt CeedInt qf_length; 1467d1d35e2fSjeremylt ierr = CeedVectorGetLength(assembled_qf, &qf_length); CeedChk(ierr); 1468e2f04181SAndrew T. Barker 1469e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1470e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1471e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1472e2f04181SAndrew T. Barker 1473e2f04181SAndrew T. Barker // Determine active input basis 1474d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1475d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChk(ierr); 1476d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, dim = 1; 1477d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 1478d1d35e2fSjeremylt CeedBasis basis_in = NULL; 1479d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 1480d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1481e2f04181SAndrew T. Barker CeedVector vec; 1482e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1483e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1484d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(input_fields[i], &basis_in); 1485e2f04181SAndrew T. Barker CeedChk(ierr); 1486d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChk(ierr); 1487d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in); 1488e2f04181SAndrew T. Barker CeedChk(ierr); 1489d1d35e2fSjeremylt CeedEvalMode eval_mode; 1490d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1491e2f04181SAndrew T. Barker CeedChk(ierr); 1492d1d35e2fSjeremylt switch (eval_mode) { 1493e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1494e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1495d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChk(ierr); 1496d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 1497d1d35e2fSjeremylt num_eval_mode_in += 1; 1498e2f04181SAndrew T. Barker break; 1499e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1500d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChk(ierr); 1501e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1502d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 1503e2f04181SAndrew T. Barker } 1504d1d35e2fSjeremylt num_eval_mode_in += dim; 1505e2f04181SAndrew T. Barker break; 1506e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1507e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1508e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1509e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1510e2f04181SAndrew T. Barker } 1511e2f04181SAndrew T. Barker } 1512e2f04181SAndrew T. Barker } 1513e2f04181SAndrew T. Barker 1514e2f04181SAndrew T. Barker // Determine active output basis 1515d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChk(ierr); 1516d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 1517d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 1518d1d35e2fSjeremylt CeedBasis basis_out = NULL; 1519d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 1520d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 1521e2f04181SAndrew T. Barker CeedVector vec; 1522e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1523e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1524d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(output_fields[i], &basis_out); 1525e2f04181SAndrew T. Barker CeedChk(ierr); 1526d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out); 1527e2f04181SAndrew T. Barker CeedChk(ierr); 1528d1d35e2fSjeremylt CeedEvalMode eval_mode; 1529d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1530e2f04181SAndrew T. Barker CeedChk(ierr); 1531d1d35e2fSjeremylt switch (eval_mode) { 1532e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1533e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1534d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChk(ierr); 1535d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 1536d1d35e2fSjeremylt num_eval_mode_out += 1; 1537e2f04181SAndrew T. Barker break; 1538e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1539d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); CeedChk(ierr); 1540e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1541d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 1542e2f04181SAndrew T. Barker } 1543d1d35e2fSjeremylt num_eval_mode_out += dim; 1544e2f04181SAndrew T. Barker break; 1545e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1546e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1547e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1548e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1549e2f04181SAndrew T. Barker } 1550e2f04181SAndrew T. Barker } 1551e2f04181SAndrew T. Barker } 1552e2f04181SAndrew T. Barker 1553d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_qpts, num_comp; 1554d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1555d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1556d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1557d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); CeedChk(ierr); 1558e2f04181SAndrew T. Barker 1559d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1560e2f04181SAndrew T. Barker 1561e2f04181SAndrew T. Barker // loop over elements and put in data structure 1562d1d35e2fSjeremylt const CeedScalar *interp_in, *grad_in; 1563d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChk(ierr); 1564d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChk(ierr); 1565e2f04181SAndrew T. Barker 1566d1d35e2fSjeremylt const CeedScalar *assembled_qf_array; 1567d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 1568e2f04181SAndrew T. Barker CeedChk(ierr); 1569e2f04181SAndrew T. Barker 1570e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1571e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1572e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1573e2f04181SAndrew T. Barker 1574d1d35e2fSjeremylt // we store B_mat_in, B_mat_out, BTD, elem_mat in row-major order 1575d1d35e2fSjeremylt CeedScalar B_mat_in[(num_qpts * num_eval_mode_in) * elem_size]; 1576d1d35e2fSjeremylt CeedScalar B_mat_out[(num_qpts * num_eval_mode_out) * elem_size]; 1577d1d35e2fSjeremylt CeedScalar D_mat[num_eval_mode_out * num_eval_mode_in * 1578d1d35e2fSjeremylt num_qpts]; // logically 3-tensor 1579d1d35e2fSjeremylt CeedScalar BTD[elem_size * num_qpts*num_eval_mode_in]; 1580d1d35e2fSjeremylt CeedScalar elem_mat[elem_size * elem_size]; 1581e2f04181SAndrew T. Barker int count = 0; 1582e2f04181SAndrew T. Barker CeedScalar *vals; 1583e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1584d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1585d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1586d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1587d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_in) * elem_size; ++ell) { 1588d1d35e2fSjeremylt B_mat_in[ell] = 0.0; 1589e2f04181SAndrew T. Barker } 1590d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_out) * elem_size; ++ell) { 1591d1d35e2fSjeremylt B_mat_out[ell] = 0.0; 1592e2f04181SAndrew T. Barker } 1593e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1594d1d35e2fSjeremylt for (int ell = 0; ell < num_eval_mode_in*num_eval_mode_out*num_qpts; ++ell) { 1595d1d35e2fSjeremylt D_mat[ell] = 0.0; 1596e2f04181SAndrew T. Barker } 1597e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1598d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*elem_size; ++ell) { 1599e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1600e2f04181SAndrew T. Barker } 1601d1d35e2fSjeremylt for (int q = 0; q < num_qpts; ++q) { 1602d1d35e2fSjeremylt for (int n = 0; n < elem_size; ++n) { 1603d1d35e2fSjeremylt CeedInt d_in = -1; 1604d1d35e2fSjeremylt for (int e_in = 0; e_in < num_eval_mode_in; ++e_in) { 1605d1d35e2fSjeremylt const int qq = num_eval_mode_in*q; 1606d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_INTERP) { 1607d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += interp_in[q * elem_size + n]; 1608d1d35e2fSjeremylt } else if (eval_mode_in[e_in] == CEED_EVAL_GRAD) { 1609d1d35e2fSjeremylt d_in += 1; 1610d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += 1611d1d35e2fSjeremylt grad_in[(d_in*num_qpts+q) * elem_size + n]; 1612e2f04181SAndrew T. Barker } else { 1613e2f04181SAndrew T. Barker // LCOV_EXCL_START 1614e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1615e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1616e2f04181SAndrew T. Barker } 1617e2f04181SAndrew T. Barker } 1618d1d35e2fSjeremylt CeedInt d_out = -1; 1619d1d35e2fSjeremylt for (int e_out = 0; e_out < num_eval_mode_out; ++e_out) { 1620d1d35e2fSjeremylt const int qq = num_eval_mode_out*q; 1621d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_INTERP) { 1622d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += interp_in[q * elem_size + n]; 1623d1d35e2fSjeremylt } else if (eval_mode_out[e_out] == CEED_EVAL_GRAD) { 1624d1d35e2fSjeremylt d_out += 1; 1625d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += 1626d1d35e2fSjeremylt grad_in[(d_out*num_qpts+q) * elem_size + n]; 1627e2f04181SAndrew T. Barker } else { 1628e2f04181SAndrew T. Barker // LCOV_EXCL_START 1629e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1630e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1631e2f04181SAndrew T. Barker } 1632e2f04181SAndrew T. Barker } 1633e2f04181SAndrew T. Barker } 1634d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_out; ++ei) { 1635d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_in; ++ej) { 1636d1d35e2fSjeremylt const int eval_mode_index = ((ei*num_comp+comp_in)*num_eval_mode_in+ej)*num_comp 1637d1d35e2fSjeremylt +comp_out; 1638d1d35e2fSjeremylt const int index = q*layout_qf[0] + eval_mode_index*layout_qf[1] + 1639d1d35e2fSjeremylt e*layout_qf[2]; 1640d1d35e2fSjeremylt D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q] += assembled_qf_array[index]; 1641e2f04181SAndrew T. Barker } 1642e2f04181SAndrew T. Barker } 1643e2f04181SAndrew T. Barker } 1644e2f04181SAndrew T. Barker // Compute B^T*D 1645d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*num_qpts*num_eval_mode_in; ++ell) { 1646e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1647e2f04181SAndrew T. Barker } 1648d1d35e2fSjeremylt for (int j = 0; j<elem_size; ++j) { 1649d1d35e2fSjeremylt for (int q = 0; q<num_qpts; ++q) { 1650d1d35e2fSjeremylt int qq = num_eval_mode_out*q; 1651d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_in; ++ei) { 1652d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_out; ++ej) { 1653d1d35e2fSjeremylt BTD[j*(num_qpts*num_eval_mode_in) + (qq+ei)] += 1654d1d35e2fSjeremylt B_mat_out[(qq+ej)*elem_size + j] * D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q]; 1655e2f04181SAndrew T. Barker } 1656e2f04181SAndrew T. Barker } 1657e2f04181SAndrew T. Barker } 1658e2f04181SAndrew T. Barker } 1659e2f04181SAndrew T. Barker 1660d1d35e2fSjeremylt ierr = CeedMatrixMultiply(ceed, BTD, B_mat_in, elem_mat, elem_size, 1661d1d35e2fSjeremylt elem_size, num_qpts*num_eval_mode_in); CeedChk(ierr); 1662e2f04181SAndrew T. Barker 1663e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1664d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1665d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1666d1d35e2fSjeremylt vals[offset + count] = elem_mat[i*elem_size + j]; 1667e2f04181SAndrew T. Barker count++; 1668e2f04181SAndrew T. Barker } 1669e2f04181SAndrew T. Barker } 1670e2f04181SAndrew T. Barker } 1671e2f04181SAndrew T. Barker } 1672e2f04181SAndrew T. Barker } 1673d1d35e2fSjeremylt if (count != local_num_entries) 1674e2f04181SAndrew T. Barker // LCOV_EXCL_START 1675e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1676e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1677e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1678e2f04181SAndrew T. Barker 1679d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(assembled_qf, &assembled_qf_array); 1680e2f04181SAndrew T. Barker CeedChk(ierr); 1681d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChk(ierr); 1682d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChk(ierr); 1683d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChk(ierr); 1684e2f04181SAndrew T. Barker 1685e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1686e2f04181SAndrew T. Barker } 1687e2f04181SAndrew T. Barker 1688e2f04181SAndrew T. Barker /** 1689e2f04181SAndrew T. Barker @ref Utility 1690e2f04181SAndrew T. Barker **/ 1691d1d35e2fSjeremylt int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, 1692d1d35e2fSjeremylt CeedInt *num_entries) { 1693e2f04181SAndrew T. Barker int ierr; 1694e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1695d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_comp; 1696e2f04181SAndrew T. Barker 1697e2f04181SAndrew T. Barker if (op->composite) 1698e2f04181SAndrew T. Barker // LCOV_EXCL_START 1699e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1700e2f04181SAndrew T. Barker "Composite operator not supported"); 1701e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1702e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1703d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChk(ierr); 1704d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); CeedChk(ierr); 1705d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); CeedChk(ierr); 1706d1d35e2fSjeremylt *num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1707e2f04181SAndrew T. Barker 1708e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1709e2f04181SAndrew T. Barker } 1710e2f04181SAndrew T. Barker 1711e2f04181SAndrew T. Barker /** 1712e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1713e2f04181SAndrew T. Barker 1714e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1715e2f04181SAndrew T. Barker 1716d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1717e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1718e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1719e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1720e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1721e2f04181SAndrew T. Barker ordering. 1722e2f04181SAndrew T. Barker 1723e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1724e2f04181SAndrew T. Barker 1725e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1726d1d35e2fSjeremylt @param[out] num_entries Number of entries in coordinate nonzero pattern. 1727e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1728e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1729e2f04181SAndrew T. Barker 1730e2f04181SAndrew T. Barker @ref User 1731e2f04181SAndrew T. Barker **/ 1732e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1733d1d35e2fSjeremylt CeedInt *num_entries, CeedInt **rows, CeedInt **cols) { 1734e2f04181SAndrew T. Barker int ierr; 1735d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1736d1d35e2fSjeremylt CeedOperator *sub_operators; 1737d1d35e2fSjeremylt bool is_composite; 1738e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1739e2f04181SAndrew T. Barker 1740e2f04181SAndrew T. Barker // Use backend version, if available 1741e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1742d1d35e2fSjeremylt return op->LinearAssembleSymbolic(op, num_entries, rows, cols); 1743e2f04181SAndrew T. Barker } else { 1744e2f04181SAndrew T. Barker // Check for valid fallback resource 1745d1d35e2fSjeremylt const char *resource, *fallback_resource; 1746e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1747d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1748d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1749e2f04181SAndrew T. Barker // Fallback to reference Ceed 1750d1d35e2fSjeremylt if (!op->op_fallback) { 1751e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1752e2f04181SAndrew T. Barker } 1753e2f04181SAndrew T. Barker // Assemble 1754d1d35e2fSjeremylt return CeedOperatorLinearAssembleSymbolic(op->op_fallback, num_entries, rows, 1755d1d35e2fSjeremylt cols); 1756e2f04181SAndrew T. Barker } 1757e2f04181SAndrew T. Barker } 1758e2f04181SAndrew T. Barker 1759e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1760e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1761e2f04181SAndrew T. Barker 1762e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1763d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1764d1d35e2fSjeremylt *num_entries = 0; 1765d1d35e2fSjeremylt if (is_composite) { 1766d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1767d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1768d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1769d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1770e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1771d1d35e2fSjeremylt *num_entries += single_entries; 1772e2f04181SAndrew T. Barker } 1773e2f04181SAndrew T. Barker } else { 1774e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1775e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1776d1d35e2fSjeremylt *num_entries += single_entries; 1777e2f04181SAndrew T. Barker } 1778d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, rows); CeedChk(ierr); 1779d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, cols); CeedChk(ierr); 1780e2f04181SAndrew T. Barker 1781e2f04181SAndrew T. Barker // assemble nonzero locations 1782e2f04181SAndrew T. Barker CeedInt offset = 0; 1783d1d35e2fSjeremylt if (is_composite) { 1784d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1785d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1786d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1787d1d35e2fSjeremylt ierr = CeedSingleOperatorAssembleSymbolic(sub_operators[k], offset, *rows, 1788e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1789d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1790d1d35e2fSjeremylt &single_entries); 1791e2f04181SAndrew T. Barker CeedChk(ierr); 1792e2f04181SAndrew T. Barker offset += single_entries; 1793e2f04181SAndrew T. Barker } 1794e2f04181SAndrew T. Barker } else { 1795e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1796e2f04181SAndrew T. Barker CeedChk(ierr); 1797e2f04181SAndrew T. Barker } 1798e2f04181SAndrew T. Barker 1799e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1800e2f04181SAndrew T. Barker } 1801e2f04181SAndrew T. Barker 1802e2f04181SAndrew T. Barker /** 1803e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1804e2f04181SAndrew T. Barker 1805e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1806e2f04181SAndrew T. Barker 1807d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1808e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1809e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1810e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1811e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1812e2f04181SAndrew T. Barker 1813e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1814e2f04181SAndrew T. Barker 1815e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1816e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1817e2f04181SAndrew T. Barker 1818e2f04181SAndrew T. Barker @ref User 1819e2f04181SAndrew T. Barker **/ 1820e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1821e2f04181SAndrew T. Barker int ierr; 1822d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1823d1d35e2fSjeremylt CeedOperator *sub_operators; 1824e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1825e2f04181SAndrew T. Barker 1826e2f04181SAndrew T. Barker // Use backend version, if available 1827e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1828e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1829e2f04181SAndrew T. Barker } else { 1830e2f04181SAndrew T. Barker // Check for valid fallback resource 1831d1d35e2fSjeremylt const char *resource, *fallback_resource; 1832e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1833d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1834d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1835e2f04181SAndrew T. Barker // Fallback to reference Ceed 1836d1d35e2fSjeremylt if (!op->op_fallback) { 1837e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1838e2f04181SAndrew T. Barker } 1839e2f04181SAndrew T. Barker // Assemble 1840d1d35e2fSjeremylt return CeedOperatorLinearAssemble(op->op_fallback, values); 1841e2f04181SAndrew T. Barker } 1842e2f04181SAndrew T. Barker } 1843e2f04181SAndrew T. Barker 1844e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1845e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1846e2f04181SAndrew T. Barker 1847d1d35e2fSjeremylt bool is_composite; 1848d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1849e2f04181SAndrew T. Barker 1850e2f04181SAndrew T. Barker CeedInt offset = 0; 1851d1d35e2fSjeremylt if (is_composite) { 1852d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1853d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1854d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1855d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemble(sub_operators[k], offset, values); 1856e2f04181SAndrew T. Barker CeedChk(ierr); 1857d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1858d1d35e2fSjeremylt &single_entries); 1859e2f04181SAndrew T. Barker CeedChk(ierr); 1860e2f04181SAndrew T. Barker offset += single_entries; 1861e2f04181SAndrew T. Barker } 1862e2f04181SAndrew T. Barker } else { 1863e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1864e2f04181SAndrew T. Barker } 1865e2f04181SAndrew T. Barker 1866e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1867d965c7a7SJeremy L Thompson } 1868d965c7a7SJeremy L Thompson 1869d965c7a7SJeremy L Thompson /** 1870d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1871d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1872d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1873d99fa3c5SJeremy L Thompson 1874d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1875d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1876d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1877d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1878d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1879d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1880d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1881d99fa3c5SJeremy L Thompson 1882d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1883d99fa3c5SJeremy L Thompson 1884d99fa3c5SJeremy L Thompson @ref User 1885d99fa3c5SJeremy L Thompson **/ 1886d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, 1887d1d35e2fSjeremylt CeedVector p_mult_fine, 1888d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1889d1d35e2fSjeremylt CeedOperator *op_coarse, CeedOperator *op_prolong, 1890d1d35e2fSjeremylt CeedOperator *op_restrict) { 1891d99fa3c5SJeremy L Thompson int ierr; 1892d99fa3c5SJeremy L Thompson Ceed ceed; 1893d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1894d99fa3c5SJeremy L Thompson 1895d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1896d1d35e2fSjeremylt CeedBasis basis_fine; 1897d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1898d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1899d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1900d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1901d1d35e2fSjeremylt if (Q_f != Q_c) 1902d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1903e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1904e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1905d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1906d99fa3c5SJeremy L Thompson 1907d99fa3c5SJeremy L Thompson // Coarse to fine basis 1908d1d35e2fSjeremylt CeedInt P_f, P_c, Q = Q_f; 1909d1d35e2fSjeremylt bool is_tensor_f, is_tensor_c; 1910d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_fine, &is_tensor_f); CeedChk(ierr); 1911d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_coarse, &is_tensor_c); CeedChk(ierr); 1912d1d35e2fSjeremylt CeedScalar *interp_c, *interp_f, *interp_c_to_f, *tau; 1913d1d35e2fSjeremylt if (is_tensor_f && is_tensor_c) { 1914d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_f); CeedChk(ierr); 1915d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_coarse, &P_c); CeedChk(ierr); 1916d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis_coarse, &Q); CeedChk(ierr); 1917d1d35e2fSjeremylt } else if (!is_tensor_f && !is_tensor_c) { 1918d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &P_f); CeedChk(ierr); 1919d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_coarse, &P_c); CeedChk(ierr); 1920d99fa3c5SJeremy L Thompson } else { 1921d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1922e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1923e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1924d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1925d99fa3c5SJeremy L Thompson } 1926d99fa3c5SJeremy L Thompson 1927d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_f, &interp_f); CeedChk(ierr); 1928d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_c, &interp_c); CeedChk(ierr); 1929d1d35e2fSjeremylt ierr = CeedCalloc(P_c*P_f, &interp_c_to_f); CeedChk(ierr); 1930d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1931d1d35e2fSjeremylt if (is_tensor_f) { 1932d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp_1d, Q*P_f*sizeof basis_fine->interp_1d[0]); 1933d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp_1d, 1934d1d35e2fSjeremylt Q*P_c*sizeof basis_coarse->interp_1d[0]); 1935d99fa3c5SJeremy L Thompson } else { 1936d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp, Q*P_f*sizeof basis_fine->interp[0]); 1937d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp, Q*P_c*sizeof basis_coarse->interp[0]); 1938d99fa3c5SJeremy L Thompson } 1939d99fa3c5SJeremy L Thompson 1940d1d35e2fSjeremylt // -- QR Factorization, interp_f = Q R 1941d1d35e2fSjeremylt ierr = CeedQRFactorization(ceed, interp_f, tau, Q, P_f); CeedChk(ierr); 1942d99fa3c5SJeremy L Thompson 1943d1d35e2fSjeremylt // -- Apply Qtranspose, interp_c = Qtranspose interp_c 1944d1d35e2fSjeremylt ierr = CeedHouseholderApplyQ(interp_c, interp_f, tau, CEED_TRANSPOSE, 1945d1d35e2fSjeremylt Q, P_c, P_f, P_c, 1); CeedChk(ierr); 1946d99fa3c5SJeremy L Thompson 1947d1d35e2fSjeremylt // -- Apply Rinv, interp_c_to_f = Rinv interp_c 1948d1d35e2fSjeremylt for (CeedInt j=0; j<P_c; j++) { // Column j 1949d1d35e2fSjeremylt 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]; 1950d1d35e2fSjeremylt for (CeedInt i=P_f-2; i>=0; i--) { // Row i 1951d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] = interp_c[j+P_c*i]; 1952d1d35e2fSjeremylt for (CeedInt k=i+1; k<P_f; k++) 1953d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] -= interp_f[k+P_f*i]*interp_c_to_f[j+P_c*k]; 1954d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] /= interp_f[i+P_f*i]; 1955d99fa3c5SJeremy L Thompson } 1956d99fa3c5SJeremy L Thompson } 1957d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1958d1d35e2fSjeremylt ierr = CeedFree(&interp_c); CeedChk(ierr); 1959d1d35e2fSjeremylt ierr = CeedFree(&interp_f); CeedChk(ierr); 1960d99fa3c5SJeremy L Thompson 1961d1d35e2fSjeremylt // Complete with interp_c_to_f versions of code 1962d1d35e2fSjeremylt if (is_tensor_f) { 1963d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateTensorH1(op_fine, p_mult_fine, 1964d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1965d99fa3c5SJeremy L Thompson CeedChk(ierr); 1966d99fa3c5SJeremy L Thompson } else { 1967d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateH1(op_fine, p_mult_fine, 1968d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1969d99fa3c5SJeremy L Thompson CeedChk(ierr); 1970d99fa3c5SJeremy L Thompson } 1971d99fa3c5SJeremy L Thompson 1972d99fa3c5SJeremy L Thompson // Cleanup 1973d1d35e2fSjeremylt ierr = CeedFree(&interp_c_to_f); CeedChk(ierr); 1974e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1975d99fa3c5SJeremy L Thompson } 1976d99fa3c5SJeremy L Thompson 1977d99fa3c5SJeremy L Thompson /** 1978d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1979d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1980d99fa3c5SJeremy L Thompson 1981d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1982d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1983d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1984d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1985d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 1986d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1987d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1988d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1989d99fa3c5SJeremy L Thompson 1990d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1991d99fa3c5SJeremy L Thompson 1992d99fa3c5SJeremy L Thompson @ref User 1993d99fa3c5SJeremy L Thompson **/ 1994d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, 1995d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1996d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, 1997d1d35e2fSjeremylt CeedOperator *op_prolong, CeedOperator *op_restrict) { 1998d99fa3c5SJeremy L Thompson int ierr; 1999d99fa3c5SJeremy L Thompson Ceed ceed; 2000d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2001d99fa3c5SJeremy L Thompson 2002d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2003d1d35e2fSjeremylt CeedBasis basis_fine; 2004d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2005d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2006d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2007d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2008d1d35e2fSjeremylt if (Q_f != Q_c) 2009d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2010e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2011e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2012d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2013d99fa3c5SJeremy L Thompson 2014d99fa3c5SJeremy L Thompson // Coarse to fine basis 2015d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c; 2016d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2017d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2018d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_1d_f); CeedChk(ierr); 2019d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2020d99fa3c5SJeremy L Thompson CeedChk(ierr); 2021d1d35e2fSjeremylt P_1d_c = dim == 1 ? num_nodes_c : 2022d1d35e2fSjeremylt dim == 2 ? sqrt(num_nodes_c) : 2023d1d35e2fSjeremylt cbrt(num_nodes_c); 2024d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2025d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_ref); CeedChk(ierr); 2026d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_weight); CeedChk(ierr); 2027d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f*P_1d_c*dim, &grad); CeedChk(ierr); 2028d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2029d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, 2030d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2031d99fa3c5SJeremy L Thompson CeedChk(ierr); 2032d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2033d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2034d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2035d99fa3c5SJeremy L Thompson 2036d99fa3c5SJeremy L Thompson // Core code 2037d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2038d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2039d1d35e2fSjeremylt op_prolong, op_restrict); 2040d99fa3c5SJeremy L Thompson CeedChk(ierr); 2041e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2042d99fa3c5SJeremy L Thompson } 2043d99fa3c5SJeremy L Thompson 2044d99fa3c5SJeremy L Thompson /** 2045d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 2046d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 2047d99fa3c5SJeremy L Thompson 2048d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 2049d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 2050d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 2051d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2052d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2053d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2054d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2055d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2056d99fa3c5SJeremy L Thompson 2057d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2058d99fa3c5SJeremy L Thompson 2059d99fa3c5SJeremy L Thompson @ref User 2060d99fa3c5SJeremy L Thompson **/ 2061d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, 2062d1d35e2fSjeremylt CeedVector p_mult_fine, 2063d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, 2064d1d35e2fSjeremylt CeedBasis basis_coarse, 2065d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, 2066d1d35e2fSjeremylt CeedOperator *op_coarse, 2067d1d35e2fSjeremylt CeedOperator *op_prolong, 2068d1d35e2fSjeremylt CeedOperator *op_restrict) { 2069d99fa3c5SJeremy L Thompson int ierr; 2070d99fa3c5SJeremy L Thompson Ceed ceed; 2071d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2072d99fa3c5SJeremy L Thompson 2073d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2074d1d35e2fSjeremylt CeedBasis basis_fine; 2075d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2076d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2077d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2078d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2079d1d35e2fSjeremylt if (Q_f != Q_c) 2080d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2081e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2082e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2083d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2084d99fa3c5SJeremy L Thompson 2085d99fa3c5SJeremy L Thompson // Coarse to fine basis 2086d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2087d1d35e2fSjeremylt ierr = CeedBasisGetTopology(basis_fine, &topo); CeedChk(ierr); 2088d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, num_nodes_f; 2089d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2090d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2091d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &num_nodes_f); CeedChk(ierr); 2092d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2093d99fa3c5SJeremy L Thompson CeedChk(ierr); 2094d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2095d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_ref); CeedChk(ierr); 2096d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_weight); CeedChk(ierr); 2097d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f*num_nodes_c*dim, &grad); CeedChk(ierr); 2098d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2099d1d35e2fSjeremylt ierr = CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, 2100d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2101d99fa3c5SJeremy L Thompson CeedChk(ierr); 2102d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2103d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2104d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2105d99fa3c5SJeremy L Thompson 2106d99fa3c5SJeremy L Thompson // Core code 2107d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2108d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2109d1d35e2fSjeremylt op_prolong, op_restrict); 2110d99fa3c5SJeremy L Thompson CeedChk(ierr); 2111e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2112d99fa3c5SJeremy L Thompson } 2113d99fa3c5SJeremy L Thompson 2114d99fa3c5SJeremy L Thompson /** 21153bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 21163bd813ffSjeremylt CeedOperator 21173bd813ffSjeremylt 21183bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 21193bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 21203bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 21213bd813ffSjeremylt M = V^T V, K = V^T S V. 21223bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 21233bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 21243bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 21253bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 21263bd813ffSjeremylt 21273bd813ffSjeremylt @param op CeedOperator to create element inverses 2128d1d35e2fSjeremylt @param[out] fdm_inv CeedOperator to apply the action of a FDM based inverse 21293bd813ffSjeremylt for each element 21303bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 21314cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 21323bd813ffSjeremylt 21333bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 21343bd813ffSjeremylt 21357a982d89SJeremy L. Thompson @ref Backend 21363bd813ffSjeremylt **/ 2137d1d35e2fSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdm_inv, 21383bd813ffSjeremylt CeedRequest *request) { 21393bd813ffSjeremylt int ierr; 2140e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 21413bd813ffSjeremylt 2142713f43c3Sjeremylt // Use backend version, if available 2143713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2144d1d35e2fSjeremylt ierr = op->CreateFDMElementInverse(op, fdm_inv, request); CeedChk(ierr); 2145713f43c3Sjeremylt } else { 2146713f43c3Sjeremylt // Fallback to reference Ceed 2147d1d35e2fSjeremylt if (!op->op_fallback) { 2148713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 21493bd813ffSjeremylt } 2150713f43c3Sjeremylt // Assemble 2151d1d35e2fSjeremylt ierr = op->op_fallback->CreateFDMElementInverse(op->op_fallback, fdm_inv, 21523bd813ffSjeremylt request); CeedChk(ierr); 21533bd813ffSjeremylt } 2154e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21553bd813ffSjeremylt } 21563bd813ffSjeremylt 21577a982d89SJeremy L. Thompson /** 21587a982d89SJeremy L. Thompson @brief View a CeedOperator 21597a982d89SJeremy L. Thompson 21607a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 21617a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 21627a982d89SJeremy L. Thompson 21637a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 21647a982d89SJeremy L. Thompson 21657a982d89SJeremy L. Thompson @ref User 21667a982d89SJeremy L. Thompson **/ 21677a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 21687a982d89SJeremy L. Thompson int ierr; 21697a982d89SJeremy L. Thompson 21707a982d89SJeremy L. Thompson if (op->composite) { 21717a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21727a982d89SJeremy L. Thompson 2173d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 21747a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 2175d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 21767a982d89SJeremy L. Thompson CeedChk(ierr); 21777a982d89SJeremy L. Thompson } 21787a982d89SJeremy L. Thompson } else { 21797a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21807a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21817a982d89SJeremy L. Thompson } 2182e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21837a982d89SJeremy L. Thompson } 21843bd813ffSjeremylt 21853bd813ffSjeremylt /** 21863bd813ffSjeremylt @brief Apply CeedOperator to a vector 2187d7b241e6Sjeremylt 2188d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2189d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2190d7b241e6Sjeremylt CeedOperatorSetField(). 2191d7b241e6Sjeremylt 2192d7b241e6Sjeremylt @param op CeedOperator to apply 21934cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 219434138859Sjeremylt there are no active inputs 2195b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21964cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 219734138859Sjeremylt active outputs 2198d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21994cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2200b11c1e72Sjeremylt 2201b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2202dfdf5a53Sjeremylt 22037a982d89SJeremy L. Thompson @ref User 2204b11c1e72Sjeremylt **/ 2205692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2206692c2638Sjeremylt CeedRequest *request) { 2207d7b241e6Sjeremylt int ierr; 2208e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2209d7b241e6Sjeremylt 2210d1d35e2fSjeremylt if (op->num_elem) { 2211250756a7Sjeremylt // Standard Operator 2212cae8b89aSjeremylt if (op->Apply) { 2213250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2214cae8b89aSjeremylt } else { 2215cae8b89aSjeremylt // Zero all output vectors 2216250756a7Sjeremylt CeedQFunction qf = op->qf; 2217d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 2218d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 2219cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2220cae8b89aSjeremylt vec = out; 2221cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2222cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2223cae8b89aSjeremylt } 2224cae8b89aSjeremylt } 2225250756a7Sjeremylt // Apply 2226250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2227250756a7Sjeremylt } 2228250756a7Sjeremylt } else if (op->composite) { 2229250756a7Sjeremylt // Composite Operator 2230250756a7Sjeremylt if (op->ApplyComposite) { 2231250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2232250756a7Sjeremylt } else { 2233d1d35e2fSjeremylt CeedInt num_suboperators; 2234d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2235d1d35e2fSjeremylt CeedOperator *sub_operators; 2236d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2237250756a7Sjeremylt 2238250756a7Sjeremylt // Zero all output vectors 2239250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2240cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2241cae8b89aSjeremylt } 2242d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2243d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 2244d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 2245250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2246250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2247250756a7Sjeremylt } 2248250756a7Sjeremylt } 2249250756a7Sjeremylt } 2250250756a7Sjeremylt // Apply 2251d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 2252d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 2253cae8b89aSjeremylt CeedChk(ierr); 2254cae8b89aSjeremylt } 2255cae8b89aSjeremylt } 2256250756a7Sjeremylt } 2257e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2258cae8b89aSjeremylt } 2259cae8b89aSjeremylt 2260cae8b89aSjeremylt /** 2261cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2262cae8b89aSjeremylt 2263cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2264cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2265cae8b89aSjeremylt CeedOperatorSetField(). 2266cae8b89aSjeremylt 2267cae8b89aSjeremylt @param op CeedOperator to apply 2268cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2269cae8b89aSjeremylt active inputs 2270cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2271cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2272cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22734cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2274cae8b89aSjeremylt 2275cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2276cae8b89aSjeremylt 22777a982d89SJeremy L. Thompson @ref User 2278cae8b89aSjeremylt **/ 2279cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2280cae8b89aSjeremylt CeedRequest *request) { 2281cae8b89aSjeremylt int ierr; 2282e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2283cae8b89aSjeremylt 2284d1d35e2fSjeremylt if (op->num_elem) { 2285250756a7Sjeremylt // Standard Operator 2286250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2287250756a7Sjeremylt } else if (op->composite) { 2288250756a7Sjeremylt // Composite Operator 2289250756a7Sjeremylt if (op->ApplyAddComposite) { 2290250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2291cae8b89aSjeremylt } else { 2292d1d35e2fSjeremylt CeedInt num_suboperators; 2293d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2294d1d35e2fSjeremylt CeedOperator *sub_operators; 2295d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2296250756a7Sjeremylt 2297d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2298d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 2299cae8b89aSjeremylt CeedChk(ierr); 23001d7d2407SJeremy L Thompson } 2301250756a7Sjeremylt } 2302250756a7Sjeremylt } 2303e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2304d7b241e6Sjeremylt } 2305d7b241e6Sjeremylt 2306d7b241e6Sjeremylt /** 2307b11c1e72Sjeremylt @brief Destroy a CeedOperator 2308d7b241e6Sjeremylt 2309d7b241e6Sjeremylt @param op CeedOperator to destroy 2310b11c1e72Sjeremylt 2311b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2312dfdf5a53Sjeremylt 23137a982d89SJeremy L. Thompson @ref User 2314b11c1e72Sjeremylt **/ 2315d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2316d7b241e6Sjeremylt int ierr; 2317d7b241e6Sjeremylt 2318d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 2319d7b241e6Sjeremylt if ((*op)->Destroy) { 2320d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2321d7b241e6Sjeremylt } 2322fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2323fe2413ffSjeremylt // Free fields 2324d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2325d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 2326d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 2327d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 232871352a93Sjeremylt CeedChk(ierr); 232915910d16Sjeremylt } 2330d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2331d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 233271352a93Sjeremylt } 2333d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 2334d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 2335d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 233671352a93Sjeremylt } 2337d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 2338d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 2339fe2413ffSjeremylt } 2340d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2341d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 2342d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 234371352a93Sjeremylt CeedChk(ierr); 2344d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2345d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 234671352a93Sjeremylt } 2347d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 2348d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 2349d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 235071352a93Sjeremylt } 2351d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 2352d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 2353fe2413ffSjeremylt } 2354d1d35e2fSjeremylt // Destroy sub_operators 2355d1d35e2fSjeremylt for (int i=0; i<(*op)->num_suboperators; i++) 2356d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 2357d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 235852d6035fSJeremy L Thompson } 2359e15f9bd0SJeremy L Thompson if ((*op)->qf) 2360e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2361d1d35e2fSjeremylt (*op)->qf->operators_set--; 2362e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2363d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2364e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2365e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2366d1d35e2fSjeremylt (*op)->dqf->operators_set--; 2367e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2368d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2369e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2370e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2371d1d35e2fSjeremylt (*op)->dqfT->operators_set--; 2372e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2373d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2374fe2413ffSjeremylt 23755107b09fSJeremy L Thompson // Destroy fallback 2376d1d35e2fSjeremylt if ((*op)->op_fallback) { 2377d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 2378d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 2379d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 2380d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 23815107b09fSJeremy L Thompson } 23825107b09fSJeremy L Thompson 2383d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 2384d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 2385d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 2386d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2387e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2388d7b241e6Sjeremylt } 2389d7b241e6Sjeremylt 2390d7b241e6Sjeremylt /// @} 2391