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); 119*78464608Sjeremylt 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, 231e15f9bd0SJeremy L Thompson "At least one non-collocated basis required"); 2327a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2337a982d89SJeremy L. Thompson } 2347a982d89SJeremy L. Thompson 235e15f9bd0SJeremy L Thompson // Flag as immutable and ready 236d1d35e2fSjeremylt op->interface_setup = true; 237e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 238e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 239d1d35e2fSjeremylt op->qf->operators_set++; 240e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 241e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 242e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 243d1d35e2fSjeremylt op->dqf->operators_set++; 244e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 245e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 246e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 247d1d35e2fSjeremylt op->dqfT->operators_set++; 248e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 249e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2507a982d89SJeremy L. Thompson } 2517a982d89SJeremy L. Thompson 2527a982d89SJeremy L. Thompson /** 2537a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2547a982d89SJeremy L. Thompson 2557a982d89SJeremy L. Thompson @param[in] field Operator field to view 256d1d35e2fSjeremylt @param[in] qf_field QFunction field (carries field name) 257d1d35e2fSjeremylt @param[in] field_number Number of field being viewed 2584c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 259d1d35e2fSjeremylt @param[in] input true for an input field; false for output field 2607a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2617a982d89SJeremy L. Thompson 2627a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2637a982d89SJeremy L. Thompson 2647a982d89SJeremy L. Thompson @ref Utility 2657a982d89SJeremy L. Thompson **/ 2667a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 267d1d35e2fSjeremylt CeedQFunctionField qf_field, 268d1d35e2fSjeremylt CeedInt field_number, bool sub, bool input, 2697a982d89SJeremy L. Thompson FILE *stream) { 2707a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 271d1d35e2fSjeremylt const char *in_out = input ? "Input" : "Output"; 2727a982d89SJeremy L. Thompson 2737a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2747a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 275d1d35e2fSjeremylt pre, in_out, field_number, pre, qf_field->field_name); 2767a982d89SJeremy L. Thompson 2777a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2787a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2797a982d89SJeremy L. Thompson 2807a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2817a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2827a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2837a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 284e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2857a982d89SJeremy L. Thompson } 2867a982d89SJeremy L. Thompson 2877a982d89SJeremy L. Thompson /** 2887a982d89SJeremy L. Thompson @brief View a single CeedOperator 2897a982d89SJeremy L. Thompson 2907a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2917a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2927a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2937a982d89SJeremy L. Thompson 2947a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2957a982d89SJeremy L. Thompson 2967a982d89SJeremy L. Thompson @ref Utility 2977a982d89SJeremy L. Thompson **/ 2987a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 2997a982d89SJeremy L. Thompson int ierr; 3007a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 3017a982d89SJeremy L. Thompson 302*78464608Sjeremylt CeedInt total_fields = 0; 303*78464608Sjeremylt ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr); 3047a982d89SJeremy L. Thompson 305*78464608Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, total_fields, 306*78464608Sjeremylt total_fields>1 ? "s" : ""); 3077a982d89SJeremy L. Thompson 308d1d35e2fSjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->num_input_fields, 309d1d35e2fSjeremylt op->qf->num_input_fields>1 ? "s" : ""); 310d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 311d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i], 3127a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 3137a982d89SJeremy L. Thompson } 3147a982d89SJeremy L. Thompson 315d1d35e2fSjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->num_output_fields, 316d1d35e2fSjeremylt op->qf->num_output_fields>1 ? "s" : ""); 317d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 318d1d35e2fSjeremylt ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i], 3197a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 3207a982d89SJeremy L. Thompson } 321e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3227a982d89SJeremy L. Thompson } 3237a982d89SJeremy L. Thompson 324d99fa3c5SJeremy L Thompson /** 325e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 326e2f04181SAndrew T. Barker 327e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 328d1d35e2fSjeremylt @param[out] active_rstr ElemRestriction for active input vector 329e2f04181SAndrew T. Barker 330e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 331e2f04181SAndrew T. Barker 332e2f04181SAndrew T. Barker @ref Utility 333e2f04181SAndrew T. Barker **/ 334e2f04181SAndrew T. Barker static int CeedOperatorGetActiveElemRestriction(CeedOperator op, 335d1d35e2fSjeremylt CeedElemRestriction *active_rstr) { 336d1d35e2fSjeremylt *active_rstr = NULL; 337d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 338d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 339d1d35e2fSjeremylt *active_rstr = op->input_fields[i]->elem_restr; 340e2f04181SAndrew T. Barker break; 341e2f04181SAndrew T. Barker } 342e2f04181SAndrew T. Barker 343d1d35e2fSjeremylt if (!*active_rstr) { 344e2f04181SAndrew T. Barker // LCOV_EXCL_START 345e2f04181SAndrew T. Barker int ierr; 346e2f04181SAndrew T. Barker Ceed ceed; 347e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 348e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 349e2f04181SAndrew T. Barker "No active ElemRestriction found!"); 350e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 351e2f04181SAndrew T. Barker } 352e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 353e2f04181SAndrew T. Barker } 354e2f04181SAndrew T. Barker 355e2f04181SAndrew T. Barker /** 356d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 357d99fa3c5SJeremy L Thompson 358d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 359d1d35e2fSjeremylt @param[out] active_basis Basis for active input vector 360d99fa3c5SJeremy L Thompson 361d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 362d99fa3c5SJeremy L Thompson 363d99fa3c5SJeremy L Thompson @ ref Developer 364d99fa3c5SJeremy L Thompson **/ 365d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 366d1d35e2fSjeremylt CeedBasis *active_basis) { 367d1d35e2fSjeremylt *active_basis = NULL; 368d1d35e2fSjeremylt for (int i = 0; i < op->qf->num_input_fields; i++) 369d1d35e2fSjeremylt if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 370d1d35e2fSjeremylt *active_basis = op->input_fields[i]->basis; 371d99fa3c5SJeremy L Thompson break; 372d99fa3c5SJeremy L Thompson } 373d99fa3c5SJeremy L Thompson 374d1d35e2fSjeremylt if (!*active_basis) { 375d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 376d99fa3c5SJeremy L Thompson int ierr; 377d99fa3c5SJeremy L Thompson Ceed ceed; 378d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 379e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 380d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 381d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 382d99fa3c5SJeremy L Thompson } 383e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 384d99fa3c5SJeremy L Thompson } 385d99fa3c5SJeremy L Thompson 386d99fa3c5SJeremy L Thompson /** 387d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 388d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 389d99fa3c5SJeremy L Thompson 390d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 391d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 392d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 393d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 394d1d35e2fSjeremylt @param[in] basis_c_to_f Basis for coarse to fine interpolation 395d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 396d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 397d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 398d99fa3c5SJeremy L Thompson 399d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 400d99fa3c5SJeremy L Thompson 401d99fa3c5SJeremy L Thompson @ref Developer 402d99fa3c5SJeremy L Thompson **/ 403d1d35e2fSjeremylt static int CeedOperatorMultigridLevel_Core(CeedOperator op_fine, 404d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 405d1d35e2fSjeremylt CeedBasis basis_c_to_f, CeedOperator *op_coarse, CeedOperator *op_prolong, 406d1d35e2fSjeremylt CeedOperator *op_restrict) { 407d99fa3c5SJeremy L Thompson int ierr; 408d99fa3c5SJeremy L Thompson Ceed ceed; 409d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 410d99fa3c5SJeremy L Thompson 411d99fa3c5SJeremy L Thompson // Check for composite operator 412d1d35e2fSjeremylt bool is_composite; 413d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op_fine, &is_composite); CeedChk(ierr); 414d1d35e2fSjeremylt if (is_composite) 415d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 416e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 417d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 418d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 419d99fa3c5SJeremy L Thompson 420d99fa3c5SJeremy L Thompson // Coarse Grid 421d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, op_fine->qf, op_fine->dqf, op_fine->dqfT, 422d1d35e2fSjeremylt op_coarse); CeedChk(ierr); 423d1d35e2fSjeremylt CeedElemRestriction rstr_fine = NULL; 424d99fa3c5SJeremy L Thompson // -- Clone input fields 425d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_input_fields; i++) { 426d1d35e2fSjeremylt if (op_fine->input_fields[i]->vec == CEED_VECTOR_ACTIVE) { 427d1d35e2fSjeremylt rstr_fine = op_fine->input_fields[i]->elem_restr; 428d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 429d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 430d99fa3c5SJeremy L Thompson CeedChk(ierr); 431d99fa3c5SJeremy L Thompson } else { 432d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->input_fields[i]->field_name, 433d1d35e2fSjeremylt op_fine->input_fields[i]->elem_restr, 434d1d35e2fSjeremylt op_fine->input_fields[i]->basis, 435d1d35e2fSjeremylt op_fine->input_fields[i]->vec); CeedChk(ierr); 436d99fa3c5SJeremy L Thompson } 437d99fa3c5SJeremy L Thompson } 438d99fa3c5SJeremy L Thompson // -- Clone output fields 439d1d35e2fSjeremylt for (int i = 0; i < op_fine->qf->num_output_fields; i++) { 440d1d35e2fSjeremylt if (op_fine->output_fields[i]->vec == CEED_VECTOR_ACTIVE) { 441d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 442d1d35e2fSjeremylt rstr_coarse, basis_coarse, CEED_VECTOR_ACTIVE); 443d99fa3c5SJeremy L Thompson CeedChk(ierr); 444d99fa3c5SJeremy L Thompson } else { 445d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_coarse, op_fine->output_fields[i]->field_name, 446d1d35e2fSjeremylt op_fine->output_fields[i]->elem_restr, 447d1d35e2fSjeremylt op_fine->output_fields[i]->basis, 448d1d35e2fSjeremylt op_fine->output_fields[i]->vec); CeedChk(ierr); 449d99fa3c5SJeremy L Thompson } 450d99fa3c5SJeremy L Thompson } 451d99fa3c5SJeremy L Thompson 452d99fa3c5SJeremy L Thompson // Multiplicity vector 453d1d35e2fSjeremylt CeedVector mult_vec, mult_e_vec; 454d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(rstr_fine, &mult_vec, &mult_e_vec); 455d99fa3c5SJeremy L Thompson CeedChk(ierr); 456d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_e_vec, 0.0); CeedChk(ierr); 457d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_NOTRANSPOSE, p_mult_fine, 458d1d35e2fSjeremylt mult_e_vec, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 459d1d35e2fSjeremylt ierr = CeedVectorSetValue(mult_vec, 0.0); CeedChk(ierr); 460d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(rstr_fine, CEED_TRANSPOSE, mult_e_vec, mult_vec, 461d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 462d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_e_vec); CeedChk(ierr); 463d1d35e2fSjeremylt ierr = CeedVectorReciprocal(mult_vec); CeedChk(ierr); 464d99fa3c5SJeremy L Thompson 465d99fa3c5SJeremy L Thompson // Restriction 466d1d35e2fSjeremylt CeedInt num_comp; 467d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_coarse, &num_comp); CeedChk(ierr); 468d1d35e2fSjeremylt CeedQFunction qf_restrict; 469d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_restrict); 470d99fa3c5SJeremy L Thompson CeedChk(ierr); 471d1d35e2fSjeremylt CeedInt *num_comp_r_data; 472d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_r_data); CeedChk(ierr); 473d1d35e2fSjeremylt num_comp_r_data[0] = num_comp; 474d1d35e2fSjeremylt CeedQFunctionContext ctx_r; 475d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_r); CeedChk(ierr); 476d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_r, CEED_MEM_HOST, CEED_OWN_POINTER, 477d1d35e2fSjeremylt sizeof(*num_comp_r_data), num_comp_r_data); 478777ff853SJeremy L Thompson CeedChk(ierr); 479d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_restrict, ctx_r); CeedChk(ierr); 480d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_r); CeedChk(ierr); 481d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "input", num_comp, CEED_EVAL_NONE); 482d99fa3c5SJeremy L Thompson CeedChk(ierr); 483d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_restrict, "scale", num_comp, CEED_EVAL_NONE); 484d99fa3c5SJeremy L Thompson CeedChk(ierr); 485d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_restrict, "output", num_comp, 486d1d35e2fSjeremylt CEED_EVAL_INTERP); CeedChk(ierr); 487d99fa3c5SJeremy L Thompson 488d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_restrict, CEED_QFUNCTION_NONE, 489d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_restrict); 490d99fa3c5SJeremy L Thompson CeedChk(ierr); 491d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "input", rstr_fine, 492d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 493d99fa3c5SJeremy L Thompson CeedChk(ierr); 494d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "scale", rstr_fine, 495d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 496d99fa3c5SJeremy L Thompson CeedChk(ierr); 497d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_restrict, "output", rstr_coarse, basis_c_to_f, 498d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 499d99fa3c5SJeremy L Thompson 500d99fa3c5SJeremy L Thompson // Prolongation 501d1d35e2fSjeremylt CeedQFunction qf_prolong; 502d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qf_prolong); 503d99fa3c5SJeremy L Thompson CeedChk(ierr); 504d1d35e2fSjeremylt CeedInt *num_comp_p_data; 505d1d35e2fSjeremylt ierr = CeedCalloc(1, &num_comp_p_data); CeedChk(ierr); 506d1d35e2fSjeremylt num_comp_p_data[0] = num_comp; 507d1d35e2fSjeremylt CeedQFunctionContext ctx_p; 508d1d35e2fSjeremylt ierr = CeedQFunctionContextCreate(ceed, &ctx_p); CeedChk(ierr); 509d1d35e2fSjeremylt ierr = CeedQFunctionContextSetData(ctx_p, CEED_MEM_HOST, CEED_OWN_POINTER, 510d1d35e2fSjeremylt sizeof(*num_comp_p_data), num_comp_p_data); 511777ff853SJeremy L Thompson CeedChk(ierr); 512d1d35e2fSjeremylt ierr = CeedQFunctionSetContext(qf_prolong, ctx_p); CeedChk(ierr); 513d1d35e2fSjeremylt ierr = CeedQFunctionContextDestroy(&ctx_p); CeedChk(ierr); 514d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "input", num_comp, CEED_EVAL_INTERP); 515d99fa3c5SJeremy L Thompson CeedChk(ierr); 516d1d35e2fSjeremylt ierr = CeedQFunctionAddInput(qf_prolong, "scale", num_comp, CEED_EVAL_NONE); 517d99fa3c5SJeremy L Thompson CeedChk(ierr); 518d1d35e2fSjeremylt ierr = CeedQFunctionAddOutput(qf_prolong, "output", num_comp, CEED_EVAL_NONE); 519d99fa3c5SJeremy L Thompson CeedChk(ierr); 520d99fa3c5SJeremy L Thompson 521d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed, qf_prolong, CEED_QFUNCTION_NONE, 522d1d35e2fSjeremylt CEED_QFUNCTION_NONE, op_prolong); 523d99fa3c5SJeremy L Thompson CeedChk(ierr); 524d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "input", rstr_coarse, basis_c_to_f, 525d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 526d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "scale", rstr_fine, 527d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, mult_vec); 528d99fa3c5SJeremy L Thompson CeedChk(ierr); 529d1d35e2fSjeremylt ierr = CeedOperatorSetField(*op_prolong, "output", rstr_fine, 530d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 531d99fa3c5SJeremy L Thompson CeedChk(ierr); 532d99fa3c5SJeremy L Thompson 533d99fa3c5SJeremy L Thompson // Cleanup 534d1d35e2fSjeremylt ierr = CeedVectorDestroy(&mult_vec); CeedChk(ierr); 535d1d35e2fSjeremylt ierr = CeedBasisDestroy(&basis_c_to_f); CeedChk(ierr); 536d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_restrict); CeedChk(ierr); 537d1d35e2fSjeremylt ierr = CeedQFunctionDestroy(&qf_prolong); CeedChk(ierr); 538e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 539d99fa3c5SJeremy L Thompson } 540d99fa3c5SJeremy L Thompson 5417a982d89SJeremy L. Thompson /// @} 5427a982d89SJeremy L. Thompson 5437a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5447a982d89SJeremy L. Thompson /// CeedOperator Backend API 5457a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5467a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5477a982d89SJeremy L. Thompson /// @{ 5487a982d89SJeremy L. Thompson 5497a982d89SJeremy L. Thompson /** 5507a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5517a982d89SJeremy L. Thompson 5527a982d89SJeremy L. Thompson @param op CeedOperator 5537a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5547a982d89SJeremy L. Thompson 5557a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5567a982d89SJeremy L. Thompson 5577a982d89SJeremy L. Thompson @ref Backend 5587a982d89SJeremy L. Thompson **/ 5597a982d89SJeremy L. Thompson 5607a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5617a982d89SJeremy L. Thompson *ceed = op->ceed; 562e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5637a982d89SJeremy L. Thompson } 5647a982d89SJeremy L. Thompson 5657a982d89SJeremy L. Thompson /** 5667a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5677a982d89SJeremy L. Thompson 5687a982d89SJeremy L. Thompson @param op CeedOperator 569d1d35e2fSjeremylt @param[out] num_elem Variable to store number of elements 5707a982d89SJeremy L. Thompson 5717a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5727a982d89SJeremy L. Thompson 5737a982d89SJeremy L. Thompson @ref Backend 5747a982d89SJeremy L. Thompson **/ 5757a982d89SJeremy L. Thompson 576d1d35e2fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) { 5777a982d89SJeremy L. Thompson if (op->composite) 5787a982d89SJeremy L. Thompson // LCOV_EXCL_START 579e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 580e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5817a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5827a982d89SJeremy L. Thompson 583d1d35e2fSjeremylt *num_elem = op->num_elem; 584e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5857a982d89SJeremy L. Thompson } 5867a982d89SJeremy L. Thompson 5877a982d89SJeremy L. Thompson /** 5887a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5897a982d89SJeremy L. Thompson 5907a982d89SJeremy L. Thompson @param op CeedOperator 591d1d35e2fSjeremylt @param[out] num_qpts Variable to store vector number of quadrature points 5927a982d89SJeremy L. Thompson 5937a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5947a982d89SJeremy L. Thompson 5957a982d89SJeremy L. Thompson @ref Backend 5967a982d89SJeremy L. Thompson **/ 5977a982d89SJeremy L. Thompson 598d1d35e2fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) { 5997a982d89SJeremy L. Thompson if (op->composite) 6007a982d89SJeremy L. Thompson // LCOV_EXCL_START 601e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 602e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6037a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6047a982d89SJeremy L. Thompson 605d1d35e2fSjeremylt *num_qpts = op->num_qpts; 606e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6077a982d89SJeremy L. Thompson } 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson /** 6107a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 6117a982d89SJeremy L. Thompson 6127a982d89SJeremy L. Thompson @param op CeedOperator 613d1d35e2fSjeremylt @param[out] num_args Variable to store vector number of arguments 6147a982d89SJeremy L. Thompson 6157a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6167a982d89SJeremy L. Thompson 6177a982d89SJeremy L. Thompson @ref Backend 6187a982d89SJeremy L. Thompson **/ 6197a982d89SJeremy L. Thompson 620d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) { 6217a982d89SJeremy L. Thompson if (op->composite) 6227a982d89SJeremy L. Thompson // LCOV_EXCL_START 623e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 624e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6257a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6267a982d89SJeremy L. Thompson 627d1d35e2fSjeremylt *num_args = op->num_fields; 628e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6297a982d89SJeremy L. Thompson } 6307a982d89SJeremy L. Thompson 6317a982d89SJeremy L. Thompson /** 6327a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6337a982d89SJeremy L. Thompson 6347a982d89SJeremy L. Thompson @param op CeedOperator 635d1d35e2fSjeremylt @param[out] is_setup_done Variable to store setup status 6367a982d89SJeremy L. Thompson 6377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6387a982d89SJeremy L. Thompson 6397a982d89SJeremy L. Thompson @ref Backend 6407a982d89SJeremy L. Thompson **/ 6417a982d89SJeremy L. Thompson 642d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) { 643d1d35e2fSjeremylt *is_setup_done = op->backend_setup; 644e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6457a982d89SJeremy L. Thompson } 6467a982d89SJeremy L. Thompson 6477a982d89SJeremy L. Thompson /** 6487a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6497a982d89SJeremy L. Thompson 6507a982d89SJeremy L. Thompson @param op CeedOperator 6517a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6527a982d89SJeremy L. Thompson 6537a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6547a982d89SJeremy L. Thompson 6557a982d89SJeremy L. Thompson @ref Backend 6567a982d89SJeremy L. Thompson **/ 6577a982d89SJeremy L. Thompson 6587a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6597a982d89SJeremy L. Thompson if (op->composite) 6607a982d89SJeremy L. Thompson // LCOV_EXCL_START 661e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 662e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6637a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6647a982d89SJeremy L. Thompson 6657a982d89SJeremy L. Thompson *qf = op->qf; 666e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6677a982d89SJeremy L. Thompson } 6687a982d89SJeremy L. Thompson 6697a982d89SJeremy L. Thompson /** 670c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 671c04a41a7SJeremy L Thompson 672c04a41a7SJeremy L Thompson @param op CeedOperator 673d1d35e2fSjeremylt @param[out] is_composite Variable to store composite status 674c04a41a7SJeremy L Thompson 675c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 676c04a41a7SJeremy L Thompson 677c04a41a7SJeremy L Thompson @ref Backend 678c04a41a7SJeremy L Thompson **/ 679c04a41a7SJeremy L Thompson 680d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) { 681d1d35e2fSjeremylt *is_composite = op->composite; 682e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 683c04a41a7SJeremy L Thompson } 684c04a41a7SJeremy L Thompson 685c04a41a7SJeremy L Thompson /** 686d1d35e2fSjeremylt @brief Get the number of sub_operators associated with a CeedOperator 6877a982d89SJeremy L. Thompson 6887a982d89SJeremy L. Thompson @param op CeedOperator 689d1d35e2fSjeremylt @param[out] num_suboperators Variable to store number of sub_operators 6907a982d89SJeremy L. Thompson 6917a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6927a982d89SJeremy L. Thompson 6937a982d89SJeremy L. Thompson @ref Backend 6947a982d89SJeremy L. Thompson **/ 6957a982d89SJeremy L. Thompson 696d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) { 6977a982d89SJeremy L. Thompson if (!op->composite) 6987a982d89SJeremy L. Thompson // LCOV_EXCL_START 699e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7007a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7017a982d89SJeremy L. Thompson 702d1d35e2fSjeremylt *num_suboperators = op->num_suboperators; 703e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7047a982d89SJeremy L. Thompson } 7057a982d89SJeremy L. Thompson 7067a982d89SJeremy L. Thompson /** 707d1d35e2fSjeremylt @brief Get the list of sub_operators associated with a CeedOperator 7087a982d89SJeremy L. Thompson 7097a982d89SJeremy L. Thompson @param op CeedOperator 710d1d35e2fSjeremylt @param[out] sub_operators Variable to store list of sub_operators 7117a982d89SJeremy L. Thompson 7127a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7137a982d89SJeremy L. Thompson 7147a982d89SJeremy L. Thompson @ref Backend 7157a982d89SJeremy L. Thompson **/ 7167a982d89SJeremy L. Thompson 717d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) { 7187a982d89SJeremy L. Thompson if (!op->composite) 7197a982d89SJeremy L. Thompson // LCOV_EXCL_START 720e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7217a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7227a982d89SJeremy L. Thompson 723d1d35e2fSjeremylt *sub_operators = op->sub_operators; 724e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7257a982d89SJeremy L. Thompson } 7267a982d89SJeremy L. Thompson 7277a982d89SJeremy L. Thompson /** 7287a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7297a982d89SJeremy L. Thompson 7307a982d89SJeremy L. Thompson @param op CeedOperator 7317a982d89SJeremy L. Thompson @param[out] data Variable to store data 7327a982d89SJeremy L. Thompson 7337a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7347a982d89SJeremy L. Thompson 7357a982d89SJeremy L. Thompson @ref Backend 7367a982d89SJeremy L. Thompson **/ 7377a982d89SJeremy L. Thompson 738777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 739777ff853SJeremy L Thompson *(void **)data = op->data; 740e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7417a982d89SJeremy L. Thompson } 7427a982d89SJeremy L. Thompson 7437a982d89SJeremy L. Thompson /** 7447a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7457a982d89SJeremy L. Thompson 7467a982d89SJeremy L. Thompson @param[out] op CeedOperator 7477a982d89SJeremy L. Thompson @param data Data to set 7487a982d89SJeremy L. Thompson 7497a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7507a982d89SJeremy L. Thompson 7517a982d89SJeremy L. Thompson @ref Backend 7527a982d89SJeremy L. Thompson **/ 7537a982d89SJeremy L. Thompson 754777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 755777ff853SJeremy L Thompson op->data = data; 756e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7577a982d89SJeremy L. Thompson } 7587a982d89SJeremy L. Thompson 7597a982d89SJeremy L. Thompson /** 7607a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7617a982d89SJeremy L. Thompson 7627a982d89SJeremy L. Thompson @param op CeedOperator 7637a982d89SJeremy L. Thompson 7647a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7657a982d89SJeremy L. Thompson 7667a982d89SJeremy L. Thompson @ref Backend 7677a982d89SJeremy L. Thompson **/ 7687a982d89SJeremy L. Thompson 7697a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 770d1d35e2fSjeremylt op->backend_setup = true; 771e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7727a982d89SJeremy L. Thompson } 7737a982d89SJeremy L. Thompson 7747a982d89SJeremy L. Thompson /** 7757a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7767a982d89SJeremy L. Thompson 7777a982d89SJeremy L. Thompson @param op CeedOperator 778d1d35e2fSjeremylt @param[out] input_fields Variable to store input_fields 779d1d35e2fSjeremylt @param[out] output_fields Variable to store output_fields 7807a982d89SJeremy L. Thompson 7817a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7827a982d89SJeremy L. Thompson 7837a982d89SJeremy L. Thompson @ref Backend 7847a982d89SJeremy L. Thompson **/ 7857a982d89SJeremy L. Thompson 786d1d35e2fSjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **input_fields, 787d1d35e2fSjeremylt CeedOperatorField **output_fields) { 7887a982d89SJeremy L. Thompson if (op->composite) 7897a982d89SJeremy L. Thompson // LCOV_EXCL_START 790e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 791e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 7927a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7937a982d89SJeremy L. Thompson 794d1d35e2fSjeremylt if (input_fields) *input_fields = op->input_fields; 795d1d35e2fSjeremylt if (output_fields) *output_fields = op->output_fields; 796e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7977a982d89SJeremy L. Thompson } 7987a982d89SJeremy L. Thompson 7997a982d89SJeremy L. Thompson /** 8007a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 8017a982d89SJeremy L. Thompson 802d1d35e2fSjeremylt @param op_field CeedOperatorField 8037a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 8047a982d89SJeremy L. Thompson 8057a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8067a982d89SJeremy L. Thompson 8077a982d89SJeremy L. Thompson @ref Backend 8087a982d89SJeremy L. Thompson **/ 8097a982d89SJeremy L. Thompson 810d1d35e2fSjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field, 8117a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 812d1d35e2fSjeremylt *rstr = op_field->elem_restr; 813e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8147a982d89SJeremy L. Thompson } 8157a982d89SJeremy L. Thompson 8167a982d89SJeremy L. Thompson /** 8177a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8187a982d89SJeremy L. Thompson 819d1d35e2fSjeremylt @param op_field CeedOperatorField 8207a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8217a982d89SJeremy L. Thompson 8227a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8237a982d89SJeremy L. Thompson 8247a982d89SJeremy L. Thompson @ref Backend 8257a982d89SJeremy L. Thompson **/ 8267a982d89SJeremy L. Thompson 827d1d35e2fSjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) { 828d1d35e2fSjeremylt *basis = op_field->basis; 829e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8307a982d89SJeremy L. Thompson } 8317a982d89SJeremy L. Thompson 8327a982d89SJeremy L. Thompson /** 8337a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8347a982d89SJeremy L. Thompson 835d1d35e2fSjeremylt @param op_field CeedOperatorField 8367a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8377a982d89SJeremy L. Thompson 8387a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8397a982d89SJeremy L. Thompson 8407a982d89SJeremy L. Thompson @ref Backend 8417a982d89SJeremy L. Thompson **/ 8427a982d89SJeremy L. Thompson 843d1d35e2fSjeremylt int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) { 844d1d35e2fSjeremylt *vec = op_field->vec; 845e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8467a982d89SJeremy L. Thompson } 8477a982d89SJeremy L. Thompson 8487a982d89SJeremy L. Thompson /// @} 8497a982d89SJeremy L. Thompson 8507a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8517a982d89SJeremy L. Thompson /// CeedOperator Public API 8527a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8537a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 854dfdf5a53Sjeremylt /// @{ 855d7b241e6Sjeremylt 856d7b241e6Sjeremylt /** 8570219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8580219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8590219ea01SJeremy L Thompson \ref CeedOperatorSetField. 860d7b241e6Sjeremylt 861b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 862d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 86334138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8644cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 865d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8664cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 867b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 868b11c1e72Sjeremylt CeedOperator will be stored 869b11c1e72Sjeremylt 870b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 871dfdf5a53Sjeremylt 8727a982d89SJeremy L. Thompson @ref User 873d7b241e6Sjeremylt */ 874d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 875d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 876d7b241e6Sjeremylt int ierr; 877d7b241e6Sjeremylt 8785fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8795fe0d4faSjeremylt Ceed delegate; 880aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8815fe0d4faSjeremylt 8825fe0d4faSjeremylt if (!delegate) 883c042f62fSJeremy L Thompson // LCOV_EXCL_START 884e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 885e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 886c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8875fe0d4faSjeremylt 8885fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 889e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8905fe0d4faSjeremylt } 8915fe0d4faSjeremylt 892b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 893b3b7035fSJeremy L Thompson // LCOV_EXCL_START 894e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 895e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 896b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 897d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 898d7b241e6Sjeremylt (*op)->ceed = ceed; 899d1d35e2fSjeremylt ceed->ref_count++; 900d1d35e2fSjeremylt (*op)->ref_count = 1; 901d7b241e6Sjeremylt (*op)->qf = qf; 902d1d35e2fSjeremylt qf->ref_count++; 903442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 904d7b241e6Sjeremylt (*op)->dqf = dqf; 905d1d35e2fSjeremylt dqf->ref_count++; 906442e7f0bSjeremylt } 907442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 908d7b241e6Sjeremylt (*op)->dqfT = dqfT; 909d1d35e2fSjeremylt dqfT->ref_count++; 910442e7f0bSjeremylt } 911d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr); 912d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr); 913d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 914e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 915d7b241e6Sjeremylt } 916d7b241e6Sjeremylt 917d7b241e6Sjeremylt /** 91852d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 91952d6035fSJeremy L Thompson 92052d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 92152d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 92252d6035fSJeremy L Thompson Composite CeedOperator will be stored 92352d6035fSJeremy L Thompson 92452d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 92552d6035fSJeremy L Thompson 9267a982d89SJeremy L. Thompson @ref User 92752d6035fSJeremy L Thompson */ 92852d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 92952d6035fSJeremy L Thompson int ierr; 93052d6035fSJeremy L Thompson 93152d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 93252d6035fSJeremy L Thompson Ceed delegate; 933aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 93452d6035fSJeremy L Thompson 935250756a7Sjeremylt if (delegate) { 93652d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 937e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 93852d6035fSJeremy L Thompson } 939250756a7Sjeremylt } 94052d6035fSJeremy L Thompson 94152d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 94252d6035fSJeremy L Thompson (*op)->ceed = ceed; 943d1d35e2fSjeremylt ceed->ref_count++; 94452d6035fSJeremy L Thompson (*op)->composite = true; 945d1d35e2fSjeremylt ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr); 946250756a7Sjeremylt 947250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 94852d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 949250756a7Sjeremylt } 950e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 95152d6035fSJeremy L Thompson } 95252d6035fSJeremy L Thompson 95352d6035fSJeremy L Thompson /** 954b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 955d7b241e6Sjeremylt 956d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 957d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 958d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 959d7b241e6Sjeremylt 960d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 961d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 962d7b241e6Sjeremylt input and at most one active output. 963d7b241e6Sjeremylt 9648c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 965d1d35e2fSjeremylt @param field_name Name of the field (to be matched with the name used by 9668795c945Sjeremylt CeedQFunction) 967b11c1e72Sjeremylt @param r CeedElemRestriction 9684cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 969b11c1e72Sjeremylt if collocated with quadrature points 9704cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9714cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9724cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 973b11c1e72Sjeremylt 974b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 975dfdf5a53Sjeremylt 9767a982d89SJeremy L. Thompson @ref User 977b11c1e72Sjeremylt **/ 978d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name, 979a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 980d7b241e6Sjeremylt int ierr; 98152d6035fSJeremy L Thompson if (op->composite) 982c042f62fSJeremy L Thompson // LCOV_EXCL_START 983e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 984e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 985c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9868b067b84SJed Brown if (!r) 987c042f62fSJeremy L Thompson // LCOV_EXCL_START 988e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 989c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 990d1d35e2fSjeremylt field_name); 991c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9928b067b84SJed Brown if (!b) 993c042f62fSJeremy L Thompson // LCOV_EXCL_START 994e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 995e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 996d1d35e2fSjeremylt field_name); 997c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9988b067b84SJed Brown if (!v) 999c042f62fSJeremy L Thompson // LCOV_EXCL_START 1000e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 1001e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 1002d1d35e2fSjeremylt field_name); 1003c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 100452d6035fSJeremy L Thompson 1005d1d35e2fSjeremylt CeedInt num_elem; 1006d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr); 1007d1d35e2fSjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction && 1008d1d35e2fSjeremylt op->num_elem != num_elem) 1009c042f62fSJeremy L Thompson // LCOV_EXCL_START 1010e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10111d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1012d1d35e2fSjeremylt "%d elements", num_elem, op->num_elem); 1013c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1014d7b241e6Sjeremylt 1015*78464608Sjeremylt CeedInt num_qpts = 0; 1016e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1017d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr); 1018d1d35e2fSjeremylt if (op->num_qpts && op->num_qpts != num_qpts) 1019c042f62fSJeremy L Thompson // LCOV_EXCL_START 1020e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1021e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 1022d1d35e2fSjeremylt "incompatible with prior %d points", num_qpts, 1023d1d35e2fSjeremylt op->num_qpts); 1024c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1025d7b241e6Sjeremylt } 1026d1d35e2fSjeremylt CeedQFunctionField qf_field; 1027d1d35e2fSjeremylt CeedOperatorField *op_field; 1028d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_input_fields; i++) { 1029d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) { 1030d1d35e2fSjeremylt qf_field = op->qf->input_fields[i]; 1031d1d35e2fSjeremylt op_field = &op->input_fields[i]; 1032d7b241e6Sjeremylt goto found; 1033d7b241e6Sjeremylt } 1034d7b241e6Sjeremylt } 1035d1d35e2fSjeremylt for (CeedInt i=0; i<op->qf->num_output_fields; i++) { 1036d1d35e2fSjeremylt if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) { 1037d1d35e2fSjeremylt qf_field = op->qf->output_fields[i]; 1038d1d35e2fSjeremylt op_field = &op->output_fields[i]; 1039d7b241e6Sjeremylt goto found; 1040d7b241e6Sjeremylt } 1041d7b241e6Sjeremylt } 1042c042f62fSJeremy L Thompson // LCOV_EXCL_START 1043e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1044e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1045d1d35e2fSjeremylt field_name); 1046c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1047d7b241e6Sjeremylt found: 1048d1d35e2fSjeremylt ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr); 1049d1d35e2fSjeremylt ierr = CeedCalloc(1, op_field); CeedChk(ierr); 1050e15f9bd0SJeremy L Thompson 1051d1d35e2fSjeremylt (*op_field)->vec = v; 1052e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1053d1d35e2fSjeremylt v->ref_count += 1; 1054e15f9bd0SJeremy L Thompson } 1055e15f9bd0SJeremy L Thompson 1056d1d35e2fSjeremylt (*op_field)->elem_restr = r; 1057d1d35e2fSjeremylt r->ref_count += 1; 1058e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1059d1d35e2fSjeremylt op->num_elem = num_elem; 1060d1d35e2fSjeremylt op->has_restriction = true; // Restriction set, but num_elem may be 0 1061e15f9bd0SJeremy L Thompson } 1062d99fa3c5SJeremy L Thompson 1063d1d35e2fSjeremylt (*op_field)->basis = b; 1064e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1065d1d35e2fSjeremylt op->num_qpts = num_qpts; 1066d1d35e2fSjeremylt b->ref_count += 1; 1067e15f9bd0SJeremy L Thompson } 1068e15f9bd0SJeremy L Thompson 1069d1d35e2fSjeremylt op->num_fields += 1; 1070d1d35e2fSjeremylt size_t len = strlen(field_name); 1071d99fa3c5SJeremy L Thompson char *tmp; 1072d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1073d1d35e2fSjeremylt memcpy(tmp, field_name, len+1); 1074d1d35e2fSjeremylt (*op_field)->field_name = tmp; 1075e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1076d7b241e6Sjeremylt } 1077d7b241e6Sjeremylt 1078d7b241e6Sjeremylt /** 107952d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1080288c0443SJeremy L Thompson 1081d1d35e2fSjeremylt @param[out] composite_op Composite CeedOperator 1082d1d35e2fSjeremylt @param sub_op Sub-operator CeedOperator 108352d6035fSJeremy L Thompson 108452d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 108552d6035fSJeremy L Thompson 10867a982d89SJeremy L. Thompson @ref User 108752d6035fSJeremy L Thompson */ 1088d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op, 1089d1d35e2fSjeremylt CeedOperator sub_op) { 1090d1d35e2fSjeremylt if (!composite_op->composite) 1091c042f62fSJeremy L Thompson // LCOV_EXCL_START 1092d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_MINOR, 1093e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1094c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 109552d6035fSJeremy L Thompson 1096d1d35e2fSjeremylt if (composite_op->num_suboperators == CEED_COMPOSITE_MAX) 1097c042f62fSJeremy L Thompson // LCOV_EXCL_START 1098d1d35e2fSjeremylt return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED, 1099d1d35e2fSjeremylt "Cannot add additional sub_operators"); 1100c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 110152d6035fSJeremy L Thompson 1102d1d35e2fSjeremylt composite_op->sub_operators[composite_op->num_suboperators] = sub_op; 1103d1d35e2fSjeremylt sub_op->ref_count++; 1104d1d35e2fSjeremylt composite_op->num_suboperators++; 1105e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 110652d6035fSJeremy L Thompson } 110752d6035fSJeremy L Thompson 110852d6035fSJeremy L Thompson /** 11091d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11101d102b48SJeremy L Thompson 11111d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11121d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11131d102b48SJeremy L Thompson The vector 'assembled' is of shape 11141d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11151d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11161d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11171d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11184cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11191d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11201d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11211d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11221d102b48SJeremy L Thompson 11231d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11241d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11251d102b48SJeremy L Thompson quadrature points 11261d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11271d102b48SJeremy L Thompson CeedQFunction 11281d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11294cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11301d102b48SJeremy L Thompson 11311d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11321d102b48SJeremy L Thompson 11337a982d89SJeremy L. Thompson @ref User 11341d102b48SJeremy L Thompson **/ 113580ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11367f823360Sjeremylt CeedElemRestriction *rstr, 11377f823360Sjeremylt CeedRequest *request) { 11381d102b48SJeremy L Thompson int ierr; 1139e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11401d102b48SJeremy L Thompson 11417172caadSjeremylt // Backend version 114280ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1143e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11445107b09fSJeremy L Thompson } else { 11455107b09fSJeremy L Thompson // Fallback to reference Ceed 1146d1d35e2fSjeremylt if (!op->op_fallback) { 11475107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11485107b09fSJeremy L Thompson } 11495107b09fSJeremy L Thompson // Assemble 1150d1d35e2fSjeremylt return CeedOperatorLinearAssembleQFunction(op->op_fallback, assembled, 1151e2f04181SAndrew T. Barker rstr, request); 11525107b09fSJeremy L Thompson } 11531d102b48SJeremy L Thompson } 11541d102b48SJeremy L Thompson 11551d102b48SJeremy L Thompson /** 1156d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1157b7ec98d8SJeremy L Thompson 11589e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1159b7ec98d8SJeremy L Thompson 1160c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1161c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1162d965c7a7SJeremy L Thompson 1163b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1164b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1165b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11664cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1167b7ec98d8SJeremy L Thompson 1168b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1169b7ec98d8SJeremy L Thompson 11707a982d89SJeremy L. Thompson @ref User 1171b7ec98d8SJeremy L Thompson **/ 11722bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11737f823360Sjeremylt CeedRequest *request) { 1174b7ec98d8SJeremy L Thompson int ierr; 1175e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1176b7ec98d8SJeremy L Thompson 1177b7ec98d8SJeremy L Thompson // Use backend version, if available 117880ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1179e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 11809e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11819e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11829e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11839e9210b8SJeremy L Thompson } else { 11849e9210b8SJeremy L Thompson // Fallback to reference Ceed 1185d1d35e2fSjeremylt if (!op->op_fallback) { 11869e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11879e9210b8SJeremy L Thompson } 11889e9210b8SJeremy L Thompson // Assemble 1189d1d35e2fSjeremylt return CeedOperatorLinearAssembleDiagonal(op->op_fallback, assembled, 1190e2f04181SAndrew T. Barker request); 11919e9210b8SJeremy L Thompson } 11929e9210b8SJeremy L Thompson } 11939e9210b8SJeremy L Thompson 11949e9210b8SJeremy L Thompson /** 11959e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 11969e9210b8SJeremy L Thompson 11979e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 11989e9210b8SJeremy L Thompson 11999e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12009e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12019e9210b8SJeremy L Thompson 12029e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12039e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 12049e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12059e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 12069e9210b8SJeremy L Thompson 12079e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12089e9210b8SJeremy L Thompson 12099e9210b8SJeremy L Thompson @ref User 12109e9210b8SJeremy L Thompson **/ 12119e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12129e9210b8SJeremy L Thompson CeedRequest *request) { 12139e9210b8SJeremy L Thompson int ierr; 1214e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12159e9210b8SJeremy L Thompson 12169e9210b8SJeremy L Thompson // Use backend version, if available 12179e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1218e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12197172caadSjeremylt } else { 12207172caadSjeremylt // Fallback to reference Ceed 1221d1d35e2fSjeremylt if (!op->op_fallback) { 12227172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1223b7ec98d8SJeremy L Thompson } 12247172caadSjeremylt // Assemble 1225d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddDiagonal(op->op_fallback, assembled, 1226e2f04181SAndrew T. Barker request); 1227b7ec98d8SJeremy L Thompson } 1228b7ec98d8SJeremy L Thompson } 1229b7ec98d8SJeremy L Thompson 1230b7ec98d8SJeremy L Thompson /** 1231d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1232d965c7a7SJeremy L Thompson 12339e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1234d965c7a7SJeremy L Thompson CeedOperator. 1235d965c7a7SJeremy L Thompson 1236c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1237c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1238d965c7a7SJeremy L Thompson 1239d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1240d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1241d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1242d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 1243d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1244d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1245d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1246d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1247d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1248d965c7a7SJeremy L Thompson 1249d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1250d965c7a7SJeremy L Thompson 1251d965c7a7SJeremy L Thompson @ref User 1252d965c7a7SJeremy L Thompson **/ 125380ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12542bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1255d965c7a7SJeremy L Thompson int ierr; 1256e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1257d965c7a7SJeremy L Thompson 1258d965c7a7SJeremy L Thompson // Use backend version, if available 125980ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1260e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12619e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12629e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12639e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12649e9210b8SJeremy L Thompson request); 1265d965c7a7SJeremy L Thompson } else { 1266d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1267d1d35e2fSjeremylt if (!op->op_fallback) { 1268d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1269d965c7a7SJeremy L Thompson } 1270d965c7a7SJeremy L Thompson // Assemble 1271d1d35e2fSjeremylt return CeedOperatorLinearAssemblePointBlockDiagonal(op->op_fallback, 1272e2f04181SAndrew T. Barker assembled, request); 12739e9210b8SJeremy L Thompson } 12749e9210b8SJeremy L Thompson } 12759e9210b8SJeremy L Thompson 12769e9210b8SJeremy L Thompson /** 12779e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12789e9210b8SJeremy L Thompson 12799e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12809e9210b8SJeremy L Thompson CeedOperator. 12819e9210b8SJeremy L Thompson 12829e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12839e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12849e9210b8SJeremy L Thompson 12859e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12869e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 12879e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 1288d1d35e2fSjeremylt @a num_comp * @a num_comp block at each node. The dimensions 12899e9210b8SJeremy L Thompson of this vector are derived from the active vector 12909e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 12919e9210b8SJeremy L Thompson [nodes, component out, component in]. 12929e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12939e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 12949e9210b8SJeremy L Thompson 12959e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12969e9210b8SJeremy L Thompson 12979e9210b8SJeremy L Thompson @ref User 12989e9210b8SJeremy L Thompson **/ 12999e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 13009e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 13019e9210b8SJeremy L Thompson int ierr; 1302e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 13039e9210b8SJeremy L Thompson 13049e9210b8SJeremy L Thompson // Use backend version, if available 13059e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1306e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 13079e9210b8SJeremy L Thompson } else { 13089e9210b8SJeremy L Thompson // Fallback to reference Ceed 1309d1d35e2fSjeremylt if (!op->op_fallback) { 13109e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13119e9210b8SJeremy L Thompson } 13129e9210b8SJeremy L Thompson // Assemble 1313d1d35e2fSjeremylt return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->op_fallback, 1314e2f04181SAndrew T. Barker assembled, request); 1315d965c7a7SJeremy L Thompson } 1316e2f04181SAndrew T. Barker } 1317e2f04181SAndrew T. Barker 1318e2f04181SAndrew T. Barker /** 1319e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1320e2f04181SAndrew T. Barker 1321e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1322e2f04181SAndrew T. Barker 1323e2f04181SAndrew T. Barker @ref Developer 1324e2f04181SAndrew T. Barker **/ 1325e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1326e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1327e2f04181SAndrew T. Barker int ierr; 1328e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1329e2f04181SAndrew T. Barker if (op->composite) 1330e2f04181SAndrew T. Barker // LCOV_EXCL_START 1331e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1332e2f04181SAndrew T. Barker "Composite operator not supported"); 1333e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1334e2f04181SAndrew T. Barker 1335d1d35e2fSjeremylt CeedElemRestriction rstr_in; 1336d1d35e2fSjeremylt ierr = CeedOperatorGetActiveElemRestriction(op, &rstr_in); CeedChk(ierr); 1337d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_nodes, num_comp; 1338d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1339d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1340d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr_in, &num_nodes); CeedChk(ierr); 1341d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1342e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1343d1d35e2fSjeremylt ierr = CeedElemRestrictionGetELayout(rstr_in, &layout_er); CeedChk(ierr); 1344e2f04181SAndrew T. Barker 1345d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1346e2f04181SAndrew T. Barker 1347e2f04181SAndrew T. Barker // Determine elem_dof relation 1348e2f04181SAndrew T. Barker CeedVector index_vec; 1349d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_nodes, &index_vec); CeedChk(ierr); 1350e2f04181SAndrew T. Barker CeedScalar *array; 1351e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1352d1d35e2fSjeremylt for (CeedInt i = 0; i < num_nodes; ++i) { 1353e2f04181SAndrew T. Barker array[i] = i; 1354e2f04181SAndrew T. Barker } 1355e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1356e2f04181SAndrew T. Barker CeedVector elem_dof; 1357d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, num_elem * elem_size * num_comp, &elem_dof); 1358e2f04181SAndrew T. Barker CeedChk(ierr); 1359e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1360d1d35e2fSjeremylt CeedElemRestrictionApply(rstr_in, CEED_NOTRANSPOSE, index_vec, 1361e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1362e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1363e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1364e2f04181SAndrew T. Barker CeedChk(ierr); 1365e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1366e2f04181SAndrew T. Barker 1367e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1368e2f04181SAndrew T. Barker CeedInt count = 0; 1369d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1370d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1371d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1372d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1373d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1374d1d35e2fSjeremylt const CeedInt elem_dof_index_row = (i)*layout_er[0] + 1375d1d35e2fSjeremylt (comp_out)*layout_er[1] + e*layout_er[2]; 1376d1d35e2fSjeremylt const CeedInt elem_dof_index_col = (j)*layout_er[0] + 1377d1d35e2fSjeremylt (comp_in)*layout_er[1] + e*layout_er[2]; 1378e2f04181SAndrew T. Barker 1379d1d35e2fSjeremylt const CeedInt row = elem_dof_a[elem_dof_index_row]; 1380d1d35e2fSjeremylt const CeedInt col = elem_dof_a[elem_dof_index_col]; 1381e2f04181SAndrew T. Barker 1382e2f04181SAndrew T. Barker rows[offset + count] = row; 1383e2f04181SAndrew T. Barker cols[offset + count] = col; 1384e2f04181SAndrew T. Barker count++; 1385e2f04181SAndrew T. Barker } 1386e2f04181SAndrew T. Barker } 1387e2f04181SAndrew T. Barker } 1388e2f04181SAndrew T. Barker } 1389e2f04181SAndrew T. Barker } 1390d1d35e2fSjeremylt if (count != local_num_entries) 1391e2f04181SAndrew T. Barker // LCOV_EXCL_START 1392e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1393e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1394e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1395e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1396e2f04181SAndrew T. Barker 1397e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1398e2f04181SAndrew T. Barker } 1399e2f04181SAndrew T. Barker 1400e2f04181SAndrew T. Barker /** 1401e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1402e2f04181SAndrew T. Barker 1403e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1404e2f04181SAndrew T. Barker 1405e2f04181SAndrew T. Barker @ref Developer 1406e2f04181SAndrew T. Barker **/ 1407e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1408e2f04181SAndrew T. Barker CeedVector values) { 1409e2f04181SAndrew T. Barker int ierr; 1410e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1411e2f04181SAndrew T. Barker if (op->composite) 1412e2f04181SAndrew T. Barker // LCOV_EXCL_START 1413e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1414e2f04181SAndrew T. Barker "Composite operator not supported"); 1415e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1416e2f04181SAndrew T. Barker 1417e2f04181SAndrew T. Barker // Assemble QFunction 1418e2f04181SAndrew T. Barker CeedQFunction qf; 1419e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1420d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 1421d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 1422e2f04181SAndrew T. Barker CeedChk(ierr); 1423d1d35e2fSjeremylt CeedVector assembled_qf; 1424e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1425e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1426d1d35e2fSjeremylt op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1427e2f04181SAndrew T. Barker 1428d1d35e2fSjeremylt CeedInt qf_length; 1429d1d35e2fSjeremylt ierr = CeedVectorGetLength(assembled_qf, &qf_length); CeedChk(ierr); 1430e2f04181SAndrew T. Barker 1431e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1432e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1433e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1434e2f04181SAndrew T. Barker 1435e2f04181SAndrew T. Barker // Determine active input basis 1436d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1437d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChk(ierr); 1438d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, dim = 1; 1439d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 1440d1d35e2fSjeremylt CeedBasis basis_in = NULL; 1441d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 1442d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1443e2f04181SAndrew T. Barker CeedVector vec; 1444e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1445e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1446d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(input_fields[i], &basis_in); 1447e2f04181SAndrew T. Barker CeedChk(ierr); 1448d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChk(ierr); 1449d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in); 1450e2f04181SAndrew T. Barker CeedChk(ierr); 1451d1d35e2fSjeremylt CeedEvalMode eval_mode; 1452d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1453e2f04181SAndrew T. Barker CeedChk(ierr); 1454d1d35e2fSjeremylt switch (eval_mode) { 1455e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1456e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1457d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChk(ierr); 1458d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 1459d1d35e2fSjeremylt num_eval_mode_in += 1; 1460e2f04181SAndrew T. Barker break; 1461e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1462d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChk(ierr); 1463e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1464d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 1465e2f04181SAndrew T. Barker } 1466d1d35e2fSjeremylt num_eval_mode_in += dim; 1467e2f04181SAndrew T. Barker break; 1468e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1469e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1470e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1471e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1472e2f04181SAndrew T. Barker } 1473e2f04181SAndrew T. Barker } 1474e2f04181SAndrew T. Barker } 1475e2f04181SAndrew T. Barker 1476e2f04181SAndrew T. Barker // Determine active output basis 1477d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChk(ierr); 1478d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 1479d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 1480d1d35e2fSjeremylt CeedBasis basis_out = NULL; 1481d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 1482d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 1483e2f04181SAndrew T. Barker CeedVector vec; 1484e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1485e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1486d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(output_fields[i], &basis_out); 1487e2f04181SAndrew T. Barker CeedChk(ierr); 1488d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out); 1489e2f04181SAndrew T. Barker CeedChk(ierr); 1490d1d35e2fSjeremylt CeedEvalMode eval_mode; 1491d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1492e2f04181SAndrew T. Barker CeedChk(ierr); 1493d1d35e2fSjeremylt switch (eval_mode) { 1494e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1495e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1496d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChk(ierr); 1497d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 1498d1d35e2fSjeremylt num_eval_mode_out += 1; 1499e2f04181SAndrew T. Barker break; 1500e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1501d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); CeedChk(ierr); 1502e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1503d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 1504e2f04181SAndrew T. Barker } 1505d1d35e2fSjeremylt num_eval_mode_out += dim; 1506e2f04181SAndrew T. Barker break; 1507e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1508e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1509e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1510e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1511e2f04181SAndrew T. Barker } 1512e2f04181SAndrew T. Barker } 1513e2f04181SAndrew T. Barker } 1514e2f04181SAndrew T. Barker 1515*78464608Sjeremylt if (num_eval_mode_in == 0 || num_eval_mode_out == 0) 1516*78464608Sjeremylt // LCOV_EXCL_START 1517*78464608Sjeremylt return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1518*78464608Sjeremylt "Cannot assemble operator with out inputs/outputs"); 1519*78464608Sjeremylt // LCOV_EXCL_STOP 1520*78464608Sjeremylt 1521d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_qpts, num_comp; 1522d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr_in, &num_elem); CeedChk(ierr); 1523d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_in, &elem_size); CeedChk(ierr); 1524d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr_in, &num_comp); CeedChk(ierr); 1525d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); CeedChk(ierr); 1526e2f04181SAndrew T. Barker 1527d1d35e2fSjeremylt CeedInt local_num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1528e2f04181SAndrew T. Barker 1529e2f04181SAndrew T. Barker // loop over elements and put in data structure 1530d1d35e2fSjeremylt const CeedScalar *interp_in, *grad_in; 1531d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChk(ierr); 1532d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChk(ierr); 1533e2f04181SAndrew T. Barker 1534d1d35e2fSjeremylt const CeedScalar *assembled_qf_array; 1535d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 1536e2f04181SAndrew T. Barker CeedChk(ierr); 1537e2f04181SAndrew T. Barker 1538e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1539e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1540e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1541e2f04181SAndrew T. Barker 1542d1d35e2fSjeremylt // we store B_mat_in, B_mat_out, BTD, elem_mat in row-major order 1543d1d35e2fSjeremylt CeedScalar B_mat_in[(num_qpts * num_eval_mode_in) * elem_size]; 1544d1d35e2fSjeremylt CeedScalar B_mat_out[(num_qpts * num_eval_mode_out) * elem_size]; 1545d1d35e2fSjeremylt CeedScalar D_mat[num_eval_mode_out * num_eval_mode_in * 1546d1d35e2fSjeremylt num_qpts]; // logically 3-tensor 1547d1d35e2fSjeremylt CeedScalar BTD[elem_size * num_qpts*num_eval_mode_in]; 1548d1d35e2fSjeremylt CeedScalar elem_mat[elem_size * elem_size]; 1549e2f04181SAndrew T. Barker int count = 0; 1550e2f04181SAndrew T. Barker CeedScalar *vals; 1551e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1552d1d35e2fSjeremylt for (int e = 0; e < num_elem; ++e) { 1553d1d35e2fSjeremylt for (int comp_in = 0; comp_in < num_comp; ++comp_in) { 1554d1d35e2fSjeremylt for (int comp_out = 0; comp_out < num_comp; ++comp_out) { 1555d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_in) * elem_size; ++ell) { 1556d1d35e2fSjeremylt B_mat_in[ell] = 0.0; 1557e2f04181SAndrew T. Barker } 1558d1d35e2fSjeremylt for (int ell = 0; ell < (num_qpts * num_eval_mode_out) * elem_size; ++ell) { 1559d1d35e2fSjeremylt B_mat_out[ell] = 0.0; 1560e2f04181SAndrew T. Barker } 1561e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1562d1d35e2fSjeremylt for (int ell = 0; ell < num_eval_mode_in*num_eval_mode_out*num_qpts; ++ell) { 1563d1d35e2fSjeremylt D_mat[ell] = 0.0; 1564e2f04181SAndrew T. Barker } 1565e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1566d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*elem_size; ++ell) { 1567e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1568e2f04181SAndrew T. Barker } 1569d1d35e2fSjeremylt for (int q = 0; q < num_qpts; ++q) { 1570d1d35e2fSjeremylt for (int n = 0; n < elem_size; ++n) { 1571d1d35e2fSjeremylt CeedInt d_in = -1; 1572d1d35e2fSjeremylt for (int e_in = 0; e_in < num_eval_mode_in; ++e_in) { 1573d1d35e2fSjeremylt const int qq = num_eval_mode_in*q; 1574d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_INTERP) { 1575d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += interp_in[q * elem_size + n]; 1576d1d35e2fSjeremylt } else if (eval_mode_in[e_in] == CEED_EVAL_GRAD) { 1577d1d35e2fSjeremylt d_in += 1; 1578d1d35e2fSjeremylt B_mat_in[(qq+e_in)*elem_size + n] += 1579d1d35e2fSjeremylt grad_in[(d_in*num_qpts+q) * elem_size + n]; 1580e2f04181SAndrew T. Barker } else { 1581e2f04181SAndrew T. Barker // LCOV_EXCL_START 1582e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1583e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1584e2f04181SAndrew T. Barker } 1585e2f04181SAndrew T. Barker } 1586d1d35e2fSjeremylt CeedInt d_out = -1; 1587d1d35e2fSjeremylt for (int e_out = 0; e_out < num_eval_mode_out; ++e_out) { 1588d1d35e2fSjeremylt const int qq = num_eval_mode_out*q; 1589d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_INTERP) { 1590d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += interp_in[q * elem_size + n]; 1591d1d35e2fSjeremylt } else if (eval_mode_out[e_out] == CEED_EVAL_GRAD) { 1592d1d35e2fSjeremylt d_out += 1; 1593d1d35e2fSjeremylt B_mat_out[(qq+e_out)*elem_size + n] += 1594d1d35e2fSjeremylt grad_in[(d_out*num_qpts+q) * elem_size + n]; 1595e2f04181SAndrew T. Barker } else { 1596e2f04181SAndrew T. Barker // LCOV_EXCL_START 1597e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1598e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1599e2f04181SAndrew T. Barker } 1600e2f04181SAndrew T. Barker } 1601e2f04181SAndrew T. Barker } 1602d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_out; ++ei) { 1603d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_in; ++ej) { 1604d1d35e2fSjeremylt const int eval_mode_index = ((ei*num_comp+comp_in)*num_eval_mode_in+ej)*num_comp 1605d1d35e2fSjeremylt +comp_out; 1606d1d35e2fSjeremylt const int index = q*layout_qf[0] + eval_mode_index*layout_qf[1] + 1607d1d35e2fSjeremylt e*layout_qf[2]; 1608d1d35e2fSjeremylt D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q] += assembled_qf_array[index]; 1609e2f04181SAndrew T. Barker } 1610e2f04181SAndrew T. Barker } 1611e2f04181SAndrew T. Barker } 1612e2f04181SAndrew T. Barker // Compute B^T*D 1613d1d35e2fSjeremylt for (int ell = 0; ell < elem_size*num_qpts*num_eval_mode_in; ++ell) { 1614e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1615e2f04181SAndrew T. Barker } 1616d1d35e2fSjeremylt for (int j = 0; j<elem_size; ++j) { 1617d1d35e2fSjeremylt for (int q = 0; q<num_qpts; ++q) { 1618d1d35e2fSjeremylt int qq = num_eval_mode_out*q; 1619d1d35e2fSjeremylt for (int ei = 0; ei < num_eval_mode_in; ++ei) { 1620d1d35e2fSjeremylt for (int ej = 0; ej < num_eval_mode_out; ++ej) { 1621d1d35e2fSjeremylt BTD[j*(num_qpts*num_eval_mode_in) + (qq+ei)] += 1622d1d35e2fSjeremylt B_mat_out[(qq+ej)*elem_size + j] * D_mat[(ei*num_eval_mode_in+ej)*num_qpts + q]; 1623e2f04181SAndrew T. Barker } 1624e2f04181SAndrew T. Barker } 1625e2f04181SAndrew T. Barker } 1626e2f04181SAndrew T. Barker } 1627e2f04181SAndrew T. Barker 1628d1d35e2fSjeremylt ierr = CeedMatrixMultiply(ceed, BTD, B_mat_in, elem_mat, elem_size, 1629d1d35e2fSjeremylt elem_size, num_qpts*num_eval_mode_in); CeedChk(ierr); 1630e2f04181SAndrew T. Barker 1631e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1632d1d35e2fSjeremylt for (int i = 0; i < elem_size; ++i) { 1633d1d35e2fSjeremylt for (int j = 0; j < elem_size; ++j) { 1634d1d35e2fSjeremylt vals[offset + count] = elem_mat[i*elem_size + j]; 1635e2f04181SAndrew T. Barker count++; 1636e2f04181SAndrew T. Barker } 1637e2f04181SAndrew T. Barker } 1638e2f04181SAndrew T. Barker } 1639e2f04181SAndrew T. Barker } 1640e2f04181SAndrew T. Barker } 1641d1d35e2fSjeremylt if (count != local_num_entries) 1642e2f04181SAndrew T. Barker // LCOV_EXCL_START 1643e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1644e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1645e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1646e2f04181SAndrew T. Barker 1647d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(assembled_qf, &assembled_qf_array); 1648e2f04181SAndrew T. Barker CeedChk(ierr); 1649d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChk(ierr); 1650d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChk(ierr); 1651d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChk(ierr); 1652e2f04181SAndrew T. Barker 1653e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1654e2f04181SAndrew T. Barker } 1655e2f04181SAndrew T. Barker 1656e2f04181SAndrew T. Barker /** 1657e2f04181SAndrew T. Barker @ref Utility 1658e2f04181SAndrew T. Barker **/ 1659d1d35e2fSjeremylt int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, 1660d1d35e2fSjeremylt CeedInt *num_entries) { 1661e2f04181SAndrew T. Barker int ierr; 1662e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1663d1d35e2fSjeremylt CeedInt num_elem, elem_size, num_comp; 1664e2f04181SAndrew T. Barker 1665e2f04181SAndrew T. Barker if (op->composite) 1666e2f04181SAndrew T. Barker // LCOV_EXCL_START 1667e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1668e2f04181SAndrew T. Barker "Composite operator not supported"); 1669e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1670e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1671d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChk(ierr); 1672d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); CeedChk(ierr); 1673d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); CeedChk(ierr); 1674d1d35e2fSjeremylt *num_entries = elem_size*num_comp * elem_size*num_comp * num_elem; 1675e2f04181SAndrew T. Barker 1676e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1677e2f04181SAndrew T. Barker } 1678e2f04181SAndrew T. Barker 1679e2f04181SAndrew T. Barker /** 1680e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1681e2f04181SAndrew T. Barker 1682e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1683e2f04181SAndrew T. Barker 1684d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1685e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1686e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1687e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1688e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1689e2f04181SAndrew T. Barker ordering. 1690e2f04181SAndrew T. Barker 1691e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1692e2f04181SAndrew T. Barker 1693e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1694d1d35e2fSjeremylt @param[out] num_entries Number of entries in coordinate nonzero pattern. 1695e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1696e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1697e2f04181SAndrew T. Barker 1698e2f04181SAndrew T. Barker @ref User 1699e2f04181SAndrew T. Barker **/ 1700e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1701d1d35e2fSjeremylt CeedInt *num_entries, CeedInt **rows, CeedInt **cols) { 1702e2f04181SAndrew T. Barker int ierr; 1703d1d35e2fSjeremylt CeedInt num_suboperators, single_entries; 1704d1d35e2fSjeremylt CeedOperator *sub_operators; 1705d1d35e2fSjeremylt bool is_composite; 1706e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1707e2f04181SAndrew T. Barker 1708e2f04181SAndrew T. Barker // Use backend version, if available 1709e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1710d1d35e2fSjeremylt return op->LinearAssembleSymbolic(op, num_entries, rows, cols); 1711e2f04181SAndrew T. Barker } else { 1712e2f04181SAndrew T. Barker // Check for valid fallback resource 1713d1d35e2fSjeremylt const char *resource, *fallback_resource; 1714e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1715d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1716*78464608Sjeremylt CeedChk(ierr); 1717d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1718e2f04181SAndrew T. Barker // Fallback to reference Ceed 1719d1d35e2fSjeremylt if (!op->op_fallback) { 1720e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1721e2f04181SAndrew T. Barker } 1722e2f04181SAndrew T. Barker // Assemble 1723d1d35e2fSjeremylt return CeedOperatorLinearAssembleSymbolic(op->op_fallback, num_entries, rows, 1724d1d35e2fSjeremylt cols); 1725e2f04181SAndrew T. Barker } 1726e2f04181SAndrew T. Barker } 1727e2f04181SAndrew T. Barker 1728e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1729e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1730e2f04181SAndrew T. Barker 1731e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1732d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1733d1d35e2fSjeremylt *num_entries = 0; 1734d1d35e2fSjeremylt if (is_composite) { 1735d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1736d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1737d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1738d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1739e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1740d1d35e2fSjeremylt *num_entries += single_entries; 1741e2f04181SAndrew T. Barker } 1742e2f04181SAndrew T. Barker } else { 1743e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1744e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1745d1d35e2fSjeremylt *num_entries += single_entries; 1746e2f04181SAndrew T. Barker } 1747d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, rows); CeedChk(ierr); 1748d1d35e2fSjeremylt ierr = CeedCalloc(*num_entries, cols); CeedChk(ierr); 1749e2f04181SAndrew T. Barker 1750e2f04181SAndrew T. Barker // assemble nonzero locations 1751e2f04181SAndrew T. Barker CeedInt offset = 0; 1752d1d35e2fSjeremylt if (is_composite) { 1753d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1754d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1755d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1756d1d35e2fSjeremylt ierr = CeedSingleOperatorAssembleSymbolic(sub_operators[k], offset, *rows, 1757e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1758d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1759d1d35e2fSjeremylt &single_entries); 1760e2f04181SAndrew T. Barker CeedChk(ierr); 1761e2f04181SAndrew T. Barker offset += single_entries; 1762e2f04181SAndrew T. Barker } 1763e2f04181SAndrew T. Barker } else { 1764e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1765e2f04181SAndrew T. Barker CeedChk(ierr); 1766e2f04181SAndrew T. Barker } 1767e2f04181SAndrew T. Barker 1768e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1769e2f04181SAndrew T. Barker } 1770e2f04181SAndrew T. Barker 1771e2f04181SAndrew T. Barker /** 1772e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1773e2f04181SAndrew T. Barker 1774e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1775e2f04181SAndrew T. Barker 1776d1d35e2fSjeremylt The assembly routines use coordinate format, with num_entries tuples of the 1777e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1778e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1779e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1780e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1781e2f04181SAndrew T. Barker 1782e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1783e2f04181SAndrew T. Barker 1784e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1785e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1786e2f04181SAndrew T. Barker 1787e2f04181SAndrew T. Barker @ref User 1788e2f04181SAndrew T. Barker **/ 1789e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1790e2f04181SAndrew T. Barker int ierr; 1791*78464608Sjeremylt CeedInt num_suboperators, single_entries = 0; 1792d1d35e2fSjeremylt CeedOperator *sub_operators; 1793e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1794e2f04181SAndrew T. Barker 1795e2f04181SAndrew T. Barker // Use backend version, if available 1796e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1797e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1798e2f04181SAndrew T. Barker } else { 1799e2f04181SAndrew T. Barker // Check for valid fallback resource 1800d1d35e2fSjeremylt const char *resource, *fallback_resource; 1801e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1802d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackResource(op->ceed, &fallback_resource); 1803*78464608Sjeremylt CeedChk(ierr); 1804d1d35e2fSjeremylt if (strcmp(fallback_resource, "") && strcmp(resource, fallback_resource)) { 1805e2f04181SAndrew T. Barker // Fallback to reference Ceed 1806d1d35e2fSjeremylt if (!op->op_fallback) { 1807e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1808e2f04181SAndrew T. Barker } 1809e2f04181SAndrew T. Barker // Assemble 1810d1d35e2fSjeremylt return CeedOperatorLinearAssemble(op->op_fallback, values); 1811e2f04181SAndrew T. Barker } 1812e2f04181SAndrew T. Barker } 1813e2f04181SAndrew T. Barker 1814e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1815e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1816e2f04181SAndrew T. Barker 1817d1d35e2fSjeremylt bool is_composite; 1818d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChk(ierr); 1819e2f04181SAndrew T. Barker 1820e2f04181SAndrew T. Barker CeedInt offset = 0; 1821d1d35e2fSjeremylt if (is_composite) { 1822d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 1823d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 1824d1d35e2fSjeremylt for (int k = 0; k < num_suboperators; ++k) { 1825d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemble(sub_operators[k], offset, values); 1826e2f04181SAndrew T. Barker CeedChk(ierr); 1827d1d35e2fSjeremylt ierr = CeedSingleOperatorAssemblyCountEntries(sub_operators[k], 1828d1d35e2fSjeremylt &single_entries); 1829e2f04181SAndrew T. Barker CeedChk(ierr); 1830e2f04181SAndrew T. Barker offset += single_entries; 1831e2f04181SAndrew T. Barker } 1832e2f04181SAndrew T. Barker } else { 1833e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1834e2f04181SAndrew T. Barker } 1835e2f04181SAndrew T. Barker 1836e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1837d965c7a7SJeremy L Thompson } 1838d965c7a7SJeremy L Thompson 1839d965c7a7SJeremy L Thompson /** 1840d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1841d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1842d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1843d99fa3c5SJeremy L Thompson 1844d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1845d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1846d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1847d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1848d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1849d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1850d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1851d99fa3c5SJeremy L Thompson 1852d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1853d99fa3c5SJeremy L Thompson 1854d99fa3c5SJeremy L Thompson @ref User 1855d99fa3c5SJeremy L Thompson **/ 1856d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreate(CeedOperator op_fine, 1857d1d35e2fSjeremylt CeedVector p_mult_fine, 1858d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1859d1d35e2fSjeremylt CeedOperator *op_coarse, CeedOperator *op_prolong, 1860d1d35e2fSjeremylt CeedOperator *op_restrict) { 1861d99fa3c5SJeremy L Thompson int ierr; 1862d99fa3c5SJeremy L Thompson Ceed ceed; 1863d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1864d99fa3c5SJeremy L Thompson 1865d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1866d1d35e2fSjeremylt CeedBasis basis_fine; 1867d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1868d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1869d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1870d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1871d1d35e2fSjeremylt if (Q_f != Q_c) 1872d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1873e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1874e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1875d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1876d99fa3c5SJeremy L Thompson 1877d99fa3c5SJeremy L Thompson // Coarse to fine basis 1878d1d35e2fSjeremylt CeedInt P_f, P_c, Q = Q_f; 1879d1d35e2fSjeremylt bool is_tensor_f, is_tensor_c; 1880d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_fine, &is_tensor_f); CeedChk(ierr); 1881d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis_coarse, &is_tensor_c); CeedChk(ierr); 1882d1d35e2fSjeremylt CeedScalar *interp_c, *interp_f, *interp_c_to_f, *tau; 1883d1d35e2fSjeremylt if (is_tensor_f && is_tensor_c) { 1884d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_f); CeedChk(ierr); 1885d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_coarse, &P_c); CeedChk(ierr); 1886d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis_coarse, &Q); CeedChk(ierr); 1887d1d35e2fSjeremylt } else if (!is_tensor_f && !is_tensor_c) { 1888d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &P_f); CeedChk(ierr); 1889d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_coarse, &P_c); CeedChk(ierr); 1890d99fa3c5SJeremy L Thompson } else { 1891d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1892e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1893e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1894d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1895d99fa3c5SJeremy L Thompson } 1896d99fa3c5SJeremy L Thompson 1897d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_f, &interp_f); CeedChk(ierr); 1898d1d35e2fSjeremylt ierr = CeedMalloc(Q*P_c, &interp_c); CeedChk(ierr); 1899d1d35e2fSjeremylt ierr = CeedCalloc(P_c*P_f, &interp_c_to_f); CeedChk(ierr); 1900d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1901d1d35e2fSjeremylt if (is_tensor_f) { 1902d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp_1d, Q*P_f*sizeof basis_fine->interp_1d[0]); 1903d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp_1d, 1904d1d35e2fSjeremylt Q*P_c*sizeof basis_coarse->interp_1d[0]); 1905d99fa3c5SJeremy L Thompson } else { 1906d1d35e2fSjeremylt memcpy(interp_f, basis_fine->interp, Q*P_f*sizeof basis_fine->interp[0]); 1907d1d35e2fSjeremylt memcpy(interp_c, basis_coarse->interp, Q*P_c*sizeof basis_coarse->interp[0]); 1908d99fa3c5SJeremy L Thompson } 1909d99fa3c5SJeremy L Thompson 1910d1d35e2fSjeremylt // -- QR Factorization, interp_f = Q R 1911d1d35e2fSjeremylt ierr = CeedQRFactorization(ceed, interp_f, tau, Q, P_f); CeedChk(ierr); 1912d99fa3c5SJeremy L Thompson 1913d1d35e2fSjeremylt // -- Apply Qtranspose, interp_c = Qtranspose interp_c 1914d1d35e2fSjeremylt ierr = CeedHouseholderApplyQ(interp_c, interp_f, tau, CEED_TRANSPOSE, 1915d1d35e2fSjeremylt Q, P_c, P_f, P_c, 1); CeedChk(ierr); 1916d99fa3c5SJeremy L Thompson 1917d1d35e2fSjeremylt // -- Apply Rinv, interp_c_to_f = Rinv interp_c 1918d1d35e2fSjeremylt for (CeedInt j=0; j<P_c; j++) { // Column j 1919d1d35e2fSjeremylt 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]; 1920d1d35e2fSjeremylt for (CeedInt i=P_f-2; i>=0; i--) { // Row i 1921d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] = interp_c[j+P_c*i]; 1922d1d35e2fSjeremylt for (CeedInt k=i+1; k<P_f; k++) 1923d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] -= interp_f[k+P_f*i]*interp_c_to_f[j+P_c*k]; 1924d1d35e2fSjeremylt interp_c_to_f[j+P_c*i] /= interp_f[i+P_f*i]; 1925d99fa3c5SJeremy L Thompson } 1926d99fa3c5SJeremy L Thompson } 1927d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1928d1d35e2fSjeremylt ierr = CeedFree(&interp_c); CeedChk(ierr); 1929d1d35e2fSjeremylt ierr = CeedFree(&interp_f); CeedChk(ierr); 1930d99fa3c5SJeremy L Thompson 1931d1d35e2fSjeremylt // Complete with interp_c_to_f versions of code 1932d1d35e2fSjeremylt if (is_tensor_f) { 1933d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateTensorH1(op_fine, p_mult_fine, 1934d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1935d99fa3c5SJeremy L Thompson CeedChk(ierr); 1936d99fa3c5SJeremy L Thompson } else { 1937d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevelCreateH1(op_fine, p_mult_fine, 1938d1d35e2fSjeremylt rstr_coarse, basis_coarse, interp_c_to_f, op_coarse, op_prolong, op_restrict); 1939d99fa3c5SJeremy L Thompson CeedChk(ierr); 1940d99fa3c5SJeremy L Thompson } 1941d99fa3c5SJeremy L Thompson 1942d99fa3c5SJeremy L Thompson // Cleanup 1943d1d35e2fSjeremylt ierr = CeedFree(&interp_c_to_f); CeedChk(ierr); 1944e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1945d99fa3c5SJeremy L Thompson } 1946d99fa3c5SJeremy L Thompson 1947d99fa3c5SJeremy L Thompson /** 1948d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1949d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1950d99fa3c5SJeremy L Thompson 1951d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 1952d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 1953d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 1954d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 1955d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 1956d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 1957d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 1958d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 1959d99fa3c5SJeremy L Thompson 1960d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1961d99fa3c5SJeremy L Thompson 1962d99fa3c5SJeremy L Thompson @ref User 1963d99fa3c5SJeremy L Thompson **/ 1964d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator op_fine, 1965d1d35e2fSjeremylt CeedVector p_mult_fine, CeedElemRestriction rstr_coarse, CeedBasis basis_coarse, 1966d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, CeedOperator *op_coarse, 1967d1d35e2fSjeremylt CeedOperator *op_prolong, CeedOperator *op_restrict) { 1968d99fa3c5SJeremy L Thompson int ierr; 1969d99fa3c5SJeremy L Thompson Ceed ceed; 1970d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 1971d99fa3c5SJeremy L Thompson 1972d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1973d1d35e2fSjeremylt CeedBasis basis_fine; 1974d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 1975d1d35e2fSjeremylt CeedInt Q_f, Q_c; 1976d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 1977d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 1978d1d35e2fSjeremylt if (Q_f != Q_c) 1979d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1980e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1981e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1982d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1983d99fa3c5SJeremy L Thompson 1984d99fa3c5SJeremy L Thompson // Coarse to fine basis 1985d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, P_1d_f, P_1d_c; 1986d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 1987d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 1988d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis_fine, &P_1d_f); CeedChk(ierr); 1989d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 1990d99fa3c5SJeremy L Thompson CeedChk(ierr); 1991d1d35e2fSjeremylt P_1d_c = dim == 1 ? num_nodes_c : 1992d1d35e2fSjeremylt dim == 2 ? sqrt(num_nodes_c) : 1993d1d35e2fSjeremylt cbrt(num_nodes_c); 1994d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 1995d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_ref); CeedChk(ierr); 1996d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f, &q_weight); CeedChk(ierr); 1997d1d35e2fSjeremylt ierr = CeedCalloc(P_1d_f*P_1d_c*dim, &grad); CeedChk(ierr); 1998d1d35e2fSjeremylt CeedBasis basis_c_to_f; 1999d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, num_comp, P_1d_c, P_1d_f, 2000d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2001d99fa3c5SJeremy L Thompson CeedChk(ierr); 2002d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2003d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2004d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2005d99fa3c5SJeremy L Thompson 2006d99fa3c5SJeremy L Thompson // Core code 2007d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2008d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2009d1d35e2fSjeremylt op_prolong, op_restrict); 2010d99fa3c5SJeremy L Thompson CeedChk(ierr); 2011e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2012d99fa3c5SJeremy L Thompson } 2013d99fa3c5SJeremy L Thompson 2014d99fa3c5SJeremy L Thompson /** 2015d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 2016d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 2017d99fa3c5SJeremy L Thompson 2018d1d35e2fSjeremylt @param[in] op_fine Fine grid operator 2019d1d35e2fSjeremylt @param[in] p_mult_fine L-vector multiplicity in parallel gather/scatter 2020d1d35e2fSjeremylt @param[in] rstr_coarse Coarse grid restriction 2021d1d35e2fSjeremylt @param[in] basis_coarse Coarse grid active vector basis 2022d1d35e2fSjeremylt @param[in] interp_c_to_f Matrix for coarse to fine interpolation 2023d1d35e2fSjeremylt @param[out] op_coarse Coarse grid operator 2024d1d35e2fSjeremylt @param[out] op_prolong Coarse to fine operator 2025d1d35e2fSjeremylt @param[out] op_restrict Fine to coarse operator 2026d99fa3c5SJeremy L Thompson 2027d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2028d99fa3c5SJeremy L Thompson 2029d99fa3c5SJeremy L Thompson @ref User 2030d99fa3c5SJeremy L Thompson **/ 2031d1d35e2fSjeremylt int CeedOperatorMultigridLevelCreateH1(CeedOperator op_fine, 2032d1d35e2fSjeremylt CeedVector p_mult_fine, 2033d1d35e2fSjeremylt CeedElemRestriction rstr_coarse, 2034d1d35e2fSjeremylt CeedBasis basis_coarse, 2035d1d35e2fSjeremylt const CeedScalar *interp_c_to_f, 2036d1d35e2fSjeremylt CeedOperator *op_coarse, 2037d1d35e2fSjeremylt CeedOperator *op_prolong, 2038d1d35e2fSjeremylt CeedOperator *op_restrict) { 2039d99fa3c5SJeremy L Thompson int ierr; 2040d99fa3c5SJeremy L Thompson Ceed ceed; 2041d1d35e2fSjeremylt ierr = CeedOperatorGetCeed(op_fine, &ceed); CeedChk(ierr); 2042d99fa3c5SJeremy L Thompson 2043d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2044d1d35e2fSjeremylt CeedBasis basis_fine; 2045d1d35e2fSjeremylt ierr = CeedOperatorGetActiveBasis(op_fine, &basis_fine); CeedChk(ierr); 2046d1d35e2fSjeremylt CeedInt Q_f, Q_c; 2047d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_fine, &Q_f); CeedChk(ierr); 2048d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_coarse, &Q_c); CeedChk(ierr); 2049d1d35e2fSjeremylt if (Q_f != Q_c) 2050d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2051e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2052e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2053d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2054d99fa3c5SJeremy L Thompson 2055d99fa3c5SJeremy L Thompson // Coarse to fine basis 2056d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2057d1d35e2fSjeremylt ierr = CeedBasisGetTopology(basis_fine, &topo); CeedChk(ierr); 2058d1d35e2fSjeremylt CeedInt dim, num_comp, num_nodes_c, num_nodes_f; 2059d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_fine, &dim); CeedChk(ierr); 2060d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_fine, &num_comp); CeedChk(ierr); 2061d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_fine, &num_nodes_f); CeedChk(ierr); 2062d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr_coarse, &num_nodes_c); 2063d99fa3c5SJeremy L Thompson CeedChk(ierr); 2064d1d35e2fSjeremylt CeedScalar *q_ref, *q_weight, *grad; 2065d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_ref); CeedChk(ierr); 2066d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f, &q_weight); CeedChk(ierr); 2067d1d35e2fSjeremylt ierr = CeedCalloc(num_nodes_f*num_nodes_c*dim, &grad); CeedChk(ierr); 2068d1d35e2fSjeremylt CeedBasis basis_c_to_f; 2069d1d35e2fSjeremylt ierr = CeedBasisCreateH1(ceed, topo, num_comp, num_nodes_c, num_nodes_f, 2070d1d35e2fSjeremylt interp_c_to_f, grad, q_ref, q_weight, &basis_c_to_f); 2071d99fa3c5SJeremy L Thompson CeedChk(ierr); 2072d1d35e2fSjeremylt ierr = CeedFree(&q_ref); CeedChk(ierr); 2073d1d35e2fSjeremylt ierr = CeedFree(&q_weight); CeedChk(ierr); 2074d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2075d99fa3c5SJeremy L Thompson 2076d99fa3c5SJeremy L Thompson // Core code 2077d1d35e2fSjeremylt ierr = CeedOperatorMultigridLevel_Core(op_fine, p_mult_fine, rstr_coarse, 2078d1d35e2fSjeremylt basis_coarse, basis_c_to_f, op_coarse, 2079d1d35e2fSjeremylt op_prolong, op_restrict); 2080d99fa3c5SJeremy L Thompson CeedChk(ierr); 2081e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2082d99fa3c5SJeremy L Thompson } 2083d99fa3c5SJeremy L Thompson 2084d99fa3c5SJeremy L Thompson /** 20853bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 20863bd813ffSjeremylt CeedOperator 20873bd813ffSjeremylt 20883bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 20893bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 20903bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 20913bd813ffSjeremylt M = V^T V, K = V^T S V. 20923bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 20933bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 20943bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 20953bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 20963bd813ffSjeremylt 20973bd813ffSjeremylt @param op CeedOperator to create element inverses 2098d1d35e2fSjeremylt @param[out] fdm_inv CeedOperator to apply the action of a FDM based inverse 20993bd813ffSjeremylt for each element 21003bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 21014cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 21023bd813ffSjeremylt 21033bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 21043bd813ffSjeremylt 21057a982d89SJeremy L. Thompson @ref Backend 21063bd813ffSjeremylt **/ 2107d1d35e2fSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdm_inv, 21083bd813ffSjeremylt CeedRequest *request) { 21093bd813ffSjeremylt int ierr; 2110e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 21113bd813ffSjeremylt 2112713f43c3Sjeremylt // Use backend version, if available 2113713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2114d1d35e2fSjeremylt ierr = op->CreateFDMElementInverse(op, fdm_inv, request); CeedChk(ierr); 2115713f43c3Sjeremylt } else { 2116713f43c3Sjeremylt // Fallback to reference Ceed 2117d1d35e2fSjeremylt if (!op->op_fallback) { 2118713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 21193bd813ffSjeremylt } 2120713f43c3Sjeremylt // Assemble 2121d1d35e2fSjeremylt ierr = op->op_fallback->CreateFDMElementInverse(op->op_fallback, fdm_inv, 21223bd813ffSjeremylt request); CeedChk(ierr); 21233bd813ffSjeremylt } 2124e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21253bd813ffSjeremylt } 21263bd813ffSjeremylt 21277a982d89SJeremy L. Thompson /** 21287a982d89SJeremy L. Thompson @brief View a CeedOperator 21297a982d89SJeremy L. Thompson 21307a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 21317a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 21327a982d89SJeremy L. Thompson 21337a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 21347a982d89SJeremy L. Thompson 21357a982d89SJeremy L. Thompson @ref User 21367a982d89SJeremy L. Thompson **/ 21377a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 21387a982d89SJeremy L. Thompson int ierr; 21397a982d89SJeremy L. Thompson 21407a982d89SJeremy L. Thompson if (op->composite) { 21417a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21427a982d89SJeremy L. Thompson 2143d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 21447a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 2145d1d35e2fSjeremylt ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream); 21467a982d89SJeremy L. Thompson CeedChk(ierr); 21477a982d89SJeremy L. Thompson } 21487a982d89SJeremy L. Thompson } else { 21497a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21507a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21517a982d89SJeremy L. Thompson } 2152e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21537a982d89SJeremy L. Thompson } 21543bd813ffSjeremylt 21553bd813ffSjeremylt /** 21563bd813ffSjeremylt @brief Apply CeedOperator to a vector 2157d7b241e6Sjeremylt 2158d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2159d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2160d7b241e6Sjeremylt CeedOperatorSetField(). 2161d7b241e6Sjeremylt 2162d7b241e6Sjeremylt @param op CeedOperator to apply 21634cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 216434138859Sjeremylt there are no active inputs 2165b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21664cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 216734138859Sjeremylt active outputs 2168d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21694cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2170b11c1e72Sjeremylt 2171b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2172dfdf5a53Sjeremylt 21737a982d89SJeremy L. Thompson @ref User 2174b11c1e72Sjeremylt **/ 2175692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2176692c2638Sjeremylt CeedRequest *request) { 2177d7b241e6Sjeremylt int ierr; 2178e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2179d7b241e6Sjeremylt 2180d1d35e2fSjeremylt if (op->num_elem) { 2181250756a7Sjeremylt // Standard Operator 2182cae8b89aSjeremylt if (op->Apply) { 2183250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2184cae8b89aSjeremylt } else { 2185cae8b89aSjeremylt // Zero all output vectors 2186250756a7Sjeremylt CeedQFunction qf = op->qf; 2187d1d35e2fSjeremylt for (CeedInt i=0; i<qf->num_output_fields; i++) { 2188d1d35e2fSjeremylt CeedVector vec = op->output_fields[i]->vec; 2189cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2190cae8b89aSjeremylt vec = out; 2191cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2192cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2193cae8b89aSjeremylt } 2194cae8b89aSjeremylt } 2195250756a7Sjeremylt // Apply 2196250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2197250756a7Sjeremylt } 2198250756a7Sjeremylt } else if (op->composite) { 2199250756a7Sjeremylt // Composite Operator 2200250756a7Sjeremylt if (op->ApplyComposite) { 2201250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2202250756a7Sjeremylt } else { 2203d1d35e2fSjeremylt CeedInt num_suboperators; 2204d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2205d1d35e2fSjeremylt CeedOperator *sub_operators; 2206d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2207250756a7Sjeremylt 2208250756a7Sjeremylt // Zero all output vectors 2209250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2210cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2211cae8b89aSjeremylt } 2212d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2213d1d35e2fSjeremylt for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) { 2214d1d35e2fSjeremylt CeedVector vec = sub_operators[i]->output_fields[j]->vec; 2215250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2216250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2217250756a7Sjeremylt } 2218250756a7Sjeremylt } 2219250756a7Sjeremylt } 2220250756a7Sjeremylt // Apply 2221d1d35e2fSjeremylt for (CeedInt i=0; i<op->num_suboperators; i++) { 2222d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request); 2223cae8b89aSjeremylt CeedChk(ierr); 2224cae8b89aSjeremylt } 2225cae8b89aSjeremylt } 2226250756a7Sjeremylt } 2227e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2228cae8b89aSjeremylt } 2229cae8b89aSjeremylt 2230cae8b89aSjeremylt /** 2231cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2232cae8b89aSjeremylt 2233cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2234cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2235cae8b89aSjeremylt CeedOperatorSetField(). 2236cae8b89aSjeremylt 2237cae8b89aSjeremylt @param op CeedOperator to apply 2238cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2239cae8b89aSjeremylt active inputs 2240cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2241cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2242cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22434cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2244cae8b89aSjeremylt 2245cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2246cae8b89aSjeremylt 22477a982d89SJeremy L. Thompson @ref User 2248cae8b89aSjeremylt **/ 2249cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2250cae8b89aSjeremylt CeedRequest *request) { 2251cae8b89aSjeremylt int ierr; 2252e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2253cae8b89aSjeremylt 2254d1d35e2fSjeremylt if (op->num_elem) { 2255250756a7Sjeremylt // Standard Operator 2256250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2257250756a7Sjeremylt } else if (op->composite) { 2258250756a7Sjeremylt // Composite Operator 2259250756a7Sjeremylt if (op->ApplyAddComposite) { 2260250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2261cae8b89aSjeremylt } else { 2262d1d35e2fSjeremylt CeedInt num_suboperators; 2263d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr); 2264d1d35e2fSjeremylt CeedOperator *sub_operators; 2265d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr); 2266250756a7Sjeremylt 2267d1d35e2fSjeremylt for (CeedInt i=0; i<num_suboperators; i++) { 2268d1d35e2fSjeremylt ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request); 2269cae8b89aSjeremylt CeedChk(ierr); 22701d7d2407SJeremy L Thompson } 2271250756a7Sjeremylt } 2272250756a7Sjeremylt } 2273e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2274d7b241e6Sjeremylt } 2275d7b241e6Sjeremylt 2276d7b241e6Sjeremylt /** 2277b11c1e72Sjeremylt @brief Destroy a CeedOperator 2278d7b241e6Sjeremylt 2279d7b241e6Sjeremylt @param op CeedOperator to destroy 2280b11c1e72Sjeremylt 2281b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2282dfdf5a53Sjeremylt 22837a982d89SJeremy L. Thompson @ref User 2284b11c1e72Sjeremylt **/ 2285d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2286d7b241e6Sjeremylt int ierr; 2287d7b241e6Sjeremylt 2288d1d35e2fSjeremylt if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS; 2289d7b241e6Sjeremylt if ((*op)->Destroy) { 2290d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2291d7b241e6Sjeremylt } 2292fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2293fe2413ffSjeremylt // Free fields 2294d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2295d1d35e2fSjeremylt if ((*op)->input_fields[i]) { 2296d1d35e2fSjeremylt if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) { 2297d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr); 229871352a93Sjeremylt CeedChk(ierr); 229915910d16Sjeremylt } 2300d1d35e2fSjeremylt if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2301d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr); 230271352a93Sjeremylt } 2303d1d35e2fSjeremylt if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE && 2304d1d35e2fSjeremylt (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) { 2305d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr); 230671352a93Sjeremylt } 2307d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr); 2308d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr); 2309fe2413ffSjeremylt } 2310d1d35e2fSjeremylt for (int i=0; i<(*op)->num_fields; i++) 2311d1d35e2fSjeremylt if ((*op)->output_fields[i]) { 2312d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr); 231371352a93Sjeremylt CeedChk(ierr); 2314d1d35e2fSjeremylt if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) { 2315d1d35e2fSjeremylt ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr); 231671352a93Sjeremylt } 2317d1d35e2fSjeremylt if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE && 2318d1d35e2fSjeremylt (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) { 2319d1d35e2fSjeremylt ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr); 232071352a93Sjeremylt } 2321d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr); 2322d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr); 2323fe2413ffSjeremylt } 2324d1d35e2fSjeremylt // Destroy sub_operators 2325d1d35e2fSjeremylt for (int i=0; i<(*op)->num_suboperators; i++) 2326d1d35e2fSjeremylt if ((*op)->sub_operators[i]) { 2327d1d35e2fSjeremylt ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr); 232852d6035fSJeremy L Thompson } 2329e15f9bd0SJeremy L Thompson if ((*op)->qf) 2330e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2331d1d35e2fSjeremylt (*op)->qf->operators_set--; 2332e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2333d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2334e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2335e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2336d1d35e2fSjeremylt (*op)->dqf->operators_set--; 2337e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2338d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2339e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2340e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2341d1d35e2fSjeremylt (*op)->dqfT->operators_set--; 2342e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2343d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2344fe2413ffSjeremylt 23455107b09fSJeremy L Thompson // Destroy fallback 2346d1d35e2fSjeremylt if ((*op)->op_fallback) { 2347d1d35e2fSjeremylt ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr); 2348d1d35e2fSjeremylt ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr); 2349d1d35e2fSjeremylt ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr); 2350d1d35e2fSjeremylt ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr); 23515107b09fSJeremy L Thompson } 23525107b09fSJeremy L Thompson 2353d1d35e2fSjeremylt ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr); 2354d1d35e2fSjeremylt ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr); 2355d1d35e2fSjeremylt ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr); 2356d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2357e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2358d7b241e6Sjeremylt } 2359d7b241e6Sjeremylt 2360d7b241e6Sjeremylt /// @} 2361