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) 131e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 132d1d35e2fSjeremylt "Field '%s' configured with CEED_EVAL_NONE must " 133d1d35e2fSjeremylt "be used with CEED_BASIS_COLLOCATED", 134d1d35e2fSjeremylt qf_field->field_name); 135e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 136d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr); 137d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) { 138e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 139e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 140d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s: ElemRestriction " 141d1d35e2fSjeremylt "has %d components, but Basis has %d components", 142d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 143d1d35e2fSjeremylt restr_num_comp, 144d1d35e2fSjeremylt num_comp); 145e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 146e15f9bd0SJeremy L Thompson } 147e15f9bd0SJeremy L Thompson } 148e15f9bd0SJeremy L Thompson // Field size 149d1d35e2fSjeremylt switch(eval_mode) { 150e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 151d1d35e2fSjeremylt if (size != restr_num_comp) 152e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 153e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 154e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 155d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 156d1d35e2fSjeremylt restr_num_comp); 157e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 158e15f9bd0SJeremy L Thompson break; 159e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 160d1d35e2fSjeremylt if (size != num_comp) 161e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 162e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 163e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 164d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], 165d1d35e2fSjeremylt num_comp); 166e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 167e15f9bd0SJeremy L Thompson break; 168e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 169d1d35e2fSjeremylt if (size != num_comp * dim) 170e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 171e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 172d1d35e2fSjeremylt "Field '%s' of size %d and EvalMode %s in %d dimensions: " 173d1d35e2fSjeremylt "ElemRestriction/Basis has %d components", 174d1d35e2fSjeremylt qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim, 175d1d35e2fSjeremylt num_comp); 176e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 177e15f9bd0SJeremy L Thompson break; 178e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 179d1d35e2fSjeremylt // No additional checks required 180e15f9bd0SJeremy L Thompson break; 181e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 182e15f9bd0SJeremy L Thompson // Not implemented 183e15f9bd0SJeremy L Thompson break; 184e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 185e15f9bd0SJeremy L Thompson // Not implemented 186e15f9bd0SJeremy L Thompson break; 187e15f9bd0SJeremy L Thompson } 188e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1897a982d89SJeremy L. Thompson } 1907a982d89SJeremy L. Thompson 1917a982d89SJeremy L. Thompson /** 1927a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 1937a982d89SJeremy L. Thompson 1947a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 1957a982d89SJeremy L. Thompson 1967a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1977a982d89SJeremy L. Thompson 1987a982d89SJeremy L. Thompson @ref Developer 1997a982d89SJeremy L. Thompson **/ 200e2f04181SAndrew T. Barker static int CeedOperatorCheckReady(CeedOperator op) { 201e2f04181SAndrew T. Barker int ierr; 202e2f04181SAndrew T. Barker Ceed ceed; 203e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 204e2f04181SAndrew T. Barker 205d1d35e2fSjeremylt if (op->interface_setup) 206e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2077a982d89SJeremy L. Thompson 208e15f9bd0SJeremy L Thompson CeedQFunction qf = op->qf; 2097a982d89SJeremy L. Thompson if (op->composite) { 210d1d35e2fSjeremylt if (!op->num_suboperators) 2117a982d89SJeremy L. Thompson // LCOV_EXCL_START 212d1d35e2fSjeremylt return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set"); 2137a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2147a982d89SJeremy L. Thompson } else { 215d1d35e2fSjeremylt if (op->num_fields == 0) 2167a982d89SJeremy L. Thompson // LCOV_EXCL_START 217e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 2187a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 219d1d35e2fSjeremylt if (op->num_fields < qf->num_input_fields + qf->num_output_fields) 2207a982d89SJeremy L. Thompson // LCOV_EXCL_START 221e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 2227a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 223d1d35e2fSjeremylt if (!op->has_restriction) 2247a982d89SJeremy L. Thompson // LCOV_EXCL_START 225e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 226e15f9bd0SJeremy L Thompson "At least one restriction required"); 2277a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 228d1d35e2fSjeremylt if (op->num_qpts == 0) 2297a982d89SJeremy L. Thompson // LCOV_EXCL_START 230e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 231*cd4dfc48Sjeremylt "At least one non-collocated basis is required " 232*cd4dfc48Sjeremylt "or the number of quadrature points must be set"); 2337a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2347a982d89SJeremy L. Thompson } 2357a982d89SJeremy L. Thompson 236e15f9bd0SJeremy L Thompson // Flag as immutable and ready 237d1d35e2fSjeremylt op->interface_setup = true; 238e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 239e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 240d1d35e2fSjeremylt op->qf->operators_set++; 241e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 242e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 243e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 244d1d35e2fSjeremylt op->dqf->operators_set++; 245e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 246e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 247e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 248d1d35e2fSjeremylt op->dqfT->operators_set++; 249e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 250e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2517a982d89SJeremy L. Thompson } 2527a982d89SJeremy L. Thompson 2537a982d89SJeremy L. Thompson /** 2547a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2557a982d89SJeremy L. Thompson 2567a982d89SJeremy L. Thompson @param[in] field Operator field to view 257d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 258d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 2594c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 260d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 2617a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2627a982d89SJeremy L. Thompson 2637a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2647a982d89SJeremy L. Thompson 2657a982d89SJeremy L. Thompson @ref Utility 2667a982d89SJeremy L. Thompson **/ 2677a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 268d1d35e2fSjeremylt CeedQFunctionField qf_field, 269d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 2707a982d89SJeremy L. Thompson FILE *stream) { 2717a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 272d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 2737a982d89SJeremy L. Thompson 2747a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2757a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 276d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 2777a982d89SJeremy L. Thompson 2787a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2797a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2807a982d89SJeremy L. Thompson 2817a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2827a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2837a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2847a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 285e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2867a982d89SJeremy L. Thompson } 2877a982d89SJeremy L. Thompson 2887a982d89SJeremy L. Thompson /** 2897a982d89SJeremy L. Thompson @brief View a single CeedOperator 2907a982d89SJeremy L. Thompson 2917a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2927a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2937a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2947a982d89SJeremy L. Thompson 2957a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2967a982d89SJeremy L. Thompson 2977a982d89SJeremy L. Thompson @ref Utility 2987a982d89SJeremy L. Thompson **/ 2997a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 3007a982d89SJeremy L. Thompson int ierr; 3017a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 3027a982d89SJeremy L. Thompson 30378464608Sjeremylt CeedInt total_fields = 0; 30478464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 3057a982d89SJeremy L. Thompson 30678464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 30778464608Sjeremylt total_fields>1 ? "s" : ""); 3087a982d89SJeremy L. Thompson 309d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 310d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 311d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 312d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 3137a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 3147a982d89SJeremy L. Thompson } 3157a982d89SJeremy L. Thompson 316d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 317d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 318d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 319d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 3207a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 3217a982d89SJeremy L. Thompson } 322e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3237a982d89SJeremy L. Thompson } 3247a982d89SJeremy L. Thompson 325d99fa3c5SJeremy L Thompson /** 326e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 327e2f04181SAndrew T. Barker 328e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 329d1d35e2fSjeremylt @param[out] active_rstr ElemRestriction for active input vector 330e2f04181SAndrew T. Barker 331e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 332e2f04181SAndrew T. Barker 333e2f04181SAndrew T. Barker @ref Utility 334e2f04181SAndrew T. Barker **/ 335e2f04181SAndrew T. Barker static int CeedOperatorGetActiveElemRestriction(CeedOperator op, 336d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 337d1d35e2fSjeremylt *active_rstr = NULL; 338d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 339d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 340d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 341e2f04181SAndrew T. Barker break; 342e2f04181SAndrew T. Barker } 343e2f04181SAndrew T. Barker 344d1d35e2fSjeremylt if (!*active_rstr) { 345e2f04181SAndrew T. Barker // LCOV_EXCL_START 346e2f04181SAndrew T. Barker int ierr; 347e2f04181SAndrew T. Barker Ceed ceed; 348e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 349e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 350e2f04181SAndrew T. Barker "No active ElemRestriction found!"); 351e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 352e2f04181SAndrew T. Barker } 353e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 354e2f04181SAndrew T. Barker } 355e2f04181SAndrew T. Barker 356e2f04181SAndrew T. Barker /** 357d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 358d99fa3c5SJeremy L Thompson 359d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 360d1d35e2fSjeremylt @param[out] active_basis Basis for active input vector 361d99fa3c5SJeremy L Thompson 362d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 363d99fa3c5SJeremy L Thompson 364d99fa3c5SJeremy L Thompson @ ref Developer 365d99fa3c5SJeremy L Thompson **/ 366d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 367d1d35e2fSjeremylt CeedBasis *active_basis) { 368d1d35e2fSjeremylt *active_basis = NULL; 369d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 370d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 371d1d35e2fSjeremylt *active_basis = op->input_fields[i]->basis; 372d99fa3c5SJeremy L Thompson break; 373d99fa3c5SJeremy L Thompson } 374d99fa3c5SJeremy L Thompson 375d1d35e2fSjeremylt if (!*active_basis) { 376d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 377d99fa3c5SJeremy L Thompson int ierr; 378d99fa3c5SJeremy L Thompson Ceed ceed; 379d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 380e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 381d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 382d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 383d99fa3c5SJeremy L Thompson } 384e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 385d99fa3c5SJeremy L Thompson } 386d99fa3c5SJeremy L Thompson 387d99fa3c5SJeremy L Thompson /** 388d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 389d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 390d99fa3c5SJeremy L Thompson 391d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 392d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 393d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 394d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 395d1d35e2fSjeremylt @param[in] basis_c_to_f Basis for coarse to fine interpolation 396d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 397d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 398d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 399d99fa3c5SJeremy L Thompson 400d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 401d99fa3c5SJeremy L Thompson 402d99fa3c5SJeremy L Thompson @ref Developer 403d99fa3c5SJeremy L Thompson **/ 404d1d35e2fSjeremylt static int CeedOperatorMultigridLevel_Core(CeedOperator op_fine, 405d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 406d1d35e2fSjeremylt CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, 407d1d35e2fSjeremylt CeedOperator *op_restrict) { 408d99fa3c5SJeremy L Thompson int ierr; 409d99fa3c5SJeremy L Thompson Ceed ceed; 410d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 411d99fa3c5SJeremy L Thompson 412d99fa3c5SJeremy L Thompson // Check for composite operator 413d1d35e2fSjeremylt bool is_composite; 414d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op_fine, &is_composite); CeedChk(ierr); 415d1d35e2fSjeremylt if (is_composite) 416d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 417e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 418d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 419d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 420d99fa3c5SJeremy L Thompson 421d99fa3c5SJeremy L Thompson // Coarse Grid 422d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, op_fine->qf, op_fine->dqf, op_fine->dqfT, 423d1d35e2fSjeremylt op_coarse); CeedChk(ierr); 424d1d35e2fSjeremylt CeedElemRestriction rstr_fine = NULL; 425d99fa3c5SJeremy L Thompson // -- Clone input fields 426d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_input_fields; i++) { 427d1d35e2fSjeremylt if (op_fine->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 428d1d35e2fSjeremylt rstr_fine = op_fine->input_fields[i]->elem_restr; 429d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 430d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 431d99fa3c5SJeremy L Thompson CeedChk(ierr); 432d99fa3c5SJeremy L Thompson } else { 433d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 434d1d35e2fSjeremylt op_fine->input_fields[i]->elem_restr, 435d1d35e2fSjeremylt op_fine->input_fields[i]->basis, 436d1d35e2fSjeremylt op_fine->input_fields[i]->vec); CeedChk(ierr); 437d99fa3c5SJeremy L Thompson } 438d99fa3c5SJeremy L Thompson } 439d99fa3c5SJeremy L Thompson // -- Clone output fields 440d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_output_fields; i++) { 441d1d35e2fSjeremylt if (op_fine->output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 442d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 443d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 444d99fa3c5SJeremy L Thompson CeedChk(ierr); 445d99fa3c5SJeremy L Thompson } else { 446d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 447d1d35e2fSjeremylt op_fine->output_fields[i]->elem_restr, 448d1d35e2fSjeremylt op_fine->output_fields[i]->basis, 449d1d35e2fSjeremylt op_fine->output_fields[i]->vec); CeedChk(ierr); 450d99fa3c5SJeremy L Thompson } 451d99fa3c5SJeremy L Thompson } 452d99fa3c5SJeremy L Thompson 453d99fa3c5SJeremy L Thompson // Multiplicity vector 454d1d35e2fSjeremylt CeedVector mult_vec, mult_e_vec; 455d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(rstr_fine, &mult_vec, &mult_e_vec); 456d99fa3c5SJeremy L Thompson CeedChk(ierr); 457d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_e_vec, 0.0); CeedChk(ierr); 458d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_NOTRANSPOSE, p_mult_fine, 459d1d35e2fSjeremylt mult_e_vec, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 460d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_vec, 0.0); CeedChk(ierr); 461d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_TRANSPOSE, mult_e_vec, mult_vec, 462d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 463d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_e_vec); CeedChk(ierr); 464d1d35e2fSjeremylt ierr = CeedVectorReciprocal(mult_vec); CeedChk(ierr); 465d99fa3c5SJeremy L Thompson 466d99fa3c5SJeremy L Thompson // Restriction 467d1d35e2fSjeremylt CeedInt num_comp; 468d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_coarse, &num_comp); CeedChk(ierr); 469d1d35e2fSjeremylt CeedQFunction qf_restrict; 470d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_restrict); 471d99fa3c5SJeremy L Thompson CeedChk(ierr); 472d1d35e2fSjeremylt CeedInt *num_comp_r_data; 473d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_r_data); CeedChk(ierr); 474d1d35e2fSjeremylt num_comp_r_data[0] = num_comp; 475d1d35e2fSjeremylt CeedQFunctionContext ctx_r; 476d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_r); CeedChk(ierr); 477d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, 478d1d35e2fSjeremylt sizeof(*num_comp_r_data), num_comp_r_data); 479777ff853SJeremy L Thompson CeedChk(ierr); 480d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_restrict, ctx_r); CeedChk(ierr); 481d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_r); CeedChk(ierr); 482d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "input", num_comp, CEED_EVAL_NONE); 483d99fa3c5SJeremy L Thompson CeedChk(ierr); 484d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "scale", num_comp, CEED_EVAL_NONE); 485d99fa3c5SJeremy L Thompson CeedChk(ierr); 486d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_restrict, "output", num_comp, 487d1d35e2fSjeremylt CEED_EVAL_INTERP); CeedChk(ierr); 488d99fa3c5SJeremy L Thompson 489d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE, 490d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_restrict); 491d99fa3c5SJeremy L Thompson CeedChk(ierr); 492d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "input", rstr_fine, 493d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 494d99fa3c5SJeremy L Thompson CeedChk(ierr); 495d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "scale", rstr_fine, 496d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 497d99fa3c5SJeremy L Thompson CeedChk(ierr); 498d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "output", rstr_coarse, basis_c_to_f, 499d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 500d99fa3c5SJeremy L Thompson 501d99fa3c5SJeremy L Thompson // Prolongation 502d1d35e2fSjeremylt CeedQFunction qf_prolong; 503d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_prolong); 504d99fa3c5SJeremy L Thompson CeedChk(ierr); 505d1d35e2fSjeremylt CeedInt *num_comp_p_data; 506d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_p_data); CeedChk(ierr); 507d1d35e2fSjeremylt num_comp_p_data[0] = num_comp; 508d1d35e2fSjeremylt CeedQFunctionContext ctx_p; 509d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_p); CeedChk(ierr); 510d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_p, CEED_MEM_HOST, CEED_OWN_POINTER, 511d1d35e2fSjeremylt sizeof(*num_comp_p_data), num_comp_p_data); 512777ff853SJeremy L Thompson CeedChk(ierr); 513d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_prolong, ctx_p); CeedChk(ierr); 514d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_p); CeedChk(ierr); 515d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "input", num_comp, CEED_EVAL_INTERP); 516d99fa3c5SJeremy L Thompson CeedChk(ierr); 517d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "scale", num_comp, CEED_EVAL_NONE); 518d99fa3c5SJeremy L Thompson CeedChk(ierr); 519d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_prolong, "output", num_comp, CEED_EVAL_NONE); 520d99fa3c5SJeremy L Thompson CeedChk(ierr); 521d99fa3c5SJeremy L Thompson 522d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_prolong, CEED_QFUNCTION_NONE, 523d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_prolong); 524d99fa3c5SJeremy L Thompson CeedChk(ierr); 525d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "input", rstr_coarse, basis_c_to_f, 526d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 527d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "scale", rstr_fine, 528d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 529d99fa3c5SJeremy L Thompson CeedChk(ierr); 530d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "output", rstr_fine, 531d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 532d99fa3c5SJeremy L Thompson CeedChk(ierr); 533d99fa3c5SJeremy L Thompson 534d99fa3c5SJeremy L Thompson // Cleanup 535d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_vec); CeedChk(ierr); 536d1d35e2fSjeremylt ierr = CeedBasisDestroy(&basis_c_to_f); CeedChk(ierr); 537d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_restrict); CeedChk(ierr); 538d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_prolong); CeedChk(ierr); 539e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 540d99fa3c5SJeremy L Thompson } 541d99fa3c5SJeremy L Thompson 5427a982d89SJeremy L. Thompson /// @} 5437a982d89SJeremy L. Thompson 5447a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5457a982d89SJeremy L. Thompson /// CeedOperator Backend API 5467a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5477a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5487a982d89SJeremy L. Thompson /// @{ 5497a982d89SJeremy L. Thompson 5507a982d89SJeremy L. Thompson /** 5517a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5527a982d89SJeremy L. Thompson 5537a982d89SJeremy L. Thompson @param op CeedOperator 5547a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5557a982d89SJeremy L. Thompson 5567a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5577a982d89SJeremy L. Thompson 5587a982d89SJeremy L. Thompson @ref Backend 5597a982d89SJeremy L. Thompson **/ 5607a982d89SJeremy L. Thompson 5617a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5627a982d89SJeremy L. Thompson *ceed = op->ceed; 563e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5647a982d89SJeremy L. Thompson } 5657a982d89SJeremy L. Thompson 5667a982d89SJeremy L. Thompson /** 5677a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5687a982d89SJeremy L. Thompson 5697a982d89SJeremy L. Thompson @param op CeedOperator 570d1d35e2fSjeremylt @param[out] num_elem Variable to store number of elements 5717a982d89SJeremy L. Thompson 5727a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5737a982d89SJeremy L. Thompson 5747a982d89SJeremy L. Thompson @ref Backend 5757a982d89SJeremy L. Thompson **/ 5767a982d89SJeremy L. Thompson 577d1d35e2fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 5787a982d89SJeremy L. Thompson if (op->composite) 5797a982d89SJeremy L. Thompson // LCOV_EXCL_START 580e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 581e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5827a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5837a982d89SJeremy L. Thompson 584d1d35e2fSjeremylt *num_elem = op->num_elem; 585e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5867a982d89SJeremy L. Thompson } 5877a982d89SJeremy L. Thompson 5887a982d89SJeremy L. Thompson /** 5897a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5907a982d89SJeremy L. Thompson 5917a982d89SJeremy L. Thompson @param op CeedOperator 592d1d35e2fSjeremylt @param[out] num_qpts Variable to store vector number of quadrature points 5937a982d89SJeremy L. Thompson 5947a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5957a982d89SJeremy L. Thompson 5967a982d89SJeremy L. Thompson @ref Backend 5977a982d89SJeremy L. Thompson **/ 5987a982d89SJeremy L. Thompson 599d1d35e2fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 6007a982d89SJeremy L. Thompson if (op->composite) 6017a982d89SJeremy L. Thompson // LCOV_EXCL_START 602e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 603e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6047a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6057a982d89SJeremy L. Thompson 606d1d35e2fSjeremylt *num_qpts = op->num_qpts; 607e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6087a982d89SJeremy L. Thompson } 6097a982d89SJeremy L. Thompson 6107a982d89SJeremy L. Thompson /** 6117a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 6127a982d89SJeremy L. Thompson 6137a982d89SJeremy L. Thompson @param op CeedOperator 614d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 6157a982d89SJeremy L. Thompson 6167a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6177a982d89SJeremy L. Thompson 6187a982d89SJeremy L. Thompson @ref Backend 6197a982d89SJeremy L. Thompson **/ 6207a982d89SJeremy L. Thompson 621d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 6227a982d89SJeremy L. Thompson if (op->composite) 6237a982d89SJeremy L. Thompson // LCOV_EXCL_START 624e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 625e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6267a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6277a982d89SJeremy L. Thompson 628d1d35e2fSjeremylt *num_args = op->num_fields; 629e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6307a982d89SJeremy L. Thompson } 6317a982d89SJeremy L. Thompson 6327a982d89SJeremy L. Thompson /** 6337a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6347a982d89SJeremy L. Thompson 6357a982d89SJeremy L. Thompson @param op CeedOperator 636d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 6377a982d89SJeremy L. Thompson 6387a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6397a982d89SJeremy L. Thompson 6407a982d89SJeremy L. Thompson @ref Backend 6417a982d89SJeremy L. Thompson **/ 6427a982d89SJeremy L. Thompson 643d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 644d1d35e2fSjeremylt *is_setup_done = op->backend_setup; 645e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6467a982d89SJeremy L. Thompson } 6477a982d89SJeremy L. Thompson 6487a982d89SJeremy L. Thompson /** 6497a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6507a982d89SJeremy L. Thompson 6517a982d89SJeremy L. Thompson @param op CeedOperator 6527a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6537a982d89SJeremy L. Thompson 6547a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson @ref Backend 6577a982d89SJeremy L. Thompson **/ 6587a982d89SJeremy L. Thompson 6597a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6607a982d89SJeremy L. Thompson if (op->composite) 6617a982d89SJeremy L. Thompson // LCOV_EXCL_START 662e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 663e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6647a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6657a982d89SJeremy L. Thompson 6667a982d89SJeremy L. Thompson *qf = op->qf; 667e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6687a982d89SJeremy L. Thompson } 6697a982d89SJeremy L. Thompson 6707a982d89SJeremy L. Thompson /** 671c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 672c04a41a7SJeremy L Thompson 673c04a41a7SJeremy L Thompson @param op CeedOperator 674d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 675c04a41a7SJeremy L Thompson 676c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 677c04a41a7SJeremy L Thompson 678c04a41a7SJeremy L Thompson @ref Backend 679c04a41a7SJeremy L Thompson **/ 680c04a41a7SJeremy L Thompson 681d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 682d1d35e2fSjeremylt *is_composite = op->composite; 683e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 684c04a41a7SJeremy L Thompson } 685c04a41a7SJeremy L Thompson 686c04a41a7SJeremy L Thompson /** 687d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 6887a982d89SJeremy L. Thompson 6897a982d89SJeremy L. Thompson @param op CeedOperator 690d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 6917a982d89SJeremy L. Thompson 6927a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6937a982d89SJeremy L. Thompson 6947a982d89SJeremy L. Thompson @ref Backend 6957a982d89SJeremy L. Thompson **/ 6967a982d89SJeremy L. Thompson 697d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 6987a982d89SJeremy L. Thompson if (!op->composite) 6997a982d89SJeremy L. Thompson // LCOV_EXCL_START 700e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7017a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7027a982d89SJeremy L. Thompson 703d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 704e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7057a982d89SJeremy L. Thompson } 7067a982d89SJeremy L. Thompson 7077a982d89SJeremy L. Thompson /** 708d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 7097a982d89SJeremy L. Thompson 7107a982d89SJeremy L. Thompson @param op CeedOperator 711d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 7127a982d89SJeremy L. Thompson 7137a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7147a982d89SJeremy L. Thompson 7157a982d89SJeremy L. Thompson @ref Backend 7167a982d89SJeremy L. Thompson **/ 7177a982d89SJeremy L. Thompson 718d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 7197a982d89SJeremy L. Thompson if (!op->composite) 7207a982d89SJeremy L. Thompson // LCOV_EXCL_START 721e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7227a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7237a982d89SJeremy L. Thompson 724d1d35e2fSjeremylt *sub_operators = op->sub_operators; 725e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7267a982d89SJeremy L. Thompson } 7277a982d89SJeremy L. Thompson 7287a982d89SJeremy L. Thompson /** 7297a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7307a982d89SJeremy L. Thompson 7317a982d89SJeremy L. Thompson @param op CeedOperator 7327a982d89SJeremy L. Thompson @param[out] data Variable to store data 7337a982d89SJeremy L. Thompson 7347a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7357a982d89SJeremy L. Thompson 7367a982d89SJeremy L. Thompson @ref Backend 7377a982d89SJeremy L. Thompson **/ 7387a982d89SJeremy L. Thompson 739777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 740777ff853SJeremy L Thompson *(void **)data = op->data; 741e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7427a982d89SJeremy L. Thompson } 7437a982d89SJeremy L. Thompson 7447a982d89SJeremy L. Thompson /** 7457a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7467a982d89SJeremy L. Thompson 7477a982d89SJeremy L. Thompson @param[out] op CeedOperator 7487a982d89SJeremy L. Thompson @param data Data to set 7497a982d89SJeremy L. Thompson 7507a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7517a982d89SJeremy L. Thompson 7527a982d89SJeremy L. Thompson @ref Backend 7537a982d89SJeremy L. Thompson **/ 7547a982d89SJeremy L. Thompson 755777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 756777ff853SJeremy L Thompson op->data = data; 757e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7587a982d89SJeremy L. Thompson } 7597a982d89SJeremy L. Thompson 7607a982d89SJeremy L. Thompson /** 76134359f16Sjeremylt @brief Increment the reference counter for a CeedOperator 76234359f16Sjeremylt 76334359f16Sjeremylt @param op CeedOperator to increment the reference counter 76434359f16Sjeremylt 76534359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 76634359f16Sjeremylt 76734359f16Sjeremylt @ref Backend 76834359f16Sjeremylt **/ 7699560d06aSjeremylt int CeedOperatorReference(CeedOperator op) { 77034359f16Sjeremylt op->ref_count++; 77134359f16Sjeremylt return CEED_ERROR_SUCCESS; 77234359f16Sjeremylt } 77334359f16Sjeremylt 77434359f16Sjeremylt /** 7757a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7767a982d89SJeremy L. Thompson 7777a982d89SJeremy L. Thompson @param op CeedOperator 7787a982d89SJeremy L. Thompson 7797a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7807a982d89SJeremy L. Thompson 7817a982d89SJeremy L. Thompson @ref Backend 7827a982d89SJeremy L. Thompson **/ 7837a982d89SJeremy L. Thompson 7847a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 785d1d35e2fSjeremylt op->backend_setup = true; 786e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7877a982d89SJeremy L. Thompson } 7887a982d89SJeremy L. Thompson 7897a982d89SJeremy L. Thompson /** 7907a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7917a982d89SJeremy L. Thompson 7927a982d89SJeremy L. Thompson @param op CeedOperator 793d1d35e2fSjeremylt @param[out] input_fields Variable to store input_fields 794d1d35e2fSjeremylt @param[out] output_fields Variable to store output_fields 7957a982d89SJeremy L. Thompson 7967a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7977a982d89SJeremy L. Thompson 7987a982d89SJeremy L. Thompson @ref Backend 7997a982d89SJeremy L. Thompson **/ 8007a982d89SJeremy L. Thompson 801d1d35e2fSjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **input_fields, 802d1d35e2fSjeremylt CeedOperatorField **output_fields) { 8037a982d89SJeremy L. Thompson if (op->composite) 8047a982d89SJeremy L. Thompson // LCOV_EXCL_START 805e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 806e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 8077a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 8087a982d89SJeremy L. Thompson 809d1d35e2fSjeremylt if (input_fields) *input_fields = op->input_fields; 810d1d35e2fSjeremylt if (output_fields) *output_fields = op->output_fields; 811e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8127a982d89SJeremy L. Thompson } 8137a982d89SJeremy L. Thompson 8147a982d89SJeremy L. Thompson /** 8157a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 8167a982d89SJeremy L. Thompson 817d1d35e2fSjeremylt @param op_field CeedOperatorField 8187a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 8197a982d89SJeremy L. Thompson 8207a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8217a982d89SJeremy L. Thompson 8227a982d89SJeremy L. Thompson @ref Backend 8237a982d89SJeremy L. Thompson **/ 8247a982d89SJeremy L. Thompson 825d1d35e2fSjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 8267a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 827d1d35e2fSjeremylt *rstr = op_field->elem_restr; 828e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8297a982d89SJeremy L. Thompson } 8307a982d89SJeremy L. Thompson 8317a982d89SJeremy L. Thompson /** 8327a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8337a982d89SJeremy L. Thompson 834d1d35e2fSjeremylt @param op_field CeedOperatorField 8357a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8367a982d89SJeremy L. Thompson 8377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8387a982d89SJeremy L. Thompson 8397a982d89SJeremy L. Thompson @ref Backend 8407a982d89SJeremy L. Thompson **/ 8417a982d89SJeremy L. Thompson 842d1d35e2fSjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 843d1d35e2fSjeremylt *basis = op_field->basis; 844e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8457a982d89SJeremy L. Thompson } 8467a982d89SJeremy L. Thompson 8477a982d89SJeremy L. Thompson /** 8487a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8497a982d89SJeremy L. Thompson 850d1d35e2fSjeremylt @param op_field CeedOperatorField 8517a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8527a982d89SJeremy L. Thompson 8537a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8547a982d89SJeremy L. Thompson 8557a982d89SJeremy L. Thompson @ref Backend 8567a982d89SJeremy L. Thompson **/ 8577a982d89SJeremy L. Thompson 858d1d35e2fSjeremylt int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 859d1d35e2fSjeremylt *vec = op_field->vec; 860e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8617a982d89SJeremy L. Thompson } 8627a982d89SJeremy L. Thompson 8637a982d89SJeremy L. Thompson /// @} 8647a982d89SJeremy L. Thompson 8657a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8667a982d89SJeremy L. Thompson /// CeedOperator Public API 8677a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8687a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 869dfdf5a53Sjeremylt /// @{ 870d7b241e6Sjeremylt 871d7b241e6Sjeremylt /** 8720219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8730219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8740219ea01SJeremy L Thompson \ref CeedOperatorSetField. 875d7b241e6Sjeremylt 876b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 877d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 87834138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8794cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 880d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8814cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 882b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 883b11c1e72Sjeremylt CeedOperator will be stored 884b11c1e72Sjeremylt 885b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 886dfdf5a53Sjeremylt 8877a982d89SJeremy L. Thompson @ref User 888d7b241e6Sjeremylt */ 889d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 890d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 891d7b241e6Sjeremylt int ierr; 892d7b241e6Sjeremylt 8935fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8945fe0d4faSjeremylt Ceed delegate; 895aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8965fe0d4faSjeremylt 8975fe0d4faSjeremylt if (!delegate) 898c042f62fSJeremy L Thompson // LCOV_EXCL_START 899e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 900e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 901c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9025fe0d4faSjeremylt 9035fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 904e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9055fe0d4faSjeremylt } 9065fe0d4faSjeremylt 907b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 908b3b7035fSJeremy L Thompson // LCOV_EXCL_START 909e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 910e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 911b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 912d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 913d7b241e6Sjeremylt (*op)->ceed = ceed; 9149560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 915d1d35e2fSjeremylt (*op)->ref_count = 1; 916d7b241e6Sjeremylt (*op)->qf = qf; 9179560d06aSjeremylt ierr = CeedQFunctionReference(qf); CeedChk(ierr); 918442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 919d7b241e6Sjeremylt (*op)->dqf = dqf; 9209560d06aSjeremylt ierr = CeedQFunctionReference(dqf); CeedChk(ierr); 921442e7f0bSjeremylt } 922442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 923d7b241e6Sjeremylt (*op)->dqfT = dqfT; 9249560d06aSjeremylt ierr = CeedQFunctionReference(dqfT); CeedChk(ierr); 925442e7f0bSjeremylt } 926d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr); 927d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr); 928d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 929e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 930d7b241e6Sjeremylt } 931d7b241e6Sjeremylt 932d7b241e6Sjeremylt /** 93352d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 93452d6035fSJeremy L Thompson 93552d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 93652d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 93752d6035fSJeremy L Thompson Composite CeedOperator will be stored 93852d6035fSJeremy L Thompson 93952d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 94052d6035fSJeremy L Thompson 9417a982d89SJeremy L. Thompson @ref User 94252d6035fSJeremy L Thompson */ 94352d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 94452d6035fSJeremy L Thompson int ierr; 94552d6035fSJeremy L Thompson 94652d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 94752d6035fSJeremy L Thompson Ceed delegate; 948aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 94952d6035fSJeremy L Thompson 950250756a7Sjeremylt if (delegate) { 95152d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 952e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 95352d6035fSJeremy L Thompson } 954250756a7Sjeremylt } 95552d6035fSJeremy L Thompson 95652d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 95752d6035fSJeremy L Thompson (*op)->ceed = ceed; 9589560d06aSjeremylt ierr = CeedReference(ceed); CeedChk(ierr); 95952d6035fSJeremy L Thompson (*op)->composite = true; 960d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr); 961250756a7Sjeremylt 962250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 96352d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 964250756a7Sjeremylt } 965e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 96652d6035fSJeremy L Thompson } 96752d6035fSJeremy L Thompson 96852d6035fSJeremy L Thompson /** 9699560d06aSjeremylt @brief Copy the pointer to a CeedOperator. Both pointers should 9709560d06aSjeremylt be destroyed with `CeedOperatorDestroy()`; 9719560d06aSjeremylt Note: If `*op_copy` is non-NULL, then it is assumed that 9729560d06aSjeremylt `*op_copy` is a pointer to a CeedOperator. This 9739560d06aSjeremylt CeedOperator will be destroyed if `*op_copy` is the only 9749560d06aSjeremylt reference to this CeedOperator. 9759560d06aSjeremylt 9769560d06aSjeremylt @param op CeedOperator to copy reference to 9779560d06aSjeremylt @param[out] op_copy Variable to store copied reference 9789560d06aSjeremylt 9799560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 9809560d06aSjeremylt 9819560d06aSjeremylt @ref User 9829560d06aSjeremylt **/ 9839560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) { 9849560d06aSjeremylt int ierr; 9859560d06aSjeremylt 9869560d06aSjeremylt ierr = CeedOperatorReference(op); CeedChk(ierr); 9879560d06aSjeremylt ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr); 9889560d06aSjeremylt *op_copy = op; 9899560d06aSjeremylt return CEED_ERROR_SUCCESS; 9909560d06aSjeremylt } 9919560d06aSjeremylt 9929560d06aSjeremylt /** 993b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 994d7b241e6Sjeremylt 995d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 996d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 997d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 998d7b241e6Sjeremylt 999d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 1000d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 1001d7b241e6Sjeremylt input and at most one active output. 1002d7b241e6Sjeremylt 10038c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 1004d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 10058795c945Sjeremylt CeedQFunction) 1006b11c1e72Sjeremylt @param r CeedElemRestriction 10074cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 1008b11c1e72Sjeremylt if collocated with quadrature points 10094cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 10104cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 10114cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 1012b11c1e72Sjeremylt 1013b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1014dfdf5a53Sjeremylt 10157a982d89SJeremy L. Thompson @ref User 1016b11c1e72Sjeremylt **/ 1017d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 1018a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 1019d7b241e6Sjeremylt int ierr; 102052d6035fSJeremy L Thompson if (op->composite) 1021c042f62fSJeremy L Thompson // LCOV_EXCL_START 1022e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1023e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 1024c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10258b067b84SJed Brown if (!r) 1026c042f62fSJeremy L Thompson // LCOV_EXCL_START 1027e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1028c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 1029d1d35e2fSjeremylt field_name); 1030c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10318b067b84SJed Brown if (!b) 1032c042f62fSJeremy L Thompson // LCOV_EXCL_START 1033e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1034e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 1035d1d35e2fSjeremylt field_name); 1036c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10378b067b84SJed Brown if (!v) 1038c042f62fSJeremy L Thompson // LCOV_EXCL_START 1039e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1040e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 1041d1d35e2fSjeremylt field_name); 1042c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 104352d6035fSJeremy L Thompson 1044d1d35e2fSjeremylt CeedInt num_elem; 1045d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 1046d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 1047d1d35e2fSjeremylt op->num_elem != num_elem) 1048c042f62fSJeremy L Thompson // LCOV_EXCL_START 1049e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10501d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1051d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 1052c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1053d7b241e6Sjeremylt 105478464608Sjeremylt CeedInt num_qpts = 0; 1055e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1056d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 1057d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 1058c042f62fSJeremy L Thompson // LCOV_EXCL_START 1059e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1060e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 1061d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 1062d1d35e2fSjeremylt op->num_qpts); 1063c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1064d7b241e6Sjeremylt } 1065d1d35e2fSjeremylt CeedQFunctionField qf_field; 1066d1d35e2fSjeremylt CeedOperatorField *op_field; 1067d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 1068d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 1069d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 1070d1d35e2fSjeremylt op_field = &op->input_fields[i]; 1071d7b241e6Sjeremylt goto found; 1072d7b241e6Sjeremylt } 1073d7b241e6Sjeremylt } 1074d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 1075d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 1076d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 1077d1d35e2fSjeremylt op_field = &op->output_fields[i]; 1078d7b241e6Sjeremylt goto found; 1079d7b241e6Sjeremylt } 1080d7b241e6Sjeremylt } 1081c042f62fSJeremy L Thompson // LCOV_EXCL_START 1082e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1083e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1084d1d35e2fSjeremylt field_name); 1085c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1086d7b241e6Sjeremylt found: 1087d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 1088d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 1089e15f9bd0SJeremy L Thompson 1090d1d35e2fSjeremylt (*op_field)->vec = v; 1091e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 10929560d06aSjeremylt ierr = CeedVectorReference(v); CeedChk(ierr); 1093e15f9bd0SJeremy L Thompson } 1094e15f9bd0SJeremy L Thompson 1095d1d35e2fSjeremylt (*op_field)->elem_restr = r; 10969560d06aSjeremylt ierr = CeedElemRestrictionReference(r); CeedChk(ierr); 1097e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1098d1d35e2fSjeremylt op->num_elem = num_elem; 1099d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 1100e15f9bd0SJeremy L Thompson } 1101d99fa3c5SJeremy L Thompson 1102d1d35e2fSjeremylt (*op_field)->basis = b; 1103e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1104*cd4dfc48Sjeremylt if (!op->num_qpts) { 1105*cd4dfc48Sjeremylt ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr); 1106*cd4dfc48Sjeremylt } 11079560d06aSjeremylt ierr = CeedBasisReference(b); CeedChk(ierr); 1108e15f9bd0SJeremy L Thompson } 1109e15f9bd0SJeremy L Thompson 1110d1d35e2fSjeremylt op->num_fields += 1; 1111d1d35e2fSjeremylt size_t len = strlen(field_name); 1112d99fa3c5SJeremy L Thompson char *tmp; 1113d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1114d1d35e2fSjeremylt memcpy(tmp, field_name, len+1); 1115d1d35e2fSjeremylt (*op_field)->field_name = tmp; 1116e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1117d7b241e6Sjeremylt } 1118d7b241e6Sjeremylt 1119d7b241e6Sjeremylt /** 112052d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1121288c0443SJeremy L Thompson 1122d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 1123d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 112452d6035fSJeremy L Thompson 112552d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 112652d6035fSJeremy L Thompson 11277a982d89SJeremy L. Thompson @ref User 112852d6035fSJeremy L Thompson */ 1129d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 1130d1d35e2fSjeremylt CeedOperator sub_op) { 113134359f16Sjeremylt int ierr; 113234359f16Sjeremylt 1133d1d35e2fSjeremylt if (!composite_op->composite) 1134c042f62fSJeremy L Thompson // LCOV_EXCL_START 1135d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 1136e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1137c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 113852d6035fSJeremy L Thompson 1139d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 1140c042f62fSJeremy L Thompson // LCOV_EXCL_START 1141d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 1142d1d35e2fSjeremylt "Cannot add additional sub_operators"); 1143c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 114452d6035fSJeremy L Thompson 1145d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 11469560d06aSjeremylt ierr = CeedOperatorReference(sub_op); CeedChk(ierr); 1147d1d35e2fSjeremylt composite_op->num_suboperators++; 1148e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 114952d6035fSJeremy L Thompson } 115052d6035fSJeremy L Thompson 115152d6035fSJeremy L Thompson /** 11521d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11531d102b48SJeremy L Thompson 11541d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11551d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11561d102b48SJeremy L Thompson The vector 'assembled' is of shape 11571d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11581d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11591d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11601d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11614cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11621d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11631d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11641d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11651d102b48SJeremy L Thompson 11661d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11671d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11681d102b48SJeremy L Thompson quadrature points 11691d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11701d102b48SJeremy L Thompson CeedQFunction 11711d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11724cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11731d102b48SJeremy L Thompson 11741d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11751d102b48SJeremy L Thompson 11767a982d89SJeremy L. Thompson @ref User 11771d102b48SJeremy L Thompson **/ 117880ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11797f823360Sjeremylt CeedElemRestriction *rstr, 11807f823360Sjeremylt CeedRequest *request) { 11811d102b48SJeremy L Thompson int ierr; 1182e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11831d102b48SJeremy L Thompson 11847172caadSjeremylt // Backend version 118580ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1186e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11875107b09fSJeremy L Thompson } else { 11885107b09fSJeremy L Thompson // Fallback to reference Ceed 1189d1d35e2fSjeremylt if (!op->op_fallback) { 11905107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11915107b09fSJeremy L Thompson } 11925107b09fSJeremy L Thompson // Assemble 1193d1d35e2fSjeremylt return CeedOperatorLinearAssembleQFunction(op->op_fallback, assembled, 1194e2f04181SAndrew T. Barker rstr, request); 11955107b09fSJeremy L Thompson } 11961d102b48SJeremy L Thompson } 11971d102b48SJeremy L Thompson 11981d102b48SJeremy L Thompson /** 1199d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1200b7ec98d8SJeremy L Thompson 12019e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1202b7ec98d8SJeremy L Thompson 1203c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1204c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1205d965c7a7SJeremy L Thompson 1206b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1207b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1208b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12094cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1210b7ec98d8SJeremy L Thompson 1211b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1212b7ec98d8SJeremy L Thompson 12137a982d89SJeremy L. Thompson @ref User 1214b7ec98d8SJeremy L Thompson **/ 12152bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 12167f823360Sjeremylt CeedRequest *request) { 1217b7ec98d8SJeremy L Thompson int ierr; 1218e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1219b7ec98d8SJeremy L Thompson 1220b7ec98d8SJeremy L Thompson // Use backend version, if available 122180ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1222e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 12239e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 12249e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12259e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 12269e9210b8SJeremy L Thompson } else { 12279e9210b8SJeremy L Thompson // Fallback to reference Ceed 1228d1d35e2fSjeremylt if (!op->op_fallback) { 12299e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 12309e9210b8SJeremy L Thompson } 12319e9210b8SJeremy L Thompson // Assemble 1232d1d35e2fSjeremylt return CeedOperatorLinearAssembleDiagonal(op->op_fallback, assembled, 1233e2f04181SAndrew T. Barker request); 12349e9210b8SJeremy L Thompson } 12359e9210b8SJeremy L Thompson } 12369e9210b8SJeremy L Thompson 12379e9210b8SJeremy L Thompson /** 12389e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 12399e9210b8SJeremy L Thompson 12409e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 12419e9210b8SJeremy L Thompson 12429e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12439e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12449e9210b8SJeremy L Thompson 12459e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12469e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 12479e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12489e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 12499e9210b8SJeremy L Thompson 12509e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12519e9210b8SJeremy L Thompson 12529e9210b8SJeremy L Thompson @ref User 12539e9210b8SJeremy L Thompson **/ 12549e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12559e9210b8SJeremy L Thompson CeedRequest *request) { 12569e9210b8SJeremy L Thompson int ierr; 1257e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12589e9210b8SJeremy L Thompson 12599e9210b8SJeremy L Thompson // Use backend version, if available 12609e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1261e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12627172caadSjeremylt } else { 12637172caadSjeremylt // Fallback to reference Ceed 1264d1d35e2fSjeremylt if (!op->op_fallback) { 12657172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1266b7ec98d8SJeremy L Thompson } 12677172caadSjeremylt // Assemble 1268d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddDiagonal(op->op_fallback, assembled, 1269e2f04181SAndrew T. Barker request); 1270b7ec98d8SJeremy L Thompson } 1271b7ec98d8SJeremy L Thompson } 1272b7ec98d8SJeremy L Thompson 1273b7ec98d8SJeremy L Thompson /** 1274d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1275d965c7a7SJeremy L Thompson 12769e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1277d965c7a7SJeremy L Thompson CeedOperator. 1278d965c7a7SJeremy L Thompson 1279c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1280c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1281d965c7a7SJeremy L Thompson 1282d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1283d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1284d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1285d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 1286d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1287d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1288d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1289d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1290d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1291d965c7a7SJeremy L Thompson 1292d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1293d965c7a7SJeremy L Thompson 1294d965c7a7SJeremy L Thompson @ref User 1295d965c7a7SJeremy L Thompson **/ 129680ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12972bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1298d965c7a7SJeremy L Thompson int ierr; 1299e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1300d965c7a7SJeremy L Thompson 1301d965c7a7SJeremy L Thompson // Use backend version, if available 130280ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1303e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 13049e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 13059e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 13069e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 13079e9210b8SJeremy L Thompson request); 1308d965c7a7SJeremy L Thompson } else { 1309d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1310d1d35e2fSjeremylt if (!op->op_fallback) { 1311d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1312d965c7a7SJeremy L Thompson } 1313d965c7a7SJeremy L Thompson // Assemble 1314d1d35e2fSjeremylt return CeedOperatorLinearAssemblePointBlockDiagonal(op->op_fallback, 1315e2f04181SAndrew T. Barker assembled, request); 13169e9210b8SJeremy L Thompson } 13179e9210b8SJeremy L Thompson } 13189e9210b8SJeremy L Thompson 13199e9210b8SJeremy L Thompson /** 13209e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 13219e9210b8SJeremy L Thompson 13229e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 13239e9210b8SJeremy L Thompson CeedOperator. 13249e9210b8SJeremy L Thompson 13259e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 13269e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 13279e9210b8SJeremy L Thompson 13289e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 13299e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 13309e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 1331d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 13329e9210b8SJeremy L Thompson of this vector are derived from the active vector 13339e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 13349e9210b8SJeremy L Thompson [nodes, component out, component in]. 13359e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 13369e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 13379e9210b8SJeremy L Thompson 13389e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13399e9210b8SJeremy L Thompson 13409e9210b8SJeremy L Thompson @ref User 13419e9210b8SJeremy L Thompson **/ 13429e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 13439e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 13449e9210b8SJeremy L Thompson int ierr; 1345e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 13469e9210b8SJeremy L Thompson 13479e9210b8SJeremy L Thompson // Use backend version, if available 13489e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1349e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 13509e9210b8SJeremy L Thompson } else { 13519e9210b8SJeremy L Thompson // Fallback to reference Ceed 1352d1d35e2fSjeremylt if (!op->op_fallback) { 13539e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13549e9210b8SJeremy L Thompson } 13559e9210b8SJeremy L Thompson // Assemble 1356d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->op_fallback, 1357e2f04181SAndrew T. Barker assembled, request); 1358d965c7a7SJeremy L Thompson } 1359e2f04181SAndrew T. Barker } 1360e2f04181SAndrew T. Barker 1361e2f04181SAndrew T. Barker /** 1362e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1363e2f04181SAndrew T. Barker 1364e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1365e2f04181SAndrew T. Barker 1366e2f04181SAndrew T. Barker @ref Developer 1367e2f04181SAndrew T. Barker **/ 1368e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1369e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1370e2f04181SAndrew T. Barker int ierr; 1371e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1372e2f04181SAndrew T. Barker if (op->composite) 1373e2f04181SAndrew T. Barker // LCOV_EXCL_START 1374e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1375e2f04181SAndrew T. Barker "Composite operator not supported"); 1376e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1377e2f04181SAndrew T. Barker 1378d1d35e2fSjeremylt CeedElemRestriction rstr_in; 1379d1d35e2fSjeremylt ierr = CeedOperatorGetActiveElemRestriction(op, &rstr_in); CeedChk(ierr); 1380d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_nodes, num_comp; 1381d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1382d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1383d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr_in, &num_nodes); CeedChk(ierr); 1384d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1385e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1386d1d35e2fSjeremylt ierr = CeedElemRestrictionGetELayout(rstr_in, &layout_er); CeedChk(ierr); 1387e2f04181SAndrew T. Barker 1388d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1389e2f04181SAndrew T. Barker 1390e2f04181SAndrew T. Barker // Determine elem_dof relation 1391e2f04181SAndrew T. Barker CeedVector index_vec; 1392d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_nodes, &index_vec); CeedChk(ierr); 1393e2f04181SAndrew T. Barker CeedScalar *array; 1394e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1395d1d35e2fSjeremylt for (CeedInt i = 0; i < num_nodes; ++i) { 1396e2f04181SAndrew T. Barker array[i] = i; 1397e2f04181SAndrew T. Barker } 1398e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1399e2f04181SAndrew T. Barker CeedVector elem_dof; 1400d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_elem * elem_size * num_comp, &elem_dof); 1401e2f04181SAndrew T. Barker CeedChk(ierr); 1402e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1403d1d35e2fSjeremylt CeedElemRestrictionApply(rstr_in, CEED_NOTRANSPOSE, index_vec, 1404e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1405e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1406e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1407e2f04181SAndrew T. Barker CeedChk(ierr); 1408e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1409e2f04181SAndrew T. Barker 1410e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1411e2f04181SAndrew T. Barker CeedInt count = 0; 1412d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1413d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1414d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1415d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1416d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1417d1d35e2fSjeremylt const CeedInt elem_dof_index_row = (i)*layout_er[0] + 1418d1d35e2fSjeremylt (comp_out)*layout_er[1] + e*layout_er[2]; 1419d1d35e2fSjeremylt const CeedInt elem_dof_index_col = (j)*layout_er[0] + 1420d1d35e2fSjeremylt (comp_in)*layout_er[1] + e*layout_er[2]; 1421e2f04181SAndrew T. Barker 1422d1d35e2fSjeremylt const CeedInt row = elem_dof_a[elem_dof_index_row]; 1423d1d35e2fSjeremylt const CeedInt col = elem_dof_a[elem_dof_index_col]; 1424e2f04181SAndrew T. Barker 1425e2f04181SAndrew T. Barker rows[offset + count] = row; 1426e2f04181SAndrew T. Barker cols[offset + count] = col; 1427e2f04181SAndrew T. Barker count++; 1428e2f04181SAndrew T. Barker } 1429e2f04181SAndrew T. Barker } 1430e2f04181SAndrew T. Barker } 1431e2f04181SAndrew T. Barker } 1432e2f04181SAndrew T. Barker } 1433d1d35e2fSjeremylt if (count != local_num_entries) 1434e2f04181SAndrew T. Barker // LCOV_EXCL_START 1435e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1436e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1437e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1438e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1439e2f04181SAndrew T. Barker 1440e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1441e2f04181SAndrew T. Barker } 1442e2f04181SAndrew T. Barker 1443e2f04181SAndrew T. Barker /** 1444e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1445e2f04181SAndrew T. Barker 1446e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1447e2f04181SAndrew T. Barker 1448e2f04181SAndrew T. Barker @ref Developer 1449e2f04181SAndrew T. Barker **/ 1450e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1451e2f04181SAndrew T. Barker CeedVector values) { 1452e2f04181SAndrew T. Barker int ierr; 1453e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1454e2f04181SAndrew T. Barker if (op->composite) 1455e2f04181SAndrew T. Barker // LCOV_EXCL_START 1456e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1457e2f04181SAndrew T. Barker "Composite operator not supported"); 1458e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1459e2f04181SAndrew T. Barker 1460e2f04181SAndrew T. Barker // Assemble QFunction 1461e2f04181SAndrew T. Barker CeedQFunction qf; 1462e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1463d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 1464d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 1465e2f04181SAndrew T. Barker CeedChk(ierr); 1466d1d35e2fSjeremylt CeedVector assembled_qf; 1467e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1468e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1469d1d35e2fSjeremylt op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1470e2f04181SAndrew T. Barker 1471d1d35e2fSjeremylt CeedInt qf_length; 1472d1d35e2fSjeremylt ierr = CeedVectorGetLength(assembled_qf, &qf_length); CeedChk(ierr); 1473e2f04181SAndrew T. Barker 1474e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1475e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1476e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1477e2f04181SAndrew T. Barker 1478e2f04181SAndrew T. Barker // Determine active input basis 1479d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1480d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChk(ierr); 1481d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, dim = 1; 1482d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 1483d1d35e2fSjeremylt CeedBasis basis_in = NULL; 1484d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 1485d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1486e2f04181SAndrew T. Barker CeedVector vec; 1487e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1488e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1489d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(input_fields[i], &basis_in); 1490e2f04181SAndrew T. Barker CeedChk(ierr); 1491d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChk(ierr); 1492d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in); 1493e2f04181SAndrew T. Barker CeedChk(ierr); 1494d1d35e2fSjeremylt CeedEvalMode eval_mode; 1495d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1496e2f04181SAndrew T. Barker CeedChk(ierr); 1497d1d35e2fSjeremylt switch (eval_mode) { 1498e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1499e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1500d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChk(ierr); 1501d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 1502d1d35e2fSjeremylt num_eval_mode_in += 1; 1503e2f04181SAndrew T. Barker break; 1504e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1505d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChk(ierr); 1506e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1507d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 1508e2f04181SAndrew T. Barker } 1509d1d35e2fSjeremylt num_eval_mode_in += dim; 1510e2f04181SAndrew T. Barker break; 1511e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1512e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1513e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1514e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1515e2f04181SAndrew T. Barker } 1516e2f04181SAndrew T. Barker } 1517e2f04181SAndrew T. Barker } 1518e2f04181SAndrew T. Barker 1519e2f04181SAndrew T. Barker // Determine active output basis 1520d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChk(ierr); 1521d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 1522d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 1523d1d35e2fSjeremylt CeedBasis basis_out = NULL; 1524d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 1525d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 1526e2f04181SAndrew T. Barker CeedVector vec; 1527e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1528e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1529d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(output_fields[i], &basis_out); 1530e2f04181SAndrew T. Barker CeedChk(ierr); 1531d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out); 1532e2f04181SAndrew T. Barker CeedChk(ierr); 1533d1d35e2fSjeremylt CeedEvalMode eval_mode; 1534d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1535e2f04181SAndrew T. Barker CeedChk(ierr); 1536d1d35e2fSjeremylt switch (eval_mode) { 1537e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1538e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1539d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChk(ierr); 1540d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 1541d1d35e2fSjeremylt num_eval_mode_out += 1; 1542e2f04181SAndrew T. Barker break; 1543e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1544d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); CeedChk(ierr); 1545e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1546d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 1547e2f04181SAndrew T. Barker } 1548d1d35e2fSjeremylt num_eval_mode_out += dim; 1549e2f04181SAndrew T. Barker break; 1550e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1551e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1552e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1553e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1554e2f04181SAndrew T. Barker } 1555e2f04181SAndrew T. Barker } 1556e2f04181SAndrew T. Barker } 1557e2f04181SAndrew T. Barker 155878464608Sjeremylt if (num_eval_mode_in == 0 || num_eval_mode_out == 0) 155978464608Sjeremylt // LCOV_EXCL_START 156078464608Sjeremylt return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 156178464608Sjeremylt "Cannot assemble operator with out inputs/outputs"); 156278464608Sjeremylt // LCOV_EXCL_STOP 156378464608Sjeremylt 1564d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_qpts, num_comp; 1565d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1566d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1567d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1568d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); CeedChk(ierr); 1569e2f04181SAndrew T. Barker 1570d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1571e2f04181SAndrew T. Barker 1572e2f04181SAndrew T. Barker // loop over elements and put in data structure 1573d1d35e2fSjeremylt const CeedScalar *interp_in, *grad_in; 1574d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChk(ierr); 1575d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChk(ierr); 1576e2f04181SAndrew T. Barker 1577d1d35e2fSjeremylt const CeedScalar *assembled_qf_array; 1578d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 1579e2f04181SAndrew T. Barker CeedChk(ierr); 1580e2f04181SAndrew T. Barker 1581e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1582e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1583e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1584e2f04181SAndrew T. Barker 1585d1d35e2fSjeremylt // we store B_mat_in, B_mat_out, BTD, elem_mat in row-major order 1586d1d35e2fSjeremylt CeedScalar B_mat_in[(num_qpts * num_eval_mode_in) * elem_size]; 1587d1d35e2fSjeremylt CeedScalar B_mat_out[(num_qpts * num_eval_mode_out) * elem_size]; 1588d1d35e2fSjeremylt CeedScalar D_mat[num_eval_mode_out * num_eval_mode_in * 1589d1d35e2fSjeremylt num_qpts]; // logically 3-tensor 1590d1d35e2fSjeremylt CeedScalar BTD[elem_size * num_qpts*num_eval_mode_in]; 1591d1d35e2fSjeremylt CeedScalar elem_mat[elem_size * elem_size]; 1592e2f04181SAndrew T. Barker int count = 0; 1593e2f04181SAndrew T. Barker CeedScalar *vals; 1594e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1595d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1596d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1597d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1598d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_in) * elem_size; ++ell) { 1599d1d35e2fSjeremylt B_mat_in[ell] = 0.0; 1600e2f04181SAndrew T. Barker } 1601d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_out) * elem_size; ++ell) { 1602d1d35e2fSjeremylt B_mat_out[ell] = 0.0; 1603e2f04181SAndrew T. Barker } 1604e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1605d1d35e2fSjeremylt for (int ell = 0; ell < num_eval_mode_in*num_eval_mode_out*num_qpts; ++ell) { 1606d1d35e2fSjeremylt D_mat[ell] = 0.0; 1607e2f04181SAndrew T. Barker } 1608e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1609d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*elem_size; ++ell) { 1610e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1611e2f04181SAndrew T. Barker } 1612d1d35e2fSjeremylt for (int q = 0; q < num_qpts; ++q) { 1613d1d35e2fSjeremylt for (int n = 0; n < elem_size; ++n) { 1614d1d35e2fSjeremylt CeedInt d_in = -1; 1615d1d35e2fSjeremylt for (int e_in = 0; e_in < num_eval_mode_in; ++e_in) { 1616d1d35e2fSjeremylt const int qq = num_eval_mode_in*q; 1617d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_INTERP) { 1618d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += interp_in[q * elem_size + n]; 1619d1d35e2fSjeremylt } else if (eval_mode_in[e_in] == CEED_EVAL_GRAD) { 1620d1d35e2fSjeremylt d_in += 1; 1621d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += 1622d1d35e2fSjeremylt grad_in[(d_in*num_qpts+q) * elem_size + n]; 1623e2f04181SAndrew T. Barker } else { 1624e2f04181SAndrew T. Barker // LCOV_EXCL_START 1625e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1626e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1627e2f04181SAndrew T. Barker } 1628e2f04181SAndrew T. Barker } 1629d1d35e2fSjeremylt CeedInt d_out = -1; 1630d1d35e2fSjeremylt for (int e_out = 0; e_out < num_eval_mode_out; ++e_out) { 1631d1d35e2fSjeremylt const int qq = num_eval_mode_out*q; 1632d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_INTERP) { 1633d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += interp_in[q * elem_size + n]; 1634d1d35e2fSjeremylt } else if (eval_mode_out[e_out] == CEED_EVAL_GRAD) { 1635d1d35e2fSjeremylt d_out += 1; 1636d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += 1637d1d35e2fSjeremylt grad_in[(d_out*num_qpts+q) * elem_size + n]; 1638e2f04181SAndrew T. Barker } else { 1639e2f04181SAndrew T. Barker // LCOV_EXCL_START 1640e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1641e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1642e2f04181SAndrew T. Barker } 1643e2f04181SAndrew T. Barker } 1644e2f04181SAndrew T. Barker } 1645d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_out; ++ei) { 1646d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_in; ++ej) { 1647d1d35e2fSjeremylt const int eval_mode_index = ((ei*num_comp+comp_in)*num_eval_mode_in+ej)*num_comp 1648d1d35e2fSjeremylt +comp_out; 1649d1d35e2fSjeremylt const int index = q*layout_qf[0] + eval_mode_index*layout_qf[1] + 1650d1d35e2fSjeremylt e*layout_qf[2]; 1651d1d35e2fSjeremylt D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q] += assembled_qf_array[index]; 1652e2f04181SAndrew T. Barker } 1653e2f04181SAndrew T. Barker } 1654e2f04181SAndrew T. Barker } 1655e2f04181SAndrew T. Barker // Compute B^T*D 1656d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*num_qpts*num_eval_mode_in; ++ell) { 1657e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1658e2f04181SAndrew T. Barker } 1659d1d35e2fSjeremylt for (int j = 0; j<elem_size; ++j) { 1660d1d35e2fSjeremylt for (int q = 0; q<num_qpts; ++q) { 1661d1d35e2fSjeremylt int qq = num_eval_mode_out*q; 1662d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_in; ++ei) { 1663d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_out; ++ej) { 1664d1d35e2fSjeremylt BTD[j*(num_qpts*num_eval_mode_in) + (qq+ei)] += 1665d1d35e2fSjeremylt B_mat_out[(qq+ej)*elem_size + j] * D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q]; 1666e2f04181SAndrew T. Barker } 1667e2f04181SAndrew T. Barker } 1668e2f04181SAndrew T. Barker } 1669e2f04181SAndrew T. Barker } 1670e2f04181SAndrew T. Barker 1671d1d35e2fSjeremylt ierr = CeedMatrixMultiply(ceed, BTD, B_mat_in, elem_mat, elem_size, 1672d1d35e2fSjeremylt elem_size, num_qpts*num_eval_mode_in); CeedChk(ierr); 1673e2f04181SAndrew T. Barker 1674e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1675d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1676d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1677d1d35e2fSjeremylt vals[offset + count] = elem_mat[i*elem_size + j]; 1678e2f04181SAndrew T. Barker count++; 1679e2f04181SAndrew T. Barker } 1680e2f04181SAndrew T. Barker } 1681e2f04181SAndrew T. Barker } 1682e2f04181SAndrew T. Barker } 1683e2f04181SAndrew T. Barker } 1684d1d35e2fSjeremylt if (count != local_num_entries) 1685e2f04181SAndrew T. Barker // LCOV_EXCL_START 1686e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1687e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1688e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1689e2f04181SAndrew T. Barker 1690d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(assembled_qf, &assembled_qf_array); 1691e2f04181SAndrew T. Barker CeedChk(ierr); 1692d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChk(ierr); 1693d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChk(ierr); 1694d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChk(ierr); 1695e2f04181SAndrew T. Barker 1696e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1697e2f04181SAndrew T. Barker } 1698e2f04181SAndrew T. Barker 1699e2f04181SAndrew T. Barker /** 1700e2f04181SAndrew T. Barker @ref Utility 1701e2f04181SAndrew T. Barker **/ 1702d1d35e2fSjeremylt int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, 1703d1d35e2fSjeremylt CeedInt *num_entries) { 1704e2f04181SAndrew T. Barker int ierr; 1705e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1706d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_comp; 1707e2f04181SAndrew T. Barker 1708e2f04181SAndrew T. Barker if (op->composite) 1709e2f04181SAndrew T. Barker // LCOV_EXCL_START 1710e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1711e2f04181SAndrew T. Barker "Composite operator not supported"); 1712e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1713e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1714d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChk(ierr); 1715d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); CeedChk(ierr); 1716d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); CeedChk(ierr); 1717d1d35e2fSjeremylt *num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1718e2f04181SAndrew T. Barker 1719e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1720e2f04181SAndrew T. Barker } 1721e2f04181SAndrew T. Barker 1722e2f04181SAndrew T. Barker /** 1723e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1724e2f04181SAndrew T. Barker 1725e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1726e2f04181SAndrew T. Barker 1727d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1728e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1729e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1730e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1731e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1732e2f04181SAndrew T. Barker ordering. 1733e2f04181SAndrew T. Barker 1734e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1735e2f04181SAndrew T. Barker 1736e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1737d1d35e2fSjeremylt @param[out] num_entries Number of entries in coordinate nonzero pattern. 1738e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1739e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1740e2f04181SAndrew T. Barker 1741e2f04181SAndrew T. Barker @ref User 1742e2f04181SAndrew T. Barker **/ 1743e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1744d1d35e2fSjeremylt CeedInt *num_entries, CeedInt **rows, CeedInt **cols) { 1745e2f04181SAndrew T. Barker int ierr; 1746d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1747d1d35e2fSjeremylt CeedOperator *sub_operators; 1748d1d35e2fSjeremylt bool is_composite; 1749e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1750e2f04181SAndrew T. Barker 1751e2f04181SAndrew T. Barker // Use backend version, if available 1752e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1753d1d35e2fSjeremylt return op->LinearAssembleSymbolic(op, num_entries, rows, cols); 1754e2f04181SAndrew T. Barker } else { 1755e2f04181SAndrew T. Barker // Check for valid fallback resource 1756d1d35e2fSjeremylt const char *resource, *fallback_resource; 1757e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1758d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 175978464608Sjeremylt CeedChk(ierr); 1760d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1761e2f04181SAndrew T. Barker // Fallback to reference Ceed 1762d1d35e2fSjeremylt if (!op->op_fallback) { 1763e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1764e2f04181SAndrew T. Barker } 1765e2f04181SAndrew T. Barker // Assemble 1766d1d35e2fSjeremylt return CeedOperatorLinearAssembleSymbolic(op->op_fallback, num_entries, rows, 1767d1d35e2fSjeremylt cols); 1768e2f04181SAndrew T. Barker } 1769e2f04181SAndrew T. Barker } 1770e2f04181SAndrew T. Barker 1771e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1772e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1773e2f04181SAndrew T. Barker 1774e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1775d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1776d1d35e2fSjeremylt *num_entries = 0; 1777d1d35e2fSjeremylt if (is_composite) { 1778d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1779d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1780d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1781d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1782e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1783d1d35e2fSjeremylt *num_entries += single_entries; 1784e2f04181SAndrew T. Barker } 1785e2f04181SAndrew T. Barker } else { 1786e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1787e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1788d1d35e2fSjeremylt *num_entries += single_entries; 1789e2f04181SAndrew T. Barker } 1790d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, rows); CeedChk(ierr); 1791d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, cols); CeedChk(ierr); 1792e2f04181SAndrew T. Barker 1793e2f04181SAndrew T. Barker // assemble nonzero locations 1794e2f04181SAndrew T. Barker CeedInt offset = 0; 1795d1d35e2fSjeremylt if (is_composite) { 1796d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1797d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1798d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1799d1d35e2fSjeremylt ierr = CeedSingleOperatorAssembleSymbolic(sub_operators[k], offset, *rows, 1800e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1801d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1802d1d35e2fSjeremylt &single_entries); 1803e2f04181SAndrew T. Barker CeedChk(ierr); 1804e2f04181SAndrew T. Barker offset += single_entries; 1805e2f04181SAndrew T. Barker } 1806e2f04181SAndrew T. Barker } else { 1807e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1808e2f04181SAndrew T. Barker CeedChk(ierr); 1809e2f04181SAndrew T. Barker } 1810e2f04181SAndrew T. Barker 1811e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1812e2f04181SAndrew T. Barker } 1813e2f04181SAndrew T. Barker 1814e2f04181SAndrew T. Barker /** 1815e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1816e2f04181SAndrew T. Barker 1817e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1818e2f04181SAndrew T. Barker 1819d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1820e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1821e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1822e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1823e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1824e2f04181SAndrew T. Barker 1825e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1826e2f04181SAndrew T. Barker 1827e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1828e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1829e2f04181SAndrew T. Barker 1830e2f04181SAndrew T. Barker @ref User 1831e2f04181SAndrew T. Barker **/ 1832e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1833e2f04181SAndrew T. Barker int ierr; 183478464608Sjeremylt CeedInt num_suboperators, single_entries = 0; 1835d1d35e2fSjeremylt CeedOperator *sub_operators; 1836e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1837e2f04181SAndrew T. Barker 1838e2f04181SAndrew T. Barker // Use backend version, if available 1839e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1840e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1841e2f04181SAndrew T. Barker } else { 1842e2f04181SAndrew T. Barker // Check for valid fallback resource 1843d1d35e2fSjeremylt const char *resource, *fallback_resource; 1844e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1845d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 184678464608Sjeremylt CeedChk(ierr); 1847d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1848e2f04181SAndrew T. Barker // Fallback to reference Ceed 1849d1d35e2fSjeremylt if (!op->op_fallback) { 1850e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1851e2f04181SAndrew T. Barker } 1852e2f04181SAndrew T. Barker // Assemble 1853d1d35e2fSjeremylt return CeedOperatorLinearAssemble(op->op_fallback, values); 1854e2f04181SAndrew T. Barker } 1855e2f04181SAndrew T. Barker } 1856e2f04181SAndrew T. Barker 1857e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1858e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1859e2f04181SAndrew T. Barker 1860d1d35e2fSjeremylt bool is_composite; 1861d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1862e2f04181SAndrew T. Barker 1863e2f04181SAndrew T. Barker CeedInt offset = 0; 1864d1d35e2fSjeremylt if (is_composite) { 1865d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1866d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1867d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1868d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemble(sub_operators[k], offset, values); 1869e2f04181SAndrew T. Barker CeedChk(ierr); 1870d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1871d1d35e2fSjeremylt &single_entries); 1872e2f04181SAndrew T. Barker CeedChk(ierr); 1873e2f04181SAndrew T. Barker offset += single_entries; 1874e2f04181SAndrew T. Barker } 1875e2f04181SAndrew T. Barker } else { 1876e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1877e2f04181SAndrew T. Barker } 1878e2f04181SAndrew T. Barker 1879e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1880d965c7a7SJeremy L Thompson } 1881d965c7a7SJeremy L Thompson 1882d965c7a7SJeremy L Thompson /** 1883d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1884d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1885d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1886d99fa3c5SJeremy L Thompson 1887d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1888d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1889d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1890d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1891d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1892d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1893d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1894d99fa3c5SJeremy L Thompson 1895d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1896d99fa3c5SJeremy L Thompson 1897d99fa3c5SJeremy L Thompson @ref User 1898d99fa3c5SJeremy L Thompson **/ 1899d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, 1900d1d35e2fSjeremylt CeedVector p_mult_fine, 1901d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1902d1d35e2fSjeremylt CeedOperator *op_coarse, CeedOperator *op_prolong, 1903d1d35e2fSjeremylt CeedOperator *op_restrict) { 1904d99fa3c5SJeremy L Thompson int ierr; 1905d99fa3c5SJeremy L Thompson Ceed ceed; 1906d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1907d99fa3c5SJeremy L Thompson 1908d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1909d1d35e2fSjeremylt CeedBasis basis_fine; 1910d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1911d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1912d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1913d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1914d1d35e2fSjeremylt if (Q_f != Q_c) 1915d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1916e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1917e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1918d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1919d99fa3c5SJeremy L Thompson 1920d99fa3c5SJeremy L Thompson // Coarse to fine basis 1921d1d35e2fSjeremylt CeedInt P_f, P_c, Q = Q_f; 1922d1d35e2fSjeremylt bool is_tensor_f, is_tensor_c; 1923d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_fine, &is_tensor_f); CeedChk(ierr); 1924d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_coarse, &is_tensor_c); CeedChk(ierr); 1925d1d35e2fSjeremylt CeedScalar *interp_c, *interp_f, *interp_c_to_f, *tau; 1926d1d35e2fSjeremylt if (is_tensor_f && is_tensor_c) { 1927d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_f); CeedChk(ierr); 1928d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_coarse, &P_c); CeedChk(ierr); 1929d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis_coarse, &Q); CeedChk(ierr); 1930d1d35e2fSjeremylt } else if (!is_tensor_f && !is_tensor_c) { 1931d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &P_f); CeedChk(ierr); 1932d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_coarse, &P_c); CeedChk(ierr); 1933d99fa3c5SJeremy L Thompson } else { 1934d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1935e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1936e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1937d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1938d99fa3c5SJeremy L Thompson } 1939d99fa3c5SJeremy L Thompson 1940d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_f, &interp_f); CeedChk(ierr); 1941d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_c, &interp_c); CeedChk(ierr); 1942d1d35e2fSjeremylt ierr = CeedCalloc(P_c*P_f, &interp_c_to_f); CeedChk(ierr); 1943d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1944d1d35e2fSjeremylt if (is_tensor_f) { 1945d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp_1d, Q*P_f*sizeof basis_fine->interp_1d[0]); 1946d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp_1d, 1947d1d35e2fSjeremylt Q*P_c*sizeof basis_coarse->interp_1d[0]); 1948d99fa3c5SJeremy L Thompson } else { 1949d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp, Q*P_f*sizeof basis_fine->interp[0]); 1950d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp, Q*P_c*sizeof basis_coarse->interp[0]); 1951d99fa3c5SJeremy L Thompson } 1952d99fa3c5SJeremy L Thompson 1953d1d35e2fSjeremylt // -- QR Factorization, interp_f = Q R 1954d1d35e2fSjeremylt ierr = CeedQRFactorization(ceed, interp_f, tau, Q, P_f); CeedChk(ierr); 1955d99fa3c5SJeremy L Thompson 1956d1d35e2fSjeremylt // -- Apply Qtranspose, interp_c = Qtranspose interp_c 1957d1d35e2fSjeremylt ierr = CeedHouseholderApplyQ(interp_c, interp_f, tau, CEED_TRANSPOSE, 1958d1d35e2fSjeremylt Q, P_c, P_f, P_c, 1); CeedChk(ierr); 1959d99fa3c5SJeremy L Thompson 1960d1d35e2fSjeremylt // -- Apply Rinv, interp_c_to_f = Rinv interp_c 1961d1d35e2fSjeremylt for (CeedInt j=0; j<P_c; j++) { // Column j 1962d1d35e2fSjeremylt 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]; 1963d1d35e2fSjeremylt for (CeedInt i=P_f-2; i>=0; i--) { // Row i 1964d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] = interp_c[j+P_c*i]; 1965d1d35e2fSjeremylt for (CeedInt k=i+1; k<P_f; k++) 1966d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] -= interp_f[k+P_f*i]*interp_c_to_f[j+P_c*k]; 1967d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] /= interp_f[i+P_f*i]; 1968d99fa3c5SJeremy L Thompson } 1969d99fa3c5SJeremy L Thompson } 1970d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1971d1d35e2fSjeremylt ierr = CeedFree(&interp_c); CeedChk(ierr); 1972d1d35e2fSjeremylt ierr = CeedFree(&interp_f); CeedChk(ierr); 1973d99fa3c5SJeremy L Thompson 1974d1d35e2fSjeremylt // Complete with interp_c_to_f versions of code 1975d1d35e2fSjeremylt if (is_tensor_f) { 1976d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateTensorH1(op_fine, p_mult_fine, 1977d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1978d99fa3c5SJeremy L Thompson CeedChk(ierr); 1979d99fa3c5SJeremy L Thompson } else { 1980d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateH1(op_fine, p_mult_fine, 1981d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1982d99fa3c5SJeremy L Thompson CeedChk(ierr); 1983d99fa3c5SJeremy L Thompson } 1984d99fa3c5SJeremy L Thompson 1985d99fa3c5SJeremy L Thompson // Cleanup 1986d1d35e2fSjeremylt ierr = CeedFree(&interp_c_to_f); CeedChk(ierr); 1987e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1988d99fa3c5SJeremy L Thompson } 1989d99fa3c5SJeremy L Thompson 1990d99fa3c5SJeremy L Thompson /** 1991d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1992d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1993d99fa3c5SJeremy L Thompson 1994d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1995d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1996d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1997d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1998d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 1999d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2000d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2001d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2002d99fa3c5SJeremy L Thompson 2003d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2004d99fa3c5SJeremy L Thompson 2005d99fa3c5SJeremy L Thompson @ref User 2006d99fa3c5SJeremy L Thompson **/ 2007d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, 2008d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 2009d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, 2010d1d35e2fSjeremylt CeedOperator *op_prolong, CeedOperator *op_restrict) { 2011d99fa3c5SJeremy L Thompson int ierr; 2012d99fa3c5SJeremy L Thompson Ceed ceed; 2013d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2014d99fa3c5SJeremy L Thompson 2015d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2016d1d35e2fSjeremylt CeedBasis basis_fine; 2017d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2018d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2019d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2020d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2021d1d35e2fSjeremylt if (Q_f != Q_c) 2022d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2023e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2024e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2025d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2026d99fa3c5SJeremy L Thompson 2027d99fa3c5SJeremy L Thompson // Coarse to fine basis 2028d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c; 2029d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2030d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2031d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_1d_f); CeedChk(ierr); 2032d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2033d99fa3c5SJeremy L Thompson CeedChk(ierr); 2034d1d35e2fSjeremylt P_1d_c = dim == 1 ? num_nodes_c : 2035d1d35e2fSjeremylt dim == 2 ? sqrt(num_nodes_c) : 2036d1d35e2fSjeremylt cbrt(num_nodes_c); 2037d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2038d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_ref); CeedChk(ierr); 2039d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_weight); CeedChk(ierr); 2040d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f*P_1d_c*dim, &grad); CeedChk(ierr); 2041d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2042d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, 2043d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2044d99fa3c5SJeremy L Thompson CeedChk(ierr); 2045d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2046d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2047d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2048d99fa3c5SJeremy L Thompson 2049d99fa3c5SJeremy L Thompson // Core code 2050d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2051d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2052d1d35e2fSjeremylt op_prolong, op_restrict); 2053d99fa3c5SJeremy L Thompson CeedChk(ierr); 2054e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2055d99fa3c5SJeremy L Thompson } 2056d99fa3c5SJeremy L Thompson 2057d99fa3c5SJeremy L Thompson /** 2058d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 2059d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 2060d99fa3c5SJeremy L Thompson 2061d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 2062d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 2063d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 2064d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2065d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2066d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2067d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2068d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2069d99fa3c5SJeremy L Thompson 2070d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2071d99fa3c5SJeremy L Thompson 2072d99fa3c5SJeremy L Thompson @ref User 2073d99fa3c5SJeremy L Thompson **/ 2074d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, 2075d1d35e2fSjeremylt CeedVector p_mult_fine, 2076d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, 2077d1d35e2fSjeremylt CeedBasis basis_coarse, 2078d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, 2079d1d35e2fSjeremylt CeedOperator *op_coarse, 2080d1d35e2fSjeremylt CeedOperator *op_prolong, 2081d1d35e2fSjeremylt CeedOperator *op_restrict) { 2082d99fa3c5SJeremy L Thompson int ierr; 2083d99fa3c5SJeremy L Thompson Ceed ceed; 2084d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2085d99fa3c5SJeremy L Thompson 2086d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2087d1d35e2fSjeremylt CeedBasis basis_fine; 2088d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2089d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2090d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2091d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2092d1d35e2fSjeremylt if (Q_f != Q_c) 2093d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2094e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2095e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2096d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2097d99fa3c5SJeremy L Thompson 2098d99fa3c5SJeremy L Thompson // Coarse to fine basis 2099d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2100d1d35e2fSjeremylt ierr = CeedBasisGetTopology(basis_fine, &topo); CeedChk(ierr); 2101d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, num_nodes_f; 2102d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2103d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2104d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &num_nodes_f); CeedChk(ierr); 2105d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2106d99fa3c5SJeremy L Thompson CeedChk(ierr); 2107d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2108d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_ref); CeedChk(ierr); 2109d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_weight); CeedChk(ierr); 2110d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f*num_nodes_c*dim, &grad); CeedChk(ierr); 2111d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2112d1d35e2fSjeremylt ierr = CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, 2113d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2114d99fa3c5SJeremy L Thompson CeedChk(ierr); 2115d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2116d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2117d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2118d99fa3c5SJeremy L Thompson 2119d99fa3c5SJeremy L Thompson // Core code 2120d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2121d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2122d1d35e2fSjeremylt op_prolong, op_restrict); 2123d99fa3c5SJeremy L Thompson CeedChk(ierr); 2124e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2125d99fa3c5SJeremy L Thompson } 2126d99fa3c5SJeremy L Thompson 2127d99fa3c5SJeremy L Thompson /** 21283bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 21293bd813ffSjeremylt CeedOperator 21303bd813ffSjeremylt 21313bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 21323bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 21333bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 21343bd813ffSjeremylt M = V^T V, K = V^T S V. 21353bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 21363bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 21373bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 21383bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 21393bd813ffSjeremylt 21403bd813ffSjeremylt @param op CeedOperator to create element inverses 2141d1d35e2fSjeremylt @param[out] fdm_inv CeedOperator to apply the action of a FDM based inverse 21423bd813ffSjeremylt for each element 21433bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 21444cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 21453bd813ffSjeremylt 21463bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 21473bd813ffSjeremylt 21487a982d89SJeremy L. Thompson @ref Backend 21493bd813ffSjeremylt **/ 2150d1d35e2fSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdm_inv, 21513bd813ffSjeremylt CeedRequest *request) { 21523bd813ffSjeremylt int ierr; 2153e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 21543bd813ffSjeremylt 2155713f43c3Sjeremylt // Use backend version, if available 2156713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2157d1d35e2fSjeremylt ierr = op->CreateFDMElementInverse(op, fdm_inv, request); CeedChk(ierr); 2158713f43c3Sjeremylt } else { 2159713f43c3Sjeremylt // Fallback to reference Ceed 2160d1d35e2fSjeremylt if (!op->op_fallback) { 2161713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 21623bd813ffSjeremylt } 2163713f43c3Sjeremylt // Assemble 2164d1d35e2fSjeremylt ierr = op->op_fallback->CreateFDMElementInverse(op->op_fallback, fdm_inv, 21653bd813ffSjeremylt request); CeedChk(ierr); 21663bd813ffSjeremylt } 2167e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21683bd813ffSjeremylt } 21693bd813ffSjeremylt 21707a982d89SJeremy L. Thompson /** 2171*cd4dfc48Sjeremylt @brief Set the number of quadrature points associated with a CeedOperator. 2172*cd4dfc48Sjeremylt This should be used when creating a CeedOperator where every 2173*cd4dfc48Sjeremylt field has a collocated basis. This function cannot be used for 2174*cd4dfc48Sjeremylt composite CeedOperators. 2175*cd4dfc48Sjeremylt 2176*cd4dfc48Sjeremylt @param op CeedOperator 2177*cd4dfc48Sjeremylt @param num_qpts Number of quadrature points to set 2178*cd4dfc48Sjeremylt 2179*cd4dfc48Sjeremylt @return An error code: 0 - success, otherwise - failure 2180*cd4dfc48Sjeremylt 2181*cd4dfc48Sjeremylt @ref Backend 2182*cd4dfc48Sjeremylt **/ 2183*cd4dfc48Sjeremylt 2184*cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) { 2185*cd4dfc48Sjeremylt if (op->composite) 2186*cd4dfc48Sjeremylt // LCOV_EXCL_START 2187*cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 2188*cd4dfc48Sjeremylt "Not defined for composite operator"); 2189*cd4dfc48Sjeremylt // LCOV_EXCL_STOP 2190*cd4dfc48Sjeremylt if (op->num_qpts) 2191*cd4dfc48Sjeremylt // LCOV_EXCL_START 2192*cd4dfc48Sjeremylt return CeedError(op->ceed, CEED_ERROR_MINOR, 2193*cd4dfc48Sjeremylt "Number of quadrature points already defined"); 2194*cd4dfc48Sjeremylt // LCOV_EXCL_STOP 2195*cd4dfc48Sjeremylt 2196*cd4dfc48Sjeremylt op->num_qpts = num_qpts; 2197*cd4dfc48Sjeremylt return CEED_ERROR_SUCCESS; 2198*cd4dfc48Sjeremylt } 2199*cd4dfc48Sjeremylt 2200*cd4dfc48Sjeremylt /** 22017a982d89SJeremy L. Thompson @brief View a CeedOperator 22027a982d89SJeremy L. Thompson 22037a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 22047a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 22057a982d89SJeremy L. Thompson 22067a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 22077a982d89SJeremy L. Thompson 22087a982d89SJeremy L. Thompson @ref User 22097a982d89SJeremy L. Thompson **/ 22107a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 22117a982d89SJeremy L. Thompson int ierr; 22127a982d89SJeremy L. Thompson 22137a982d89SJeremy L. Thompson if (op->composite) { 22147a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 22157a982d89SJeremy L. Thompson 2216d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 22177a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 2218d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 22197a982d89SJeremy L. Thompson CeedChk(ierr); 22207a982d89SJeremy L. Thompson } 22217a982d89SJeremy L. Thompson } else { 22227a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 22237a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 22247a982d89SJeremy L. Thompson } 2225e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 22267a982d89SJeremy L. Thompson } 22273bd813ffSjeremylt 22283bd813ffSjeremylt /** 22293bd813ffSjeremylt @brief Apply CeedOperator to a vector 2230d7b241e6Sjeremylt 2231d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2232d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2233d7b241e6Sjeremylt CeedOperatorSetField(). 2234d7b241e6Sjeremylt 2235d7b241e6Sjeremylt @param op CeedOperator to apply 22364cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 223734138859Sjeremylt there are no active inputs 2238b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 22394cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 224034138859Sjeremylt active outputs 2241d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 22424cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2243b11c1e72Sjeremylt 2244b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2245dfdf5a53Sjeremylt 22467a982d89SJeremy L. Thompson @ref User 2247b11c1e72Sjeremylt **/ 2248692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2249692c2638Sjeremylt CeedRequest *request) { 2250d7b241e6Sjeremylt int ierr; 2251e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2252d7b241e6Sjeremylt 2253d1d35e2fSjeremylt if (op->num_elem) { 2254250756a7Sjeremylt // Standard Operator 2255cae8b89aSjeremylt if (op->Apply) { 2256250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2257cae8b89aSjeremylt } else { 2258cae8b89aSjeremylt // Zero all output vectors 2259250756a7Sjeremylt CeedQFunction qf = op->qf; 2260d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 2261d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 2262cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2263cae8b89aSjeremylt vec = out; 2264cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2265cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2266cae8b89aSjeremylt } 2267cae8b89aSjeremylt } 2268250756a7Sjeremylt // Apply 2269250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2270250756a7Sjeremylt } 2271250756a7Sjeremylt } else if (op->composite) { 2272250756a7Sjeremylt // Composite Operator 2273250756a7Sjeremylt if (op->ApplyComposite) { 2274250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2275250756a7Sjeremylt } else { 2276d1d35e2fSjeremylt CeedInt num_suboperators; 2277d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2278d1d35e2fSjeremylt CeedOperator *sub_operators; 2279d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2280250756a7Sjeremylt 2281250756a7Sjeremylt // Zero all output vectors 2282250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2283cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2284cae8b89aSjeremylt } 2285d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2286d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 2287d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 2288250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2289250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2290250756a7Sjeremylt } 2291250756a7Sjeremylt } 2292250756a7Sjeremylt } 2293250756a7Sjeremylt // Apply 2294d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 2295d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 2296cae8b89aSjeremylt CeedChk(ierr); 2297cae8b89aSjeremylt } 2298cae8b89aSjeremylt } 2299250756a7Sjeremylt } 2300e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2301cae8b89aSjeremylt } 2302cae8b89aSjeremylt 2303cae8b89aSjeremylt /** 2304cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2305cae8b89aSjeremylt 2306cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2307cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2308cae8b89aSjeremylt CeedOperatorSetField(). 2309cae8b89aSjeremylt 2310cae8b89aSjeremylt @param op CeedOperator to apply 2311cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2312cae8b89aSjeremylt active inputs 2313cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2314cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2315cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 23164cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2317cae8b89aSjeremylt 2318cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2319cae8b89aSjeremylt 23207a982d89SJeremy L. Thompson @ref User 2321cae8b89aSjeremylt **/ 2322cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2323cae8b89aSjeremylt CeedRequest *request) { 2324cae8b89aSjeremylt int ierr; 2325e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2326cae8b89aSjeremylt 2327d1d35e2fSjeremylt if (op->num_elem) { 2328250756a7Sjeremylt // Standard Operator 2329250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2330250756a7Sjeremylt } else if (op->composite) { 2331250756a7Sjeremylt // Composite Operator 2332250756a7Sjeremylt if (op->ApplyAddComposite) { 2333250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2334cae8b89aSjeremylt } else { 2335d1d35e2fSjeremylt CeedInt num_suboperators; 2336d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2337d1d35e2fSjeremylt CeedOperator *sub_operators; 2338d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2339250756a7Sjeremylt 2340d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2341d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 2342cae8b89aSjeremylt CeedChk(ierr); 23431d7d2407SJeremy L Thompson } 2344250756a7Sjeremylt } 2345250756a7Sjeremylt } 2346e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2347d7b241e6Sjeremylt } 2348d7b241e6Sjeremylt 2349d7b241e6Sjeremylt /** 2350b11c1e72Sjeremylt @brief Destroy a CeedOperator 2351d7b241e6Sjeremylt 2352d7b241e6Sjeremylt @param op CeedOperator to destroy 2353b11c1e72Sjeremylt 2354b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2355dfdf5a53Sjeremylt 23567a982d89SJeremy L. Thompson @ref User 2357b11c1e72Sjeremylt **/ 2358d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2359d7b241e6Sjeremylt int ierr; 2360d7b241e6Sjeremylt 2361d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 2362d7b241e6Sjeremylt if ((*op)->Destroy) { 2363d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2364d7b241e6Sjeremylt } 2365fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2366fe2413ffSjeremylt // Free fields 2367d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2368d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 2369d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 2370d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 237171352a93Sjeremylt CeedChk(ierr); 237215910d16Sjeremylt } 2373d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2374d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 237571352a93Sjeremylt } 2376d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 2377d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 2378d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 237971352a93Sjeremylt } 2380d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 2381d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 2382fe2413ffSjeremylt } 2383d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2384d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 2385d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 238671352a93Sjeremylt CeedChk(ierr); 2387d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2388d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 238971352a93Sjeremylt } 2390d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 2391d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 2392d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 239371352a93Sjeremylt } 2394d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 2395d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 2396fe2413ffSjeremylt } 2397d1d35e2fSjeremylt // Destroy sub_operators 2398d1d35e2fSjeremylt for (int i=0; i<(*op)->num_suboperators; i++) 2399d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 2400d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 240152d6035fSJeremy L Thompson } 2402e15f9bd0SJeremy L Thompson if ((*op)->qf) 2403e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2404d1d35e2fSjeremylt (*op)->qf->operators_set--; 2405e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2406d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2407e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2408e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2409d1d35e2fSjeremylt (*op)->dqf->operators_set--; 2410e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2411d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2412e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2413e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2414d1d35e2fSjeremylt (*op)->dqfT->operators_set--; 2415e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2416d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2417fe2413ffSjeremylt 24185107b09fSJeremy L Thompson // Destroy fallback 2419d1d35e2fSjeremylt if ((*op)->op_fallback) { 2420d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 2421d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 2422d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 2423d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 24245107b09fSJeremy L Thompson } 24255107b09fSJeremy L Thompson 2426d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 2427d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 2428d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 2429d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2430e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2431d7b241e6Sjeremylt } 2432d7b241e6Sjeremylt 2433d7b241e6Sjeremylt /// @} 2434