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 173d576824SJeremy L Thompson #include <ceed.h> 18d863ab9bSjeremylt #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 487a982d89SJeremy L. Thompson const char *resource, *fallbackresource; 497a982d89SJeremy L. Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 507a982d89SJeremy L. Thompson ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 517a982d89SJeremy L. Thompson CeedChk(ierr); 527a982d89SJeremy L. Thompson if (!strcmp(resource, fallbackresource)) 537a982d89SJeremy L. Thompson // LCOV_EXCL_START 54*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 55*e15f9bd0SJeremy L Thompson "Backend %s cannot create an operator" 567a982d89SJeremy L. Thompson "fallback to resource %s", resource, fallbackresource); 577a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 587a982d89SJeremy L. Thompson 597a982d89SJeremy L. Thompson // Fallback Ceed 607a982d89SJeremy L. Thompson Ceed ceedref; 617a982d89SJeremy L. Thompson if (!op->ceed->opfallbackceed) { 627a982d89SJeremy L. Thompson ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr); 637a982d89SJeremy L. Thompson ceedref->opfallbackparent = op->ceed; 64fc164cf7SWill Pazner ceedref->Error = op->ceed->Error; 657a982d89SJeremy L. Thompson op->ceed->opfallbackceed = ceedref; 667a982d89SJeremy L. Thompson } 677a982d89SJeremy L. Thompson ceedref = op->ceed->opfallbackceed; 687a982d89SJeremy L. Thompson 697a982d89SJeremy L. Thompson // Clone Op 707a982d89SJeremy L. Thompson CeedOperator opref; 717a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &opref); CeedChk(ierr); 72*e15f9bd0SJeremy L Thompson memcpy(opref, op, sizeof(*opref)); 737a982d89SJeremy L. Thompson opref->data = NULL; 74*e15f9bd0SJeremy L Thompson opref->interfacesetup = false; 75*e15f9bd0SJeremy L Thompson opref->backendsetup = false; 767a982d89SJeremy L. Thompson opref->ceed = ceedref; 777a982d89SJeremy L. Thompson ierr = ceedref->OperatorCreate(opref); CeedChk(ierr); 787a982d89SJeremy L. Thompson op->opfallback = opref; 797a982d89SJeremy L. Thompson 807a982d89SJeremy L. Thompson // Clone QF 817a982d89SJeremy L. Thompson CeedQFunction qfref; 827a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &qfref); CeedChk(ierr); 83*e15f9bd0SJeremy L Thompson memcpy(qfref, (op->qf), sizeof(*qfref)); 847a982d89SJeremy L. Thompson qfref->data = NULL; 857a982d89SJeremy L. Thompson qfref->ceed = ceedref; 867a982d89SJeremy L. Thompson ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr); 877a982d89SJeremy L. Thompson opref->qf = qfref; 887a982d89SJeremy L. Thompson op->qffallback = qfref; 89*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 90*e15f9bd0SJeremy L Thompson } 917a982d89SJeremy L. Thompson 92*e15f9bd0SJeremy L Thompson /** 93*e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 94*e15f9bd0SJeremy L Thompson 95*e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 96*e15f9bd0SJeremy L Thompson @param[in] qfield QFunction Field matching Operator Field 97*e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 98*e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 99*e15f9bd0SJeremy L Thompson 100*e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 101*e15f9bd0SJeremy L Thompson 102*e15f9bd0SJeremy L Thompson @ref Developer 103*e15f9bd0SJeremy L Thompson **/ 104*e15f9bd0SJeremy L Thompson static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qfield, 105*e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 106*e15f9bd0SJeremy L Thompson int ierr; 107*e15f9bd0SJeremy L Thompson CeedEvalMode emode = qfield->emode; 108*e15f9bd0SJeremy L Thompson CeedInt dim = 1, ncomp = 1, restr_ncomp = 1, size = qfield->size; 109*e15f9bd0SJeremy L Thompson // Restriction 110*e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 111*e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetNumComponents(r, &restr_ncomp); 112*e15f9bd0SJeremy L Thompson } else if (emode != CEED_EVAL_WEIGHT) { 113*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 114*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 115*e15f9bd0SJeremy L Thompson "CEED_ELEMRESTRICTION_NONE can only be used " 116*e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 117*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 118*e15f9bd0SJeremy L Thompson } 119*e15f9bd0SJeremy L Thompson // Basis 120*e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 121*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 122*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumComponents(b, &ncomp); CeedChk(ierr); 123*e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE && restr_ncomp != ncomp) { 124*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 125*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 126*e15f9bd0SJeremy L Thompson "ElemRestriction and Basis have incompatible numbers of components"); 127*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 128*e15f9bd0SJeremy L Thompson } 129*e15f9bd0SJeremy L Thompson } 130*e15f9bd0SJeremy L Thompson // Field size 131*e15f9bd0SJeremy L Thompson switch(emode) { 132*e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 133*e15f9bd0SJeremy L Thompson if (size != restr_ncomp) 134*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 135*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 136*e15f9bd0SJeremy L Thompson "Incompatible QFunction field size and Operator field " 137*e15f9bd0SJeremy L Thompson "ElemRestriction number of components"); 138*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 139*e15f9bd0SJeremy L Thompson break; 140*e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 141*e15f9bd0SJeremy L Thompson if (size != ncomp) 142*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 143*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 144*e15f9bd0SJeremy L Thompson "Incompatible QFunction field size and Operator field " 145*e15f9bd0SJeremy L Thompson "Basis number of components"); 146*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 147*e15f9bd0SJeremy L Thompson break; 148*e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 149*e15f9bd0SJeremy L Thompson if (size != ncomp * dim) 150*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 151*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 152*e15f9bd0SJeremy L Thompson "Incompatible QFunction field size and Operator field " 153*e15f9bd0SJeremy L Thompson "Basis dimension and number of components"); 154*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 155*e15f9bd0SJeremy L Thompson break; 156*e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 157*e15f9bd0SJeremy L Thompson // No addional checks required 158*e15f9bd0SJeremy L Thompson break; 159*e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 160*e15f9bd0SJeremy L Thompson // Not implemented 161*e15f9bd0SJeremy L Thompson break; 162*e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 163*e15f9bd0SJeremy L Thompson // Not implemented 164*e15f9bd0SJeremy L Thompson break; 165*e15f9bd0SJeremy L Thompson } 166*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1677a982d89SJeremy L. Thompson } 1687a982d89SJeremy L. Thompson 1697a982d89SJeremy L. Thompson /** 1707a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 1717a982d89SJeremy L. Thompson 1727a982d89SJeremy L. Thompson @param[in] ceed Ceed object for error handling 1737a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 1747a982d89SJeremy L. Thompson 1757a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1767a982d89SJeremy L. Thompson 1777a982d89SJeremy L. Thompson @ref Developer 1787a982d89SJeremy L. Thompson **/ 1797a982d89SJeremy L. Thompson static int CeedOperatorCheckReady(Ceed ceed, CeedOperator op) { 180*e15f9bd0SJeremy L Thompson if (op->interfacesetup) 181*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1827a982d89SJeremy L. Thompson 183*e15f9bd0SJeremy L Thompson CeedQFunction qf = op->qf; 1847a982d89SJeremy L. Thompson if (op->composite) { 1857a982d89SJeremy L. Thompson if (!op->numsub) 1867a982d89SJeremy L. Thompson // LCOV_EXCL_START 187*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No suboperators set"); 1887a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1897a982d89SJeremy L. Thompson } else { 1907a982d89SJeremy L. Thompson if (op->nfields == 0) 1917a982d89SJeremy L. Thompson // LCOV_EXCL_START 192*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 1937a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1947a982d89SJeremy L. Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 1957a982d89SJeremy L. Thompson // LCOV_EXCL_START 196*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 1977a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1987a982d89SJeremy L. Thompson if (!op->hasrestriction) 1997a982d89SJeremy L. Thompson // LCOV_EXCL_START 200*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 201*e15f9bd0SJeremy L Thompson "At least one restriction required"); 2027a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2037a982d89SJeremy L. Thompson if (op->numqpoints == 0) 2047a982d89SJeremy L. Thompson // LCOV_EXCL_START 205*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 206*e15f9bd0SJeremy L Thompson "At least one non-collocated basis required"); 2077a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2087a982d89SJeremy L. Thompson } 2097a982d89SJeremy L. Thompson 210*e15f9bd0SJeremy L Thompson // Flag as immutable and ready 211*e15f9bd0SJeremy L Thompson op->interfacesetup = true; 212*e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 213*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 214*e15f9bd0SJeremy L Thompson op->qf->operatorsset++; 215*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 216*e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 217*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 218*e15f9bd0SJeremy L Thompson op->dqf->operatorsset++; 219*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 220*e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 221*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 222*e15f9bd0SJeremy L Thompson op->dqfT->operatorsset++; 223*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 224*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2257a982d89SJeremy L. Thompson } 2267a982d89SJeremy L. Thompson 2277a982d89SJeremy L. Thompson /** 2287a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2297a982d89SJeremy L. Thompson 2307a982d89SJeremy L. Thompson @param[in] field Operator field to view 2314c4400c7SValeria Barra @param[in] qffield QFunction field (carries field name) 2327a982d89SJeremy L. Thompson @param[in] fieldnumber Number of field being viewed 2334c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 2344c4400c7SValeria Barra @param[in] in true for an input field; false for output field 2357a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2367a982d89SJeremy L. Thompson 2377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2387a982d89SJeremy L. Thompson 2397a982d89SJeremy L. Thompson @ref Utility 2407a982d89SJeremy L. Thompson **/ 2417a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 2427a982d89SJeremy L. Thompson CeedQFunctionField qffield, 2437a982d89SJeremy L. Thompson CeedInt fieldnumber, bool sub, bool in, 2447a982d89SJeremy L. Thompson FILE *stream) { 2457a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 2467a982d89SJeremy L. Thompson const char *inout = in ? "Input" : "Output"; 2477a982d89SJeremy L. Thompson 2487a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2497a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 2507a982d89SJeremy L. Thompson pre, inout, fieldnumber, pre, qffield->fieldname); 2517a982d89SJeremy L. Thompson 2527a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2537a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2547a982d89SJeremy L. Thompson 2557a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2567a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2577a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2587a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 259*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2607a982d89SJeremy L. Thompson } 2617a982d89SJeremy L. Thompson 2627a982d89SJeremy L. Thompson /** 2637a982d89SJeremy L. Thompson @brief View a single CeedOperator 2647a982d89SJeremy L. Thompson 2657a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2667a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2677a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2687a982d89SJeremy L. Thompson 2697a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2707a982d89SJeremy L. Thompson 2717a982d89SJeremy L. Thompson @ref Utility 2727a982d89SJeremy L. Thompson **/ 2737a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 2747a982d89SJeremy L. Thompson int ierr; 2757a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 2767a982d89SJeremy L. Thompson 2777a982d89SJeremy L. Thompson CeedInt totalfields; 2787a982d89SJeremy L. Thompson ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 2797a982d89SJeremy L. Thompson 2807a982d89SJeremy L. Thompson fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 2817a982d89SJeremy L. Thompson 2827a982d89SJeremy L. Thompson fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 2837a982d89SJeremy L. Thompson op->qf->numinputfields>1 ? "s" : ""); 2847a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numinputfields; i++) { 2857a982d89SJeremy L. Thompson ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 2867a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 2877a982d89SJeremy L. Thompson } 2887a982d89SJeremy L. Thompson 2897a982d89SJeremy L. Thompson fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 2907a982d89SJeremy L. Thompson op->qf->numoutputfields>1 ? "s" : ""); 2917a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 292829936eeSWill Pazner ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->outputfields[i], 2937a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 2947a982d89SJeremy L. Thompson } 295*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2967a982d89SJeremy L. Thompson } 2977a982d89SJeremy L. Thompson 298d99fa3c5SJeremy L Thompson /** 299d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 300d99fa3c5SJeremy L Thompson 301d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 302d99fa3c5SJeremy L Thompson @param[out] activeBasis Basis for active input vector 303d99fa3c5SJeremy L Thompson 304d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 305d99fa3c5SJeremy L Thompson 306d99fa3c5SJeremy L Thompson @ ref Developer 307d99fa3c5SJeremy L Thompson **/ 308d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 309d99fa3c5SJeremy L Thompson CeedBasis *activeBasis) { 310d99fa3c5SJeremy L Thompson *activeBasis = NULL; 311d99fa3c5SJeremy L Thompson for (int i = 0; i < op->qf->numinputfields; i++) 312d99fa3c5SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 313d99fa3c5SJeremy L Thompson *activeBasis = op->inputfields[i]->basis; 314d99fa3c5SJeremy L Thompson break; 315d99fa3c5SJeremy L Thompson } 316d99fa3c5SJeremy L Thompson 317d99fa3c5SJeremy L Thompson if (!*activeBasis) { 318d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 319d99fa3c5SJeremy L Thompson int ierr; 320d99fa3c5SJeremy L Thompson Ceed ceed; 321d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 322*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 323d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 324d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 325d99fa3c5SJeremy L Thompson } 326*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 327d99fa3c5SJeremy L Thompson } 328d99fa3c5SJeremy L Thompson 329d99fa3c5SJeremy L Thompson 330d99fa3c5SJeremy L Thompson /** 331d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 332d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 333d99fa3c5SJeremy L Thompson 334d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 335d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 336d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 337d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 338d99fa3c5SJeremy L Thompson @param[in] basisCtoF Basis for coarse to fine interpolation 339d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 340d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 341d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 342d99fa3c5SJeremy L Thompson 343d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 344d99fa3c5SJeremy L Thompson 345d99fa3c5SJeremy L Thompson @ref Developer 346d99fa3c5SJeremy L Thompson **/ 347d99fa3c5SJeremy L Thompson static int CeedOperatorMultigridLevel_Core(CeedOperator opFine, 348d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 349d99fa3c5SJeremy L Thompson CeedBasis basisCtoF, CeedOperator *opCoarse, CeedOperator *opProlong, 350d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 351d99fa3c5SJeremy L Thompson int ierr; 352d99fa3c5SJeremy L Thompson Ceed ceed; 353d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 354d99fa3c5SJeremy L Thompson 355d99fa3c5SJeremy L Thompson // Check for composite operator 356d99fa3c5SJeremy L Thompson bool isComposite; 357d99fa3c5SJeremy L Thompson ierr = CeedOperatorIsComposite(opFine, &isComposite); CeedChk(ierr); 358d99fa3c5SJeremy L Thompson if (isComposite) 359d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 360*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 361d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 362d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 363d99fa3c5SJeremy L Thompson 364d99fa3c5SJeremy L Thompson // Coarse Grid 365d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, opFine->qf, opFine->dqf, opFine->dqfT, 366d99fa3c5SJeremy L Thompson opCoarse); CeedChk(ierr); 367d99fa3c5SJeremy L Thompson CeedElemRestriction rstrFine = NULL; 368d99fa3c5SJeremy L Thompson // -- Clone input fields 369d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numinputfields; i++) { 370d99fa3c5SJeremy L Thompson if (opFine->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 371d99fa3c5SJeremy L Thompson rstrFine = opFine->inputfields[i]->Erestrict; 372d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 373d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 374d99fa3c5SJeremy L Thompson CeedChk(ierr); 375d99fa3c5SJeremy L Thompson } else { 376d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 377d99fa3c5SJeremy L Thompson opFine->inputfields[i]->Erestrict, 378d99fa3c5SJeremy L Thompson opFine->inputfields[i]->basis, 379d99fa3c5SJeremy L Thompson opFine->inputfields[i]->vec); CeedChk(ierr); 380d99fa3c5SJeremy L Thompson } 381d99fa3c5SJeremy L Thompson } 382d99fa3c5SJeremy L Thompson // -- Clone output fields 383d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numoutputfields; i++) { 384d99fa3c5SJeremy L Thompson if (opFine->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 385d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 386d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 387d99fa3c5SJeremy L Thompson CeedChk(ierr); 388d99fa3c5SJeremy L Thompson } else { 389d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 390d99fa3c5SJeremy L Thompson opFine->outputfields[i]->Erestrict, 391d99fa3c5SJeremy L Thompson opFine->outputfields[i]->basis, 392d99fa3c5SJeremy L Thompson opFine->outputfields[i]->vec); CeedChk(ierr); 393d99fa3c5SJeremy L Thompson } 394d99fa3c5SJeremy L Thompson } 395d99fa3c5SJeremy L Thompson 396d99fa3c5SJeremy L Thompson // Multiplicity vector 397d99fa3c5SJeremy L Thompson CeedVector multVec, multE; 398d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrFine, &multVec, &multE); 399d99fa3c5SJeremy L Thompson CeedChk(ierr); 400d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multE, 0.0); CeedChk(ierr); 401d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_NOTRANSPOSE, PMultFine, multE, 402d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 403d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multVec, 0.0); CeedChk(ierr); 404d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_TRANSPOSE, multE, multVec, 405d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 406d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multE); CeedChk(ierr); 407d99fa3c5SJeremy L Thompson ierr = CeedVectorReciprocal(multVec); CeedChk(ierr); 408d99fa3c5SJeremy L Thompson 409d99fa3c5SJeremy L Thompson // Restriction 410d99fa3c5SJeremy L Thompson CeedInt ncomp; 411d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisCoarse, &ncomp); CeedChk(ierr); 412d99fa3c5SJeremy L Thompson CeedQFunction qfRestrict; 413d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfRestrict); 414d99fa3c5SJeremy L Thompson CeedChk(ierr); 415777ff853SJeremy L Thompson CeedInt *ncompRData; 416777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompRData); CeedChk(ierr); 417777ff853SJeremy L Thompson ncompRData[0] = ncomp; 418777ff853SJeremy L Thompson CeedQFunctionContext ctxR; 419777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxR); CeedChk(ierr); 420777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxR, CEED_MEM_HOST, CEED_OWN_POINTER, 421777ff853SJeremy L Thompson sizeof(*ncompRData), ncompRData); 422777ff853SJeremy L Thompson CeedChk(ierr); 423777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfRestrict, ctxR); CeedChk(ierr); 424777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxR); CeedChk(ierr); 425d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "input", ncomp, CEED_EVAL_NONE); 426d99fa3c5SJeremy L Thompson CeedChk(ierr); 427d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "scale", ncomp, CEED_EVAL_NONE); 428d99fa3c5SJeremy L Thompson CeedChk(ierr); 429d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfRestrict, "output", ncomp, CEED_EVAL_INTERP); 430d99fa3c5SJeremy L Thompson CeedChk(ierr); 431d99fa3c5SJeremy L Thompson 432d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfRestrict, CEED_QFUNCTION_NONE, 433d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opRestrict); 434d99fa3c5SJeremy L Thompson CeedChk(ierr); 435d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "input", rstrFine, 436d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 437d99fa3c5SJeremy L Thompson CeedChk(ierr); 438d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "scale", rstrFine, 439d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 440d99fa3c5SJeremy L Thompson CeedChk(ierr); 441d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "output", rstrCoarse, basisCtoF, 442d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 443d99fa3c5SJeremy L Thompson 444d99fa3c5SJeremy L Thompson // Prolongation 445d99fa3c5SJeremy L Thompson CeedQFunction qfProlong; 446d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfProlong); 447d99fa3c5SJeremy L Thompson CeedChk(ierr); 448777ff853SJeremy L Thompson CeedInt *ncompPData; 449777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompPData); CeedChk(ierr); 450777ff853SJeremy L Thompson ncompPData[0] = ncomp; 451777ff853SJeremy L Thompson CeedQFunctionContext ctxP; 452777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxP); CeedChk(ierr); 453777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxP, CEED_MEM_HOST, CEED_OWN_POINTER, 454777ff853SJeremy L Thompson sizeof(*ncompPData), ncompPData); 455777ff853SJeremy L Thompson CeedChk(ierr); 456777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfProlong, ctxP); CeedChk(ierr); 457777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxP); CeedChk(ierr); 458d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "input", ncomp, CEED_EVAL_INTERP); 459d99fa3c5SJeremy L Thompson CeedChk(ierr); 460d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "scale", ncomp, CEED_EVAL_NONE); 461d99fa3c5SJeremy L Thompson CeedChk(ierr); 462d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfProlong, "output", ncomp, CEED_EVAL_NONE); 463d99fa3c5SJeremy L Thompson CeedChk(ierr); 464d99fa3c5SJeremy L Thompson 465d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfProlong, CEED_QFUNCTION_NONE, 466d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opProlong); 467d99fa3c5SJeremy L Thompson CeedChk(ierr); 468d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "input", rstrCoarse, basisCtoF, 469d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 470d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "scale", rstrFine, 471d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 472d99fa3c5SJeremy L Thompson CeedChk(ierr); 473d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "output", rstrFine, 474d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 475d99fa3c5SJeremy L Thompson CeedChk(ierr); 476d99fa3c5SJeremy L Thompson 477d99fa3c5SJeremy L Thompson // Cleanup 478d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multVec); CeedChk(ierr); 479d99fa3c5SJeremy L Thompson ierr = CeedBasisDestroy(&basisCtoF); CeedChk(ierr); 480d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfRestrict); CeedChk(ierr); 481d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfProlong); CeedChk(ierr); 482*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 483d99fa3c5SJeremy L Thompson } 484d99fa3c5SJeremy L Thompson 4857a982d89SJeremy L. Thompson /// @} 4867a982d89SJeremy L. Thompson 4877a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 4887a982d89SJeremy L. Thompson /// CeedOperator Backend API 4897a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 4907a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 4917a982d89SJeremy L. Thompson /// @{ 4927a982d89SJeremy L. Thompson 4937a982d89SJeremy L. Thompson /** 4947a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 4957a982d89SJeremy L. Thompson 4967a982d89SJeremy L. Thompson @param op CeedOperator 4977a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 4987a982d89SJeremy L. Thompson 4997a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5007a982d89SJeremy L. Thompson 5017a982d89SJeremy L. Thompson @ref Backend 5027a982d89SJeremy L. Thompson **/ 5037a982d89SJeremy L. Thompson 5047a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5057a982d89SJeremy L. Thompson *ceed = op->ceed; 506*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5077a982d89SJeremy L. Thompson } 5087a982d89SJeremy L. Thompson 5097a982d89SJeremy L. Thompson /** 5107a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5117a982d89SJeremy L. Thompson 5127a982d89SJeremy L. Thompson @param op CeedOperator 5137a982d89SJeremy L. Thompson @param[out] numelem Variable to store number of elements 5147a982d89SJeremy L. Thompson 5157a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5167a982d89SJeremy L. Thompson 5177a982d89SJeremy L. Thompson @ref Backend 5187a982d89SJeremy L. Thompson **/ 5197a982d89SJeremy L. Thompson 5207a982d89SJeremy L. Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 5217a982d89SJeremy L. Thompson if (op->composite) 5227a982d89SJeremy L. Thompson // LCOV_EXCL_START 523*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 524*e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5257a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5267a982d89SJeremy L. Thompson 5277a982d89SJeremy L. Thompson *numelem = op->numelements; 528*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5297a982d89SJeremy L. Thompson } 5307a982d89SJeremy L. Thompson 5317a982d89SJeremy L. Thompson /** 5327a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5337a982d89SJeremy L. Thompson 5347a982d89SJeremy L. Thompson @param op CeedOperator 5357a982d89SJeremy L. Thompson @param[out] numqpts Variable to store vector number of quadrature points 5367a982d89SJeremy L. Thompson 5377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5387a982d89SJeremy L. Thompson 5397a982d89SJeremy L. Thompson @ref Backend 5407a982d89SJeremy L. Thompson **/ 5417a982d89SJeremy L. Thompson 5427a982d89SJeremy L. Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 5437a982d89SJeremy L. Thompson if (op->composite) 5447a982d89SJeremy L. Thompson // LCOV_EXCL_START 545*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 546*e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5477a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5487a982d89SJeremy L. Thompson 5497a982d89SJeremy L. Thompson *numqpts = op->numqpoints; 550*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5517a982d89SJeremy L. Thompson } 5527a982d89SJeremy L. Thompson 5537a982d89SJeremy L. Thompson /** 5547a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 5557a982d89SJeremy L. Thompson 5567a982d89SJeremy L. Thompson @param op CeedOperator 5577a982d89SJeremy L. Thompson @param[out] numargs Variable to store vector number of arguments 5587a982d89SJeremy L. Thompson 5597a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5607a982d89SJeremy L. Thompson 5617a982d89SJeremy L. Thompson @ref Backend 5627a982d89SJeremy L. Thompson **/ 5637a982d89SJeremy L. Thompson 5647a982d89SJeremy L. Thompson int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 5657a982d89SJeremy L. Thompson if (op->composite) 5667a982d89SJeremy L. Thompson // LCOV_EXCL_START 567*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 568*e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 5697a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5707a982d89SJeremy L. Thompson 5717a982d89SJeremy L. Thompson *numargs = op->nfields; 572*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5737a982d89SJeremy L. Thompson } 5747a982d89SJeremy L. Thompson 5757a982d89SJeremy L. Thompson /** 5767a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 5777a982d89SJeremy L. Thompson 5787a982d89SJeremy L. Thompson @param op CeedOperator 579fd364f38SJeremy L Thompson @param[out] issetupdone Variable to store setup status 5807a982d89SJeremy L. Thompson 5817a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5827a982d89SJeremy L. Thompson 5837a982d89SJeremy L. Thompson @ref Backend 5847a982d89SJeremy L. Thompson **/ 5857a982d89SJeremy L. Thompson 586fd364f38SJeremy L Thompson int CeedOperatorIsSetupDone(CeedOperator op, bool *issetupdone) { 587*e15f9bd0SJeremy L Thompson *issetupdone = op->backendsetup; 588*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5897a982d89SJeremy L. Thompson } 5907a982d89SJeremy L. Thompson 5917a982d89SJeremy L. Thompson /** 5927a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 5937a982d89SJeremy L. Thompson 5947a982d89SJeremy L. Thompson @param op CeedOperator 5957a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 5967a982d89SJeremy L. Thompson 5977a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5987a982d89SJeremy L. Thompson 5997a982d89SJeremy L. Thompson @ref Backend 6007a982d89SJeremy L. Thompson **/ 6017a982d89SJeremy L. Thompson 6027a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6037a982d89SJeremy L. Thompson if (op->composite) 6047a982d89SJeremy L. Thompson // LCOV_EXCL_START 605*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 606*e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6077a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson *qf = op->qf; 610*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6117a982d89SJeremy L. Thompson } 6127a982d89SJeremy L. Thompson 6137a982d89SJeremy L. Thompson /** 614c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 615c04a41a7SJeremy L Thompson 616c04a41a7SJeremy L Thompson @param op CeedOperator 617fd364f38SJeremy L Thompson @param[out] iscomposite Variable to store composite status 618c04a41a7SJeremy L Thompson 619c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 620c04a41a7SJeremy L Thompson 621c04a41a7SJeremy L Thompson @ref Backend 622c04a41a7SJeremy L Thompson **/ 623c04a41a7SJeremy L Thompson 624fd364f38SJeremy L Thompson int CeedOperatorIsComposite(CeedOperator op, bool *iscomposite) { 625fd364f38SJeremy L Thompson *iscomposite = op->composite; 626*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 627c04a41a7SJeremy L Thompson } 628c04a41a7SJeremy L Thompson 629c04a41a7SJeremy L Thompson /** 6307a982d89SJeremy L. Thompson @brief Get the number of suboperators associated with a CeedOperator 6317a982d89SJeremy L. Thompson 6327a982d89SJeremy L. Thompson @param op CeedOperator 6337a982d89SJeremy L. Thompson @param[out] numsub Variable to store number of suboperators 6347a982d89SJeremy L. Thompson 6357a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6367a982d89SJeremy L. Thompson 6377a982d89SJeremy L. Thompson @ref Backend 6387a982d89SJeremy L. Thompson **/ 6397a982d89SJeremy L. Thompson 6407a982d89SJeremy L. Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 6417a982d89SJeremy L. Thompson if (!op->composite) 6427a982d89SJeremy L. Thompson // LCOV_EXCL_START 643*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6447a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6457a982d89SJeremy L. Thompson 6467a982d89SJeremy L. Thompson *numsub = op->numsub; 647*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6487a982d89SJeremy L. Thompson } 6497a982d89SJeremy L. Thompson 6507a982d89SJeremy L. Thompson /** 6517a982d89SJeremy L. Thompson @brief Get the list of suboperators associated with a CeedOperator 6527a982d89SJeremy L. Thompson 6537a982d89SJeremy L. Thompson @param op CeedOperator 6547a982d89SJeremy L. Thompson @param[out] suboperators Variable to store list of suboperators 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6577a982d89SJeremy L. Thompson 6587a982d89SJeremy L. Thompson @ref Backend 6597a982d89SJeremy L. Thompson **/ 6607a982d89SJeremy L. Thompson 6617a982d89SJeremy L. Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 6627a982d89SJeremy L. Thompson if (!op->composite) 6637a982d89SJeremy L. Thompson // LCOV_EXCL_START 664*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6657a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6667a982d89SJeremy L. Thompson 6677a982d89SJeremy L. Thompson *suboperators = op->suboperators; 668*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6697a982d89SJeremy L. Thompson } 6707a982d89SJeremy L. Thompson 6717a982d89SJeremy L. Thompson /** 6727a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 6737a982d89SJeremy L. Thompson 6747a982d89SJeremy L. Thompson @param op CeedOperator 6757a982d89SJeremy L. Thompson @param[out] data Variable to store data 6767a982d89SJeremy L. Thompson 6777a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6787a982d89SJeremy L. Thompson 6797a982d89SJeremy L. Thompson @ref Backend 6807a982d89SJeremy L. Thompson **/ 6817a982d89SJeremy L. Thompson 682777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 683777ff853SJeremy L Thompson *(void **)data = op->data; 684*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6857a982d89SJeremy L. Thompson } 6867a982d89SJeremy L. Thompson 6877a982d89SJeremy L. Thompson /** 6887a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 6897a982d89SJeremy L. Thompson 6907a982d89SJeremy L. Thompson @param[out] op CeedOperator 6917a982d89SJeremy L. Thompson @param data Data to set 6927a982d89SJeremy L. Thompson 6937a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6947a982d89SJeremy L. Thompson 6957a982d89SJeremy L. Thompson @ref Backend 6967a982d89SJeremy L. Thompson **/ 6977a982d89SJeremy L. Thompson 698777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 699777ff853SJeremy L Thompson op->data = data; 700*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7017a982d89SJeremy L. Thompson } 7027a982d89SJeremy L. Thompson 7037a982d89SJeremy L. Thompson /** 7047a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7057a982d89SJeremy L. Thompson 7067a982d89SJeremy L. Thompson @param op CeedOperator 7077a982d89SJeremy L. Thompson 7087a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7097a982d89SJeremy L. Thompson 7107a982d89SJeremy L. Thompson @ref Backend 7117a982d89SJeremy L. Thompson **/ 7127a982d89SJeremy L. Thompson 7137a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 714*e15f9bd0SJeremy L Thompson op->backendsetup = true; 715*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7167a982d89SJeremy L. Thompson } 7177a982d89SJeremy L. Thompson 7187a982d89SJeremy L. Thompson /** 7197a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7207a982d89SJeremy L. Thompson 7217a982d89SJeremy L. Thompson @param op CeedOperator 7227a982d89SJeremy L. Thompson @param[out] inputfields Variable to store inputfields 7237a982d89SJeremy L. Thompson @param[out] outputfields Variable to store outputfields 7247a982d89SJeremy L. Thompson 7257a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7267a982d89SJeremy L. Thompson 7277a982d89SJeremy L. Thompson @ref Backend 7287a982d89SJeremy L. Thompson **/ 7297a982d89SJeremy L. Thompson 7307a982d89SJeremy L. Thompson int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 7317a982d89SJeremy L. Thompson CeedOperatorField **outputfields) { 7327a982d89SJeremy L. Thompson if (op->composite) 7337a982d89SJeremy L. Thompson // LCOV_EXCL_START 734*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 735*e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 7367a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7377a982d89SJeremy L. Thompson 7387a982d89SJeremy L. Thompson if (inputfields) *inputfields = op->inputfields; 7397a982d89SJeremy L. Thompson if (outputfields) *outputfields = op->outputfields; 740*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7417a982d89SJeremy L. Thompson } 7427a982d89SJeremy L. Thompson 7437a982d89SJeremy L. Thompson /** 7447a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 7457a982d89SJeremy L. Thompson 7467a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7477a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 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 7547a982d89SJeremy L. Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 7557a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 7567a982d89SJeremy L. Thompson *rstr = opfield->Erestrict; 757*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7587a982d89SJeremy L. Thompson } 7597a982d89SJeremy L. Thompson 7607a982d89SJeremy L. Thompson /** 7617a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 7627a982d89SJeremy L. Thompson 7637a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7647a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 7657a982d89SJeremy L. Thompson 7667a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7677a982d89SJeremy L. Thompson 7687a982d89SJeremy L. Thompson @ref Backend 7697a982d89SJeremy L. Thompson **/ 7707a982d89SJeremy L. Thompson 7717a982d89SJeremy L. Thompson int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 7727a982d89SJeremy L. Thompson *basis = opfield->basis; 773*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7747a982d89SJeremy L. Thompson } 7757a982d89SJeremy L. Thompson 7767a982d89SJeremy L. Thompson /** 7777a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 7787a982d89SJeremy L. Thompson 7797a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7807a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 7817a982d89SJeremy L. Thompson 7827a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7837a982d89SJeremy L. Thompson 7847a982d89SJeremy L. Thompson @ref Backend 7857a982d89SJeremy L. Thompson **/ 7867a982d89SJeremy L. Thompson 7877a982d89SJeremy L. Thompson int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 7887a982d89SJeremy L. Thompson *vec = opfield->vec; 789*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7907a982d89SJeremy L. Thompson } 7917a982d89SJeremy L. Thompson 7927a982d89SJeremy L. Thompson /// @} 7937a982d89SJeremy L. Thompson 7947a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 7957a982d89SJeremy L. Thompson /// CeedOperator Public API 7967a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 7977a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 798dfdf5a53Sjeremylt /// @{ 799d7b241e6Sjeremylt 800d7b241e6Sjeremylt /** 8010219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8020219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8030219ea01SJeremy L Thompson \ref CeedOperatorSetField. 804d7b241e6Sjeremylt 805b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 806d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 80734138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8084cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 809d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8104cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 811b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 812b11c1e72Sjeremylt CeedOperator will be stored 813b11c1e72Sjeremylt 814b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 815dfdf5a53Sjeremylt 8167a982d89SJeremy L. Thompson @ref User 817d7b241e6Sjeremylt */ 818d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 819d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 820d7b241e6Sjeremylt int ierr; 821d7b241e6Sjeremylt 8225fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8235fe0d4faSjeremylt Ceed delegate; 824aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8255fe0d4faSjeremylt 8265fe0d4faSjeremylt if (!delegate) 827c042f62fSJeremy L Thompson // LCOV_EXCL_START 828*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 829*e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 830c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8315fe0d4faSjeremylt 8325fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 833*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8345fe0d4faSjeremylt } 8355fe0d4faSjeremylt 836b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 837b3b7035fSJeremy L Thompson // LCOV_EXCL_START 838*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 839*e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 840b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 841d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 842d7b241e6Sjeremylt (*op)->ceed = ceed; 843d7b241e6Sjeremylt ceed->refcount++; 844d7b241e6Sjeremylt (*op)->refcount = 1; 845d7b241e6Sjeremylt (*op)->qf = qf; 846d7b241e6Sjeremylt qf->refcount++; 847442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 848d7b241e6Sjeremylt (*op)->dqf = dqf; 849442e7f0bSjeremylt dqf->refcount++; 850442e7f0bSjeremylt } 851442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 852d7b241e6Sjeremylt (*op)->dqfT = dqfT; 853442e7f0bSjeremylt dqfT->refcount++; 854442e7f0bSjeremylt } 855fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 856fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 857d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 858*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 859d7b241e6Sjeremylt } 860d7b241e6Sjeremylt 861d7b241e6Sjeremylt /** 86252d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 86352d6035fSJeremy L Thompson 86452d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 86552d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 86652d6035fSJeremy L Thompson Composite CeedOperator will be stored 86752d6035fSJeremy L Thompson 86852d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 86952d6035fSJeremy L Thompson 8707a982d89SJeremy L. Thompson @ref User 87152d6035fSJeremy L Thompson */ 87252d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 87352d6035fSJeremy L Thompson int ierr; 87452d6035fSJeremy L Thompson 87552d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 87652d6035fSJeremy L Thompson Ceed delegate; 877aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 87852d6035fSJeremy L Thompson 879250756a7Sjeremylt if (delegate) { 88052d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 881*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 88252d6035fSJeremy L Thompson } 883250756a7Sjeremylt } 88452d6035fSJeremy L Thompson 88552d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 88652d6035fSJeremy L Thompson (*op)->ceed = ceed; 88752d6035fSJeremy L Thompson ceed->refcount++; 88852d6035fSJeremy L Thompson (*op)->composite = true; 88952d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 890250756a7Sjeremylt 891250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 89252d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 893250756a7Sjeremylt } 894*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 89552d6035fSJeremy L Thompson } 89652d6035fSJeremy L Thompson 89752d6035fSJeremy L Thompson /** 898b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 899d7b241e6Sjeremylt 900d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 901d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 902d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 903d7b241e6Sjeremylt 904d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 905d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 906d7b241e6Sjeremylt input and at most one active output. 907d7b241e6Sjeremylt 9088c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 9098795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 9108795c945Sjeremylt CeedQFunction) 911b11c1e72Sjeremylt @param r CeedElemRestriction 9124cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 913b11c1e72Sjeremylt if collocated with quadrature points 9144cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9154cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9164cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 917b11c1e72Sjeremylt 918b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 919dfdf5a53Sjeremylt 9207a982d89SJeremy L. Thompson @ref User 921b11c1e72Sjeremylt **/ 922d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 923a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 924d7b241e6Sjeremylt int ierr; 92552d6035fSJeremy L Thompson if (op->composite) 926c042f62fSJeremy L Thompson // LCOV_EXCL_START 927*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 928*e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 929c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9308b067b84SJed Brown if (!r) 931c042f62fSJeremy L Thompson // LCOV_EXCL_START 932*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 933c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 934c042f62fSJeremy L Thompson fieldname); 935c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9368b067b84SJed Brown if (!b) 937c042f62fSJeremy L Thompson // LCOV_EXCL_START 938*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 939*e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 940c042f62fSJeremy L Thompson fieldname); 941c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9428b067b84SJed Brown if (!v) 943c042f62fSJeremy L Thompson // LCOV_EXCL_START 944*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 945*e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 946c042f62fSJeremy L Thompson fieldname); 947c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 94852d6035fSJeremy L Thompson 949d7b241e6Sjeremylt CeedInt numelements; 950d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 95115910d16Sjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->hasrestriction && 95215910d16Sjeremylt op->numelements != numelements) 953c042f62fSJeremy L Thompson // LCOV_EXCL_START 954*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 9551d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 9561d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 957c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 958d7b241e6Sjeremylt 959d7b241e6Sjeremylt CeedInt numqpoints; 960*e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 961d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 962d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 963c042f62fSJeremy L Thompson // LCOV_EXCL_START 964*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 965*e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 9661d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 9671d102b48SJeremy L Thompson op->numqpoints); 968c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 969d7b241e6Sjeremylt } 97015910d16Sjeremylt CeedQFunctionField qfield; 971d1bcdac9Sjeremylt CeedOperatorField *ofield; 972d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 973fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 97415910d16Sjeremylt qfield = op->qf->inputfields[i]; 975d7b241e6Sjeremylt ofield = &op->inputfields[i]; 976d7b241e6Sjeremylt goto found; 977d7b241e6Sjeremylt } 978d7b241e6Sjeremylt } 979d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 980fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 981*e15f9bd0SJeremy L Thompson qfield = op->qf->outputfields[i]; 982d7b241e6Sjeremylt ofield = &op->outputfields[i]; 983d7b241e6Sjeremylt goto found; 984d7b241e6Sjeremylt } 985d7b241e6Sjeremylt } 986c042f62fSJeremy L Thompson // LCOV_EXCL_START 987*e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 988*e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 989d7b241e6Sjeremylt fieldname); 990c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 991d7b241e6Sjeremylt found: 992*e15f9bd0SJeremy L Thompson ierr = CeedOperatorCheckField(op->ceed, qfield, r, b); CeedChk(ierr); 993fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 994*e15f9bd0SJeremy L Thompson 995*e15f9bd0SJeremy L Thompson (*ofield)->vec = v; 996*e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 997*e15f9bd0SJeremy L Thompson v->refcount += 1; 998*e15f9bd0SJeremy L Thompson } 999*e15f9bd0SJeremy L Thompson 1000fe2413ffSjeremylt (*ofield)->Erestrict = r; 100171352a93Sjeremylt r->refcount += 1; 1002*e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1003*e15f9bd0SJeremy L Thompson op->numelements = numelements; 1004*e15f9bd0SJeremy L Thompson op->hasrestriction = true; // Restriction set, but numelements may be 0 1005*e15f9bd0SJeremy L Thompson } 1006d99fa3c5SJeremy L Thompson 1007*e15f9bd0SJeremy L Thompson (*ofield)->basis = b; 1008*e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1009*e15f9bd0SJeremy L Thompson op->numqpoints = numqpoints; 1010*e15f9bd0SJeremy L Thompson b->refcount += 1; 1011*e15f9bd0SJeremy L Thompson } 1012*e15f9bd0SJeremy L Thompson 1013*e15f9bd0SJeremy L Thompson op->nfields += 1; 1014d99fa3c5SJeremy L Thompson size_t len = strlen(fieldname); 1015d99fa3c5SJeremy L Thompson char *tmp; 1016d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1017d99fa3c5SJeremy L Thompson memcpy(tmp, fieldname, len+1); 1018d99fa3c5SJeremy L Thompson (*ofield)->fieldname = tmp; 1019*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1020d7b241e6Sjeremylt } 1021d7b241e6Sjeremylt 1022d7b241e6Sjeremylt /** 102352d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1024288c0443SJeremy L Thompson 102534138859Sjeremylt @param[out] compositeop Composite CeedOperator 102634138859Sjeremylt @param subop Sub-operator CeedOperator 102752d6035fSJeremy L Thompson 102852d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 102952d6035fSJeremy L Thompson 10307a982d89SJeremy L. Thompson @ref User 103152d6035fSJeremy L Thompson */ 1032692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 103352d6035fSJeremy L Thompson if (!compositeop->composite) 1034c042f62fSJeremy L Thompson // LCOV_EXCL_START 1035*e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_MINOR, 1036*e15f9bd0SJeremy L Thompson "CeedOperator is not a composite " 10371d102b48SJeremy L Thompson "operator"); 1038c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 103952d6035fSJeremy L Thompson 104052d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 1041c042f62fSJeremy L Thompson // LCOV_EXCL_START 1042*e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_UNSUPPORTED, 1043*e15f9bd0SJeremy L Thompson "Cannot add additional suboperators"); 1044c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 104552d6035fSJeremy L Thompson 104652d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 104752d6035fSJeremy L Thompson subop->refcount++; 104852d6035fSJeremy L Thompson compositeop->numsub++; 1049*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 105052d6035fSJeremy L Thompson } 105152d6035fSJeremy L Thompson 105252d6035fSJeremy L Thompson /** 10531d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 10541d102b48SJeremy L Thompson 10551d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 10561d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 10571d102b48SJeremy L Thompson The vector 'assembled' is of shape 10581d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 10591d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 10601d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 10611d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 10624cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 10631d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 10641d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 10651d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 10661d102b48SJeremy L Thompson 10671d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 10681d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 10691d102b48SJeremy L Thompson quadrature points 10701d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 10711d102b48SJeremy L Thompson CeedQFunction 10721d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 10734cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 10741d102b48SJeremy L Thompson 10751d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10761d102b48SJeremy L Thompson 10777a982d89SJeremy L. Thompson @ref User 10781d102b48SJeremy L Thompson **/ 107980ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 10807f823360Sjeremylt CeedElemRestriction *rstr, 10817f823360Sjeremylt CeedRequest *request) { 10821d102b48SJeremy L Thompson int ierr; 10831d102b48SJeremy L Thompson Ceed ceed = op->ceed; 1084250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 10851d102b48SJeremy L Thompson 10867172caadSjeremylt // Backend version 108780ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 108880ac2e43SJeremy L Thompson ierr = op->LinearAssembleQFunction(op, assembled, rstr, request); 10891d102b48SJeremy L Thompson CeedChk(ierr); 10905107b09fSJeremy L Thompson } else { 10915107b09fSJeremy L Thompson // Fallback to reference Ceed 10925107b09fSJeremy L Thompson if (!op->opfallback) { 10935107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 10945107b09fSJeremy L Thompson } 10955107b09fSJeremy L Thompson // Assemble 109680ac2e43SJeremy L Thompson ierr = op->opfallback->LinearAssembleQFunction(op->opfallback, assembled, 10975107b09fSJeremy L Thompson rstr, request); CeedChk(ierr); 10985107b09fSJeremy L Thompson } 1099*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11001d102b48SJeremy L Thompson } 11011d102b48SJeremy L Thompson 11021d102b48SJeremy L Thompson /** 1103d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1104b7ec98d8SJeremy L Thompson 11059e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1106b7ec98d8SJeremy L Thompson 1107c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1108c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1109d965c7a7SJeremy L Thompson 1110b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1111b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1112b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11134cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1114b7ec98d8SJeremy L Thompson 1115b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1116b7ec98d8SJeremy L Thompson 11177a982d89SJeremy L. Thompson @ref User 1118b7ec98d8SJeremy L Thompson **/ 11192bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11207f823360Sjeremylt CeedRequest *request) { 1121b7ec98d8SJeremy L Thompson int ierr; 1122b7ec98d8SJeremy L Thompson Ceed ceed = op->ceed; 1123250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1124b7ec98d8SJeremy L Thompson 1125b7ec98d8SJeremy L Thompson // Use backend version, if available 112680ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 112780ac2e43SJeremy L Thompson ierr = op->LinearAssembleDiagonal(op, assembled, request); CeedChk(ierr); 11289e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11299e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11309e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11319e9210b8SJeremy L Thompson } else { 11329e9210b8SJeremy L Thompson // Fallback to reference Ceed 11339e9210b8SJeremy L Thompson if (!op->opfallback) { 11349e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11359e9210b8SJeremy L Thompson } 11369e9210b8SJeremy L Thompson // Assemble 11379e9210b8SJeremy L Thompson if (op->opfallback->LinearAssembleDiagonal) { 11389e9210b8SJeremy L Thompson ierr = op->opfallback->LinearAssembleDiagonal(op->opfallback, assembled, 11399e9210b8SJeremy L Thompson request); CeedChk(ierr); 11409e9210b8SJeremy L Thompson } else { 11419e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11429e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11439e9210b8SJeremy L Thompson } 11449e9210b8SJeremy L Thompson } 1145*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 11469e9210b8SJeremy L Thompson } 11479e9210b8SJeremy L Thompson 11489e9210b8SJeremy L Thompson /** 11499e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 11509e9210b8SJeremy L Thompson 11519e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 11529e9210b8SJeremy L Thompson 11539e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 11549e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 11559e9210b8SJeremy L Thompson 11569e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11579e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 11589e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11599e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 11609e9210b8SJeremy L Thompson 11619e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11629e9210b8SJeremy L Thompson 11639e9210b8SJeremy L Thompson @ref User 11649e9210b8SJeremy L Thompson **/ 11659e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 11669e9210b8SJeremy L Thompson CeedRequest *request) { 11679e9210b8SJeremy L Thompson int ierr; 11689e9210b8SJeremy L Thompson Ceed ceed = op->ceed; 11699e9210b8SJeremy L Thompson ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 11709e9210b8SJeremy L Thompson 11719e9210b8SJeremy L Thompson // Use backend version, if available 11729e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 11739e9210b8SJeremy L Thompson ierr = op->LinearAssembleAddDiagonal(op, assembled, request); CeedChk(ierr); 11747172caadSjeremylt } else { 11757172caadSjeremylt // Fallback to reference Ceed 11767172caadSjeremylt if (!op->opfallback) { 11777172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1178b7ec98d8SJeremy L Thompson } 11797172caadSjeremylt // Assemble 11809e9210b8SJeremy L Thompson ierr = op->opfallback->LinearAssembleAddDiagonal(op->opfallback, assembled, 11817172caadSjeremylt request); CeedChk(ierr); 1182b7ec98d8SJeremy L Thompson } 1183*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1184b7ec98d8SJeremy L Thompson } 1185b7ec98d8SJeremy L Thompson 1186b7ec98d8SJeremy L Thompson /** 1187d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1188d965c7a7SJeremy L Thompson 11899e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1190d965c7a7SJeremy L Thompson CeedOperator. 1191d965c7a7SJeremy L Thompson 1192c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1193c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1194d965c7a7SJeremy L Thompson 1195d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1196d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1197d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1198d965c7a7SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 1199d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1200d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1201d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1202d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1203d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1204d965c7a7SJeremy L Thompson 1205d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1206d965c7a7SJeremy L Thompson 1207d965c7a7SJeremy L Thompson @ref User 1208d965c7a7SJeremy L Thompson **/ 120980ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12102bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1211d965c7a7SJeremy L Thompson int ierr; 1212d965c7a7SJeremy L Thompson Ceed ceed = op->ceed; 1213d965c7a7SJeremy L Thompson ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1214d965c7a7SJeremy L Thompson 1215d965c7a7SJeremy L Thompson // Use backend version, if available 121680ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 121780ac2e43SJeremy L Thompson ierr = op->LinearAssemblePointBlockDiagonal(op, assembled, request); 1218d965c7a7SJeremy L Thompson CeedChk(ierr); 12199e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12209e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12219e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12229e9210b8SJeremy L Thompson request); 1223d965c7a7SJeremy L Thompson } else { 1224d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1225d965c7a7SJeremy L Thompson if (!op->opfallback) { 1226d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1227d965c7a7SJeremy L Thompson } 1228d965c7a7SJeremy L Thompson // Assemble 12299e9210b8SJeremy L Thompson if (op->opfallback->LinearAssemblePointBlockDiagonal) { 123080ac2e43SJeremy L Thompson ierr = op->opfallback->LinearAssemblePointBlockDiagonal(op->opfallback, 1231d965c7a7SJeremy L Thompson assembled, request); CeedChk(ierr); 12329e9210b8SJeremy L Thompson } else { 12339e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12349e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12359e9210b8SJeremy L Thompson request); 12369e9210b8SJeremy L Thompson } 12379e9210b8SJeremy L Thompson } 1238*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 12399e9210b8SJeremy L Thompson } 12409e9210b8SJeremy L Thompson 12419e9210b8SJeremy L Thompson /** 12429e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12439e9210b8SJeremy L Thompson 12449e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12459e9210b8SJeremy L Thompson CeedOperator. 12469e9210b8SJeremy L Thompson 12479e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12489e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12499e9210b8SJeremy L Thompson 12509e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12519e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 12529e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 12539e9210b8SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 12549e9210b8SJeremy L Thompson of this vector are derived from the active vector 12559e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 12569e9210b8SJeremy L Thompson [nodes, component out, component in]. 12579e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12589e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 12599e9210b8SJeremy L Thompson 12609e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12619e9210b8SJeremy L Thompson 12629e9210b8SJeremy L Thompson @ref User 12639e9210b8SJeremy L Thompson **/ 12649e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 12659e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 12669e9210b8SJeremy L Thompson int ierr; 12679e9210b8SJeremy L Thompson Ceed ceed = op->ceed; 12689e9210b8SJeremy L Thompson ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 12699e9210b8SJeremy L Thompson 12709e9210b8SJeremy L Thompson // Use backend version, if available 12719e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 12729e9210b8SJeremy L Thompson ierr = op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 12739e9210b8SJeremy L Thompson CeedChk(ierr); 12749e9210b8SJeremy L Thompson } else { 12759e9210b8SJeremy L Thompson // Fallback to reference Ceed 12769e9210b8SJeremy L Thompson if (!op->opfallback) { 12779e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 12789e9210b8SJeremy L Thompson } 12799e9210b8SJeremy L Thompson // Assemble 12809e9210b8SJeremy L Thompson ierr = op->opfallback->LinearAssembleAddPointBlockDiagonal(op->opfallback, 12819e9210b8SJeremy L Thompson assembled, request); CeedChk(ierr); 1282d965c7a7SJeremy L Thompson } 1283*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1284d965c7a7SJeremy L Thompson } 1285d965c7a7SJeremy L Thompson 1286d965c7a7SJeremy L Thompson /** 1287d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1288d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1289d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1290d99fa3c5SJeremy L Thompson 1291d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1292d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1293d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1294d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1295d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1296d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1297d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1298d99fa3c5SJeremy L Thompson 1299d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1300d99fa3c5SJeremy L Thompson 1301d99fa3c5SJeremy L Thompson @ref User 1302d99fa3c5SJeremy L Thompson **/ 1303d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreate(CeedOperator opFine, CeedVector PMultFine, 1304d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1305d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, CeedOperator *opProlong, CeedOperator *opRestrict) { 1306d99fa3c5SJeremy L Thompson int ierr; 1307d99fa3c5SJeremy L Thompson Ceed ceed; 1308d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1309d99fa3c5SJeremy L Thompson 1310d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1311d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1312d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1313d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1314d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1315d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1316d99fa3c5SJeremy L Thompson if (Qf != Qc) 1317d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1318*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1319*e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1320d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1321d99fa3c5SJeremy L Thompson 1322d99fa3c5SJeremy L Thompson // Coarse to fine basis 1323d99fa3c5SJeremy L Thompson CeedInt Pf, Pc, Q = Qf; 1324d99fa3c5SJeremy L Thompson bool isTensorF, isTensorC; 1325d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisFine, &isTensorF); CeedChk(ierr); 1326d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisCoarse, &isTensorC); CeedChk(ierr); 1327d99fa3c5SJeremy L Thompson CeedScalar *interpC, *interpF, *interpCtoF, *tau; 1328d99fa3c5SJeremy L Thompson if (isTensorF && isTensorC) { 1329d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &Pf); CeedChk(ierr); 1330d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisCoarse, &Pc); CeedChk(ierr); 1331d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basisCoarse, &Q); CeedChk(ierr); 1332d99fa3c5SJeremy L Thompson } else if (!isTensorF && !isTensorC) { 1333d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &Pf); CeedChk(ierr); 1334d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisCoarse, &Pc); CeedChk(ierr); 1335d99fa3c5SJeremy L Thompson } else { 1336d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1337*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1338*e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1339d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1340d99fa3c5SJeremy L Thompson } 1341d99fa3c5SJeremy L Thompson 1342d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pf, &interpF); CeedChk(ierr); 1343d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pc, &interpC); CeedChk(ierr); 1344d99fa3c5SJeremy L Thompson ierr = CeedCalloc(Pc*Pf, &interpCtoF); CeedChk(ierr); 1345d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1346d99fa3c5SJeremy L Thompson if (isTensorF) { 1347d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp1d, Q*Pf*sizeof basisFine->interp1d[0]); 1348d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp1d, Q*Pc*sizeof basisCoarse->interp1d[0]); 1349d99fa3c5SJeremy L Thompson } else { 1350d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp, Q*Pf*sizeof basisFine->interp[0]); 1351d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp, Q*Pc*sizeof basisCoarse->interp[0]); 1352d99fa3c5SJeremy L Thompson } 1353d99fa3c5SJeremy L Thompson 1354d99fa3c5SJeremy L Thompson // -- QR Factorization, interpF = Q R 1355d99fa3c5SJeremy L Thompson ierr = CeedQRFactorization(ceed, interpF, tau, Q, Pf); CeedChk(ierr); 1356d99fa3c5SJeremy L Thompson 1357d99fa3c5SJeremy L Thompson // -- Apply Qtranspose, interpC = Qtranspose interpC 1358d99fa3c5SJeremy L Thompson CeedHouseholderApplyQ(interpC, interpF, tau, CEED_TRANSPOSE, 1359d99fa3c5SJeremy L Thompson Q, Pc, Pf, Pc, 1); 1360d99fa3c5SJeremy L Thompson 1361d99fa3c5SJeremy L Thompson // -- Apply Rinv, interpCtoF = Rinv interpC 1362d99fa3c5SJeremy L Thompson for (CeedInt j=0; j<Pc; j++) { // Column j 1363d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*(Pf-1)] = interpC[j+Pc*(Pf-1)]/interpF[Pf*Pf-1]; 1364d99fa3c5SJeremy L Thompson for (CeedInt i=Pf-2; i>=0; i--) { // Row i 1365d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] = interpC[j+Pc*i]; 1366d99fa3c5SJeremy L Thompson for (CeedInt k=i+1; k<Pf; k++) 1367d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] -= interpF[k+Pf*i]*interpCtoF[j+Pc*k]; 1368d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] /= interpF[i+Pf*i]; 1369d99fa3c5SJeremy L Thompson } 1370d99fa3c5SJeremy L Thompson } 1371d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1372d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpC); CeedChk(ierr); 1373d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpF); CeedChk(ierr); 1374d99fa3c5SJeremy L Thompson 1375*e15f9bd0SJeremy L Thompson // Complete with interpCtoF versions of code 1376d99fa3c5SJeremy L Thompson if (isTensorF) { 1377d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateTensorH1(opFine, PMultFine, 1378d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1379d99fa3c5SJeremy L Thompson CeedChk(ierr); 1380d99fa3c5SJeremy L Thompson } else { 1381d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateH1(opFine, PMultFine, 1382d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1383d99fa3c5SJeremy L Thompson CeedChk(ierr); 1384d99fa3c5SJeremy L Thompson } 1385d99fa3c5SJeremy L Thompson 1386d99fa3c5SJeremy L Thompson // Cleanup 1387d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpCtoF); CeedChk(ierr); 1388*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1389d99fa3c5SJeremy L Thompson } 1390d99fa3c5SJeremy L Thompson 1391d99fa3c5SJeremy L Thompson /** 1392d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1393d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1394d99fa3c5SJeremy L Thompson 1395d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1396d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1397d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1398d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1399d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1400d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1401d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1402d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1403d99fa3c5SJeremy L Thompson 1404d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1405d99fa3c5SJeremy L Thompson 1406d99fa3c5SJeremy L Thompson @ref User 1407d99fa3c5SJeremy L Thompson **/ 1408d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator opFine, 1409d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1410d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, CeedOperator *opCoarse, 1411d99fa3c5SJeremy L Thompson CeedOperator *opProlong, CeedOperator *opRestrict) { 1412d99fa3c5SJeremy L Thompson int ierr; 1413d99fa3c5SJeremy L Thompson Ceed ceed; 1414d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1415d99fa3c5SJeremy L Thompson 1416d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1417d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1418d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1419d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1420d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1421d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1422d99fa3c5SJeremy L Thompson if (Qf != Qc) 1423d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1424*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1425*e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1426d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1427d99fa3c5SJeremy L Thompson 1428d99fa3c5SJeremy L Thompson // Coarse to fine basis 1429d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, P1dFine, P1dCoarse; 1430d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1431d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1432d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &P1dFine); CeedChk(ierr); 1433d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1434d99fa3c5SJeremy L Thompson CeedChk(ierr); 1435d99fa3c5SJeremy L Thompson P1dCoarse = dim == 1 ? nnodesCoarse : 1436d99fa3c5SJeremy L Thompson dim == 2 ? sqrt(nnodesCoarse) : 1437d99fa3c5SJeremy L Thompson cbrt(nnodesCoarse); 1438d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1439d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qref); CeedChk(ierr); 1440d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qweight); CeedChk(ierr); 1441d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine*P1dCoarse*dim, &grad); CeedChk(ierr); 1442d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1443d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1dCoarse, P1dFine, 1444d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1445d99fa3c5SJeremy L Thompson CeedChk(ierr); 1446d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1447d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1448d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1449d99fa3c5SJeremy L Thompson 1450d99fa3c5SJeremy L Thompson // Core code 1451d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1452d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1453d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1454d99fa3c5SJeremy L Thompson CeedChk(ierr); 1455*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1456d99fa3c5SJeremy L Thompson } 1457d99fa3c5SJeremy L Thompson 1458d99fa3c5SJeremy L Thompson /** 1459d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1460d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 1461d99fa3c5SJeremy L Thompson 1462d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1463d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1464d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1465d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1466d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1467d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1468d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1469d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1470d99fa3c5SJeremy L Thompson 1471d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1472d99fa3c5SJeremy L Thompson 1473d99fa3c5SJeremy L Thompson @ref User 1474d99fa3c5SJeremy L Thompson **/ 1475d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateH1(CeedOperator opFine, 1476d99fa3c5SJeremy L Thompson CeedVector PMultFine, 1477d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, 1478d99fa3c5SJeremy L Thompson CeedBasis basisCoarse, 1479d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, 1480d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, 1481d99fa3c5SJeremy L Thompson CeedOperator *opProlong, 1482d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 1483d99fa3c5SJeremy L Thompson int ierr; 1484d99fa3c5SJeremy L Thompson Ceed ceed; 1485d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1486d99fa3c5SJeremy L Thompson 1487d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1488d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1489d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1490d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1491d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1492d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1493d99fa3c5SJeremy L Thompson if (Qf != Qc) 1494d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1495*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1496*e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1497d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1498d99fa3c5SJeremy L Thompson 1499d99fa3c5SJeremy L Thompson // Coarse to fine basis 1500d99fa3c5SJeremy L Thompson CeedElemTopology topo; 1501d99fa3c5SJeremy L Thompson ierr = CeedBasisGetTopology(basisFine, &topo); CeedChk(ierr); 1502d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, nnodesFine; 1503d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1504d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1505d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &nnodesFine); CeedChk(ierr); 1506d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1507d99fa3c5SJeremy L Thompson CeedChk(ierr); 1508d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1509d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qref); CeedChk(ierr); 1510d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qweight); CeedChk(ierr); 1511d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine*nnodesCoarse*dim, &grad); CeedChk(ierr); 1512d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1513d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateH1(ceed, topo, ncomp, nnodesCoarse, nnodesFine, 1514d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1515d99fa3c5SJeremy L Thompson CeedChk(ierr); 1516d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1517d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1518d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1519d99fa3c5SJeremy L Thompson 1520d99fa3c5SJeremy L Thompson // Core code 1521d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1522d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1523d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1524d99fa3c5SJeremy L Thompson CeedChk(ierr); 1525*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1526d99fa3c5SJeremy L Thompson } 1527d99fa3c5SJeremy L Thompson 1528d99fa3c5SJeremy L Thompson /** 15293bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 15303bd813ffSjeremylt CeedOperator 15313bd813ffSjeremylt 15323bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 15333bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 15343bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 15353bd813ffSjeremylt M = V^T V, K = V^T S V. 15363bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 15373bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 15383bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 15393bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 15403bd813ffSjeremylt 15413bd813ffSjeremylt @param op CeedOperator to create element inverses 15423bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 15433bd813ffSjeremylt for each element 15443bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 15454cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 15463bd813ffSjeremylt 15473bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 15483bd813ffSjeremylt 15497a982d89SJeremy L. Thompson @ref Backend 15503bd813ffSjeremylt **/ 15513bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 15523bd813ffSjeremylt CeedRequest *request) { 15533bd813ffSjeremylt int ierr; 15543bd813ffSjeremylt Ceed ceed = op->ceed; 1555713f43c3Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 15563bd813ffSjeremylt 1557713f43c3Sjeremylt // Use backend version, if available 1558713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 1559713f43c3Sjeremylt ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr); 1560713f43c3Sjeremylt } else { 1561713f43c3Sjeremylt // Fallback to reference Ceed 1562713f43c3Sjeremylt if (!op->opfallback) { 1563713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 15643bd813ffSjeremylt } 1565713f43c3Sjeremylt // Assemble 1566713f43c3Sjeremylt ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv, 15673bd813ffSjeremylt request); CeedChk(ierr); 15683bd813ffSjeremylt } 1569*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 15703bd813ffSjeremylt } 15713bd813ffSjeremylt 15727a982d89SJeremy L. Thompson /** 15737a982d89SJeremy L. Thompson @brief View a CeedOperator 15747a982d89SJeremy L. Thompson 15757a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 15767a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 15777a982d89SJeremy L. Thompson 15787a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 15797a982d89SJeremy L. Thompson 15807a982d89SJeremy L. Thompson @ref User 15817a982d89SJeremy L. Thompson **/ 15827a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 15837a982d89SJeremy L. Thompson int ierr; 15847a982d89SJeremy L. Thompson 15857a982d89SJeremy L. Thompson if (op->composite) { 15867a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 15877a982d89SJeremy L. Thompson 15887a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->numsub; i++) { 15897a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 15907a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 15917a982d89SJeremy L. Thompson CeedChk(ierr); 15927a982d89SJeremy L. Thompson } 15937a982d89SJeremy L. Thompson } else { 15947a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 15957a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 15967a982d89SJeremy L. Thompson } 1597*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 15987a982d89SJeremy L. Thompson } 15993bd813ffSjeremylt 16003bd813ffSjeremylt /** 16013bd813ffSjeremylt @brief Apply CeedOperator to a vector 1602d7b241e6Sjeremylt 1603d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 1604d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 1605d7b241e6Sjeremylt CeedOperatorSetField(). 1606d7b241e6Sjeremylt 1607d7b241e6Sjeremylt @param op CeedOperator to apply 16084cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 160934138859Sjeremylt there are no active inputs 1610b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 16114cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 161234138859Sjeremylt active outputs 1613d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 16144cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1615b11c1e72Sjeremylt 1616b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1617dfdf5a53Sjeremylt 16187a982d89SJeremy L. Thompson @ref User 1619b11c1e72Sjeremylt **/ 1620692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1621692c2638Sjeremylt CeedRequest *request) { 1622d7b241e6Sjeremylt int ierr; 1623d7b241e6Sjeremylt Ceed ceed = op->ceed; 1624250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1625d7b241e6Sjeremylt 1626250756a7Sjeremylt if (op->numelements) { 1627250756a7Sjeremylt // Standard Operator 1628cae8b89aSjeremylt if (op->Apply) { 1629250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1630cae8b89aSjeremylt } else { 1631cae8b89aSjeremylt // Zero all output vectors 1632250756a7Sjeremylt CeedQFunction qf = op->qf; 1633cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 1634cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 1635cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 1636cae8b89aSjeremylt vec = out; 1637cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 1638cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1639cae8b89aSjeremylt } 1640cae8b89aSjeremylt } 1641250756a7Sjeremylt // Apply 1642250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1643250756a7Sjeremylt } 1644250756a7Sjeremylt } else if (op->composite) { 1645250756a7Sjeremylt // Composite Operator 1646250756a7Sjeremylt if (op->ApplyComposite) { 1647250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1648250756a7Sjeremylt } else { 1649250756a7Sjeremylt CeedInt numsub; 1650250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1651250756a7Sjeremylt CeedOperator *suboperators; 1652250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1653250756a7Sjeremylt 1654250756a7Sjeremylt // Zero all output vectors 1655250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 1656cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1657cae8b89aSjeremylt } 1658250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 1659250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 1660250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 1661250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1662250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1663250756a7Sjeremylt } 1664250756a7Sjeremylt } 1665250756a7Sjeremylt } 1666250756a7Sjeremylt // Apply 1667250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 1668250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 1669cae8b89aSjeremylt CeedChk(ierr); 1670cae8b89aSjeremylt } 1671cae8b89aSjeremylt } 1672250756a7Sjeremylt } 1673*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1674cae8b89aSjeremylt } 1675cae8b89aSjeremylt 1676cae8b89aSjeremylt /** 1677cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 1678cae8b89aSjeremylt 1679cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 1680cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 1681cae8b89aSjeremylt CeedOperatorSetField(). 1682cae8b89aSjeremylt 1683cae8b89aSjeremylt @param op CeedOperator to apply 1684cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 1685cae8b89aSjeremylt active inputs 1686cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 1687cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 1688cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 16894cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1690cae8b89aSjeremylt 1691cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 1692cae8b89aSjeremylt 16937a982d89SJeremy L. Thompson @ref User 1694cae8b89aSjeremylt **/ 1695cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1696cae8b89aSjeremylt CeedRequest *request) { 1697cae8b89aSjeremylt int ierr; 1698cae8b89aSjeremylt Ceed ceed = op->ceed; 1699250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1700cae8b89aSjeremylt 1701250756a7Sjeremylt if (op->numelements) { 1702250756a7Sjeremylt // Standard Operator 1703250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1704250756a7Sjeremylt } else if (op->composite) { 1705250756a7Sjeremylt // Composite Operator 1706250756a7Sjeremylt if (op->ApplyAddComposite) { 1707250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1708cae8b89aSjeremylt } else { 1709250756a7Sjeremylt CeedInt numsub; 1710250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1711250756a7Sjeremylt CeedOperator *suboperators; 1712250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1713250756a7Sjeremylt 1714250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 1715250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 1716cae8b89aSjeremylt CeedChk(ierr); 17171d7d2407SJeremy L Thompson } 1718250756a7Sjeremylt } 1719250756a7Sjeremylt } 1720*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1721d7b241e6Sjeremylt } 1722d7b241e6Sjeremylt 1723d7b241e6Sjeremylt /** 1724b11c1e72Sjeremylt @brief Destroy a CeedOperator 1725d7b241e6Sjeremylt 1726d7b241e6Sjeremylt @param op CeedOperator to destroy 1727b11c1e72Sjeremylt 1728b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1729dfdf5a53Sjeremylt 17307a982d89SJeremy L. Thompson @ref User 1731b11c1e72Sjeremylt **/ 1732d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1733d7b241e6Sjeremylt int ierr; 1734d7b241e6Sjeremylt 1735*e15f9bd0SJeremy L Thompson if (!*op || --(*op)->refcount > 0) return CEED_ERROR_SUCCESS; 1736d7b241e6Sjeremylt if ((*op)->Destroy) { 1737d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1738d7b241e6Sjeremylt } 1739fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1740fe2413ffSjeremylt // Free fields 17411d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 174252d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 174315910d16Sjeremylt if ((*op)->inputfields[i]->Erestrict != CEED_ELEMRESTRICTION_NONE) { 174471352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 174571352a93Sjeremylt CeedChk(ierr); 174615910d16Sjeremylt } 174771352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 174871352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 174971352a93Sjeremylt } 175071352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 175171352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 175271352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 175371352a93Sjeremylt } 1754d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->inputfields[i]->fieldname); CeedChk(ierr); 1755fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 1756fe2413ffSjeremylt } 17571d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 1758d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 175971352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 176071352a93Sjeremylt CeedChk(ierr); 176171352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 176271352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 176371352a93Sjeremylt } 176471352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 176571352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 176671352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 176771352a93Sjeremylt } 1768d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->outputfields[i]->fieldname); CeedChk(ierr); 1769fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1770fe2413ffSjeremylt } 177152d6035fSJeremy L Thompson // Destroy suboperators 17721d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 177352d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 177452d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 177552d6035fSJeremy L Thompson } 1776*e15f9bd0SJeremy L Thompson if ((*op)->qf) 1777*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 1778*e15f9bd0SJeremy L Thompson (*op)->qf->operatorsset--; 1779*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 1780d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1781*e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 1782*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 1783*e15f9bd0SJeremy L Thompson (*op)->dqf->operatorsset--; 1784*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 1785d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1786*e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 1787*e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 1788*e15f9bd0SJeremy L Thompson (*op)->dqfT->operatorsset--; 1789*e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 1790d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1791fe2413ffSjeremylt 17925107b09fSJeremy L Thompson // Destroy fallback 17935107b09fSJeremy L Thompson if ((*op)->opfallback) { 17945107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 17955107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 17965107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 17975107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 17985107b09fSJeremy L Thompson } 17995107b09fSJeremy L Thompson 1800fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1801fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 180252d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1803d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1804*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1805d7b241e6Sjeremylt } 1806d7b241e6Sjeremylt 1807d7b241e6Sjeremylt /// @} 1808