xref: /petsc/src/dm/dt/dualspace/impls/lagrange/tests/ex1.c (revision 6ff1568834b9ee5da48e4fa02ac7a4227caec5c3)
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 
108a820b8eSToby Isaac typedef struct _PetscHashLagKey
118a820b8eSToby Isaac {
128a820b8eSToby Isaac   PetscInt  dim;
138a820b8eSToby Isaac   PetscInt  order;
148a820b8eSToby Isaac   PetscInt  formDegree;
158a820b8eSToby Isaac   PetscBool trimmed;
16*6ff15688SToby Isaac   PetscInt  tensor;
178a820b8eSToby Isaac   PetscBool continuous;
188a820b8eSToby Isaac } PetscHashLagKey;
198a820b8eSToby Isaac 
208a820b8eSToby Isaac #define PetscHashLagKeyHash(key) \
218a820b8eSToby Isaac   PetscHashCombine(PetscHashCombine(PetscHashCombine(PetscHashInt((key).dim), \
228a820b8eSToby Isaac                                                      PetscHashInt((key).order)), \
238a820b8eSToby Isaac                                     PetscHashInt((key).formDegree)), \
248a820b8eSToby Isaac                    PetscHashCombine(PetscHashCombine(PetscHashInt((key).trimmed), \
258a820b8eSToby Isaac                                                      PetscHashInt((key).tensor)), \
268a820b8eSToby Isaac                                     PetscHashInt((key).continuous)))
278a820b8eSToby Isaac 
288a820b8eSToby Isaac #define PetscHashLagKeyEqual(k1,k2) \
298a820b8eSToby Isaac   (((k1).dim == (k2).dim) ? \
308a820b8eSToby Isaac    ((k1).order == (k2).order) ? \
318a820b8eSToby Isaac    ((k1).formDegree == (k2).formDegree) ? \
328a820b8eSToby Isaac    ((k1).trimmed == (k2).trimmed) ? \
338a820b8eSToby Isaac    ((k1).tensor == (k2).tensor) ? \
348a820b8eSToby Isaac    ((k1).continuous == (k2).continuous) : 0 : 0 : 0 : 0 : 0)
358a820b8eSToby Isaac 
368a820b8eSToby Isaac PETSC_HASH_MAP(HashLag, PetscHashLagKey, PetscInt, PetscHashLagKeyHash, PetscHashLagKeyEqual, 0)
378a820b8eSToby Isaac 
388a820b8eSToby Isaac static PetscErrorCode ExpectedNumDofs_Total(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs);
398a820b8eSToby Isaac static PetscErrorCode ExpectedNumDofs_Interior(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs);
408a820b8eSToby Isaac 
418a820b8eSToby Isaac static PetscErrorCode ExpectedNumDofs_Total(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs)
428a820b8eSToby Isaac {
438a820b8eSToby Isaac   PetscErrorCode ierr;
448a820b8eSToby Isaac 
458a820b8eSToby Isaac   PetscFunctionBegin;
468a820b8eSToby Isaac   formDegree = PetscAbsInt(formDegree);
478a820b8eSToby Isaac   /* see femtable.org for the source of most of these values */
488a820b8eSToby Isaac   *nDofs = -1;
498a820b8eSToby Isaac   if (tensor == 0) { /* simplex spaces */
508a820b8eSToby Isaac     if (trimmed) {
518a820b8eSToby Isaac       PetscInt rnchooserk;
528a820b8eSToby Isaac       PetscInt rkm1choosek;
538a820b8eSToby Isaac 
548a820b8eSToby Isaac       ierr = PetscDTBinomialInt(order + dim, order + formDegree, &rnchooserk);CHKERRQ(ierr);
558a820b8eSToby Isaac       ierr = PetscDTBinomialInt(order + formDegree - 1, formDegree, &rkm1choosek);CHKERRQ(ierr);
568a820b8eSToby Isaac       *nDofs = rnchooserk * rkm1choosek * nCopies;
578a820b8eSToby Isaac     } else {
588a820b8eSToby Isaac       PetscInt rnchooserk;
598a820b8eSToby Isaac       PetscInt rkchoosek;
608a820b8eSToby Isaac 
618a820b8eSToby Isaac       ierr = PetscDTBinomialInt(order + dim, order + formDegree, &rnchooserk);CHKERRQ(ierr);
628a820b8eSToby Isaac       ierr = PetscDTBinomialInt(order + formDegree, formDegree, &rkchoosek);CHKERRQ(ierr);
638a820b8eSToby Isaac       *nDofs = rnchooserk * rkchoosek * nCopies;
648a820b8eSToby Isaac     }
658a820b8eSToby Isaac   } else if (tensor == 1) { /* hypercubes */
668a820b8eSToby Isaac     if (trimmed) {
678a820b8eSToby Isaac       PetscInt nchoosek;
688a820b8eSToby Isaac       PetscInt rpowk, rp1pownmk;
698a820b8eSToby Isaac 
708a820b8eSToby Isaac       ierr = PetscDTBinomialInt(dim, formDegree, &nchoosek);CHKERRQ(ierr);
718a820b8eSToby Isaac       rpowk = PetscPowInt(order, formDegree);CHKERRQ(ierr);
728a820b8eSToby Isaac       rp1pownmk = PetscPowInt(order + 1, dim - formDegree);CHKERRQ(ierr);
738a820b8eSToby Isaac       *nDofs = nchoosek * rpowk * rp1pownmk * nCopies;
748a820b8eSToby Isaac     } else {
758a820b8eSToby Isaac       PetscInt nchoosek;
768a820b8eSToby Isaac       PetscInt rp1pown;
778a820b8eSToby Isaac 
788a820b8eSToby Isaac       ierr = PetscDTBinomialInt(dim, formDegree, &nchoosek);CHKERRQ(ierr);
798a820b8eSToby Isaac       rp1pown = PetscPowInt(order + 1, dim);CHKERRQ(ierr);
808a820b8eSToby Isaac       *nDofs = nchoosek * rp1pown * nCopies;
818a820b8eSToby Isaac     }
828a820b8eSToby Isaac   } else { /* prism */
838a820b8eSToby Isaac     PetscInt tracek = 0;
848a820b8eSToby Isaac     PetscInt tracekm1 = 0;
858a820b8eSToby Isaac     PetscInt fiber0 = 0;
868a820b8eSToby Isaac     PetscInt fiber1 = 0;
878a820b8eSToby Isaac 
888a820b8eSToby Isaac     if (formDegree < dim) {
898a820b8eSToby Isaac       ierr = ExpectedNumDofs_Total(dim - 1, order, formDegree, trimmed, 0, 1, &tracek);CHKERRQ(ierr);
908a820b8eSToby Isaac       ierr = ExpectedNumDofs_Total(1, order, 0, trimmed, 0, 1, &fiber0);CHKERRQ(ierr);
918a820b8eSToby Isaac     }
928a820b8eSToby Isaac     if (formDegree > 0) {
938a820b8eSToby Isaac       ierr = ExpectedNumDofs_Total(dim - 1, order, formDegree - 1, trimmed, 0, 1, &tracekm1);CHKERRQ(ierr);
948a820b8eSToby Isaac       ierr = ExpectedNumDofs_Total(1, order, 1, trimmed, 0, 1, &fiber1);CHKERRQ(ierr);
958a820b8eSToby Isaac     }
968a820b8eSToby Isaac     *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies;
978a820b8eSToby Isaac   }
988a820b8eSToby Isaac   PetscFunctionReturn(0);
998a820b8eSToby Isaac }
1008a820b8eSToby Isaac 
1018a820b8eSToby Isaac static PetscErrorCode ExpectedNumDofs_Interior(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed,
1028a820b8eSToby Isaac                                                PetscInt tensor, PetscInt nCopies, PetscInt *nDofs)
1038a820b8eSToby Isaac {
1048a820b8eSToby Isaac   PetscErrorCode ierr;
1058a820b8eSToby Isaac 
1068a820b8eSToby Isaac   PetscFunctionBegin;
1078a820b8eSToby Isaac   formDegree = PetscAbsInt(formDegree);
1088a820b8eSToby Isaac   /* see femtable.org for the source of most of these values */
1098a820b8eSToby Isaac   *nDofs = -1;
1108a820b8eSToby Isaac   if (tensor == 0) { /* simplex spaces */
1118a820b8eSToby Isaac     if (trimmed) {
1128a820b8eSToby Isaac       if (order + formDegree > dim) {
1138a820b8eSToby Isaac         PetscInt eorder = order + formDegree - dim - 1;
1148a820b8eSToby Isaac         PetscInt eformDegree = dim - formDegree;
1158a820b8eSToby Isaac         PetscInt rnchooserk;
1168a820b8eSToby Isaac         PetscInt rkchoosek;
1178a820b8eSToby Isaac 
1188a820b8eSToby Isaac         ierr = PetscDTBinomialInt(eorder + dim, eorder + eformDegree, &rnchooserk);CHKERRQ(ierr);
1198a820b8eSToby Isaac         ierr = PetscDTBinomialInt(eorder + eformDegree, eformDegree, &rkchoosek);CHKERRQ(ierr);
1208a820b8eSToby Isaac         *nDofs = rnchooserk * rkchoosek * nCopies;
1218a820b8eSToby Isaac       } else {
1228a820b8eSToby Isaac         *nDofs = 0;
1238a820b8eSToby Isaac       }
1248a820b8eSToby Isaac 
1258a820b8eSToby Isaac     } else {
1268a820b8eSToby Isaac       if (order + formDegree > dim) {
1278a820b8eSToby Isaac         PetscInt eorder = order + formDegree - dim;
1288a820b8eSToby Isaac         PetscInt eformDegree = dim - formDegree;
1298a820b8eSToby Isaac         PetscInt rnchooserk;
1308a820b8eSToby Isaac         PetscInt rkm1choosek;
1318a820b8eSToby Isaac 
1328a820b8eSToby Isaac         ierr = PetscDTBinomialInt(eorder + dim, eorder + eformDegree, &rnchooserk);CHKERRQ(ierr);
1338a820b8eSToby Isaac         ierr = PetscDTBinomialInt(eorder + eformDegree - 1, eformDegree, &rkm1choosek);CHKERRQ(ierr);
1348a820b8eSToby Isaac         *nDofs = rnchooserk * rkm1choosek * nCopies;
1358a820b8eSToby Isaac       } else {
1368a820b8eSToby Isaac         *nDofs = 0;
1378a820b8eSToby Isaac       }
1388a820b8eSToby Isaac     }
1398a820b8eSToby Isaac   } else if (tensor == 1) { /* hypercubes */
1408a820b8eSToby Isaac     if (dim < 2) {
1418a820b8eSToby Isaac       ierr = ExpectedNumDofs_Interior(dim, order, formDegree, trimmed, 0, nCopies, nDofs);CHKERRQ(ierr);
1428a820b8eSToby Isaac     } else {
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) {
1498a820b8eSToby Isaac         ierr = ExpectedNumDofs_Interior(dim - 1, order, formDegree, trimmed, dim > 2 ? 1 : 0, 1, &tracek);CHKERRQ(ierr);
1508a820b8eSToby Isaac         ierr = ExpectedNumDofs_Interior(1, order, 0, trimmed, 0, 1, &fiber0);CHKERRQ(ierr);
1518a820b8eSToby Isaac       }
1528a820b8eSToby Isaac       if (formDegree > 0) {
1538a820b8eSToby Isaac         ierr = ExpectedNumDofs_Interior(dim - 1, order, formDegree - 1, trimmed, dim > 2 ? 1 : 0, 1, &tracekm1);CHKERRQ(ierr);
1548a820b8eSToby Isaac         ierr = ExpectedNumDofs_Interior(1, order, 1, trimmed, 0, 1, &fiber1);CHKERRQ(ierr);
1558a820b8eSToby Isaac       }
1568a820b8eSToby Isaac       *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies;
1578a820b8eSToby Isaac     }
1588a820b8eSToby Isaac   } else { /* prism */
1598a820b8eSToby Isaac     PetscInt tracek = 0;
1608a820b8eSToby Isaac     PetscInt tracekm1 = 0;
1618a820b8eSToby Isaac     PetscInt fiber0 = 0;
1628a820b8eSToby Isaac     PetscInt fiber1 = 0;
1638a820b8eSToby Isaac 
1648a820b8eSToby Isaac     if (formDegree < dim) {
1658a820b8eSToby Isaac       ierr = ExpectedNumDofs_Interior(dim - 1, order, formDegree, trimmed, 0, 1, &tracek);CHKERRQ(ierr);
1668a820b8eSToby Isaac       ierr = ExpectedNumDofs_Interior(1, order, 0, trimmed, 0, 1, &fiber0);CHKERRQ(ierr);
1678a820b8eSToby Isaac     }
1688a820b8eSToby Isaac     if (formDegree > 0) {
1698a820b8eSToby Isaac       ierr = ExpectedNumDofs_Interior(dim - 1, order, formDegree - 1, trimmed, 0, 1, &tracekm1);CHKERRQ(ierr);
1708a820b8eSToby Isaac       ierr = ExpectedNumDofs_Interior(1, order, 1, trimmed, 0, 1, &fiber1);CHKERRQ(ierr);
1718a820b8eSToby Isaac     }
1728a820b8eSToby Isaac     *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies;
1738a820b8eSToby Isaac   }
1748a820b8eSToby Isaac   PetscFunctionReturn(0);
1758a820b8eSToby Isaac }
1768a820b8eSToby Isaac 
1778a820b8eSToby Isaac PetscErrorCode testLagrange(PetscHashLag lagTable, DM K, PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscBool continuous, PetscInt nCopies)
1788a820b8eSToby Isaac {
1798a820b8eSToby Isaac   PetscDualSpace  sp;
1808a820b8eSToby Isaac   MPI_Comm        comm = PETSC_COMM_SELF;
1818a820b8eSToby Isaac   PetscInt        Nk;
1828a820b8eSToby Isaac   PetscHashLagKey key;
1838a820b8eSToby Isaac   PetscHashIter   iter;
1848a820b8eSToby Isaac   PetscBool       missing;
1858a820b8eSToby Isaac   PetscInt        spdim, spintdim, exspdim, exspintdim;
1868a820b8eSToby Isaac   PetscErrorCode  ierr;
1878a820b8eSToby Isaac 
1888a820b8eSToby Isaac   PetscFunctionBegin;
1898a820b8eSToby Isaac   ierr = PetscDTBinomialInt(dim, PetscAbsInt(formDegree), &Nk);CHKERRQ(ierr);
1908a820b8eSToby Isaac   ierr = PetscDualSpaceCreate(comm, &sp);CHKERRQ(ierr);
1918a820b8eSToby Isaac   ierr = PetscDualSpaceSetType(sp, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
1928a820b8eSToby Isaac   ierr = PetscDualSpaceSetDM(sp, K);CHKERRQ(ierr);
1938a820b8eSToby Isaac   ierr = PetscDualSpaceSetOrder(sp, order);CHKERRQ(ierr);
1948a820b8eSToby Isaac   ierr = PetscDualSpaceSetFormDegree(sp, formDegree);CHKERRQ(ierr);
1958a820b8eSToby Isaac   ierr = PetscDualSpaceSetNumComponents(sp, nCopies * Nk);CHKERRQ(ierr);
1968a820b8eSToby Isaac   ierr = PetscDualSpaceLagrangeSetContinuity(sp, continuous);CHKERRQ(ierr);
1978a820b8eSToby Isaac   ierr = PetscDualSpaceLagrangeSetTensor(sp, (PetscBool) tensor);CHKERRQ(ierr);
1988a820b8eSToby Isaac   ierr = PetscDualSpaceLagrangeSetTrimmed(sp, trimmed);CHKERRQ(ierr);
199*6ff15688SToby Isaac   ierr = PetscInfo7(NULL, "Input: dim %D, order %D, trimmed %D, tensor %D, continuous %D, formDegree %D, nCopies %D\n", dim, order, (PetscInt) trimmed, tensor, (PetscInt) continuous, formDegree, nCopies);CHKERRQ(ierr);
2008a820b8eSToby Isaac   ierr = ExpectedNumDofs_Total(dim, order, formDegree, trimmed, tensor, nCopies, &exspdim);CHKERRQ(ierr);
2018a820b8eSToby Isaac   if (continuous && dim > 0 && order > 0) {
2028a820b8eSToby Isaac     ierr = ExpectedNumDofs_Interior(dim, order, formDegree, trimmed, tensor, nCopies, &exspintdim);CHKERRQ(ierr);
2038a820b8eSToby Isaac   } else {
2048a820b8eSToby Isaac     exspintdim = exspdim;
2058a820b8eSToby Isaac   }
2068a820b8eSToby Isaac   ierr = PetscDualSpaceSetUp(sp);CHKERRQ(ierr);
2078a820b8eSToby Isaac   ierr = PetscDualSpaceGetDimension(sp, &spdim);CHKERRQ(ierr);
2088a820b8eSToby Isaac   ierr = PetscDualSpaceGetInteriorDimension(sp, &spintdim);CHKERRQ(ierr);
2098a820b8eSToby Isaac   if (spdim != exspdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected dual space dimension %D, got %D\n", exspdim, spdim);CHKERRQ(ierr);
2108a820b8eSToby Isaac   if (spintdim != exspintdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected dual space interior dimension %D, got %D\n", exspintdim, spintdim);CHKERRQ(ierr);
2118a820b8eSToby Isaac   key.dim = dim;
2128a820b8eSToby Isaac   key.formDegree = formDegree;
2138a820b8eSToby Isaac   ierr = PetscDualSpaceGetOrder(sp, &key.order);CHKERRQ(ierr);
2148a820b8eSToby Isaac   ierr = PetscDualSpaceLagrangeGetContinuity(sp, &key.continuous);CHKERRQ(ierr);
2158a820b8eSToby Isaac   if (tensor == 2) {
2168a820b8eSToby Isaac     key.tensor = 2;
2178a820b8eSToby Isaac   } else {
218*6ff15688SToby Isaac     PetscBool bTensor;
219*6ff15688SToby Isaac 
220*6ff15688SToby Isaac     ierr = PetscDualSpaceLagrangeGetTensor(sp, &bTensor);CHKERRQ(ierr);
221*6ff15688SToby Isaac     key.tensor = bTensor;
2228a820b8eSToby Isaac   }
2238a820b8eSToby Isaac   ierr = PetscDualSpaceLagrangeGetTrimmed(sp, &key.trimmed);CHKERRQ(ierr);
224*6ff15688SToby Isaac   ierr = PetscInfo4(NULL, "After setup:  order %D, trimmed %D, tensor %D, continuous %D\n", key.order, (PetscInt) key.trimmed, key.tensor, (PetscInt) key.continuous);CHKERRQ(ierr);
2258a820b8eSToby Isaac   ierr = PetscHashLagPut(lagTable, key, &iter, &missing);CHKERRQ(ierr);
2268a820b8eSToby Isaac   if (missing) {
2278a820b8eSToby Isaac     DMPolytopeType type;
2288a820b8eSToby Isaac 
2298a820b8eSToby Isaac     ierr = DMPlexGetCellType(K, 0, &type);CHKERRQ(ierr);
230*6ff15688SToby Isaac     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "New space: %s, order %D, trimmed %D, tensor %D, continuous %D, form degree %D\n", DMPolytopeTypes[type], order, (PetscInt) trimmed, tensor, (PetscInt) continuous, formDegree);CHKERRQ(ierr);
2318a820b8eSToby Isaac     ierr = PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2328a820b8eSToby Isaac     {
2338a820b8eSToby Isaac       PetscQuadrature intNodes, allNodes;
2348a820b8eSToby Isaac       Mat intMat, allMat;
2358a820b8eSToby Isaac       MatInfo info;
2368a820b8eSToby Isaac       PetscInt i, j, nodeIdxDim, nodeVecDim, nNodes;
2378a820b8eSToby Isaac       const PetscInt *nodeIdx;
2388a820b8eSToby Isaac       const PetscReal *nodeVec;
2398a820b8eSToby Isaac 
2408a820b8eSToby Isaac       PetscDualSpace_Lag *lag = (PetscDualSpace_Lag *) sp->data;
2418a820b8eSToby Isaac 
2428a820b8eSToby Isaac       ierr = PetscLagNodeIndicesGetData_Internal(lag->allNodeIndices, &nodeIdxDim, &nodeVecDim, &nNodes, &nodeIdx, &nodeVec);CHKERRQ(ierr);
2438a820b8eSToby Isaac       if (nodeVecDim != Nk) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect nodeVecDim");CHKERRQ(ierr);
2448a820b8eSToby Isaac       if (nNodes != spdim) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect nNodes");CHKERRQ(ierr);
2458a820b8eSToby Isaac 
2468a820b8eSToby Isaac       ierr = PetscDualSpaceGetAllData(sp, &allNodes, &allMat);CHKERRQ(ierr);
2478a820b8eSToby Isaac 
2488a820b8eSToby Isaac       ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All nodes:\n");CHKERRQ(ierr);
2498a820b8eSToby Isaac       ierr = PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2508a820b8eSToby Isaac       ierr = PetscQuadratureView(allNodes, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2518a820b8eSToby Isaac       ierr = PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2528a820b8eSToby Isaac       ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All node indices:\n");CHKERRQ(ierr);
2538a820b8eSToby Isaac       for (i = 0; i < spdim; i++) {
2548a820b8eSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "(");CHKERRQ(ierr);
2558a820b8eSToby Isaac         for (j = 0; j < nodeIdxDim; j++) {
2568a820b8eSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, " %D,", nodeIdx[i * nodeIdxDim + j]);CHKERRQ(ierr);
2578a820b8eSToby Isaac         }
2588a820b8eSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "): [");CHKERRQ(ierr);
2598a820b8eSToby Isaac         for (j = 0; j < nodeVecDim; j++) {
260*6ff15688SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, " %g,", (double) nodeVec[i * nodeVecDim + j]);CHKERRQ(ierr);
2618a820b8eSToby Isaac         }
2628a820b8eSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "]\n");CHKERRQ(ierr);
2638a820b8eSToby Isaac       }
2648a820b8eSToby Isaac 
2658a820b8eSToby Isaac       ierr = MatGetInfo(allMat, MAT_LOCAL, &info);CHKERRQ(ierr);
2668a820b8eSToby Isaac       ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All matrix: %D nonzeros\n", (PetscInt) info.nz_used);CHKERRQ(ierr);
2678a820b8eSToby Isaac 
2688a820b8eSToby Isaac       ierr = PetscDualSpaceGetInteriorData(sp, &intNodes, &intMat);CHKERRQ(ierr);
2698a820b8eSToby Isaac       if (intMat && intMat != allMat) {
2708a820b8eSToby Isaac         PetscInt intNodeIdxDim, intNodeVecDim, intNnodes;
2718a820b8eSToby Isaac         const PetscInt *intNodeIdx;
2728a820b8eSToby Isaac         const PetscReal *intNodeVec;
2738a820b8eSToby Isaac         PetscBool same;
2748a820b8eSToby Isaac 
2758a820b8eSToby Isaac         ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior nodes:\n");CHKERRQ(ierr);
2768a820b8eSToby Isaac         ierr = PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2778a820b8eSToby Isaac         ierr = PetscQuadratureView(intNodes, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2788a820b8eSToby Isaac         ierr = PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
2798a820b8eSToby Isaac 
2808a820b8eSToby Isaac         ierr = MatGetInfo(intMat, MAT_LOCAL, &info);CHKERRQ(ierr);
2818a820b8eSToby Isaac         ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior matrix: %D nonzeros\n", (PetscInt) info.nz_used);CHKERRQ(ierr);
2828a820b8eSToby Isaac         ierr = PetscLagNodeIndicesGetData_Internal(lag->intNodeIndices, &intNodeIdxDim, &intNodeVecDim, &intNnodes, &intNodeIdx, &intNodeVec);CHKERRQ(ierr);
2838a820b8eSToby Isaac         if (intNodeIdxDim != nodeIdxDim || intNodeVecDim != nodeVecDim) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices not the same shale as all node indices");
2848a820b8eSToby Isaac         if (intNnodes != spintdim) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect interior nNodes");CHKERRQ(ierr);
2858a820b8eSToby Isaac         ierr = PetscArraycmp(intNodeIdx, nodeIdx, nodeIdxDim * intNnodes, &same);CHKERRQ(ierr);
2868a820b8eSToby Isaac         if (!same) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices not the same as start of all node indices");
2878a820b8eSToby Isaac         ierr = PetscArraycmp(intNodeVec, nodeVec, nodeVecDim * intNnodes, &same);CHKERRQ(ierr);
2888a820b8eSToby Isaac         if (!same) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node vectors not the same as start of all node vectors");
2898a820b8eSToby Isaac       } else if (intMat) {
2908a820b8eSToby Isaac         ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior data is the same as all data\n");CHKERRQ(ierr);
2918a820b8eSToby Isaac         if (intNodes != allNodes) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior nodes should be the same as all nodes");
2928a820b8eSToby Isaac         if (lag->intNodeIndices != lag->allNodeIndices) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices should be the same as all node indices");
2938a820b8eSToby Isaac       }
2948a820b8eSToby Isaac     }
2958a820b8eSToby Isaac     if (dim <= 2 && spintdim) {
2968a820b8eSToby Isaac       PetscInt coneSize, o;
2978a820b8eSToby Isaac 
2988a820b8eSToby Isaac       ierr = DMPlexGetConeSize(K, 0, &coneSize);CHKERRQ(ierr);
2998a820b8eSToby Isaac       for (o = -coneSize; o < coneSize; o++) {
3008a820b8eSToby Isaac         Mat symMat;
3018a820b8eSToby Isaac 
3028a820b8eSToby Isaac         ierr = PetscDualSpaceCreateInteriorSymmetryMatrix_Lagrange(sp, o, &symMat);CHKERRQ(ierr);
3038a820b8eSToby Isaac         ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior node symmetry matrix for orientation %D:\n", o);CHKERRQ(ierr);
3048a820b8eSToby Isaac         ierr = PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3058a820b8eSToby Isaac         ierr = MatView(symMat, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3068a820b8eSToby Isaac         ierr = PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3078a820b8eSToby Isaac         ierr = MatDestroy(&symMat);CHKERRQ(ierr);
3088a820b8eSToby Isaac       }
3098a820b8eSToby Isaac     }
3108a820b8eSToby Isaac     ierr = PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3118a820b8eSToby Isaac   }
3128a820b8eSToby Isaac   ierr = PetscDualSpaceDestroy(&sp);CHKERRQ(ierr);
3138a820b8eSToby Isaac   PetscFunctionReturn(0);
3148a820b8eSToby Isaac }
3158a820b8eSToby Isaac 
3168a820b8eSToby Isaac static PetscErrorCode DMPlexCreateReferenceWedge(MPI_Comm comm, DM *refdm)
3178a820b8eSToby Isaac {
3188a820b8eSToby Isaac   PetscInt       dim = 3;
3198a820b8eSToby Isaac   DM             rdm;
3208a820b8eSToby Isaac   PetscErrorCode ierr;
3218a820b8eSToby Isaac 
3228a820b8eSToby Isaac   PetscFunctionBeginUser;
3238a820b8eSToby Isaac   ierr = DMCreate(comm, &rdm);CHKERRQ(ierr);
3248a820b8eSToby Isaac   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
3258a820b8eSToby Isaac   ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr);
3268a820b8eSToby Isaac   {
3278a820b8eSToby Isaac     PetscInt    numPoints[4]         = {6, 9, 5, 1};
3288a820b8eSToby Isaac     PetscInt    coneSize[21]         = {5,
3298a820b8eSToby Isaac                                         3, 3,
3308a820b8eSToby Isaac                                         4, 4, 4,
3318a820b8eSToby Isaac                                         2, 2, 2, 2, 2, 2, 2, 2, 2,
3328a820b8eSToby Isaac                                         0, 0, 0, 0, 0, 0};
3338a820b8eSToby Isaac     PetscInt    cones[41]            = {1, 2, 3, 4, 5,
3348a820b8eSToby Isaac                                         6, 7, 8,
3358a820b8eSToby Isaac                                         9, 10, 11,
3368a820b8eSToby Isaac                                         8, 12, 9, 13,
3378a820b8eSToby Isaac                                         7, 14, 10, 12,
3388a820b8eSToby Isaac                                         6, 13, 11, 14,
3398a820b8eSToby Isaac                                         15, 16,  16, 17,  17, 15,
3408a820b8eSToby Isaac                                         18, 19,  19, 20,  20, 18,
3418a820b8eSToby Isaac                                         17, 19,  18, 15,  16, 20};
3428a820b8eSToby Isaac     PetscInt    coneOrientations[41] = {0, 0, 0, 0, 0,
3438a820b8eSToby Isaac                                         0, 0, 0,
3448a820b8eSToby Isaac                                         0, 0, 0,
3458a820b8eSToby Isaac                                         -2,  0, -2,  0,
3468a820b8eSToby Isaac                                         -2,  0, -2, -2,
3478a820b8eSToby Isaac                                         -2, -2, -2, -2,
3488a820b8eSToby Isaac                                         0, 0, 0, 0, 0, 0,
3498a820b8eSToby Isaac                                         0, 0, 0, 0, 0, 0,
3508a820b8eSToby Isaac                                         0, 0, 0, 0, 0, 0};
3518a820b8eSToby Isaac     PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0,
3528a820b8eSToby Isaac                                        -1.0,  1.0, -1.0,
3538a820b8eSToby Isaac                                         1.0, -1.0, -1.0,
3548a820b8eSToby Isaac                                        -1.0, -1.0,  1.0,
3558a820b8eSToby Isaac                                         1.0, -1.0,  1.0,
3568a820b8eSToby Isaac                                        -1.0,  1.0,  1.0};
3578a820b8eSToby Isaac 
3588a820b8eSToby Isaac     ierr = DMPlexCreateFromDAG(rdm, 3, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr);
3598a820b8eSToby Isaac   }
3608a820b8eSToby Isaac   *refdm = rdm;
3618a820b8eSToby Isaac   PetscFunctionReturn(0);
3628a820b8eSToby Isaac }
3638a820b8eSToby Isaac 
3648a820b8eSToby Isaac int main (int argc, char **argv)
3658a820b8eSToby Isaac {
3668a820b8eSToby Isaac   PetscInt        dim;
3678a820b8eSToby Isaac   PetscHashLag    lagTable;
3688a820b8eSToby Isaac   PetscInt        tensorCell;
3698a820b8eSToby Isaac   PetscInt        order, ordermin, ordermax;
3708a820b8eSToby Isaac   PetscBool       continuous;
3718a820b8eSToby Isaac   PetscBool       trimmed;
3728a820b8eSToby Isaac   DM              dm;
3738a820b8eSToby Isaac   PetscErrorCode  ierr;
3748a820b8eSToby Isaac 
3758a820b8eSToby Isaac   ierr = PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr;
3768a820b8eSToby Isaac   dim = 3;
3778a820b8eSToby Isaac   tensorCell = 0;
3788a820b8eSToby Isaac   continuous = PETSC_FALSE;
3798a820b8eSToby Isaac   trimmed = PETSC_FALSE;
3808a820b8eSToby Isaac   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"","Options for PETSCDUALSPACELAGRANGE test","none");CHKERRQ(ierr);
3818a820b8eSToby Isaac   ierr = PetscOptionsRangeInt("-dim", "The spatial dimension","ex1.c",dim,&dim,NULL,0,3);CHKERRQ(ierr);
3825ffaa15fSToby Isaac   ierr = PetscOptionsRangeInt("-tensor", "(0) simplex (1) hypercube (2) wedge","ex1.c",tensorCell,&tensorCell,NULL,0,2);CHKERRQ(ierr);
3838a820b8eSToby Isaac   ierr = PetscOptionsBool("-continuous", "Whether the dual space has continuity","ex1.c",continuous,&continuous,NULL);CHKERRQ(ierr);
3848a820b8eSToby Isaac   ierr = PetscOptionsBool("-trimmed", "Whether the dual space matches a trimmed polynomial space","ex1.c",trimmed,&trimmed,NULL);CHKERRQ(ierr);
3858a820b8eSToby Isaac   ierr = PetscOptionsEnd();
3868a820b8eSToby Isaac   ierr = PetscHashLagCreate(&lagTable);CHKERRQ(ierr);
3878a820b8eSToby Isaac 
3888a820b8eSToby Isaac   if (tensorCell < 2) {
3898a820b8eSToby Isaac     ierr = DMPlexCreateReferenceCell(PETSC_COMM_SELF, dim, (PetscBool) !tensorCell, &dm);CHKERRQ(ierr);
3908a820b8eSToby Isaac   } else {
3918a820b8eSToby Isaac     ierr = DMPlexCreateReferenceWedge(PETSC_COMM_SELF, &dm);CHKERRQ(ierr);
3928a820b8eSToby Isaac   }
3938a820b8eSToby Isaac   ordermin = trimmed ? 1 : 0;
3948a820b8eSToby Isaac   ordermax = tensorCell == 2 ? 4 : tensorCell == 1 ? 3 : dim + 2;
3958a820b8eSToby Isaac   for (order = ordermin; order <= ordermax; order++) {
3968a820b8eSToby Isaac     PetscInt formDegree;
3978a820b8eSToby Isaac 
3988a820b8eSToby Isaac     for (formDegree = PetscMin(0,-dim+1); formDegree <= dim; formDegree++) {
3998a820b8eSToby Isaac       PetscInt nCopies;
4008a820b8eSToby Isaac 
4018a820b8eSToby Isaac       for (nCopies = 1; nCopies <= 3; nCopies++) {
4028a820b8eSToby Isaac         ierr = testLagrange(lagTable, dm, dim, order, formDegree, trimmed, (PetscBool) tensorCell, continuous, nCopies);CHKERRQ(ierr);
4038a820b8eSToby Isaac       }
4048a820b8eSToby Isaac     }
4058a820b8eSToby Isaac   }
4068a820b8eSToby Isaac   ierr = DMDestroy(&dm);CHKERRQ(ierr);
4078a820b8eSToby Isaac   ierr = PetscHashLagDestroy(&lagTable);CHKERRQ(ierr);
4088a820b8eSToby Isaac   ierr = PetscFinalize();
4098a820b8eSToby Isaac   return ierr;
4108a820b8eSToby Isaac }
4118a820b8eSToby Isaac 
4128a820b8eSToby Isaac /*TEST
4138a820b8eSToby Isaac 
4148a820b8eSToby Isaac  test:
4158a820b8eSToby Isaac    suffix: 0
4168a820b8eSToby Isaac    args: -dim 0
4178a820b8eSToby Isaac 
4188a820b8eSToby Isaac  test:
4198a820b8eSToby Isaac    suffix: 1_discontinuous_full
4208a820b8eSToby Isaac    args: -dim 1 -continuous 0 -trimmed 0
4218a820b8eSToby Isaac 
4228a820b8eSToby Isaac  test:
4238a820b8eSToby Isaac    suffix: 1_continuous_full
4248a820b8eSToby Isaac    args: -dim 1 -continuous 1 -trimmed 0
4258a820b8eSToby Isaac 
4268a820b8eSToby Isaac  test:
4278a820b8eSToby Isaac    suffix: 2_simplex_discontinuous_full
4288a820b8eSToby Isaac    args: -dim 2 -tensor 0 -continuous 0 -trimmed 0
4298a820b8eSToby Isaac 
4308a820b8eSToby Isaac  test:
4318a820b8eSToby Isaac    suffix: 2_simplex_continuous_full
4328a820b8eSToby Isaac    args: -dim 2 -tensor 0 -continuous 1 -trimmed 0
4338a820b8eSToby Isaac 
4348a820b8eSToby Isaac  test:
4358a820b8eSToby Isaac    suffix: 2_tensor_discontinuous_full
4368a820b8eSToby Isaac    args: -dim 2 -tensor 1 -continuous 0 -trimmed 0
4378a820b8eSToby Isaac 
4388a820b8eSToby Isaac  test:
4398a820b8eSToby Isaac    suffix: 2_tensor_continuous_full
4408a820b8eSToby Isaac    args: -dim 2 -tensor 1 -continuous 1 -trimmed 0
4418a820b8eSToby Isaac 
4428a820b8eSToby Isaac  test:
4438a820b8eSToby Isaac    suffix: 3_simplex_discontinuous_full
4448a820b8eSToby Isaac    args: -dim 3 -tensor 0 -continuous 0 -trimmed 0
4458a820b8eSToby Isaac 
4468a820b8eSToby Isaac  test:
4478a820b8eSToby Isaac    suffix: 3_simplex_continuous_full
4488a820b8eSToby Isaac    args: -dim 3 -tensor 0 -continuous 1 -trimmed 0
4498a820b8eSToby Isaac 
4508a820b8eSToby Isaac  test:
4518a820b8eSToby Isaac    suffix: 3_tensor_discontinuous_full
4528a820b8eSToby Isaac    args: -dim 3 -tensor 1 -continuous 0 -trimmed 0
4538a820b8eSToby Isaac 
4548a820b8eSToby Isaac  test:
4558a820b8eSToby Isaac    suffix: 3_tensor_continuous_full
4568a820b8eSToby Isaac    args: -dim 3 -tensor 1 -continuous 1 -trimmed 0
4578a820b8eSToby Isaac 
4588a820b8eSToby Isaac  test:
4598a820b8eSToby Isaac    suffix: 3_wedge_discontinuous_full
4608a820b8eSToby Isaac    args: -dim 3 -tensor 2 -continuous 0 -trimmed 0
4618a820b8eSToby Isaac 
4628a820b8eSToby Isaac  test:
4638a820b8eSToby Isaac    suffix: 3_wedge_continuous_full
4648a820b8eSToby Isaac    args: -dim 3 -tensor 2 -continuous 1 -trimmed 0
4658a820b8eSToby Isaac 
4668a820b8eSToby Isaac  test:
4678a820b8eSToby Isaac    suffix: 1_discontinuous_trimmed
4688a820b8eSToby Isaac    args: -dim 1 -continuous 0 -trimmed 1
4698a820b8eSToby Isaac 
4708a820b8eSToby Isaac  test:
4718a820b8eSToby Isaac    suffix: 1_continuous_trimmed
4728a820b8eSToby Isaac    args: -dim 1 -continuous 1 -trimmed 1
4738a820b8eSToby Isaac 
4748a820b8eSToby Isaac  test:
4758a820b8eSToby Isaac    suffix: 2_simplex_discontinuous_trimmed
4768a820b8eSToby Isaac    args: -dim 2 -tensor 0 -continuous 0 -trimmed 1
4778a820b8eSToby Isaac 
4788a820b8eSToby Isaac  test:
4798a820b8eSToby Isaac    suffix: 2_simplex_continuous_trimmed
4808a820b8eSToby Isaac    args: -dim 2 -tensor 0 -continuous 1 -trimmed 1
4818a820b8eSToby Isaac 
4828a820b8eSToby Isaac  test:
4838a820b8eSToby Isaac    suffix: 2_tensor_discontinuous_trimmed
4848a820b8eSToby Isaac    args: -dim 2 -tensor 1 -continuous 0 -trimmed 1
4858a820b8eSToby Isaac 
4868a820b8eSToby Isaac  test:
4878a820b8eSToby Isaac    suffix: 2_tensor_continuous_trimmed
4888a820b8eSToby Isaac    args: -dim 2 -tensor 1 -continuous 1 -trimmed 1
4898a820b8eSToby Isaac 
4908a820b8eSToby Isaac  test:
4918a820b8eSToby Isaac    suffix: 3_simplex_discontinuous_trimmed
4928a820b8eSToby Isaac    args: -dim 3 -tensor 0 -continuous 0 -trimmed 1
4938a820b8eSToby Isaac 
4948a820b8eSToby Isaac  test:
4958a820b8eSToby Isaac    suffix: 3_simplex_continuous_trimmed
4968a820b8eSToby Isaac    args: -dim 3 -tensor 0 -continuous 1 -trimmed 1
4978a820b8eSToby Isaac 
4988a820b8eSToby Isaac  test:
4998a820b8eSToby Isaac    suffix: 3_tensor_discontinuous_trimmed
5008a820b8eSToby Isaac    args: -dim 3 -tensor 1 -continuous 0 -trimmed 1
5018a820b8eSToby Isaac 
5028a820b8eSToby Isaac  test:
5038a820b8eSToby Isaac    suffix: 3_tensor_continuous_trimmed
5048a820b8eSToby Isaac    args: -dim 3 -tensor 1 -continuous 1 -trimmed 1
5058a820b8eSToby Isaac 
5068a820b8eSToby Isaac  test:
5078a820b8eSToby Isaac    suffix: 3_wedge_discontinuous_trimmed
5088a820b8eSToby Isaac    args: -dim 3 -tensor 2 -continuous 0 -trimmed 1
5098a820b8eSToby Isaac 
5108a820b8eSToby Isaac  test:
5118a820b8eSToby Isaac    suffix: 3_wedge_continuous_trimmed
5128a820b8eSToby Isaac    args: -dim 3 -tensor 2 -continuous 1 -trimmed 1
5138a820b8eSToby Isaac 
5148a820b8eSToby Isaac TEST*/
515