xref: /petsc/src/dm/impls/plex/plexcreate.c (revision 5552b385b77b214b234683fbe1b434751e6350f0)
15e2c5519SMatthew G. Knepley #include "petscsystypes.h"
2552f7358SJed Brown #define PETSCDM_DLL
3af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
4cc4c1da9SBarry Smith #include <petsc/private/hashseti.h>
50c312b8eSJed Brown #include <petscsf.h>
6cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I   "petscdmplextransform.h"   I*/
79f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h>
8b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
9b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
10552f7358SJed Brown 
11d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H
12d0812dedSMatthew G. Knepley   #include <unistd.h>
13d0812dedSMatthew G. Knepley #endif
14d0812dedSMatthew G. Knepley #include <errno.h>
15d0812dedSMatthew G. Knepley 
16708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1758cd63d5SVaclav Hapla 
189318fe57SMatthew G. Knepley /* External function declarations here */
199318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
209318fe57SMatthew G. Knepley 
21*5552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm)
22*5552b385SBrandon {
23*5552b385SBrandon   PetscObject modelObj;
24*5552b385SBrandon 
25*5552b385SBrandon   PetscFunctionBegin;
26*5552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj));
27*5552b385SBrandon   PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model");
28*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
29*5552b385SBrandon }
30*5552b385SBrandon 
31*5552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout)
32*5552b385SBrandon {
33*5552b385SBrandon   PetscObject obj;
34*5552b385SBrandon 
35*5552b385SBrandon   PetscFunctionBegin;
36*5552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj));
37*5552b385SBrandon   if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj));
38*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
39*5552b385SBrandon }
40*5552b385SBrandon 
41*5552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB)
42*5552b385SBrandon {
43*5552b385SBrandon   PetscObject objA, objB;
44*5552b385SBrandon 
45*5552b385SBrandon   PetscFunctionBegin;
46*5552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA));
47*5552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB));
48*5552b385SBrandon   PetscCall(PetscObjectReference(objA));
49*5552b385SBrandon   PetscCall(PetscObjectReference(objB));
50*5552b385SBrandon   PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB));
51*5552b385SBrandon   PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA));
52*5552b385SBrandon   PetscCall(PetscObjectDereference(objA));
53*5552b385SBrandon   PetscCall(PetscObjectDereference(objB));
54*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
55*5552b385SBrandon }
56*5552b385SBrandon 
57*5552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout)
58*5552b385SBrandon {
59*5552b385SBrandon   PetscFunctionBegin;
60*5552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout));
61*5552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout));
62*5552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout));
63*5552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout));
64*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
65*5552b385SBrandon }
66*5552b385SBrandon 
67*5552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB)
68*5552b385SBrandon {
69*5552b385SBrandon   PetscFunctionBegin;
70*5552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB));
71*5552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB));
72*5552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB));
73*5552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB));
74*5552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
75*5552b385SBrandon }
76*5552b385SBrandon 
77e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
78d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
79d71ae5a4SJacob Faibussowitsch {
804fb89dddSMatthew G. Knepley   const PetscReal     *maxCell, *Lstart, *L;
8112a88998SMatthew G. Knepley   VecType              vecType;
8212a88998SMatthew G. Knepley   MatType              matType;
83129f447cSJames Wright   PetscBool            dist, useCeed, balance_partition;
84adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
85e600fa54SMatthew G. Knepley 
86e600fa54SMatthew G. Knepley   PetscFunctionBegin;
87835f2295SStefano Zampini   if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS);
8812a88998SMatthew G. Knepley   PetscCall(DMGetVecType(dmin, &vecType));
8912a88998SMatthew G. Knepley   PetscCall(DMSetVecType(dmout, vecType));
9012a88998SMatthew G. Knepley   PetscCall(DMGetMatType(dmin, &matType));
9112a88998SMatthew G. Knepley   PetscCall(DMSetMatType(dmout, matType));
92e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
934fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
944fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
953d0e8ed9SDavid Salac     PetscCall(DMLocalizeCoordinates(dmout));
96e600fa54SMatthew G. Knepley   }
979566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
989566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
996bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
1006bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
1015962854dSMatthew G. Knepley   PetscCall(DMPlexGetUseCeed(dmin, &useCeed));
1025962854dSMatthew G. Knepley   PetscCall(DMPlexSetUseCeed(dmout, useCeed));
103129f447cSJames Wright   PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition));
104129f447cSJames Wright   PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition));
105e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
1065962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printSetValues  = ((DM_Plex *)dmin->data)->printSetValues;
1075962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printFEM        = ((DM_Plex *)dmin->data)->printFEM;
1085962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printFVM        = ((DM_Plex *)dmin->data)->printFVM;
1095962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printL2         = ((DM_Plex *)dmin->data)->printL2;
1105962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printLocate     = ((DM_Plex *)dmin->data)->printLocate;
111a77a5016SMatthew G. Knepley   ((DM_Plex *)dmout->data)->printProject    = ((DM_Plex *)dmin->data)->printProject;
1125962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printTol        = ((DM_Plex *)dmin->data)->printTol;
1131baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
114*5552b385SBrandon   PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout));
1153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
116e600fa54SMatthew G. Knepley }
117e600fa54SMatthew G. Knepley 
1189318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
1199318fe57SMatthew G. Knepley    - Share the DM_Plex structure
1209318fe57SMatthew G. Knepley    - Share the coordinates
1219318fe57SMatthew G. Knepley    - Share the SF
1229318fe57SMatthew G. Knepley */
123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
124d71ae5a4SJacob Faibussowitsch {
1259318fe57SMatthew G. Knepley   PetscSF          sf;
1269318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
1279318fe57SMatthew G. Knepley   Vec              coords;
1284fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
1299318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
130e535cce4SJames Wright   PetscBool        use_natural;
1319318fe57SMatthew G. Knepley 
1329318fe57SMatthew G. Knepley   PetscFunctionBegin;
1339318fe57SMatthew G. Knepley   if (dm == dmNew) {
1349566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
1353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1369318fe57SMatthew G. Knepley   }
1379318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
138d0812dedSMatthew G. Knepley   if (!dm->hdr.name) {
139d0812dedSMatthew G. Knepley     const char *name;
140d0812dedSMatthew G. Knepley 
141d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
142d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
143d0812dedSMatthew G. Knepley   }
1449566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
1459566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1469566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
1479566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
1489566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
1499566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
1509566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
1519566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
1529566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
1539566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
1546858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
1556858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
1566858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
1576858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
1589318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
1596858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
1606858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
16161a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
1624fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
1634fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
164e535cce4SJames Wright   PetscCall(DMGetNaturalSF(dmNew, &sf));
165e535cce4SJames Wright   PetscCall(DMSetNaturalSF(dm, sf));
166e535cce4SJames Wright   PetscCall(DMGetUseNatural(dmNew, &use_natural));
167e535cce4SJames Wright   PetscCall(DMSetUseNatural(dm, use_natural));
1689566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
1699566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
1709318fe57SMatthew G. Knepley   dm->data = dmNew->data;
1719318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
1721fca310dSJames Wright   {
1731fca310dSJames Wright     PetscInt       num_face_sfs;
1741fca310dSJames Wright     const PetscSF *sfs;
1751fca310dSJames Wright     PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs));
1761fca310dSJames Wright     PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm
1771fca310dSJames Wright   }
1789566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
1799566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
1809566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
1819566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
182*5552b385SBrandon   PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm));
1839566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1859318fe57SMatthew G. Knepley }
1869318fe57SMatthew G. Knepley 
1879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
1889318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
1899318fe57SMatthew G. Knepley    - Swap the coordinates
1909318fe57SMatthew G. Knepley    - Swap the point PetscSF
1919318fe57SMatthew G. Knepley */
192d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
193d71ae5a4SJacob Faibussowitsch {
1949318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
1959318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
1969318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
1979318fe57SMatthew G. Knepley   DMField     fieldTmp;
1989318fe57SMatthew G. Knepley   void       *tmp;
1999318fe57SMatthew G. Knepley   DMLabelLink listTmp;
2009318fe57SMatthew G. Knepley   DMLabel     depthTmp;
2019318fe57SMatthew G. Knepley   PetscInt    tmpI;
2029318fe57SMatthew G. Knepley 
2039318fe57SMatthew G. Knepley   PetscFunctionBegin;
2043ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
2059566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
2069566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
2079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
2089566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
2099566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
2109566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
2119318fe57SMatthew G. Knepley 
2129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
2139566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
2149566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
2159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
2169566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
2179566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
2189318fe57SMatthew G. Knepley 
2199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
2209566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
2219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
2229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
2239566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
2249566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
2259318fe57SMatthew G. Knepley 
2266858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
2276858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
2286858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
2296858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
2306858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
2316858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
2326858538eSMatthew G. Knepley 
2336858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
2346858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
2356858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
2366858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
2376858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
2386858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
2396858538eSMatthew G. Knepley 
240*5552b385SBrandon   PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB));
241*5552b385SBrandon 
2426858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
2436858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
2446858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
2456858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
2466858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
2476858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
2489318fe57SMatthew G. Knepley   tmp                       = dmA->data;
2499318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
2509318fe57SMatthew G. Knepley   dmB->data                 = tmp;
2519318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
2529318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
2539318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
2549318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
2559318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
2569318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
2579318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
2589318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
2599318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
2609318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
2619318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
2629318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2649318fe57SMatthew G. Knepley }
2659318fe57SMatthew G. Knepley 
2663431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
267d71ae5a4SJacob Faibussowitsch {
2689318fe57SMatthew G. Knepley   DM idm;
2699318fe57SMatthew G. Knepley 
2709318fe57SMatthew G. Knepley   PetscFunctionBegin;
2719566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
2729566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
27369d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
2743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2759318fe57SMatthew G. Knepley }
2769318fe57SMatthew G. Knepley 
2779318fe57SMatthew G. Knepley /*@C
2789318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
2799318fe57SMatthew G. Knepley 
28020f4b53cSBarry Smith   Collective
2819318fe57SMatthew G. Knepley 
2829318fe57SMatthew G. Knepley   Input Parameters:
28360225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
28420f4b53cSBarry Smith . degree    - The degree of the finite element or `PETSC_DECIDE`
285e44f6aebSMatthew G. Knepley . project   - Flag to project current coordinates into the space
2869318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
2879318fe57SMatthew G. Knepley 
2889318fe57SMatthew G. Knepley   Level: advanced
2899318fe57SMatthew G. Knepley 
2901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
2919318fe57SMatthew G. Knepley @*/
292e44f6aebSMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool project, PetscPointFunc coordFunc)
293d71ae5a4SJacob Faibussowitsch {
2949318fe57SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
295e44f6aebSMatthew G. Knepley   PetscFE  fe   = NULL;
2969318fe57SMatthew G. Knepley   DM       cdm;
2971df12153SMatthew G. Knepley   PetscInt dim, dE, qorder, height;
2989318fe57SMatthew G. Knepley 
299e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
3009566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
3019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
3029318fe57SMatthew G. Knepley   qorder = degree;
303e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
304d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)cdm);
305dc431b0cSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
306d0609cedSBarry Smith   PetscOptionsEnd();
3071df12153SMatthew G. Knepley   PetscCall(DMPlexGetVTKCellHeight(dm, &height));
308e44f6aebSMatthew G. Knepley   if (degree >= 0) {
309e44f6aebSMatthew G. Knepley     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
310e44f6aebSMatthew G. Knepley     PetscInt       cStart, cEnd, gct;
311dc431b0cSMatthew G. Knepley 
3121df12153SMatthew G. Knepley     PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd));
313dc431b0cSMatthew G. Knepley     if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
314e44f6aebSMatthew G. Knepley     gct = (PetscInt)ct;
315462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
316e44f6aebSMatthew G. Knepley     ct = (DMPolytopeType)gct;
317e44f6aebSMatthew G. Knepley     // Work around current bug in PetscDualSpaceSetUp_Lagrange()
318e44f6aebSMatthew G. Knepley     //   Can be seen in plex_tutorials-ex10_1
319e44f6aebSMatthew G. Knepley     if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
3204f9ab2b4SJed Brown   }
321e44f6aebSMatthew G. Knepley   PetscCall(DMSetCoordinateDisc(dm, fe, project));
3229566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
3239318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
3243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3259318fe57SMatthew G. Knepley }
3269318fe57SMatthew G. Knepley 
3271df5d5c5SMatthew G. Knepley /*@
3281df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
3291df5d5c5SMatthew G. Knepley 
330d083f849SBarry Smith   Collective
3311df5d5c5SMatthew G. Knepley 
3321df5d5c5SMatthew G. Knepley   Input Parameters:
333a1cb98faSBarry Smith + comm            - The communicator for the `DM` object
3341df5d5c5SMatthew G. Knepley . dim             - The spatial dimension
3351df5d5c5SMatthew G. Knepley . simplex         - Flag for simplicial cells, otherwise they are tensor product cells
3361df5d5c5SMatthew G. Knepley . interpolate     - Flag to create intermediate mesh pieces (edges, faces)
3371df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
3381df5d5c5SMatthew G. Knepley 
3391df5d5c5SMatthew G. Knepley   Output Parameter:
34060225df5SJacob Faibussowitsch . newdm - The `DM` object
3411df5d5c5SMatthew G. Knepley 
3421df5d5c5SMatthew G. Knepley   Level: beginner
3431df5d5c5SMatthew G. Knepley 
3441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3451df5d5c5SMatthew G. Knepley @*/
346d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
347d71ae5a4SJacob Faibussowitsch {
3481df5d5c5SMatthew G. Knepley   DM          dm;
3491df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
3501df5d5c5SMatthew G. Knepley 
3511df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
3529566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
3539566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
3549566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
35546139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
3569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
357ce78fa2fSMatthew G. Knepley   switch (dim) {
358ce78fa2fSMatthew G. Knepley   case 2:
3599566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
3609566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
361ce78fa2fSMatthew G. Knepley     break;
362ce78fa2fSMatthew G. Knepley   case 3:
3639566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
3649566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
365ce78fa2fSMatthew G. Knepley     break;
366d71ae5a4SJacob Faibussowitsch   default:
367d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
368ce78fa2fSMatthew G. Knepley   }
3691df5d5c5SMatthew G. Knepley   if (rank) {
3701df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
3719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
3721df5d5c5SMatthew G. Knepley   } else {
3731df5d5c5SMatthew G. Knepley     switch (dim) {
3741df5d5c5SMatthew G. Knepley     case 2:
3751df5d5c5SMatthew G. Knepley       if (simplex) {
3761df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
3771df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
3781df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
3791df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
3801df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
3811df5d5c5SMatthew G. Knepley 
3829566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3831df5d5c5SMatthew G. Knepley       } else {
3841df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
3851df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
3861df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
3871df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3881df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[12]    = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5};
3891df5d5c5SMatthew G. Knepley 
3909566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3911df5d5c5SMatthew G. Knepley       }
3921df5d5c5SMatthew G. Knepley       break;
3931df5d5c5SMatthew G. Knepley     case 3:
3941df5d5c5SMatthew G. Knepley       if (simplex) {
3951df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
3961df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
3971df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
3981df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3991df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[15]    = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0};
4001df5d5c5SMatthew G. Knepley 
4019566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4021df5d5c5SMatthew G. Knepley       } else {
4031df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
4041df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4051df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
4061df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4079371c9d4SSatish Balay         PetscScalar vertexCoords[36]     = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5};
4081df5d5c5SMatthew G. Knepley 
4099566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4101df5d5c5SMatthew G. Knepley       }
4111df5d5c5SMatthew G. Knepley       break;
412d71ae5a4SJacob Faibussowitsch     default:
413d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
4141df5d5c5SMatthew G. Knepley     }
4151df5d5c5SMatthew G. Knepley   }
41646139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
4171df5d5c5SMatthew G. Knepley   *newdm = dm;
4181df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
4191df5d5c5SMatthew G. Knepley     DM          rdm;
4201df5d5c5SMatthew G. Knepley     const char *name;
4211df5d5c5SMatthew G. Knepley 
4229566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
4239566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
4249566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
4259566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
4269566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
4279566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
4281df5d5c5SMatthew G. Knepley     *newdm = rdm;
4291df5d5c5SMatthew G. Knepley   }
4301df5d5c5SMatthew G. Knepley   if (interpolate) {
4315fd9971aSMatthew G. Knepley     DM idm;
4321df5d5c5SMatthew G. Knepley 
4339566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
4349566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
4351df5d5c5SMatthew G. Knepley     *newdm = idm;
4361df5d5c5SMatthew G. Knepley   }
4373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4381df5d5c5SMatthew G. Knepley }
4391df5d5c5SMatthew G. Knepley 
440d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
441d71ae5a4SJacob Faibussowitsch {
4429318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
4439318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
4449318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
4459318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
4469318fe57SMatthew G. Knepley   Vec            coordinates;
4479318fe57SMatthew G. Knepley   PetscSection   coordSection;
4489318fe57SMatthew G. Knepley   PetscScalar   *coords;
4499318fe57SMatthew G. Knepley   PetscInt       coordSize;
4509318fe57SMatthew G. Knepley   PetscMPIInt    rank;
4519318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
452552f7358SJed Brown 
4539318fe57SMatthew G. Knepley   PetscFunctionBegin;
4549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
4559318fe57SMatthew G. Knepley   if (markerSeparate) {
4569318fe57SMatthew G. Knepley     markerRight = 2;
4579318fe57SMatthew G. Knepley     markerLeft  = 1;
4589318fe57SMatthew G. Knepley   }
4599566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
460c5853193SPierre Jolivet   if (rank == 0) {
4619566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
4629566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
4639566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
4649566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
4659318fe57SMatthew G. Knepley   }
4669566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4679566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
4689318fe57SMatthew G. Knepley   /* Build coordinates */
4699566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
4709566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4729566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
4739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
4749318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
4759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
4769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
4779318fe57SMatthew G. Knepley   }
4789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4809566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4829566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4839566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
4849566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
4859566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4869318fe57SMatthew G. Knepley   coords[0] = lower[0];
4879318fe57SMatthew G. Knepley   coords[1] = upper[0];
4889566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
4899566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
4909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
4913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4929318fe57SMatthew G. Knepley }
49326492d91SMatthew G. Knepley 
494d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
495d71ae5a4SJacob Faibussowitsch {
4961df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
4971df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
498552f7358SJed Brown   PetscInt       markerTop      = 1;
499552f7358SJed Brown   PetscInt       markerBottom   = 1;
500552f7358SJed Brown   PetscInt       markerRight    = 1;
501552f7358SJed Brown   PetscInt       markerLeft     = 1;
502552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
503552f7358SJed Brown   Vec            coordinates;
504552f7358SJed Brown   PetscSection   coordSection;
505552f7358SJed Brown   PetscScalar   *coords;
506552f7358SJed Brown   PetscInt       coordSize;
507552f7358SJed Brown   PetscMPIInt    rank;
508552f7358SJed Brown   PetscInt       v, vx, vy;
509552f7358SJed Brown 
510552f7358SJed Brown   PetscFunctionBegin;
5119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
512552f7358SJed Brown   if (markerSeparate) {
5131df21d24SMatthew G. Knepley     markerTop    = 3;
5141df21d24SMatthew G. Knepley     markerBottom = 1;
5151df21d24SMatthew G. Knepley     markerRight  = 2;
5161df21d24SMatthew G. Knepley     markerLeft   = 4;
517552f7358SJed Brown   }
5189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
519dd400576SPatrick Sanan   if (rank == 0) {
520552f7358SJed Brown     PetscInt e, ex, ey;
521552f7358SJed Brown 
5229566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
52348a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
5249566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
525552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
526552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
527552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
528552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
529da80777bSKarl Rupp         PetscInt cone[2];
530552f7358SJed Brown 
5319371c9d4SSatish Balay         cone[0] = vertex;
5329371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
5339566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
534552f7358SJed Brown         if (vx == edges[0]) {
5359566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
5369566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
537552f7358SJed Brown           if (ey == edges[1] - 1) {
5389566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
5399566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
540552f7358SJed Brown           }
541552f7358SJed Brown         } else if (vx == 0) {
5429566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
5439566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
544552f7358SJed Brown           if (ey == edges[1] - 1) {
5459566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
5469566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
547552f7358SJed Brown           }
548552f7358SJed Brown         }
549552f7358SJed Brown       }
550552f7358SJed Brown     }
551552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
552552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
553552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
554552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
555da80777bSKarl Rupp         PetscInt cone[2];
556552f7358SJed Brown 
5579371c9d4SSatish Balay         cone[0] = vertex;
5589371c9d4SSatish Balay         cone[1] = vertex + 1;
5599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
560552f7358SJed Brown         if (vy == edges[1]) {
5619566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
5629566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
563552f7358SJed Brown           if (ex == edges[0] - 1) {
5649566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
5659566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
566552f7358SJed Brown           }
567552f7358SJed Brown         } else if (vy == 0) {
5689566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
5699566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
570552f7358SJed Brown           if (ex == edges[0] - 1) {
5719566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
5729566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
573552f7358SJed Brown           }
574552f7358SJed Brown         }
575552f7358SJed Brown       }
576552f7358SJed Brown     }
577552f7358SJed Brown   }
5789566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
5799566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
580552f7358SJed Brown   /* Build coordinates */
5819566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
5829566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
5839566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
5849566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
5859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
586552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
5879566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
5889566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
589552f7358SJed Brown   }
5909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
5919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
5929566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
5939566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
5949566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
5959566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
5969566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
5979566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
598552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
599552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
600552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
601552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
602552f7358SJed Brown     }
603552f7358SJed Brown   }
6049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6059566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
6073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
608552f7358SJed Brown }
609552f7358SJed Brown 
610d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
611d71ae5a4SJacob Faibussowitsch {
6129e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
6137b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
614c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
615c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
616c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
617c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
618c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
619c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
620c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
621552f7358SJed Brown   Vec          coordinates;
622552f7358SJed Brown   PetscSection coordSection;
623552f7358SJed Brown   PetscScalar *coords;
624552f7358SJed Brown   PetscInt     coordSize;
625552f7358SJed Brown   PetscMPIInt  rank;
626552f7358SJed Brown   PetscInt     v, vx, vy, vz;
6277b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
628552f7358SJed Brown 
629552f7358SJed Brown   PetscFunctionBegin;
6301dca8a05SBarry Smith   PetscCheck(faces[0] >= 1 && faces[1] >= 1 && faces[2] >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side");
6319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
632c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
633c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
634c2df9bbfSMatthew G. Knepley     markerBottom = 1;
635c2df9bbfSMatthew G. Knepley     markerTop    = 2;
636c2df9bbfSMatthew G. Knepley     markerFront  = 3;
637c2df9bbfSMatthew G. Knepley     markerBack   = 4;
638c2df9bbfSMatthew G. Knepley     markerRight  = 5;
639c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
640c2df9bbfSMatthew G. Knepley   }
6419371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
6429371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
6439371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
6449e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
645dd400576SPatrick Sanan   if (rank == 0) {
646552f7358SJed Brown     PetscInt f;
647552f7358SJed Brown 
6489566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
64948a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
6509566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
6517b59f5a9SMichael Lange 
6527b59f5a9SMichael Lange     /* Side 0 (Top) */
6537b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
6547b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6557b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
6569371c9d4SSatish Balay         cone[0] = voffset;
6579371c9d4SSatish Balay         cone[1] = voffset + 1;
6589371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
6599371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6609566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
661c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
662c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
663c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
664c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
665c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
6667b59f5a9SMichael Lange         iface++;
667552f7358SJed Brown       }
668552f7358SJed Brown     }
6697b59f5a9SMichael Lange 
6707b59f5a9SMichael Lange     /* Side 1 (Bottom) */
6717b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
6727b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6737b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
6749371c9d4SSatish Balay         cone[0] = voffset + 1;
6759371c9d4SSatish Balay         cone[1] = voffset;
6769371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6779371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
6789566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
679c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
680c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
681c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
682c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
683c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
6847b59f5a9SMichael Lange         iface++;
685552f7358SJed Brown       }
686552f7358SJed Brown     }
6877b59f5a9SMichael Lange 
6887b59f5a9SMichael Lange     /* Side 2 (Front) */
6897b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6907b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6917b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
6929371c9d4SSatish Balay         cone[0] = voffset;
6939371c9d4SSatish Balay         cone[1] = voffset + 1;
6949371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
6959371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
6969566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
697c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
698c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
699c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
700c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
701c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
7027b59f5a9SMichael Lange         iface++;
703552f7358SJed Brown       }
7047b59f5a9SMichael Lange     }
7057b59f5a9SMichael Lange 
7067b59f5a9SMichael Lange     /* Side 3 (Back) */
7077b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7087b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7097b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
7109371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
7119371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
7129371c9d4SSatish Balay         cone[2] = voffset + 1;
7139371c9d4SSatish Balay         cone[3] = voffset;
7149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
715c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
716c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
717c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
718c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
719c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
7207b59f5a9SMichael Lange         iface++;
7217b59f5a9SMichael Lange       }
7227b59f5a9SMichael Lange     }
7237b59f5a9SMichael Lange 
7247b59f5a9SMichael Lange     /* Side 4 (Left) */
7257b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7267b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
7277b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
7289371c9d4SSatish Balay         cone[0] = voffset;
7299371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
7309371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
7319371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
7329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
733c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
734c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
735c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
736c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
737c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
7387b59f5a9SMichael Lange         iface++;
7397b59f5a9SMichael Lange       }
7407b59f5a9SMichael Lange     }
7417b59f5a9SMichael Lange 
7427b59f5a9SMichael Lange     /* Side 5 (Right) */
7437b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7447b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
745aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
7469371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
7479371c9d4SSatish Balay         cone[1] = voffset;
7489371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
7499371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
7509566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
751c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
752c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
753c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
754c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
755c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
7567b59f5a9SMichael Lange         iface++;
7577b59f5a9SMichael Lange       }
758552f7358SJed Brown     }
759552f7358SJed Brown   }
7609566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
7619566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
762552f7358SJed Brown   /* Build coordinates */
7639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
7649566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
7669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
7679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
768552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
7699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
7709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
771552f7358SJed Brown   }
7729566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
7739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
7749566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
7759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
7769566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
7779566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
7789566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
7799566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
780552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
781552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
782552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
783552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
784552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
785552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
786552f7358SJed Brown       }
787552f7358SJed Brown     }
788552f7358SJed Brown   }
7899566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
7909566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
7919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
7923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
793552f7358SJed Brown }
794552f7358SJed Brown 
795d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
796d71ae5a4SJacob Faibussowitsch {
7979318fe57SMatthew G. Knepley   PetscFunctionBegin;
7989318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
79946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
8009566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
8019566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
8029318fe57SMatthew G. Knepley   switch (dim) {
803d71ae5a4SJacob Faibussowitsch   case 1:
804d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
805d71ae5a4SJacob Faibussowitsch     break;
806d71ae5a4SJacob Faibussowitsch   case 2:
807d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
808d71ae5a4SJacob Faibussowitsch     break;
809d71ae5a4SJacob Faibussowitsch   case 3:
810d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
811d71ae5a4SJacob Faibussowitsch     break;
812d71ae5a4SJacob Faibussowitsch   default:
813d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
8149318fe57SMatthew G. Knepley   }
81546139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
8169566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8189318fe57SMatthew G. Knepley }
8199318fe57SMatthew G. Knepley 
8209318fe57SMatthew G. Knepley /*@C
8219318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
8229318fe57SMatthew G. Knepley 
8239318fe57SMatthew G. Knepley   Collective
8249318fe57SMatthew G. Knepley 
8259318fe57SMatthew G. Knepley   Input Parameters:
826a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
82720f4b53cSBarry Smith . dim         - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1
82820f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
82920f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
83020f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
8319318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
8329318fe57SMatthew G. Knepley 
8339318fe57SMatthew G. Knepley   Output Parameter:
834a1cb98faSBarry Smith . dm - The `DM` object
8359318fe57SMatthew G. Knepley 
8369318fe57SMatthew G. Knepley   Level: beginner
8379318fe57SMatthew G. Knepley 
8381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
8399318fe57SMatthew G. Knepley @*/
840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
841d71ae5a4SJacob Faibussowitsch {
8429318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
8439318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
8449318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
8459318fe57SMatthew G. Knepley 
8469318fe57SMatthew G. Knepley   PetscFunctionBegin;
8479566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
8489566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
8499566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
8503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8519318fe57SMatthew G. Knepley }
8529318fe57SMatthew G. Knepley 
853d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
854d71ae5a4SJacob Faibussowitsch {
855fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
856fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
857fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
858fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
859fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
860fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
861fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
862fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
863fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
864fdbf62faSLisandro Dalcin 
865fdbf62faSLisandro Dalcin   PetscFunctionBegin;
8664f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
867fdbf62faSLisandro Dalcin 
8689566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
8699566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8709566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
871fdbf62faSLisandro Dalcin 
8729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
873dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
874dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
875fdbf62faSLisandro Dalcin 
8769371c9d4SSatish Balay   numPoints[0] = numVerts;
8779371c9d4SSatish Balay   numPoints[1] = numCells;
8789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
8799566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
880ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
881ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
8829371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
8839371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
8849371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
8859371c9d4SSatish Balay   }
886ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
8879566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
8889566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
889fdbf62faSLisandro Dalcin 
8909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
8919371c9d4SSatish Balay   if (markerSeparate) {
8929371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
8939371c9d4SSatish Balay     markerRight = faceMarkerRight;
8949371c9d4SSatish Balay   }
895dd400576SPatrick Sanan   if (!wrap && rank == 0) {
8969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
8979566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
8989566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
8999566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
9009566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
901fdbf62faSLisandro Dalcin   }
902fdbf62faSLisandro Dalcin   if (wrap) {
903fdbf62faSLisandro Dalcin     L       = upper - lower;
904fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
9054fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
906fdbf62faSLisandro Dalcin   }
9079566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
9083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
909fdbf62faSLisandro Dalcin }
910fdbf62faSLisandro Dalcin 
9114054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions
912d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[])
9134054ae39SJames Wright {
9146ff49feeSJames Wright   DM              cdm;
9156ff49feeSJames Wright   PetscSection    csection;
9166ff49feeSJames Wright   Vec             coordinates;
9174054ae39SJames Wright   DMLabel         label;
9186ff49feeSJames Wright   IS              faces_is;
9192b4f33d9SJames Wright   PetscInt        dim, num_face = 0;
9204054ae39SJames Wright   const PetscInt *faces;
9214054ae39SJames Wright   PetscInt        faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft;
9224054ae39SJames Wright 
9234054ae39SJames Wright   PetscFunctionBeginUser;
9244054ae39SJames Wright   PetscCall(DMGetDimension(dm, &dim));
925d7c1f440SPierre Jolivet   PetscCheck((dim == 2) || (dim == 3), PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DMPlex box labeling only supports 2D and 3D meshes, received DM of dimension %" PetscInt_FMT, dim);
9264054ae39SJames Wright   // Get Face Sets label
9274054ae39SJames Wright   PetscCall(DMGetLabel(dm, "Face Sets", &label));
9284054ae39SJames Wright   if (label) {
9294054ae39SJames Wright     PetscCall(DMLabelReset(label));
9304054ae39SJames Wright   } else {
9314054ae39SJames Wright     PetscCall(DMCreateLabel(dm, "Face Sets"));
9324054ae39SJames Wright     PetscCall(DMGetLabel(dm, "Face Sets", &label));
9334054ae39SJames Wright   }
9344054ae39SJames Wright   PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label));
9356ff49feeSJames Wright   PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is));
9364054ae39SJames Wright 
9374054ae39SJames Wright   switch (dim) {
9384054ae39SJames Wright   case 2:
9394054ae39SJames Wright     faceMarkerTop    = 3;
9404054ae39SJames Wright     faceMarkerBottom = 1;
9414054ae39SJames Wright     faceMarkerRight  = 2;
9424054ae39SJames Wright     faceMarkerLeft   = 4;
9434054ae39SJames Wright     break;
9444054ae39SJames Wright   case 3:
9454054ae39SJames Wright     faceMarkerBottom = 1;
9464054ae39SJames Wright     faceMarkerTop    = 2;
9474054ae39SJames Wright     faceMarkerFront  = 3;
9484054ae39SJames Wright     faceMarkerBack   = 4;
9494054ae39SJames Wright     faceMarkerRight  = 5;
9504054ae39SJames Wright     faceMarkerLeft   = 6;
9514054ae39SJames Wright     break;
9524054ae39SJames Wright   default:
9534054ae39SJames Wright     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
9544054ae39SJames Wright   }
9554054ae39SJames Wright 
9562b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face));
9572b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetIndices(faces_is, &faces));
9586ff49feeSJames Wright   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9596ff49feeSJames Wright   PetscCall(DMGetCoordinateDM(dm, &cdm));
9606ff49feeSJames Wright   PetscCall(DMGetLocalSection(cdm, &csection));
9614054ae39SJames Wright   for (PetscInt f = 0; f < num_face; ++f) {
9626ff49feeSJames Wright     PetscScalar *coords = NULL;
9636ff49feeSJames Wright     PetscInt     face = faces[f], flip = 1, label_value = -1, coords_size;
9644054ae39SJames Wright 
9654054ae39SJames Wright     { // Determine if orientation of face is flipped
9664054ae39SJames Wright       PetscInt        num_cells_support, num_faces, start = -1;
9674054ae39SJames Wright       const PetscInt *orients, *cell_faces, *cells;
9684054ae39SJames Wright 
9694054ae39SJames Wright       PetscCall(DMPlexGetSupport(dm, face, &cells));
9704054ae39SJames Wright       PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support));
9714054ae39SJames Wright       PetscCheck(num_cells_support == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Expected one cell in support of exterior face, but got %" PetscInt_FMT " cells", num_cells_support);
9724054ae39SJames Wright       PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces));
9734054ae39SJames Wright       PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces));
9744054ae39SJames Wright       for (PetscInt i = 0; i < num_faces; i++) {
9754054ae39SJames Wright         if (cell_faces[i] == face) start = i;
9764054ae39SJames Wright       }
9774054ae39SJames Wright       PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face);
9784054ae39SJames Wright       PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients));
9794054ae39SJames Wright       if (orients[start] < 0) flip = -1;
9804054ae39SJames Wright     }
9814054ae39SJames Wright 
9826ff49feeSJames Wright     // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually
9836ff49feeSJames Wright     // Use the vertices (depth 0) of coordinate DM to calculate normal vector
9846ff49feeSJames Wright     PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
9854054ae39SJames Wright     switch (dim) {
9864054ae39SJames Wright     case 2: {
9876ff49feeSJames Wright       PetscScalar vec[2];
9886ff49feeSJames Wright 
9896ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]));
9906ff49feeSJames Wright       PetscScalar normal[] = {vec[1], -vec[0]};
9916ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
9926ff49feeSJames Wright         label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
9934054ae39SJames Wright       } else {
9946ff49feeSJames Wright         label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom;
9954054ae39SJames Wright       }
9964054ae39SJames Wright     } break;
9974054ae39SJames Wright     case 3: {
9986ff49feeSJames Wright       PetscScalar vec1[3], vec2[3], normal[3];
9996ff49feeSJames Wright 
10006ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) {
10016ff49feeSJames Wright         vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]);
10026ff49feeSJames Wright         vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]);
10036ff49feeSJames Wright       }
10046ff49feeSJames Wright 
10056ff49feeSJames Wright       // Calculate normal vector via cross-product
10066ff49feeSJames Wright       normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1]));
10076ff49feeSJames Wright       normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2]));
10086ff49feeSJames Wright       normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0]));
10096ff49feeSJames Wright 
10106ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
10116ff49feeSJames Wright         if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) {
10126ff49feeSJames Wright           label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
10134054ae39SJames Wright         } else {
10146ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
10154054ae39SJames Wright         }
10164054ae39SJames Wright       } else {
10176ff49feeSJames Wright         if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) {
10186ff49feeSJames Wright           label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront;
10194054ae39SJames Wright         } else {
10206ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
10214054ae39SJames Wright         }
10224054ae39SJames Wright       }
10234054ae39SJames Wright     } break;
10244054ae39SJames Wright     }
10254054ae39SJames Wright 
10264054ae39SJames Wright     PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above
10274054ae39SJames Wright     PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value));
10284054ae39SJames Wright     PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value));
10294054ae39SJames Wright     PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value));
10306ff49feeSJames Wright     PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
10314054ae39SJames Wright   }
10322b4f33d9SJames Wright   if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces));
10336ff49feeSJames Wright   PetscCall(ISDestroy(&faces_is));
1034d7d2d1d2SJames Wright 
1035d7d2d1d2SJames Wright   // Create Isoperiodic SF from newly-created face labels
1036d7d2d1d2SJames Wright   PetscSF     periodicsfs[3];
1037d7d2d1d2SJames Wright   PetscInt    periodic_sf_index  = 0;
1038d7d2d1d2SJames Wright   PetscScalar transform[3][4][4] = {{{0.}}};
1039d7d2d1d2SJames Wright   for (PetscInt d = 0; d < dim; d++) {
1040d7d2d1d2SJames Wright     IS              donor_is, periodic_is;
1041d7d2d1d2SJames Wright     const PetscInt *donor_faces = NULL, *periodic_faces = NULL;
1042d7d2d1d2SJames Wright     PetscInt        num_donor = 0, num_periodic = 0;
1043d7d2d1d2SJames Wright     PetscSF         centroidsf;
1044d7d2d1d2SJames Wright     PetscReal       donor_to_periodic_distance;
1045d7d2d1d2SJames Wright     const PetscInt  face_pairings[2][3][2] = {
1046d7d2d1d2SJames Wright       // 2D face pairings, {donor, periodic}
1047d7d2d1d2SJames Wright       {{4, 2}, {1, 3}},
1048d7d2d1d2SJames Wright       // 3D face pairings
1049d7d2d1d2SJames Wright       {{5, 6}, {3, 4}, {1, 2}}
1050d7d2d1d2SJames Wright     };
1051d7d2d1d2SJames Wright 
1052d7d2d1d2SJames Wright     if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue;
1053d7d2d1d2SJames Wright     {
1054d7d2d1d2SJames Wright       // Compute centroidsf, which is the mapping from donor faces to periodic faces
1055d7d2d1d2SJames Wright       // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face)
1056d7d2d1d2SJames Wright       PetscInt     coords_size, centroid_comps = dim - 1;
1057d7d2d1d2SJames Wright       PetscScalar *coords = NULL;
1058d7d2d1d2SJames Wright       PetscReal   *donor_centroids, *periodic_centroids;
1059d7d2d1d2SJames Wright       PetscReal    loc_periodic[2] = {PETSC_MIN_REAL, PETSC_MIN_REAL}, loc_periodic_global[2]; // Location of donor (0) and periodic (1) faces in periodic direction
1060d7d2d1d2SJames Wright 
1061d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is));
1062d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is));
1063d7d2d1d2SJames Wright       if (donor_is) {
1064d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(donor_is, &num_donor));
1065d7d2d1d2SJames Wright         PetscCall(ISGetIndices(donor_is, &donor_faces));
1066d7d2d1d2SJames Wright       }
1067d7d2d1d2SJames Wright       if (periodic_is) {
1068d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(periodic_is, &num_periodic));
1069d7d2d1d2SJames Wright         PetscCall(ISGetIndices(periodic_is, &periodic_faces));
1070d7d2d1d2SJames Wright       }
1071d7d2d1d2SJames Wright       PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids));
1072d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_donor; f++) {
1073d7d2d1d2SJames Wright         PetscInt face = donor_faces[f], num_coords;
1074d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1075d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1076d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1077d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1078d7d2d1d2SJames Wright           loc_periodic[0]     = PetscRealPart(coords[c * dim + d]);
1079d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1080d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1081d7d2d1d2SJames Wright             donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1082d7d2d1d2SJames Wright             comp_index++;
1083d7d2d1d2SJames Wright           }
1084d7d2d1d2SJames Wright         }
1085d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1086d7d2d1d2SJames Wright       }
1087d7d2d1d2SJames Wright 
1088d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_periodic; f++) {
1089d7d2d1d2SJames Wright         PetscInt face = periodic_faces[f], num_coords;
1090d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1091d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1092d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1093d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1094d7d2d1d2SJames Wright           loc_periodic[1]     = PetscRealPart(coords[c * dim + d]);
1095d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1096d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1097d7d2d1d2SJames Wright             periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1098d7d2d1d2SJames Wright             comp_index++;
1099d7d2d1d2SJames Wright           }
1100d7d2d1d2SJames Wright         }
1101d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1102d7d2d1d2SJames Wright       }
1103d7d2d1d2SJames Wright       PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
1104d7d2d1d2SJames Wright       donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0];
1105d7d2d1d2SJames Wright 
1106d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &centroidsf));
1107d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids));
1108d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view"));
1109d7d2d1d2SJames Wright       PetscCall(PetscFree2(donor_centroids, periodic_centroids));
1110d7d2d1d2SJames Wright     }
1111d7d2d1d2SJames Wright 
1112d7d2d1d2SJames Wright     { // Create Isoperiodic SF using centroidsSF
1113d7d2d1d2SJames Wright       PetscInt           pStart, pEnd;
1114d7d2d1d2SJames Wright       PetscInt          *leaf_faces;
1115d7d2d1d2SJames Wright       const PetscSFNode *firemote;
1116d7d2d1d2SJames Wright       PetscSFNode       *isoperiodic_leaves;
1117d7d2d1d2SJames Wright 
1118d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &leaf_faces));
1119d7d2d1d2SJames Wright       PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1120d7d2d1d2SJames Wright       PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1121d7d2d1d2SJames Wright 
1122d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves));
1123d7d2d1d2SJames Wright       PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote));
1124d7d2d1d2SJames Wright       for (PetscInt l = 0; l < num_periodic; ++l) {
1125d7d2d1d2SJames Wright         isoperiodic_leaves[l].index = leaf_faces[l];
1126d7d2d1d2SJames Wright         isoperiodic_leaves[l].rank  = firemote[l].rank;
1127d7d2d1d2SJames Wright       }
1128d7d2d1d2SJames Wright 
1129d7d2d1d2SJames Wright       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
1130d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index]));
1131d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER));
1132d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view"));
1133d7d2d1d2SJames Wright       PetscCall(PetscFree(leaf_faces));
1134d7d2d1d2SJames Wright     }
1135d7d2d1d2SJames Wright 
1136d7d2d1d2SJames Wright     transform[periodic_sf_index][0][0] = 1;
1137d7d2d1d2SJames Wright     transform[periodic_sf_index][1][1] = 1;
1138d7d2d1d2SJames Wright     transform[periodic_sf_index][2][2] = 1;
1139d7d2d1d2SJames Wright     transform[periodic_sf_index][3][3] = 1;
1140d7d2d1d2SJames Wright     transform[periodic_sf_index][d][3] = donor_to_periodic_distance;
1141d7d2d1d2SJames Wright 
1142d7d2d1d2SJames Wright     periodic_sf_index++;
1143d7d2d1d2SJames Wright     PetscCall(PetscSFDestroy(&centroidsf));
1144d7d2d1d2SJames Wright     if (donor_is) {
1145d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(donor_is, &donor_faces));
1146d7d2d1d2SJames Wright       PetscCall(ISDestroy(&donor_is));
1147d7d2d1d2SJames Wright     }
1148d7d2d1d2SJames Wright     if (periodic_is) {
1149d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(periodic_is, &periodic_faces));
1150d7d2d1d2SJames Wright       PetscCall(ISDestroy(&periodic_is));
1151d7d2d1d2SJames Wright     }
1152d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0]));
1153d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1]));
1154d7d2d1d2SJames Wright   }
1155d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs));
1156d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform));
1157d7d2d1d2SJames Wright   for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p]));
1158d7d2d1d2SJames Wright 
1159d7d2d1d2SJames Wright   { // Update coordinate DM with new Face Sets label
1160d7d2d1d2SJames Wright     DM      cdm;
1161d7d2d1d2SJames Wright     DMLabel oldFaceSets, newFaceSets;
1162d7d2d1d2SJames Wright     PetscCall(DMGetCoordinateDM(dm, &cdm));
1163d7d2d1d2SJames Wright     PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets));
1164d7d2d1d2SJames Wright     if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE));
1165d7d2d1d2SJames Wright     PetscCall(DMLabelDuplicate(label, &newFaceSets));
1166d7d2d1d2SJames Wright     PetscCall(DMAddLabel(cdm, newFaceSets));
1167d7d2d1d2SJames Wright     PetscCall(DMLabelDestroy(&newFaceSets));
1168d7d2d1d2SJames Wright   }
11694054ae39SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
11704054ae39SJames Wright }
11714054ae39SJames Wright 
1172d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1173d71ae5a4SJacob Faibussowitsch {
11749318fe57SMatthew G. Knepley   DM      boundary, vol;
1175c22d3578SMatthew G. Knepley   DMLabel bdlabel;
1176d6218766SMatthew G. Knepley 
1177d6218766SMatthew G. Knepley   PetscFunctionBegin;
11784f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
1179c22d3578SMatthew G. Knepley   for (PetscInt i = 0; i < dim; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity is not supported for simplex meshes");
11809566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
11819566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
11829566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
11839566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
1184c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
1185c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
11865de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
118769d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
11884054ae39SJames Wright   if (interpolate) {
11894054ae39SJames Wright     PetscCall(DMPlexInterpolateInPlace_Internal(dm));
1190d7d2d1d2SJames Wright     PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity));
11914054ae39SJames Wright   }
11929566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
11933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1194d6218766SMatthew G. Knepley }
1195d6218766SMatthew G. Knepley 
1196d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
1197d71ae5a4SJacob Faibussowitsch {
1198ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
1199f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
1200f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
1201f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
1202f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
1203f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
1204f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
12053dfda0b1SToby Isaac   PetscInt    dim;
1206d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
12073dfda0b1SToby Isaac   PetscMPIInt rank;
12083dfda0b1SToby Isaac 
12093dfda0b1SToby Isaac   PetscFunctionBegin;
12109566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
12119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
12129566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
12139566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
12149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
12159371c9d4SSatish Balay   if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST || bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST || bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) {
12169371c9d4SSatish Balay     if (cutMarker) {
12179371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
12189371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
12199371c9d4SSatish Balay     }
1220d8211ee3SMatthew G. Knepley   }
12213dfda0b1SToby Isaac   switch (dim) {
12223dfda0b1SToby Isaac   case 2:
1223f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
1224f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1225f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
1226f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
12273dfda0b1SToby Isaac     break;
12283dfda0b1SToby Isaac   case 3:
1229f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1230f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
1231f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
1232f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
1233f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
1234f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
12353dfda0b1SToby Isaac     break;
1236d71ae5a4SJacob Faibussowitsch   default:
1237d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
12383dfda0b1SToby Isaac   }
12399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1240f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
1241f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
1242f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
1243f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
1244f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
1245f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
1246f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
12473dfda0b1SToby Isaac   }
12483dfda0b1SToby Isaac   {
1249dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1250dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1251dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
1252dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
1253dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
1254dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
12553dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
12563dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
12573dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
12583dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
12593dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
12603dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
12613dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
12623dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
12633dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
12643dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
12653dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
12663dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
12673dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
12683dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
12693dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
12703dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
12713dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
12723dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
12733dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
12743dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
12753dfda0b1SToby Isaac     Vec            coordinates;
12763dfda0b1SToby Isaac     PetscSection   coordSection;
12773dfda0b1SToby Isaac     PetscScalar   *coords;
12783dfda0b1SToby Isaac     PetscInt       coordSize;
12793dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
12803dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
12813dfda0b1SToby Isaac 
12829566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
128348a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
128448a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
128548a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
12869566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
12873dfda0b1SToby Isaac     /* Build cells */
12883dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
12893dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
12903dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
12913dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
12923dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
12933dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
12943dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
12953dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
12963dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
12973dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
12983dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
1299b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
130042206facSLisandro Dalcin           PetscInt cone[6];
13013dfda0b1SToby Isaac 
13023dfda0b1SToby Isaac           /* no boundary twisting in 3D */
13039371c9d4SSatish Balay           cone[0] = faceB;
13049371c9d4SSatish Balay           cone[1] = faceT;
13059371c9d4SSatish Balay           cone[2] = faceF;
13069371c9d4SSatish Balay           cone[3] = faceK;
13079371c9d4SSatish Balay           cone[4] = faceR;
13089371c9d4SSatish Balay           cone[5] = faceL;
13099566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
13109566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
13119566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
13129566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
13139566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
13143dfda0b1SToby Isaac         }
13153dfda0b1SToby Isaac       }
13163dfda0b1SToby Isaac     }
13173dfda0b1SToby Isaac     /* Build x faces */
13183dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
13193dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
13203dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
13213dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
13223dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
13233dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
13243dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
13253dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
1326b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
13273dfda0b1SToby Isaac           PetscInt cone[4];
13283dfda0b1SToby Isaac 
13293dfda0b1SToby Isaac           if (dim == 3) {
13303dfda0b1SToby Isaac             /* markers */
13313dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
13323dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
13339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
13349566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
13359371c9d4SSatish Balay               } else if (fx == 0) {
13369566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
13379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
13383dfda0b1SToby Isaac               }
13393dfda0b1SToby Isaac             }
13403dfda0b1SToby Isaac           }
13419371c9d4SSatish Balay           cone[0] = edgeB;
13429371c9d4SSatish Balay           cone[1] = edgeR;
13439371c9d4SSatish Balay           cone[2] = edgeT;
13449371c9d4SSatish Balay           cone[3] = edgeL;
13459566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
13469566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
13473dfda0b1SToby Isaac         }
13483dfda0b1SToby Isaac       }
13493dfda0b1SToby Isaac     }
13503dfda0b1SToby Isaac     /* Build y faces */
13513dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
135242206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
13533dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
13543dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
13553dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
13563dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
13573dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
13583dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
1359b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
13603dfda0b1SToby Isaac           PetscInt cone[4];
13613dfda0b1SToby Isaac 
13623dfda0b1SToby Isaac           if (dim == 3) {
13633dfda0b1SToby Isaac             /* markers */
13643dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
13653dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
13669566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
13679566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
13689371c9d4SSatish Balay               } else if (fy == 0) {
13699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
13709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
13713dfda0b1SToby Isaac               }
13723dfda0b1SToby Isaac             }
13733dfda0b1SToby Isaac           }
13749371c9d4SSatish Balay           cone[0] = edgeB;
13759371c9d4SSatish Balay           cone[1] = edgeR;
13769371c9d4SSatish Balay           cone[2] = edgeT;
13779371c9d4SSatish Balay           cone[3] = edgeL;
13789566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
13799566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
13803dfda0b1SToby Isaac         }
13813dfda0b1SToby Isaac       }
13823dfda0b1SToby Isaac     }
13833dfda0b1SToby Isaac     /* Build z faces */
13843dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
13853dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
13863dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
13873dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
13883dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
13893dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
13903dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
13913dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1392b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
13933dfda0b1SToby Isaac           PetscInt cone[4];
13943dfda0b1SToby Isaac 
13953dfda0b1SToby Isaac           if (dim == 2) {
13969371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
13979371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
13989371c9d4SSatish Balay               ornt[1] = -1;
13999371c9d4SSatish Balay             }
14009371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
14019371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
14029371c9d4SSatish Balay               ornt[2] = 0;
14039371c9d4SSatish Balay             }
14049566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
14059566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1406d1c88043SMatthew G. Knepley           } else {
14073dfda0b1SToby Isaac             /* markers */
14083dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
14093dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
14109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
14119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
14129371c9d4SSatish Balay               } else if (fz == 0) {
14139566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
14149566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
14153dfda0b1SToby Isaac               }
14163dfda0b1SToby Isaac             }
14173dfda0b1SToby Isaac           }
14189371c9d4SSatish Balay           cone[0] = edgeB;
14199371c9d4SSatish Balay           cone[1] = edgeR;
14209371c9d4SSatish Balay           cone[2] = edgeT;
14219371c9d4SSatish Balay           cone[3] = edgeL;
14229566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
14239566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
14243dfda0b1SToby Isaac         }
14253dfda0b1SToby Isaac       }
14263dfda0b1SToby Isaac     }
14273dfda0b1SToby Isaac     /* Build Z edges*/
14283dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
14293dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
14303dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
14313dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
14323dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
14333dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
14343dfda0b1SToby Isaac           PetscInt       cone[2];
14353dfda0b1SToby Isaac 
14369371c9d4SSatish Balay           cone[0] = vertexB;
14379371c9d4SSatish Balay           cone[1] = vertexT;
1438c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
14393dfda0b1SToby Isaac           if (dim == 3) {
14403dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
14413dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
14429566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1443c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1444c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1445c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
14469566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1447c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1448c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
14493dfda0b1SToby Isaac               }
14503dfda0b1SToby Isaac             }
14513dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
14523dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
14539566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1454c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1455c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1456c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
14579566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1458c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1459c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
14603dfda0b1SToby Isaac               }
14613dfda0b1SToby Isaac             }
14623dfda0b1SToby Isaac           }
14633dfda0b1SToby Isaac         }
14643dfda0b1SToby Isaac       }
14653dfda0b1SToby Isaac     }
14663dfda0b1SToby Isaac     /* Build Y edges*/
14673dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
14683dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
14693dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
14703dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
14713dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
14723dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
14733dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
14743dfda0b1SToby Isaac           PetscInt       cone[2];
14753dfda0b1SToby Isaac 
14769371c9d4SSatish Balay           cone[0] = vertexF;
14779371c9d4SSatish Balay           cone[1] = vertexK;
14789566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
14793dfda0b1SToby Isaac           if (dim == 2) {
14803dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
14813dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
14829566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
14839566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
14849566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1485c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1486d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
14879566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
14889566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
14899566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1490c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
14913dfda0b1SToby Isaac               }
1492d8211ee3SMatthew G. Knepley             } else {
14934c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
14949566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
14959566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1496c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
14973dfda0b1SToby Isaac               }
1498d8211ee3SMatthew G. Knepley             }
1499d8211ee3SMatthew G. Knepley           } else {
15003dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
15013dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
15029566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1503c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1504c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1505d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
15069566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1507c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1508c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
15093dfda0b1SToby Isaac               }
15103dfda0b1SToby Isaac             }
15113dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
15123dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
15139566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1514c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1515c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1516d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
15179566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1518c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1519c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
15203dfda0b1SToby Isaac               }
15213dfda0b1SToby Isaac             }
15223dfda0b1SToby Isaac           }
15233dfda0b1SToby Isaac         }
15243dfda0b1SToby Isaac       }
15253dfda0b1SToby Isaac     }
15263dfda0b1SToby Isaac     /* Build X edges*/
15273dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
15283dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
15293dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
15303dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
15313dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
15323dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
15333dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
15343dfda0b1SToby Isaac           PetscInt       cone[2];
15353dfda0b1SToby Isaac 
15369371c9d4SSatish Balay           cone[0] = vertexL;
15379371c9d4SSatish Balay           cone[1] = vertexR;
15389566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
15393dfda0b1SToby Isaac           if (dim == 2) {
15403dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
15413dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
15429566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
15439566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
15449566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1545c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1546d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
15479566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
15489566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
15499566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1550c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
15513dfda0b1SToby Isaac               }
1552d8211ee3SMatthew G. Knepley             } else {
15534c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
15549566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
15559566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1556c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
15573dfda0b1SToby Isaac               }
1558d8211ee3SMatthew G. Knepley             }
1559d8211ee3SMatthew G. Knepley           } else {
15603dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
15613dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
15629566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1563c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1564c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1565c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
15669566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1567c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1568c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
15693dfda0b1SToby Isaac               }
15703dfda0b1SToby Isaac             }
15713dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
15723dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
15739566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1574c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1575c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1576c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
15779566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1578c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1579c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
15803dfda0b1SToby Isaac               }
15813dfda0b1SToby Isaac             }
15823dfda0b1SToby Isaac           }
15833dfda0b1SToby Isaac         }
15843dfda0b1SToby Isaac       }
15853dfda0b1SToby Isaac     }
15869566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
15879566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
15883dfda0b1SToby Isaac     /* Build coordinates */
15899566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
15909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
15919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
15929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
15933dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
15949566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
15959566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
15963dfda0b1SToby Isaac     }
15979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
15989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
15999566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
16009566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
16019566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
16029566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
16039566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
16049566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
16053dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
16063dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
16073dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
16083dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
16093dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1610ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
16113dfda0b1SToby Isaac         }
16123dfda0b1SToby Isaac       }
16133dfda0b1SToby Isaac     }
16149566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
16159566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
16169566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
16173dfda0b1SToby Isaac   }
16183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16193dfda0b1SToby Isaac }
16203dfda0b1SToby Isaac 
1621d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1622d71ae5a4SJacob Faibussowitsch {
16239318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
16249318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1625552f7358SJed Brown 
1626552f7358SJed Brown   PetscFunctionBegin;
16274f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
16289318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
16299566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
16309371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
16319371c9d4SSatish Balay     fac[d] = faces[d];
16329371c9d4SSatish Balay     bdt[d] = periodicity[d];
16339371c9d4SSatish Balay   }
16349566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
16359371c9d4SSatish Balay   if (periodicity[0] == DM_BOUNDARY_PERIODIC || periodicity[0] == DM_BOUNDARY_TWIST || periodicity[1] == DM_BOUNDARY_PERIODIC || periodicity[1] == DM_BOUNDARY_TWIST || (dim > 2 && (periodicity[2] == DM_BOUNDARY_PERIODIC || periodicity[2] == DM_BOUNDARY_TWIST))) {
16366858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
16376858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1638552f7358SJed Brown 
16399318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
16406858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
16419318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
16429318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1643768d5fceSMatthew G. Knepley       }
16446858538eSMatthew G. Knepley     }
16454fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1646768d5fceSMatthew G. Knepley   }
16479566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
16483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16499318fe57SMatthew G. Knepley }
16509318fe57SMatthew G. Knepley 
16515dca41c3SJed Brown static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, DMPlexShape shape, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1652d71ae5a4SJacob Faibussowitsch {
16539318fe57SMatthew G. Knepley   PetscFunctionBegin;
165446139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
16555dca41c3SJed Brown   if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
16566725e60dSJed Brown   else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
16579566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
16589566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
16599318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1660768d5fceSMatthew G. Knepley     DM udm;
1661768d5fceSMatthew G. Knepley 
16629566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
16639566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
166469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1665768d5fceSMatthew G. Knepley   }
166646139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
16673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1668c8c68bd8SToby Isaac }
1669c8c68bd8SToby Isaac 
16705d83a8b1SBarry Smith /*@
1671768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1672768d5fceSMatthew G. Knepley 
1673d083f849SBarry Smith   Collective
1674768d5fceSMatthew G. Knepley 
1675768d5fceSMatthew G. Knepley   Input Parameters:
1676a1cb98faSBarry Smith + comm               - The communicator for the `DM` object
1677768d5fceSMatthew G. Knepley . dim                - The spatial dimension
1678a1cb98faSBarry Smith . simplex            - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
167920f4b53cSBarry Smith . faces              - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
168020f4b53cSBarry Smith . lower              - The lower left corner, or `NULL` for (0, 0, 0)
168120f4b53cSBarry Smith . upper              - The upper right corner, or `NULL` for (1, 1, 1)
168220f4b53cSBarry Smith . periodicity        - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
168342108689Sksagiyam . interpolate        - Flag to create intermediate mesh pieces (edges, faces)
168442108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes
168542108689Sksagiyam - sparseLocalize     - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes
1686768d5fceSMatthew G. Knepley 
1687768d5fceSMatthew G. Knepley   Output Parameter:
1688a1cb98faSBarry Smith . dm - The `DM` object
1689768d5fceSMatthew G. Knepley 
1690768d5fceSMatthew G. Knepley   Level: beginner
1691768d5fceSMatthew G. Knepley 
1692a1cb98faSBarry Smith   Note:
1693a1cb98faSBarry Smith   To customize this mesh using options, use
1694a1cb98faSBarry Smith .vb
1695a1cb98faSBarry Smith   DMCreate(comm, &dm);
1696a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1697a1cb98faSBarry Smith   DMSetFromOptions(dm);
1698a1cb98faSBarry Smith .ve
1699a1cb98faSBarry Smith   and use the options in `DMSetFromOptions()`.
1700a1cb98faSBarry Smith 
1701a4e35b19SJacob Faibussowitsch   Here is the numbering returned for 2 faces in each direction for tensor cells\:
1702a1cb98faSBarry Smith .vb
1703a1cb98faSBarry Smith  10---17---11---18----12
1704a1cb98faSBarry Smith   |         |         |
1705a1cb98faSBarry Smith   |         |         |
1706a1cb98faSBarry Smith  20    2   22    3    24
1707a1cb98faSBarry Smith   |         |         |
1708a1cb98faSBarry Smith   |         |         |
1709a1cb98faSBarry Smith   7---15----8---16----9
1710a1cb98faSBarry Smith   |         |         |
1711a1cb98faSBarry Smith   |         |         |
1712a1cb98faSBarry Smith  19    0   21    1   23
1713a1cb98faSBarry Smith   |         |         |
1714a1cb98faSBarry Smith   |         |         |
1715a1cb98faSBarry Smith   4---13----5---14----6
1716a1cb98faSBarry Smith .ve
1717a1cb98faSBarry Smith   and for simplicial cells
1718a1cb98faSBarry Smith .vb
1719a1cb98faSBarry Smith  14----8---15----9----16
1720a1cb98faSBarry Smith   |\     5  |\      7 |
1721a1cb98faSBarry Smith   | \       | \       |
1722a1cb98faSBarry Smith  13   2    14    3    15
1723a1cb98faSBarry Smith   | 4   \   | 6   \   |
1724a1cb98faSBarry Smith   |       \ |       \ |
1725a1cb98faSBarry Smith  11----6---12----7----13
1726a1cb98faSBarry Smith   |\        |\        |
1727a1cb98faSBarry Smith   | \    1  | \     3 |
1728a1cb98faSBarry Smith  10   0    11    1    12
1729a1cb98faSBarry Smith   | 0   \   | 2   \   |
1730a1cb98faSBarry Smith   |       \ |       \ |
1731a1cb98faSBarry Smith   8----4----9----5----10
1732a1cb98faSBarry Smith .ve
1733a1cb98faSBarry Smith 
17341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1735768d5fceSMatthew G. Knepley @*/
173642108689Sksagiyam PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, PetscInt localizationHeight, PetscBool sparseLocalize, DM *dm)
1737d71ae5a4SJacob Faibussowitsch {
17389318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1739fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1740fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1741fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1742552f7358SJed Brown 
1743768d5fceSMatthew G. Knepley   PetscFunctionBegin;
17449566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
17459566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
17465dca41c3SJed Brown   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
174742108689Sksagiyam   if (periodicity) {
174842108689Sksagiyam     DM cdm;
174942108689Sksagiyam 
175042108689Sksagiyam     PetscCall(DMGetCoordinateDM(*dm, &cdm));
175142108689Sksagiyam     PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight));
175242108689Sksagiyam     PetscCall(DMSetSparseLocalize(*dm, sparseLocalize));
175342108689Sksagiyam     PetscCall(DMLocalizeCoordinates(*dm));
175442108689Sksagiyam   }
17553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17569318fe57SMatthew G. Knepley }
1757fdbf62faSLisandro Dalcin 
1758d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1759d71ae5a4SJacob Faibussowitsch {
17609318fe57SMatthew G. Knepley   DM       bdm, vol;
17619318fe57SMatthew G. Knepley   PetscInt i;
17629318fe57SMatthew G. Knepley 
17639318fe57SMatthew G. Knepley   PetscFunctionBegin;
17641fcf445aSMatthew G. Knepley   // TODO Now we can support periodicity
176508401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
17669566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
17679566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
17689566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
176946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0));
17709566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
17711fcf445aSMatthew G. Knepley   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol));
177246139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0));
17739566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
177469d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
17759318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
17769318fe57SMatthew G. Knepley     Vec          v;
17779318fe57SMatthew G. Knepley     PetscScalar *x;
17789318fe57SMatthew G. Knepley     PetscInt     cDim, n;
17799318fe57SMatthew G. Knepley 
17809566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
17819566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
17829566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
17839566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
17849318fe57SMatthew G. Knepley     x += cDim;
17859318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
17869566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
17879566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
17889318fe57SMatthew G. Knepley   }
17893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1790552f7358SJed Brown }
1791552f7358SJed Brown 
179200dabe28SStefano Zampini /*@
179339f4f5dbSPierre Jolivet   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells.
179400dabe28SStefano Zampini 
1795d083f849SBarry Smith   Collective
179600dabe28SStefano Zampini 
179700dabe28SStefano Zampini   Input Parameters:
1798a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
179920f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1, 1, 1)
180020f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
180120f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
180220f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
1803a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
180400dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
180500dabe28SStefano Zampini 
180600dabe28SStefano Zampini   Output Parameter:
1807a1cb98faSBarry Smith . dm - The `DM` object
180800dabe28SStefano Zampini 
180900dabe28SStefano Zampini   Level: beginner
181000dabe28SStefano Zampini 
18111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
181200dabe28SStefano Zampini @*/
1813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1814d71ae5a4SJacob Faibussowitsch {
18159318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
181600dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
181700dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
181800dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
181900dabe28SStefano Zampini 
182000dabe28SStefano Zampini   PetscFunctionBegin;
18219566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
18229566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
18239566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1824d410b0cfSMatthew G. Knepley   if (!interpolate) {
1825d410b0cfSMatthew G. Knepley     DM udm;
182600dabe28SStefano Zampini 
18279566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
182869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
182900dabe28SStefano Zampini   }
18307ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
18313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
183200dabe28SStefano Zampini }
183300dabe28SStefano Zampini 
1834cfb853baSMatthew G. Knepley /*
1835cfb853baSMatthew G. Knepley   DMPlexTensorPointLexicographic_Private - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max' for that dimension.
1836cfb853baSMatthew G. Knepley 
1837cfb853baSMatthew G. Knepley   Input Parameters:
1838cfb853baSMatthew G. Knepley + len - The length of the tuple
1839cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max)
1840cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
1841cfb853baSMatthew G. Knepley 
1842cfb853baSMatthew G. Knepley   Output Parameter:
184320f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
1844cfb853baSMatthew G. Knepley 
1845cfb853baSMatthew G. Knepley   Level: developer
1846cfb853baSMatthew G. Knepley 
184720f4b53cSBarry Smith   Note:
184820f4b53cSBarry Smith   Ordering is lexicographic with lowest index as least significant in ordering.
184920f4b53cSBarry Smith   e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}.
185020f4b53cSBarry Smith 
1851cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal()
1852cfb853baSMatthew G. Knepley */
1853cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[])
1854cfb853baSMatthew G. Knepley {
1855cfb853baSMatthew G. Knepley   PetscInt i;
1856cfb853baSMatthew G. Knepley 
1857cfb853baSMatthew G. Knepley   PetscFunctionBegin;
1858cfb853baSMatthew G. Knepley   for (i = 0; i < len; ++i) {
1859cfb853baSMatthew G. Knepley     if (tup[i] < max[i] - 1) {
1860cfb853baSMatthew G. Knepley       break;
1861cfb853baSMatthew G. Knepley     } else {
1862cfb853baSMatthew G. Knepley       tup[i] = 0;
1863cfb853baSMatthew G. Knepley     }
1864cfb853baSMatthew G. Knepley   }
1865cfb853baSMatthew G. Knepley   if (i == len) tup[i - 1] = max[i - 1];
1866cfb853baSMatthew G. Knepley   else ++tup[i];
18673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1868cfb853baSMatthew G. Knepley }
1869cfb853baSMatthew G. Knepley 
1870cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[])
1871cfb853baSMatthew G. Knepley {
18728d2ec52aSSatish Balay   PetscInt idx = tup[len - 1];
1873cfb853baSMatthew G. Knepley 
18748d2ec52aSSatish Balay   for (PetscInt i = len - 2; i >= 0; --i) {
1875cfb853baSMatthew G. Knepley     idx *= max[i];
1876cfb853baSMatthew G. Knepley     idx += tup[i];
1877cfb853baSMatthew G. Knepley   }
1878cfb853baSMatthew G. Knepley   return idx;
1879cfb853baSMatthew G. Knepley }
1880cfb853baSMatthew G. Knepley 
18818d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[])
1882cfb853baSMatthew G. Knepley {
18838d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
18848d2ec52aSSatish Balay     tup[i] = idx % max[i];
18858d2ec52aSSatish Balay     idx    = (idx - tup[i]) / max[i];
18868d2ec52aSSatish Balay   }
18878d2ec52aSSatish Balay }
18888d2ec52aSSatish Balay 
18898d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[])
18908d2ec52aSSatish Balay {
18918d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
18928d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
18938d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
18948d2ec52aSSatish Balay     const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i];
18958d2ec52aSSatish Balay 
18968d2ec52aSSatish Balay     if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1);
18978d2ec52aSSatish Balay     else ranks[i] = rem + (idx - rem * (div + 1)) / div;
18988d2ec52aSSatish Balay   }
18998d2ec52aSSatish Balay }
19008d2ec52aSSatish Balay 
19018d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[])
19028d2ec52aSSatish Balay {
19038d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
19048d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
19058d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
19068d2ec52aSSatish Balay 
19078d2ec52aSSatish Balay     sizes[i] = ranks[i] < rem ? div + 1 : div;
19088d2ec52aSSatish Balay   }
19098d2ec52aSSatish Balay }
19108d2ec52aSSatish Balay 
19118d2ec52aSSatish Balay /*
19128d2ec52aSSatish Balay   In serial, the mesh is completely periodic. In parallel, we will include a layer of ghost vertices around the patch, so our edges will not wrap around in parallel. This will instead be handled by the SF.
19138d2ec52aSSatish Balay 
19148d2ec52aSSatish Balay   The cone for all edges will always be complete. Even in the presence of boundaries, we will keep all support sizes constant. When an edge would not exist in the support, we will create one to wrap back periodically. This allows for uniform stencils, and that edge will not be used for computation.
19158d2ec52aSSatish Balay 
19168d2ec52aSSatish Balay   All point which do not attain the vertex lower or upper bound in any dimension are owned, the rest are leaves owned by another process and present in the SF.
1917dfe9cfe5SMatthew Knepley 
1918dfe9cfe5SMatthew Knepley   Parallel Layout:
1919dfe9cfe5SMatthew Knepley 
1920dfe9cfe5SMatthew Knepley   We create a cubic process grid of dimension P^{1/d} on each side. The IndexToTuple_Private() function maps the global rank to the local rank in each dimension. We divide edges using the PETSc distribution rule in each dimension, and then add overlap. TupleToRanks_Private() returns the local rank in ech dimension for a tuple. RanksToSizes_Private() gives the size in each dimension for the domain with those local ranks.
19218d2ec52aSSatish Balay */
19228d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[])
19238d2ec52aSSatish Balay {
19248d2ec52aSSatish Balay   const PetscInt debug = ((DM_Plex *)dm->data)->printAdj;
19258d2ec52aSSatish Balay   PetscSF        sf;
1926cfb853baSMatthew G. Knepley   Vec            coordinates;
1927cfb853baSMatthew G. Knepley   PetscSection   coordSection;
1928cfb853baSMatthew G. Knepley   DMLabel        cutLabel    = NULL;
1929cfb853baSMatthew G. Knepley   PetscBool      cutMarker   = PETSC_FALSE;
1930cfb853baSMatthew G. Knepley   PetscBool      periodic    = PETSC_FALSE;
19318d2ec52aSSatish Balay   PetscInt       numCells    = 1;
19328d2ec52aSSatish Balay   PetscInt       numVertices = 1;
19338d2ec52aSSatish Balay   PetscSFNode   *remotes;
1934cfb853baSMatthew G. Knepley   PetscScalar   *coords;
19358d2ec52aSSatish Balay   PetscInt      *procs;     // The number of processes along each dimension
19368d2ec52aSSatish Balay   PetscInt      *lrank;     // Rank in each dimension, lrank[d] \in [0, procs[d])
19378d2ec52aSSatish Balay   PetscInt      *ledges;    // The number of edges along each dimension for this process
19388d2ec52aSSatish Balay   PetscInt      *vstart;    // The first vertex along each dimension on this processes
19398d2ec52aSSatish Balay   PetscInt      *vertices;  // The number of vertices along each dimension on this process
19408d2ec52aSSatish Balay   PetscInt      *rvert;     // The global (not local) vertex number along each dimension
19418d2ec52aSSatish Balay   PetscInt      *rrank;     // The rank along each dimension for the process owning rvert[]
19428d2ec52aSSatish Balay   PetscInt      *rvertices; // The number of vertices along each dimension for the process rrank[]
19438d2ec52aSSatish Balay   PetscInt      *vert, *vtmp, *supp, cone[2], *leaves;
19448d2ec52aSSatish Balay   PetscInt       cell = 0, coordSize, Nl = 0, Nl2 = 0;
19458d2ec52aSSatish Balay   PetscMPIInt    rank, size;
19468d2ec52aSSatish Balay   MPI_Comm       comm;
1947cfb853baSMatthew G. Knepley 
1948cfb853baSMatthew G. Knepley   PetscFunctionBegin;
19498d2ec52aSSatish Balay   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
19508d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_rank(comm, &rank));
19518d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_size(comm, &size));
1952cfb853baSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
19538d2ec52aSSatish Balay   PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
19548d2ec52aSSatish Balay   PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp));
19558d2ec52aSSatish Balay   PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp));
1956cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
1957cfb853baSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
19588d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE;
1959cfb853baSMatthew G. Knepley   if (periodic && cutMarker) {
1960cfb853baSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, "periodic_cut"));
1961cfb853baSMatthew G. Knepley     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
1962cfb853baSMatthew G. Knepley   }
19638d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now");
19648d2ec52aSSatish Balay   overlap = overlap == PETSC_DETERMINE ? 1 : overlap;
19658d2ec52aSSatish Balay   PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap);
19668d2ec52aSSatish Balay   if (size > 1) {
19678d2ec52aSSatish Balay     PetscInt Npr = 1;
19688d2ec52aSSatish Balay 
19698d2ec52aSSatish Balay     // Make process grid
19708d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "Process grid:"));
19718d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
19728d2ec52aSSatish Balay       procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim));
19738d2ec52aSSatish Balay       Npr *= procs[d];
19748d2ec52aSSatish Balay       if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d]));
19758d2ec52aSSatish Balay     }
19768d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "\n"));
19778d2ec52aSSatish Balay     PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size);
19788d2ec52aSSatish Balay     IndexToTuple_Private(dim, procs, rank, lrank);
19798d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
19808d2ec52aSSatish Balay       ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0);
19818d2ec52aSSatish Balay       vstart[d] = 0;
19828d2ec52aSSatish Balay       for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0);
19838d2ec52aSSatish Balay       vstart[d] -= overlap; // For halo
19848d2ec52aSSatish Balay     }
19858d2ec52aSSatish Balay   } else {
19868d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
19878d2ec52aSSatish Balay       procs[d]  = 1;
19888d2ec52aSSatish Balay       ledges[d] = edges[d];
19898d2ec52aSSatish Balay     }
19908d2ec52aSSatish Balay   }
19918d2ec52aSSatish Balay   // Calculate local patch size
19928d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) {
19938d2ec52aSSatish Balay     vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0);
1994cfb853baSMatthew G. Knepley     numVertices *= vertices[d];
1995cfb853baSMatthew G. Knepley   }
1996cfb853baSMatthew G. Knepley   numCells = numVertices * dim;
1997cfb853baSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19988d2ec52aSSatish Balay   for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2));
19998d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim));
2000cfb853baSMatthew G. Knepley   PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */
2001cfb853baSMatthew G. Knepley   /* Build cell cones and vertex supports */
2002cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "celltype"));
20038d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank));
2004cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2005cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells;
2006cfb853baSMatthew G. Knepley     PetscInt       s      = 0;
20078d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2008cfb853baSMatthew G. Knepley 
20098d2ec52aSSatish Balay     if (debug) {
20108d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
20118d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d]));
20128d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
20138d2ec52aSSatish Balay     }
2014cfb853baSMatthew G. Knepley     PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT));
20158d2ec52aSSatish Balay     // Define edge cones
20168d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20178d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2018cfb853baSMatthew G. Knepley       vtmp[d] = (vert[d] + 1) % vertices[d];
2019cfb853baSMatthew G. Knepley       cone[0] = vertex;
2020cfb853baSMatthew G. Knepley       cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells;
20218d2ec52aSSatish Balay       if (debug) {
20228d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ":", cone[1]));
20238d2ec52aSSatish Balay         for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e]));
20248d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
20258d2ec52aSSatish Balay       }
2026cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, cell, cone));
2027cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT));
20288d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]));
2029cfb853baSMatthew G. Knepley       ++cell;
20308d2ec52aSSatish Balay       // Shared vertices are any in the first or last overlap layers
20318d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
2032cfb853baSMatthew G. Knepley     }
20338d2ec52aSSatish Balay     if (size > 1 && leaf) ++Nl;
20348d2ec52aSSatish Balay     // Define vertex supports
20358d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20368d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2037cfb853baSMatthew G. Knepley       vtmp[d]   = (vert[d] + vertices[d] - 1) % vertices[d];
2038cfb853baSMatthew G. Knepley       supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d;
2039cfb853baSMatthew G. Knepley       supp[s++] = (vertex - numCells) * dim + d;
2040cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetSupport(dm, vertex, supp));
2041cfb853baSMatthew G. Knepley     }
2042cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2043cfb853baSMatthew G. Knepley   }
20448d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2045cfb853baSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
20468d2ec52aSSatish Balay   // Allocate for SF
20478d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &leaves));
20488d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &remotes));
20498d2ec52aSSatish Balay   // Build coordinates
2050cfb853baSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
2051cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
2052cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
2053cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
20548d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) {
2055cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, dim));
2056cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
2057cfb853baSMatthew G. Knepley   }
2058cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
2059cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
20608d2ec52aSSatish Balay   PetscCall(VecCreate(comm, &coordinates));
2061cfb853baSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
2062cfb853baSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
2063cfb853baSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, dim));
2064cfb853baSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
2065cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
20668d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank));
20678d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) vert[d] = 0;
2068cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2069cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert);
20708d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2071cfb853baSMatthew G. Knepley 
20728d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20738d2ec52aSSatish Balay       coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]);
20748d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
20758d2ec52aSSatish Balay     }
20768d2ec52aSSatish Balay     if (size > 1 && leaf) {
20778d2ec52aSSatish Balay       PetscInt rnumCells = 1;
20788d2ec52aSSatish Balay 
20798d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d];
20808d2ec52aSSatish Balay       TupleToRanks_Private(dim, edges, procs, rvert, rrank);
20818d2ec52aSSatish Balay       leaves[Nl2]       = vertex + numCells;
20828d2ec52aSSatish Balay       remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank);
20838d2ec52aSSatish Balay       RanksToSizes_Private(dim, edges, procs, rrank, rvertices);
20848d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
20858d2ec52aSSatish Balay         rvertices[d] += 2 * overlap; // Add halo
20868d2ec52aSSatish Balay         rnumCells *= rvertices[d];
20878d2ec52aSSatish Balay       }
20888d2ec52aSSatish Balay       rnumCells *= dim;
20898d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
20908d2ec52aSSatish Balay         const PetscInt diff = rrank[d] - lrank[d];
20918d2ec52aSSatish Balay 
20928d2ec52aSSatish Balay         if (!diff) rvert[d] = vert[d];                                     // Vertex is local
20938d2ec52aSSatish Balay         else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d];     // Wrap around at the bottom
20948d2ec52aSSatish Balay         else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top
20958d2ec52aSSatish Balay         else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap);
20968d2ec52aSSatish Balay         else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap;
20978d2ec52aSSatish Balay         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d);
20988d2ec52aSSatish Balay       }
20998d2ec52aSSatish Balay       remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells;
21008d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index));
21018d2ec52aSSatish Balay       ++Nl2;
21028d2ec52aSSatish Balay     }
21038d2ec52aSSatish Balay     if (debug) {
21048d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
21058d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d]));
21068d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d])));
21078d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
21088d2ec52aSSatish Balay     }
2109cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2110cfb853baSMatthew G. Knepley   }
21118d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2112cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
2113cfb853baSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
2114cfb853baSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
21158d2ec52aSSatish Balay   // Build SF
21168d2ec52aSSatish Balay   PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2);
21178d2ec52aSSatish Balay   PetscCall(DMGetPointSF(dm, &sf));
21188d2ec52aSSatish Balay   PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
21198d2ec52aSSatish Balay   if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD));
2120cfb853baSMatthew G. Knepley   //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper));
2121cfb853baSMatthew G. Knepley   // Attach the extent
2122cfb853baSMatthew G. Knepley   {
2123cfb853baSMatthew G. Knepley     PetscContainer c;
21248d2ec52aSSatish Balay     PetscInt      *extent, *lextent;
2125cfb853baSMatthew G. Knepley 
2126cfb853baSMatthew G. Knepley     PetscCall(PetscMalloc1(dim, &extent));
21278d2ec52aSSatish Balay     PetscCall(PetscMalloc1(dim, &lextent));
21288d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
21298d2ec52aSSatish Balay       extent[d]  = edges[d];
21308d2ec52aSSatish Balay       lextent[d] = ledges[d];
21318d2ec52aSSatish Balay     }
2132cfb853baSMatthew G. Knepley     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
213349abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
2134cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetPointer(c, extent));
2135cfb853baSMatthew G. Knepley     PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c));
2136cfb853baSMatthew G. Knepley     PetscCall(PetscContainerDestroy(&c));
21378d2ec52aSSatish Balay     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
21388d2ec52aSSatish Balay     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
21398d2ec52aSSatish Balay     PetscCall(PetscContainerSetPointer(c, lextent));
21408d2ec52aSSatish Balay     PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c));
21418d2ec52aSSatish Balay     PetscCall(PetscContainerDestroy(&c));
2142cfb853baSMatthew G. Knepley   }
21438d2ec52aSSatish Balay   PetscCall(PetscFree4(procs, lrank, rrank, supp));
21448d2ec52aSSatish Balay   PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp));
21453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2146cfb853baSMatthew G. Knepley }
2147cfb853baSMatthew G. Knepley 
2148cfb853baSMatthew G. Knepley /*@C
2149aaa8cc7dSPierre Jolivet   DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges.
2150cfb853baSMatthew G. Knepley 
2151cfb853baSMatthew G. Knepley   Collective
2152cfb853baSMatthew G. Knepley 
2153cfb853baSMatthew G. Knepley   Input Parameters:
21548d2ec52aSSatish Balay + comm    - The communicator for the `DM` object
2155cfb853baSMatthew G. Knepley . dim     - The spatial dimension
215620f4b53cSBarry Smith . edges   - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
215720f4b53cSBarry Smith . lower   - The lower left corner, or `NULL` for (0, 0, 0)
21588d2ec52aSSatish Balay . upper   - The upper right corner, or `NULL` for (1, 1, 1)
21598d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1)
2160cfb853baSMatthew G. Knepley 
2161cfb853baSMatthew G. Knepley   Output Parameter:
2162cfb853baSMatthew G. Knepley . dm - The DM object
2163cfb853baSMatthew G. Knepley 
216420f4b53cSBarry Smith   Level: beginner
216520f4b53cSBarry Smith 
216620f4b53cSBarry Smith   Note:
216720f4b53cSBarry Smith   If you want to customize this mesh using options, you just need to
216820f4b53cSBarry Smith .vb
216920f4b53cSBarry Smith   DMCreate(comm, &dm);
217020f4b53cSBarry Smith   DMSetType(dm, DMPLEX);
217120f4b53cSBarry Smith   DMSetFromOptions(dm);
217220f4b53cSBarry Smith .ve
217320f4b53cSBarry Smith   and use the options on the `DMSetFromOptions()` page.
2174cfb853baSMatthew G. Knepley 
2175cfb853baSMatthew G. Knepley   The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively,
217620f4b53cSBarry Smith .vb
217720f4b53cSBarry Smith  18--0-19--2-20--4-18
217820f4b53cSBarry Smith   |     |     |     |
217920f4b53cSBarry Smith  13    15    17    13
218020f4b53cSBarry Smith   |     |     |     |
218120f4b53cSBarry Smith  24-12-25-14-26-16-24
218220f4b53cSBarry Smith   |     |     |     |
218320f4b53cSBarry Smith   7     9    11     7
218420f4b53cSBarry Smith   |     |     |     |
218520f4b53cSBarry Smith  21--6-22--8-23-10-21
218620f4b53cSBarry Smith   |     |     |     |
218720f4b53cSBarry Smith   1     3     5     1
218820f4b53cSBarry Smith   |     |     |     |
218920f4b53cSBarry Smith  18--0-19--2-20--4-18
219020f4b53cSBarry Smith .ve
2191cfb853baSMatthew G. Knepley 
219276fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2193cfb853baSMatthew G. Knepley @*/
21948d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm)
2195cfb853baSMatthew G. Knepley {
2196cfb853baSMatthew G. Knepley   PetscInt       *edg;
2197cfb853baSMatthew G. Knepley   PetscReal      *low, *upp;
2198cfb853baSMatthew G. Knepley   DMBoundaryType *bdt;
2199cfb853baSMatthew G. Knepley   PetscInt        d;
2200cfb853baSMatthew G. Knepley 
2201cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2202cfb853baSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
2203cfb853baSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
2204cfb853baSMatthew G. Knepley   PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt));
2205cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
2206cfb853baSMatthew G. Knepley     edg[d] = edges ? edges[d] : 1;
2207cfb853baSMatthew G. Knepley     low[d] = lower ? lower[d] : 0.;
2208cfb853baSMatthew G. Knepley     upp[d] = upper ? upper[d] : 1.;
2209cfb853baSMatthew G. Knepley     bdt[d] = DM_BOUNDARY_PERIODIC;
2210cfb853baSMatthew G. Knepley   }
22118d2ec52aSSatish Balay   PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt));
2212cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(edg, low, upp, bdt));
22133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2214cfb853baSMatthew G. Knepley }
2215cfb853baSMatthew G. Knepley 
2216cc4c1da9SBarry Smith /*@
2217a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
2218a9074c1eSMatthew G. Knepley 
221920f4b53cSBarry Smith   Logically Collective
2220a9074c1eSMatthew G. Knepley 
2221a9074c1eSMatthew G. Knepley   Input Parameters:
222220f4b53cSBarry Smith + dm     - the `DM` context
2223a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
2224a9074c1eSMatthew G. Knepley 
2225a1cb98faSBarry Smith   Level: advanced
2226a1cb98faSBarry Smith 
2227a1cb98faSBarry Smith   Note:
2228a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
2229a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
2230a9074c1eSMatthew G. Knepley 
22311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
2232a9074c1eSMatthew G. Knepley @*/
2233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
2234d71ae5a4SJacob Faibussowitsch {
2235a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
2236a9074c1eSMatthew G. Knepley 
2237a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
2238a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
22409566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
22413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2242a9074c1eSMatthew G. Knepley }
2243a9074c1eSMatthew G. Knepley 
22449318fe57SMatthew G. Knepley /* Remap geometry to cylinder
224561a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
224661a622f3SMatthew G. Knepley 
22479318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
22489318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
22499318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
22500510c589SMatthew G. Knepley 
22519318fe57SMatthew G. Knepley        phi     = arctan(y/x)
22529318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
22539318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
22540510c589SMatthew G. Knepley 
22559318fe57SMatthew G. Knepley      so we remap them using
22560510c589SMatthew G. Knepley 
22579318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
22589318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
22590510c589SMatthew G. Knepley 
22609318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
22619318fe57SMatthew G. Knepley */
2262d71ae5a4SJacob Faibussowitsch static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
2263d71ae5a4SJacob Faibussowitsch {
22649318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
22659318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
226622cc497dSMatthew G. Knepley 
22679318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
22689318fe57SMatthew G. Knepley     f0[0] = u[0];
22699318fe57SMatthew G. Knepley     f0[1] = u[1];
22709318fe57SMatthew G. Knepley   } else {
22719318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
22720510c589SMatthew G. Knepley 
22739318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
22749318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
22759318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
22769318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
22779318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
22789318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
22799318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
22809318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
22819318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
22829318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
22839318fe57SMatthew G. Knepley     } else {
22849318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
22859318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
22869318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
22879318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
22889318fe57SMatthew G. Knepley     }
22899318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
22909318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
22919318fe57SMatthew G. Knepley   }
22929318fe57SMatthew G. Knepley   f0[2] = u[2];
22939318fe57SMatthew G. Knepley }
22940510c589SMatthew G. Knepley 
229549704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr)
2296d71ae5a4SJacob Faibussowitsch {
22970510c589SMatthew G. Knepley   const PetscInt dim = 3;
22989318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
2299d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
23000510c589SMatthew G. Knepley 
23010510c589SMatthew G. Knepley   PetscFunctionBegin;
230246139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
23039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
23049566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
23050510c589SMatthew G. Knepley   /* Create topology */
23060510c589SMatthew G. Knepley   {
23070510c589SMatthew G. Knepley     PetscInt cone[8], c;
23080510c589SMatthew G. Knepley 
2309dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
2310dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
2311006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
2312ae8bcbbbSMatthew G. Knepley       numCells *= 3;
2313dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
2314006a8963SMatthew G. Knepley     }
23159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
23169566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
23179566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
2318dd400576SPatrick Sanan     if (rank == 0) {
2319006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
23209371c9d4SSatish Balay         cone[0] = 15;
23219371c9d4SSatish Balay         cone[1] = 18;
23229371c9d4SSatish Balay         cone[2] = 17;
23239371c9d4SSatish Balay         cone[3] = 16;
23249371c9d4SSatish Balay         cone[4] = 31;
23259371c9d4SSatish Balay         cone[5] = 32;
23269371c9d4SSatish Balay         cone[6] = 33;
23279371c9d4SSatish Balay         cone[7] = 34;
23289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
23299371c9d4SSatish Balay         cone[0] = 16;
23309371c9d4SSatish Balay         cone[1] = 17;
23319371c9d4SSatish Balay         cone[2] = 24;
23329371c9d4SSatish Balay         cone[3] = 23;
23339371c9d4SSatish Balay         cone[4] = 32;
23349371c9d4SSatish Balay         cone[5] = 36;
23359371c9d4SSatish Balay         cone[6] = 37;
23369371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
23379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
23389371c9d4SSatish Balay         cone[0] = 18;
23399371c9d4SSatish Balay         cone[1] = 27;
23409371c9d4SSatish Balay         cone[2] = 24;
23419371c9d4SSatish Balay         cone[3] = 17;
23429371c9d4SSatish Balay         cone[4] = 34;
23439371c9d4SSatish Balay         cone[5] = 33;
23449371c9d4SSatish Balay         cone[6] = 37;
23459371c9d4SSatish Balay         cone[7] = 38;
23469566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
23479371c9d4SSatish Balay         cone[0] = 29;
23489371c9d4SSatish Balay         cone[1] = 27;
23499371c9d4SSatish Balay         cone[2] = 18;
23509371c9d4SSatish Balay         cone[3] = 15;
23519371c9d4SSatish Balay         cone[4] = 35;
23529371c9d4SSatish Balay         cone[5] = 31;
23539371c9d4SSatish Balay         cone[6] = 34;
23549371c9d4SSatish Balay         cone[7] = 38;
23559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
23569371c9d4SSatish Balay         cone[0] = 29;
23579371c9d4SSatish Balay         cone[1] = 15;
23589371c9d4SSatish Balay         cone[2] = 16;
23599371c9d4SSatish Balay         cone[3] = 23;
23609371c9d4SSatish Balay         cone[4] = 35;
23619371c9d4SSatish Balay         cone[5] = 36;
23629371c9d4SSatish Balay         cone[6] = 32;
23639371c9d4SSatish Balay         cone[7] = 31;
23649566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2365006a8963SMatthew G. Knepley 
23669371c9d4SSatish Balay         cone[0] = 31;
23679371c9d4SSatish Balay         cone[1] = 34;
23689371c9d4SSatish Balay         cone[2] = 33;
23699371c9d4SSatish Balay         cone[3] = 32;
23709371c9d4SSatish Balay         cone[4] = 19;
23719371c9d4SSatish Balay         cone[5] = 22;
23729371c9d4SSatish Balay         cone[6] = 21;
23739371c9d4SSatish Balay         cone[7] = 20;
23749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
23759371c9d4SSatish Balay         cone[0] = 32;
23769371c9d4SSatish Balay         cone[1] = 33;
23779371c9d4SSatish Balay         cone[2] = 37;
23789371c9d4SSatish Balay         cone[3] = 36;
23799371c9d4SSatish Balay         cone[4] = 22;
23809371c9d4SSatish Balay         cone[5] = 25;
23819371c9d4SSatish Balay         cone[6] = 26;
23829371c9d4SSatish Balay         cone[7] = 21;
23839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
23849371c9d4SSatish Balay         cone[0] = 34;
23859371c9d4SSatish Balay         cone[1] = 38;
23869371c9d4SSatish Balay         cone[2] = 37;
23879371c9d4SSatish Balay         cone[3] = 33;
23889371c9d4SSatish Balay         cone[4] = 20;
23899371c9d4SSatish Balay         cone[5] = 21;
23909371c9d4SSatish Balay         cone[6] = 26;
23919371c9d4SSatish Balay         cone[7] = 28;
23929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
23939371c9d4SSatish Balay         cone[0] = 35;
23949371c9d4SSatish Balay         cone[1] = 38;
23959371c9d4SSatish Balay         cone[2] = 34;
23969371c9d4SSatish Balay         cone[3] = 31;
23979371c9d4SSatish Balay         cone[4] = 30;
23989371c9d4SSatish Balay         cone[5] = 19;
23999371c9d4SSatish Balay         cone[6] = 20;
24009371c9d4SSatish Balay         cone[7] = 28;
24019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
24029371c9d4SSatish Balay         cone[0] = 35;
24039371c9d4SSatish Balay         cone[1] = 31;
24049371c9d4SSatish Balay         cone[2] = 32;
24059371c9d4SSatish Balay         cone[3] = 36;
24069371c9d4SSatish Balay         cone[4] = 30;
24079371c9d4SSatish Balay         cone[5] = 25;
24089371c9d4SSatish Balay         cone[6] = 22;
24099371c9d4SSatish Balay         cone[7] = 19;
24109566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
2411ae8bcbbbSMatthew G. Knepley 
24129371c9d4SSatish Balay         cone[0] = 19;
24139371c9d4SSatish Balay         cone[1] = 20;
24149371c9d4SSatish Balay         cone[2] = 21;
24159371c9d4SSatish Balay         cone[3] = 22;
24169371c9d4SSatish Balay         cone[4] = 15;
24179371c9d4SSatish Balay         cone[5] = 16;
24189371c9d4SSatish Balay         cone[6] = 17;
24199371c9d4SSatish Balay         cone[7] = 18;
24209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
24219371c9d4SSatish Balay         cone[0] = 22;
24229371c9d4SSatish Balay         cone[1] = 21;
24239371c9d4SSatish Balay         cone[2] = 26;
24249371c9d4SSatish Balay         cone[3] = 25;
24259371c9d4SSatish Balay         cone[4] = 16;
24269371c9d4SSatish Balay         cone[5] = 23;
24279371c9d4SSatish Balay         cone[6] = 24;
24289371c9d4SSatish Balay         cone[7] = 17;
24299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
24309371c9d4SSatish Balay         cone[0] = 20;
24319371c9d4SSatish Balay         cone[1] = 28;
24329371c9d4SSatish Balay         cone[2] = 26;
24339371c9d4SSatish Balay         cone[3] = 21;
24349371c9d4SSatish Balay         cone[4] = 18;
24359371c9d4SSatish Balay         cone[5] = 17;
24369371c9d4SSatish Balay         cone[6] = 24;
24379371c9d4SSatish Balay         cone[7] = 27;
24389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
24399371c9d4SSatish Balay         cone[0] = 30;
24409371c9d4SSatish Balay         cone[1] = 28;
24419371c9d4SSatish Balay         cone[2] = 20;
24429371c9d4SSatish Balay         cone[3] = 19;
24439371c9d4SSatish Balay         cone[4] = 29;
24449371c9d4SSatish Balay         cone[5] = 15;
24459371c9d4SSatish Balay         cone[6] = 18;
24469371c9d4SSatish Balay         cone[7] = 27;
24479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
24489371c9d4SSatish Balay         cone[0] = 30;
24499371c9d4SSatish Balay         cone[1] = 19;
24509371c9d4SSatish Balay         cone[2] = 22;
24519371c9d4SSatish Balay         cone[3] = 25;
24529371c9d4SSatish Balay         cone[4] = 29;
24539371c9d4SSatish Balay         cone[5] = 23;
24549371c9d4SSatish Balay         cone[6] = 16;
24559371c9d4SSatish Balay         cone[7] = 15;
24569566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
2457006a8963SMatthew G. Knepley       } else {
24589371c9d4SSatish Balay         cone[0] = 5;
24599371c9d4SSatish Balay         cone[1] = 8;
24609371c9d4SSatish Balay         cone[2] = 7;
24619371c9d4SSatish Balay         cone[3] = 6;
24629371c9d4SSatish Balay         cone[4] = 9;
24639371c9d4SSatish Balay         cone[5] = 12;
24649371c9d4SSatish Balay         cone[6] = 11;
24659371c9d4SSatish Balay         cone[7] = 10;
24669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
24679371c9d4SSatish Balay         cone[0] = 6;
24689371c9d4SSatish Balay         cone[1] = 7;
24699371c9d4SSatish Balay         cone[2] = 14;
24709371c9d4SSatish Balay         cone[3] = 13;
24719371c9d4SSatish Balay         cone[4] = 12;
24729371c9d4SSatish Balay         cone[5] = 15;
24739371c9d4SSatish Balay         cone[6] = 16;
24749371c9d4SSatish Balay         cone[7] = 11;
24759566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
24769371c9d4SSatish Balay         cone[0] = 8;
24779371c9d4SSatish Balay         cone[1] = 17;
24789371c9d4SSatish Balay         cone[2] = 14;
24799371c9d4SSatish Balay         cone[3] = 7;
24809371c9d4SSatish Balay         cone[4] = 10;
24819371c9d4SSatish Balay         cone[5] = 11;
24829371c9d4SSatish Balay         cone[6] = 16;
24839371c9d4SSatish Balay         cone[7] = 18;
24849566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
24859371c9d4SSatish Balay         cone[0] = 19;
24869371c9d4SSatish Balay         cone[1] = 17;
24879371c9d4SSatish Balay         cone[2] = 8;
24889371c9d4SSatish Balay         cone[3] = 5;
24899371c9d4SSatish Balay         cone[4] = 20;
24909371c9d4SSatish Balay         cone[5] = 9;
24919371c9d4SSatish Balay         cone[6] = 10;
24929371c9d4SSatish Balay         cone[7] = 18;
24939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
24949371c9d4SSatish Balay         cone[0] = 19;
24959371c9d4SSatish Balay         cone[1] = 5;
24969371c9d4SSatish Balay         cone[2] = 6;
24979371c9d4SSatish Balay         cone[3] = 13;
24989371c9d4SSatish Balay         cone[4] = 20;
24999371c9d4SSatish Balay         cone[5] = 15;
25009371c9d4SSatish Balay         cone[6] = 12;
25019371c9d4SSatish Balay         cone[7] = 9;
25029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2503006a8963SMatthew G. Knepley       }
2504d8c47e87SMatthew G. Knepley     }
25059566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
25069566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
25070510c589SMatthew G. Knepley   }
2508dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
25090510c589SMatthew G. Knepley   {
25100510c589SMatthew G. Knepley     Vec             coordinates;
25110510c589SMatthew G. Knepley     PetscSection    coordSection;
25120510c589SMatthew G. Knepley     PetscScalar    *coords;
25130510c589SMatthew G. Knepley     PetscInt        coordSize, v;
25140510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
25150510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
25160510c589SMatthew G. Knepley 
25170510c589SMatthew G. Knepley     /* Build coordinates */
25189566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
25199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
25209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
25219566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
25220510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
25239566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
25249566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
25250510c589SMatthew G. Knepley     }
25269566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
25279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25289566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25299566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25309566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25319566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
25329566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
25339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
2534dd400576SPatrick Sanan     if (rank == 0) {
25359371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
25369371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
25379371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
25389371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
25399371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
25409371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
25419371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
25429371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
25439371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
25449371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
25459371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
25469371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
25479371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
25489371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
25499371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
25509371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
25519371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
25529371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
25539371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
25549371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
25559371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
25569371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
25579371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
25589371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
25599371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
25609371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
25619371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
25629371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
25639371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
25649371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
25659371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
25669371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
25679371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
25689371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
25699371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
25709371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
25719371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
25729371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
25739371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
25749371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
25759371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
25769371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
25779371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
25789371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
25799371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
25809371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
25819371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
25829371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
2583ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
25849371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
25859371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
25869371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
25879371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
25889371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
25899371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
25909371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
25919371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
25929371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
25939371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
25949371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
25959371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
25969371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
25979371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
25989371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
25999371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
26009371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
26019371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
26029371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
26039371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
26049371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
26059371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
26069371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
26079371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
2608ae8bcbbbSMatthew G. Knepley       }
2609d8c47e87SMatthew G. Knepley     }
26109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
26119566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
26129566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
26130510c589SMatthew G. Knepley   }
2614006a8963SMatthew G. Knepley   /* Create periodicity */
2615006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
26166858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
26176858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
2618006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
2619ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
26206858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
2621006a8963SMatthew G. Knepley 
26226858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
26236858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
26244fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
2625006a8963SMatthew G. Knepley   }
2626dbc1dc17SMatthew G. Knepley   {
26279318fe57SMatthew G. Knepley     DM          cdm;
26289318fe57SMatthew G. Knepley     PetscDS     cds;
26299318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
2630dbc1dc17SMatthew G. Knepley 
263149704ca5SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
26329566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
26339566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
26349566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
2635dbc1dc17SMatthew G. Knepley   }
263646139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
263746139095SJed Brown 
26389318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
26399566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
264049704ca5SMatthew G. Knepley 
264149704ca5SMatthew G. Knepley   char        oldprefix[PETSC_MAX_PATH_LEN];
264249704ca5SMatthew G. Knepley   const char *prefix;
264349704ca5SMatthew G. Knepley 
264449704ca5SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
264549704ca5SMatthew G. Knepley   PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN));
264649704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_"));
264749704ca5SMatthew G. Knepley   for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) {
264849704ca5SMatthew G. Knepley     DM rdm;
264949704ca5SMatthew G. Knepley 
265049704ca5SMatthew G. Knepley     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
265149704ca5SMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &rdm));
265249704ca5SMatthew G. Knepley   }
265349704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix));
265449704ca5SMatthew G. Knepley   PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder));
265549704ca5SMatthew G. Knepley 
265649704ca5SMatthew G. Knepley   DMLabel         bdlabel, edgelabel;
265749704ca5SMatthew G. Knepley   IS              faceIS;
265849704ca5SMatthew G. Knepley   const PetscInt *faces;
265949704ca5SMatthew G. Knepley   PetscInt        Nf;
266049704ca5SMatthew G. Knepley 
266149704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
266249704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
266349704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "generatrix"));
266449704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "generatrix", &edgelabel));
266549704ca5SMatthew G. Knepley   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
266649704ca5SMatthew G. Knepley   // Remove faces on top and bottom
266749704ca5SMatthew G. Knepley   PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS));
2668ba1b3593SJeremy L Thompson   if (faceIS) {
266949704ca5SMatthew G. Knepley     PetscCall(ISGetLocalSize(faceIS, &Nf));
267049704ca5SMatthew G. Knepley     PetscCall(ISGetIndices(faceIS, &faces));
267149704ca5SMatthew G. Knepley     for (PetscInt f = 0; f < Nf; ++f) {
267249704ca5SMatthew G. Knepley       PetscReal vol, normal[3];
267349704ca5SMatthew G. Knepley 
267449704ca5SMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal));
267549704ca5SMatthew G. Knepley       if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1));
267649704ca5SMatthew G. Knepley     }
267749704ca5SMatthew G. Knepley     PetscCall(ISRestoreIndices(faceIS, &faces));
267849704ca5SMatthew G. Knepley     PetscCall(ISDestroy(&faceIS));
2679ba1b3593SJeremy L Thompson   }
268049704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, bdlabel));
268149704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, edgelabel));
26823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26830510c589SMatthew G. Knepley }
26840510c589SMatthew G. Knepley 
268524119c2aSMatthew G. Knepley /*@
26869318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
268724119c2aSMatthew G. Knepley 
2688d083f849SBarry Smith   Collective
268924119c2aSMatthew G. Knepley 
269024119c2aSMatthew G. Knepley   Input Parameters:
2691a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
269249704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction
269349704ca5SMatthew G. Knepley - Nr        - The number of refinements to carry out
269424119c2aSMatthew G. Knepley 
269524119c2aSMatthew G. Knepley   Output Parameter:
269620f4b53cSBarry Smith . dm - The `DM` object
269724119c2aSMatthew G. Knepley 
269824119c2aSMatthew G. Knepley   Level: beginner
269924119c2aSMatthew G. Knepley 
2700a1cb98faSBarry Smith   Note:
2701a4e35b19SJacob Faibussowitsch   Here is the output numbering looking from the bottom of the cylinder\:
2702a1cb98faSBarry Smith .vb
2703a1cb98faSBarry Smith        17-----14
2704a1cb98faSBarry Smith         |     |
2705a1cb98faSBarry Smith         |  2  |
2706a1cb98faSBarry Smith         |     |
2707a1cb98faSBarry Smith  17-----8-----7-----14
2708a1cb98faSBarry Smith   |     |     |     |
2709a1cb98faSBarry Smith   |  3  |  0  |  1  |
2710a1cb98faSBarry Smith   |     |     |     |
2711a1cb98faSBarry Smith  19-----5-----6-----13
2712a1cb98faSBarry Smith         |     |
2713a1cb98faSBarry Smith         |  4  |
2714a1cb98faSBarry Smith         |     |
2715a1cb98faSBarry Smith        19-----13
2716a1cb98faSBarry Smith 
2717a1cb98faSBarry Smith  and up through the top
2718a1cb98faSBarry Smith 
2719a1cb98faSBarry Smith        18-----16
2720a1cb98faSBarry Smith         |     |
2721a1cb98faSBarry Smith         |  2  |
2722a1cb98faSBarry Smith         |     |
2723a1cb98faSBarry Smith  18----10----11-----16
2724a1cb98faSBarry Smith   |     |     |     |
2725a1cb98faSBarry Smith   |  3  |  0  |  1  |
2726a1cb98faSBarry Smith   |     |     |     |
2727a1cb98faSBarry Smith  20-----9----12-----15
2728a1cb98faSBarry Smith         |     |
2729a1cb98faSBarry Smith         |  4  |
2730a1cb98faSBarry Smith         |     |
2731a1cb98faSBarry Smith        20-----15
2732a1cb98faSBarry Smith .ve
2733a1cb98faSBarry Smith 
27341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
273524119c2aSMatthew G. Knepley @*/
273649704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm)
2737d71ae5a4SJacob Faibussowitsch {
27389318fe57SMatthew G. Knepley   PetscFunctionBegin;
273949704ca5SMatthew G. Knepley   PetscAssertPointer(dm, 4);
27409566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
27419566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
274249704ca5SMatthew G. Knepley   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr));
27433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27449318fe57SMatthew G. Knepley }
27459318fe57SMatthew G. Knepley 
2746d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
2747d71ae5a4SJacob Faibussowitsch {
274824119c2aSMatthew G. Knepley   const PetscInt dim = 3;
2749412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
27509fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
275124119c2aSMatthew G. Knepley 
275224119c2aSMatthew G. Knepley   PetscFunctionBegin;
275363a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
275446139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
27559566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
27569566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2757412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
27589566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
275924119c2aSMatthew G. Knepley   /* Create topology */
276024119c2aSMatthew G. Knepley   {
276124119c2aSMatthew G. Knepley     PetscInt cone[6], c;
276224119c2aSMatthew G. Knepley 
2763dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
2764dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
27659566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
27669566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
27679566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
276824119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
27699371c9d4SSatish Balay       cone[0] = c + n * 1;
27709371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
27719371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
27729371c9d4SSatish Balay       cone[3] = c + n * 2;
27739371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
27749371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
27759566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
27769566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
277724119c2aSMatthew G. Knepley     }
27789566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
27799566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
278024119c2aSMatthew G. Knepley   }
278148a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
278224119c2aSMatthew G. Knepley   /* Create cylinder geometry */
278324119c2aSMatthew G. Knepley   {
278424119c2aSMatthew G. Knepley     Vec          coordinates;
278524119c2aSMatthew G. Knepley     PetscSection coordSection;
278624119c2aSMatthew G. Knepley     PetscScalar *coords;
2787412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
278824119c2aSMatthew G. Knepley 
278924119c2aSMatthew G. Knepley     /* Build coordinates */
27909566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
27919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
27929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
27939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
279424119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
27959566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
27969566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
279724119c2aSMatthew G. Knepley     }
27989566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
27999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
28009566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
28019566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
28029566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
28039566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
28049566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
28059566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
280624119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
28079371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
28089371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
28099371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
28109371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
28119371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
28129371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
281324119c2aSMatthew G. Knepley     }
2814dd400576SPatrick Sanan     if (rank == 0) {
28159371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
28169371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
28179371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
28189371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
28199371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
28209371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
28219fe9f049SMatthew G. Knepley     }
28229566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
28239566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
28249566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
282524119c2aSMatthew G. Knepley   }
282646139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
28279318fe57SMatthew G. Knepley   /* Interpolate */
28289566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
28293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28309318fe57SMatthew G. Knepley }
28319318fe57SMatthew G. Knepley 
28329318fe57SMatthew G. Knepley /*@
28339318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
28349318fe57SMatthew G. Knepley 
28359318fe57SMatthew G. Knepley   Collective
28369318fe57SMatthew G. Knepley 
28379318fe57SMatthew G. Knepley   Input Parameters:
2838a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
28399318fe57SMatthew G. Knepley . n           - The number of wedges around the origin
28409318fe57SMatthew G. Knepley - interpolate - Create edges and faces
28419318fe57SMatthew G. Knepley 
28429318fe57SMatthew G. Knepley   Output Parameter:
2843a1cb98faSBarry Smith . dm - The `DM` object
28449318fe57SMatthew G. Knepley 
28459318fe57SMatthew G. Knepley   Level: beginner
28469318fe57SMatthew G. Knepley 
28471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
28489318fe57SMatthew G. Knepley @*/
2849d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2850d71ae5a4SJacob Faibussowitsch {
28519318fe57SMatthew G. Knepley   PetscFunctionBegin;
28524f572ea9SToby Isaac   PetscAssertPointer(dm, 4);
28539566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
28549566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
28559566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
28563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
285724119c2aSMatthew G. Knepley }
285824119c2aSMatthew G. Knepley 
2859d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2860d71ae5a4SJacob Faibussowitsch {
286165a81367SMatthew G. Knepley   PetscReal prod = 0.0;
286265a81367SMatthew G. Knepley   PetscInt  i;
286365a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
286465a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
286565a81367SMatthew G. Knepley }
2866dd2b43ebSStefano Zampini 
2867d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2868d71ae5a4SJacob Faibussowitsch {
286965a81367SMatthew G. Knepley   PetscReal prod = 0.0;
287065a81367SMatthew G. Knepley   PetscInt  i;
287165a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
287265a81367SMatthew G. Knepley   return prod;
287365a81367SMatthew G. Knepley }
287465a81367SMatthew G. Knepley 
287551a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2876d71ae5a4SJacob Faibussowitsch static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
2877d71ae5a4SJacob Faibussowitsch {
287851a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
287951a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
288051a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
288151a74b61SMatthew G. Knepley 
288251a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
288351a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
288451a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
288551a74b61SMatthew G. Knepley }
288651a74b61SMatthew G. Knepley 
2887d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2888d71ae5a4SJacob Faibussowitsch {
288965a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
289065a81367SMatthew G. Knepley   PetscSection   coordSection;
289165a81367SMatthew G. Knepley   Vec            coordinates;
289265a81367SMatthew G. Knepley   PetscScalar   *coords;
289365a81367SMatthew G. Knepley   PetscReal     *coordsIn;
289407c565c5SJose E. Roman   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e;
289565a81367SMatthew G. Knepley   PetscMPIInt    rank;
289665a81367SMatthew G. Knepley 
289765a81367SMatthew G. Knepley   PetscFunctionBegin;
28989318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
289946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
29009566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
29019566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
29029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
290365a81367SMatthew G. Knepley   switch (dim) {
29045c344501SMatthew G. Knepley   case 1:
29055c344501SMatthew G. Knepley     numCells = 16;
29065c344501SMatthew G. Knepley     numVerts = numCells;
29075c344501SMatthew G. Knepley 
29085c344501SMatthew G. Knepley     // Build Topology
29095c344501SMatthew G. Knepley     PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
29105c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
29115c344501SMatthew G. Knepley     PetscCall(DMSetUp(dm));
29125c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; ++c) {
29135c344501SMatthew G. Knepley       PetscInt cone[2];
29145c344501SMatthew G. Knepley 
29155c344501SMatthew G. Knepley       cone[0] = c + numCells;
29165c344501SMatthew G. Knepley       cone[1] = (c + 1) % numVerts + numCells;
29175c344501SMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, c, cone));
29185c344501SMatthew G. Knepley     }
29195c344501SMatthew G. Knepley     PetscCall(DMPlexSymmetrize(dm));
29205c344501SMatthew G. Knepley     PetscCall(DMPlexStratify(dm));
29215c344501SMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn));
29225c344501SMatthew G. Knepley     for (PetscInt v = 0; v < numVerts; ++v) {
29235c344501SMatthew G. Knepley       const PetscReal rad = 2. * PETSC_PI * v / numVerts;
29245c344501SMatthew G. Knepley 
29255c344501SMatthew G. Knepley       coordsIn[v * embedDim + 0] = PetscCosReal(rad);
29265c344501SMatthew G. Knepley       coordsIn[v * embedDim + 1] = PetscSinReal(rad);
29275c344501SMatthew G. Knepley     }
29285c344501SMatthew G. Knepley     break;
292965a81367SMatthew G. Knepley   case 2:
293065a81367SMatthew G. Knepley     if (simplex) {
293151a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
293251a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
293365a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
293451a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
293565a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
293665a81367SMatthew G. Knepley       PetscInt        cone[3];
293707c565c5SJose E. Roman       PetscInt       *graph;
293865a81367SMatthew G. Knepley 
29399371c9d4SSatish Balay       vertex[0] *= R / radius;
29409371c9d4SSatish Balay       vertex[1] *= R / radius;
29419371c9d4SSatish Balay       vertex[2] *= R / radius;
2942dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2943dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
294465a81367SMatthew G. Knepley       firstVertex = numCells;
294551a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
294665a81367SMatthew G. Knepley 
294765a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
294865a81367SMatthew G. Knepley 
294965a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
295051a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
295165a81367SMatthew G. Knepley       */
295265a81367SMatthew G. Knepley       /* Construct vertices */
29539566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2954dd400576SPatrick Sanan       if (rank == 0) {
295507c565c5SJose E. Roman         for (PetscInt p = 0, i = 0; p < embedDim; ++p) {
295665a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
295765a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
295865a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
295965a81367SMatthew G. Knepley               ++i;
296065a81367SMatthew G. Knepley             }
296165a81367SMatthew G. Knepley           }
296265a81367SMatthew G. Knepley         }
296345da822fSValeria Barra       }
296465a81367SMatthew G. Knepley       /* Construct graph */
29659566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
296607c565c5SJose E. Roman       for (PetscInt i = 0; i < numVerts; ++i) {
296707c565c5SJose E. Roman         PetscInt k = 0;
296807c565c5SJose E. Roman         for (PetscInt j = 0; j < numVerts; ++j) {
29699371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
29709371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
29719371c9d4SSatish Balay             ++k;
29729371c9d4SSatish Balay           }
297365a81367SMatthew G. Knepley         }
297463a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
297565a81367SMatthew G. Knepley       }
297665a81367SMatthew G. Knepley       /* Build Topology */
29779566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
297807c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
29799566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
298065a81367SMatthew G. Knepley       /* Cells */
298107c565c5SJose E. Roman       for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
298207c565c5SJose E. Roman         for (PetscInt j = 0; j < i; ++j) {
298307c565c5SJose E. Roman           for (PetscInt k = 0; k < j; ++k) {
298465a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
29859371c9d4SSatish Balay               cone[0] = firstVertex + i;
29869371c9d4SSatish Balay               cone[1] = firstVertex + j;
29879371c9d4SSatish Balay               cone[2] = firstVertex + k;
298865a81367SMatthew G. Knepley               /* Check orientation */
298965a81367SMatthew G. Knepley               {
29909371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
29919371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
29929371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
29939371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
29949371c9d4SSatish Balay                 };
299565a81367SMatthew G. Knepley                 PetscReal normal[3];
299665a81367SMatthew G. Knepley                 PetscInt  e, f;
299765a81367SMatthew G. Knepley 
299865a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
299965a81367SMatthew G. Knepley                   normal[d] = 0.0;
300065a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
3001ad540459SPierre Jolivet                     for (f = 0; f < embedDim; ++f) normal[d] += epsilon[d][e][f] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]);
300265a81367SMatthew G. Knepley                   }
300365a81367SMatthew G. Knepley                 }
30049371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
30059371c9d4SSatish Balay                   PetscInt tmp = cone[1];
30069371c9d4SSatish Balay                   cone[1]      = cone[2];
30079371c9d4SSatish Balay                   cone[2]      = tmp;
300865a81367SMatthew G. Knepley                 }
300965a81367SMatthew G. Knepley               }
30109566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
301165a81367SMatthew G. Knepley             }
301265a81367SMatthew G. Knepley           }
301365a81367SMatthew G. Knepley         }
301465a81367SMatthew G. Knepley       }
30159566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
30169566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
30179566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
301865a81367SMatthew G. Knepley     } else {
30192829fed8SMatthew G. Knepley       /*
30202829fed8SMatthew G. Knepley         12-21--13
30212829fed8SMatthew G. Knepley          |     |
30222829fed8SMatthew G. Knepley         25  4  24
30232829fed8SMatthew G. Knepley          |     |
30242829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
30252829fed8SMatthew G. Knepley    |     |     |     |
30262829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
30272829fed8SMatthew G. Knepley    |     |     |     |
30282829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
30292829fed8SMatthew G. Knepley          |     |
30302829fed8SMatthew G. Knepley         20  1  19
30312829fed8SMatthew G. Knepley          |     |
30322829fed8SMatthew G. Knepley         10-18--11
30332829fed8SMatthew G. Knepley          |     |
30342829fed8SMatthew G. Knepley         23  2  22
30352829fed8SMatthew G. Knepley          |     |
30362829fed8SMatthew G. Knepley         12-21--13
30372829fed8SMatthew G. Knepley        */
30382829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
30392829fed8SMatthew G. Knepley 
3040dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
3041dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
3042dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
304365a81367SMatthew G. Knepley       firstVertex = numCells;
304465a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
30452829fed8SMatthew G. Knepley       /* Build Topology */
30469566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
304707c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
304848a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
30499566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3050dd400576SPatrick Sanan       if (rank == 0) {
30512829fed8SMatthew G. Knepley         /* Cell 0 */
30529371c9d4SSatish Balay         cone[0] = 14;
30539371c9d4SSatish Balay         cone[1] = 15;
30549371c9d4SSatish Balay         cone[2] = 16;
30559371c9d4SSatish Balay         cone[3] = 17;
30569566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
30579371c9d4SSatish Balay         ornt[0] = 0;
30589371c9d4SSatish Balay         ornt[1] = 0;
30599371c9d4SSatish Balay         ornt[2] = 0;
30609371c9d4SSatish Balay         ornt[3] = 0;
30619566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
30622829fed8SMatthew G. Knepley         /* Cell 1 */
30639371c9d4SSatish Balay         cone[0] = 18;
30649371c9d4SSatish Balay         cone[1] = 19;
30659371c9d4SSatish Balay         cone[2] = 14;
30669371c9d4SSatish Balay         cone[3] = 20;
30679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
30689371c9d4SSatish Balay         ornt[0] = 0;
30699371c9d4SSatish Balay         ornt[1] = 0;
30709371c9d4SSatish Balay         ornt[2] = -1;
30719371c9d4SSatish Balay         ornt[3] = 0;
30729566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
30732829fed8SMatthew G. Knepley         /* Cell 2 */
30749371c9d4SSatish Balay         cone[0] = 21;
30759371c9d4SSatish Balay         cone[1] = 22;
30769371c9d4SSatish Balay         cone[2] = 18;
30779371c9d4SSatish Balay         cone[3] = 23;
30789566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
30799371c9d4SSatish Balay         ornt[0] = 0;
30809371c9d4SSatish Balay         ornt[1] = 0;
30819371c9d4SSatish Balay         ornt[2] = -1;
30829371c9d4SSatish Balay         ornt[3] = 0;
30839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
30842829fed8SMatthew G. Knepley         /* Cell 3 */
30859371c9d4SSatish Balay         cone[0] = 19;
30869371c9d4SSatish Balay         cone[1] = 22;
30879371c9d4SSatish Balay         cone[2] = 24;
30889371c9d4SSatish Balay         cone[3] = 15;
30899566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
30909371c9d4SSatish Balay         ornt[0] = -1;
30919371c9d4SSatish Balay         ornt[1] = -1;
30929371c9d4SSatish Balay         ornt[2] = 0;
30939371c9d4SSatish Balay         ornt[3] = -1;
30949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
30952829fed8SMatthew G. Knepley         /* Cell 4 */
30969371c9d4SSatish Balay         cone[0] = 16;
30979371c9d4SSatish Balay         cone[1] = 24;
30989371c9d4SSatish Balay         cone[2] = 21;
30999371c9d4SSatish Balay         cone[3] = 25;
31009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
31019371c9d4SSatish Balay         ornt[0] = -1;
31029371c9d4SSatish Balay         ornt[1] = -1;
31039371c9d4SSatish Balay         ornt[2] = -1;
31049371c9d4SSatish Balay         ornt[3] = 0;
31059566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
31062829fed8SMatthew G. Knepley         /* Cell 5 */
31079371c9d4SSatish Balay         cone[0] = 20;
31089371c9d4SSatish Balay         cone[1] = 17;
31099371c9d4SSatish Balay         cone[2] = 25;
31109371c9d4SSatish Balay         cone[3] = 23;
31119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
31129371c9d4SSatish Balay         ornt[0] = -1;
31139371c9d4SSatish Balay         ornt[1] = -1;
31149371c9d4SSatish Balay         ornt[2] = -1;
31159371c9d4SSatish Balay         ornt[3] = -1;
31169566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
31172829fed8SMatthew G. Knepley         /* Edges */
31189371c9d4SSatish Balay         cone[0] = 6;
31199371c9d4SSatish Balay         cone[1] = 7;
31209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
31219371c9d4SSatish Balay         cone[0] = 7;
31229371c9d4SSatish Balay         cone[1] = 8;
31239566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
31249371c9d4SSatish Balay         cone[0] = 8;
31259371c9d4SSatish Balay         cone[1] = 9;
31269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
31279371c9d4SSatish Balay         cone[0] = 9;
31289371c9d4SSatish Balay         cone[1] = 6;
31299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
31309371c9d4SSatish Balay         cone[0] = 10;
31319371c9d4SSatish Balay         cone[1] = 11;
31329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
31339371c9d4SSatish Balay         cone[0] = 11;
31349371c9d4SSatish Balay         cone[1] = 7;
31359566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
31369371c9d4SSatish Balay         cone[0] = 6;
31379371c9d4SSatish Balay         cone[1] = 10;
31389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
31399371c9d4SSatish Balay         cone[0] = 12;
31409371c9d4SSatish Balay         cone[1] = 13;
31419566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
31429371c9d4SSatish Balay         cone[0] = 13;
31439371c9d4SSatish Balay         cone[1] = 11;
31449566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
31459371c9d4SSatish Balay         cone[0] = 10;
31469371c9d4SSatish Balay         cone[1] = 12;
31479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
31489371c9d4SSatish Balay         cone[0] = 13;
31499371c9d4SSatish Balay         cone[1] = 8;
31509566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
31519371c9d4SSatish Balay         cone[0] = 12;
31529371c9d4SSatish Balay         cone[1] = 9;
31539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
315445da822fSValeria Barra       }
31559566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
31569566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
31572829fed8SMatthew G. Knepley       /* Build coordinates */
31589566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3159dd400576SPatrick Sanan       if (rank == 0) {
31609371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
31619371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
31629371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
31639371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
31649371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
31659371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
31669371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
31679371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
31689371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
31699371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
31709371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
31719371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
31729371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
31739371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
31749371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
31759371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
31769371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
31779371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
31789371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
31799371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
31809371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
31819371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
31829371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
31839371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
318465a81367SMatthew G. Knepley       }
318545da822fSValeria Barra     }
318665a81367SMatthew G. Knepley     break;
318765a81367SMatthew G. Knepley   case 3:
3188116ded15SMatthew G. Knepley     if (simplex) {
3189116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
319051a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
319151a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
319251a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
3193116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
3194116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
31959371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
31969371c9d4SSatish Balay         {0, 1, 2, 3},
31979371c9d4SSatish Balay         {0, 2, 3, 1},
31989371c9d4SSatish Balay         {0, 3, 1, 2},
31999371c9d4SSatish Balay         {1, 0, 3, 2},
32009371c9d4SSatish Balay         {1, 2, 0, 3},
32019371c9d4SSatish Balay         {1, 3, 2, 0},
32029371c9d4SSatish Balay         {2, 0, 1, 3},
32039371c9d4SSatish Balay         {2, 1, 3, 0},
32049371c9d4SSatish Balay         {2, 3, 0, 1},
32059371c9d4SSatish Balay         {3, 0, 2, 1},
32069371c9d4SSatish Balay         {3, 1, 0, 2},
32079371c9d4SSatish Balay         {3, 2, 1, 0}
32089371c9d4SSatish Balay       };
3209116ded15SMatthew G. Knepley       PetscInt  cone[4];
3210116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
3211116ded15SMatthew G. Knepley 
32129371c9d4SSatish Balay       vertexA[0] *= R;
32139371c9d4SSatish Balay       vertexA[1] *= R;
32149371c9d4SSatish Balay       vertexA[2] *= R;
32159371c9d4SSatish Balay       vertexA[3] *= R;
32169371c9d4SSatish Balay       vertexB[0] *= R;
32179371c9d4SSatish Balay       vertexB[1] *= R;
32189371c9d4SSatish Balay       vertexB[2] *= R;
32199371c9d4SSatish Balay       vertexB[3] *= R;
32209371c9d4SSatish Balay       vertexC[0] *= R;
32219371c9d4SSatish Balay       vertexC[1] *= R;
32229371c9d4SSatish Balay       vertexC[2] *= R;
32239371c9d4SSatish Balay       vertexC[3] *= R;
3224dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
3225dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
3226116ded15SMatthew G. Knepley       firstVertex = numCells;
3227116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
3228116ded15SMatthew G. Knepley 
3229116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
3230116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
3231116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
3232116ded15SMatthew G. Knepley 
3233116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
32346333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
3235116ded15SMatthew G. Knepley 
3236116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
3237116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
3238116ded15SMatthew G. Knepley       */
3239116ded15SMatthew G. Knepley       /* Construct vertices */
32409566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3241116ded15SMatthew G. Knepley       i = 0;
3242dd400576SPatrick Sanan       if (rank == 0) {
3243116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
3244116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
3245116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
3246116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
3247116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
3248116ded15SMatthew G. Knepley                 ++i;
3249116ded15SMatthew G. Knepley               }
3250116ded15SMatthew G. Knepley             }
3251116ded15SMatthew G. Knepley           }
3252116ded15SMatthew G. Knepley         }
3253116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
3254116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
3255116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3256116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
3257116ded15SMatthew G. Knepley             ++i;
3258116ded15SMatthew G. Knepley           }
3259116ded15SMatthew G. Knepley         }
3260116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
3261116ded15SMatthew G. Knepley           s[3] = 1;
3262116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3263116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
3264116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
3265116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
3266116ded15SMatthew G. Knepley                 ++i;
3267116ded15SMatthew G. Knepley               }
3268116ded15SMatthew G. Knepley             }
3269116ded15SMatthew G. Knepley           }
3270116ded15SMatthew G. Knepley         }
327145da822fSValeria Barra       }
327263a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
3273116ded15SMatthew G. Knepley       /* Construct graph */
32749566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
3275116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
3276116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
32779371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
32789371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
32799371c9d4SSatish Balay             ++k;
32809371c9d4SSatish Balay           }
3281116ded15SMatthew G. Knepley         }
328263a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
3283116ded15SMatthew G. Knepley       }
3284116ded15SMatthew G. Knepley       /* Build Topology */
32859566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
328607c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
32879566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3288116ded15SMatthew G. Knepley       /* Cells */
3289dd400576SPatrick Sanan       if (rank == 0) {
329007c565c5SJose E. Roman         for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
3291116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
3292116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
3293116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
32949371c9d4SSatish Balay                 if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i] && graph[l * numVerts + i] && graph[l * numVerts + j] && graph[l * numVerts + k]) {
32959371c9d4SSatish Balay                   cone[0] = firstVertex + i;
32969371c9d4SSatish Balay                   cone[1] = firstVertex + j;
32979371c9d4SSatish Balay                   cone[2] = firstVertex + k;
32989371c9d4SSatish Balay                   cone[3] = firstVertex + l;
3299116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
3300116ded15SMatthew G. Knepley                   {
33019371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
33029371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},  {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, -1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, -1}, {0, 0, 0, 0}, {0, 1, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 1, 0}, {0, -1, 0, 0}, {0, 0, 0, 0}}},
3303116ded15SMatthew G. Knepley 
33049371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, -1}, {0, 0, 1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},  {{0, 0, 0, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {-1, 0, 0, 0}}, {{0, 0, -1, 0}, {0, 0, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}}},
3305116ded15SMatthew G. Knepley 
33069371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 0, 0}, {0, -1, 0, 0}}, {{0, 0, 0, -1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},  {{0, 1, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}},
3307116ded15SMatthew G. Knepley 
33089371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, -1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 1, 0}, {0, 0, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 0}}, {{0, -1, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} }
33099371c9d4SSatish Balay                     };
3310116ded15SMatthew G. Knepley                     PetscReal normal[4];
3311116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
3312116ded15SMatthew G. Knepley 
3313116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
3314116ded15SMatthew G. Knepley                       normal[d] = 0.0;
3315116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
3316116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
3317116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
3318116ded15SMatthew G. Knepley                             normal[d] += epsilon[d][e][f][g] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]) * (coordsIn[l * embedDim + f] - coordsIn[i * embedDim + f]);
3319116ded15SMatthew G. Knepley                           }
3320116ded15SMatthew G. Knepley                         }
3321116ded15SMatthew G. Knepley                       }
3322116ded15SMatthew G. Knepley                     }
33239371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
33249371c9d4SSatish Balay                       PetscInt tmp = cone[1];
33259371c9d4SSatish Balay                       cone[1]      = cone[2];
33269371c9d4SSatish Balay                       cone[2]      = tmp;
33279371c9d4SSatish Balay                     }
3328116ded15SMatthew G. Knepley                   }
33299566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
3330116ded15SMatthew G. Knepley                 }
3331116ded15SMatthew G. Knepley               }
3332116ded15SMatthew G. Knepley             }
3333116ded15SMatthew G. Knepley           }
3334116ded15SMatthew G. Knepley         }
333545da822fSValeria Barra       }
33369566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
33379566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
33389566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
3339116ded15SMatthew G. Knepley     }
3340f4d061e9SPierre Jolivet     break;
3341d71ae5a4SJacob Faibussowitsch   default:
3342d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
334365a81367SMatthew G. Knepley   }
334465a81367SMatthew G. Knepley   /* Create coordinates */
33459566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
33469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
33479566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
33489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
33492829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
33509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
33519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
33522829fed8SMatthew G. Knepley   }
33539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
33549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
33559566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
33569566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
33579566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
33589566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
33599566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
33609566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
33619371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
3362ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
33639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
33649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
33659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
33669566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
336751a74b61SMatthew G. Knepley   {
336851a74b61SMatthew G. Knepley     DM          cdm;
336951a74b61SMatthew G. Knepley     PetscDS     cds;
33709318fe57SMatthew G. Knepley     PetscScalar c = R;
337151a74b61SMatthew G. Knepley 
3372e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere));
33739566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
33749566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
33759566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
337651a74b61SMatthew G. Knepley   }
337746139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
33789318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
33799566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
33803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33819318fe57SMatthew G. Knepley }
33829318fe57SMatthew G. Knepley 
3383b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
3384b7f5c055SJed Brown 
3385b7f5c055SJed Brown /*
3386b7f5c055SJed Brown  The Schwarz P implicit surface is
3387b7f5c055SJed Brown 
3388b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
3389b7f5c055SJed Brown */
3390d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3391d71ae5a4SJacob Faibussowitsch {
3392b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
3393b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
3394b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
3395b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3396b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
3397ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
3398b7f5c055SJed Brown   }
3399b7f5c055SJed Brown }
3400b7f5c055SJed Brown 
34014663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3402d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3403d71ae5a4SJacob Faibussowitsch {
3404ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
34053ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
34064663dae6SJed Brown }
34074663dae6SJed Brown 
3408b7f5c055SJed Brown /*
3409b7f5c055SJed Brown  The Gyroid implicit surface is
3410b7f5c055SJed Brown 
3411b7f5c055SJed Brown  f(x,y,z) = sin(pi * x) * cos (pi * (y + 1/2))  + sin(pi * (y + 1/2)) * cos(pi * (z + 1/4)) + sin(pi * (z + 1/4)) * cos(pi * x)
3412b7f5c055SJed Brown 
3413b7f5c055SJed Brown */
3414d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3415d71ae5a4SJacob Faibussowitsch {
3416b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
3417b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
3418b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
3419b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
3420b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
3421b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
3422b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
3423b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3424b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3425b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
3426b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3427b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3428b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
3429b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3430b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3431b7f5c055SJed Brown }
3432b7f5c055SJed Brown 
34334663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3434d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3435d71ae5a4SJacob Faibussowitsch {
34364663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
34374663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
34384663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
34394663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
34404663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
34413ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
34424663dae6SJed Brown }
34434663dae6SJed Brown 
3444b7f5c055SJed Brown /*
3445b7f5c055SJed Brown    We wish to solve
3446b7f5c055SJed Brown 
3447b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
3448b7f5c055SJed Brown 
3449b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
3450b7f5c055SJed Brown    f(y) = 0 and (y-x) is parallel to g(y).  We do this by using Householder QR to obtain a basis for the
3451b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
3452b7f5c055SJed Brown 
3453b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
3454b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
3455b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
3456b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
3457da81f932SPierre Jolivet    Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries.
3458b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
3459b7f5c055SJed Brown 
3460b7f5c055SJed Brown      f(y) = 0                       1 equation
3461b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
3462b7f5c055SJed Brown 
3463b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
3464b7f5c055SJed Brown */
3465d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
3466d71ae5a4SJacob Faibussowitsch {
3467b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
3468b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
34692f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
34709371c9d4SSatish Balay   PetscReal n_y[3][3] = {
34719371c9d4SSatish Balay     {0, 0, 0},
34729371c9d4SSatish Balay     {0, 0, 0},
34739371c9d4SSatish Balay     {0, 0, 0}
34749371c9d4SSatish Balay   };
3475b7f5c055SJed Brown 
3476b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
3477b7f5c055SJed Brown 
3478b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
3479b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3480ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
3481b7f5c055SJed Brown 
3482b7f5c055SJed Brown   // Define the Householder reflector
3483b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
3484b7f5c055SJed Brown   n[0] += norm * sign;
3485b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
3486b7f5c055SJed Brown 
3487b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3488b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
3489b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
3490b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
3491b7f5c055SJed Brown 
3492b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3493b7f5c055SJed Brown     n[i] /= norm;
3494b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
3495b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
3496b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
3497b7f5c055SJed Brown     }
3498b7f5c055SJed Brown   }
3499b7f5c055SJed Brown 
3500b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
3501b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) nd_y[i] = n[i] + n_y[0][i] * d[0] + n_y[1][i] * d[1] + n_y[2][i] * d[2];
3502b7f5c055SJed Brown 
3503b7f5c055SJed Brown   res[0] = f;
3504b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
3505b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
3506b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
3507b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
3508b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
3509b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
3510b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
3511b7f5c055SJed Brown   }
3512b7f5c055SJed Brown }
3513b7f5c055SJed Brown 
3514b7f5c055SJed Brown /*
3515b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
3516b7f5c055SJed Brown */
3517d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
3518d71ae5a4SJacob Faibussowitsch {
3519b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
3520b7f5c055SJed Brown 
3521b7f5c055SJed Brown   PetscFunctionBegin;
3522b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
3523b7f5c055SJed Brown     PetscScalar res[3], J[9];
3524b7f5c055SJed Brown     PetscReal   resnorm;
3525b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
3526b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
3527b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
352863a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%" PetscInt_FMT "] res [%g %g %g]\n", iter, (double)PetscRealPart(res[0]), (double)PetscRealPart(res[1]), (double)PetscRealPart(res[2])));
3529b7f5c055SJed Brown     }
3530b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
3531b7f5c055SJed Brown 
3532b7f5c055SJed Brown     // Take the Newton step
35339566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
3534b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
3535b7f5c055SJed Brown   }
3536b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
35373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3538b7f5c055SJed Brown }
3539b7f5c055SJed Brown 
3540b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
3541b7f5c055SJed Brown 
3542d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
3543d71ae5a4SJacob Faibussowitsch {
3544b7f5c055SJed Brown   PetscMPIInt rank;
3545b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
3546b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
3547b7f5c055SJed Brown   PetscInt           *cells_flat = NULL;
3548b7f5c055SJed Brown   PetscReal          *vtxCoords  = NULL;
3549b7f5c055SJed Brown   TPSEvaluateFunc     evalFunc   = NULL;
35508434afd1SBarry Smith   PetscSimplePointFn *normalFunc = NULL;
3551b7f5c055SJed Brown   DMLabel             label;
3552b7f5c055SJed Brown 
3553b7f5c055SJed Brown   PetscFunctionBegin;
355446139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
35559566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
355663a3b9bcSJacob Faibussowitsch   PetscCheck((layers != 0) ^ (thickness == 0.), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Layers %" PetscInt_FMT " must be nonzero iff thickness %g is nonzero", layers, (double)thickness);
3557b7f5c055SJed Brown   switch (tpstype) {
3558b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
3559b7f5c055SJed Brown     PetscCheck(!periodic || (periodic[0] == DM_BOUNDARY_NONE && periodic[1] == DM_BOUNDARY_NONE && periodic[2] == DM_BOUNDARY_NONE), PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Schwarz P does not support periodic meshes");
3560c5853193SPierre Jolivet     if (rank == 0) {
3561b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
3562b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
3563b7f5c055SJed Brown       PetscReal L = 1;
3564b7f5c055SJed Brown 
3565b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
3566b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
3567b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
3568b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
3569b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
3570b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
35719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
35729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
35739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
35749566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
3575b7f5c055SJed Brown       // x-normal pipes
3576b7f5c055SJed Brown       vcount = 0;
3577b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
3578b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3579b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3580b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3581b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
3582b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3583b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3584b7f5c055SJed Brown             }
3585b7f5c055SJed Brown           }
3586b7f5c055SJed Brown         }
3587b7f5c055SJed Brown       }
3588b7f5c055SJed Brown       // y-normal pipes
3589b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3590b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
3591b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3592b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3593b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3594b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
3595b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3596b7f5c055SJed Brown             }
3597b7f5c055SJed Brown           }
3598b7f5c055SJed Brown         }
3599b7f5c055SJed Brown       }
3600b7f5c055SJed Brown       // z-normal pipes
3601b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3602b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3603b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
3604b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3605b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3606b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3607b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
3608b7f5c055SJed Brown             }
3609b7f5c055SJed Brown           }
3610b7f5c055SJed Brown         }
3611b7f5c055SJed Brown       }
3612b7f5c055SJed Brown       // junctions
3613b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3614b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3615b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3616b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
3617b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
3618b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
3619b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
3620b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
3621b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
3622b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
3623b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
3624b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
3625b7f5c055SJed Brown                 }
3626b7f5c055SJed Brown               }
3627b7f5c055SJed Brown             }
3628b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
3629b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
3630b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
3631b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
3632b7f5c055SJed Brown             };
3633b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
36349371c9d4SSatish Balay                                          ((i * extent[1] + j) * extent[2] + k) * 4, ((i * (extent[1] + 1) + j) * extent[2] + k + Npipes[0]) * 4, ((i * extent[1] + j) * (extent[2] + 1) + k + Npipes[0] + Npipes[1]) * 4};
3635b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
36369371c9d4SSatish Balay                                          (((i + 1) * extent[1] + j) * extent[2] + k) * 4, ((i * (extent[1] + 1) + j + 1) * extent[2] + k + Npipes[0]) * 4, ((i * extent[1] + j) * (extent[2] + 1) + k + 1 + Npipes[0] + Npipes[1]) * 4};
3637b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
3638b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
3639b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
3640b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
3641b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
3642b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
3643b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
3644b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
3645b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
3646b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
3647b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
3648b7f5c055SJed Brown                 if (ijk[dir] == 0) {
3649b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
3650b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
3651b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
3652b7f5c055SJed Brown                   numEdges++;
3653b7f5c055SJed Brown                 }
3654b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
3655b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
3656b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
3657b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
3658b7f5c055SJed Brown                   numEdges++;
3659b7f5c055SJed Brown                 }
3660b7f5c055SJed Brown               }
3661b7f5c055SJed Brown             }
3662b7f5c055SJed Brown           }
3663b7f5c055SJed Brown         }
3664b7f5c055SJed Brown       }
366563a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
3666b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
3667b7f5c055SJed Brown       cells_flat = cells[0][0][0];
3668b7f5c055SJed Brown     }
3669b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
36704663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
3671b7f5c055SJed Brown     break;
3672b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
3673c5853193SPierre Jolivet     if (rank == 0) {
3674b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
3675b7f5c055SJed Brown       //
3676b7f5c055SJed Brown       //     sin(pi*x)*cos(pi*(y+1/2)) + sin(pi*(y+1/2))*cos(pi*(z+1/4)) + sin(pi*(z+1/4))*cos(x)
3677b7f5c055SJed Brown       //
3678b7f5c055SJed Brown       // on the cell [0,2]^3.
3679b7f5c055SJed Brown       //
3680b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
3681b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
3682b7f5c055SJed Brown       // like a boomerang:
3683b7f5c055SJed Brown       //
3684b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
3685b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3686b7f5c055SJed Brown       //                                                              //
3687b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3688b7f5c055SJed Brown       //      \                                   /            \      //
3689b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
3690b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
3691b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
3692b7f5c055SJed Brown       //                                                              //
3693b7f5c055SJed Brown       //                                                              //
3694b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
3695b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3696b7f5c055SJed Brown       //                                                              //
3697b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
3698b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
3699b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
3700b7f5c055SJed Brown       //            \                       /                \        //
3701b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3702b7f5c055SJed Brown       //
3703b7f5c055SJed Brown       //
3704b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
3705b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
3706b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
3707b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
3708b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
3709b7f5c055SJed Brown       //
3710b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
3711b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
3712b7f5c055SJed Brown       //
3713b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
3714b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
3715b7f5c055SJed Brown 
3716b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
3717b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
3718b7f5c055SJed Brown       PetscInt extentPlus[3];
3719b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
37209371c9d4SSatish Balay       const PetscInt A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, II = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14, P = 15, Q = 16, R = 17, S = 18, T = 19, U = 20, V = 21, W = 22, X = 23, Y = 24, Z = 25, Ap = 26, Bp = 27, Cp = 28, Dp = 29, Ep = 30, Fp = 31, Gp = 32, Hp = 33, Ip = 34, Jp = 35, Kp = 36, Lp = 37, Mp = 38, Np = 39, Op = 40, Pp = 41, Qp = 42, Rp = 43, Sp = 44, Tp = 45, Up = 46, Vp = 47, Wp = 48, Xp = 49, Yp = 50, Zp = 51, Aq = 52, Bq = 53, Cq = 54, Dq = 55;
37219371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
37229371c9d4SSatish Balay         /* face to vertex within the coarse discretization of a single gyroid block */
3723b7f5c055SJed Brown         /* layer 0 */
37249371c9d4SSatish Balay         {A,           C,           K,           G          },
37259371c9d4SSatish Balay         {C,           B,           II,          K          },
37269371c9d4SSatish Balay         {D,           A,           H,           L          },
37279371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
37289371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
37299371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
37309371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
37319371c9d4SSatish Balay         {B,           F,           M,           II         },
3732b7f5c055SJed Brown         /* layer 1 */
37339371c9d4SSatish Balay         {G,           K,           Q,           O          },
37349371c9d4SSatish Balay         {K,           II,          P,           Q          },
37359371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
37369371c9d4SSatish Balay         {J,           L,           R,           P          },
37379371c9d4SSatish Balay         {N,           J,           P,           S          },
37389371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
37399371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
37409371c9d4SSatish Balay         {II,          M,           T,           P          },
3741b7f5c055SJed Brown         /* layer 2 */
37429371c9d4SSatish Balay         {O,           Q,           Y,           U          },
37439371c9d4SSatish Balay         {Q,           P,           W,           Y          },
37449371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
37459371c9d4SSatish Balay         {P,           R,           Ap,          W          },
37469371c9d4SSatish Balay         {S,           P,           X,           Bp         },
37479371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
37489371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
37499371c9d4SSatish Balay         {P,           T,           Z,           X          },
3750b7f5c055SJed Brown         /* layer 3 */
37519371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
37529371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
37539371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
37549371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
37559371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
37569371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
37579371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
37589371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
3759b7f5c055SJed Brown         /* layer 4 */
37609371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
37619371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
37629371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
37639371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
37649371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
37659371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
37669371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
37679371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
3768b7f5c055SJed Brown         /* layer 5 */
37699371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
37709371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
37719371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
37729371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
37739371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
37749371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
37759371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
37769371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
3777b7f5c055SJed Brown         /* layer 6 */
37789371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
37799371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
37809371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
37819371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
37829371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
37839371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
37849371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
37859371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
3786b7f5c055SJed Brown         /* layer 7 (the top is the periodic image of the bottom of layer 0) */
37879371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
37889371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
37899371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
37909371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
37919371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
37929371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
37939371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
37949371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
3795b7f5c055SJed Brown       };
3796b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
37979371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
3798bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
3799bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
3800bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
3801bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
3802bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
3803bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
3804b7f5c055SJed Brown 
3805bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
3806bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
3807bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
3808bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
3809bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
3810bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
3811bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
3812bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
3813b7f5c055SJed Brown 
3814bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
3815bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
3816bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
3817bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
3818bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
3819bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
3820b7f5c055SJed Brown 
3821bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
3822bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
3823bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
3824bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
3825bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
3826bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
3827bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
3828bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
3829b7f5c055SJed Brown 
3830bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
3831bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
3832bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
3833bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
3834bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
3835bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
3836b7f5c055SJed Brown 
3837bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
3838bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
3839bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
3840bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
3841bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
3842bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
3843bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
3844bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
3845b7f5c055SJed Brown 
3846bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
3847bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
3848bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
3849bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
3850bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
3851bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
3852b7f5c055SJed Brown 
3853bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3854bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3855bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3856bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3857bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3858bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3859bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3860bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3861b7f5c055SJed Brown       };
3862b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3863b7f5c055SJed Brown       PetscBool *seen;
3864b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3865b7f5c055SJed Brown       PetscInt   count;
3866b7f5c055SJed Brown 
3867b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3868b7f5c055SJed Brown       numBlocks = 1;
3869b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3870b7f5c055SJed Brown       numBlocksPlus = 1;
3871b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3872b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
38739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
38749566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3875b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3876b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3877b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3878b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3879b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3880b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3881b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3882b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3883b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3884b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3885b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3886b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3887b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3888b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3889b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3890b7f5c055SJed Brown 
3891b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3892b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3893b7f5c055SJed Brown               }
3894b7f5c055SJed Brown             }
3895b7f5c055SJed Brown           }
3896b7f5c055SJed Brown         }
3897b7f5c055SJed Brown       }
38989371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
38999371c9d4SSatish Balay         if (seen[i]) numVertices++;
3900b7f5c055SJed Brown       count = 0;
39019566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
39029566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3903b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3904b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3905b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3906b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3907b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3908b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3909b7f5c055SJed Brown 
3910b7f5c055SJed Brown               if (seen[vIdx]) {
3911b7f5c055SJed Brown                 PetscInt thisVert;
3912b7f5c055SJed Brown 
3913b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3914b7f5c055SJed Brown 
3915b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3916b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3917b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3918b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3919b7f5c055SJed Brown               }
3920b7f5c055SJed Brown             }
3921b7f5c055SJed Brown           }
3922b7f5c055SJed Brown         }
3923b7f5c055SJed Brown       }
3924b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3925b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3926ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3927b7f5c055SJed Brown         }
3928b7f5c055SJed Brown       }
39299566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
39309566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3931b7f5c055SJed Brown       cells_flat = cells[0][0];
3932b7f5c055SJed Brown       numEdges   = 0;
3933b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3934b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3935b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3936b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3937b7f5c055SJed Brown 
3938b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3939b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3940b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3941b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3942b7f5c055SJed Brown             }
3943b7f5c055SJed Brown           }
3944b7f5c055SJed Brown         }
3945b7f5c055SJed Brown       }
39469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
39479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3948b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3949b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3950b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3951b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3952b7f5c055SJed Brown 
3953b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3954b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3955b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3956b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3957b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3958b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3959b7f5c055SJed Brown               }
3960b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3961b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3962b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3963b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3964b7f5c055SJed Brown               }
3965b7f5c055SJed Brown             }
3966b7f5c055SJed Brown           }
3967b7f5c055SJed Brown         }
3968b7f5c055SJed Brown       }
3969b7f5c055SJed Brown     }
3970b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
39714663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3972b7f5c055SJed Brown     break;
3973b7f5c055SJed Brown   }
3974b7f5c055SJed Brown 
39759566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3976c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
39779566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
39789566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3979b7f5c055SJed Brown   {
3980b7f5c055SJed Brown     DM idm;
39819566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
398269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3983b7f5c055SJed Brown   }
3984c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
39859566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
39869566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3987b7f5c055SJed Brown 
39889566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
39899566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3990b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3991b7f5c055SJed Brown     PetscInt        njoin;
3992b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
39939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
399463a3b9bcSJacob Faibussowitsch     PetscCheck(njoin == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected unique join of vertices %" PetscInt_FMT " and %" PetscInt_FMT, edges[e][0], edges[e][1]);
39959566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
39969566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3997b7f5c055SJed Brown   }
39989566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
39999566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
40001436d7faSJed Brown   if (tps_distribute) {
40011436d7faSJed Brown     DM               pdm = NULL;
40021436d7faSJed Brown     PetscPartitioner part;
40031436d7faSJed Brown 
40049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
40059566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
40069566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
400748a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
40081436d7faSJed Brown     // Do not auto-distribute again
40099566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
40101436d7faSJed Brown   }
4011b7f5c055SJed Brown 
40129566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
4013b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
4014b7f5c055SJed Brown     PetscInt     m;
4015b7f5c055SJed Brown     DM           dmf;
4016b7f5c055SJed Brown     Vec          X;
4017b7f5c055SJed Brown     PetscScalar *x;
40189566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
401969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
4020b7f5c055SJed Brown 
40219566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
40229566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
40239566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
402448a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
40259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
4026b7f5c055SJed Brown   }
4027b7f5c055SJed Brown 
4028b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
40299566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
40309566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
4031b7f5c055SJed Brown 
403246139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
403346139095SJed Brown 
4034b7f5c055SJed Brown   if (thickness > 0) {
40354663dae6SJed Brown     DM              edm, cdm, ecdm;
40364663dae6SJed Brown     DMPlexTransform tr;
40374663dae6SJed Brown     const char     *prefix;
40384663dae6SJed Brown     PetscOptions    options;
40394663dae6SJed Brown     // Code from DMPlexExtrude
40404663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
40414663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
40424663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
40434663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
40444663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
40454663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
40464663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
40474663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
40484663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
40494663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
40504663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
40514663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
40524663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
40534663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
40544663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
40554663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
40564663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
40574663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
40584663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
40594663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
40604663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
40614663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
40624663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
4063a77a5016SMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm));
406469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
4065b7f5c055SJed Brown   }
40663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4067b7f5c055SJed Brown }
4068b7f5c055SJed Brown 
4069b7f5c055SJed Brown /*@
4070b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
4071b7f5c055SJed Brown 
4072b7f5c055SJed Brown   Collective
4073b7f5c055SJed Brown 
4074b7f5c055SJed Brown   Input Parameters:
4075a1cb98faSBarry Smith + comm           - The communicator for the `DM` object
4076b7f5c055SJed Brown . tpstype        - Type of triply-periodic surface
4077b7f5c055SJed Brown . extent         - Array of length 3 containing number of periods in each direction
407820f4b53cSBarry Smith . periodic       - array of length 3 with periodicity, or `NULL` for non-periodic
40791436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
4080817da375SSatish Balay . refinements    - Number of factor-of-2 refinements of 2D manifold mesh
40811436d7faSJed Brown . layers         - Number of cell layers extruded in normal direction
4082817da375SSatish Balay - thickness      - Thickness in normal direction
4083b7f5c055SJed Brown 
4084b7f5c055SJed Brown   Output Parameter:
4085a1cb98faSBarry Smith . dm - The `DM` object
4086a1cb98faSBarry Smith 
4087a1cb98faSBarry Smith   Level: beginner
4088b7f5c055SJed Brown 
4089b7f5c055SJed Brown   Notes:
409015229ffcSPierre Jolivet   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is the simplest member of the triply-periodic minimal surfaces.
40911d27aa22SBarry Smith   <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries.
40921d27aa22SBarry Smith   The Gyroid <https://en.wikipedia.org/wiki/Gyroid> is another triply-periodic minimal surface with applications in additive manufacturing; it is much more difficult to "cut" since there are no planes of symmetry.
4093b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
4094b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
4095b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
4096b7f5c055SJed Brown 
40971d27aa22SBarry Smith   See {cite}`maskery2018insights`
40981d27aa22SBarry Smith 
40991d27aa22SBarry Smith   The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$.
41001d27aa22SBarry Smith   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).
41011d27aa22SBarry Smith   Use `DMPlexLabelComplete()` to propagate to coarse-level vertices.
4102b7f5c055SJed Brown 
410360225df5SJacob Faibussowitsch   Developer Notes:
4104b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
4105b7f5c055SJed Brown 
41061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
4107b7f5c055SJed Brown @*/
4108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm)
4109d71ae5a4SJacob Faibussowitsch {
4110b7f5c055SJed Brown   PetscFunctionBegin;
41119566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
41129566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
41139566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
41143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4115b7f5c055SJed Brown }
4116b7f5c055SJed Brown 
41179318fe57SMatthew G. Knepley /*@
41189318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
41199318fe57SMatthew G. Knepley 
41209318fe57SMatthew G. Knepley   Collective
41219318fe57SMatthew G. Knepley 
41229318fe57SMatthew G. Knepley   Input Parameters:
4123a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
41249318fe57SMatthew G. Knepley . dim     - The dimension
41259318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
41269318fe57SMatthew G. Knepley - R       - The radius
41279318fe57SMatthew G. Knepley 
41289318fe57SMatthew G. Knepley   Output Parameter:
4129a1cb98faSBarry Smith . dm - The `DM` object
41309318fe57SMatthew G. Knepley 
41319318fe57SMatthew G. Knepley   Level: beginner
41329318fe57SMatthew G. Knepley 
41331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
41349318fe57SMatthew G. Knepley @*/
4135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
4136d71ae5a4SJacob Faibussowitsch {
41379318fe57SMatthew G. Knepley   PetscFunctionBegin;
41384f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
41399566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
41409566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
41419566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
41423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41439318fe57SMatthew G. Knepley }
41449318fe57SMatthew G. Knepley 
4145d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
4146d71ae5a4SJacob Faibussowitsch {
41479318fe57SMatthew G. Knepley   DM          sdm, vol;
41489318fe57SMatthew G. Knepley   DMLabel     bdlabel;
4149dd2b43ebSStefano Zampini   const char *prefix;
41509318fe57SMatthew G. Knepley 
41519318fe57SMatthew G. Knepley   PetscFunctionBegin;
41529566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
41539566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
4154dd2b43ebSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
4155dd2b43ebSStefano Zampini   PetscCall(DMSetOptionsPrefix(sdm, prefix));
4156dd2b43ebSStefano Zampini   PetscCall(DMAppendOptionsPrefix(sdm, "bd_"));
4157dd2b43ebSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE));
41589566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
41599566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
41609566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
41619566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
41629566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
416369d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
41649566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
41659566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
41669566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
41679566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
41683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
416951a74b61SMatthew G. Knepley }
417051a74b61SMatthew G. Knepley 
417151a74b61SMatthew G. Knepley /*@
417251a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
417351a74b61SMatthew G. Knepley 
417451a74b61SMatthew G. Knepley   Collective
417551a74b61SMatthew G. Knepley 
417651a74b61SMatthew G. Knepley   Input Parameters:
4177a1cb98faSBarry Smith + comm - The communicator for the `DM` object
417851a74b61SMatthew G. Knepley . dim  - The dimension
417951a74b61SMatthew G. Knepley - R    - The radius
418051a74b61SMatthew G. Knepley 
418151a74b61SMatthew G. Knepley   Output Parameter:
4182a1cb98faSBarry Smith . dm - The `DM` object
418351a74b61SMatthew G. Knepley 
4184a1cb98faSBarry Smith   Options Database Key:
418560225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
418651a74b61SMatthew G. Knepley 
418751a74b61SMatthew G. Knepley   Level: beginner
418851a74b61SMatthew G. Knepley 
41891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
419051a74b61SMatthew G. Knepley @*/
4191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
4192d71ae5a4SJacob Faibussowitsch {
419351a74b61SMatthew G. Knepley   PetscFunctionBegin;
41949566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
41959566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
41969566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
41973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41982829fed8SMatthew G. Knepley }
41992829fed8SMatthew G. Knepley 
4200d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
4201d71ae5a4SJacob Faibussowitsch {
42020a6ba040SMatthew G. Knepley   PetscFunctionBegin;
42039318fe57SMatthew G. Knepley   switch (ct) {
42049371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
42059318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
42069318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
42079318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
42089318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
42099318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
42109318fe57SMatthew G. Knepley 
42119566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
42129566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42139371c9d4SSatish Balay   } break;
42149371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
42159318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
42169318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
42179318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
42189318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
42199318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
42209318fe57SMatthew G. Knepley 
42219566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
42229566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42239371c9d4SSatish Balay   } break;
42249371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
4225b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
4226b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
4227b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
4228b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
4229b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
4230b5a892a1SMatthew G. Knepley 
42319566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
42329566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42339371c9d4SSatish Balay   } break;
42349371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
42359318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
42369318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
42379318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
42389318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
42399318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
42409318fe57SMatthew G. Knepley 
42419566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
42429566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42439371c9d4SSatish Balay   } break;
42449371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
42459318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
42469318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
42479318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
42489318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
42499318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
42509318fe57SMatthew G. Knepley 
42519566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
42529566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42539371c9d4SSatish Balay   } break;
42549371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
42559318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
42569318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
42579318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
42589318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
42599318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
42609318fe57SMatthew G. Knepley 
42619566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
42629566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42639371c9d4SSatish Balay   } break;
42649371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
42659318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
42669318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
4267f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
42689318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
4269f0edb160SMatthew G. Knepley     PetscScalar vertexCoords[12]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0};
42709318fe57SMatthew G. Knepley 
42719566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
42729566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42739371c9d4SSatish Balay   } break;
42749371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
42759318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
42769318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
4277f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
42789318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
42799371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0};
42809318fe57SMatthew G. Knepley 
42819566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
42829566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42839371c9d4SSatish Balay   } break;
42849371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
42859318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
42869318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
4287f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
42889318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
42899371c9d4SSatish Balay     PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0};
42909318fe57SMatthew G. Knepley 
42919566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
42929566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42939371c9d4SSatish Balay   } break;
42949371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
42959318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
42969318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
42979318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
42989318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
42999371c9d4SSatish Balay     PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0};
43009318fe57SMatthew G. Knepley 
43019566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43029566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43039371c9d4SSatish Balay   } break;
43049371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
43059318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
43069318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
43079318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
43089318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43099371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0};
43109318fe57SMatthew G. Knepley 
43119566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43129566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43139371c9d4SSatish Balay   } break;
43149371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
43159318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
43169318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
4317f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
43189318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43199371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0};
43209318fe57SMatthew G. Knepley 
43219566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43229566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43239371c9d4SSatish Balay   } break;
4324d71ae5a4SJacob Faibussowitsch   default:
4325d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
43269318fe57SMatthew G. Knepley   }
43279318fe57SMatthew G. Knepley   {
43289318fe57SMatthew G. Knepley     PetscInt Nv, v;
43299318fe57SMatthew G. Knepley 
43309318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
43319566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
43329566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
43339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
43349566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
43359318fe57SMatthew G. Knepley   }
43369566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
43379566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
43383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43390a6ba040SMatthew G. Knepley }
43400a6ba040SMatthew G. Knepley 
43419318fe57SMatthew G. Knepley /*@
4342a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
43439318fe57SMatthew G. Knepley 
43449318fe57SMatthew G. Knepley   Collective
43459318fe57SMatthew G. Knepley 
43469318fe57SMatthew G. Knepley   Input Parameters:
43479318fe57SMatthew G. Knepley + comm - The communicator
43489318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
43499318fe57SMatthew G. Knepley 
43509318fe57SMatthew G. Knepley   Output Parameter:
43519318fe57SMatthew G. Knepley . refdm - The reference cell
43529318fe57SMatthew G. Knepley 
43539318fe57SMatthew G. Knepley   Level: intermediate
43549318fe57SMatthew G. Knepley 
435542747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`
43569318fe57SMatthew G. Knepley @*/
4357d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
4358d71ae5a4SJacob Faibussowitsch {
43590a6ba040SMatthew G. Knepley   PetscFunctionBegin;
43609566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
43619566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
43629566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
43633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43649318fe57SMatthew G. Knepley }
436579a015ccSMatthew G. Knepley 
4366d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
4367d71ae5a4SJacob Faibussowitsch {
43689318fe57SMatthew G. Knepley   DM        plex;
43699318fe57SMatthew G. Knepley   DMLabel   label;
43709318fe57SMatthew G. Knepley   PetscBool hasLabel;
43710a6ba040SMatthew G. Knepley 
4372c22d3578SMatthew G. Knepley   PetscFunctionBegin;
43739566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
43743ba16761SJacob Faibussowitsch   if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS);
43759566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
43769566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
43779566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
43789566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
43791c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
43809566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
43813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43829318fe57SMatthew G. Knepley }
4383acdc6f61SToby Isaac 
4384669647acSMatthew G. Knepley /*
4385669647acSMatthew G. Knepley   We use the last coordinate as the radius, the inner radius is lower[dim-1] and the outer radius is upper[dim-1]. Then we map the first coordinate around the circle.
4386669647acSMatthew G. Knepley 
4387669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
4388669647acSMatthew G. Knepley */
4389d71ae5a4SJacob Faibussowitsch static void boxToAnnulus(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
4390d71ae5a4SJacob Faibussowitsch {
4391669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
4392669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
4393669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
4394669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
4395669647acSMatthew G. Knepley 
4396669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
4397669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
4398669647acSMatthew G. Knepley }
4399669647acSMatthew G. Knepley 
44005390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth
44015390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[])
44025390be7dSMatthew G. Knepley {
44035390be7dSMatthew G. Knepley   PetscFunctionBegin;
44045390be7dSMatthew G. Knepley   PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL));
44055390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
44065390be7dSMatthew G. Knepley }
44075390be7dSMatthew G. Knepley 
44085390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth
44095390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[])
44105390be7dSMatthew G. Knepley {
44115390be7dSMatthew G. Knepley   PetscFunctionBegin;
44125390be7dSMatthew G. Knepley   for (PetscInt p = 0; p < n; ++p) {
44135390be7dSMatthew G. Knepley     const PetscInt point   = faces[p];
44145390be7dSMatthew G. Knepley     PetscInt      *closure = NULL;
44155390be7dSMatthew G. Knepley     PetscInt       clSize, pdepth;
44165390be7dSMatthew G. Knepley 
44175390be7dSMatthew G. Knepley     PetscCall(DMPlexGetPointDepth(dm, point, &pdepth));
44185390be7dSMatthew G. Knepley     PetscCall(DMLabelSetValue(label, point, pdepth));
44195390be7dSMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
44205390be7dSMatthew G. Knepley     for (PetscInt cl = 0; cl < clSize * 2; cl += 2) {
44215390be7dSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth));
44225390be7dSMatthew G. Knepley       PetscCall(DMLabelSetValue(label, closure[cl], pdepth));
44235390be7dSMatthew G. Knepley     }
44245390be7dSMatthew G. Knepley     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
44255390be7dSMatthew G. Knepley   }
44265390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
44275390be7dSMatthew G. Knepley }
44285390be7dSMatthew G. Knepley 
44294e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg);
44304e22dd4cSMatthew G. Knepley 
44315dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
44329318fe57SMatthew G. Knepley 
4433d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
4434d71ae5a4SJacob Faibussowitsch {
44359318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
44369318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
44379318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
4438b9da1bb3SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
4439d0812dedSMatthew G. Knepley   PetscBool      flg, flg2, fflg, strflg, bdfflg, nameflg;
44409318fe57SMatthew G. Knepley   MPI_Comm       comm;
4441ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
4442ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
4443ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
44444e22dd4cSMatthew G. Knepley   const char    *option;
44459318fe57SMatthew G. Knepley 
44469318fe57SMatthew G. Knepley   PetscFunctionBegin;
4447708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
44489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
44499318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
44509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
4451d0812dedSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg));
44529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
44539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
44549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
44559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
44569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
44579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
44589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
44599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
4460b9da1bb3SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg));
44619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
44629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
44639566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
44643f3e541fSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0));
44659318fe57SMatthew G. Knepley 
446661a622f3SMatthew G. Knepley   switch (cell) {
446761a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
446861a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
446961a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
447061a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
447161a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
447261a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
4473d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
4474d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
4475d71ae5a4SJacob Faibussowitsch     break;
4476d71ae5a4SJacob Faibussowitsch   default:
4477d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
4478d71ae5a4SJacob Faibussowitsch     break;
447961a622f3SMatthew G. Knepley   }
448061a622f3SMatthew G. Knepley 
44819318fe57SMatthew G. Knepley   if (fflg) {
44829318fe57SMatthew G. Knepley     DM          dmnew;
44831e4a82c4SMatthew G. Knepley     const char *name;
44849318fe57SMatthew G. Knepley 
44851e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
44861e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew));
44875de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
448869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
44899318fe57SMatthew G. Knepley   } else if (refDomain) {
44909566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
44919318fe57SMatthew G. Knepley   } else if (bdfflg) {
44929318fe57SMatthew G. Knepley     DM          bdm, dmnew;
44931e4a82c4SMatthew G. Knepley     const char *name;
44949318fe57SMatthew G. Knepley 
44951e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
44961e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm));
44979566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
44989566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
44999566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
45009566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
45015de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
450269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
4503d0812dedSMatthew G. Knepley   } else if (strflg) {
4504d0812dedSMatthew G. Knepley     DM          dmnew;
4505d0812dedSMatthew G. Knepley     PetscViewer viewer;
4506d0812dedSMatthew G. Knepley     const char *contents;
4507d0812dedSMatthew G. Knepley     char       *strname;
4508d0812dedSMatthew G. Knepley     char        tmpdir[PETSC_MAX_PATH_LEN];
4509d0812dedSMatthew G. Knepley     char        tmpfilename[PETSC_MAX_PATH_LEN];
4510d0812dedSMatthew G. Knepley     char        name[PETSC_MAX_PATH_LEN];
4511d0812dedSMatthew G. Knepley     MPI_Comm    comm;
4512d0812dedSMatthew G. Knepley     PetscMPIInt rank;
4513d0812dedSMatthew G. Knepley 
4514d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4515d0812dedSMatthew G. Knepley     PetscCallMPI(MPI_Comm_rank(comm, &rank));
4516d0812dedSMatthew G. Knepley     PetscCall(PetscStrchr(filename, ':', &strname));
4517d0812dedSMatthew G. Knepley     PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename);
4518d0812dedSMatthew G. Knepley     strname[0] = '\0';
4519d0812dedSMatthew G. Knepley     ++strname;
4520d0812dedSMatthew G. Knepley     PetscCall(PetscDLSym(NULL, strname, (void **)&contents));
4521d0812dedSMatthew G. Knepley     PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname);
4522d0812dedSMatthew G. Knepley     PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN));
4523ed32af8cSMatthew G. Knepley     PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN));
4524ed32af8cSMatthew G. Knepley     PetscCall(PetscMkdtemp(tmpdir));
4525ed32af8cSMatthew G. Knepley     PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename));
4526d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer));
4527d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents));
4528d0812dedSMatthew G. Knepley     PetscCall(PetscViewerDestroy(&viewer));
4529d0812dedSMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew));
4530ed32af8cSMatthew G. Knepley     PetscCall(PetscRMTree(tmpdir));
4531d0812dedSMatthew G. Knepley     PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname));
4532d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
4533d0812dedSMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
4534d0812dedSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
45359318fe57SMatthew G. Knepley   } else {
45369566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
45379318fe57SMatthew G. Knepley     switch (shape) {
4538669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
45395dca41c3SJed Brown     case DM_SHAPE_ZBOX:
4540669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
45419318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
45429318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
45439318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
45449318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4545669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
45469318fe57SMatthew G. Knepley       PetscInt       i, n;
45479318fe57SMatthew G. Knepley 
45489318fe57SMatthew G. Knepley       n = dim;
45499318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
45509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
45519318fe57SMatthew G. Knepley       n = 3;
45529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
455363a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
45549318fe57SMatthew G. Knepley       n = 3;
45559566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
455663a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
45579318fe57SMatthew G. Knepley       n = 3;
45589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
455963a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4560669647acSMatthew G. Knepley 
4561669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
4562669647acSMatthew G. Knepley       if (isAnnular)
4563669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
4564669647acSMatthew G. Knepley 
45659318fe57SMatthew G. Knepley       switch (cell) {
456661a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
45679566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
4568d410b0cfSMatthew G. Knepley         if (!interpolate) {
4569d410b0cfSMatthew G. Knepley           DM udm;
4570d410b0cfSMatthew G. Knepley 
45719566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
457269d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
4573d410b0cfSMatthew G. Knepley         }
45749318fe57SMatthew G. Knepley         break;
4575d71ae5a4SJacob Faibussowitsch       default:
45765dca41c3SJed Brown         PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate));
4577d71ae5a4SJacob Faibussowitsch         break;
45789318fe57SMatthew G. Knepley       }
4579669647acSMatthew G. Knepley       if (isAnnular) {
4580669647acSMatthew G. Knepley         DM          cdm;
4581669647acSMatthew G. Knepley         PetscDS     cds;
4582669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
4583669647acSMatthew G. Knepley 
4584669647acSMatthew G. Knepley         // Fix coordinates for annular region
4585669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
4586669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
4587669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
4588e44f6aebSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
4589669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
4590669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
4591669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
4592669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
4593669647acSMatthew G. Knepley       }
45949371c9d4SSatish Balay     } break;
45959371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
45969318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
45979318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
45989318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
45999318fe57SMatthew G. Knepley       PetscInt  i, n;
46009318fe57SMatthew G. Knepley 
46019318fe57SMatthew G. Knepley       n = dim + 1;
46029318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
46039566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
46049318fe57SMatthew G. Knepley       n = 3;
46059566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
460663a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim + 1), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim + 1);
46079318fe57SMatthew G. Knepley       n = 3;
46089566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
460963a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim + 1), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim + 1);
46109566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
46119371c9d4SSatish Balay     } break;
46129371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
46139318fe57SMatthew G. Knepley       PetscReal R = 1.0;
46149318fe57SMatthew G. Knepley 
46159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
46169566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
46179371c9d4SSatish Balay     } break;
46189371c9d4SSatish Balay     case DM_SHAPE_BALL: {
46199318fe57SMatthew G. Knepley       PetscReal R = 1.0;
46209318fe57SMatthew G. Knepley 
46219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
46229566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
46239371c9d4SSatish Balay     } break;
46249371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
46259318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
46269318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
462749704ca5SMatthew G. Knepley       PetscInt       Nr  = 0;
46289318fe57SMatthew G. Knepley 
46299566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
46309566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
463149704ca5SMatthew G. Knepley       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL));
46329318fe57SMatthew G. Knepley       switch (cell) {
4633d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
4634d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
4635d71ae5a4SJacob Faibussowitsch         break;
4636d71ae5a4SJacob Faibussowitsch       default:
463749704ca5SMatthew G. Knepley         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr));
4638d71ae5a4SJacob Faibussowitsch         break;
46399318fe57SMatthew G. Knepley       }
46409371c9d4SSatish Balay     } break;
4641b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
46429371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
4643b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
4644b7f5c055SJed Brown       PetscReal      thickness   = 0.;
4645b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4646b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
46471436d7faSJed Brown       PetscBool      tps_distribute;
46489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
46499566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
46509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
46519566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
46529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
46539566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
46549566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
46559566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
46569371c9d4SSatish Balay     } break;
46579371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
465805bd46c0SStefano Zampini       DM        dmnew;
465905bd46c0SStefano Zampini       PetscReal rl = 0.0;
466005bd46c0SStefano Zampini 
466105bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
466205bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
46635de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
466469d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
46659371c9d4SSatish Balay     } break;
4666cfb853baSMatthew G. Knepley     case DM_SHAPE_HYPERCUBIC: {
46678d2ec52aSSatish Balay       PetscInt       *edges, overlap = 1;
4668cfb853baSMatthew G. Knepley       PetscReal      *lower, *upper;
4669cfb853baSMatthew G. Knepley       DMBoundaryType *bdt;
4670cfb853baSMatthew G. Knepley       PetscInt        n, d;
4671cfb853baSMatthew G. Knepley 
4672cfb853baSMatthew G. Knepley       *useCoordSpace = PETSC_FALSE;
4673cfb853baSMatthew G. Knepley       PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt));
4674cfb853baSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
4675cfb853baSMatthew G. Knepley         edges[d] = 1;
4676cfb853baSMatthew G. Knepley         lower[d] = 0.;
4677cfb853baSMatthew G. Knepley         upper[d] = 1.;
4678cfb853baSMatthew G. Knepley         bdt[d]   = DM_BOUNDARY_PERIODIC;
4679cfb853baSMatthew G. Knepley       }
4680cfb853baSMatthew G. Knepley       n = dim;
4681cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg));
4682cfb853baSMatthew G. Knepley       n = dim;
4683cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
4684cfb853baSMatthew G. Knepley       PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4685cfb853baSMatthew G. Knepley       n = dim;
4686cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
4687cfb853baSMatthew G. Knepley       PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4688cfb853baSMatthew G. Knepley       n = dim;
4689cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
4690cfb853baSMatthew G. Knepley       PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
46918d2ec52aSSatish Balay       PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0));
46928d2ec52aSSatish Balay       PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt));
4693cfb853baSMatthew G. Knepley       PetscCall(PetscFree4(edges, lower, upper, bdt));
4694cfb853baSMatthew G. Knepley     } break;
4695d71ae5a4SJacob Faibussowitsch     default:
4696d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
46979318fe57SMatthew G. Knepley     }
46989318fe57SMatthew G. Knepley   }
46999566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
470048a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
4701b9da1bb3SMatthew G. Knepley   if (orient) PetscCall(DMPlexOrient(dm));
47024e22dd4cSMatthew G. Knepley   // Allow label creation
47034e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg));
47044e22dd4cSMatthew G. Knepley   if (flg) {
47054e22dd4cSMatthew G. Knepley     DMLabel     label;
47064e22dd4cSMatthew G. Knepley     PetscInt    points[1024], n = 1024;
47074e22dd4cSMatthew G. Knepley     char        fulloption[PETSC_MAX_PATH_LEN];
47084e22dd4cSMatthew G. Knepley     const char *name = &option[14];
47094e22dd4cSMatthew G. Knepley 
47104e22dd4cSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, name));
47114e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, name, &label));
47124e22dd4cSMatthew G. Knepley     fulloption[0] = '-';
47134e22dd4cSMatthew G. Knepley     fulloption[1] = 0;
47144e22dd4cSMatthew G. Knepley     PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN));
47154e22dd4cSMatthew G. Knepley     PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL));
47164e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1));
47174e22dd4cSMatthew G. Knepley   }
4718dd0eeac9SMatthew G. Knepley   // Allow cohesive label creation
4719dd0eeac9SMatthew G. Knepley   //   Faces are input, completed, and all points are marked with their depth
4720dd0eeac9SMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg));
4721dd0eeac9SMatthew G. Knepley   if (flg) {
4722dd0eeac9SMatthew G. Knepley     DMLabel   label;
4723dd0eeac9SMatthew G. Knepley     PetscInt  points[1024], n, pStart, pEnd, Nl = 1;
47245390be7dSMatthew G. Knepley     PetscBool noCreate = PETSC_FALSE;
4725dd0eeac9SMatthew G. Knepley     char      fulloption[PETSC_MAX_PATH_LEN];
4726dd0eeac9SMatthew G. Knepley     char      name[PETSC_MAX_PATH_LEN];
4727dd0eeac9SMatthew G. Knepley     size_t    len;
4728dd0eeac9SMatthew G. Knepley 
4729dd0eeac9SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4730dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN));
4731dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrlen(name, &len));
4732dd0eeac9SMatthew G. Knepley     if (name[len - 1] == '0') Nl = 10;
4733dd0eeac9SMatthew G. Knepley     for (PetscInt l = 0; l < Nl; ++l) {
47346497c311SBarry Smith       if (l > 0) name[len - 1] = (char)('0' + l);
4735dd0eeac9SMatthew G. Knepley       fulloption[0] = 0;
4736dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32));
4737dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32));
4738dd0eeac9SMatthew G. Knepley       n = 1024;
4739dd0eeac9SMatthew G. Knepley       PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg));
4740dd0eeac9SMatthew G. Knepley       if (!flg) break;
47415390be7dSMatthew G. Knepley       PetscCall(DMHasLabel(dm, name, &noCreate));
47425390be7dSMatthew G. Knepley       if (noCreate) {
47435390be7dSMatthew G. Knepley         DMLabel         inlabel;
47445390be7dSMatthew G. Knepley         IS              pointIS;
47455390be7dSMatthew G. Knepley         const PetscInt *lpoints;
47465390be7dSMatthew G. Knepley         PetscInt        pdep, ln, inval = points[0];
47475390be7dSMatthew G. Knepley         char            newname[PETSC_MAX_PATH_LEN];
47485390be7dSMatthew G. Knepley 
47495390be7dSMatthew G. Knepley         PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option");
47505390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &inlabel));
47515390be7dSMatthew G. Knepley         PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS));
47525390be7dSMatthew G. Knepley         PetscCall(ISGetLocalSize(pointIS, &ln));
47535390be7dSMatthew G. Knepley         PetscCall(ISGetIndices(pointIS, &lpoints));
47545390be7dSMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep));
47555390be7dSMatthew G. Knepley         PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0]));
47565390be7dSMatthew G. Knepley         PetscCall(DMCreateLabel(dm, newname));
47575390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, newname, &label));
47585390be7dSMatthew G. Knepley         if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints));
47595390be7dSMatthew G. Knepley         else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints));
47605390be7dSMatthew G. Knepley         PetscCall(ISRestoreIndices(pointIS, &lpoints));
47615390be7dSMatthew G. Knepley         PetscCall(ISDestroy(&pointIS));
47625390be7dSMatthew G. Knepley       } else {
4763dd0eeac9SMatthew G. Knepley         PetscCall(DMCreateLabel(dm, name));
4764dd0eeac9SMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &label));
4765dd0eeac9SMatthew G. Knepley         if (pStart >= pEnd) n = 0;
47665390be7dSMatthew G. Knepley         PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points));
4767dd0eeac9SMatthew G. Knepley       }
4768dd0eeac9SMatthew G. Knepley       PetscCall(DMPlexOrientLabel(dm, label));
47690542aa8cSMatthew G. Knepley       PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL));
4770dd0eeac9SMatthew G. Knepley     }
4771dd0eeac9SMatthew G. Knepley   }
47725390be7dSMatthew G. Knepley   PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view"));
4773708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
47743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47750a6ba040SMatthew G. Knepley }
47760a6ba040SMatthew G. Knepley 
4777d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
4778d71ae5a4SJacob Faibussowitsch {
47790a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
47807f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
47819318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
4782adc21957SMatthew G. Knepley   char      method[PETSC_MAX_PATH_LEN];
47830a6ba040SMatthew G. Knepley 
47840a6ba040SMatthew G. Knepley   PetscFunctionBegin;
47850a6ba040SMatthew G. Knepley   /* Handle viewing */
47869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
47875962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
47885962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0));
47899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
47909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
4791f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
4792a77a5016SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0));
47939566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
47949566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
47955e2c5519SMatthew G. Knepley   // Interpolation
47965e2c5519SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL));
47979318fe57SMatthew G. Knepley   /* Labeling */
47989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
47999566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
4800953fc75cSMatthew G. Knepley   /* Point Location */
48019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
48020848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
48039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
4804d02c7345SMatthew G. Knepley   /* Reordering */
4805adc21957SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg));
4806adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE));
4807adc21957SMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg));
4808adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetType(dm, method));
48092e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
48109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
4811b29cfa1cSToby Isaac   /* Projection behavior */
4812d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
48139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
4814f12cf164SMatthew G. Knepley   /* Checking structure */
4815f12cf164SMatthew G. Knepley   {
48167f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
4817f12cf164SMatthew G. Knepley 
48187f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
48197f9d8d6cSVaclav Hapla     if (all) {
48207f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
48217f9d8d6cSVaclav Hapla     } else {
48229566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
48237f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
48249566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_skeleton", "Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes)", "DMPlexCheckSkeleton", PETSC_FALSE, &flg, &flg2));
48257f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
48269566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_faces", "Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type", "DMPlexCheckFaces", PETSC_FALSE, &flg, &flg2));
48277f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
48289566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
48297f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
48309566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
4831d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
48329566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_interface_cones", "Check points on inter-partition interfaces have conforming order of cone points", "DMPlexCheckInterfaceCones", PETSC_FALSE, &flg, &flg2));
48337f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
48347f9d8d6cSVaclav Hapla     }
48359566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
48369566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
4837f12cf164SMatthew G. Knepley   }
48389318fe57SMatthew G. Knepley   {
48399318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
48404f3833eaSMatthew G. Knepley 
48419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
48429318fe57SMatthew G. Knepley     if (flg) {
48439318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
48449318fe57SMatthew G. Knepley 
48459566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
48469566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
48479566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
48489566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
48499318fe57SMatthew G. Knepley     }
48509318fe57SMatthew G. Knepley   }
48519566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
48523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485368d4fef7SMatthew G. Knepley }
485468d4fef7SMatthew G. Knepley 
4855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
4856d71ae5a4SJacob Faibussowitsch {
4857c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
4858c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
4859c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
4860c506a872SMatthew G. Knepley   PetscBool flg;
4861c506a872SMatthew G. Knepley 
4862c506a872SMatthew G. Knepley   PetscFunctionBegin;
4863c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
4864c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
4865c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
4866c506a872SMatthew G. Knepley   if (numOvLabels) {
4867c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
4868c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
4869c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
4870c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
4871c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
4872c506a872SMatthew G. Knepley     }
4873c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
4874c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
4875c506a872SMatthew G. Knepley     PetscCheck(numOvLabels == numOvValues, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "The number of labels %" PetscInt_FMT " must match the number of values %" PetscInt_FMT, numOvLabels, numOvValues);
4876c506a872SMatthew G. Knepley 
4877c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
4878c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
4879c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
4880c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
4881c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
4882c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
4883c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
4884c506a872SMatthew G. Knepley     }
4885c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
4886c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
4887c506a872SMatthew G. Knepley     PetscCheck(numOvExLabels == numOvExValues, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "The number of exclude labels %" PetscInt_FMT " must match the number of values %" PetscInt_FMT, numOvExLabels, numOvExValues);
4888c506a872SMatthew G. Knepley   }
48893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4890c506a872SMatthew G. Knepley }
4891c506a872SMatthew G. Knepley 
4892d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
4893d71ae5a4SJacob Faibussowitsch {
4894bdf63967SMatthew G. Knepley   PetscFunctionList    ordlist;
4895bdf63967SMatthew G. Knepley   char                 oname[256];
48964e22dd4cSMatthew G. Knepley   char                 sublabelname[PETSC_MAX_PATH_LEN] = "";
4897adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
4898d410b0cfSMatthew G. Knepley   PetscReal            volume    = -1.0;
48999318fe57SMatthew G. Knepley   PetscInt             prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
49001b742f01SMatthew G. Knepley   PetscBool            uniformOrig = PETSC_FALSE, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg;
490168d4fef7SMatthew G. Knepley 
490268d4fef7SMatthew G. Knepley   PetscFunctionBegin;
4903d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
4904dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
49059318fe57SMatthew G. Knepley   /* Handle automatic creation */
49069566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
49076bc1bd01Sksagiyam   if (dim < 0) {
49086bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
49096bc1bd01Sksagiyam     created = PETSC_TRUE;
49106bc1bd01Sksagiyam   }
49116bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
4912d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
49139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
4914d89e6e46SMatthew G. Knepley   if (flg) {
4915d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
4916d89e6e46SMatthew G. Knepley 
49179566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
4918d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
4919d89e6e46SMatthew G. Knepley       DM udm;
4920d89e6e46SMatthew G. Knepley 
49219566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
492269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
4923d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
4924d89e6e46SMatthew G. Knepley       DM idm;
4925d89e6e46SMatthew G. Knepley 
49269566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
492769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
4928d89e6e46SMatthew G. Knepley     }
4929d89e6e46SMatthew G. Knepley   }
49304e22dd4cSMatthew G. Knepley   // Handle submesh selection before distribution
49314e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg));
49324e22dd4cSMatthew G. Knepley   if (flg) {
49334e22dd4cSMatthew G. Knepley     DM              subdm;
49344e22dd4cSMatthew G. Knepley     DMLabel         label;
49354e22dd4cSMatthew G. Knepley     IS              valueIS, pointIS;
49364e22dd4cSMatthew G. Knepley     const PetscInt *values, *points;
49374e22dd4cSMatthew G. Knepley     PetscBool       markedFaces = PETSC_FALSE;
49384e22dd4cSMatthew G. Knepley     PetscInt        Nv, value, Np;
49394e22dd4cSMatthew G. Knepley 
49404e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, sublabelname, &label));
49414e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetNumValues(label, &Nv));
49424e22dd4cSMatthew G. Knepley     PetscCheck(Nv == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only a single label value is currently supported for submesh selection, not %" PetscInt_FMT, Nv);
49434e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetValueIS(label, &valueIS));
49444e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(valueIS, &values));
49454e22dd4cSMatthew G. Knepley     value = values[0];
49464e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(valueIS, &values));
49474e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&valueIS));
49484e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumSize(label, value, &Np));
49494e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumIS(label, value, &pointIS));
49504e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
49514e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < Np; ++p) {
49524e22dd4cSMatthew G. Knepley       PetscInt pdepth;
49534e22dd4cSMatthew G. Knepley 
49544e22dd4cSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth));
49554e22dd4cSMatthew G. Knepley       if (pdepth) {
49564e22dd4cSMatthew G. Knepley         markedFaces = PETSC_TRUE;
49574e22dd4cSMatthew G. Knepley         break;
49584e22dd4cSMatthew G. Knepley       }
49594e22dd4cSMatthew G. Knepley     }
49604e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(pointIS, &points));
49614e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
49624e22dd4cSMatthew G. Knepley     PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm));
49634e22dd4cSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &subdm));
49644e22dd4cSMatthew G. Knepley     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
49654e22dd4cSMatthew G. Knepley   }
49669b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
49679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
49689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
49699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
49709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
49719566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
49729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
49739318fe57SMatthew G. Knepley   if (flg) {
49749566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
49759566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
49769318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
49779318fe57SMatthew G. Knepley   }
4978b23db253SStefano Zampini   if (prerefine) PetscCall(DMLocalizeCoordinates(dm));
49799b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
49809b44eab4SMatthew G. Knepley     DM             rdm;
49819b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
49829b44eab4SMatthew G. Knepley 
4983dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
49849566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
498569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
4986dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
498761a622f3SMatthew G. Knepley     if (coordFunc && remap) {
49889566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
49899b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
49909b44eab4SMatthew G. Knepley     }
49919b44eab4SMatthew G. Knepley   }
49929566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
49939318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
49949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
49959318fe57SMatthew G. Knepley   if (extLayers) {
49969318fe57SMatthew G. Knepley     DM edm;
49979318fe57SMatthew G. Knepley 
49989566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
499969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
500048d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
5001dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5002d410b0cfSMatthew G. Knepley     extLayers = 0;
50035e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
50049318fe57SMatthew G. Knepley   }
5005bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
50066bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
50079566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
50086bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
50099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
5010adc21957SMatthew G. Knepley   if (reorder == DM_REORDER_DEFAULT_TRUE || flg) {
5011bdf63967SMatthew G. Knepley     DM pdm;
5012bdf63967SMatthew G. Knepley     IS perm;
5013bdf63967SMatthew G. Knepley 
50149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
50159566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
50169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
501769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
5018dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5019bdf63967SMatthew G. Knepley   }
50209b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
50219566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
5022c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
5023a286e215SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL));
5024dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
50259b44eab4SMatthew G. Knepley   if (distribute) {
50269b44eab4SMatthew G. Knepley     DM               pdm = NULL;
50279b44eab4SMatthew G. Knepley     PetscPartitioner part;
5028a286e215SMatthew G. Knepley     PetscSF          sfMigration;
50299b44eab4SMatthew G. Knepley 
50309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
50319566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
5032a286e215SMatthew G. Knepley     PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm));
50335d2873a6SJames Wright     if (pdm) {
50345d2873a6SJames Wright       // Delete the local section to force the existing one to be rebuilt with the distributed DM
50355d2873a6SJames Wright       PetscCall(DMSetLocalSection(dm, pdm->localSection));
50365d2873a6SJames Wright       PetscCall(DMPlexReplace_Internal(dm, &pdm));
50375d2873a6SJames Wright     }
5038a286e215SMatthew G. Knepley     if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration));
5039a286e215SMatthew G. Knepley     PetscCall(PetscSFDestroy(&sfMigration));
50409b44eab4SMatthew G. Knepley   }
50414054ae39SJames Wright 
50424054ae39SJames Wright   {
50434054ae39SJames Wright     PetscBool useBoxLabel = PETSC_FALSE;
50444054ae39SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL));
5045d7d2d1d2SJames Wright     if (useBoxLabel) {
5046d7d2d1d2SJames Wright       PetscInt       n      = 3;
5047d7d2d1d2SJames Wright       DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
5048d7d2d1d2SJames Wright 
5049d7d2d1d2SJames Wright       PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
5050d7d2d1d2SJames Wright       PetscCheck(!flg || !(n != dim), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
5051d7d2d1d2SJames Wright       PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt));
5052d7d2d1d2SJames Wright     }
50534054ae39SJames Wright   }
5054d2b2dc1eSMatthew G. Knepley   /* Must check CEED options before creating function space for coordinates */
5055d2b2dc1eSMatthew G. Knepley   {
5056d2b2dc1eSMatthew G. Knepley     PetscBool useCeed = PETSC_FALSE, flg;
5057d2b2dc1eSMatthew G. Knepley 
5058d2b2dc1eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg));
5059d2b2dc1eSMatthew G. Knepley     if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed));
5060d2b2dc1eSMatthew G. Knepley   }
50619318fe57SMatthew G. Knepley   /* Create coordinate space */
50629318fe57SMatthew G. Knepley   if (created) {
506361a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
5064e44f6aebSMatthew G. Knepley     PetscInt  degree = 1, deg;
50655515ebd3SMatthew G. Knepley     PetscInt  height = 0;
50665515ebd3SMatthew G. Knepley     DM        cdm;
5067c3db174cSMatthew G. Knepley     PetscBool flg, localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE;
50689318fe57SMatthew G. Knepley 
50699566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
50709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
5071e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDegree_Internal(dm, &deg));
5072e44f6aebSMatthew G. Knepley     if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc));
50735515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
507461a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
507561a622f3SMatthew G. Knepley       PetscDS      cds;
507661a622f3SMatthew G. Knepley       PetscObject  obj;
507761a622f3SMatthew G. Knepley       PetscClassId id;
507861a622f3SMatthew G. Knepley 
50799566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
50809566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
50819566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
508261a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
508361a622f3SMatthew G. Knepley         PetscContainer dummy;
508461a622f3SMatthew G. Knepley 
50859566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
50869566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
50879566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
50889566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
50899566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
509061a622f3SMatthew G. Knepley       }
509161a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
509261a622f3SMatthew G. Knepley     }
5093c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL));
5094c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg));
5095c3db174cSMatthew G. Knepley     if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize));
50965515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
50975515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
5098c3db174cSMatthew G. Knepley     if (localize) PetscCall(DMLocalizeCoordinates(dm));
50999318fe57SMatthew G. Knepley   }
510068d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
510161a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
51029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
51039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
51049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
51059566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
510668d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
5107acdc6f61SToby Isaac     DM *dms, coarseDM;
510868d4fef7SMatthew G. Knepley 
51099566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
51109566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
51119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
51129566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
511368d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
51149566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
511568d4fef7SMatthew G. Knepley     if (refine == 1) {
51169566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
51179566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
511868d4fef7SMatthew G. Knepley     } else {
51199566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
51209566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
51219566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
51229566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
512368d4fef7SMatthew G. Knepley     }
51249566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
51259566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
512668d4fef7SMatthew G. Knepley     /* Free DMs */
512768d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
5128dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
51299566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
513068d4fef7SMatthew G. Knepley     }
51319566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
513268d4fef7SMatthew G. Knepley   } else {
513368d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
51349318fe57SMatthew G. Knepley       DM             rdm;
513551a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
513668d4fef7SMatthew G. Knepley 
5137dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
51389566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
513968d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
514069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
5141dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
514261a622f3SMatthew G. Knepley       if (coordFunc && remap) {
51439566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
514451a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
514551a74b61SMatthew G. Knepley       }
514668d4fef7SMatthew G. Knepley     }
514768d4fef7SMatthew G. Knepley   }
51483cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
51499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
51509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
5151b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
5152b653a561SMatthew G. Knepley     DM *dms;
5153b653a561SMatthew G. Knepley 
51549566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
51559566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
5156b653a561SMatthew G. Knepley     /* Free DMs */
5157b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
5158dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
51599566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
5160b653a561SMatthew G. Knepley     }
51619566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
5162b653a561SMatthew G. Knepley   } else {
5163b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
51649318fe57SMatthew G. Knepley       DM             cdm;
51659318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
51663cf6fe12SMatthew G. Knepley 
5167dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
51689566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
51693cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
517069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
5171dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
51729318fe57SMatthew G. Knepley       if (coordFunc) {
51739566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
51749318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
51759318fe57SMatthew G. Knepley       }
51763cf6fe12SMatthew G. Knepley     }
5177b653a561SMatthew G. Knepley   }
5178be664eb1SMatthew G. Knepley   // Handle coordinate remapping
5179be664eb1SMatthew G. Knepley   remap = PETSC_FALSE;
5180be664eb1SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL));
5181be664eb1SMatthew G. Knepley   if (remap) {
5182be664eb1SMatthew G. Knepley     DMPlexCoordMap map     = DM_COORD_MAP_NONE;
5183be664eb1SMatthew G. Knepley     PetscPointFunc mapFunc = NULL;
5184be664eb1SMatthew G. Knepley     PetscScalar    params[16];
5185f45b553cSPierre Jolivet     PetscInt       Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim;
5186be664eb1SMatthew G. Knepley     MPI_Comm       comm;
5187be664eb1SMatthew G. Knepley 
5188be664eb1SMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5189be664eb1SMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
5190be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg));
5191be664eb1SMatthew G. Knepley     if (!flg) Np = 0;
5192be664eb1SMatthew G. Knepley     // TODO Allow user to pass a map function by name
5193be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg));
5194be664eb1SMatthew G. Knepley     if (flg) {
5195be664eb1SMatthew G. Knepley       switch (map) {
5196be664eb1SMatthew G. Knepley       case DM_COORD_MAP_NONE:
5197be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5198be664eb1SMatthew G. Knepley         break;
5199be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHEAR:
5200be664eb1SMatthew G. Knepley         mapFunc = coordMap_shear;
5201be664eb1SMatthew G. Knepley         if (!Np) {
5202be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5203be664eb1SMatthew G. Knepley           params[0] = 0;
5204be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5205be664eb1SMatthew G. Knepley         }
5206be664eb1SMatthew G. Knepley         PetscCheck(Np == cdim + 1, comm, PETSC_ERR_ARG_WRONG, "The shear coordinate map must have cdim + 1 = %" PetscInt_FMT " parameters, not %" PetscInt_FMT, cdim + 1, Np);
5207be664eb1SMatthew G. Knepley         break;
5208be664eb1SMatthew G. Knepley       case DM_COORD_MAP_FLARE:
5209be664eb1SMatthew G. Knepley         mapFunc = coordMap_flare;
5210be664eb1SMatthew G. Knepley         if (!Np) {
5211be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5212be664eb1SMatthew G. Knepley           params[0] = 0;
5213be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5214be664eb1SMatthew G. Knepley         }
5215be664eb1SMatthew G. Knepley         PetscCheck(Np == cdim + 1, comm, PETSC_ERR_ARG_WRONG, "The flare coordinate map must have cdim + 1 = %" PetscInt_FMT " parameters, not %" PetscInt_FMT, cdim + 1, Np);
5216be664eb1SMatthew G. Knepley         break;
5217be664eb1SMatthew G. Knepley       case DM_COORD_MAP_ANNULUS:
5218be664eb1SMatthew G. Knepley         mapFunc = coordMap_annulus;
5219be664eb1SMatthew G. Knepley         if (!Np) {
5220be664eb1SMatthew G. Knepley           Np        = 2;
5221be664eb1SMatthew G. Knepley           params[0] = 1.;
5222be664eb1SMatthew G. Knepley           params[1] = 2.;
5223be664eb1SMatthew G. Knepley         }
5224be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5225be664eb1SMatthew G. Knepley         break;
5226be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHELL:
5227be664eb1SMatthew G. Knepley         mapFunc = coordMap_shell;
5228be664eb1SMatthew G. Knepley         if (!Np) {
5229be664eb1SMatthew G. Knepley           Np        = 2;
5230be664eb1SMatthew G. Knepley           params[0] = 1.;
5231be664eb1SMatthew G. Knepley           params[1] = 2.;
5232be664eb1SMatthew G. Knepley         }
5233be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5234be664eb1SMatthew G. Knepley         break;
5235be664eb1SMatthew G. Knepley       default:
5236be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5237be664eb1SMatthew G. Knepley       }
5238be664eb1SMatthew G. Knepley     }
5239be664eb1SMatthew G. Knepley     if (Np) {
5240be664eb1SMatthew G. Knepley       DM      cdm;
5241be664eb1SMatthew G. Knepley       PetscDS cds;
5242be664eb1SMatthew G. Knepley 
5243be664eb1SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5244be664eb1SMatthew G. Knepley       PetscCall(DMGetDS(cdm, &cds));
5245be664eb1SMatthew G. Knepley       PetscCall(PetscDSSetConstants(cds, Np, params));
5246be664eb1SMatthew G. Knepley     }
5247be664eb1SMatthew G. Knepley     PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc));
5248be664eb1SMatthew G. Knepley   }
5249909dfd52SMatthew G. Knepley   /* Handle ghost cells */
52509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
5251909dfd52SMatthew G. Knepley   if (ghostCells) {
5252909dfd52SMatthew G. Knepley     DM   gdm;
5253909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
5254909dfd52SMatthew G. Knepley 
5255909dfd52SMatthew G. Knepley     lname[0] = '\0';
52569566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
52579566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
525869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
5259909dfd52SMatthew G. Knepley   }
52606913077dSMatthew G. Knepley   /* Handle 1D order */
5261adc21957SMatthew G. Knepley   if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) {
52626913077dSMatthew G. Knepley     DM           cdm, rdm;
52636913077dSMatthew G. Knepley     PetscDS      cds;
52646913077dSMatthew G. Knepley     PetscObject  obj;
52656913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
52666913077dSMatthew G. Knepley     IS           perm;
52676bc1bd01Sksagiyam     PetscInt     Nf;
52686913077dSMatthew G. Knepley     PetscBool    distributed;
52696913077dSMatthew G. Knepley 
52709566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
52719566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
52729566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
52739566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
52746913077dSMatthew G. Knepley     if (Nf) {
52759566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
52769566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
52776913077dSMatthew G. Knepley     }
52786bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
52799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
52809566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
528169d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
52829566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
52836913077dSMatthew G. Knepley     }
52846913077dSMatthew G. Knepley   }
52853cf6fe12SMatthew G. Knepley /* Handle */
5286dd4c3f67SMatthew G. Knepley non_refine:
5287dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
528822d6dc08SStefano Zampini   char    *phases[16];
528922d6dc08SStefano Zampini   PetscInt Nphases = 16;
529022d6dc08SStefano Zampini   PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg));
5291d0609cedSBarry Smith   PetscOptionsHeadEnd();
529222d6dc08SStefano Zampini 
529322d6dc08SStefano Zampini   // Phases
529422d6dc08SStefano Zampini   if (flg) {
529522d6dc08SStefano Zampini     const char *oldPrefix;
529622d6dc08SStefano Zampini 
529722d6dc08SStefano Zampini     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &oldPrefix));
529822d6dc08SStefano Zampini     for (PetscInt ph = 0; ph < Nphases; ++ph) {
529922d6dc08SStefano Zampini       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph]));
530022d6dc08SStefano Zampini       PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name));
530122d6dc08SStefano Zampini       PetscCall(DMSetFromOptions(dm));
530222d6dc08SStefano Zampini       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix));
530322d6dc08SStefano Zampini       PetscCall(PetscFree(phases[ph]));
530422d6dc08SStefano Zampini     }
530522d6dc08SStefano Zampini   }
53063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53070a6ba040SMatthew G. Knepley }
53080a6ba040SMatthew G. Knepley 
5309d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
5310d71ae5a4SJacob Faibussowitsch {
5311552f7358SJed Brown   PetscFunctionBegin;
53129566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
53139566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
53149566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
53159566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
53169566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
53179566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
53183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5319552f7358SJed Brown }
5320552f7358SJed Brown 
5321d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
5322d71ae5a4SJacob Faibussowitsch {
5323552f7358SJed Brown   PetscFunctionBegin;
53249566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
53259566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
53269566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
53273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5328552f7358SJed Brown }
5329552f7358SJed Brown 
5330d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5331d71ae5a4SJacob Faibussowitsch {
5332793f3fe5SMatthew G. Knepley   PetscInt depth, d;
5333793f3fe5SMatthew G. Knepley 
5334793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
53359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
5336793f3fe5SMatthew G. Knepley   if (depth == 1) {
53379566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
53389566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
53399566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
53409371c9d4SSatish Balay     else {
53419371c9d4SSatish Balay       *pStart = 0;
53429371c9d4SSatish Balay       *pEnd   = 0;
53439371c9d4SSatish Balay     }
5344793f3fe5SMatthew G. Knepley   } else {
53459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
5346793f3fe5SMatthew G. Knepley   }
53473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5348793f3fe5SMatthew G. Knepley }
5349793f3fe5SMatthew G. Knepley 
5350d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
5351d71ae5a4SJacob Faibussowitsch {
5352502a2867SDave May   PetscSF            sf;
53536497c311SBarry Smith   PetscMPIInt        niranks, njranks;
53546497c311SBarry Smith   PetscInt           n;
53550a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
53560a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
5357502a2867SDave May 
53582f356facSMatthew G. Knepley   PetscFunctionBegin;
53599566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
53600a19bb7dSprj-   if (!data->neighbors) {
53619566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
53629566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
53639566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
53649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
53659566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
53669566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
53670a19bb7dSprj-     n = njranks + niranks;
53689566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
53690a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
53709566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
53710a19bb7dSprj-   }
53720a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
53730a19bb7dSprj-   if (ranks) {
53740a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
53750a19bb7dSprj-     else *ranks = NULL;
53760a19bb7dSprj-   }
53773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5378502a2867SDave May }
5379502a2867SDave May 
53801eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
53811eb70e55SToby Isaac 
5382d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
5383d71ae5a4SJacob Faibussowitsch {
5384552f7358SJed Brown   PetscFunctionBegin;
5385552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
53862c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
5387552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
538838221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
5389552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
53901bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
5391adc21957SMatthew G. Knepley   dm->ops->createsectionpermutation  = DMCreateSectionPermutation_Plex;
539266ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
5393552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
5394552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
5395184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
53960298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
5397552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
5398f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
53990a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
5400552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
5401bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
5402bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
5403b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
54045a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
5405552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
54060a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
54070a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
5408b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
5409d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
54100298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
54110298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
54120298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
54130298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
5414552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
5415552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
54162adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
5417793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
5418552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
54190709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
54200709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
5421bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
54228c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
5423ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
54240709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
5425b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
54262a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
542728d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
54286c6a6b79SMatthew G. Knepley   dm->ops->getlocalboundingbox       = DMGetLocalBoundingBox_Coordinates;
5429907a3e9cSStefano Zampini   dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex;
5430907a3e9cSStefano Zampini   dm->ops->createddscatters          = DMCreateDomainDecompositionScatters_Plex;
54319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
54326c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
54339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
54349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
54359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
54369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
54376bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
54386bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
5439adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex));
5440adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex));
5441adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex));
5442adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex));
54439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
5444c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
5445c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
5446d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex));
5447d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex));
54483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5449552f7358SJed Brown }
5450552f7358SJed Brown 
5451d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
5452d71ae5a4SJacob Faibussowitsch {
545363a16f15SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *)dm->data;
54541fca310dSJames Wright   const PetscSF *face_sfs;
54551fca310dSJames Wright   PetscInt       num_face_sfs;
545663a16f15SMatthew G. Knepley 
545763a16f15SMatthew G. Knepley   PetscFunctionBegin;
545863a16f15SMatthew G. Knepley   mesh->refct++;
545963a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
54601fca310dSJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs));
54611fca310dSJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs));
54629566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
54639566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
54643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546563a16f15SMatthew G. Knepley }
546663a16f15SMatthew G. Knepley 
54678818961aSMatthew G Knepley /*MC
5468a1cb98faSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
546920f4b53cSBarry Smith                     In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is
54708818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
5471a1cb98faSBarry Smith                     ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
54728818961aSMatthew G Knepley 
5473e5893cccSMatthew G. Knepley   Options Database Keys:
5474250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
5475250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
5476250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
5477250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
5478250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
5479250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
5480c3db174cSMatthew G. Knepley . -dm_localize <bool>                - Whether to localize coordinates for periodic meshes
5481c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool>         - Whether to only localize cells on the periodic boundary
5482250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
5483ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
5484f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
5485f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
5486d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
5487f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
5488d02c7345SMatthew G. Knepley . -dm_plex_reorder_section           - Use specialized blocking if available
5489aaa8cc7dSPierre Jolivet . -dm_plex_check_all                 - Perform all checks below
5490f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
5491f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
5492f12cf164SMatthew G. Knepley . -dm_plex_check_faces <celltype>    - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type
5493f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
5494f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
5495e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
54965962854dSMatthew G. Knepley . -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
54975962854dSMatthew G. Knepley - -dm_plex_print_fvm <num>           - View FVM assembly information, such as flux updates
5498e5893cccSMatthew G. Knepley 
54998818961aSMatthew G Knepley   Level: intermediate
55008818961aSMatthew G Knepley 
55011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
55028818961aSMatthew G Knepley M*/
55038818961aSMatthew G Knepley 
5504d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
5505d71ae5a4SJacob Faibussowitsch {
5506552f7358SJed Brown   DM_Plex *mesh;
5507412e9a14SMatthew G. Knepley   PetscInt unit;
5508552f7358SJed Brown 
5509552f7358SJed Brown   PetscFunctionBegin;
5510f39ec787SMatthew G. Knepley   PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite));
5511552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55124dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
5513adc21957SMatthew G. Knepley   dm->reorderSection = DM_REORDER_DEFAULT_NOTSET;
5514552f7358SJed Brown   dm->data           = mesh;
5515552f7358SJed Brown 
5516552f7358SJed Brown   mesh->refct = 1;
55179566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
55189566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
5519552f7358SJed Brown   mesh->refinementUniform       = PETSC_TRUE;
5520552f7358SJed Brown   mesh->refinementLimit         = -1.0;
5521e600fa54SMatthew G. Knepley   mesh->distDefault             = PETSC_TRUE;
5522adc21957SMatthew G. Knepley   mesh->reorderDefault          = DM_REORDER_DEFAULT_NOTSET;
55231d1f2f2aSksagiyam   mesh->distributionName        = NULL;
55247d0f5628SVaclav Hapla   mesh->interpolated            = DMPLEX_INTERPOLATED_INVALID;
55257d0f5628SVaclav Hapla   mesh->interpolatedCollective  = DMPLEX_INTERPOLATED_INVALID;
55265e2c5519SMatthew G. Knepley   mesh->interpolatePreferTensor = PETSC_TRUE;
5527552f7358SJed Brown 
55289566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
55292e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
5530d9deefdfSMatthew G. Knepley 
55318865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
5532552f7358SJed Brown 
5533df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
5534ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
55356113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
5536c29ce622SStefano Zampini   mesh->nonempty_comm = MPI_COMM_SELF;
5537552f7358SJed Brown 
55389566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
55393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5540552f7358SJed Brown }
5541552f7358SJed Brown 
5542552f7358SJed Brown /*@
5543a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
5544552f7358SJed Brown 
5545d083f849SBarry Smith   Collective
5546552f7358SJed Brown 
5547552f7358SJed Brown   Input Parameter:
5548a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
5549552f7358SJed Brown 
5550552f7358SJed Brown   Output Parameter:
5551a1cb98faSBarry Smith . mesh - The `DMPLEX` object
5552552f7358SJed Brown 
5553552f7358SJed Brown   Level: beginner
5554552f7358SJed Brown 
555542747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()`
5556552f7358SJed Brown @*/
5557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
5558d71ae5a4SJacob Faibussowitsch {
5559552f7358SJed Brown   PetscFunctionBegin;
55604f572ea9SToby Isaac   PetscAssertPointer(mesh, 2);
55619566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
55629566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
55633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5564552f7358SJed Brown }
5565552f7358SJed Brown 
5566b09969d6SVaclav Hapla /*@C
5567b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype
5568a1cb98faSBarry Smith 
556920f4b53cSBarry Smith   Collective; No Fortran Support
5570b09969d6SVaclav Hapla 
5571b09969d6SVaclav Hapla   Input Parameters:
5572a1cb98faSBarry Smith + dm          - The `DM`
5573b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5574a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5575a1cb98faSBarry Smith . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5576b09969d6SVaclav Hapla . numCorners  - The number of vertices for each cell
55775e488331SVaclav Hapla - cells       - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5578b09969d6SVaclav Hapla 
5579be8c289dSNicolas Barral   Output Parameters:
5580a1cb98faSBarry Smith + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5581be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
5582b09969d6SVaclav Hapla 
5583b09969d6SVaclav Hapla   Level: advanced
5584b09969d6SVaclav Hapla 
5585a1cb98faSBarry Smith   Notes:
5586a1cb98faSBarry Smith   Two triangles sharing a face
5587a1cb98faSBarry Smith .vb
5588a1cb98faSBarry Smith 
5589a1cb98faSBarry Smith         2
5590a1cb98faSBarry Smith       / | \
5591a1cb98faSBarry Smith      /  |  \
5592a1cb98faSBarry Smith     /   |   \
5593a1cb98faSBarry Smith    0  0 | 1  3
5594a1cb98faSBarry Smith     \   |   /
5595a1cb98faSBarry Smith      \  |  /
5596a1cb98faSBarry Smith       \ | /
5597a1cb98faSBarry Smith         1
5598a1cb98faSBarry Smith .ve
5599a1cb98faSBarry Smith   would have input
5600a1cb98faSBarry Smith .vb
5601a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5602a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5603a1cb98faSBarry Smith .ve
5604a1cb98faSBarry Smith   which would result in the `DMPLEX`
5605a1cb98faSBarry Smith .vb
5606a1cb98faSBarry Smith 
5607a1cb98faSBarry Smith         4
5608a1cb98faSBarry Smith       / | \
5609a1cb98faSBarry Smith      /  |  \
5610a1cb98faSBarry Smith     /   |   \
5611a1cb98faSBarry Smith    2  0 | 1  5
5612a1cb98faSBarry Smith     \   |   /
5613a1cb98faSBarry Smith      \  |  /
5614a1cb98faSBarry Smith       \ | /
5615a1cb98faSBarry Smith         3
5616a1cb98faSBarry Smith .ve
5617a1cb98faSBarry Smith 
5618a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
5619a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
5620a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5621a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5622a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5623a1cb98faSBarry Smith 
5624a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5625a1cb98faSBarry Smith 
56261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5627a1cb98faSBarry Smith           `PetscSF`
5628b09969d6SVaclav Hapla @*/
5629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
5630d71ae5a4SJacob Faibussowitsch {
56312464107aSksagiyam   PetscSF     sfPoint;
56322464107aSksagiyam   PetscLayout layout;
563382fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
5634a47d0d45SMatthew G. Knepley 
5635a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
563625b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
56379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
563825b6865aSVaclav Hapla   /* Get/check global number of vertices */
563925b6865aSVaclav Hapla   {
564025b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
564125b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
564225b6865aSVaclav Hapla 
564325b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
56441690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
56459371c9d4SSatish Balay     for (i = 0; i < len; i++)
56469371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
564725b6865aSVaclav Hapla     ++NVerticesInCells;
5648462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
564925b6865aSVaclav Hapla 
565025b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
56519371c9d4SSatish Balay     else
56529371c9d4SSatish Balay       PetscCheck(NVertices == PETSC_DECIDE || NVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, NVertices, NVerticesInCells);
565325b6865aSVaclav Hapla   }
56549079aca8SVaclav Hapla   /* Count locally unique vertices */
56559079aca8SVaclav Hapla   {
56569079aca8SVaclav Hapla     PetscHSetI vhash;
56579079aca8SVaclav Hapla     PetscInt   off = 0;
56589079aca8SVaclav Hapla 
56599566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
5660a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
566148a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
5662a47d0d45SMatthew G. Knepley     }
56639566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
56649566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5665ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
56669566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
56679566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
566863a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5669a47d0d45SMatthew G. Knepley   }
56709566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5671a47d0d45SMatthew G. Knepley   /* Create cones */
56729566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
56739566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
56749566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
56759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
5676a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
5677a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
5678a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
5679a47d0d45SMatthew G. Knepley       PetscInt       lv;
5680a47d0d45SMatthew G. Knepley 
56819079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
56829079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
56839566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
568463a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5685961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
5686a47d0d45SMatthew G. Knepley     }
5687a47d0d45SMatthew G. Knepley   }
56882464107aSksagiyam   /* Build point sf */
56899566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
56909566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
56919566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
56929566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
56939566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
56949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
56959566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
56969566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
56972464107aSksagiyam   if (dm->sf) {
56982464107aSksagiyam     const char *prefix;
56992464107aSksagiyam 
57009566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
57019566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
57022464107aSksagiyam   }
57039566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
57049566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
5705f4f49eeaSPierre Jolivet   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5706a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
57079566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
57089566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
57099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
57103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5711a47d0d45SMatthew G. Knepley }
5712a47d0d45SMatthew G. Knepley 
5713b0fe842aSMatthew G. Knepley /*@C
5714b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes
5715b0fe842aSMatthew G. Knepley 
5716b0fe842aSMatthew G. Knepley   Collective; No Fortran Support
5717b0fe842aSMatthew G. Knepley 
5718b0fe842aSMatthew G. Knepley   Input Parameters:
5719b0fe842aSMatthew G. Knepley + dm          - The `DM`
5720b0fe842aSMatthew G. Knepley . numCells    - The number of cells owned by this process
5721b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5722b0fe842aSMatthew G. Knepley . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5723b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells)
5724b0fe842aSMatthew G. Knepley - cells       - An array of the global vertex numbers for each cell
5725b0fe842aSMatthew G. Knepley 
5726b0fe842aSMatthew G. Knepley   Output Parameters:
5727b0fe842aSMatthew G. Knepley + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5728b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array
5729b0fe842aSMatthew G. Knepley 
5730b0fe842aSMatthew G. Knepley   Level: advanced
5731b0fe842aSMatthew G. Knepley 
5732b0fe842aSMatthew G. Knepley   Notes:
5733b0fe842aSMatthew G. Knepley   A triangle and quadrilateral sharing a face
5734b0fe842aSMatthew G. Knepley .vb
5735b0fe842aSMatthew G. Knepley         2----------3
5736b0fe842aSMatthew G. Knepley       / |          |
5737b0fe842aSMatthew G. Knepley      /  |          |
5738b0fe842aSMatthew G. Knepley     /   |          |
5739b0fe842aSMatthew G. Knepley    0  0 |     1    |
5740b0fe842aSMatthew G. Knepley     \   |          |
5741b0fe842aSMatthew G. Knepley      \  |          |
5742b0fe842aSMatthew G. Knepley       \ |          |
5743b0fe842aSMatthew G. Knepley         1----------4
5744b0fe842aSMatthew G. Knepley .ve
5745b0fe842aSMatthew G. Knepley   would have input
5746b0fe842aSMatthew G. Knepley .vb
5747b0fe842aSMatthew G. Knepley   numCells = 2, numVertices = 5
5748b0fe842aSMatthew G. Knepley   cells = [0 1 2  1 4 3 2]
5749b0fe842aSMatthew G. Knepley .ve
5750b0fe842aSMatthew G. Knepley   which would result in the `DMPLEX`
5751b0fe842aSMatthew G. Knepley .vb
5752b0fe842aSMatthew G. Knepley         4----------5
5753b0fe842aSMatthew G. Knepley       / |          |
5754b0fe842aSMatthew G. Knepley      /  |          |
5755b0fe842aSMatthew G. Knepley     /   |          |
5756b0fe842aSMatthew G. Knepley    2  0 |     1    |
5757b0fe842aSMatthew G. Knepley     \   |          |
5758b0fe842aSMatthew G. Knepley      \  |          |
5759b0fe842aSMatthew G. Knepley       \ |          |
5760b0fe842aSMatthew G. Knepley         3----------6
5761b0fe842aSMatthew G. Knepley .ve
5762b0fe842aSMatthew G. Knepley 
5763b0fe842aSMatthew G. Knepley   Vertices are implicitly numbered consecutively 0,...,NVertices.
5764b0fe842aSMatthew G. Knepley   Each rank owns a chunk of numVertices consecutive vertices.
5765b0fe842aSMatthew G. Knepley   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5766b0fe842aSMatthew G. Knepley   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5767b0fe842aSMatthew G. Knepley   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5768b0fe842aSMatthew G. Knepley 
5769b0fe842aSMatthew G. Knepley   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5770b0fe842aSMatthew G. Knepley 
5771b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5772b0fe842aSMatthew G. Knepley           `PetscSF`
5773b0fe842aSMatthew G. Knepley @*/
5774b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
5775b0fe842aSMatthew G. Knepley {
5776b0fe842aSMatthew G. Knepley   PetscSF     sfPoint;
5777b0fe842aSMatthew G. Knepley   PetscLayout layout;
5778b0fe842aSMatthew G. Knepley   PetscInt    numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len;
5779b0fe842aSMatthew G. Knepley 
5780b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
5781b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
5782b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
5783b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd));
5784b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(cellSection, &len));
5785b0fe842aSMatthew G. Knepley   PetscCheck(cStart == 0 && cEnd == numCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section chart [%" PetscInt_FMT ", %" PetscInt_FMT ") should be [0, %" PetscInt_FMT ")", cStart, cEnd, numCells);
5786b0fe842aSMatthew G. Knepley   /* Get/check global number of vertices */
5787b0fe842aSMatthew G. Knepley   {
5788b0fe842aSMatthew G. Knepley     PetscInt NVerticesInCells;
5789b0fe842aSMatthew G. Knepley 
5790b0fe842aSMatthew G. Knepley     /* NVerticesInCells = max(cells) + 1 */
5791b0fe842aSMatthew G. Knepley     NVerticesInCells = PETSC_MIN_INT;
5792b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++)
5793b0fe842aSMatthew G. Knepley       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
5794b0fe842aSMatthew G. Knepley     ++NVerticesInCells;
5795b0fe842aSMatthew G. Knepley     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
5796b0fe842aSMatthew G. Knepley 
5797b0fe842aSMatthew G. Knepley     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
5798b0fe842aSMatthew G. Knepley     else
5799b0fe842aSMatthew G. Knepley       PetscCheck(NVertices == PETSC_DECIDE || NVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, NVertices, NVerticesInCells);
5800b0fe842aSMatthew G. Knepley   }
5801b0fe842aSMatthew G. Knepley   /* Count locally unique vertices */
5802b0fe842aSMatthew G. Knepley   {
5803b0fe842aSMatthew G. Knepley     PetscHSetI vhash;
5804b0fe842aSMatthew G. Knepley     PetscInt   off = 0;
5805b0fe842aSMatthew G. Knepley 
5806b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetICreate(&vhash));
5807b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i]));
5808b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
5809b0fe842aSMatthew G. Knepley     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5810b0fe842aSMatthew G. Knepley     else verticesAdj = *verticesAdjSaved;
5811b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
5812b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIDestroy(&vhash));
5813b0fe842aSMatthew G. Knepley     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5814b0fe842aSMatthew G. Knepley   }
5815b0fe842aSMatthew G. Knepley   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5816b0fe842aSMatthew G. Knepley   /* Create cones */
5817b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
5818b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
5819b0fe842aSMatthew G. Knepley     PetscInt dof;
5820b0fe842aSMatthew G. Knepley 
5821b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
5822b0fe842aSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(dm, c, dof));
5823b0fe842aSMatthew G. Knepley   }
5824b0fe842aSMatthew G. Knepley   PetscCall(DMSetUp(dm));
5825b0fe842aSMatthew G. Knepley   PetscCall(DMPlexGetCones(dm, &cones));
5826b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
5827b0fe842aSMatthew G. Knepley     PetscInt dof, off;
5828b0fe842aSMatthew G. Knepley 
5829b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
5830b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(cellSection, c, &off));
5831b0fe842aSMatthew G. Knepley     for (PetscInt p = off; p < off + dof; ++p) {
5832b0fe842aSMatthew G. Knepley       const PetscInt gv = cells[p];
5833b0fe842aSMatthew G. Knepley       PetscInt       lv;
5834b0fe842aSMatthew G. Knepley 
5835b0fe842aSMatthew G. Knepley       /* Positions within verticesAdj form 0-based local vertex numbering;
5836b0fe842aSMatthew G. Knepley          we need to shift it by numCells to get correct DAG points (cells go first) */
5837b0fe842aSMatthew G. Knepley       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
5838b0fe842aSMatthew G. Knepley       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5839b0fe842aSMatthew G. Knepley       cones[p] = lv + numCells;
5840b0fe842aSMatthew G. Knepley     }
5841b0fe842aSMatthew G. Knepley   }
5842b0fe842aSMatthew G. Knepley   /* Build point sf */
5843b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
5844b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetSize(layout, NVertices));
5845b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
5846b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(layout, 1));
5847b0fe842aSMatthew G. Knepley   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
5848b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&layout));
5849b0fe842aSMatthew G. Knepley   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
5850b0fe842aSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
5851b0fe842aSMatthew G. Knepley   if (dm->sf) {
5852b0fe842aSMatthew G. Knepley     const char *prefix;
5853b0fe842aSMatthew G. Knepley 
5854b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
5855b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
5856b0fe842aSMatthew G. Knepley   }
5857b0fe842aSMatthew G. Knepley   PetscCall(DMSetPointSF(dm, sfPoint));
5858b0fe842aSMatthew G. Knepley   PetscCall(PetscSFDestroy(&sfPoint));
5859b0fe842aSMatthew G. Knepley   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5860b0fe842aSMatthew G. Knepley   /* Fill in the rest of the topology structure */
5861b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(dm));
5862b0fe842aSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
5863b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
5864b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5865b0fe842aSMatthew G. Knepley }
5866b0fe842aSMatthew G. Knepley 
5867cc4c1da9SBarry Smith /*@
5868a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
5869a1cb98faSBarry Smith 
587020f4b53cSBarry Smith   Collective; No Fortran Support
5871b09969d6SVaclav Hapla 
5872b09969d6SVaclav Hapla   Input Parameters:
5873a1cb98faSBarry Smith + dm           - The `DM`
5874b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
5875a1cb98faSBarry Smith . sfVert       - `PetscSF` describing complete vertex ownership
5876b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5877b09969d6SVaclav Hapla 
5878b09969d6SVaclav Hapla   Level: advanced
5879b09969d6SVaclav Hapla 
58801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
5881b09969d6SVaclav Hapla @*/
5882d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
5883d71ae5a4SJacob Faibussowitsch {
5884a47d0d45SMatthew G. Knepley   PetscSection coordSection;
5885a47d0d45SMatthew G. Knepley   Vec          coordinates;
5886a47d0d45SMatthew G. Knepley   PetscScalar *coords;
58871edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
5888835f2295SStefano Zampini   PetscMPIInt  spaceDimi;
5889a47d0d45SMatthew G. Knepley 
5890a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
58919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
58929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
58931dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
58949566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
58959566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
58961dca8a05SBarry Smith   PetscCheck(vEnd - vStart == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Supplied sfVert has wrong number of leaves = %" PetscInt_FMT " != %" PetscInt_FMT " = vEnd - vStart", numVerticesAdj, vEnd - vStart);
58979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
58989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
58999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
59009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
59011edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
59029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
59039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
5904a47d0d45SMatthew G. Knepley   }
59059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
59069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
59079566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
59089566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
59099566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
59109566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
59119566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
59129566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5913a47d0d45SMatthew G. Knepley   {
5914a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
5915a47d0d45SMatthew G. Knepley 
5916a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
5917835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi));
5918835f2295SStefano Zampini     PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype));
59199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
592021016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
592121016a8bSBarry Smith     {
592221016a8bSBarry Smith       PetscScalar *svertexCoords;
592321016a8bSBarry Smith       PetscInt     i;
59249566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
59253612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
59269566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
59279566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
59289566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
592921016a8bSBarry Smith     }
593021016a8bSBarry Smith #else
59319566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
59329566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
593321016a8bSBarry Smith #endif
59349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
5935a47d0d45SMatthew G. Knepley   }
59369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
59379566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
59389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
59399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
59403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5941a47d0d45SMatthew G. Knepley }
5942a47d0d45SMatthew G. Knepley 
5943c3edce3dSSatish Balay /*@
5944b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype
5945a1cb98faSBarry Smith 
5946a1cb98faSBarry Smith   Collective
5947a47d0d45SMatthew G. Knepley 
5948a47d0d45SMatthew G. Knepley   Input Parameters:
5949a47d0d45SMatthew G. Knepley + comm         - The communicator
5950a47d0d45SMatthew G. Knepley . dim          - The topological dimension of the mesh
5951a47d0d45SMatthew G. Knepley . numCells     - The number of cells owned by this process
5952a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
5953a1cb98faSBarry Smith . NVertices    - The global number of vertices, or `PETSC_DECIDE`
5954a47d0d45SMatthew G. Knepley . numCorners   - The number of vertices for each cell
5955a47d0d45SMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
5956a47d0d45SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5957a47d0d45SMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
5958a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5959a47d0d45SMatthew G. Knepley 
5960d8d19677SJose E. Roman   Output Parameters:
5961a1cb98faSBarry Smith + dm          - The `DM`
5962a1cb98faSBarry Smith . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
596360225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array
5964a47d0d45SMatthew G. Knepley 
5965b09969d6SVaclav Hapla   Level: intermediate
5966a47d0d45SMatthew G. Knepley 
5967a1cb98faSBarry Smith   Notes:
5968a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
5969a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
5970a1cb98faSBarry Smith 
5971a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
5972a1cb98faSBarry Smith 
5973a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
5974a1cb98faSBarry Smith 
59751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
5976a47d0d45SMatthew G. Knepley @*/
5977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
5978d71ae5a4SJacob Faibussowitsch {
5979a47d0d45SMatthew G. Knepley   PetscSF sfVert;
5980a47d0d45SMatthew G. Knepley 
5981a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
59829566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
59839566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
5984a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
5985064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
59869566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
59879566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
5988a47d0d45SMatthew G. Knepley   if (interpolate) {
59895fd9971aSMatthew G. Knepley     DM idm;
5990a47d0d45SMatthew G. Knepley 
59919566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
59929566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
5993a47d0d45SMatthew G. Knepley     *dm = idm;
5994a47d0d45SMatthew G. Knepley   }
59959566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
599618d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
59979566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
59983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5999a47d0d45SMatthew G. Knepley }
6000a47d0d45SMatthew G. Knepley 
6001cc4c1da9SBarry Smith /*@
6002b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes
6003b0fe842aSMatthew G. Knepley 
6004b0fe842aSMatthew G. Knepley   Collective
6005b0fe842aSMatthew G. Knepley 
6006b0fe842aSMatthew G. Knepley   Input Parameters:
6007b0fe842aSMatthew G. Knepley + comm         - The communicator
6008b0fe842aSMatthew G. Knepley . dim          - The topological dimension of the mesh
6009b0fe842aSMatthew G. Knepley . numCells     - The number of cells owned by this process
6010b0fe842aSMatthew G. Knepley . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6011b0fe842aSMatthew G. Knepley . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6012b0fe842aSMatthew G. Knepley . cellSection  - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6013b0fe842aSMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6014b0fe842aSMatthew G. Knepley . cells        - An array of the global vertex numbers for each cell
6015b0fe842aSMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6016b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6017b0fe842aSMatthew G. Knepley 
6018b0fe842aSMatthew G. Knepley   Output Parameters:
6019b0fe842aSMatthew G. Knepley + dm          - The `DM`
6020b0fe842aSMatthew G. Knepley . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
6021b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array
6022b0fe842aSMatthew G. Knepley 
6023b0fe842aSMatthew G. Knepley   Level: intermediate
6024b0fe842aSMatthew G. Knepley 
6025b0fe842aSMatthew G. Knepley   Notes:
6026b0fe842aSMatthew G. Knepley   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6027b0fe842aSMatthew G. Knepley   `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6028b0fe842aSMatthew G. Knepley 
6029b0fe842aSMatthew G. Knepley   See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters.
6030b0fe842aSMatthew G. Knepley 
6031b0fe842aSMatthew G. Knepley   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6032b0fe842aSMatthew G. Knepley 
6033b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6034b0fe842aSMatthew G. Knepley @*/
6035b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexCreateFromCellSectionParallel(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
6036b0fe842aSMatthew G. Knepley {
6037b0fe842aSMatthew G. Knepley   PetscSF sfVert;
6038b0fe842aSMatthew G. Knepley 
6039b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6040b0fe842aSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
6041b0fe842aSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
6042b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6043b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
6044b0fe842aSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
6045b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj));
6046b0fe842aSMatthew G. Knepley   if (interpolate) {
6047b0fe842aSMatthew G. Knepley     DM idm;
6048b0fe842aSMatthew G. Knepley 
6049b0fe842aSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
6050b0fe842aSMatthew G. Knepley     PetscCall(DMDestroy(dm));
6051b0fe842aSMatthew G. Knepley     *dm = idm;
6052b0fe842aSMatthew G. Knepley   }
6053b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
6054b0fe842aSMatthew G. Knepley   if (vertexSF) *vertexSF = sfVert;
6055b0fe842aSMatthew G. Knepley   else PetscCall(PetscSFDestroy(&sfVert));
6056b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6057b0fe842aSMatthew G. Knepley }
6058b0fe842aSMatthew G. Knepley 
6059b0fe842aSMatthew G. Knepley /*@
6060a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
6061a1cb98faSBarry Smith 
606220f4b53cSBarry Smith   Collective; No Fortran Support
60639298eaa6SMatthew G Knepley 
60649298eaa6SMatthew G Knepley   Input Parameters:
6065a1cb98faSBarry Smith + dm          - The `DM`
6066b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
6067a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
60689298eaa6SMatthew G Knepley . numCorners  - The number of vertices for each cell
6069a3b724e8SBarry Smith - cells       - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell
60709298eaa6SMatthew G Knepley 
6071b09969d6SVaclav Hapla   Level: advanced
60729298eaa6SMatthew G Knepley 
6073b09969d6SVaclav Hapla   Notes:
6074b09969d6SVaclav Hapla   Two triangles sharing a face
6075a1cb98faSBarry Smith .vb
60769298eaa6SMatthew G Knepley 
6077a1cb98faSBarry Smith         2
6078a1cb98faSBarry Smith       / | \
6079a1cb98faSBarry Smith      /  |  \
6080a1cb98faSBarry Smith     /   |   \
6081a1cb98faSBarry Smith    0  0 | 1  3
6082a1cb98faSBarry Smith     \   |   /
6083a1cb98faSBarry Smith      \  |  /
6084a1cb98faSBarry Smith       \ | /
6085a1cb98faSBarry Smith         1
6086a1cb98faSBarry Smith .ve
6087a1cb98faSBarry Smith   would have input
6088a1cb98faSBarry Smith .vb
6089a1cb98faSBarry Smith   numCells = 2, numVertices = 4
6090a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
6091a1cb98faSBarry Smith .ve
6092a1cb98faSBarry Smith   which would result in the `DMPLEX`
6093a1cb98faSBarry Smith .vb
6094a1cb98faSBarry Smith 
6095a1cb98faSBarry Smith         4
6096a1cb98faSBarry Smith       / | \
6097a1cb98faSBarry Smith      /  |  \
6098a1cb98faSBarry Smith     /   |   \
6099a1cb98faSBarry Smith    2  0 | 1  5
6100a1cb98faSBarry Smith     \   |   /
6101a1cb98faSBarry Smith      \  |  /
6102a1cb98faSBarry Smith       \ | /
6103a1cb98faSBarry Smith         3
6104a1cb98faSBarry Smith .ve
6105a1cb98faSBarry Smith 
6106a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
610725b6865aSVaclav Hapla 
61081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
6109b09969d6SVaclav Hapla @*/
6110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
6111d71ae5a4SJacob Faibussowitsch {
6112961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
6113b09969d6SVaclav Hapla 
6114b09969d6SVaclav Hapla   PetscFunctionBegin;
61159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
61169566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
611725b6865aSVaclav Hapla   /* Get/check global number of vertices */
611825b6865aSVaclav Hapla   {
611925b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
612025b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
612125b6865aSVaclav Hapla 
612225b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
61231690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
61249371c9d4SSatish Balay     for (i = 0; i < len; i++)
61259371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
612625b6865aSVaclav Hapla     ++NVerticesInCells;
612725b6865aSVaclav Hapla 
612825b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
61299371c9d4SSatish Balay     else
61309371c9d4SSatish Balay       PetscCheck(numVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, numVertices, NVerticesInCells);
613125b6865aSVaclav Hapla   }
61329566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
613348a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
61349566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
61359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6136b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
6137ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
6138b09969d6SVaclav Hapla   }
61399566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
61409566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
61419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
61423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6143b09969d6SVaclav Hapla }
6144b09969d6SVaclav Hapla 
6145cc4c1da9SBarry Smith /*@
6146a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6147a1cb98faSBarry Smith 
6148cc4c1da9SBarry Smith   Collective
6149b09969d6SVaclav Hapla 
6150b09969d6SVaclav Hapla   Input Parameters:
6151a1cb98faSBarry Smith + dm           - The `DM`
6152b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6153b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6154b09969d6SVaclav Hapla 
6155b09969d6SVaclav Hapla   Level: advanced
6156b09969d6SVaclav Hapla 
61571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
6158b09969d6SVaclav Hapla @*/
6159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
6160d71ae5a4SJacob Faibussowitsch {
6161b09969d6SVaclav Hapla   PetscSection coordSection;
6162b09969d6SVaclav Hapla   Vec          coordinates;
6163b09969d6SVaclav Hapla   DM           cdm;
6164b09969d6SVaclav Hapla   PetscScalar *coords;
61651edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
6166b09969d6SVaclav Hapla 
6167b09969d6SVaclav Hapla   PetscFunctionBegin;
61689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
61699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
61701dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
61719566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
61729566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
61739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
61749566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
61759566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
61761edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
61779566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
61789566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6179b09969d6SVaclav Hapla   }
61809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6181b09969d6SVaclav Hapla 
61829566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
61839566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
61849566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
61859566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
61869566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
61871edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
6188ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
6189b09969d6SVaclav Hapla   }
61909566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
61919566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
61929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
61939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
61943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6195b09969d6SVaclav Hapla }
6196b09969d6SVaclav Hapla 
6197b09969d6SVaclav Hapla /*@
6198a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
61993df08285SMatthew G. Knepley 
6200a1cb98faSBarry Smith   Collective
6201b09969d6SVaclav Hapla 
6202b09969d6SVaclav Hapla   Input Parameters:
6203b09969d6SVaclav Hapla + comm         - The communicator
6204b09969d6SVaclav Hapla . dim          - The topological dimension of the mesh
62053df08285SMatthew G. Knepley . numCells     - The number of cells, only on process 0
6206a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
62073df08285SMatthew G. Knepley . numCorners   - The number of vertices for each cell, only on process 0
6208b09969d6SVaclav Hapla . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
62093df08285SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
6210b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
62113df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
6212b09969d6SVaclav Hapla 
6213b09969d6SVaclav Hapla   Output Parameter:
6214a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
621525b6865aSVaclav Hapla 
6216b09969d6SVaclav Hapla   Level: intermediate
6217b09969d6SVaclav Hapla 
6218a1cb98faSBarry Smith   Notes:
6219a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
6220a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
6221a1cb98faSBarry Smith 
6222a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
6223a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
6224a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
6225a1cb98faSBarry Smith 
62261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
62279298eaa6SMatthew G Knepley @*/
6228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], DM *dm)
6229d71ae5a4SJacob Faibussowitsch {
62303df08285SMatthew G. Knepley   PetscMPIInt rank;
62319298eaa6SMatthew G Knepley 
62329298eaa6SMatthew G Knepley   PetscFunctionBegin;
623328b400f6SJacob Faibussowitsch   PetscCheck(dim, comm, PETSC_ERR_ARG_OUTOFRANGE, "This is not appropriate for 0-dimensional meshes. Consider either creating the DM using DMPlexCreateFromDAG(), by hand, or using DMSwarm.");
62349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
62359566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
62369566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
62379566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
6238c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
62399566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
62409298eaa6SMatthew G Knepley   if (interpolate) {
62415fd9971aSMatthew G. Knepley     DM idm;
62429298eaa6SMatthew G Knepley 
62439566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
62449566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
62459298eaa6SMatthew G Knepley     *dm = idm;
62469298eaa6SMatthew G Knepley   }
6247c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
62489566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
62493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62509298eaa6SMatthew G Knepley }
62519298eaa6SMatthew G Knepley 
6252939f6067SMatthew G. Knepley /*@
625320f4b53cSBarry Smith   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM`
6254939f6067SMatthew G. Knepley 
6255939f6067SMatthew G. Knepley   Input Parameters:
625620f4b53cSBarry Smith + dm               - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()`
6257939f6067SMatthew G. Knepley . depth            - The depth of the DAG
625820f4b53cSBarry Smith . numPoints        - Array of size depth + 1 containing the number of points at each `depth`
6259939f6067SMatthew G. Knepley . coneSize         - The cone size of each point
6260939f6067SMatthew G. Knepley . cones            - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
6261939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
626220f4b53cSBarry Smith - vertexCoords     - An array of `numPoints`[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via `DMSetCoordinateDim()`
6263939f6067SMatthew G. Knepley 
6264939f6067SMatthew G. Knepley   Output Parameter:
626520f4b53cSBarry Smith . dm - The `DM`
626620f4b53cSBarry Smith 
626720f4b53cSBarry Smith   Level: advanced
6268939f6067SMatthew G. Knepley 
6269a1cb98faSBarry Smith   Note:
6270a1cb98faSBarry Smith   Two triangles sharing a face would have input
6271a1cb98faSBarry Smith .vb
6272a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
6273a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
6274a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
6275a1cb98faSBarry Smith .ve
6276939f6067SMatthew G. Knepley   which would result in the DMPlex
6277a1cb98faSBarry Smith .vb
6278a1cb98faSBarry Smith         4
6279a1cb98faSBarry Smith       / | \
6280a1cb98faSBarry Smith      /  |  \
6281a1cb98faSBarry Smith     /   |   \
6282a1cb98faSBarry Smith    2  0 | 1  5
6283a1cb98faSBarry Smith     \   |   /
6284a1cb98faSBarry Smith      \  |  /
6285a1cb98faSBarry Smith       \ | /
6286a1cb98faSBarry Smith         3
6287a1cb98faSBarry Smith .ve
6288a1cb98faSBarry Smith   Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
6289939f6067SMatthew G. Knepley 
62901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
6291939f6067SMatthew G. Knepley @*/
6292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
6293d71ae5a4SJacob Faibussowitsch {
62949298eaa6SMatthew G Knepley   Vec          coordinates;
62959298eaa6SMatthew G Knepley   PetscSection coordSection;
62969298eaa6SMatthew G Knepley   PetscScalar *coords;
6297811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
62989298eaa6SMatthew G Knepley 
62999298eaa6SMatthew G Knepley   PetscFunctionBegin;
63009566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
63019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
630263a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
63039298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
63049566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
63059298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
63069566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
6307ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
630897e052ccSToby Isaac   }
63091dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
63109566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
63119298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
63129566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
63139566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
63149298eaa6SMatthew G Knepley   }
63159566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
63169566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
63179298eaa6SMatthew G Knepley   /* Build coordinates */
63189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
63199566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
63209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
63219566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
63229298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
63239566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
63249566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
63259298eaa6SMatthew G Knepley   }
63269566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
63279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
63289566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
63299566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
63309566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
63319566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
63329566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
63339318fe57SMatthew G. Knepley   if (vertexCoords) {
63349566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
63359298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
63369298eaa6SMatthew G Knepley       PetscInt off;
63379298eaa6SMatthew G Knepley 
63389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
6339ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
63409298eaa6SMatthew G Knepley     }
63419318fe57SMatthew G. Knepley   }
63429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
63439566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
63449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
63453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63469298eaa6SMatthew G Knepley }
63478415267dSToby Isaac 
6348a4e35b19SJacob Faibussowitsch /*
6349a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
6350a1cb98faSBarry Smith 
6351a1cb98faSBarry Smith   Collective
63528ca92349SMatthew G. Knepley 
63538ca92349SMatthew G. Knepley + comm        - The MPI communicator
63548ca92349SMatthew G. Knepley . filename    - Name of the .dat file
63558ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
63568ca92349SMatthew G. Knepley 
63578ca92349SMatthew G. Knepley   Output Parameter:
6358a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
63598ca92349SMatthew G. Knepley 
63608ca92349SMatthew G. Knepley   Level: beginner
63618ca92349SMatthew G. Knepley 
6362a1cb98faSBarry Smith   Note:
6363a1cb98faSBarry Smith   The format is the simplest possible:
6364a1cb98faSBarry Smith .vb
6365d0812dedSMatthew G. Knepley   dim Ne Nv Nc Nl
6366d0812dedSMatthew G. Knepley   v_1 v_2 ... v_Nc
6367d0812dedSMatthew G. Knepley   ...
6368d0812dedSMatthew G. Knepley   x y z marker_1 ... marker_Nl
6369a1cb98faSBarry Smith .ve
6370a1cb98faSBarry Smith 
6371a1cb98faSBarry Smith   Developer Note:
6372a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
6373a1cb98faSBarry Smith 
63746afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6375a4e35b19SJacob Faibussowitsch */
6376ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6377d71ae5a4SJacob Faibussowitsch {
63788ca92349SMatthew G. Knepley   DMLabel      marker;
63798ca92349SMatthew G. Knepley   PetscViewer  viewer;
63808ca92349SMatthew G. Knepley   Vec          coordinates;
63818ca92349SMatthew G. Knepley   PetscSection coordSection;
63828ca92349SMatthew G. Knepley   PetscScalar *coords;
63838ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6384d0812dedSMatthew G. Knepley   PetscInt     cdim, coordSize, v, c, d;
63858ca92349SMatthew G. Knepley   PetscMPIInt  rank;
6386d0812dedSMatthew G. Knepley   int          snum, dim, Nv, Nc, Ncn, Nl;
63878ca92349SMatthew G. Knepley 
63888ca92349SMatthew G. Knepley   PetscFunctionBegin;
63899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
63909566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
63919566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
63929566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
63939566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
6394dd400576SPatrick Sanan   if (rank == 0) {
6395d0812dedSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING));
6396d0812dedSMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl);
6397d0812dedSMatthew G. Knepley     PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
639825ce1634SJed Brown   } else {
6399f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
64008ca92349SMatthew G. Knepley   }
6401d0812dedSMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
6402835f2295SStefano Zampini   cdim = dim;
64039566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
64049566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
64059566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6406835f2295SStefano Zampini   PetscCall(DMSetDimension(*dm, dim));
64079566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
64088ca92349SMatthew G. Knepley   /* Read topology */
6409dd400576SPatrick Sanan   if (rank == 0) {
6410f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
6411f8d5e320SMatthew G. Knepley     PetscInt cone[8];
64128ca92349SMatthew G. Knepley     int      vbuf[8], v;
64138ca92349SMatthew G. Knepley 
64149371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
64159371c9d4SSatish Balay       format[c * 3 + 0] = '%';
64169371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
64179371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
64189371c9d4SSatish Balay     }
6419f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
64209566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
64219566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
64228ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
64239566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
6424f8d5e320SMatthew G. Knepley       switch (Ncn) {
6425d71ae5a4SJacob Faibussowitsch       case 2:
6426d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
6427d71ae5a4SJacob Faibussowitsch         break;
6428d71ae5a4SJacob Faibussowitsch       case 3:
6429d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
6430d71ae5a4SJacob Faibussowitsch         break;
6431d71ae5a4SJacob Faibussowitsch       case 4:
6432d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
6433d71ae5a4SJacob Faibussowitsch         break;
6434d71ae5a4SJacob Faibussowitsch       case 6:
6435d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
6436d71ae5a4SJacob Faibussowitsch         break;
6437d71ae5a4SJacob Faibussowitsch       case 8:
6438d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
6439d71ae5a4SJacob Faibussowitsch         break;
6440d71ae5a4SJacob Faibussowitsch       default:
6441d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
6442f8d5e320SMatthew G. Knepley       }
644308401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6444f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
64458ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
6446f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
64478ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
64488ca92349SMatthew G. Knepley         cone[1]      = cone[3];
64498ca92349SMatthew G. Knepley         cone[3]      = tmp;
64508ca92349SMatthew G. Knepley       }
64519566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
64528ca92349SMatthew G. Knepley     }
64538ca92349SMatthew G. Knepley   }
64549566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
64559566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
64568ca92349SMatthew G. Knepley   /* Read coordinates */
64579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
64589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
64599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
64609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
64618ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
64629566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
64639566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
64648ca92349SMatthew G. Knepley   }
64659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
64669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
64679566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
64689566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
64699566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
64709566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
64719566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
64729566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6473dd400576SPatrick Sanan   if (rank == 0) {
6474f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
64758ca92349SMatthew G. Knepley     double x[3];
6476f8d5e320SMatthew G. Knepley     int    l, val[3];
64778ca92349SMatthew G. Knepley 
6478f8d5e320SMatthew G. Knepley     if (Nl) {
64799371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
64809371c9d4SSatish Balay         format[l * 3 + 0] = '%';
64819371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
64829371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
64839371c9d4SSatish Balay       }
6484f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
64859566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
64869566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
6487f8d5e320SMatthew G. Knepley     }
64888ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
64899566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
6490f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
649108401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6492f8d5e320SMatthew G. Knepley       switch (Nl) {
6493d71ae5a4SJacob Faibussowitsch       case 0:
6494d71ae5a4SJacob Faibussowitsch         snum = 0;
6495d71ae5a4SJacob Faibussowitsch         break;
6496d71ae5a4SJacob Faibussowitsch       case 1:
6497d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
6498d71ae5a4SJacob Faibussowitsch         break;
6499d71ae5a4SJacob Faibussowitsch       case 2:
6500d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
6501d71ae5a4SJacob Faibussowitsch         break;
6502d71ae5a4SJacob Faibussowitsch       case 3:
6503d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
6504d71ae5a4SJacob Faibussowitsch         break;
6505d71ae5a4SJacob Faibussowitsch       default:
6506d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
6507f8d5e320SMatthew G. Knepley       }
650808401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
65098ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
65109566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
65118ca92349SMatthew G. Knepley     }
65128ca92349SMatthew G. Knepley   }
65139566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
65149566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
65159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
65169566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
65178ca92349SMatthew G. Knepley   if (interpolate) {
65188ca92349SMatthew G. Knepley     DM      idm;
65198ca92349SMatthew G. Knepley     DMLabel bdlabel;
65208ca92349SMatthew G. Knepley 
65219566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
65229566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
65238ca92349SMatthew G. Knepley     *dm = idm;
65248ca92349SMatthew G. Knepley 
6525f8d5e320SMatthew G. Knepley     if (!Nl) {
65269566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
65279566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
65289566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
65299566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
65308ca92349SMatthew G. Knepley     }
6531f8d5e320SMatthew G. Knepley   }
65323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65338ca92349SMatthew G. Knepley }
65348ca92349SMatthew G. Knepley 
6535cc4c1da9SBarry Smith /*@
6536a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
6537a1cb98faSBarry Smith 
6538a1cb98faSBarry Smith   Collective
6539ca522641SMatthew G. Knepley 
6540ca522641SMatthew G. Knepley   Input Parameters:
6541ca522641SMatthew G. Knepley + comm        - The communicator
6542ca522641SMatthew G. Knepley . filename    - A file name
6543a1cb98faSBarry Smith . plexname    - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
6544ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
6545ca522641SMatthew G. Knepley 
6546ca522641SMatthew G. Knepley   Output Parameter:
6547a1cb98faSBarry Smith . dm - The `DM`
6548ca522641SMatthew G. Knepley 
6549a1cb98faSBarry Smith   Options Database Key:
6550a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
655102ef0d99SVaclav Hapla 
655237fdd005SBarry Smith   Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g.
6553bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
6554bca97951SVaclav Hapla 
6555ca522641SMatthew G. Knepley   Level: beginner
6556ca522641SMatthew G. Knepley 
6557a1cb98faSBarry Smith   Notes:
6558a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
6559a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
6560a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
6561a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
6562a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
6563a1cb98faSBarry Smith 
65641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
6565ca522641SMatthew G. Knepley @*/
6566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
6567d71ae5a4SJacob Faibussowitsch {
6568ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
6569ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
6570ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
6571ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
6572ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
6573ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
6574ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
6575ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
6576ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
65776f2c871aSStefano Zampini   const char  extXDMFHDF5[]  = ".xdmf.h5";
6578ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
6579*5552b385SBrandon   const char  extEGADSlite[] = ".egadslite";
6580ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
6581ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
6582*5552b385SBrandon   const char  extIGES2[]     = ".iges";
6583ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
6584*5552b385SBrandon   const char  extSTEP2[]     = ".step";
6585*5552b385SBrandon   const char  extBREP[]      = ".brep";
6586ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
6587ca522641SMatthew G. Knepley   size_t      len;
6588*5552b385SBrandon   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5;
6589ca522641SMatthew G. Knepley   PetscMPIInt rank;
6590ca522641SMatthew G. Knepley 
6591ca522641SMatthew G. Knepley   PetscFunctionBegin;
65924f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
65934f572ea9SToby Isaac   if (plexname) PetscAssertPointer(plexname, 3);
65944f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
65959566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
65969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
65979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
65989566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
659928b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
6600ef3a5affSJacob Faibussowitsch 
66019371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
66029371c9d4SSatish Balay   do { \
6603274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
6604274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
6605274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
6606274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
6607ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
6608ef3a5affSJacob Faibussowitsch     } else { \
6609274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
6610ef3a5affSJacob Faibussowitsch     } \
6611ef3a5affSJacob Faibussowitsch   } while (0)
6612ef3a5affSJacob Faibussowitsch 
6613ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
6614ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
6615ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
6616ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
6617ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
6618ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
6619ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
6620ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
6621ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
6622ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
6623*5552b385SBrandon   CheckExtension(extEGADSlite, isEGADSlite);
6624ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
6625ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
6626*5552b385SBrandon   CheckExtension(extIGES2, isIGES2);
6627ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
6628*5552b385SBrandon   CheckExtension(extSTEP2, isSTEP2);
6629*5552b385SBrandon   CheckExtension(extBREP, isBREP);
6630ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
66316f2c871aSStefano Zampini   CheckExtension(extXDMFHDF5, isXDMFHDF5);
6632ef3a5affSJacob Faibussowitsch 
6633ef3a5affSJacob Faibussowitsch #undef CheckExtension
6634ef3a5affSJacob Faibussowitsch 
6635de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
66369566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
6637ca522641SMatthew G. Knepley   } else if (isCGNS) {
66389566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
663990c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
66409566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
66412f0bd6dcSMichael Lange   } else if (isFluent) {
66429566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
6643cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
6644cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
6645cc2f8f65SMatthew G. Knepley 
664643b242b4SVaclav Hapla     /* PETSC_VIEWER_HDF5_XDMF is used if the filename ends with .xdmf.h5, or if -dm_plex_create_from_hdf5_xdmf option is present */
66476f2c871aSStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL));
66489566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
66499566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
66509566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
66519566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
66529566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
66539566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
6654cd7e8a5eSksagiyam 
66559566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
6656f4f49eeaSPierre Jolivet     PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
66579566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
66586f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
66599566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
66606f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer));
66619566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
66625fd9971aSMatthew G. Knepley 
66635fd9971aSMatthew G. Knepley     if (interpolate) {
66645fd9971aSMatthew G. Knepley       DM idm;
66655fd9971aSMatthew G. Knepley 
66669566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
66679566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
66685fd9971aSMatthew G. Knepley       *dm = idm;
66695fd9971aSMatthew G. Knepley     }
6670f2801cd6SMatthew G. Knepley   } else if (isPLY) {
66719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
6672*5552b385SBrandon   } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) {
6673*5552b385SBrandon     PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite));
6674*5552b385SBrandon 
66757bee2925SMatthew Knepley     if (!interpolate) {
66767bee2925SMatthew Knepley       DM udm;
66777bee2925SMatthew Knepley 
66789566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
66799566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
66807bee2925SMatthew Knepley       *dm = udm;
66817bee2925SMatthew Knepley     }
66828ca92349SMatthew G. Knepley   } else if (isCV) {
66839566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
668498921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
66859566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
6686f4f49eeaSPierre Jolivet   if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
66879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
66883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6689ca522641SMatthew G. Knepley }
669012b8a6daSStefano Zampini 
6691cc4c1da9SBarry Smith /*@
66929f6c5813SMatthew G. Knepley   DMPlexCreateEphemeral - This takes a `DMPlexTransform` and a base `DMPlex` and produces an ephemeral `DM`, meaning one that is created on the fly in response to queries.
66939f6c5813SMatthew G. Knepley 
66940528010dSStefano Zampini   Input Parameters:
66950528010dSStefano Zampini + tr     - The `DMPlexTransform`
66960528010dSStefano Zampini - prefix - An options prefix, or NULL
66979f6c5813SMatthew G. Knepley 
66989f6c5813SMatthew G. Knepley   Output Parameter:
66999f6c5813SMatthew G. Knepley . dm - The `DM`
67009f6c5813SMatthew G. Knepley 
67019f6c5813SMatthew G. Knepley   Level: beginner
67029f6c5813SMatthew G. Knepley 
670320f4b53cSBarry Smith   Notes:
670420f4b53cSBarry Smith   An emphemeral mesh is one that is not stored concretely, as in the default `DMPLEX` implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh.
670520f4b53cSBarry Smith 
67069f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
67079f6c5813SMatthew G. Knepley @*/
67080528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm)
67099f6c5813SMatthew G. Knepley {
67100528010dSStefano Zampini   DM           bdm, bcdm, cdm;
67110528010dSStefano Zampini   Vec          coordinates, coordinatesNew;
67120528010dSStefano Zampini   PetscSection cs;
6713817b2c36SMatthew G. Knepley   PetscInt     cdim, Nl;
67149f6c5813SMatthew G. Knepley 
67159f6c5813SMatthew G. Knepley   PetscFunctionBegin;
67169f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
67179f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
67180528010dSStefano Zampini   ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL;
67190528010dSStefano Zampini   // Handle coordinates
67200528010dSStefano Zampini   PetscCall(DMPlexTransformGetDM(tr, &bdm));
6721817b2c36SMatthew G. Knepley   PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm));
6722817b2c36SMatthew G. Knepley   PetscCall(DMGetCoordinateDim(*dm, &cdim));
67230528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(bdm, &bcdm));
67240528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(*dm, &cdm));
67250528010dSStefano Zampini   PetscCall(DMCopyDisc(bcdm, cdm));
67260528010dSStefano Zampini   PetscCall(DMGetLocalSection(cdm, &cs));
67270528010dSStefano Zampini   PetscCall(PetscSectionSetNumFields(cs, 1));
67280528010dSStefano Zampini   PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim));
67290528010dSStefano Zampini   PetscCall(DMGetCoordinatesLocal(bdm, &coordinates));
67300528010dSStefano Zampini   PetscCall(VecDuplicate(coordinates, &coordinatesNew));
67310528010dSStefano Zampini   PetscCall(VecCopy(coordinates, coordinatesNew));
67320528010dSStefano Zampini   PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew));
67330528010dSStefano Zampini   PetscCall(VecDestroy(&coordinatesNew));
67349f6c5813SMatthew G. Knepley 
67359f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
67369f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
67379f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
67380528010dSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
67390528010dSStefano Zampini   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix));
67400528010dSStefano Zampini   PetscCall(DMSetFromOptions(*dm));
67419f6c5813SMatthew G. Knepley 
67429f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
67439f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
67449f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
67459f6c5813SMatthew G. Knepley     const char *lname;
67469f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
67479f6c5813SMatthew G. Knepley 
67489f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
67499f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
67509f6c5813SMatthew G. Knepley     if (isDepth) continue;
67519f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
67529f6c5813SMatthew G. Knepley     if (isCellType) continue;
67539f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
67549f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
67559f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
67569f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
67579f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
67589f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
67599f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
67609f6c5813SMatthew G. Knepley   }
67613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67629f6c5813SMatthew G. Knepley }
6763