18a820b8eSToby Isaac 28a820b8eSToby Isaac #include <petscfe.h> 38a820b8eSToby Isaac #include <petscdmplex.h> 48a820b8eSToby Isaac #include <petsc/private/hashmap.h> 58a820b8eSToby Isaac #include <petsc/private/dmpleximpl.h> 68a820b8eSToby Isaac #include <petsc/private/petscfeimpl.h> 78a820b8eSToby Isaac 88a820b8eSToby Isaac const char help[] = "Test PETSCDUALSPACELAGRANGE\n"; 98a820b8eSToby Isaac 109371c9d4SSatish Balay typedef struct _PetscHashLagKey { 118a820b8eSToby Isaac PetscInt dim; 128a820b8eSToby Isaac PetscInt order; 138a820b8eSToby Isaac PetscInt formDegree; 148a820b8eSToby Isaac PetscBool trimmed; 156ff15688SToby Isaac PetscInt tensor; 168a820b8eSToby Isaac PetscBool continuous; 178a820b8eSToby Isaac } PetscHashLagKey; 188a820b8eSToby Isaac 198a820b8eSToby Isaac #define PetscHashLagKeyHash(key) \ 209371c9d4SSatish Balay PetscHashCombine(PetscHashCombine(PetscHashCombine(PetscHashInt((key).dim), PetscHashInt((key).order)), PetscHashInt((key).formDegree)), PetscHashCombine(PetscHashCombine(PetscHashInt((key).trimmed), PetscHashInt((key).tensor)), PetscHashInt((key).continuous))) 218a820b8eSToby Isaac 228a820b8eSToby Isaac #define PetscHashLagKeyEqual(k1, k2) \ 239371c9d4SSatish Balay (((k1).dim == (k2).dim) ? ((k1).order == (k2).order) ? ((k1).formDegree == (k2).formDegree) ? ((k1).trimmed == (k2).trimmed) ? ((k1).tensor == (k2).tensor) ? ((k1).continuous == (k2).continuous) : 0 : 0 : 0 : 0 : 0) 248a820b8eSToby Isaac 258a820b8eSToby Isaac PETSC_HASH_MAP(HashLag, PetscHashLagKey, PetscInt, PetscHashLagKeyHash, PetscHashLagKeyEqual, 0) 268a820b8eSToby Isaac 278a820b8eSToby Isaac static PetscErrorCode ExpectedNumDofs_Total(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs); 288a820b8eSToby Isaac static PetscErrorCode ExpectedNumDofs_Interior(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs); 298a820b8eSToby Isaac 30*d71ae5a4SJacob Faibussowitsch static PetscErrorCode ExpectedNumDofs_Total(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs) 31*d71ae5a4SJacob Faibussowitsch { 328a820b8eSToby Isaac PetscFunctionBegin; 338a820b8eSToby Isaac formDegree = PetscAbsInt(formDegree); 348a820b8eSToby Isaac /* see femtable.org for the source of most of these values */ 358a820b8eSToby Isaac *nDofs = -1; 368a820b8eSToby Isaac if (tensor == 0) { /* simplex spaces */ 378a820b8eSToby Isaac if (trimmed) { 388a820b8eSToby Isaac PetscInt rnchooserk; 398a820b8eSToby Isaac PetscInt rkm1choosek; 408a820b8eSToby Isaac 419566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(order + dim, order + formDegree, &rnchooserk)); 429566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(order + formDegree - 1, formDegree, &rkm1choosek)); 438a820b8eSToby Isaac *nDofs = rnchooserk * rkm1choosek * nCopies; 448a820b8eSToby Isaac } else { 458a820b8eSToby Isaac PetscInt rnchooserk; 468a820b8eSToby Isaac PetscInt rkchoosek; 478a820b8eSToby Isaac 489566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(order + dim, order + formDegree, &rnchooserk)); 499566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(order + formDegree, formDegree, &rkchoosek)); 508a820b8eSToby Isaac *nDofs = rnchooserk * rkchoosek * nCopies; 518a820b8eSToby Isaac } 528a820b8eSToby Isaac } else if (tensor == 1) { /* hypercubes */ 538a820b8eSToby Isaac if (trimmed) { 548a820b8eSToby Isaac PetscInt nchoosek; 558a820b8eSToby Isaac PetscInt rpowk, rp1pownmk; 568a820b8eSToby Isaac 579566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, formDegree, &nchoosek)); 582f613bf5SBarry Smith rpowk = PetscPowInt(order, formDegree); 592f613bf5SBarry Smith rp1pownmk = PetscPowInt(order + 1, dim - formDegree); 608a820b8eSToby Isaac *nDofs = nchoosek * rpowk * rp1pownmk * nCopies; 618a820b8eSToby Isaac } else { 628a820b8eSToby Isaac PetscInt nchoosek; 638a820b8eSToby Isaac PetscInt rp1pown; 648a820b8eSToby Isaac 659566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, formDegree, &nchoosek)); 662f613bf5SBarry Smith rp1pown = PetscPowInt(order + 1, dim); 678a820b8eSToby Isaac *nDofs = nchoosek * rp1pown * nCopies; 688a820b8eSToby Isaac } 698a820b8eSToby Isaac } else { /* prism */ 708a820b8eSToby Isaac PetscInt tracek = 0; 718a820b8eSToby Isaac PetscInt tracekm1 = 0; 728a820b8eSToby Isaac PetscInt fiber0 = 0; 738a820b8eSToby Isaac PetscInt fiber1 = 0; 748a820b8eSToby Isaac 758a820b8eSToby Isaac if (formDegree < dim) { 769566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Total(dim - 1, order, formDegree, trimmed, 0, 1, &tracek)); 779566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Total(1, order, 0, trimmed, 0, 1, &fiber0)); 788a820b8eSToby Isaac } 798a820b8eSToby Isaac if (formDegree > 0) { 809566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Total(dim - 1, order, formDegree - 1, trimmed, 0, 1, &tracekm1)); 819566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Total(1, order, 1, trimmed, 0, 1, &fiber1)); 828a820b8eSToby Isaac } 838a820b8eSToby Isaac *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies; 848a820b8eSToby Isaac } 858a820b8eSToby Isaac PetscFunctionReturn(0); 868a820b8eSToby Isaac } 878a820b8eSToby Isaac 88*d71ae5a4SJacob Faibussowitsch static PetscErrorCode ExpectedNumDofs_Interior(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs) 89*d71ae5a4SJacob Faibussowitsch { 908a820b8eSToby Isaac PetscFunctionBegin; 918a820b8eSToby Isaac formDegree = PetscAbsInt(formDegree); 928a820b8eSToby Isaac /* see femtable.org for the source of most of these values */ 938a820b8eSToby Isaac *nDofs = -1; 948a820b8eSToby Isaac if (tensor == 0) { /* simplex spaces */ 958a820b8eSToby Isaac if (trimmed) { 968a820b8eSToby Isaac if (order + formDegree > dim) { 978a820b8eSToby Isaac PetscInt eorder = order + formDegree - dim - 1; 988a820b8eSToby Isaac PetscInt eformDegree = dim - formDegree; 998a820b8eSToby Isaac PetscInt rnchooserk; 1008a820b8eSToby Isaac PetscInt rkchoosek; 1018a820b8eSToby Isaac 1029566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(eorder + dim, eorder + eformDegree, &rnchooserk)); 1039566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(eorder + eformDegree, eformDegree, &rkchoosek)); 1048a820b8eSToby Isaac *nDofs = rnchooserk * rkchoosek * nCopies; 1058a820b8eSToby Isaac } else { 1068a820b8eSToby Isaac *nDofs = 0; 1078a820b8eSToby Isaac } 1088a820b8eSToby Isaac 1098a820b8eSToby Isaac } else { 1108a820b8eSToby Isaac if (order + formDegree > dim) { 1118a820b8eSToby Isaac PetscInt eorder = order + formDegree - dim; 1128a820b8eSToby Isaac PetscInt eformDegree = dim - formDegree; 1138a820b8eSToby Isaac PetscInt rnchooserk; 1148a820b8eSToby Isaac PetscInt rkm1choosek; 1158a820b8eSToby Isaac 1169566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(eorder + dim, eorder + eformDegree, &rnchooserk)); 1179566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(eorder + eformDegree - 1, eformDegree, &rkm1choosek)); 1188a820b8eSToby Isaac *nDofs = rnchooserk * rkm1choosek * nCopies; 1198a820b8eSToby Isaac } else { 1208a820b8eSToby Isaac *nDofs = 0; 1218a820b8eSToby Isaac } 1228a820b8eSToby Isaac } 1238a820b8eSToby Isaac } else if (tensor == 1) { /* hypercubes */ 1248a820b8eSToby Isaac if (dim < 2) { 1259566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(dim, order, formDegree, trimmed, 0, nCopies, nDofs)); 1268a820b8eSToby Isaac } else { 1278a820b8eSToby Isaac PetscInt tracek = 0; 1288a820b8eSToby Isaac PetscInt tracekm1 = 0; 1298a820b8eSToby Isaac PetscInt fiber0 = 0; 1308a820b8eSToby Isaac PetscInt fiber1 = 0; 1318a820b8eSToby Isaac 1328a820b8eSToby Isaac if (formDegree < dim) { 1339566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree, trimmed, dim > 2 ? 1 : 0, 1, &tracek)); 1349566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(1, order, 0, trimmed, 0, 1, &fiber0)); 1358a820b8eSToby Isaac } 1368a820b8eSToby Isaac if (formDegree > 0) { 1379566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree - 1, trimmed, dim > 2 ? 1 : 0, 1, &tracekm1)); 1389566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(1, order, 1, trimmed, 0, 1, &fiber1)); 1398a820b8eSToby Isaac } 1408a820b8eSToby Isaac *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies; 1418a820b8eSToby Isaac } 1428a820b8eSToby Isaac } else { /* prism */ 1438a820b8eSToby Isaac PetscInt tracek = 0; 1448a820b8eSToby Isaac PetscInt tracekm1 = 0; 1458a820b8eSToby Isaac PetscInt fiber0 = 0; 1468a820b8eSToby Isaac PetscInt fiber1 = 0; 1478a820b8eSToby Isaac 1488a820b8eSToby Isaac if (formDegree < dim) { 1499566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree, trimmed, 0, 1, &tracek)); 1509566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(1, order, 0, trimmed, 0, 1, &fiber0)); 1518a820b8eSToby Isaac } 1528a820b8eSToby Isaac if (formDegree > 0) { 1539566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree - 1, trimmed, 0, 1, &tracekm1)); 1549566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(1, order, 1, trimmed, 0, 1, &fiber1)); 1558a820b8eSToby Isaac } 1568a820b8eSToby Isaac *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies; 1578a820b8eSToby Isaac } 1588a820b8eSToby Isaac PetscFunctionReturn(0); 1598a820b8eSToby Isaac } 1608a820b8eSToby Isaac 161*d71ae5a4SJacob Faibussowitsch PetscErrorCode testLagrange(PetscHashLag lagTable, DM K, PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscBool continuous, PetscInt nCopies) 162*d71ae5a4SJacob Faibussowitsch { 1638a820b8eSToby Isaac PetscDualSpace sp; 1648a820b8eSToby Isaac MPI_Comm comm = PETSC_COMM_SELF; 1658a820b8eSToby Isaac PetscInt Nk; 1668a820b8eSToby Isaac PetscHashLagKey key; 1678a820b8eSToby Isaac PetscHashIter iter; 1688a820b8eSToby Isaac PetscBool missing; 1698a820b8eSToby Isaac PetscInt spdim, spintdim, exspdim, exspintdim; 1708a820b8eSToby Isaac 1718a820b8eSToby Isaac PetscFunctionBegin; 1729566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(formDegree), &Nk)); 1739566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &sp)); 1749566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, PETSCDUALSPACELAGRANGE)); 1759566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K)); 1769566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(sp, order)); 1779566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFormDegree(sp, formDegree)); 1789566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(sp, nCopies * Nk)); 1799566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(sp, continuous)); 1809566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(sp, (PetscBool)tensor)); 1819566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTrimmed(sp, trimmed)); 18263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Input: dim %" PetscInt_FMT ", order %" PetscInt_FMT ", trimmed %" PetscInt_FMT ", tensor %" PetscInt_FMT ", continuous %" PetscInt_FMT ", formDegree %" PetscInt_FMT ", nCopies %" PetscInt_FMT "\n", dim, order, (PetscInt)trimmed, tensor, (PetscInt)continuous, formDegree, nCopies)); 1839566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Total(dim, order, formDegree, trimmed, tensor, nCopies, &exspdim)); 1848a820b8eSToby Isaac if (continuous && dim > 0 && order > 0) { 1859566063dSJacob Faibussowitsch PetscCall(ExpectedNumDofs_Interior(dim, order, formDegree, trimmed, tensor, nCopies, &exspintdim)); 1868a820b8eSToby Isaac } else { 1878a820b8eSToby Isaac exspintdim = exspdim; 1888a820b8eSToby Isaac } 1899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(sp)); 1909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim)); 1919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(sp, &spintdim)); 19263a3b9bcSJacob Faibussowitsch PetscCheck(spdim == exspdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected dual space dimension %" PetscInt_FMT ", got %" PetscInt_FMT, exspdim, spdim); 19363a3b9bcSJacob Faibussowitsch PetscCheck(spintdim == exspintdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected dual space interior dimension %" PetscInt_FMT ", got %" PetscInt_FMT, exspintdim, spintdim); 1948a820b8eSToby Isaac key.dim = dim; 1958a820b8eSToby Isaac key.formDegree = formDegree; 1969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetOrder(sp, &key.order)); 1979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeGetContinuity(sp, &key.continuous)); 1988a820b8eSToby Isaac if (tensor == 2) { 1998a820b8eSToby Isaac key.tensor = 2; 2008a820b8eSToby Isaac } else { 2016ff15688SToby Isaac PetscBool bTensor; 2026ff15688SToby Isaac 2039566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeGetTensor(sp, &bTensor)); 2046ff15688SToby Isaac key.tensor = bTensor; 2058a820b8eSToby Isaac } 2069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeGetTrimmed(sp, &key.trimmed)); 20763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "After setup: order %" PetscInt_FMT ", trimmed %" PetscInt_FMT ", tensor %" PetscInt_FMT ", continuous %" PetscInt_FMT "\n", key.order, (PetscInt)key.trimmed, key.tensor, (PetscInt)key.continuous)); 2089566063dSJacob Faibussowitsch PetscCall(PetscHashLagPut(lagTable, key, &iter, &missing)); 2098a820b8eSToby Isaac if (missing) { 2108a820b8eSToby Isaac DMPolytopeType type; 2118a820b8eSToby Isaac 2129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, 0, &type)); 21363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "New space: %s, order %" PetscInt_FMT ", trimmed %" PetscInt_FMT ", tensor %" PetscInt_FMT ", continuous %" PetscInt_FMT ", form degree %" PetscInt_FMT "\n", DMPolytopeTypes[type], order, (PetscInt)trimmed, tensor, (PetscInt)continuous, formDegree)); 2149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF)); 2158a820b8eSToby Isaac { 2168a820b8eSToby Isaac PetscQuadrature intNodes, allNodes; 2178a820b8eSToby Isaac Mat intMat, allMat; 2188a820b8eSToby Isaac MatInfo info; 2198a820b8eSToby Isaac PetscInt i, j, nodeIdxDim, nodeVecDim, nNodes; 2208a820b8eSToby Isaac const PetscInt *nodeIdx; 2218a820b8eSToby Isaac const PetscReal *nodeVec; 2228a820b8eSToby Isaac 2238a820b8eSToby Isaac PetscDualSpace_Lag *lag = (PetscDualSpace_Lag *)sp->data; 2248a820b8eSToby Isaac 2259566063dSJacob Faibussowitsch PetscCall(PetscLagNodeIndicesGetData_Internal(lag->allNodeIndices, &nodeIdxDim, &nodeVecDim, &nNodes, &nodeIdx, &nodeVec)); 22608401ef6SPierre Jolivet PetscCheck(nodeVecDim == Nk, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect nodeVecDim"); 22708401ef6SPierre Jolivet PetscCheck(nNodes == spdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect nNodes"); 2288a820b8eSToby Isaac 2299566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, &allNodes, &allMat)); 2308a820b8eSToby Isaac 2319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All nodes:\n")); 2329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF)); 2339566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(allNodes, PETSC_VIEWER_STDOUT_SELF)); 2349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF)); 2359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All node indices:\n")); 2368a820b8eSToby Isaac for (i = 0; i < spdim; i++) { 2379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "(")); 23848a46eb9SPierre Jolivet for (j = 0; j < nodeIdxDim; j++) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT ",", nodeIdx[i * nodeIdxDim + j])); 2399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "): [")); 24048a46eb9SPierre Jolivet for (j = 0; j < nodeVecDim; j++) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g,", (double)nodeVec[i * nodeVecDim + j])); 2419566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n")); 2428a820b8eSToby Isaac } 2438a820b8eSToby Isaac 2449566063dSJacob Faibussowitsch PetscCall(MatGetInfo(allMat, MAT_LOCAL, &info)); 24563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All matrix: %" PetscInt_FMT " nonzeros\n", (PetscInt)info.nz_used)); 2468a820b8eSToby Isaac 2479566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, &intNodes, &intMat)); 2488a820b8eSToby Isaac if (intMat && intMat != allMat) { 2498a820b8eSToby Isaac PetscInt intNodeIdxDim, intNodeVecDim, intNnodes; 2508a820b8eSToby Isaac const PetscInt *intNodeIdx; 2518a820b8eSToby Isaac const PetscReal *intNodeVec; 2528a820b8eSToby Isaac PetscBool same; 2538a820b8eSToby Isaac 2549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior nodes:\n")); 2559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF)); 2569566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(intNodes, PETSC_VIEWER_STDOUT_SELF)); 2579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF)); 2588a820b8eSToby Isaac 2599566063dSJacob Faibussowitsch PetscCall(MatGetInfo(intMat, MAT_LOCAL, &info)); 26063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior matrix: %" PetscInt_FMT " nonzeros\n", (PetscInt)info.nz_used)); 2619566063dSJacob Faibussowitsch PetscCall(PetscLagNodeIndicesGetData_Internal(lag->intNodeIndices, &intNodeIdxDim, &intNodeVecDim, &intNnodes, &intNodeIdx, &intNodeVec)); 2621dca8a05SBarry Smith PetscCheck(intNodeIdxDim == nodeIdxDim && intNodeVecDim == nodeVecDim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices not the same shale as all node indices"); 26308401ef6SPierre Jolivet PetscCheck(intNnodes == spintdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect interior nNodes"); 2649566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(intNodeIdx, nodeIdx, nodeIdxDim * intNnodes, &same)); 26528b400f6SJacob Faibussowitsch PetscCheck(same, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices not the same as start of all node indices"); 2669566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(intNodeVec, nodeVec, nodeVecDim * intNnodes, &same)); 26728b400f6SJacob Faibussowitsch PetscCheck(same, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node vectors not the same as start of all node vectors"); 2688a820b8eSToby Isaac } else if (intMat) { 2699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior data is the same as all data\n")); 27008401ef6SPierre Jolivet PetscCheck(intNodes == allNodes, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior nodes should be the same as all nodes"); 27108401ef6SPierre Jolivet PetscCheck(lag->intNodeIndices == lag->allNodeIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices should be the same as all node indices"); 2728a820b8eSToby Isaac } 2738a820b8eSToby Isaac } 2748a820b8eSToby Isaac if (dim <= 2 && spintdim) { 275b5a892a1SMatthew G. Knepley PetscInt numFaces, o; 2768a820b8eSToby Isaac 277b5a892a1SMatthew G. Knepley { 278b5a892a1SMatthew G. Knepley DMPolytopeType ct; 279b5a892a1SMatthew G. Knepley /* The number of arrangements is no longer based on the number of faces */ 2809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, 0, &ct)); 281b5a892a1SMatthew G. Knepley numFaces = DMPolytopeTypeGetNumArrangments(ct) / 2; 282b5a892a1SMatthew G. Knepley } 283b5a892a1SMatthew G. Knepley for (o = -numFaces; o < numFaces; ++o) { 2848a820b8eSToby Isaac Mat symMat; 2858a820b8eSToby Isaac 2869566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreateInteriorSymmetryMatrix_Lagrange(sp, o, &symMat)); 28763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior node symmetry matrix for orientation %" PetscInt_FMT ":\n", o)); 2889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF)); 2899566063dSJacob Faibussowitsch PetscCall(MatView(symMat, PETSC_VIEWER_STDOUT_SELF)); 2909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF)); 2919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&symMat)); 2928a820b8eSToby Isaac } 2938a820b8eSToby Isaac } 2949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF)); 2958a820b8eSToby Isaac } 2969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&sp)); 2978a820b8eSToby Isaac PetscFunctionReturn(0); 2988a820b8eSToby Isaac } 2998a820b8eSToby Isaac 300*d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 301*d71ae5a4SJacob Faibussowitsch { 3028a820b8eSToby Isaac PetscInt dim; 3038a820b8eSToby Isaac PetscHashLag lagTable; 3048a820b8eSToby Isaac PetscInt tensorCell; 3058a820b8eSToby Isaac PetscInt order, ordermin, ordermax; 3068a820b8eSToby Isaac PetscBool continuous; 3078a820b8eSToby Isaac PetscBool trimmed; 3088a820b8eSToby Isaac DM dm; 3098a820b8eSToby Isaac 310327415f7SBarry Smith PetscFunctionBeginUser; 3119566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 3128a820b8eSToby Isaac dim = 3; 3138a820b8eSToby Isaac tensorCell = 0; 3148a820b8eSToby Isaac continuous = PETSC_FALSE; 3158a820b8eSToby Isaac trimmed = PETSC_FALSE; 316d0609cedSBarry Smith PetscOptionsBegin(PETSC_COMM_WORLD, "", "Options for PETSCDUALSPACELAGRANGE test", "none"); 3179566063dSJacob Faibussowitsch PetscCall(PetscOptionsRangeInt("-dim", "The spatial dimension", "ex1.c", dim, &dim, NULL, 0, 3)); 3189566063dSJacob Faibussowitsch PetscCall(PetscOptionsRangeInt("-tensor", "(0) simplex (1) hypercube (2) wedge", "ex1.c", tensorCell, &tensorCell, NULL, 0, 2)); 3199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-continuous", "Whether the dual space has continuity", "ex1.c", continuous, &continuous, NULL)); 3209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-trimmed", "Whether the dual space matches a trimmed polynomial space", "ex1.c", trimmed, &trimmed, NULL)); 321d0609cedSBarry Smith PetscOptionsEnd(); 3229566063dSJacob Faibussowitsch PetscCall(PetscHashLagCreate(&lagTable)); 3238a820b8eSToby Isaac 3248a820b8eSToby Isaac if (tensorCell < 2) { 3259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, (PetscBool)!tensorCell), &dm)); 3268a820b8eSToby Isaac } else { 3279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DM_POLYTOPE_TRI_PRISM, &dm)); 3288a820b8eSToby Isaac } 3298a820b8eSToby Isaac ordermin = trimmed ? 1 : 0; 3308a820b8eSToby Isaac ordermax = tensorCell == 2 ? 4 : tensorCell == 1 ? 3 : dim + 2; 3318a820b8eSToby Isaac for (order = ordermin; order <= ordermax; order++) { 3328a820b8eSToby Isaac PetscInt formDegree; 3338a820b8eSToby Isaac 3348a820b8eSToby Isaac for (formDegree = PetscMin(0, -dim + 1); formDegree <= dim; formDegree++) { 3358a820b8eSToby Isaac PetscInt nCopies; 3368a820b8eSToby Isaac 33748a46eb9SPierre Jolivet for (nCopies = 1; nCopies <= 3; nCopies++) PetscCall(testLagrange(lagTable, dm, dim, order, formDegree, trimmed, (PetscBool)tensorCell, continuous, nCopies)); 3388a820b8eSToby Isaac } 3398a820b8eSToby Isaac } 3409566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 3419566063dSJacob Faibussowitsch PetscCall(PetscHashLagDestroy(&lagTable)); 3429566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 343b122ec5aSJacob Faibussowitsch return 0; 3448a820b8eSToby Isaac } 3458a820b8eSToby Isaac 3468a820b8eSToby Isaac /*TEST 3478a820b8eSToby Isaac 3488a820b8eSToby Isaac test: 3498a820b8eSToby Isaac suffix: 0 3508a820b8eSToby Isaac args: -dim 0 3518a820b8eSToby Isaac 3528a820b8eSToby Isaac test: 3538a820b8eSToby Isaac suffix: 1_discontinuous_full 3548a820b8eSToby Isaac args: -dim 1 -continuous 0 -trimmed 0 3558a820b8eSToby Isaac 3568a820b8eSToby Isaac test: 3578a820b8eSToby Isaac suffix: 1_continuous_full 3588a820b8eSToby Isaac args: -dim 1 -continuous 1 -trimmed 0 3598a820b8eSToby Isaac 3608a820b8eSToby Isaac test: 3618a820b8eSToby Isaac suffix: 2_simplex_discontinuous_full 3628a820b8eSToby Isaac args: -dim 2 -tensor 0 -continuous 0 -trimmed 0 3638a820b8eSToby Isaac 3648a820b8eSToby Isaac test: 3658a820b8eSToby Isaac suffix: 2_simplex_continuous_full 3668a820b8eSToby Isaac args: -dim 2 -tensor 0 -continuous 1 -trimmed 0 3678a820b8eSToby Isaac 3688a820b8eSToby Isaac test: 3698a820b8eSToby Isaac suffix: 2_tensor_discontinuous_full 3708a820b8eSToby Isaac args: -dim 2 -tensor 1 -continuous 0 -trimmed 0 3718a820b8eSToby Isaac 3728a820b8eSToby Isaac test: 3738a820b8eSToby Isaac suffix: 2_tensor_continuous_full 3748a820b8eSToby Isaac args: -dim 2 -tensor 1 -continuous 1 -trimmed 0 3758a820b8eSToby Isaac 3768a820b8eSToby Isaac test: 3778a820b8eSToby Isaac suffix: 3_simplex_discontinuous_full 3788a820b8eSToby Isaac args: -dim 3 -tensor 0 -continuous 0 -trimmed 0 3798a820b8eSToby Isaac 3808a820b8eSToby Isaac test: 3818a820b8eSToby Isaac suffix: 3_simplex_continuous_full 3828a820b8eSToby Isaac args: -dim 3 -tensor 0 -continuous 1 -trimmed 0 3838a820b8eSToby Isaac 3848a820b8eSToby Isaac test: 3858a820b8eSToby Isaac suffix: 3_tensor_discontinuous_full 3868a820b8eSToby Isaac args: -dim 3 -tensor 1 -continuous 0 -trimmed 0 3878a820b8eSToby Isaac 3888a820b8eSToby Isaac test: 3898a820b8eSToby Isaac suffix: 3_tensor_continuous_full 3908a820b8eSToby Isaac args: -dim 3 -tensor 1 -continuous 1 -trimmed 0 3918a820b8eSToby Isaac 3928a820b8eSToby Isaac test: 3938a820b8eSToby Isaac suffix: 3_wedge_discontinuous_full 3948a820b8eSToby Isaac args: -dim 3 -tensor 2 -continuous 0 -trimmed 0 3958a820b8eSToby Isaac 3968a820b8eSToby Isaac test: 3978a820b8eSToby Isaac suffix: 3_wedge_continuous_full 3988a820b8eSToby Isaac args: -dim 3 -tensor 2 -continuous 1 -trimmed 0 3998a820b8eSToby Isaac 4008a820b8eSToby Isaac test: 4018a820b8eSToby Isaac suffix: 1_discontinuous_trimmed 4028a820b8eSToby Isaac args: -dim 1 -continuous 0 -trimmed 1 4038a820b8eSToby Isaac 4048a820b8eSToby Isaac test: 4058a820b8eSToby Isaac suffix: 1_continuous_trimmed 4068a820b8eSToby Isaac args: -dim 1 -continuous 1 -trimmed 1 4078a820b8eSToby Isaac 4088a820b8eSToby Isaac test: 4098a820b8eSToby Isaac suffix: 2_simplex_discontinuous_trimmed 4108a820b8eSToby Isaac args: -dim 2 -tensor 0 -continuous 0 -trimmed 1 4118a820b8eSToby Isaac 4128a820b8eSToby Isaac test: 4138a820b8eSToby Isaac suffix: 2_simplex_continuous_trimmed 4148a820b8eSToby Isaac args: -dim 2 -tensor 0 -continuous 1 -trimmed 1 4158a820b8eSToby Isaac 4168a820b8eSToby Isaac test: 4178a820b8eSToby Isaac suffix: 2_tensor_discontinuous_trimmed 4188a820b8eSToby Isaac args: -dim 2 -tensor 1 -continuous 0 -trimmed 1 4198a820b8eSToby Isaac 4208a820b8eSToby Isaac test: 4218a820b8eSToby Isaac suffix: 2_tensor_continuous_trimmed 4228a820b8eSToby Isaac args: -dim 2 -tensor 1 -continuous 1 -trimmed 1 4238a820b8eSToby Isaac 4248a820b8eSToby Isaac test: 4258a820b8eSToby Isaac suffix: 3_simplex_discontinuous_trimmed 4268a820b8eSToby Isaac args: -dim 3 -tensor 0 -continuous 0 -trimmed 1 4278a820b8eSToby Isaac 4288a820b8eSToby Isaac test: 4298a820b8eSToby Isaac suffix: 3_simplex_continuous_trimmed 4308a820b8eSToby Isaac args: -dim 3 -tensor 0 -continuous 1 -trimmed 1 4318a820b8eSToby Isaac 4328a820b8eSToby Isaac test: 4338a820b8eSToby Isaac suffix: 3_tensor_discontinuous_trimmed 4348a820b8eSToby Isaac args: -dim 3 -tensor 1 -continuous 0 -trimmed 1 4358a820b8eSToby Isaac 4368a820b8eSToby Isaac test: 4378a820b8eSToby Isaac suffix: 3_tensor_continuous_trimmed 4388a820b8eSToby Isaac args: -dim 3 -tensor 1 -continuous 1 -trimmed 1 4398a820b8eSToby Isaac 4408a820b8eSToby Isaac test: 4418a820b8eSToby Isaac suffix: 3_wedge_discontinuous_trimmed 4428a820b8eSToby Isaac args: -dim 3 -tensor 2 -continuous 0 -trimmed 1 4438a820b8eSToby Isaac 4448a820b8eSToby Isaac test: 4458a820b8eSToby Isaac suffix: 3_wedge_continuous_trimmed 4468a820b8eSToby Isaac args: -dim 3 -tensor 2 -continuous 1 -trimmed 1 4478a820b8eSToby Isaac 4488a820b8eSToby Isaac TEST*/ 449