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 17d7b241e6Sjeremylt #include <ceed-impl.h> 18d863ab9bSjeremylt #include <ceed-backend.h> 19d7b241e6Sjeremylt #include <string.h> 203bd813ffSjeremylt #include <math.h> 21d7b241e6Sjeremylt 22dfdf5a53Sjeremylt /// @file 237a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 247a982d89SJeremy L. Thompson 257a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 267a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 277a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 287a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 297a982d89SJeremy L. Thompson /// @{ 307a982d89SJeremy L. Thompson 317a982d89SJeremy L. Thompson /** 327a982d89SJeremy L. Thompson @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced 337a982d89SJeremy L. Thompson CeedOperator functionality 347a982d89SJeremy L. Thompson 357a982d89SJeremy L. Thompson @param op CeedOperator to create fallback for 367a982d89SJeremy L. Thompson 377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 387a982d89SJeremy L. Thompson 397a982d89SJeremy L. Thompson @ref Developer 407a982d89SJeremy L. Thompson **/ 417a982d89SJeremy L. Thompson int CeedOperatorCreateFallback(CeedOperator op) { 427a982d89SJeremy L. Thompson int ierr; 437a982d89SJeremy L. Thompson 447a982d89SJeremy L. Thompson // Fallback Ceed 457a982d89SJeremy L. Thompson const char *resource, *fallbackresource; 467a982d89SJeremy L. Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 477a982d89SJeremy L. Thompson ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 487a982d89SJeremy L. Thompson CeedChk(ierr); 497a982d89SJeremy L. Thompson if (!strcmp(resource, fallbackresource)) 507a982d89SJeremy L. Thompson // LCOV_EXCL_START 517a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Backend %s cannot create an operator" 527a982d89SJeremy L. Thompson "fallback to resource %s", resource, fallbackresource); 537a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 547a982d89SJeremy L. Thompson 557a982d89SJeremy L. Thompson // Fallback Ceed 567a982d89SJeremy L. Thompson Ceed ceedref; 577a982d89SJeremy L. Thompson if (!op->ceed->opfallbackceed) { 587a982d89SJeremy L. Thompson ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr); 597a982d89SJeremy L. Thompson ceedref->opfallbackparent = op->ceed; 607a982d89SJeremy L. Thompson op->ceed->opfallbackceed = ceedref; 617a982d89SJeremy L. Thompson } 627a982d89SJeremy L. Thompson ceedref = op->ceed->opfallbackceed; 637a982d89SJeremy L. Thompson 647a982d89SJeremy L. Thompson // Clone Op 657a982d89SJeremy L. Thompson CeedOperator opref; 667a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &opref); CeedChk(ierr); 677a982d89SJeremy L. Thompson memcpy(opref, op, sizeof(*opref)); CeedChk(ierr); 687a982d89SJeremy L. Thompson opref->data = NULL; 697a982d89SJeremy L. Thompson opref->setupdone = 0; 707a982d89SJeremy L. Thompson opref->ceed = ceedref; 717a982d89SJeremy L. Thompson ierr = ceedref->OperatorCreate(opref); CeedChk(ierr); 727a982d89SJeremy L. Thompson op->opfallback = opref; 737a982d89SJeremy L. Thompson 747a982d89SJeremy L. Thompson // Clone QF 757a982d89SJeremy L. Thompson CeedQFunction qfref; 767a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &qfref); CeedChk(ierr); 777a982d89SJeremy L. Thompson memcpy(qfref, (op->qf), sizeof(*qfref)); CeedChk(ierr); 787a982d89SJeremy L. Thompson qfref->data = NULL; 797a982d89SJeremy L. Thompson qfref->ceed = ceedref; 807a982d89SJeremy L. Thompson ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr); 817a982d89SJeremy L. Thompson opref->qf = qfref; 827a982d89SJeremy L. Thompson op->qffallback = qfref; 837a982d89SJeremy L. Thompson 847a982d89SJeremy L. Thompson return 0; 857a982d89SJeremy L. Thompson } 867a982d89SJeremy L. Thompson 877a982d89SJeremy L. Thompson /** 887a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 897a982d89SJeremy L. Thompson 907a982d89SJeremy L. Thompson @param[in] ceed Ceed object for error handling 917a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 927a982d89SJeremy L. Thompson 937a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 947a982d89SJeremy L. Thompson 957a982d89SJeremy L. Thompson @ref Developer 967a982d89SJeremy L. Thompson **/ 977a982d89SJeremy L. Thompson static int CeedOperatorCheckReady(Ceed ceed, CeedOperator op) { 987a982d89SJeremy L. Thompson CeedQFunction qf = op->qf; 997a982d89SJeremy L. Thompson 1007a982d89SJeremy L. Thompson if (op->composite) { 1017a982d89SJeremy L. Thompson if (!op->numsub) 1027a982d89SJeremy L. Thompson // LCOV_EXCL_START 1037a982d89SJeremy L. Thompson return CeedError(ceed, 1, "No suboperators set"); 1047a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1057a982d89SJeremy L. Thompson } else { 1067a982d89SJeremy L. Thompson if (op->nfields == 0) 1077a982d89SJeremy L. Thompson // LCOV_EXCL_START 1087a982d89SJeremy L. Thompson return CeedError(ceed, 1, "No operator fields set"); 1097a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1107a982d89SJeremy L. Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 1117a982d89SJeremy L. Thompson // LCOV_EXCL_START 1127a982d89SJeremy L. Thompson return CeedError(ceed, 1, "Not all operator fields set"); 1137a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1147a982d89SJeremy L. Thompson if (!op->hasrestriction) 1157a982d89SJeremy L. Thompson // LCOV_EXCL_START 1167a982d89SJeremy L. Thompson return CeedError(ceed, 1,"At least one restriction required"); 1177a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1187a982d89SJeremy L. Thompson if (op->numqpoints == 0) 1197a982d89SJeremy L. Thompson // LCOV_EXCL_START 1207a982d89SJeremy L. Thompson return CeedError(ceed, 1,"At least one non-collocated basis required"); 1217a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1227a982d89SJeremy L. Thompson } 1237a982d89SJeremy L. Thompson 1247a982d89SJeremy L. Thompson return 0; 1257a982d89SJeremy L. Thompson } 1267a982d89SJeremy L. Thompson 1277a982d89SJeremy L. Thompson /** 1287a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 1297a982d89SJeremy L. Thompson 1307a982d89SJeremy L. Thompson @param[in] field Operator field to view 1314c4400c7SValeria Barra @param[in] qffield QFunction field (carries field name) 1327a982d89SJeremy L. Thompson @param[in] fieldnumber Number of field being viewed 1334c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 1344c4400c7SValeria Barra @param[in] in true for an input field; false for output field 1357a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 1367a982d89SJeremy L. Thompson 1377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1387a982d89SJeremy L. Thompson 1397a982d89SJeremy L. Thompson @ref Utility 1407a982d89SJeremy L. Thompson **/ 1417a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 1427a982d89SJeremy L. Thompson CeedQFunctionField qffield, 1437a982d89SJeremy L. Thompson CeedInt fieldnumber, bool sub, bool in, 1447a982d89SJeremy L. Thompson FILE *stream) { 1457a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 1467a982d89SJeremy L. Thompson const char *inout = in ? "Input" : "Output"; 1477a982d89SJeremy L. Thompson 1487a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 1497a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 1507a982d89SJeremy L. Thompson pre, inout, fieldnumber, pre, qffield->fieldname); 1517a982d89SJeremy L. Thompson 1527a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 1537a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 1547a982d89SJeremy L. Thompson 1557a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 1567a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 1577a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 1587a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 1597a982d89SJeremy L. Thompson 1607a982d89SJeremy L. Thompson return 0; 1617a982d89SJeremy L. Thompson } 1627a982d89SJeremy L. Thompson 1637a982d89SJeremy L. Thompson /** 1647a982d89SJeremy L. Thompson @brief View a single CeedOperator 1657a982d89SJeremy L. Thompson 1667a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 1677a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 1687a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 1697a982d89SJeremy L. Thompson 1707a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 1717a982d89SJeremy L. Thompson 1727a982d89SJeremy L. Thompson @ref Utility 1737a982d89SJeremy L. Thompson **/ 1747a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 1757a982d89SJeremy L. Thompson int ierr; 1767a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 1777a982d89SJeremy L. Thompson 1787a982d89SJeremy L. Thompson CeedInt totalfields; 1797a982d89SJeremy L. Thompson ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 1807a982d89SJeremy L. Thompson 1817a982d89SJeremy L. Thompson fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 1827a982d89SJeremy L. Thompson 1837a982d89SJeremy L. Thompson fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 1847a982d89SJeremy L. Thompson op->qf->numinputfields>1 ? "s" : ""); 1857a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numinputfields; i++) { 1867a982d89SJeremy L. Thompson ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 1877a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 1887a982d89SJeremy L. Thompson } 1897a982d89SJeremy L. Thompson 1907a982d89SJeremy L. Thompson fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 1917a982d89SJeremy L. Thompson op->qf->numoutputfields>1 ? "s" : ""); 1927a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 1937a982d89SJeremy L. Thompson ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 1947a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 1957a982d89SJeremy L. Thompson } 1967a982d89SJeremy L. Thompson 1977a982d89SJeremy L. Thompson return 0; 1987a982d89SJeremy L. Thompson } 1997a982d89SJeremy L. Thompson 200*d99fa3c5SJeremy L Thompson /** 201*d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 202*d99fa3c5SJeremy L Thompson 203*d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 204*d99fa3c5SJeremy L Thompson @param[out] activeBasis Basis for active input vector 205*d99fa3c5SJeremy L Thompson 206*d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 207*d99fa3c5SJeremy L Thompson 208*d99fa3c5SJeremy L Thompson @ ref Developer 209*d99fa3c5SJeremy L Thompson **/ 210*d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 211*d99fa3c5SJeremy L Thompson CeedBasis *activeBasis) { 212*d99fa3c5SJeremy L Thompson *activeBasis = NULL; 213*d99fa3c5SJeremy L Thompson for (int i = 0; i < op->qf->numinputfields; i++) 214*d99fa3c5SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 215*d99fa3c5SJeremy L Thompson *activeBasis = op->inputfields[i]->basis; 216*d99fa3c5SJeremy L Thompson break; 217*d99fa3c5SJeremy L Thompson } 218*d99fa3c5SJeremy L Thompson 219*d99fa3c5SJeremy L Thompson if (!*activeBasis) { 220*d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 221*d99fa3c5SJeremy L Thompson int ierr; 222*d99fa3c5SJeremy L Thompson Ceed ceed; 223*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 224*d99fa3c5SJeremy L Thompson return CeedError(ceed, 1, 225*d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 226*d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 227*d99fa3c5SJeremy L Thompson } 228*d99fa3c5SJeremy L Thompson return 0; 229*d99fa3c5SJeremy L Thompson } 230*d99fa3c5SJeremy L Thompson 231*d99fa3c5SJeremy L Thompson 232*d99fa3c5SJeremy L Thompson /** 233*d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 234*d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 235*d99fa3c5SJeremy L Thompson 236*d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 237*d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 238*d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 239*d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 240*d99fa3c5SJeremy L Thompson @param[in] basisCtoF Basis for coarse to fine interpolation 241*d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 242*d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 243*d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 244*d99fa3c5SJeremy L Thompson 245*d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 246*d99fa3c5SJeremy L Thompson 247*d99fa3c5SJeremy L Thompson @ref Developer 248*d99fa3c5SJeremy L Thompson **/ 249*d99fa3c5SJeremy L Thompson static int CeedOperatorMultigridLevel_Core(CeedOperator opFine, 250*d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 251*d99fa3c5SJeremy L Thompson CeedBasis basisCtoF, CeedOperator *opCoarse, CeedOperator *opProlong, 252*d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 253*d99fa3c5SJeremy L Thompson int ierr; 254*d99fa3c5SJeremy L Thompson Ceed ceed; 255*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 256*d99fa3c5SJeremy L Thompson 257*d99fa3c5SJeremy L Thompson // Check for composite operator 258*d99fa3c5SJeremy L Thompson bool isComposite; 259*d99fa3c5SJeremy L Thompson ierr = CeedOperatorIsComposite(opFine, &isComposite); CeedChk(ierr); 260*d99fa3c5SJeremy L Thompson if (isComposite) 261*d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 262*d99fa3c5SJeremy L Thompson return CeedError(ceed, 1, 263*d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 264*d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 265*d99fa3c5SJeremy L Thompson 266*d99fa3c5SJeremy L Thompson // Coarse Grid 267*d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, opFine->qf, opFine->dqf, opFine->dqfT, 268*d99fa3c5SJeremy L Thompson opCoarse); CeedChk(ierr); 269*d99fa3c5SJeremy L Thompson CeedElemRestriction rstrFine = NULL; 270*d99fa3c5SJeremy L Thompson // -- Clone input fields 271*d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numinputfields; i++) { 272*d99fa3c5SJeremy L Thompson if (opFine->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 273*d99fa3c5SJeremy L Thompson rstrFine = opFine->inputfields[i]->Erestrict; 274*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 275*d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 276*d99fa3c5SJeremy L Thompson CeedChk(ierr); 277*d99fa3c5SJeremy L Thompson } else { 278*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 279*d99fa3c5SJeremy L Thompson opFine->inputfields[i]->Erestrict, 280*d99fa3c5SJeremy L Thompson opFine->inputfields[i]->basis, 281*d99fa3c5SJeremy L Thompson opFine->inputfields[i]->vec); CeedChk(ierr); 282*d99fa3c5SJeremy L Thompson } 283*d99fa3c5SJeremy L Thompson } 284*d99fa3c5SJeremy L Thompson // -- Clone output fields 285*d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numoutputfields; i++) { 286*d99fa3c5SJeremy L Thompson if (opFine->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 287*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 288*d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 289*d99fa3c5SJeremy L Thompson CeedChk(ierr); 290*d99fa3c5SJeremy L Thompson } else { 291*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 292*d99fa3c5SJeremy L Thompson opFine->outputfields[i]->Erestrict, 293*d99fa3c5SJeremy L Thompson opFine->outputfields[i]->basis, 294*d99fa3c5SJeremy L Thompson opFine->outputfields[i]->vec); CeedChk(ierr); 295*d99fa3c5SJeremy L Thompson } 296*d99fa3c5SJeremy L Thompson } 297*d99fa3c5SJeremy L Thompson 298*d99fa3c5SJeremy L Thompson // Multiplicity vector 299*d99fa3c5SJeremy L Thompson CeedVector multVec, multE; 300*d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrFine, &multVec, &multE); 301*d99fa3c5SJeremy L Thompson CeedChk(ierr); 302*d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multE, 0.0); CeedChk(ierr); 303*d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_NOTRANSPOSE, PMultFine, multE, 304*d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 305*d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multVec, 0.0); CeedChk(ierr); 306*d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_TRANSPOSE, multE, multVec, 307*d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 308*d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multE); CeedChk(ierr); 309*d99fa3c5SJeremy L Thompson ierr = CeedVectorReciprocal(multVec); CeedChk(ierr); 310*d99fa3c5SJeremy L Thompson 311*d99fa3c5SJeremy L Thompson // Restriction 312*d99fa3c5SJeremy L Thompson CeedInt ncomp; 313*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisCoarse, &ncomp); CeedChk(ierr); 314*d99fa3c5SJeremy L Thompson CeedQFunction qfRestrict; 315*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfRestrict); 316*d99fa3c5SJeremy L Thompson CeedChk(ierr); 317*d99fa3c5SJeremy L Thompson CeedInt *ctxR; 318*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(1, &ctxR); CeedChk(ierr); 319*d99fa3c5SJeremy L Thompson ctxR[0] = ncomp; 320*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionSetContext(qfRestrict, ctxR, sizeof(*ctxR)); CeedChk(ierr); 321*d99fa3c5SJeremy L Thompson qfRestrict->ctx_allocated = qfRestrict->ctx; 322*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "input", ncomp, CEED_EVAL_NONE); 323*d99fa3c5SJeremy L Thompson CeedChk(ierr); 324*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "scale", ncomp, CEED_EVAL_NONE); 325*d99fa3c5SJeremy L Thompson CeedChk(ierr); 326*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfRestrict, "output", ncomp, CEED_EVAL_INTERP); 327*d99fa3c5SJeremy L Thompson CeedChk(ierr); 328*d99fa3c5SJeremy L Thompson 329*d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfRestrict, CEED_QFUNCTION_NONE, 330*d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opRestrict); 331*d99fa3c5SJeremy L Thompson CeedChk(ierr); 332*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "input", rstrFine, 333*d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 334*d99fa3c5SJeremy L Thompson CeedChk(ierr); 335*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "scale", rstrFine, 336*d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 337*d99fa3c5SJeremy L Thompson CeedChk(ierr); 338*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "output", rstrCoarse, basisCtoF, 339*d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 340*d99fa3c5SJeremy L Thompson 341*d99fa3c5SJeremy L Thompson // Prolongation 342*d99fa3c5SJeremy L Thompson CeedQFunction qfProlong; 343*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfProlong); 344*d99fa3c5SJeremy L Thompson CeedChk(ierr); 345*d99fa3c5SJeremy L Thompson CeedInt *ctxP; 346*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(1, &ctxP); CeedChk(ierr); 347*d99fa3c5SJeremy L Thompson ctxP[0] = ncomp; 348*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionSetContext(qfProlong, ctxP, sizeof(*ctxP)); CeedChk(ierr); 349*d99fa3c5SJeremy L Thompson qfProlong->ctx_allocated = qfProlong->ctx; 350*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "input", ncomp, CEED_EVAL_INTERP); 351*d99fa3c5SJeremy L Thompson CeedChk(ierr); 352*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "scale", ncomp, CEED_EVAL_NONE); 353*d99fa3c5SJeremy L Thompson CeedChk(ierr); 354*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfProlong, "output", ncomp, CEED_EVAL_NONE); 355*d99fa3c5SJeremy L Thompson CeedChk(ierr); 356*d99fa3c5SJeremy L Thompson 357*d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfProlong, CEED_QFUNCTION_NONE, 358*d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opProlong); 359*d99fa3c5SJeremy L Thompson CeedChk(ierr); 360*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "input", rstrCoarse, basisCtoF, 361*d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 362*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "scale", rstrFine, 363*d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 364*d99fa3c5SJeremy L Thompson CeedChk(ierr); 365*d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "output", rstrFine, 366*d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 367*d99fa3c5SJeremy L Thompson CeedChk(ierr); 368*d99fa3c5SJeremy L Thompson 369*d99fa3c5SJeremy L Thompson // Cleanup 370*d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multVec); CeedChk(ierr); 371*d99fa3c5SJeremy L Thompson ierr = CeedBasisDestroy(&basisCtoF); CeedChk(ierr); 372*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfRestrict); CeedChk(ierr); 373*d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfProlong); CeedChk(ierr); 374*d99fa3c5SJeremy L Thompson 375*d99fa3c5SJeremy L Thompson return 0; 376*d99fa3c5SJeremy L Thompson } 377*d99fa3c5SJeremy L Thompson 3787a982d89SJeremy L. Thompson /// @} 3797a982d89SJeremy L. Thompson 3807a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3817a982d89SJeremy L. Thompson /// CeedOperator Backend API 3827a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 3837a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 3847a982d89SJeremy L. Thompson /// @{ 3857a982d89SJeremy L. Thompson 3867a982d89SJeremy L. Thompson /** 3877a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 3887a982d89SJeremy L. Thompson 3897a982d89SJeremy L. Thompson @param op CeedOperator 3907a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 3917a982d89SJeremy L. Thompson 3927a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3937a982d89SJeremy L. Thompson 3947a982d89SJeremy L. Thompson @ref Backend 3957a982d89SJeremy L. Thompson **/ 3967a982d89SJeremy L. Thompson 3977a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 3987a982d89SJeremy L. Thompson *ceed = op->ceed; 3997a982d89SJeremy L. Thompson return 0; 4007a982d89SJeremy L. Thompson } 4017a982d89SJeremy L. Thompson 4027a982d89SJeremy L. Thompson /** 4037a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 4047a982d89SJeremy L. Thompson 4057a982d89SJeremy L. Thompson @param op CeedOperator 4067a982d89SJeremy L. Thompson @param[out] numelem Variable to store number of elements 4077a982d89SJeremy L. Thompson 4087a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4097a982d89SJeremy L. Thompson 4107a982d89SJeremy L. Thompson @ref Backend 4117a982d89SJeremy L. Thompson **/ 4127a982d89SJeremy L. Thompson 4137a982d89SJeremy L. Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 4147a982d89SJeremy L. Thompson if (op->composite) 4157a982d89SJeremy L. Thompson // LCOV_EXCL_START 4167a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 4177a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4187a982d89SJeremy L. Thompson 4197a982d89SJeremy L. Thompson *numelem = op->numelements; 4207a982d89SJeremy L. Thompson return 0; 4217a982d89SJeremy L. Thompson } 4227a982d89SJeremy L. Thompson 4237a982d89SJeremy L. Thompson /** 4247a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 4257a982d89SJeremy L. Thompson 4267a982d89SJeremy L. Thompson @param op CeedOperator 4277a982d89SJeremy L. Thompson @param[out] numqpts Variable to store vector number of quadrature points 4287a982d89SJeremy L. Thompson 4297a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4307a982d89SJeremy L. Thompson 4317a982d89SJeremy L. Thompson @ref Backend 4327a982d89SJeremy L. Thompson **/ 4337a982d89SJeremy L. Thompson 4347a982d89SJeremy L. Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 4357a982d89SJeremy L. Thompson if (op->composite) 4367a982d89SJeremy L. Thompson // LCOV_EXCL_START 4377a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 4387a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4397a982d89SJeremy L. Thompson 4407a982d89SJeremy L. Thompson *numqpts = op->numqpoints; 4417a982d89SJeremy L. Thompson return 0; 4427a982d89SJeremy L. Thompson } 4437a982d89SJeremy L. Thompson 4447a982d89SJeremy L. Thompson /** 4457a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 4467a982d89SJeremy L. Thompson 4477a982d89SJeremy L. Thompson @param op CeedOperator 4487a982d89SJeremy L. Thompson @param[out] numargs Variable to store vector number of arguments 4497a982d89SJeremy L. Thompson 4507a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4517a982d89SJeremy L. Thompson 4527a982d89SJeremy L. Thompson @ref Backend 4537a982d89SJeremy L. Thompson **/ 4547a982d89SJeremy L. Thompson 4557a982d89SJeremy L. Thompson int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 4567a982d89SJeremy L. Thompson if (op->composite) 4577a982d89SJeremy L. Thompson // LCOV_EXCL_START 4587a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not defined for composite operators"); 4597a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4607a982d89SJeremy L. Thompson 4617a982d89SJeremy L. Thompson *numargs = op->nfields; 4627a982d89SJeremy L. Thompson return 0; 4637a982d89SJeremy L. Thompson } 4647a982d89SJeremy L. Thompson 4657a982d89SJeremy L. Thompson /** 4667a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 4677a982d89SJeremy L. Thompson 4687a982d89SJeremy L. Thompson @param op CeedOperator 469fd364f38SJeremy L Thompson @param[out] issetupdone Variable to store setup status 4707a982d89SJeremy L. Thompson 4717a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4727a982d89SJeremy L. Thompson 4737a982d89SJeremy L. Thompson @ref Backend 4747a982d89SJeremy L. Thompson **/ 4757a982d89SJeremy L. Thompson 476fd364f38SJeremy L Thompson int CeedOperatorIsSetupDone(CeedOperator op, bool *issetupdone) { 477fd364f38SJeremy L Thompson *issetupdone = op->setupdone; 4787a982d89SJeremy L. Thompson return 0; 4797a982d89SJeremy L. Thompson } 4807a982d89SJeremy L. Thompson 4817a982d89SJeremy L. Thompson /** 4827a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 4837a982d89SJeremy L. Thompson 4847a982d89SJeremy L. Thompson @param op CeedOperator 4857a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 4867a982d89SJeremy L. Thompson 4877a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 4887a982d89SJeremy L. Thompson 4897a982d89SJeremy L. Thompson @ref Backend 4907a982d89SJeremy L. Thompson **/ 4917a982d89SJeremy L. Thompson 4927a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 4937a982d89SJeremy L. Thompson if (op->composite) 4947a982d89SJeremy L. Thompson // LCOV_EXCL_START 4957a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 4967a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 4977a982d89SJeremy L. Thompson 4987a982d89SJeremy L. Thompson *qf = op->qf; 4997a982d89SJeremy L. Thompson return 0; 5007a982d89SJeremy L. Thompson } 5017a982d89SJeremy L. Thompson 5027a982d89SJeremy L. Thompson /** 503c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 504c04a41a7SJeremy L Thompson 505c04a41a7SJeremy L Thompson @param op CeedOperator 506fd364f38SJeremy L Thompson @param[out] iscomposite Variable to store composite status 507c04a41a7SJeremy L Thompson 508c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 509c04a41a7SJeremy L Thompson 510c04a41a7SJeremy L Thompson @ref Backend 511c04a41a7SJeremy L Thompson **/ 512c04a41a7SJeremy L Thompson 513fd364f38SJeremy L Thompson int CeedOperatorIsComposite(CeedOperator op, bool *iscomposite) { 514fd364f38SJeremy L Thompson *iscomposite = op->composite; 515c04a41a7SJeremy L Thompson return 0; 516c04a41a7SJeremy L Thompson } 517c04a41a7SJeremy L Thompson 518c04a41a7SJeremy L Thompson /** 5197a982d89SJeremy L. Thompson @brief Get the number of suboperators associated with a CeedOperator 5207a982d89SJeremy L. Thompson 5217a982d89SJeremy L. Thompson @param op CeedOperator 5227a982d89SJeremy L. Thompson @param[out] numsub Variable to store number of suboperators 5237a982d89SJeremy L. Thompson 5247a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5257a982d89SJeremy L. Thompson 5267a982d89SJeremy L. Thompson @ref Backend 5277a982d89SJeremy L. Thompson **/ 5287a982d89SJeremy L. Thompson 5297a982d89SJeremy L. Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 5307a982d89SJeremy L. Thompson if (!op->composite) 5317a982d89SJeremy L. Thompson // LCOV_EXCL_START 5327a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 5337a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5347a982d89SJeremy L. Thompson 5357a982d89SJeremy L. Thompson *numsub = op->numsub; 5367a982d89SJeremy L. Thompson return 0; 5377a982d89SJeremy L. Thompson } 5387a982d89SJeremy L. Thompson 5397a982d89SJeremy L. Thompson /** 5407a982d89SJeremy L. Thompson @brief Get the list of suboperators associated with a CeedOperator 5417a982d89SJeremy L. Thompson 5427a982d89SJeremy L. Thompson @param op CeedOperator 5437a982d89SJeremy L. Thompson @param[out] suboperators Variable to store list of suboperators 5447a982d89SJeremy L. Thompson 5457a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5467a982d89SJeremy L. Thompson 5477a982d89SJeremy L. Thompson @ref Backend 5487a982d89SJeremy L. Thompson **/ 5497a982d89SJeremy L. Thompson 5507a982d89SJeremy L. Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 5517a982d89SJeremy L. Thompson if (!op->composite) 5527a982d89SJeremy L. Thompson // LCOV_EXCL_START 5537a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 5547a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5557a982d89SJeremy L. Thompson 5567a982d89SJeremy L. Thompson *suboperators = op->suboperators; 5577a982d89SJeremy L. Thompson return 0; 5587a982d89SJeremy L. Thompson } 5597a982d89SJeremy L. Thompson 5607a982d89SJeremy L. Thompson /** 5617a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 5627a982d89SJeremy L. Thompson 5637a982d89SJeremy L. Thompson @param op CeedOperator 5647a982d89SJeremy L. Thompson @param[out] data Variable to store data 5657a982d89SJeremy L. Thompson 5667a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5677a982d89SJeremy L. Thompson 5687a982d89SJeremy L. Thompson @ref Backend 5697a982d89SJeremy L. Thompson **/ 5707a982d89SJeremy L. Thompson 5717a982d89SJeremy L. Thompson int CeedOperatorGetData(CeedOperator op, void **data) { 5727a982d89SJeremy L. Thompson *data = op->data; 5737a982d89SJeremy L. Thompson return 0; 5747a982d89SJeremy L. Thompson } 5757a982d89SJeremy L. Thompson 5767a982d89SJeremy L. Thompson /** 5777a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 5787a982d89SJeremy L. Thompson 5797a982d89SJeremy L. Thompson @param[out] op CeedOperator 5807a982d89SJeremy L. Thompson @param data Data to set 5817a982d89SJeremy L. Thompson 5827a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5837a982d89SJeremy L. Thompson 5847a982d89SJeremy L. Thompson @ref Backend 5857a982d89SJeremy L. Thompson **/ 5867a982d89SJeremy L. Thompson 5877a982d89SJeremy L. Thompson int CeedOperatorSetData(CeedOperator op, void **data) { 5887a982d89SJeremy L. Thompson op->data = *data; 5897a982d89SJeremy L. Thompson return 0; 5907a982d89SJeremy L. Thompson } 5917a982d89SJeremy L. Thompson 5927a982d89SJeremy L. Thompson /** 5937a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 5947a982d89SJeremy L. Thompson 5957a982d89SJeremy L. Thompson @param op CeedOperator 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 CeedOperatorSetSetupDone(CeedOperator op) { 6037a982d89SJeremy L. Thompson op->setupdone = 1; 6047a982d89SJeremy L. Thompson return 0; 6057a982d89SJeremy L. Thompson } 6067a982d89SJeremy L. Thompson 6077a982d89SJeremy L. Thompson /** 6087a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 6097a982d89SJeremy L. Thompson 6107a982d89SJeremy L. Thompson @param op CeedOperator 6117a982d89SJeremy L. Thompson @param[out] inputfields Variable to store inputfields 6127a982d89SJeremy L. Thompson @param[out] outputfields Variable to store outputfields 6137a982d89SJeremy L. Thompson 6147a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6157a982d89SJeremy L. Thompson 6167a982d89SJeremy L. Thompson @ref Backend 6177a982d89SJeremy L. Thompson **/ 6187a982d89SJeremy L. Thompson 6197a982d89SJeremy L. Thompson int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 6207a982d89SJeremy L. Thompson CeedOperatorField **outputfields) { 6217a982d89SJeremy L. Thompson if (op->composite) 6227a982d89SJeremy L. Thompson // LCOV_EXCL_START 6237a982d89SJeremy L. Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 6247a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6257a982d89SJeremy L. Thompson 6267a982d89SJeremy L. Thompson if (inputfields) *inputfields = op->inputfields; 6277a982d89SJeremy L. Thompson if (outputfields) *outputfields = op->outputfields; 6287a982d89SJeremy L. Thompson return 0; 6297a982d89SJeremy L. Thompson } 6307a982d89SJeremy L. Thompson 6317a982d89SJeremy L. Thompson /** 6327a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 6337a982d89SJeremy L. Thompson 6347a982d89SJeremy L. Thompson @param opfield CeedOperatorField 6357a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 6367a982d89SJeremy L. Thompson 6377a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6387a982d89SJeremy L. Thompson 6397a982d89SJeremy L. Thompson @ref Backend 6407a982d89SJeremy L. Thompson **/ 6417a982d89SJeremy L. Thompson 6427a982d89SJeremy L. Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 6437a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 6447a982d89SJeremy L. Thompson *rstr = opfield->Erestrict; 6457a982d89SJeremy L. Thompson return 0; 6467a982d89SJeremy L. Thompson } 6477a982d89SJeremy L. Thompson 6487a982d89SJeremy L. Thompson /** 6497a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 6507a982d89SJeremy L. Thompson 6517a982d89SJeremy L. Thompson @param opfield CeedOperatorField 6527a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 6537a982d89SJeremy L. Thompson 6547a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson @ref Backend 6577a982d89SJeremy L. Thompson **/ 6587a982d89SJeremy L. Thompson 6597a982d89SJeremy L. Thompson int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 6607a982d89SJeremy L. Thompson *basis = opfield->basis; 6617a982d89SJeremy L. Thompson return 0; 6627a982d89SJeremy L. Thompson } 6637a982d89SJeremy L. Thompson 6647a982d89SJeremy L. Thompson /** 6657a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 6667a982d89SJeremy L. Thompson 6677a982d89SJeremy L. Thompson @param opfield CeedOperatorField 6687a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 6697a982d89SJeremy L. Thompson 6707a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6717a982d89SJeremy L. Thompson 6727a982d89SJeremy L. Thompson @ref Backend 6737a982d89SJeremy L. Thompson **/ 6747a982d89SJeremy L. Thompson 6757a982d89SJeremy L. Thompson int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 6767a982d89SJeremy L. Thompson *vec = opfield->vec; 6777a982d89SJeremy L. Thompson return 0; 6787a982d89SJeremy L. Thompson } 6797a982d89SJeremy L. Thompson 6807a982d89SJeremy L. Thompson /// @} 6817a982d89SJeremy L. Thompson 6827a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 6837a982d89SJeremy L. Thompson /// CeedOperator Public API 6847a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 6857a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 686dfdf5a53Sjeremylt /// @{ 687d7b241e6Sjeremylt 688d7b241e6Sjeremylt /** 6890219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 6900219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 6910219ea01SJeremy L Thompson \ref CeedOperatorSetField. 692d7b241e6Sjeremylt 693b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 694d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 69534138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 6964cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 697d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 6984cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 699b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 700b11c1e72Sjeremylt CeedOperator will be stored 701b11c1e72Sjeremylt 702b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 703dfdf5a53Sjeremylt 7047a982d89SJeremy L. Thompson @ref User 705d7b241e6Sjeremylt */ 706d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 707d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 708d7b241e6Sjeremylt int ierr; 709d7b241e6Sjeremylt 7105fe0d4faSjeremylt if (!ceed->OperatorCreate) { 7115fe0d4faSjeremylt Ceed delegate; 712aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 7135fe0d4faSjeremylt 7145fe0d4faSjeremylt if (!delegate) 715c042f62fSJeremy L Thompson // LCOV_EXCL_START 7165fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 717c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 7185fe0d4faSjeremylt 7195fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 7205fe0d4faSjeremylt return 0; 7215fe0d4faSjeremylt } 7225fe0d4faSjeremylt 723b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 724b3b7035fSJeremy L Thompson // LCOV_EXCL_START 725b3b7035fSJeremy L Thompson return CeedError(ceed, 1, "Operator must have a valid QFunction."); 726b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 727d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 728d7b241e6Sjeremylt (*op)->ceed = ceed; 729d7b241e6Sjeremylt ceed->refcount++; 730d7b241e6Sjeremylt (*op)->refcount = 1; 731d7b241e6Sjeremylt (*op)->qf = qf; 732d7b241e6Sjeremylt qf->refcount++; 733442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 734d7b241e6Sjeremylt (*op)->dqf = dqf; 735442e7f0bSjeremylt dqf->refcount++; 736442e7f0bSjeremylt } 737442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 738d7b241e6Sjeremylt (*op)->dqfT = dqfT; 739442e7f0bSjeremylt dqfT->refcount++; 740442e7f0bSjeremylt } 741fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 742fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 743d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 744d7b241e6Sjeremylt return 0; 745d7b241e6Sjeremylt } 746d7b241e6Sjeremylt 747d7b241e6Sjeremylt /** 74852d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 74952d6035fSJeremy L Thompson 75052d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 75152d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 75252d6035fSJeremy L Thompson Composite CeedOperator will be stored 75352d6035fSJeremy L Thompson 75452d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 75552d6035fSJeremy L Thompson 7567a982d89SJeremy L. Thompson @ref User 75752d6035fSJeremy L Thompson */ 75852d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 75952d6035fSJeremy L Thompson int ierr; 76052d6035fSJeremy L Thompson 76152d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 76252d6035fSJeremy L Thompson Ceed delegate; 763aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 76452d6035fSJeremy L Thompson 765250756a7Sjeremylt if (delegate) { 76652d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 76752d6035fSJeremy L Thompson return 0; 76852d6035fSJeremy L Thompson } 769250756a7Sjeremylt } 77052d6035fSJeremy L Thompson 77152d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 77252d6035fSJeremy L Thompson (*op)->ceed = ceed; 77352d6035fSJeremy L Thompson ceed->refcount++; 77452d6035fSJeremy L Thompson (*op)->composite = true; 77552d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 776250756a7Sjeremylt 777250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 77852d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 779250756a7Sjeremylt } 78052d6035fSJeremy L Thompson return 0; 78152d6035fSJeremy L Thompson } 78252d6035fSJeremy L Thompson 78352d6035fSJeremy L Thompson /** 784b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 785d7b241e6Sjeremylt 786d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 787d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 788d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 789d7b241e6Sjeremylt 790d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 791d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 792d7b241e6Sjeremylt input and at most one active output. 793d7b241e6Sjeremylt 7948c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 7958795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 7968795c945Sjeremylt CeedQFunction) 797b11c1e72Sjeremylt @param r CeedElemRestriction 7984cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 799b11c1e72Sjeremylt if collocated with quadrature points 8004cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 8014cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 8024cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 803b11c1e72Sjeremylt 804b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 805dfdf5a53Sjeremylt 8067a982d89SJeremy L. Thompson @ref User 807b11c1e72Sjeremylt **/ 808d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 809a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 810d7b241e6Sjeremylt int ierr; 81152d6035fSJeremy L Thompson if (op->composite) 812c042f62fSJeremy L Thompson // LCOV_EXCL_START 81352d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 814c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8158b067b84SJed Brown if (!r) 816c042f62fSJeremy L Thompson // LCOV_EXCL_START 817c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, 818c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 819c042f62fSJeremy L Thompson fieldname); 820c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8218b067b84SJed Brown if (!b) 822c042f62fSJeremy L Thompson // LCOV_EXCL_START 823c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.", 824c042f62fSJeremy L Thompson fieldname); 825c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8268b067b84SJed Brown if (!v) 827c042f62fSJeremy L Thompson // LCOV_EXCL_START 828c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.", 829c042f62fSJeremy L Thompson fieldname); 830c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 83152d6035fSJeremy L Thompson 832d7b241e6Sjeremylt CeedInt numelements; 833d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 83415910d16Sjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->hasrestriction && 83515910d16Sjeremylt op->numelements != numelements) 836c042f62fSJeremy L Thompson // LCOV_EXCL_START 837d7b241e6Sjeremylt return CeedError(op->ceed, 1, 8381d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 8391d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 840c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 84115910d16Sjeremylt if (r != CEED_ELEMRESTRICTION_NONE) { 842d7b241e6Sjeremylt op->numelements = numelements; 8432cb0afc5Sjeremylt op->hasrestriction = true; // Restriction set, but numelements may be 0 84415910d16Sjeremylt } 845d7b241e6Sjeremylt 846783c99b3SValeria Barra if (b != CEED_BASIS_COLLOCATED) { 847d7b241e6Sjeremylt CeedInt numqpoints; 848d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 849d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 850c042f62fSJeremy L Thompson // LCOV_EXCL_START 8511d102b48SJeremy L Thompson return CeedError(op->ceed, 1, "Basis with %d quadrature points " 8521d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 8531d102b48SJeremy L Thompson op->numqpoints); 854c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 855d7b241e6Sjeremylt op->numqpoints = numqpoints; 856d7b241e6Sjeremylt } 85715910d16Sjeremylt CeedQFunctionField qfield; 858d1bcdac9Sjeremylt CeedOperatorField *ofield; 859d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 860fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 86115910d16Sjeremylt qfield = op->qf->inputfields[i]; 862d7b241e6Sjeremylt ofield = &op->inputfields[i]; 863d7b241e6Sjeremylt goto found; 864d7b241e6Sjeremylt } 865d7b241e6Sjeremylt } 866d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 867fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 86815910d16Sjeremylt qfield = op->qf->inputfields[i]; 869d7b241e6Sjeremylt ofield = &op->outputfields[i]; 870d7b241e6Sjeremylt goto found; 871d7b241e6Sjeremylt } 872d7b241e6Sjeremylt } 873c042f62fSJeremy L Thompson // LCOV_EXCL_START 874d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 875d7b241e6Sjeremylt fieldname); 876c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 877d7b241e6Sjeremylt found: 87815910d16Sjeremylt if (r == CEED_ELEMRESTRICTION_NONE && qfield->emode != CEED_EVAL_WEIGHT) 879b0d62198Sjeremylt // LCOV_EXCL_START 88015910d16Sjeremylt return CeedError(op->ceed, 1, "CEED_ELEMRESTRICTION_NONE can only be used " 88115910d16Sjeremylt "for a field with eval mode CEED_EVAL_WEIGHT"); 882b0d62198Sjeremylt // LCOV_EXCL_STOP 883fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 884fe2413ffSjeremylt (*ofield)->Erestrict = r; 88571352a93Sjeremylt r->refcount += 1; 886fe2413ffSjeremylt (*ofield)->basis = b; 88771352a93Sjeremylt if (b != CEED_BASIS_COLLOCATED) 88871352a93Sjeremylt b->refcount += 1; 889fe2413ffSjeremylt (*ofield)->vec = v; 89071352a93Sjeremylt if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) 89171352a93Sjeremylt v->refcount += 1; 892d7b241e6Sjeremylt op->nfields += 1; 893*d99fa3c5SJeremy L Thompson 894*d99fa3c5SJeremy L Thompson size_t len = strlen(fieldname); 895*d99fa3c5SJeremy L Thompson char *tmp; 896*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 897*d99fa3c5SJeremy L Thompson memcpy(tmp, fieldname, len+1); 898*d99fa3c5SJeremy L Thompson (*ofield)->fieldname = tmp; 899d7b241e6Sjeremylt return 0; 900d7b241e6Sjeremylt } 901d7b241e6Sjeremylt 902d7b241e6Sjeremylt /** 90352d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 904288c0443SJeremy L Thompson 90534138859Sjeremylt @param[out] compositeop Composite CeedOperator 90634138859Sjeremylt @param subop Sub-operator CeedOperator 90752d6035fSJeremy L Thompson 90852d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 90952d6035fSJeremy L Thompson 9107a982d89SJeremy L. Thompson @ref User 91152d6035fSJeremy L Thompson */ 912692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 91352d6035fSJeremy L Thompson if (!compositeop->composite) 914c042f62fSJeremy L Thompson // LCOV_EXCL_START 9151d102b48SJeremy L Thompson return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite " 9161d102b48SJeremy L Thompson "operator"); 917c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 91852d6035fSJeremy L Thompson 91952d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 920c042f62fSJeremy L Thompson // LCOV_EXCL_START 9211d102b48SJeremy L Thompson return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators"); 922c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 92352d6035fSJeremy L Thompson 92452d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 92552d6035fSJeremy L Thompson subop->refcount++; 92652d6035fSJeremy L Thompson compositeop->numsub++; 92752d6035fSJeremy L Thompson return 0; 92852d6035fSJeremy L Thompson } 92952d6035fSJeremy L Thompson 93052d6035fSJeremy L Thompson /** 9311d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 9321d102b48SJeremy L Thompson 9331d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 9341d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 9351d102b48SJeremy L Thompson The vector 'assembled' is of shape 9361d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 9371d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 9381d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 9391d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 9404cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 9411d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 9421d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 9431d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 9441d102b48SJeremy L Thompson 9451d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 9461d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 9471d102b48SJeremy L Thompson quadrature points 9481d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 9491d102b48SJeremy L Thompson CeedQFunction 9501d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 9514cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 9521d102b48SJeremy L Thompson 9531d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9541d102b48SJeremy L Thompson 9557a982d89SJeremy L. Thompson @ref User 9561d102b48SJeremy L Thompson **/ 95780ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 9587f823360Sjeremylt CeedElemRestriction *rstr, 9597f823360Sjeremylt CeedRequest *request) { 9601d102b48SJeremy L Thompson int ierr; 9611d102b48SJeremy L Thompson Ceed ceed = op->ceed; 962250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 9631d102b48SJeremy L Thompson 9647172caadSjeremylt // Backend version 96580ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 96680ac2e43SJeremy L Thompson ierr = op->LinearAssembleQFunction(op, assembled, rstr, request); 9671d102b48SJeremy L Thompson CeedChk(ierr); 9685107b09fSJeremy L Thompson } else { 9695107b09fSJeremy L Thompson // Fallback to reference Ceed 9705107b09fSJeremy L Thompson if (!op->opfallback) { 9715107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 9725107b09fSJeremy L Thompson } 9735107b09fSJeremy L Thompson // Assemble 97480ac2e43SJeremy L Thompson ierr = op->opfallback->LinearAssembleQFunction(op->opfallback, assembled, 9755107b09fSJeremy L Thompson rstr, request); CeedChk(ierr); 9765107b09fSJeremy L Thompson } 977250756a7Sjeremylt 9781d102b48SJeremy L Thompson return 0; 9791d102b48SJeremy L Thompson } 9801d102b48SJeremy L Thompson 9811d102b48SJeremy L Thompson /** 982d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 983b7ec98d8SJeremy L Thompson 9849e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 985b7ec98d8SJeremy L Thompson 986c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 987c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 988d965c7a7SJeremy L Thompson 989b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 990b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 991b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 9924cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 993b7ec98d8SJeremy L Thompson 994b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 995b7ec98d8SJeremy L Thompson 9967a982d89SJeremy L. Thompson @ref User 997b7ec98d8SJeremy L Thompson **/ 9982bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 9997f823360Sjeremylt CeedRequest *request) { 1000b7ec98d8SJeremy L Thompson int ierr; 1001b7ec98d8SJeremy L Thompson Ceed ceed = op->ceed; 1002250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1003b7ec98d8SJeremy L Thompson 1004b7ec98d8SJeremy L Thompson // Use backend version, if available 100580ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 100680ac2e43SJeremy L Thompson ierr = op->LinearAssembleDiagonal(op, assembled, request); CeedChk(ierr); 10079e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 10089e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 10099e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 10109e9210b8SJeremy L Thompson } else { 10119e9210b8SJeremy L Thompson // Fallback to reference Ceed 10129e9210b8SJeremy L Thompson if (!op->opfallback) { 10139e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 10149e9210b8SJeremy L Thompson } 10159e9210b8SJeremy L Thompson // Assemble 10169e9210b8SJeremy L Thompson if (op->opfallback->LinearAssembleDiagonal) { 10179e9210b8SJeremy L Thompson ierr = op->opfallback->LinearAssembleDiagonal(op->opfallback, assembled, 10189e9210b8SJeremy L Thompson request); CeedChk(ierr); 10199e9210b8SJeremy L Thompson } else { 10209e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 10219e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 10229e9210b8SJeremy L Thompson } 10239e9210b8SJeremy L Thompson } 10249e9210b8SJeremy L Thompson 10259e9210b8SJeremy L Thompson return 0; 10269e9210b8SJeremy L Thompson } 10279e9210b8SJeremy L Thompson 10289e9210b8SJeremy L Thompson /** 10299e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 10309e9210b8SJeremy L Thompson 10319e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 10329e9210b8SJeremy L Thompson 10339e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 10349e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 10359e9210b8SJeremy L Thompson 10369e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 10379e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 10389e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 10399e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 10409e9210b8SJeremy L Thompson 10419e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 10429e9210b8SJeremy L Thompson 10439e9210b8SJeremy L Thompson @ref User 10449e9210b8SJeremy L Thompson **/ 10459e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 10469e9210b8SJeremy L Thompson CeedRequest *request) { 10479e9210b8SJeremy L Thompson int ierr; 10489e9210b8SJeremy L Thompson Ceed ceed = op->ceed; 10499e9210b8SJeremy L Thompson ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 10509e9210b8SJeremy L Thompson 10519e9210b8SJeremy L Thompson // Use backend version, if available 10529e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 10539e9210b8SJeremy L Thompson ierr = op->LinearAssembleAddDiagonal(op, assembled, request); CeedChk(ierr); 10547172caadSjeremylt } else { 10557172caadSjeremylt // Fallback to reference Ceed 10567172caadSjeremylt if (!op->opfallback) { 10577172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1058b7ec98d8SJeremy L Thompson } 10597172caadSjeremylt // Assemble 10602bba3ffaSJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 10619e9210b8SJeremy L Thompson ierr = op->opfallback->LinearAssembleAddDiagonal(op->opfallback, assembled, 10627172caadSjeremylt request); CeedChk(ierr); 1063b7ec98d8SJeremy L Thompson } 1064b7ec98d8SJeremy L Thompson 1065b7ec98d8SJeremy L Thompson return 0; 1066b7ec98d8SJeremy L Thompson } 1067b7ec98d8SJeremy L Thompson 1068b7ec98d8SJeremy L Thompson /** 1069d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1070d965c7a7SJeremy L Thompson 10719e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1072d965c7a7SJeremy L Thompson CeedOperator. 1073d965c7a7SJeremy L Thompson 1074c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1075c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1076d965c7a7SJeremy L Thompson 1077d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1078d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1079d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1080d965c7a7SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 1081d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1082d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1083d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1084d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1085d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1086d965c7a7SJeremy L Thompson 1087d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1088d965c7a7SJeremy L Thompson 1089d965c7a7SJeremy L Thompson @ref User 1090d965c7a7SJeremy L Thompson **/ 109180ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 10922bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1093d965c7a7SJeremy L Thompson int ierr; 1094d965c7a7SJeremy L Thompson Ceed ceed = op->ceed; 1095d965c7a7SJeremy L Thompson ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1096d965c7a7SJeremy L Thompson 1097d965c7a7SJeremy L Thompson // Use backend version, if available 109880ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 109980ac2e43SJeremy L Thompson ierr = op->LinearAssemblePointBlockDiagonal(op, assembled, request); 1100d965c7a7SJeremy L Thompson CeedChk(ierr); 11019e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 11029e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11039e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 11049e9210b8SJeremy L Thompson request); 1105d965c7a7SJeremy L Thompson } else { 1106d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1107d965c7a7SJeremy L Thompson if (!op->opfallback) { 1108d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1109d965c7a7SJeremy L Thompson } 1110d965c7a7SJeremy L Thompson // Assemble 11119e9210b8SJeremy L Thompson if (op->opfallback->LinearAssemblePointBlockDiagonal) { 111280ac2e43SJeremy L Thompson ierr = op->opfallback->LinearAssemblePointBlockDiagonal(op->opfallback, 1113d965c7a7SJeremy L Thompson assembled, request); CeedChk(ierr); 11149e9210b8SJeremy L Thompson } else { 11159e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11169e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 11179e9210b8SJeremy L Thompson request); 11189e9210b8SJeremy L Thompson } 11199e9210b8SJeremy L Thompson } 11209e9210b8SJeremy L Thompson 11219e9210b8SJeremy L Thompson return 0; 11229e9210b8SJeremy L Thompson } 11239e9210b8SJeremy L Thompson 11249e9210b8SJeremy L Thompson /** 11259e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 11269e9210b8SJeremy L Thompson 11279e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 11289e9210b8SJeremy L Thompson CeedOperator. 11299e9210b8SJeremy L Thompson 11309e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 11319e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 11329e9210b8SJeremy L Thompson 11339e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11349e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 11359e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 11369e9210b8SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 11379e9210b8SJeremy L Thompson of this vector are derived from the active vector 11389e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 11399e9210b8SJeremy L Thompson [nodes, component out, component in]. 11409e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11419e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 11429e9210b8SJeremy L Thompson 11439e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11449e9210b8SJeremy L Thompson 11459e9210b8SJeremy L Thompson @ref User 11469e9210b8SJeremy L Thompson **/ 11479e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 11489e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 11499e9210b8SJeremy L Thompson int ierr; 11509e9210b8SJeremy L Thompson Ceed ceed = op->ceed; 11519e9210b8SJeremy L Thompson ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 11529e9210b8SJeremy L Thompson 11539e9210b8SJeremy L Thompson // Use backend version, if available 11549e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 11559e9210b8SJeremy L Thompson ierr = op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 11569e9210b8SJeremy L Thompson CeedChk(ierr); 11579e9210b8SJeremy L Thompson } else { 11589e9210b8SJeremy L Thompson // Fallback to reference Ceed 11599e9210b8SJeremy L Thompson if (!op->opfallback) { 11609e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11619e9210b8SJeremy L Thompson } 11629e9210b8SJeremy L Thompson // Assemble 11639e9210b8SJeremy L Thompson ierr = op->opfallback->LinearAssembleAddPointBlockDiagonal(op->opfallback, 11649e9210b8SJeremy L Thompson assembled, request); CeedChk(ierr); 1165d965c7a7SJeremy L Thompson } 1166d965c7a7SJeremy L Thompson 1167d965c7a7SJeremy L Thompson return 0; 1168d965c7a7SJeremy L Thompson } 1169d965c7a7SJeremy L Thompson 1170d965c7a7SJeremy L Thompson /** 1171*d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1172*d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1173*d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1174*d99fa3c5SJeremy L Thompson 1175*d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1176*d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1177*d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1178*d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1179*d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1180*d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1181*d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1182*d99fa3c5SJeremy L Thompson 1183*d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1184*d99fa3c5SJeremy L Thompson 1185*d99fa3c5SJeremy L Thompson @ref User 1186*d99fa3c5SJeremy L Thompson **/ 1187*d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreate(CeedOperator opFine, CeedVector PMultFine, 1188*d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1189*d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, CeedOperator *opProlong, CeedOperator *opRestrict) { 1190*d99fa3c5SJeremy L Thompson int ierr; 1191*d99fa3c5SJeremy L Thompson Ceed ceed; 1192*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1193*d99fa3c5SJeremy L Thompson 1194*d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1195*d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1196*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1197*d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1198*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1199*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1200*d99fa3c5SJeremy L Thompson if (Qf != Qc) 1201*d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1202*d99fa3c5SJeremy L Thompson return CeedError(ceed, 1, "Bases must have compatible quadrature spaces"); 1203*d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1204*d99fa3c5SJeremy L Thompson 1205*d99fa3c5SJeremy L Thompson // Coarse to fine basis 1206*d99fa3c5SJeremy L Thompson CeedInt Pf, Pc, Q = Qf; 1207*d99fa3c5SJeremy L Thompson bool isTensorF, isTensorC; 1208*d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisFine, &isTensorF); CeedChk(ierr); 1209*d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisCoarse, &isTensorC); CeedChk(ierr); 1210*d99fa3c5SJeremy L Thompson CeedScalar *interpC, *interpF, *interpCtoF, *tau; 1211*d99fa3c5SJeremy L Thompson if (isTensorF && isTensorC) { 1212*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &Pf); CeedChk(ierr); 1213*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisCoarse, &Pc); CeedChk(ierr); 1214*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basisCoarse, &Q); CeedChk(ierr); 1215*d99fa3c5SJeremy L Thompson } else if (!isTensorF && !isTensorC) { 1216*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &Pf); CeedChk(ierr); 1217*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisCoarse, &Pc); CeedChk(ierr); 1218*d99fa3c5SJeremy L Thompson } else { 1219*d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1220*d99fa3c5SJeremy L Thompson return CeedError(ceed, 1, "Bases must both be tensor or non-tensor"); 1221*d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1222*d99fa3c5SJeremy L Thompson } 1223*d99fa3c5SJeremy L Thompson 1224*d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pf, &interpF); CeedChk(ierr); 1225*d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pc, &interpC); CeedChk(ierr); 1226*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(Pc*Pf, &interpCtoF); CeedChk(ierr); 1227*d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1228*d99fa3c5SJeremy L Thompson if (isTensorF) { 1229*d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp1d, Q*Pf*sizeof basisFine->interp1d[0]); 1230*d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp1d, Q*Pc*sizeof basisCoarse->interp1d[0]); 1231*d99fa3c5SJeremy L Thompson } else { 1232*d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp, Q*Pf*sizeof basisFine->interp[0]); 1233*d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp, Q*Pc*sizeof basisCoarse->interp[0]); 1234*d99fa3c5SJeremy L Thompson } 1235*d99fa3c5SJeremy L Thompson 1236*d99fa3c5SJeremy L Thompson // -- QR Factorization, interpF = Q R 1237*d99fa3c5SJeremy L Thompson ierr = CeedQRFactorization(ceed, interpF, tau, Q, Pf); CeedChk(ierr); 1238*d99fa3c5SJeremy L Thompson 1239*d99fa3c5SJeremy L Thompson // -- Apply Qtranspose, interpC = Qtranspose interpC 1240*d99fa3c5SJeremy L Thompson CeedHouseholderApplyQ(interpC, interpF, tau, CEED_TRANSPOSE, 1241*d99fa3c5SJeremy L Thompson Q, Pc, Pf, Pc, 1); 1242*d99fa3c5SJeremy L Thompson 1243*d99fa3c5SJeremy L Thompson // -- Apply Rinv, interpCtoF = Rinv interpC 1244*d99fa3c5SJeremy L Thompson for (CeedInt j=0; j<Pc; j++) { // Column j 1245*d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*(Pf-1)] = interpC[j+Pc*(Pf-1)]/interpF[Pf*Pf-1]; 1246*d99fa3c5SJeremy L Thompson for (CeedInt i=Pf-2; i>=0; i--) { // Row i 1247*d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] = interpC[j+Pc*i]; 1248*d99fa3c5SJeremy L Thompson for (CeedInt k=i+1; k<Pf; k++) 1249*d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] -= interpF[k+Pf*i]*interpCtoF[j+Pc*k]; 1250*d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] /= interpF[i+Pf*i]; 1251*d99fa3c5SJeremy L Thompson } 1252*d99fa3c5SJeremy L Thompson } 1253*d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1254*d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpC); CeedChk(ierr); 1255*d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpF); CeedChk(ierr); 1256*d99fa3c5SJeremy L Thompson 1257*d99fa3c5SJeremy L Thompson // Fallback to interpCtoF versions of code 1258*d99fa3c5SJeremy L Thompson if (isTensorF) { 1259*d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateTensorH1(opFine, PMultFine, 1260*d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1261*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1262*d99fa3c5SJeremy L Thompson } else { 1263*d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateH1(opFine, PMultFine, 1264*d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1265*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1266*d99fa3c5SJeremy L Thompson } 1267*d99fa3c5SJeremy L Thompson 1268*d99fa3c5SJeremy L Thompson // Cleanup 1269*d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpCtoF); CeedChk(ierr); 1270*d99fa3c5SJeremy L Thompson return 0; 1271*d99fa3c5SJeremy L Thompson } 1272*d99fa3c5SJeremy L Thompson 1273*d99fa3c5SJeremy L Thompson /** 1274*d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1275*d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1276*d99fa3c5SJeremy L Thompson 1277*d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1278*d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1279*d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1280*d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1281*d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1282*d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1283*d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1284*d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1285*d99fa3c5SJeremy L Thompson 1286*d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1287*d99fa3c5SJeremy L Thompson 1288*d99fa3c5SJeremy L Thompson @ref User 1289*d99fa3c5SJeremy L Thompson **/ 1290*d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator opFine, 1291*d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1292*d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, CeedOperator *opCoarse, 1293*d99fa3c5SJeremy L Thompson CeedOperator *opProlong, CeedOperator *opRestrict) { 1294*d99fa3c5SJeremy L Thompson int ierr; 1295*d99fa3c5SJeremy L Thompson Ceed ceed; 1296*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1297*d99fa3c5SJeremy L Thompson 1298*d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1299*d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1300*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1301*d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1302*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1303*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1304*d99fa3c5SJeremy L Thompson if (Qf != Qc) 1305*d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1306*d99fa3c5SJeremy L Thompson return CeedError(ceed, 1, "Bases must have compatible quadrature spaces"); 1307*d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1308*d99fa3c5SJeremy L Thompson 1309*d99fa3c5SJeremy L Thompson // Coarse to fine basis 1310*d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, P1dFine, P1dCoarse; 1311*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1312*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1313*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &P1dFine); CeedChk(ierr); 1314*d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1315*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1316*d99fa3c5SJeremy L Thompson P1dCoarse = dim == 1 ? nnodesCoarse : 1317*d99fa3c5SJeremy L Thompson dim == 2 ? sqrt(nnodesCoarse) : 1318*d99fa3c5SJeremy L Thompson cbrt(nnodesCoarse); 1319*d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1320*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qref); CeedChk(ierr); 1321*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qweight); CeedChk(ierr); 1322*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine*P1dCoarse*dim, &grad); CeedChk(ierr); 1323*d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1324*d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1dCoarse, P1dFine, 1325*d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1326*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1327*d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1328*d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1329*d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1330*d99fa3c5SJeremy L Thompson 1331*d99fa3c5SJeremy L Thompson // Core code 1332*d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1333*d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1334*d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1335*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1336*d99fa3c5SJeremy L Thompson return 0; 1337*d99fa3c5SJeremy L Thompson } 1338*d99fa3c5SJeremy L Thompson 1339*d99fa3c5SJeremy L Thompson /** 1340*d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1341*d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 1342*d99fa3c5SJeremy L Thompson 1343*d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1344*d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1345*d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1346*d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1347*d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1348*d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1349*d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1350*d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1351*d99fa3c5SJeremy L Thompson 1352*d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1353*d99fa3c5SJeremy L Thompson 1354*d99fa3c5SJeremy L Thompson @ref User 1355*d99fa3c5SJeremy L Thompson **/ 1356*d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateH1(CeedOperator opFine, 1357*d99fa3c5SJeremy L Thompson CeedVector PMultFine, 1358*d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, 1359*d99fa3c5SJeremy L Thompson CeedBasis basisCoarse, 1360*d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, 1361*d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, 1362*d99fa3c5SJeremy L Thompson CeedOperator *opProlong, 1363*d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 1364*d99fa3c5SJeremy L Thompson int ierr; 1365*d99fa3c5SJeremy L Thompson Ceed ceed; 1366*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1367*d99fa3c5SJeremy L Thompson 1368*d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1369*d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1370*d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1371*d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1372*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1373*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1374*d99fa3c5SJeremy L Thompson if (Qf != Qc) 1375*d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1376*d99fa3c5SJeremy L Thompson return CeedError(ceed, 1, "Bases must have compatible quadrature spaces"); 1377*d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1378*d99fa3c5SJeremy L Thompson 1379*d99fa3c5SJeremy L Thompson // Coarse to fine basis 1380*d99fa3c5SJeremy L Thompson CeedElemTopology topo; 1381*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetTopology(basisFine, &topo); CeedChk(ierr); 1382*d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, nnodesFine; 1383*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1384*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1385*d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &nnodesFine); CeedChk(ierr); 1386*d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1387*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1388*d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1389*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qref); CeedChk(ierr); 1390*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qweight); CeedChk(ierr); 1391*d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine*nnodesCoarse*dim, &grad); CeedChk(ierr); 1392*d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1393*d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateH1(ceed, topo, ncomp, nnodesCoarse, nnodesFine, 1394*d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1395*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1396*d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1397*d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1398*d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1399*d99fa3c5SJeremy L Thompson 1400*d99fa3c5SJeremy L Thompson // Core code 1401*d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1402*d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1403*d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1404*d99fa3c5SJeremy L Thompson CeedChk(ierr); 1405*d99fa3c5SJeremy L Thompson return 0; 1406*d99fa3c5SJeremy L Thompson } 1407*d99fa3c5SJeremy L Thompson 1408*d99fa3c5SJeremy L Thompson /** 14093bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 14103bd813ffSjeremylt CeedOperator 14113bd813ffSjeremylt 14123bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 14133bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 14143bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 14153bd813ffSjeremylt M = V^T V, K = V^T S V. 14163bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 14173bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 14183bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 14193bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 14203bd813ffSjeremylt 14213bd813ffSjeremylt @param op CeedOperator to create element inverses 14223bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 14233bd813ffSjeremylt for each element 14243bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 14254cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 14263bd813ffSjeremylt 14273bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 14283bd813ffSjeremylt 14297a982d89SJeremy L. Thompson @ref Backend 14303bd813ffSjeremylt **/ 14313bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 14323bd813ffSjeremylt CeedRequest *request) { 14333bd813ffSjeremylt int ierr; 14343bd813ffSjeremylt Ceed ceed = op->ceed; 1435713f43c3Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 14363bd813ffSjeremylt 1437713f43c3Sjeremylt // Use backend version, if available 1438713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 1439713f43c3Sjeremylt ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr); 1440713f43c3Sjeremylt } else { 1441713f43c3Sjeremylt // Fallback to reference Ceed 1442713f43c3Sjeremylt if (!op->opfallback) { 1443713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 14443bd813ffSjeremylt } 1445713f43c3Sjeremylt // Assemble 1446713f43c3Sjeremylt ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv, 14473bd813ffSjeremylt request); CeedChk(ierr); 14483bd813ffSjeremylt } 14493bd813ffSjeremylt 14503bd813ffSjeremylt return 0; 14513bd813ffSjeremylt } 14523bd813ffSjeremylt 14537a982d89SJeremy L. Thompson /** 14547a982d89SJeremy L. Thompson @brief View a CeedOperator 14557a982d89SJeremy L. Thompson 14567a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 14577a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 14587a982d89SJeremy L. Thompson 14597a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 14607a982d89SJeremy L. Thompson 14617a982d89SJeremy L. Thompson @ref User 14627a982d89SJeremy L. Thompson **/ 14637a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 14647a982d89SJeremy L. Thompson int ierr; 14657a982d89SJeremy L. Thompson 14667a982d89SJeremy L. Thompson if (op->composite) { 14677a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 14687a982d89SJeremy L. Thompson 14697a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->numsub; i++) { 14707a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 14717a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 14727a982d89SJeremy L. Thompson CeedChk(ierr); 14737a982d89SJeremy L. Thompson } 14747a982d89SJeremy L. Thompson } else { 14757a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 14767a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 14777a982d89SJeremy L. Thompson } 14787a982d89SJeremy L. Thompson 14797a982d89SJeremy L. Thompson return 0; 14807a982d89SJeremy L. Thompson } 14813bd813ffSjeremylt 14823bd813ffSjeremylt /** 14833bd813ffSjeremylt @brief Apply CeedOperator to a vector 1484d7b241e6Sjeremylt 1485d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 1486d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 1487d7b241e6Sjeremylt CeedOperatorSetField(). 1488d7b241e6Sjeremylt 1489d7b241e6Sjeremylt @param op CeedOperator to apply 14904cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 149134138859Sjeremylt there are no active inputs 1492b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 14934cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 149434138859Sjeremylt active outputs 1495d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 14964cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1497b11c1e72Sjeremylt 1498b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1499dfdf5a53Sjeremylt 15007a982d89SJeremy L. Thompson @ref User 1501b11c1e72Sjeremylt **/ 1502692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 1503692c2638Sjeremylt CeedRequest *request) { 1504d7b241e6Sjeremylt int ierr; 1505d7b241e6Sjeremylt Ceed ceed = op->ceed; 1506250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1507d7b241e6Sjeremylt 1508250756a7Sjeremylt if (op->numelements) { 1509250756a7Sjeremylt // Standard Operator 1510cae8b89aSjeremylt if (op->Apply) { 1511250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 1512cae8b89aSjeremylt } else { 1513cae8b89aSjeremylt // Zero all output vectors 1514250756a7Sjeremylt CeedQFunction qf = op->qf; 1515cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 1516cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 1517cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 1518cae8b89aSjeremylt vec = out; 1519cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 1520cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1521cae8b89aSjeremylt } 1522cae8b89aSjeremylt } 1523250756a7Sjeremylt // Apply 1524250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1525250756a7Sjeremylt } 1526250756a7Sjeremylt } else if (op->composite) { 1527250756a7Sjeremylt // Composite Operator 1528250756a7Sjeremylt if (op->ApplyComposite) { 1529250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 1530250756a7Sjeremylt } else { 1531250756a7Sjeremylt CeedInt numsub; 1532250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1533250756a7Sjeremylt CeedOperator *suboperators; 1534250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1535250756a7Sjeremylt 1536250756a7Sjeremylt // Zero all output vectors 1537250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 1538cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 1539cae8b89aSjeremylt } 1540250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 1541250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 1542250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 1543250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 1544250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 1545250756a7Sjeremylt } 1546250756a7Sjeremylt } 1547250756a7Sjeremylt } 1548250756a7Sjeremylt // Apply 1549250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 1550250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 1551cae8b89aSjeremylt CeedChk(ierr); 1552cae8b89aSjeremylt } 1553cae8b89aSjeremylt } 1554250756a7Sjeremylt } 1555250756a7Sjeremylt 1556cae8b89aSjeremylt return 0; 1557cae8b89aSjeremylt } 1558cae8b89aSjeremylt 1559cae8b89aSjeremylt /** 1560cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 1561cae8b89aSjeremylt 1562cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 1563cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 1564cae8b89aSjeremylt CeedOperatorSetField(). 1565cae8b89aSjeremylt 1566cae8b89aSjeremylt @param op CeedOperator to apply 1567cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 1568cae8b89aSjeremylt active inputs 1569cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 1570cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 1571cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 15724cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1573cae8b89aSjeremylt 1574cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 1575cae8b89aSjeremylt 15767a982d89SJeremy L. Thompson @ref User 1577cae8b89aSjeremylt **/ 1578cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 1579cae8b89aSjeremylt CeedRequest *request) { 1580cae8b89aSjeremylt int ierr; 1581cae8b89aSjeremylt Ceed ceed = op->ceed; 1582250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 1583cae8b89aSjeremylt 1584250756a7Sjeremylt if (op->numelements) { 1585250756a7Sjeremylt // Standard Operator 1586250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 1587250756a7Sjeremylt } else if (op->composite) { 1588250756a7Sjeremylt // Composite Operator 1589250756a7Sjeremylt if (op->ApplyAddComposite) { 1590250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 1591cae8b89aSjeremylt } else { 1592250756a7Sjeremylt CeedInt numsub; 1593250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1594250756a7Sjeremylt CeedOperator *suboperators; 1595250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1596250756a7Sjeremylt 1597250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 1598250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 1599cae8b89aSjeremylt CeedChk(ierr); 16001d7d2407SJeremy L Thompson } 1601250756a7Sjeremylt } 1602250756a7Sjeremylt } 1603250756a7Sjeremylt 1604d7b241e6Sjeremylt return 0; 1605d7b241e6Sjeremylt } 1606d7b241e6Sjeremylt 1607d7b241e6Sjeremylt /** 1608b11c1e72Sjeremylt @brief Destroy a CeedOperator 1609d7b241e6Sjeremylt 1610d7b241e6Sjeremylt @param op CeedOperator to destroy 1611b11c1e72Sjeremylt 1612b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1613dfdf5a53Sjeremylt 16147a982d89SJeremy L. Thompson @ref User 1615b11c1e72Sjeremylt **/ 1616d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1617d7b241e6Sjeremylt int ierr; 1618d7b241e6Sjeremylt 1619d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 1620d7b241e6Sjeremylt if ((*op)->Destroy) { 1621d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1622d7b241e6Sjeremylt } 1623fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1624fe2413ffSjeremylt // Free fields 16251d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 162652d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 162715910d16Sjeremylt if ((*op)->inputfields[i]->Erestrict != CEED_ELEMRESTRICTION_NONE) { 162871352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 162971352a93Sjeremylt CeedChk(ierr); 163015910d16Sjeremylt } 163171352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 163271352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 163371352a93Sjeremylt } 163471352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 163571352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 163671352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 163771352a93Sjeremylt } 1638*d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->inputfields[i]->fieldname); CeedChk(ierr); 1639fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 1640fe2413ffSjeremylt } 16411d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 1642d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 164371352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 164471352a93Sjeremylt CeedChk(ierr); 164571352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 164671352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 164771352a93Sjeremylt } 164871352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 164971352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 165071352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 165171352a93Sjeremylt } 1652*d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->outputfields[i]->fieldname); CeedChk(ierr); 1653fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1654fe2413ffSjeremylt } 165552d6035fSJeremy L Thompson // Destroy suboperators 16561d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 165752d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 165852d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 165952d6035fSJeremy L Thompson } 1660d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1661d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1662d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1663fe2413ffSjeremylt 16645107b09fSJeremy L Thompson // Destroy fallback 16655107b09fSJeremy L Thompson if ((*op)->opfallback) { 16665107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 16675107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 16685107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 16695107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 16705107b09fSJeremy L Thompson } 16715107b09fSJeremy L Thompson 1672fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1673fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 167452d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1675d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1676d7b241e6Sjeremylt return 0; 1677d7b241e6Sjeremylt } 1678d7b241e6Sjeremylt 1679d7b241e6Sjeremylt /// @} 1680