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); 11978464608Sjeremylt CeedChk(ierr); 120e1e9e29dSJed Brown } 121d1d35e2fSjeremylt if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) { 122e1e9e29dSJed Brown // LCOV_EXCL_START 123e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 124e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 125e1e9e29dSJed Brown "must be used together."); 126e1e9e29dSJed Brown // LCOV_EXCL_STOP 127e1e9e29dSJed Brown } 128e15f9bd0SJeremy L Thompson // Basis 129e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 130d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) 131*8229195eSjeremylt // LCOV_EXCL_START 132e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 133d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 134d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 135*8229195eSjeremylt // LCOV_EXCL_STOP 136d1d35e2fSjeremylt qf_field->field_name); 137e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 138d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 139d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 140e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 141e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 142d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 143d1d35e2fSjeremylt "has %d components, but Basis has %d components", 144d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 145d1d35e2fSjeremylt restr_num_comp, 146d1d35e2fSjeremylt num_comp); 147e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 148e15f9bd0SJeremy L Thompson } 149e15f9bd0SJeremy L Thompson } 150e15f9bd0SJeremy L Thompson // Field size 151d1d35e2fSjeremylt switch(eval_mode) { 152e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 153d1d35e2fSjeremylt if (size != restr_num_comp) 154e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 155e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 156e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 157d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 158d1d35e2fSjeremylt restr_num_comp); 159e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 160e15f9bd0SJeremy L Thompson break; 161e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 162d1d35e2fSjeremylt if (size != num_comp) 163e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 164e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 165e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 166d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 167d1d35e2fSjeremylt num_comp); 168e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 169e15f9bd0SJeremy L Thompson break; 170e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 171d1d35e2fSjeremylt if (size != num_comp * dim) 172e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 173e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 174d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 175d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 176d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 177d1d35e2fSjeremylt num_comp); 178e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 179e15f9bd0SJeremy L Thompson break; 180e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 181d1d35e2fSjeremylt // No additional checks required 182e15f9bd0SJeremy L Thompson break; 183e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 184e15f9bd0SJeremy L Thompson // Not implemented 185e15f9bd0SJeremy L Thompson break; 186e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 187e15f9bd0SJeremy L Thompson // Not implemented 188e15f9bd0SJeremy L Thompson break; 189e15f9bd0SJeremy L Thompson } 190e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1917a982d89SJeremy L. Thompson } 1927a982d89SJeremy L. Thompson 1937a982d89SJeremy L. Thompson /** 1947a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 1957a982d89SJeremy L. Thompson 1967a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 1977a982d89SJeremy L. Thompson 1987a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1997a982d89SJeremy L. Thompson 2007a982d89SJeremy L. Thompson @ref Developer 2017a982d89SJeremy L. Thompson **/ 202e2f04181SAndrew T. Barker static int CeedOperatorCheckReady(CeedOperator op) { 203e2f04181SAndrew T. Barker int ierr; 204e2f04181SAndrew T. Barker Ceed ceed; 205e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 206e2f04181SAndrew T. Barker 207d1d35e2fSjeremylt if (op->interface_setup) 208e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2097a982d89SJeremy L. Thompson 210e15f9bd0SJeremy L Thompson CeedQFunction qf = op->qf; 2117a982d89SJeremy L. Thompson if (op->composite) { 212d1d35e2fSjeremylt if (!op->num_suboperators) 2137a982d89SJeremy L. Thompson // LCOV_EXCL_START 214d1d35e2fSjeremylt return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 2157a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2167a982d89SJeremy L. Thompson } else { 217d1d35e2fSjeremylt if (op->num_fields == 0) 2187a982d89SJeremy L. Thompson // LCOV_EXCL_START 219e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 2207a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 221d1d35e2fSjeremylt if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 2227a982d89SJeremy L. Thompson // LCOV_EXCL_START 223e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 2247a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 225d1d35e2fSjeremylt if (!op->has_restriction) 2267a982d89SJeremy L. Thompson // LCOV_EXCL_START 227e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 228e15f9bd0SJeremy L Thompson "At least one restriction required"); 2297a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 230d1d35e2fSjeremylt if (op->num_qpts == 0) 2317a982d89SJeremy L. Thompson // LCOV_EXCL_START 232e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 233cd4dfc48Sjeremylt "At least one non-collocated basis is required " 234cd4dfc48Sjeremylt "or the number of quadrature points must be set"); 2357a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2367a982d89SJeremy L. Thompson } 2377a982d89SJeremy L. Thompson 238e15f9bd0SJeremy L Thompson // Flag as immutable and ready 239d1d35e2fSjeremylt op->interface_setup = true; 240e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 241e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 242d1d35e2fSjeremylt op->qf->operators_set++; 243e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 244e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 245e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 246d1d35e2fSjeremylt op->dqf->operators_set++; 247e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 248e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 249e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 250d1d35e2fSjeremylt op->dqfT->operators_set++; 251e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 252e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2537a982d89SJeremy L. Thompson } 2547a982d89SJeremy L. Thompson 2557a982d89SJeremy L. Thompson /** 2567a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2577a982d89SJeremy L. Thompson 2587a982d89SJeremy L. Thompson @param[in] field Operator field to view 259d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 260d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 2614c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 262d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 2637a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2647a982d89SJeremy L. Thompson 2657a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2667a982d89SJeremy L. Thompson 2677a982d89SJeremy L. Thompson @ref Utility 2687a982d89SJeremy L. Thompson **/ 2697a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 270d1d35e2fSjeremylt CeedQFunctionField qf_field, 271d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 2727a982d89SJeremy L. Thompson FILE *stream) { 2737a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 274d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 2757a982d89SJeremy L. Thompson 2767a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2777a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 278d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 2797a982d89SJeremy L. Thompson 2807a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2817a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2827a982d89SJeremy L. Thompson 2837a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2847a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2857a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2867a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 287e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2887a982d89SJeremy L. Thompson } 2897a982d89SJeremy L. Thompson 2907a982d89SJeremy L. Thompson /** 2917a982d89SJeremy L. Thompson @brief View a single CeedOperator 2927a982d89SJeremy L. Thompson 2937a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2947a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2957a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2967a982d89SJeremy L. Thompson 2977a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2987a982d89SJeremy L. Thompson 2997a982d89SJeremy L. Thompson @ref Utility 3007a982d89SJeremy L. Thompson **/ 3017a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 3027a982d89SJeremy L. Thompson int ierr; 3037a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 3047a982d89SJeremy L. Thompson 30578464608Sjeremylt CeedInt total_fields = 0; 30678464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 3077a982d89SJeremy L. Thompson 30878464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 30978464608Sjeremylt total_fields>1 ? "s" : ""); 3107a982d89SJeremy L. Thompson 311d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 312d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 313d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 314d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 3157a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 3167a982d89SJeremy L. Thompson } 3177a982d89SJeremy L. Thompson 318d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 319d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 320d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 321d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 3227a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 3237a982d89SJeremy L. Thompson } 324e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3257a982d89SJeremy L. Thompson } 3267a982d89SJeremy L. Thompson 327d99fa3c5SJeremy L Thompson /** 328e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 329e2f04181SAndrew T. Barker 330e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 331d1d35e2fSjeremylt @param[out] active_rstr ElemRestriction for active input vector 332e2f04181SAndrew T. Barker 333e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 334e2f04181SAndrew T. Barker 335e2f04181SAndrew T. Barker @ref Utility 336e2f04181SAndrew T. Barker **/ 337e2f04181SAndrew T. Barker static int CeedOperatorGetActiveElemRestriction(CeedOperator op, 338d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 339d1d35e2fSjeremylt *active_rstr = NULL; 340d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 341d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 342d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 343e2f04181SAndrew T. Barker break; 344e2f04181SAndrew T. Barker } 345e2f04181SAndrew T. Barker 346d1d35e2fSjeremylt if (!*active_rstr) { 347e2f04181SAndrew T. Barker // LCOV_EXCL_START 348e2f04181SAndrew T. Barker int ierr; 349e2f04181SAndrew T. Barker Ceed ceed; 350e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 351e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 352e2f04181SAndrew T. Barker "No active ElemRestriction found!"); 353e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 354e2f04181SAndrew T. Barker } 355e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 356e2f04181SAndrew T. Barker } 357e2f04181SAndrew T. Barker 358e2f04181SAndrew T. Barker /** 359d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 360d99fa3c5SJeremy L Thompson 361d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 362d1d35e2fSjeremylt @param[out] active_basis Basis for active input vector 363d99fa3c5SJeremy L Thompson 364d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 365d99fa3c5SJeremy L Thompson 366d99fa3c5SJeremy L Thompson @ ref Developer 367d99fa3c5SJeremy L Thompson **/ 368d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 369d1d35e2fSjeremylt CeedBasis *active_basis) { 370d1d35e2fSjeremylt *active_basis = NULL; 371d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 372d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 373d1d35e2fSjeremylt *active_basis = op->input_fields[i]->basis; 374d99fa3c5SJeremy L Thompson break; 375d99fa3c5SJeremy L Thompson } 376d99fa3c5SJeremy L Thompson 377d1d35e2fSjeremylt if (!*active_basis) { 378d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 379d99fa3c5SJeremy L Thompson int ierr; 380d99fa3c5SJeremy L Thompson Ceed ceed; 381d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 382e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 383d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 384d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 385d99fa3c5SJeremy L Thompson } 386e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 387d99fa3c5SJeremy L Thompson } 388d99fa3c5SJeremy L Thompson 389d99fa3c5SJeremy L Thompson /** 390d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 391d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 392d99fa3c5SJeremy L Thompson 393d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 394d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 395d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 396d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 397d1d35e2fSjeremylt @param[in] basis_c_to_f Basis for coarse to fine interpolation 398d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 399d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 400d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 401d99fa3c5SJeremy L Thompson 402d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 403d99fa3c5SJeremy L Thompson 404d99fa3c5SJeremy L Thompson @ref Developer 405d99fa3c5SJeremy L Thompson **/ 406d1d35e2fSjeremylt static int CeedOperatorMultigridLevel_Core(CeedOperator op_fine, 407d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 408d1d35e2fSjeremylt CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, 409d1d35e2fSjeremylt CeedOperator *op_restrict) { 410d99fa3c5SJeremy L Thompson int ierr; 411d99fa3c5SJeremy L Thompson Ceed ceed; 412d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 413d99fa3c5SJeremy L Thompson 414d99fa3c5SJeremy L Thompson // Check for composite operator 415d1d35e2fSjeremylt bool is_composite; 416d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op_fine, &is_composite); CeedChk(ierr); 417d1d35e2fSjeremylt if (is_composite) 418d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 419e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 420d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 421d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 422d99fa3c5SJeremy L Thompson 423d99fa3c5SJeremy L Thompson // Coarse Grid 424d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, op_fine->qf, op_fine->dqf, op_fine->dqfT, 425d1d35e2fSjeremylt op_coarse); CeedChk(ierr); 426d1d35e2fSjeremylt CeedElemRestriction rstr_fine = NULL; 427d99fa3c5SJeremy L Thompson // -- Clone input fields 428d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_input_fields; i++) { 429d1d35e2fSjeremylt if (op_fine->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 430d1d35e2fSjeremylt rstr_fine = op_fine->input_fields[i]->elem_restr; 431d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 432d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 433d99fa3c5SJeremy L Thompson CeedChk(ierr); 434d99fa3c5SJeremy L Thompson } else { 435d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 436d1d35e2fSjeremylt op_fine->input_fields[i]->elem_restr, 437d1d35e2fSjeremylt op_fine->input_fields[i]->basis, 438d1d35e2fSjeremylt op_fine->input_fields[i]->vec); CeedChk(ierr); 439d99fa3c5SJeremy L Thompson } 440d99fa3c5SJeremy L Thompson } 441d99fa3c5SJeremy L Thompson // -- Clone output fields 442d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_output_fields; i++) { 443d1d35e2fSjeremylt if (op_fine->output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 444d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 445d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 446d99fa3c5SJeremy L Thompson CeedChk(ierr); 447d99fa3c5SJeremy L Thompson } else { 448d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 449d1d35e2fSjeremylt op_fine->output_fields[i]->elem_restr, 450d1d35e2fSjeremylt op_fine->output_fields[i]->basis, 451d1d35e2fSjeremylt op_fine->output_fields[i]->vec); CeedChk(ierr); 452d99fa3c5SJeremy L Thompson } 453d99fa3c5SJeremy L Thompson } 454d99fa3c5SJeremy L Thompson 455d99fa3c5SJeremy L Thompson // Multiplicity vector 456d1d35e2fSjeremylt CeedVector mult_vec, mult_e_vec; 457d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(rstr_fine, &mult_vec, &mult_e_vec); 458d99fa3c5SJeremy L Thompson CeedChk(ierr); 459d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_e_vec, 0.0); CeedChk(ierr); 460d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_NOTRANSPOSE, p_mult_fine, 461d1d35e2fSjeremylt mult_e_vec, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 462d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_vec, 0.0); CeedChk(ierr); 463d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_TRANSPOSE, mult_e_vec, mult_vec, 464d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 465d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_e_vec); CeedChk(ierr); 466d1d35e2fSjeremylt ierr = CeedVectorReciprocal(mult_vec); CeedChk(ierr); 467d99fa3c5SJeremy L Thompson 468d99fa3c5SJeremy L Thompson // Restriction 469d1d35e2fSjeremylt CeedInt num_comp; 470d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_coarse, &num_comp); CeedChk(ierr); 471d1d35e2fSjeremylt CeedQFunction qf_restrict; 472d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_restrict); 473d99fa3c5SJeremy L Thompson CeedChk(ierr); 474d1d35e2fSjeremylt CeedInt *num_comp_r_data; 475d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_r_data); CeedChk(ierr); 476d1d35e2fSjeremylt num_comp_r_data[0] = num_comp; 477d1d35e2fSjeremylt CeedQFunctionContext ctx_r; 478d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_r); CeedChk(ierr); 479d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, 480d1d35e2fSjeremylt sizeof(*num_comp_r_data), num_comp_r_data); 481777ff853SJeremy L Thompson CeedChk(ierr); 482d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_restrict, ctx_r); CeedChk(ierr); 483d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_r); CeedChk(ierr); 484d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "input", num_comp, CEED_EVAL_NONE); 485d99fa3c5SJeremy L Thompson CeedChk(ierr); 486d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "scale", num_comp, CEED_EVAL_NONE); 487d99fa3c5SJeremy L Thompson CeedChk(ierr); 488d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_restrict, "output", num_comp, 489d1d35e2fSjeremylt CEED_EVAL_INTERP); CeedChk(ierr); 490d99fa3c5SJeremy L Thompson 491d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE, 492d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_restrict); 493d99fa3c5SJeremy L Thompson CeedChk(ierr); 494d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "input", rstr_fine, 495d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 496d99fa3c5SJeremy L Thompson CeedChk(ierr); 497d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "scale", rstr_fine, 498d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 499d99fa3c5SJeremy L Thompson CeedChk(ierr); 500d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "output", rstr_coarse, basis_c_to_f, 501d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 502d99fa3c5SJeremy L Thompson 503d99fa3c5SJeremy L Thompson // Prolongation 504d1d35e2fSjeremylt CeedQFunction qf_prolong; 505d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_prolong); 506d99fa3c5SJeremy L Thompson CeedChk(ierr); 507d1d35e2fSjeremylt CeedInt *num_comp_p_data; 508d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_p_data); CeedChk(ierr); 509d1d35e2fSjeremylt num_comp_p_data[0] = num_comp; 510d1d35e2fSjeremylt CeedQFunctionContext ctx_p; 511d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_p); CeedChk(ierr); 512d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_p, CEED_MEM_HOST, CEED_OWN_POINTER, 513d1d35e2fSjeremylt sizeof(*num_comp_p_data), num_comp_p_data); 514777ff853SJeremy L Thompson CeedChk(ierr); 515d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_prolong, ctx_p); CeedChk(ierr); 516d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_p); CeedChk(ierr); 517d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "input", num_comp, CEED_EVAL_INTERP); 518d99fa3c5SJeremy L Thompson CeedChk(ierr); 519d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "scale", num_comp, CEED_EVAL_NONE); 520d99fa3c5SJeremy L Thompson CeedChk(ierr); 521d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_prolong, "output", num_comp, CEED_EVAL_NONE); 522d99fa3c5SJeremy L Thompson CeedChk(ierr); 523d99fa3c5SJeremy L Thompson 524d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_prolong, CEED_QFUNCTION_NONE, 525d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_prolong); 526d99fa3c5SJeremy L Thompson CeedChk(ierr); 527d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "input", rstr_coarse, basis_c_to_f, 528d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 529d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "scale", rstr_fine, 530d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 531d99fa3c5SJeremy L Thompson CeedChk(ierr); 532d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "output", rstr_fine, 533d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 534d99fa3c5SJeremy L Thompson CeedChk(ierr); 535d99fa3c5SJeremy L Thompson 536d99fa3c5SJeremy L Thompson // Cleanup 537d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_vec); CeedChk(ierr); 538d1d35e2fSjeremylt ierr = CeedBasisDestroy(&basis_c_to_f); CeedChk(ierr); 539d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_restrict); CeedChk(ierr); 540d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_prolong); CeedChk(ierr); 541e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 542d99fa3c5SJeremy L Thompson } 543d99fa3c5SJeremy L Thompson 5447a982d89SJeremy L. Thompson /// @} 5457a982d89SJeremy L. Thompson 5467a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5477a982d89SJeremy L. Thompson /// CeedOperator Backend API 5487a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5497a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5507a982d89SJeremy L. Thompson /// @{ 5517a982d89SJeremy L. Thompson 5527a982d89SJeremy L. Thompson /** 5537a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5547a982d89SJeremy L. Thompson 5557a982d89SJeremy L. Thompson @param op CeedOperator 5567a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5577a982d89SJeremy L. Thompson 5587a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5597a982d89SJeremy L. Thompson 5607a982d89SJeremy L. Thompson @ref Backend 5617a982d89SJeremy L. Thompson **/ 5627a982d89SJeremy L. Thompson 5637a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5647a982d89SJeremy L. Thompson *ceed = op->ceed; 565e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5667a982d89SJeremy L. Thompson } 5677a982d89SJeremy L. Thompson 5687a982d89SJeremy L. Thompson /** 5697a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5707a982d89SJeremy L. Thompson 5717a982d89SJeremy L. Thompson @param op CeedOperator 572d1d35e2fSjeremylt @param[out] num_elem Variable to store number of elements 5737a982d89SJeremy L. Thompson 5747a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5757a982d89SJeremy L. Thompson 5767a982d89SJeremy L. Thompson @ref Backend 5777a982d89SJeremy L. Thompson **/ 5787a982d89SJeremy L. Thompson 579d1d35e2fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 5807a982d89SJeremy L. Thompson if (op->composite) 5817a982d89SJeremy L. Thompson // LCOV_EXCL_START 582e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 583e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5847a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5857a982d89SJeremy L. Thompson 586d1d35e2fSjeremylt *num_elem = op->num_elem; 587e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5887a982d89SJeremy L. Thompson } 5897a982d89SJeremy L. Thompson 5907a982d89SJeremy L. Thompson /** 5917a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5927a982d89SJeremy L. Thompson 5937a982d89SJeremy L. Thompson @param op CeedOperator 594d1d35e2fSjeremylt @param[out] num_qpts Variable to store vector number of quadrature points 5957a982d89SJeremy L. Thompson 5967a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5977a982d89SJeremy L. Thompson 5987a982d89SJeremy L. Thompson @ref Backend 5997a982d89SJeremy L. Thompson **/ 6007a982d89SJeremy L. Thompson 601d1d35e2fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 6027a982d89SJeremy L. Thompson if (op->composite) 6037a982d89SJeremy L. Thompson // LCOV_EXCL_START 604e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 605e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6067a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6077a982d89SJeremy L. Thompson 608d1d35e2fSjeremylt *num_qpts = op->num_qpts; 609e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6107a982d89SJeremy L. Thompson } 6117a982d89SJeremy L. Thompson 6127a982d89SJeremy L. Thompson /** 6137a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 6147a982d89SJeremy L. Thompson 6157a982d89SJeremy L. Thompson @param op CeedOperator 616d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 6177a982d89SJeremy L. Thompson 6187a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6197a982d89SJeremy L. Thompson 6207a982d89SJeremy L. Thompson @ref Backend 6217a982d89SJeremy L. Thompson **/ 6227a982d89SJeremy L. Thompson 623d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 6247a982d89SJeremy L. Thompson if (op->composite) 6257a982d89SJeremy L. Thompson // LCOV_EXCL_START 626e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 627e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6287a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6297a982d89SJeremy L. Thompson 630d1d35e2fSjeremylt *num_args = op->num_fields; 631e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6327a982d89SJeremy L. Thompson } 6337a982d89SJeremy L. Thompson 6347a982d89SJeremy L. Thompson /** 6357a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6367a982d89SJeremy L. Thompson 6377a982d89SJeremy L. Thompson @param op CeedOperator 638d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 6397a982d89SJeremy L. Thompson 6407a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6417a982d89SJeremy L. Thompson 6427a982d89SJeremy L. Thompson @ref Backend 6437a982d89SJeremy L. Thompson **/ 6447a982d89SJeremy L. Thompson 645d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 646d1d35e2fSjeremylt *is_setup_done = op->backend_setup; 647e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6487a982d89SJeremy L. Thompson } 6497a982d89SJeremy L. Thompson 6507a982d89SJeremy L. Thompson /** 6517a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6527a982d89SJeremy L. Thompson 6537a982d89SJeremy L. Thompson @param op CeedOperator 6547a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6577a982d89SJeremy L. Thompson 6587a982d89SJeremy L. Thompson @ref Backend 6597a982d89SJeremy L. Thompson **/ 6607a982d89SJeremy L. Thompson 6617a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6627a982d89SJeremy L. Thompson if (op->composite) 6637a982d89SJeremy L. Thompson // LCOV_EXCL_START 664e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 665e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6667a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6677a982d89SJeremy L. Thompson 6687a982d89SJeremy L. Thompson *qf = op->qf; 669e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6707a982d89SJeremy L. Thompson } 6717a982d89SJeremy L. Thompson 6727a982d89SJeremy L. Thompson /** 673c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 674c04a41a7SJeremy L Thompson 675c04a41a7SJeremy L Thompson @param op CeedOperator 676d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 677c04a41a7SJeremy L Thompson 678c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 679c04a41a7SJeremy L Thompson 680c04a41a7SJeremy L Thompson @ref Backend 681c04a41a7SJeremy L Thompson **/ 682c04a41a7SJeremy L Thompson 683d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 684d1d35e2fSjeremylt *is_composite = op->composite; 685e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 686c04a41a7SJeremy L Thompson } 687c04a41a7SJeremy L Thompson 688c04a41a7SJeremy L Thompson /** 689d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 6907a982d89SJeremy L. Thompson 6917a982d89SJeremy L. Thompson @param op CeedOperator 692d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 6937a982d89SJeremy L. Thompson 6947a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6957a982d89SJeremy L. Thompson 6967a982d89SJeremy L. Thompson @ref Backend 6977a982d89SJeremy L. Thompson **/ 6987a982d89SJeremy L. Thompson 699d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 7007a982d89SJeremy L. Thompson if (!op->composite) 7017a982d89SJeremy L. Thompson // LCOV_EXCL_START 702e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7037a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7047a982d89SJeremy L. Thompson 705d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 706e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7077a982d89SJeremy L. Thompson } 7087a982d89SJeremy L. Thompson 7097a982d89SJeremy L. Thompson /** 710d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 7117a982d89SJeremy L. Thompson 7127a982d89SJeremy L. Thompson @param op CeedOperator 713d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 7147a982d89SJeremy L. Thompson 7157a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7167a982d89SJeremy L. Thompson 7177a982d89SJeremy L. Thompson @ref Backend 7187a982d89SJeremy L. Thompson **/ 7197a982d89SJeremy L. Thompson 720d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 7217a982d89SJeremy L. Thompson if (!op->composite) 7227a982d89SJeremy L. Thompson // LCOV_EXCL_START 723e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7247a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7257a982d89SJeremy L. Thompson 726d1d35e2fSjeremylt *sub_operators = op->sub_operators; 727e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7287a982d89SJeremy L. Thompson } 7297a982d89SJeremy L. Thompson 7307a982d89SJeremy L. Thompson /** 7317a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7327a982d89SJeremy L. Thompson 7337a982d89SJeremy L. Thompson @param op CeedOperator 7347a982d89SJeremy L. Thompson @param[out] data Variable to store data 7357a982d89SJeremy L. Thompson 7367a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7377a982d89SJeremy L. Thompson 7387a982d89SJeremy L. Thompson @ref Backend 7397a982d89SJeremy L. Thompson **/ 7407a982d89SJeremy L. Thompson 741777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 742777ff853SJeremy L Thompson *(void **)data = op->data; 743e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7447a982d89SJeremy L. Thompson } 7457a982d89SJeremy L. Thompson 7467a982d89SJeremy L. Thompson /** 7477a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7487a982d89SJeremy L. Thompson 7497a982d89SJeremy L. Thompson @param[out] op CeedOperator 7507a982d89SJeremy L. Thompson @param data Data to set 7517a982d89SJeremy L. Thompson 7527a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7537a982d89SJeremy L. Thompson 7547a982d89SJeremy L. Thompson @ref Backend 7557a982d89SJeremy L. Thompson **/ 7567a982d89SJeremy L. Thompson 757777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 758777ff853SJeremy L Thompson op->data = data; 759e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7607a982d89SJeremy L. Thompson } 7617a982d89SJeremy L. Thompson 7627a982d89SJeremy L. Thompson /** 76334359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 76434359f16Sjeremylt 76534359f16Sjeremylt @param op CeedOperator to increment the reference counter 76634359f16Sjeremylt 76734359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 76834359f16Sjeremylt 76934359f16Sjeremylt @ref Backend 77034359f16Sjeremylt **/ 7719560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 77234359f16Sjeremylt op->ref_count++; 77334359f16Sjeremylt return CEED_ERROR_SUCCESS; 77434359f16Sjeremylt } 77534359f16Sjeremylt 77634359f16Sjeremylt /** 7777a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7787a982d89SJeremy L. Thompson 7797a982d89SJeremy L. Thompson @param op CeedOperator 7807a982d89SJeremy L. Thompson 7817a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7827a982d89SJeremy L. Thompson 7837a982d89SJeremy L. Thompson @ref Backend 7847a982d89SJeremy L. Thompson **/ 7857a982d89SJeremy L. Thompson 7867a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 787d1d35e2fSjeremylt op->backend_setup = true; 788e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7897a982d89SJeremy L. Thompson } 7907a982d89SJeremy L. Thompson 7917a982d89SJeremy L. Thompson /** 7927a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7937a982d89SJeremy L. Thompson 7947a982d89SJeremy L. Thompson @param op CeedOperator 795d1d35e2fSjeremylt @param[out] input_fields Variable to store input_fields 796d1d35e2fSjeremylt @param[out] output_fields Variable to store output_fields 7977a982d89SJeremy L. Thompson 7987a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7997a982d89SJeremy L. Thompson 8007a982d89SJeremy L. Thompson @ref Backend 8017a982d89SJeremy L. Thompson **/ 8027a982d89SJeremy L. Thompson 803d1d35e2fSjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **input_fields, 804d1d35e2fSjeremylt CeedOperatorField **output_fields) { 8057a982d89SJeremy L. Thompson if (op->composite) 8067a982d89SJeremy L. Thompson // LCOV_EXCL_START 807e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 808e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 8097a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 8107a982d89SJeremy L. Thompson 811d1d35e2fSjeremylt if (input_fields) *input_fields = op->input_fields; 812d1d35e2fSjeremylt if (output_fields) *output_fields = op->output_fields; 813e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8147a982d89SJeremy L. Thompson } 8157a982d89SJeremy L. Thompson 8167a982d89SJeremy L. Thompson /** 8177a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 8187a982d89SJeremy L. Thompson 819d1d35e2fSjeremylt @param op_field CeedOperatorField 8207a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 8217a982d89SJeremy L. Thompson 8227a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8237a982d89SJeremy L. Thompson 8247a982d89SJeremy L. Thompson @ref Backend 8257a982d89SJeremy L. Thompson **/ 8267a982d89SJeremy L. Thompson 827d1d35e2fSjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 8287a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 829d1d35e2fSjeremylt *rstr = op_field->elem_restr; 830e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8317a982d89SJeremy L. Thompson } 8327a982d89SJeremy L. Thompson 8337a982d89SJeremy L. Thompson /** 8347a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8357a982d89SJeremy L. Thompson 836d1d35e2fSjeremylt @param op_field CeedOperatorField 8377a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8387a982d89SJeremy L. Thompson 8397a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8407a982d89SJeremy L. Thompson 8417a982d89SJeremy L. Thompson @ref Backend 8427a982d89SJeremy L. Thompson **/ 8437a982d89SJeremy L. Thompson 844d1d35e2fSjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 845d1d35e2fSjeremylt *basis = op_field->basis; 846e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8477a982d89SJeremy L. Thompson } 8487a982d89SJeremy L. Thompson 8497a982d89SJeremy L. Thompson /** 8507a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8517a982d89SJeremy L. Thompson 852d1d35e2fSjeremylt @param op_field CeedOperatorField 8537a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8547a982d89SJeremy L. Thompson 8557a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8567a982d89SJeremy L. Thompson 8577a982d89SJeremy L. Thompson @ref Backend 8587a982d89SJeremy L. Thompson **/ 8597a982d89SJeremy L. Thompson 860d1d35e2fSjeremylt int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 861d1d35e2fSjeremylt *vec = op_field->vec; 862e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8637a982d89SJeremy L. Thompson } 8647a982d89SJeremy L. Thompson 8657a982d89SJeremy L. Thompson /// @} 8667a982d89SJeremy L. Thompson 8677a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8687a982d89SJeremy L. Thompson /// CeedOperator Public API 8697a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8707a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 871dfdf5a53Sjeremylt /// @{ 872d7b241e6Sjeremylt 873d7b241e6Sjeremylt /** 8740219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8750219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8760219ea01SJeremy L Thompson \ref CeedOperatorSetField. 877d7b241e6Sjeremylt 878b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 879d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 88034138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8814cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 882d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8834cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 884b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 885b11c1e72Sjeremylt CeedOperator will be stored 886b11c1e72Sjeremylt 887b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 888dfdf5a53Sjeremylt 8897a982d89SJeremy L. Thompson @ref User 890d7b241e6Sjeremylt */ 891d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 892d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 893d7b241e6Sjeremylt int ierr; 894d7b241e6Sjeremylt 8955fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8965fe0d4faSjeremylt Ceed delegate; 897aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8985fe0d4faSjeremylt 8995fe0d4faSjeremylt if (!delegate) 900c042f62fSJeremy L Thompson // LCOV_EXCL_START 901e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 902e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 903c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9045fe0d4faSjeremylt 9055fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 906e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9075fe0d4faSjeremylt } 9085fe0d4faSjeremylt 909b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 910b3b7035fSJeremy L Thompson // LCOV_EXCL_START 911e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 912e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 913b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 914d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 915d7b241e6Sjeremylt (*op)->ceed = ceed; 9169560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 917d1d35e2fSjeremylt (*op)->ref_count = 1; 918d7b241e6Sjeremylt (*op)->qf = qf; 9199560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 920442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 921d7b241e6Sjeremylt (*op)->dqf = dqf; 9229560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 923442e7f0bSjeremylt } 924442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 925d7b241e6Sjeremylt (*op)->dqfT = dqfT; 9269560d06aSjeremylt ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 927442e7f0bSjeremylt } 928d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr); 929d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr); 930d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 931e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 932d7b241e6Sjeremylt } 933d7b241e6Sjeremylt 934d7b241e6Sjeremylt /** 93552d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 93652d6035fSJeremy L Thompson 93752d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 93852d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 93952d6035fSJeremy L Thompson Composite CeedOperator will be stored 94052d6035fSJeremy L Thompson 94152d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 94252d6035fSJeremy L Thompson 9437a982d89SJeremy L. Thompson @ref User 94452d6035fSJeremy L Thompson */ 94552d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 94652d6035fSJeremy L Thompson int ierr; 94752d6035fSJeremy L Thompson 94852d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 94952d6035fSJeremy L Thompson Ceed delegate; 950aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 95152d6035fSJeremy L Thompson 952250756a7Sjeremylt if (delegate) { 95352d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 954e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 95552d6035fSJeremy L Thompson } 956250756a7Sjeremylt } 95752d6035fSJeremy L Thompson 95852d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 95952d6035fSJeremy L Thompson (*op)->ceed = ceed; 9609560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 96152d6035fSJeremy L Thompson (*op)->composite = true; 962d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr); 963250756a7Sjeremylt 964250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 96552d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 966250756a7Sjeremylt } 967e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 96852d6035fSJeremy L Thompson } 96952d6035fSJeremy L Thompson 97052d6035fSJeremy L Thompson /** 9719560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 9729560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 9739560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 9749560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 9759560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 9769560d06aSjeremylt reference to this CeedOperator. 9779560d06aSjeremylt 9789560d06aSjeremylt @param op CeedOperator to copy reference to 9799560d06aSjeremylt @param[out] op_copy Variable to store copied reference 9809560d06aSjeremylt 9819560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 9829560d06aSjeremylt 9839560d06aSjeremylt @ref User 9849560d06aSjeremylt **/ 9859560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 9869560d06aSjeremylt int ierr; 9879560d06aSjeremylt 9889560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 9899560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 9909560d06aSjeremylt *op_copy = op; 9919560d06aSjeremylt return CEED_ERROR_SUCCESS; 9929560d06aSjeremylt } 9939560d06aSjeremylt 9949560d06aSjeremylt /** 995b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 996d7b241e6Sjeremylt 997d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 998d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 999d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 1000d7b241e6Sjeremylt 1001d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 1002d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 1003d7b241e6Sjeremylt input and at most one active output. 1004d7b241e6Sjeremylt 10058c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 1006d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 10078795c945Sjeremylt CeedQFunction) 1008b11c1e72Sjeremylt @param r CeedElemRestriction 10094cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 1010b11c1e72Sjeremylt if collocated with quadrature points 10114cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 10124cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 10134cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 1014b11c1e72Sjeremylt 1015b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1016dfdf5a53Sjeremylt 10177a982d89SJeremy L. Thompson @ref User 1018b11c1e72Sjeremylt **/ 1019d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 1020a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 1021d7b241e6Sjeremylt int ierr; 102252d6035fSJeremy L Thompson if (op->composite) 1023c042f62fSJeremy L Thompson // LCOV_EXCL_START 1024e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1025e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 1026c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10278b067b84SJed Brown if (!r) 1028c042f62fSJeremy L Thompson // LCOV_EXCL_START 1029e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1030c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 1031d1d35e2fSjeremylt field_name); 1032c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10338b067b84SJed Brown if (!b) 1034c042f62fSJeremy L Thompson // LCOV_EXCL_START 1035e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1036e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 1037d1d35e2fSjeremylt field_name); 1038c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10398b067b84SJed Brown if (!v) 1040c042f62fSJeremy L Thompson // LCOV_EXCL_START 1041e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1042e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 1043d1d35e2fSjeremylt field_name); 1044c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 104552d6035fSJeremy L Thompson 1046d1d35e2fSjeremylt CeedInt num_elem; 1047d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 1048d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 1049d1d35e2fSjeremylt op->num_elem != num_elem) 1050c042f62fSJeremy L Thompson // LCOV_EXCL_START 1051e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10521d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1053d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 1054c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1055d7b241e6Sjeremylt 105678464608Sjeremylt CeedInt num_qpts = 0; 1057e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1058d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 1059d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 1060c042f62fSJeremy L Thompson // LCOV_EXCL_START 1061e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1062e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 1063d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 1064d1d35e2fSjeremylt op->num_qpts); 1065c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1066d7b241e6Sjeremylt } 1067d1d35e2fSjeremylt CeedQFunctionField qf_field; 1068d1d35e2fSjeremylt CeedOperatorField *op_field; 1069d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 1070d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 1071d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 1072d1d35e2fSjeremylt op_field = &op->input_fields[i]; 1073d7b241e6Sjeremylt goto found; 1074d7b241e6Sjeremylt } 1075d7b241e6Sjeremylt } 1076d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 1077d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 1078d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 1079d1d35e2fSjeremylt op_field = &op->output_fields[i]; 1080d7b241e6Sjeremylt goto found; 1081d7b241e6Sjeremylt } 1082d7b241e6Sjeremylt } 1083c042f62fSJeremy L Thompson // LCOV_EXCL_START 1084e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1085e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1086d1d35e2fSjeremylt field_name); 1087c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1088d7b241e6Sjeremylt found: 1089d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 1090d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 1091e15f9bd0SJeremy L Thompson 1092d1d35e2fSjeremylt (*op_field)->vec = v; 1093e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 10949560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 1095e15f9bd0SJeremy L Thompson } 1096e15f9bd0SJeremy L Thompson 1097d1d35e2fSjeremylt (*op_field)->elem_restr = r; 10989560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 1099e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1100d1d35e2fSjeremylt op->num_elem = num_elem; 1101d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 1102e15f9bd0SJeremy L Thompson } 1103d99fa3c5SJeremy L Thompson 1104d1d35e2fSjeremylt (*op_field)->basis = b; 1105e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1106cd4dfc48Sjeremylt if (!op->num_qpts) { 1107cd4dfc48Sjeremylt ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 1108cd4dfc48Sjeremylt } 11099560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 1110e15f9bd0SJeremy L Thompson } 1111e15f9bd0SJeremy L Thompson 1112d1d35e2fSjeremylt op->num_fields += 1; 1113d1d35e2fSjeremylt size_t len = strlen(field_name); 1114d99fa3c5SJeremy L Thompson char *tmp; 1115d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1116d1d35e2fSjeremylt memcpy(tmp, field_name, len+1); 1117d1d35e2fSjeremylt (*op_field)->field_name = tmp; 1118e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1119d7b241e6Sjeremylt } 1120d7b241e6Sjeremylt 1121d7b241e6Sjeremylt /** 112252d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1123288c0443SJeremy L Thompson 1124d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 1125d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 112652d6035fSJeremy L Thompson 112752d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 112852d6035fSJeremy L Thompson 11297a982d89SJeremy L. Thompson @ref User 113052d6035fSJeremy L Thompson */ 1131d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 1132d1d35e2fSjeremylt CeedOperator sub_op) { 113334359f16Sjeremylt int ierr; 113434359f16Sjeremylt 1135d1d35e2fSjeremylt if (!composite_op->composite) 1136c042f62fSJeremy L Thompson // LCOV_EXCL_START 1137d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 1138e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1139c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 114052d6035fSJeremy L Thompson 1141d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 1142c042f62fSJeremy L Thompson // LCOV_EXCL_START 1143d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 1144d1d35e2fSjeremylt "Cannot add additional sub_operators"); 1145c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 114652d6035fSJeremy L Thompson 1147d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 11489560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 1149d1d35e2fSjeremylt composite_op->num_suboperators++; 1150e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 115152d6035fSJeremy L Thompson } 115252d6035fSJeremy L Thompson 115352d6035fSJeremy L Thompson /** 11541d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11551d102b48SJeremy L Thompson 11561d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11571d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11581d102b48SJeremy L Thompson The vector 'assembled' is of shape 11591d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11601d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11611d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11621d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11634cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11641d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11651d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11661d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11671d102b48SJeremy L Thompson 11681d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11691d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11701d102b48SJeremy L Thompson quadrature points 11711d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11721d102b48SJeremy L Thompson CeedQFunction 11731d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11744cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11751d102b48SJeremy L Thompson 11761d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11771d102b48SJeremy L Thompson 11787a982d89SJeremy L. Thompson @ref User 11791d102b48SJeremy L Thompson **/ 118080ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11817f823360Sjeremylt CeedElemRestriction *rstr, 11827f823360Sjeremylt CeedRequest *request) { 11831d102b48SJeremy L Thompson int ierr; 1184e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11851d102b48SJeremy L Thompson 11867172caadSjeremylt // Backend version 118780ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1188e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11895107b09fSJeremy L Thompson } else { 11905107b09fSJeremy L Thompson // Fallback to reference Ceed 1191d1d35e2fSjeremylt if (!op->op_fallback) { 11925107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11935107b09fSJeremy L Thompson } 11945107b09fSJeremy L Thompson // Assemble 1195d1d35e2fSjeremylt return CeedOperatorLinearAssembleQFunction(op->op_fallback, assembled, 1196e2f04181SAndrew T. Barker rstr, request); 11975107b09fSJeremy L Thompson } 11981d102b48SJeremy L Thompson } 11991d102b48SJeremy L Thompson 12001d102b48SJeremy L Thompson /** 1201d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1202b7ec98d8SJeremy L Thompson 12039e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1204b7ec98d8SJeremy L Thompson 1205c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1206c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1207d965c7a7SJeremy L Thompson 1208b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1209b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1210b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12114cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1212b7ec98d8SJeremy L Thompson 1213b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1214b7ec98d8SJeremy L Thompson 12157a982d89SJeremy L. Thompson @ref User 1216b7ec98d8SJeremy L Thompson **/ 12172bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 12187f823360Sjeremylt CeedRequest *request) { 1219b7ec98d8SJeremy L Thompson int ierr; 1220e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1221b7ec98d8SJeremy L Thompson 1222b7ec98d8SJeremy L Thompson // Use backend version, if available 122380ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1224e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 12259e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 12269e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12279e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 12289e9210b8SJeremy L Thompson } else { 12299e9210b8SJeremy L Thompson // Fallback to reference Ceed 1230d1d35e2fSjeremylt if (!op->op_fallback) { 12319e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 12329e9210b8SJeremy L Thompson } 12339e9210b8SJeremy L Thompson // Assemble 1234d1d35e2fSjeremylt return CeedOperatorLinearAssembleDiagonal(op->op_fallback, assembled, 1235e2f04181SAndrew T. Barker request); 12369e9210b8SJeremy L Thompson } 12379e9210b8SJeremy L Thompson } 12389e9210b8SJeremy L Thompson 12399e9210b8SJeremy L Thompson /** 12409e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 12419e9210b8SJeremy L Thompson 12429e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 12439e9210b8SJeremy L Thompson 12449e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12459e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12469e9210b8SJeremy L Thompson 12479e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12489e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 12499e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12509e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 12519e9210b8SJeremy L Thompson 12529e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12539e9210b8SJeremy L Thompson 12549e9210b8SJeremy L Thompson @ref User 12559e9210b8SJeremy L Thompson **/ 12569e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12579e9210b8SJeremy L Thompson CeedRequest *request) { 12589e9210b8SJeremy L Thompson int ierr; 1259e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12609e9210b8SJeremy L Thompson 12619e9210b8SJeremy L Thompson // Use backend version, if available 12629e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1263e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12647172caadSjeremylt } else { 12657172caadSjeremylt // Fallback to reference Ceed 1266d1d35e2fSjeremylt if (!op->op_fallback) { 12677172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1268b7ec98d8SJeremy L Thompson } 12697172caadSjeremylt // Assemble 1270d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddDiagonal(op->op_fallback, assembled, 1271e2f04181SAndrew T. Barker request); 1272b7ec98d8SJeremy L Thompson } 1273b7ec98d8SJeremy L Thompson } 1274b7ec98d8SJeremy L Thompson 1275b7ec98d8SJeremy L Thompson /** 1276d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1277d965c7a7SJeremy L Thompson 12789e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1279d965c7a7SJeremy L Thompson CeedOperator. 1280d965c7a7SJeremy L Thompson 1281c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1282c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1283d965c7a7SJeremy L Thompson 1284d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1285d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1286d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1287d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 1288d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1289d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1290d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1291d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1292d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1293d965c7a7SJeremy L Thompson 1294d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1295d965c7a7SJeremy L Thompson 1296d965c7a7SJeremy L Thompson @ref User 1297d965c7a7SJeremy L Thompson **/ 129880ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12992bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1300d965c7a7SJeremy L Thompson int ierr; 1301e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1302d965c7a7SJeremy L Thompson 1303d965c7a7SJeremy L Thompson // Use backend version, if available 130480ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1305e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 13069e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 13079e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 13089e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 13099e9210b8SJeremy L Thompson request); 1310d965c7a7SJeremy L Thompson } else { 1311d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1312d1d35e2fSjeremylt if (!op->op_fallback) { 1313d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1314d965c7a7SJeremy L Thompson } 1315d965c7a7SJeremy L Thompson // Assemble 1316d1d35e2fSjeremylt return CeedOperatorLinearAssemblePointBlockDiagonal(op->op_fallback, 1317e2f04181SAndrew T. Barker assembled, request); 13189e9210b8SJeremy L Thompson } 13199e9210b8SJeremy L Thompson } 13209e9210b8SJeremy L Thompson 13219e9210b8SJeremy L Thompson /** 13229e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 13239e9210b8SJeremy L Thompson 13249e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 13259e9210b8SJeremy L Thompson CeedOperator. 13269e9210b8SJeremy L Thompson 13279e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 13289e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 13299e9210b8SJeremy L Thompson 13309e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 13319e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 13329e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 1333d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 13349e9210b8SJeremy L Thompson of this vector are derived from the active vector 13359e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 13369e9210b8SJeremy L Thompson [nodes, component out, component in]. 13379e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 13389e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 13399e9210b8SJeremy L Thompson 13409e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13419e9210b8SJeremy L Thompson 13429e9210b8SJeremy L Thompson @ref User 13439e9210b8SJeremy L Thompson **/ 13449e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 13459e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 13469e9210b8SJeremy L Thompson int ierr; 1347e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 13489e9210b8SJeremy L Thompson 13499e9210b8SJeremy L Thompson // Use backend version, if available 13509e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1351e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 13529e9210b8SJeremy L Thompson } else { 13539e9210b8SJeremy L Thompson // Fallback to reference Ceed 1354d1d35e2fSjeremylt if (!op->op_fallback) { 13559e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13569e9210b8SJeremy L Thompson } 13579e9210b8SJeremy L Thompson // Assemble 1358d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->op_fallback, 1359e2f04181SAndrew T. Barker assembled, request); 1360d965c7a7SJeremy L Thompson } 1361e2f04181SAndrew T. Barker } 1362e2f04181SAndrew T. Barker 1363e2f04181SAndrew T. Barker /** 1364e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1365e2f04181SAndrew T. Barker 1366e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1367e2f04181SAndrew T. Barker 1368e2f04181SAndrew T. Barker @ref Developer 1369e2f04181SAndrew T. Barker **/ 1370e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1371e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1372e2f04181SAndrew T. Barker int ierr; 1373e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1374e2f04181SAndrew T. Barker if (op->composite) 1375e2f04181SAndrew T. Barker // LCOV_EXCL_START 1376e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1377e2f04181SAndrew T. Barker "Composite operator not supported"); 1378e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1379e2f04181SAndrew T. Barker 1380d1d35e2fSjeremylt CeedElemRestriction rstr_in; 1381d1d35e2fSjeremylt ierr = CeedOperatorGetActiveElemRestriction(op, &rstr_in); CeedChk(ierr); 1382d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_nodes, num_comp; 1383d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1384d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1385d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr_in, &num_nodes); CeedChk(ierr); 1386d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1387e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1388d1d35e2fSjeremylt ierr = CeedElemRestrictionGetELayout(rstr_in, &layout_er); CeedChk(ierr); 1389e2f04181SAndrew T. Barker 1390d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1391e2f04181SAndrew T. Barker 1392e2f04181SAndrew T. Barker // Determine elem_dof relation 1393e2f04181SAndrew T. Barker CeedVector index_vec; 1394d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_nodes, &index_vec); CeedChk(ierr); 1395e2f04181SAndrew T. Barker CeedScalar *array; 1396e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1397d1d35e2fSjeremylt for (CeedInt i = 0; i < num_nodes; ++i) { 1398e2f04181SAndrew T. Barker array[i] = i; 1399e2f04181SAndrew T. Barker } 1400e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1401e2f04181SAndrew T. Barker CeedVector elem_dof; 1402d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_elem * elem_size * num_comp, &elem_dof); 1403e2f04181SAndrew T. Barker CeedChk(ierr); 1404e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1405d1d35e2fSjeremylt CeedElemRestrictionApply(rstr_in, CEED_NOTRANSPOSE, index_vec, 1406e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1407e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1408e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1409e2f04181SAndrew T. Barker CeedChk(ierr); 1410e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1411e2f04181SAndrew T. Barker 1412e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1413e2f04181SAndrew T. Barker CeedInt count = 0; 1414d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1415d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1416d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1417d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1418d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1419d1d35e2fSjeremylt const CeedInt elem_dof_index_row = (i)*layout_er[0] + 1420d1d35e2fSjeremylt (comp_out)*layout_er[1] + e*layout_er[2]; 1421d1d35e2fSjeremylt const CeedInt elem_dof_index_col = (j)*layout_er[0] + 1422d1d35e2fSjeremylt (comp_in)*layout_er[1] + e*layout_er[2]; 1423e2f04181SAndrew T. Barker 1424d1d35e2fSjeremylt const CeedInt row = elem_dof_a[elem_dof_index_row]; 1425d1d35e2fSjeremylt const CeedInt col = elem_dof_a[elem_dof_index_col]; 1426e2f04181SAndrew T. Barker 1427e2f04181SAndrew T. Barker rows[offset + count] = row; 1428e2f04181SAndrew T. Barker cols[offset + count] = col; 1429e2f04181SAndrew T. Barker count++; 1430e2f04181SAndrew T. Barker } 1431e2f04181SAndrew T. Barker } 1432e2f04181SAndrew T. Barker } 1433e2f04181SAndrew T. Barker } 1434e2f04181SAndrew T. Barker } 1435d1d35e2fSjeremylt if (count != local_num_entries) 1436e2f04181SAndrew T. Barker // LCOV_EXCL_START 1437e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1438e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1439e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1440e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1441e2f04181SAndrew T. Barker 1442e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1443e2f04181SAndrew T. Barker } 1444e2f04181SAndrew T. Barker 1445e2f04181SAndrew T. Barker /** 1446e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1447e2f04181SAndrew T. Barker 1448e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1449e2f04181SAndrew T. Barker 1450e2f04181SAndrew T. Barker @ref Developer 1451e2f04181SAndrew T. Barker **/ 1452e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1453e2f04181SAndrew T. Barker CeedVector values) { 1454e2f04181SAndrew T. Barker int ierr; 1455e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1456e2f04181SAndrew T. Barker if (op->composite) 1457e2f04181SAndrew T. Barker // LCOV_EXCL_START 1458e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1459e2f04181SAndrew T. Barker "Composite operator not supported"); 1460e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1461e2f04181SAndrew T. Barker 1462e2f04181SAndrew T. Barker // Assemble QFunction 1463e2f04181SAndrew T. Barker CeedQFunction qf; 1464e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1465d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 1466d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 1467e2f04181SAndrew T. Barker CeedChk(ierr); 1468d1d35e2fSjeremylt CeedVector assembled_qf; 1469e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1470e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1471d1d35e2fSjeremylt op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1472e2f04181SAndrew T. Barker 1473d1d35e2fSjeremylt CeedInt qf_length; 1474d1d35e2fSjeremylt ierr = CeedVectorGetLength(assembled_qf, &qf_length); CeedChk(ierr); 1475e2f04181SAndrew T. Barker 1476e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1477e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1478e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1479e2f04181SAndrew T. Barker 1480e2f04181SAndrew T. Barker // Determine active input basis 1481d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1482d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChk(ierr); 1483d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, dim = 1; 1484d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 1485d1d35e2fSjeremylt CeedBasis basis_in = NULL; 1486d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 1487d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1488e2f04181SAndrew T. Barker CeedVector vec; 1489e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1490e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1491d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(input_fields[i], &basis_in); 1492e2f04181SAndrew T. Barker CeedChk(ierr); 1493d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChk(ierr); 1494d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in); 1495e2f04181SAndrew T. Barker CeedChk(ierr); 1496d1d35e2fSjeremylt CeedEvalMode eval_mode; 1497d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1498e2f04181SAndrew T. Barker CeedChk(ierr); 1499d1d35e2fSjeremylt switch (eval_mode) { 1500e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1501e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1502d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChk(ierr); 1503d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 1504d1d35e2fSjeremylt num_eval_mode_in += 1; 1505e2f04181SAndrew T. Barker break; 1506e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1507d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChk(ierr); 1508e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1509d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 1510e2f04181SAndrew T. Barker } 1511d1d35e2fSjeremylt num_eval_mode_in += dim; 1512e2f04181SAndrew T. Barker break; 1513e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1514e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1515e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1516e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1517e2f04181SAndrew T. Barker } 1518e2f04181SAndrew T. Barker } 1519e2f04181SAndrew T. Barker } 1520e2f04181SAndrew T. Barker 1521e2f04181SAndrew T. Barker // Determine active output basis 1522d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChk(ierr); 1523d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 1524d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 1525d1d35e2fSjeremylt CeedBasis basis_out = NULL; 1526d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 1527d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 1528e2f04181SAndrew T. Barker CeedVector vec; 1529e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1530e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1531d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(output_fields[i], &basis_out); 1532e2f04181SAndrew T. Barker CeedChk(ierr); 1533d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out); 1534e2f04181SAndrew T. Barker CeedChk(ierr); 1535d1d35e2fSjeremylt CeedEvalMode eval_mode; 1536d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1537e2f04181SAndrew T. Barker CeedChk(ierr); 1538d1d35e2fSjeremylt switch (eval_mode) { 1539e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1540e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1541d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChk(ierr); 1542d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 1543d1d35e2fSjeremylt num_eval_mode_out += 1; 1544e2f04181SAndrew T. Barker break; 1545e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1546d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); CeedChk(ierr); 1547e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1548d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 1549e2f04181SAndrew T. Barker } 1550d1d35e2fSjeremylt num_eval_mode_out += dim; 1551e2f04181SAndrew T. Barker break; 1552e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1553e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1554e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1555e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1556e2f04181SAndrew T. Barker } 1557e2f04181SAndrew T. Barker } 1558e2f04181SAndrew T. Barker } 1559e2f04181SAndrew T. Barker 156078464608Sjeremylt if (num_eval_mode_in == 0 || num_eval_mode_out == 0) 156178464608Sjeremylt // LCOV_EXCL_START 156278464608Sjeremylt return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 156378464608Sjeremylt "Cannot assemble operator with out inputs/outputs"); 156478464608Sjeremylt // LCOV_EXCL_STOP 156578464608Sjeremylt 1566d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_qpts, num_comp; 1567d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1568d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1569d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1570d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); CeedChk(ierr); 1571e2f04181SAndrew T. Barker 1572d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1573e2f04181SAndrew T. Barker 1574e2f04181SAndrew T. Barker // loop over elements and put in data structure 1575d1d35e2fSjeremylt const CeedScalar *interp_in, *grad_in; 1576d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChk(ierr); 1577d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChk(ierr); 1578e2f04181SAndrew T. Barker 1579d1d35e2fSjeremylt const CeedScalar *assembled_qf_array; 1580d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 1581e2f04181SAndrew T. Barker CeedChk(ierr); 1582e2f04181SAndrew T. Barker 1583e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1584e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1585e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1586e2f04181SAndrew T. Barker 1587d1d35e2fSjeremylt // we store B_mat_in, B_mat_out, BTD, elem_mat in row-major order 1588d1d35e2fSjeremylt CeedScalar B_mat_in[(num_qpts * num_eval_mode_in) * elem_size]; 1589d1d35e2fSjeremylt CeedScalar B_mat_out[(num_qpts * num_eval_mode_out) * elem_size]; 1590d1d35e2fSjeremylt CeedScalar D_mat[num_eval_mode_out * num_eval_mode_in * 1591d1d35e2fSjeremylt num_qpts]; // logically 3-tensor 1592d1d35e2fSjeremylt CeedScalar BTD[elem_size * num_qpts*num_eval_mode_in]; 1593d1d35e2fSjeremylt CeedScalar elem_mat[elem_size * elem_size]; 1594e2f04181SAndrew T. Barker int count = 0; 1595e2f04181SAndrew T. Barker CeedScalar *vals; 1596e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1597d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1598d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1599d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1600d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_in) * elem_size; ++ell) { 1601d1d35e2fSjeremylt B_mat_in[ell] = 0.0; 1602e2f04181SAndrew T. Barker } 1603d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_out) * elem_size; ++ell) { 1604d1d35e2fSjeremylt B_mat_out[ell] = 0.0; 1605e2f04181SAndrew T. Barker } 1606e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1607d1d35e2fSjeremylt for (int ell = 0; ell < num_eval_mode_in*num_eval_mode_out*num_qpts; ++ell) { 1608d1d35e2fSjeremylt D_mat[ell] = 0.0; 1609e2f04181SAndrew T. Barker } 1610e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1611d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*elem_size; ++ell) { 1612e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1613e2f04181SAndrew T. Barker } 1614d1d35e2fSjeremylt for (int q = 0; q < num_qpts; ++q) { 1615d1d35e2fSjeremylt for (int n = 0; n < elem_size; ++n) { 1616d1d35e2fSjeremylt CeedInt d_in = -1; 1617d1d35e2fSjeremylt for (int e_in = 0; e_in < num_eval_mode_in; ++e_in) { 1618d1d35e2fSjeremylt const int qq = num_eval_mode_in*q; 1619d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_INTERP) { 1620d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += interp_in[q * elem_size + n]; 1621d1d35e2fSjeremylt } else if (eval_mode_in[e_in] == CEED_EVAL_GRAD) { 1622d1d35e2fSjeremylt d_in += 1; 1623d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += 1624d1d35e2fSjeremylt grad_in[(d_in*num_qpts+q) * elem_size + n]; 1625e2f04181SAndrew T. Barker } else { 1626e2f04181SAndrew T. Barker // LCOV_EXCL_START 1627e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1628e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1629e2f04181SAndrew T. Barker } 1630e2f04181SAndrew T. Barker } 1631d1d35e2fSjeremylt CeedInt d_out = -1; 1632d1d35e2fSjeremylt for (int e_out = 0; e_out < num_eval_mode_out; ++e_out) { 1633d1d35e2fSjeremylt const int qq = num_eval_mode_out*q; 1634d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_INTERP) { 1635d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += interp_in[q * elem_size + n]; 1636d1d35e2fSjeremylt } else if (eval_mode_out[e_out] == CEED_EVAL_GRAD) { 1637d1d35e2fSjeremylt d_out += 1; 1638d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += 1639d1d35e2fSjeremylt grad_in[(d_out*num_qpts+q) * elem_size + n]; 1640e2f04181SAndrew T. Barker } else { 1641e2f04181SAndrew T. Barker // LCOV_EXCL_START 1642e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1643e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1644e2f04181SAndrew T. Barker } 1645e2f04181SAndrew T. Barker } 1646e2f04181SAndrew T. Barker } 1647d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_out; ++ei) { 1648d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_in; ++ej) { 1649d1d35e2fSjeremylt const int eval_mode_index = ((ei*num_comp+comp_in)*num_eval_mode_in+ej)*num_comp 1650d1d35e2fSjeremylt +comp_out; 1651d1d35e2fSjeremylt const int index = q*layout_qf[0] + eval_mode_index*layout_qf[1] + 1652d1d35e2fSjeremylt e*layout_qf[2]; 1653d1d35e2fSjeremylt D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q] += assembled_qf_array[index]; 1654e2f04181SAndrew T. Barker } 1655e2f04181SAndrew T. Barker } 1656e2f04181SAndrew T. Barker } 1657e2f04181SAndrew T. Barker // Compute B^T*D 1658d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*num_qpts*num_eval_mode_in; ++ell) { 1659e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1660e2f04181SAndrew T. Barker } 1661d1d35e2fSjeremylt for (int j = 0; j<elem_size; ++j) { 1662d1d35e2fSjeremylt for (int q = 0; q<num_qpts; ++q) { 1663d1d35e2fSjeremylt int qq = num_eval_mode_out*q; 1664d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_in; ++ei) { 1665d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_out; ++ej) { 1666d1d35e2fSjeremylt BTD[j*(num_qpts*num_eval_mode_in) + (qq+ei)] += 1667d1d35e2fSjeremylt B_mat_out[(qq+ej)*elem_size + j] * D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q]; 1668e2f04181SAndrew T. Barker } 1669e2f04181SAndrew T. Barker } 1670e2f04181SAndrew T. Barker } 1671e2f04181SAndrew T. Barker } 1672e2f04181SAndrew T. Barker 1673d1d35e2fSjeremylt ierr = CeedMatrixMultiply(ceed, BTD, B_mat_in, elem_mat, elem_size, 1674d1d35e2fSjeremylt elem_size, num_qpts*num_eval_mode_in); CeedChk(ierr); 1675e2f04181SAndrew T. Barker 1676e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1677d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1678d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1679d1d35e2fSjeremylt vals[offset + count] = elem_mat[i*elem_size + j]; 1680e2f04181SAndrew T. Barker count++; 1681e2f04181SAndrew T. Barker } 1682e2f04181SAndrew T. Barker } 1683e2f04181SAndrew T. Barker } 1684e2f04181SAndrew T. Barker } 1685e2f04181SAndrew T. Barker } 1686d1d35e2fSjeremylt if (count != local_num_entries) 1687e2f04181SAndrew T. Barker // LCOV_EXCL_START 1688e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1689e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1690e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1691e2f04181SAndrew T. Barker 1692d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(assembled_qf, &assembled_qf_array); 1693e2f04181SAndrew T. Barker CeedChk(ierr); 1694d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChk(ierr); 1695d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChk(ierr); 1696d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChk(ierr); 1697e2f04181SAndrew T. Barker 1698e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1699e2f04181SAndrew T. Barker } 1700e2f04181SAndrew T. Barker 1701e2f04181SAndrew T. Barker /** 1702e2f04181SAndrew T. Barker @ref Utility 1703e2f04181SAndrew T. Barker **/ 1704d1d35e2fSjeremylt int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, 1705d1d35e2fSjeremylt CeedInt *num_entries) { 1706e2f04181SAndrew T. Barker int ierr; 1707e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1708d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_comp; 1709e2f04181SAndrew T. Barker 1710e2f04181SAndrew T. Barker if (op->composite) 1711e2f04181SAndrew T. Barker // LCOV_EXCL_START 1712e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1713e2f04181SAndrew T. Barker "Composite operator not supported"); 1714e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1715e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1716d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChk(ierr); 1717d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); CeedChk(ierr); 1718d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); CeedChk(ierr); 1719d1d35e2fSjeremylt *num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1720e2f04181SAndrew T. Barker 1721e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1722e2f04181SAndrew T. Barker } 1723e2f04181SAndrew T. Barker 1724e2f04181SAndrew T. Barker /** 1725e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1726e2f04181SAndrew T. Barker 1727e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1728e2f04181SAndrew T. Barker 1729d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1730e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1731e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1732e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1733e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1734e2f04181SAndrew T. Barker ordering. 1735e2f04181SAndrew T. Barker 1736e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1737e2f04181SAndrew T. Barker 1738e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1739d1d35e2fSjeremylt @param[out] num_entries Number of entries in coordinate nonzero pattern. 1740e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1741e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1742e2f04181SAndrew T. Barker 1743e2f04181SAndrew T. Barker @ref User 1744e2f04181SAndrew T. Barker **/ 1745e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1746d1d35e2fSjeremylt CeedInt *num_entries, CeedInt **rows, CeedInt **cols) { 1747e2f04181SAndrew T. Barker int ierr; 1748d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1749d1d35e2fSjeremylt CeedOperator *sub_operators; 1750d1d35e2fSjeremylt bool is_composite; 1751e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1752e2f04181SAndrew T. Barker 1753e2f04181SAndrew T. Barker // Use backend version, if available 1754e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1755d1d35e2fSjeremylt return op->LinearAssembleSymbolic(op, num_entries, rows, cols); 1756e2f04181SAndrew T. Barker } else { 1757e2f04181SAndrew T. Barker // Check for valid fallback resource 1758d1d35e2fSjeremylt const char *resource, *fallback_resource; 1759e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1760d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 176178464608Sjeremylt CeedChk(ierr); 1762d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1763e2f04181SAndrew T. Barker // Fallback to reference Ceed 1764d1d35e2fSjeremylt if (!op->op_fallback) { 1765e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1766e2f04181SAndrew T. Barker } 1767e2f04181SAndrew T. Barker // Assemble 1768d1d35e2fSjeremylt return CeedOperatorLinearAssembleSymbolic(op->op_fallback, num_entries, rows, 1769d1d35e2fSjeremylt cols); 1770e2f04181SAndrew T. Barker } 1771e2f04181SAndrew T. Barker } 1772e2f04181SAndrew T. Barker 1773e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1774e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1775e2f04181SAndrew T. Barker 1776e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1777d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1778d1d35e2fSjeremylt *num_entries = 0; 1779d1d35e2fSjeremylt if (is_composite) { 1780d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1781d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1782d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1783d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1784e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1785d1d35e2fSjeremylt *num_entries += single_entries; 1786e2f04181SAndrew T. Barker } 1787e2f04181SAndrew T. Barker } else { 1788e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1789e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1790d1d35e2fSjeremylt *num_entries += single_entries; 1791e2f04181SAndrew T. Barker } 1792d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, rows); CeedChk(ierr); 1793d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, cols); CeedChk(ierr); 1794e2f04181SAndrew T. Barker 1795e2f04181SAndrew T. Barker // assemble nonzero locations 1796e2f04181SAndrew T. Barker CeedInt offset = 0; 1797d1d35e2fSjeremylt if (is_composite) { 1798d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1799d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1800d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1801d1d35e2fSjeremylt ierr = CeedSingleOperatorAssembleSymbolic(sub_operators[k], offset, *rows, 1802e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1803d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1804d1d35e2fSjeremylt &single_entries); 1805e2f04181SAndrew T. Barker CeedChk(ierr); 1806e2f04181SAndrew T. Barker offset += single_entries; 1807e2f04181SAndrew T. Barker } 1808e2f04181SAndrew T. Barker } else { 1809e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1810e2f04181SAndrew T. Barker CeedChk(ierr); 1811e2f04181SAndrew T. Barker } 1812e2f04181SAndrew T. Barker 1813e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1814e2f04181SAndrew T. Barker } 1815e2f04181SAndrew T. Barker 1816e2f04181SAndrew T. Barker /** 1817e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1818e2f04181SAndrew T. Barker 1819e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1820e2f04181SAndrew T. Barker 1821d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1822e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1823e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1824e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1825e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1826e2f04181SAndrew T. Barker 1827e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1828e2f04181SAndrew T. Barker 1829e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1830e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1831e2f04181SAndrew T. Barker 1832e2f04181SAndrew T. Barker @ref User 1833e2f04181SAndrew T. Barker **/ 1834e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1835e2f04181SAndrew T. Barker int ierr; 183678464608Sjeremylt CeedInt num_suboperators, single_entries = 0; 1837d1d35e2fSjeremylt CeedOperator *sub_operators; 1838e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1839e2f04181SAndrew T. Barker 1840e2f04181SAndrew T. Barker // Use backend version, if available 1841e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1842e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1843e2f04181SAndrew T. Barker } else { 1844e2f04181SAndrew T. Barker // Check for valid fallback resource 1845d1d35e2fSjeremylt const char *resource, *fallback_resource; 1846e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1847d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 184878464608Sjeremylt CeedChk(ierr); 1849d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1850e2f04181SAndrew T. Barker // Fallback to reference Ceed 1851d1d35e2fSjeremylt if (!op->op_fallback) { 1852e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1853e2f04181SAndrew T. Barker } 1854e2f04181SAndrew T. Barker // Assemble 1855d1d35e2fSjeremylt return CeedOperatorLinearAssemble(op->op_fallback, values); 1856e2f04181SAndrew T. Barker } 1857e2f04181SAndrew T. Barker } 1858e2f04181SAndrew T. Barker 1859e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1860e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1861e2f04181SAndrew T. Barker 1862d1d35e2fSjeremylt bool is_composite; 1863d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1864e2f04181SAndrew T. Barker 1865e2f04181SAndrew T. Barker CeedInt offset = 0; 1866d1d35e2fSjeremylt if (is_composite) { 1867d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1868d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1869d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1870d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemble(sub_operators[k], offset, values); 1871e2f04181SAndrew T. Barker CeedChk(ierr); 1872d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1873d1d35e2fSjeremylt &single_entries); 1874e2f04181SAndrew T. Barker CeedChk(ierr); 1875e2f04181SAndrew T. Barker offset += single_entries; 1876e2f04181SAndrew T. Barker } 1877e2f04181SAndrew T. Barker } else { 1878e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1879e2f04181SAndrew T. Barker } 1880e2f04181SAndrew T. Barker 1881e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1882d965c7a7SJeremy L Thompson } 1883d965c7a7SJeremy L Thompson 1884d965c7a7SJeremy L Thompson /** 1885d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1886d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1887d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1888d99fa3c5SJeremy L Thompson 1889d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1890d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1891d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1892d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1893d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1894d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1895d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1896d99fa3c5SJeremy L Thompson 1897d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1898d99fa3c5SJeremy L Thompson 1899d99fa3c5SJeremy L Thompson @ref User 1900d99fa3c5SJeremy L Thompson **/ 1901d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, 1902d1d35e2fSjeremylt CeedVector p_mult_fine, 1903d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1904d1d35e2fSjeremylt CeedOperator *op_coarse, CeedOperator *op_prolong, 1905d1d35e2fSjeremylt CeedOperator *op_restrict) { 1906d99fa3c5SJeremy L Thompson int ierr; 1907d99fa3c5SJeremy L Thompson Ceed ceed; 1908d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1909d99fa3c5SJeremy L Thompson 1910d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1911d1d35e2fSjeremylt CeedBasis basis_fine; 1912d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1913d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1914d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1915d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1916d1d35e2fSjeremylt if (Q_f != Q_c) 1917d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1918e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1919e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1920d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1921d99fa3c5SJeremy L Thompson 1922d99fa3c5SJeremy L Thompson // Coarse to fine basis 1923d1d35e2fSjeremylt CeedInt P_f, P_c, Q = Q_f; 1924d1d35e2fSjeremylt bool is_tensor_f, is_tensor_c; 1925d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_fine, &is_tensor_f); CeedChk(ierr); 1926d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_coarse, &is_tensor_c); CeedChk(ierr); 1927d1d35e2fSjeremylt CeedScalar *interp_c, *interp_f, *interp_c_to_f, *tau; 1928d1d35e2fSjeremylt if (is_tensor_f && is_tensor_c) { 1929d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_f); CeedChk(ierr); 1930d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_coarse, &P_c); CeedChk(ierr); 1931d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis_coarse, &Q); CeedChk(ierr); 1932d1d35e2fSjeremylt } else if (!is_tensor_f && !is_tensor_c) { 1933d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &P_f); CeedChk(ierr); 1934d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_coarse, &P_c); CeedChk(ierr); 1935d99fa3c5SJeremy L Thompson } else { 1936d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1937e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1938e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1939d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1940d99fa3c5SJeremy L Thompson } 1941d99fa3c5SJeremy L Thompson 1942d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_f, &interp_f); CeedChk(ierr); 1943d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_c, &interp_c); CeedChk(ierr); 1944d1d35e2fSjeremylt ierr = CeedCalloc(P_c*P_f, &interp_c_to_f); CeedChk(ierr); 1945d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1946d1d35e2fSjeremylt if (is_tensor_f) { 1947d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp_1d, Q*P_f*sizeof basis_fine->interp_1d[0]); 1948d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp_1d, 1949d1d35e2fSjeremylt Q*P_c*sizeof basis_coarse->interp_1d[0]); 1950d99fa3c5SJeremy L Thompson } else { 1951d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp, Q*P_f*sizeof basis_fine->interp[0]); 1952d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp, Q*P_c*sizeof basis_coarse->interp[0]); 1953d99fa3c5SJeremy L Thompson } 1954d99fa3c5SJeremy L Thompson 1955d1d35e2fSjeremylt // -- QR Factorization, interp_f = Q R 1956d1d35e2fSjeremylt ierr = CeedQRFactorization(ceed, interp_f, tau, Q, P_f); CeedChk(ierr); 1957d99fa3c5SJeremy L Thompson 1958d1d35e2fSjeremylt // -- Apply Qtranspose, interp_c = Qtranspose interp_c 1959d1d35e2fSjeremylt ierr = CeedHouseholderApplyQ(interp_c, interp_f, tau, CEED_TRANSPOSE, 1960d1d35e2fSjeremylt Q, P_c, P_f, P_c, 1); CeedChk(ierr); 1961d99fa3c5SJeremy L Thompson 1962d1d35e2fSjeremylt // -- Apply Rinv, interp_c_to_f = Rinv interp_c 1963d1d35e2fSjeremylt for (CeedInt j=0; j<P_c; j++) { // Column j 1964d1d35e2fSjeremylt 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]; 1965d1d35e2fSjeremylt for (CeedInt i=P_f-2; i>=0; i--) { // Row i 1966d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] = interp_c[j+P_c*i]; 1967d1d35e2fSjeremylt for (CeedInt k=i+1; k<P_f; k++) 1968d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] -= interp_f[k+P_f*i]*interp_c_to_f[j+P_c*k]; 1969d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] /= interp_f[i+P_f*i]; 1970d99fa3c5SJeremy L Thompson } 1971d99fa3c5SJeremy L Thompson } 1972d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1973d1d35e2fSjeremylt ierr = CeedFree(&interp_c); CeedChk(ierr); 1974d1d35e2fSjeremylt ierr = CeedFree(&interp_f); CeedChk(ierr); 1975d99fa3c5SJeremy L Thompson 1976d1d35e2fSjeremylt // Complete with interp_c_to_f versions of code 1977d1d35e2fSjeremylt if (is_tensor_f) { 1978d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateTensorH1(op_fine, p_mult_fine, 1979d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1980d99fa3c5SJeremy L Thompson CeedChk(ierr); 1981d99fa3c5SJeremy L Thompson } else { 1982d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateH1(op_fine, p_mult_fine, 1983d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1984d99fa3c5SJeremy L Thompson CeedChk(ierr); 1985d99fa3c5SJeremy L Thompson } 1986d99fa3c5SJeremy L Thompson 1987d99fa3c5SJeremy L Thompson // Cleanup 1988d1d35e2fSjeremylt ierr = CeedFree(&interp_c_to_f); CeedChk(ierr); 1989e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1990d99fa3c5SJeremy L Thompson } 1991d99fa3c5SJeremy L Thompson 1992d99fa3c5SJeremy L Thompson /** 1993d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1994d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1995d99fa3c5SJeremy L Thompson 1996d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1997d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1998d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1999d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2000d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2001d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2002d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2003d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2004d99fa3c5SJeremy L Thompson 2005d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2006d99fa3c5SJeremy L Thompson 2007d99fa3c5SJeremy L Thompson @ref User 2008d99fa3c5SJeremy L Thompson **/ 2009d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, 2010d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 2011d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, 2012d1d35e2fSjeremylt CeedOperator *op_prolong, CeedOperator *op_restrict) { 2013d99fa3c5SJeremy L Thompson int ierr; 2014d99fa3c5SJeremy L Thompson Ceed ceed; 2015d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2016d99fa3c5SJeremy L Thompson 2017d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2018d1d35e2fSjeremylt CeedBasis basis_fine; 2019d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2020d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2021d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2022d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2023d1d35e2fSjeremylt if (Q_f != Q_c) 2024d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2025e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2026e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2027d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2028d99fa3c5SJeremy L Thompson 2029d99fa3c5SJeremy L Thompson // Coarse to fine basis 2030d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c; 2031d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2032d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2033d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_1d_f); CeedChk(ierr); 2034d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2035d99fa3c5SJeremy L Thompson CeedChk(ierr); 2036d1d35e2fSjeremylt P_1d_c = dim == 1 ? num_nodes_c : 2037d1d35e2fSjeremylt dim == 2 ? sqrt(num_nodes_c) : 2038d1d35e2fSjeremylt cbrt(num_nodes_c); 2039d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2040d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_ref); CeedChk(ierr); 2041d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_weight); CeedChk(ierr); 2042d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f*P_1d_c*dim, &grad); CeedChk(ierr); 2043d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2044d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, 2045d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2046d99fa3c5SJeremy L Thompson CeedChk(ierr); 2047d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2048d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2049d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2050d99fa3c5SJeremy L Thompson 2051d99fa3c5SJeremy L Thompson // Core code 2052d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2053d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2054d1d35e2fSjeremylt op_prolong, op_restrict); 2055d99fa3c5SJeremy L Thompson CeedChk(ierr); 2056e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2057d99fa3c5SJeremy L Thompson } 2058d99fa3c5SJeremy L Thompson 2059d99fa3c5SJeremy L Thompson /** 2060d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 2061d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 2062d99fa3c5SJeremy L Thompson 2063d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 2064d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 2065d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 2066d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2067d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2068d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2069d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2070d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2071d99fa3c5SJeremy L Thompson 2072d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2073d99fa3c5SJeremy L Thompson 2074d99fa3c5SJeremy L Thompson @ref User 2075d99fa3c5SJeremy L Thompson **/ 2076d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, 2077d1d35e2fSjeremylt CeedVector p_mult_fine, 2078d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, 2079d1d35e2fSjeremylt CeedBasis basis_coarse, 2080d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, 2081d1d35e2fSjeremylt CeedOperator *op_coarse, 2082d1d35e2fSjeremylt CeedOperator *op_prolong, 2083d1d35e2fSjeremylt CeedOperator *op_restrict) { 2084d99fa3c5SJeremy L Thompson int ierr; 2085d99fa3c5SJeremy L Thompson Ceed ceed; 2086d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2087d99fa3c5SJeremy L Thompson 2088d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2089d1d35e2fSjeremylt CeedBasis basis_fine; 2090d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2091d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2092d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2093d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2094d1d35e2fSjeremylt if (Q_f != Q_c) 2095d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2096e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2097e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2098d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2099d99fa3c5SJeremy L Thompson 2100d99fa3c5SJeremy L Thompson // Coarse to fine basis 2101d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2102d1d35e2fSjeremylt ierr = CeedBasisGetTopology(basis_fine, &topo); CeedChk(ierr); 2103d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, num_nodes_f; 2104d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2105d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2106d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &num_nodes_f); CeedChk(ierr); 2107d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2108d99fa3c5SJeremy L Thompson CeedChk(ierr); 2109d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2110d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_ref); CeedChk(ierr); 2111d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_weight); CeedChk(ierr); 2112d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f*num_nodes_c*dim, &grad); CeedChk(ierr); 2113d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2114d1d35e2fSjeremylt ierr = CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, 2115d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2116d99fa3c5SJeremy L Thompson CeedChk(ierr); 2117d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2118d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2119d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2120d99fa3c5SJeremy L Thompson 2121d99fa3c5SJeremy L Thompson // Core code 2122d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2123d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2124d1d35e2fSjeremylt op_prolong, op_restrict); 2125d99fa3c5SJeremy L Thompson CeedChk(ierr); 2126e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2127d99fa3c5SJeremy L Thompson } 2128d99fa3c5SJeremy L Thompson 2129d99fa3c5SJeremy L Thompson /** 21303bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 21313bd813ffSjeremylt CeedOperator 21323bd813ffSjeremylt 21333bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 21343bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 21353bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 21363bd813ffSjeremylt M = V^T V, K = V^T S V. 21373bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 21383bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 21393bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 21403bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 21413bd813ffSjeremylt 21423bd813ffSjeremylt @param op CeedOperator to create element inverses 2143d1d35e2fSjeremylt @param[out] fdm_inv CeedOperator to apply the action of a FDM based inverse 21443bd813ffSjeremylt for each element 21453bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 21464cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 21473bd813ffSjeremylt 21483bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 21493bd813ffSjeremylt 21507a982d89SJeremy L. Thompson @ref Backend 21513bd813ffSjeremylt **/ 2152d1d35e2fSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdm_inv, 21533bd813ffSjeremylt CeedRequest *request) { 21543bd813ffSjeremylt int ierr; 2155e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 21563bd813ffSjeremylt 2157713f43c3Sjeremylt // Use backend version, if available 2158713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2159d1d35e2fSjeremylt ierr = op->CreateFDMElementInverse(op, fdm_inv, request); CeedChk(ierr); 2160713f43c3Sjeremylt } else { 2161713f43c3Sjeremylt // Fallback to reference Ceed 2162d1d35e2fSjeremylt if (!op->op_fallback) { 2163713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 21643bd813ffSjeremylt } 2165713f43c3Sjeremylt // Assemble 2166d1d35e2fSjeremylt ierr = op->op_fallback->CreateFDMElementInverse(op->op_fallback, fdm_inv, 21673bd813ffSjeremylt request); CeedChk(ierr); 21683bd813ffSjeremylt } 2169e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21703bd813ffSjeremylt } 21713bd813ffSjeremylt 21727a982d89SJeremy L. Thompson /** 2173cd4dfc48Sjeremylt @brief Set the number of quadrature points associated with a CeedOperator. 2174cd4dfc48Sjeremylt This should be used when creating a CeedOperator where every 2175cd4dfc48Sjeremylt field has a collocated basis. This function cannot be used for 2176cd4dfc48Sjeremylt composite CeedOperators. 2177cd4dfc48Sjeremylt 2178cd4dfc48Sjeremylt @param op CeedOperator 2179cd4dfc48Sjeremylt @param num_qpts Number of quadrature points to set 2180cd4dfc48Sjeremylt 2181cd4dfc48Sjeremylt @return An error code: 0 - success, otherwise - failure 2182cd4dfc48Sjeremylt 2183cd4dfc48Sjeremylt @ref Backend 2184cd4dfc48Sjeremylt **/ 2185cd4dfc48Sjeremylt 2186cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 2187cd4dfc48Sjeremylt if (op->composite) 2188cd4dfc48Sjeremylt // LCOV_EXCL_START 2189cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 2190cd4dfc48Sjeremylt "Not defined for composite operator"); 2191cd4dfc48Sjeremylt // LCOV_EXCL_STOP 2192cd4dfc48Sjeremylt if (op->num_qpts) 2193cd4dfc48Sjeremylt // LCOV_EXCL_START 2194cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 2195cd4dfc48Sjeremylt "Number of quadrature points already defined"); 2196cd4dfc48Sjeremylt // LCOV_EXCL_STOP 2197cd4dfc48Sjeremylt 2198cd4dfc48Sjeremylt op->num_qpts = num_qpts; 2199cd4dfc48Sjeremylt return CEED_ERROR_SUCCESS; 2200cd4dfc48Sjeremylt } 2201cd4dfc48Sjeremylt 2202cd4dfc48Sjeremylt /** 22037a982d89SJeremy L. Thompson @brief View a CeedOperator 22047a982d89SJeremy L. Thompson 22057a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 22067a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 22077a982d89SJeremy L. Thompson 22087a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 22097a982d89SJeremy L. Thompson 22107a982d89SJeremy L. Thompson @ref User 22117a982d89SJeremy L. Thompson **/ 22127a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 22137a982d89SJeremy L. Thompson int ierr; 22147a982d89SJeremy L. Thompson 22157a982d89SJeremy L. Thompson if (op->composite) { 22167a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 22177a982d89SJeremy L. Thompson 2218d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 22197a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 2220d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 22217a982d89SJeremy L. Thompson CeedChk(ierr); 22227a982d89SJeremy L. Thompson } 22237a982d89SJeremy L. Thompson } else { 22247a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 22257a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 22267a982d89SJeremy L. Thompson } 2227e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 22287a982d89SJeremy L. Thompson } 22293bd813ffSjeremylt 22303bd813ffSjeremylt /** 22313bd813ffSjeremylt @brief Apply CeedOperator to a vector 2232d7b241e6Sjeremylt 2233d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2234d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2235d7b241e6Sjeremylt CeedOperatorSetField(). 2236d7b241e6Sjeremylt 2237d7b241e6Sjeremylt @param op CeedOperator to apply 22384cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 223934138859Sjeremylt there are no active inputs 2240b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 22414cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 224234138859Sjeremylt active outputs 2243d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 22444cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2245b11c1e72Sjeremylt 2246b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2247dfdf5a53Sjeremylt 22487a982d89SJeremy L. Thompson @ref User 2249b11c1e72Sjeremylt **/ 2250692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2251692c2638Sjeremylt CeedRequest *request) { 2252d7b241e6Sjeremylt int ierr; 2253e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2254d7b241e6Sjeremylt 2255d1d35e2fSjeremylt if (op->num_elem) { 2256250756a7Sjeremylt // Standard Operator 2257cae8b89aSjeremylt if (op->Apply) { 2258250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2259cae8b89aSjeremylt } else { 2260cae8b89aSjeremylt // Zero all output vectors 2261250756a7Sjeremylt CeedQFunction qf = op->qf; 2262d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 2263d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 2264cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2265cae8b89aSjeremylt vec = out; 2266cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2267cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2268cae8b89aSjeremylt } 2269cae8b89aSjeremylt } 2270250756a7Sjeremylt // Apply 2271250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2272250756a7Sjeremylt } 2273250756a7Sjeremylt } else if (op->composite) { 2274250756a7Sjeremylt // Composite Operator 2275250756a7Sjeremylt if (op->ApplyComposite) { 2276250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2277250756a7Sjeremylt } else { 2278d1d35e2fSjeremylt CeedInt num_suboperators; 2279d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2280d1d35e2fSjeremylt CeedOperator *sub_operators; 2281d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2282250756a7Sjeremylt 2283250756a7Sjeremylt // Zero all output vectors 2284250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2285cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2286cae8b89aSjeremylt } 2287d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2288d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 2289d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 2290250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2291250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2292250756a7Sjeremylt } 2293250756a7Sjeremylt } 2294250756a7Sjeremylt } 2295250756a7Sjeremylt // Apply 2296d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 2297d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 2298cae8b89aSjeremylt CeedChk(ierr); 2299cae8b89aSjeremylt } 2300cae8b89aSjeremylt } 2301250756a7Sjeremylt } 2302e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2303cae8b89aSjeremylt } 2304cae8b89aSjeremylt 2305cae8b89aSjeremylt /** 2306cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2307cae8b89aSjeremylt 2308cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2309cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2310cae8b89aSjeremylt CeedOperatorSetField(). 2311cae8b89aSjeremylt 2312cae8b89aSjeremylt @param op CeedOperator to apply 2313cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2314cae8b89aSjeremylt active inputs 2315cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2316cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2317cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 23184cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2319cae8b89aSjeremylt 2320cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2321cae8b89aSjeremylt 23227a982d89SJeremy L. Thompson @ref User 2323cae8b89aSjeremylt **/ 2324cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2325cae8b89aSjeremylt CeedRequest *request) { 2326cae8b89aSjeremylt int ierr; 2327e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2328cae8b89aSjeremylt 2329d1d35e2fSjeremylt if (op->num_elem) { 2330250756a7Sjeremylt // Standard Operator 2331250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2332250756a7Sjeremylt } else if (op->composite) { 2333250756a7Sjeremylt // Composite Operator 2334250756a7Sjeremylt if (op->ApplyAddComposite) { 2335250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2336cae8b89aSjeremylt } else { 2337d1d35e2fSjeremylt CeedInt num_suboperators; 2338d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2339d1d35e2fSjeremylt CeedOperator *sub_operators; 2340d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2341250756a7Sjeremylt 2342d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2343d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 2344cae8b89aSjeremylt CeedChk(ierr); 23451d7d2407SJeremy L Thompson } 2346250756a7Sjeremylt } 2347250756a7Sjeremylt } 2348e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2349d7b241e6Sjeremylt } 2350d7b241e6Sjeremylt 2351d7b241e6Sjeremylt /** 2352b11c1e72Sjeremylt @brief Destroy a CeedOperator 2353d7b241e6Sjeremylt 2354d7b241e6Sjeremylt @param op CeedOperator to destroy 2355b11c1e72Sjeremylt 2356b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2357dfdf5a53Sjeremylt 23587a982d89SJeremy L. Thompson @ref User 2359b11c1e72Sjeremylt **/ 2360d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2361d7b241e6Sjeremylt int ierr; 2362d7b241e6Sjeremylt 2363d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 2364d7b241e6Sjeremylt if ((*op)->Destroy) { 2365d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2366d7b241e6Sjeremylt } 2367fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2368fe2413ffSjeremylt // Free fields 2369d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2370d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 2371d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 2372d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 237371352a93Sjeremylt CeedChk(ierr); 237415910d16Sjeremylt } 2375d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2376d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 237771352a93Sjeremylt } 2378d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 2379d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 2380d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 238171352a93Sjeremylt } 2382d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 2383d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 2384fe2413ffSjeremylt } 2385d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2386d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 2387d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 238871352a93Sjeremylt CeedChk(ierr); 2389d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2390d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 239171352a93Sjeremylt } 2392d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 2393d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 2394d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 239571352a93Sjeremylt } 2396d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 2397d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 2398fe2413ffSjeremylt } 2399d1d35e2fSjeremylt // Destroy sub_operators 2400d1d35e2fSjeremylt for (int i=0; i<(*op)->num_suboperators; i++) 2401d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 2402d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 240352d6035fSJeremy L Thompson } 2404e15f9bd0SJeremy L Thompson if ((*op)->qf) 2405e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2406d1d35e2fSjeremylt (*op)->qf->operators_set--; 2407e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2408d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2409e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2410e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2411d1d35e2fSjeremylt (*op)->dqf->operators_set--; 2412e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2413d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2414e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2415e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2416d1d35e2fSjeremylt (*op)->dqfT->operators_set--; 2417e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2418d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2419fe2413ffSjeremylt 24205107b09fSJeremy L Thompson // Destroy fallback 2421d1d35e2fSjeremylt if ((*op)->op_fallback) { 2422d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 2423d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 2424d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 2425d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 24265107b09fSJeremy L Thompson } 24275107b09fSJeremy L Thompson 2428d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 2429d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 2430d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 2431d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2432e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2433d7b241e6Sjeremylt } 2434d7b241e6Sjeremylt 2435d7b241e6Sjeremylt /// @} 2436