xref: /petsc/src/dm/impls/plex/plexcreate.c (revision 5515ebd38caf9dfb24758a1fa7a0ef84b8937157)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h>   /*I   "petscdmplex.h"   I*/
40c312b8eSJed Brown #include <petscsf.h>
54663dae6SJed Brown #include <petscdmplextransform.h>
69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h>
7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
9552f7358SJed Brown 
10b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1158cd63d5SVaclav Hapla 
129318fe57SMatthew G. Knepley /* External function declarations here */
139318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
149318fe57SMatthew G. Knepley 
15e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
17d71ae5a4SJacob Faibussowitsch {
184fb89dddSMatthew G. Knepley   const PetscReal         *maxCell, *Lstart, *L;
196858538eSMatthew G. Knepley   PetscBool                dist;
206bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
21e600fa54SMatthew G. Knepley 
22e600fa54SMatthew G. Knepley   PetscFunctionBegin;
23e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
244fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
254fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
26e600fa54SMatthew G. Knepley   }
279566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
289566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
296bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
306bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
31e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
321baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
33e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
34e600fa54SMatthew G. Knepley }
35e600fa54SMatthew G. Knepley 
369318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
379318fe57SMatthew G. Knepley    - Share the DM_Plex structure
389318fe57SMatthew G. Knepley    - Share the coordinates
399318fe57SMatthew G. Knepley    - Share the SF
409318fe57SMatthew G. Knepley */
41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
42d71ae5a4SJacob Faibussowitsch {
439318fe57SMatthew G. Knepley   PetscSF          sf;
449318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
459318fe57SMatthew G. Knepley   Vec              coords;
464fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
479318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
489318fe57SMatthew G. Knepley 
499318fe57SMatthew G. Knepley   PetscFunctionBegin;
509318fe57SMatthew G. Knepley   if (dm == dmNew) {
519566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
529318fe57SMatthew G. Knepley     PetscFunctionReturn(0);
539318fe57SMatthew G. Knepley   }
549318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
559566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
569566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
589566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
599566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
609566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
629566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
656858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
666858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
676858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
686858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
699318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
706858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
716858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
7261a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
734fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
744fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
759566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
769566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
779318fe57SMatthew G. Knepley   dm->data = dmNew->data;
789318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
799566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
809566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
819566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
829566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
839566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
849318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
859318fe57SMatthew G. Knepley }
869318fe57SMatthew G. Knepley 
879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
889318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
899318fe57SMatthew G. Knepley    - Swap the coordinates
909318fe57SMatthew G. Knepley    - Swap the point PetscSF
919318fe57SMatthew G. Knepley */
92d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
93d71ae5a4SJacob Faibussowitsch {
949318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
959318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
969318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
979318fe57SMatthew G. Knepley   DMField     fieldTmp;
989318fe57SMatthew G. Knepley   void       *tmp;
999318fe57SMatthew G. Knepley   DMLabelLink listTmp;
1009318fe57SMatthew G. Knepley   DMLabel     depthTmp;
1019318fe57SMatthew G. Knepley   PetscInt    tmpI;
1029318fe57SMatthew G. Knepley 
1039318fe57SMatthew G. Knepley   PetscFunctionBegin;
1049318fe57SMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
1059566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
1069566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
1079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
1089566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
1099566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
1109566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
1119318fe57SMatthew G. Knepley 
1129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
1139566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
1149566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
1169566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
1179566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1189318fe57SMatthew G. Knepley 
1199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
1209566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
1219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
1229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
1239566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
1249566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1259318fe57SMatthew G. Knepley 
1266858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
1276858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
1286858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1296858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
1306858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
1316858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1326858538eSMatthew G. Knepley 
1336858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
1346858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
1356858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
1366858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
1376858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
1386858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1396858538eSMatthew G. Knepley 
1406858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
1416858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
1426858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
1436858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
1446858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
1456858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
1469318fe57SMatthew G. Knepley   tmp                       = dmA->data;
1479318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
1489318fe57SMatthew G. Knepley   dmB->data                 = tmp;
1499318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
1509318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
1519318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
1529318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
1539318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
1549318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
1559318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
1569318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
1579318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
1589318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
1599318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
1609318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
1619318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1629318fe57SMatthew G. Knepley }
1639318fe57SMatthew G. Knepley 
164d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
165d71ae5a4SJacob Faibussowitsch {
1669318fe57SMatthew G. Knepley   DM idm;
1679318fe57SMatthew G. Knepley 
1689318fe57SMatthew G. Knepley   PetscFunctionBegin;
1699566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
1709566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
17169d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
1729318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1739318fe57SMatthew G. Knepley }
1749318fe57SMatthew G. Knepley 
1759318fe57SMatthew G. Knepley /*@C
1769318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
1779318fe57SMatthew G. Knepley 
178a1cb98faSBarry Smith   Collective on dm
1799318fe57SMatthew G. Knepley 
1809318fe57SMatthew G. Knepley   Input Parameters:
1819318fe57SMatthew G. Knepley + DM        - The DM
1824f9ab2b4SJed Brown . degree    - The degree of the finite element or PETSC_DECIDE
1839318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
1849318fe57SMatthew G. Knepley 
1859318fe57SMatthew G. Knepley   Level: advanced
1869318fe57SMatthew G. Knepley 
187a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
1889318fe57SMatthew G. Knepley @*/
189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc)
190d71ae5a4SJacob Faibussowitsch {
1919318fe57SMatthew G. Knepley   DM_Plex     *mesh = (DM_Plex *)dm->data;
1929318fe57SMatthew G. Knepley   DM           cdm;
1939318fe57SMatthew G. Knepley   PetscDS      cds;
1949318fe57SMatthew G. Knepley   PetscFE      fe;
1959318fe57SMatthew G. Knepley   PetscClassId id;
1969318fe57SMatthew G. Knepley 
1979318fe57SMatthew G. Knepley   PetscFunctionBegin;
1989566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
1999566063dSJacob Faibussowitsch   PetscCall(DMGetDS(cdm, &cds));
2009566063dSJacob Faibussowitsch   PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe));
2019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
2029318fe57SMatthew G. Knepley   if (id != PETSCFE_CLASSID) {
2039318fe57SMatthew G. Knepley     PetscInt dim, dE, qorder;
2049318fe57SMatthew G. Knepley 
2059566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
2069566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dm, &dE));
2079318fe57SMatthew G. Knepley     qorder = degree;
208d0609cedSBarry Smith     PetscObjectOptionsBegin((PetscObject)cdm);
209dc431b0cSMatthew G. Knepley     PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
210d0609cedSBarry Smith     PetscOptionsEnd();
2114f9ab2b4SJed Brown     if (degree == PETSC_DECIDE) fe = NULL;
2124f9ab2b4SJed Brown     else {
213dc431b0cSMatthew G. Knepley       DMPolytopeType ct;
214dc431b0cSMatthew G. Knepley       PetscInt       cStart, cEnd, ctTmp;
215dc431b0cSMatthew G. Knepley 
216dc431b0cSMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
217dc431b0cSMatthew G. Knepley       // Want to match cell types
218dc431b0cSMatthew G. Knepley       if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
219dc431b0cSMatthew G. Knepley       else ct = DM_POLYTOPE_UNKNOWN;
220dc431b0cSMatthew G. Knepley       ctTmp = (PetscInt)ct;
221dc431b0cSMatthew G. Knepley       PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &ctTmp, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
222dc431b0cSMatthew G. Knepley       ct = (DMPolytopeType)ctTmp;
223dc431b0cSMatthew G. Knepley       // Work around current bug
224dc431b0cSMatthew G. Knepley       if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) fe = NULL;
225dc431b0cSMatthew G. Knepley       else PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
2264f9ab2b4SJed Brown     }
227dc431b0cSMatthew G. Knepley     if (fe) PetscCall(DMProjectCoordinates(dm, fe));
2289566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2299318fe57SMatthew G. Knepley   }
2309318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2319318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
2329318fe57SMatthew G. Knepley }
2339318fe57SMatthew G. Knepley 
2341df5d5c5SMatthew G. Knepley /*@
2351df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2361df5d5c5SMatthew G. Knepley 
237d083f849SBarry Smith   Collective
2381df5d5c5SMatthew G. Knepley 
2391df5d5c5SMatthew G. Knepley   Input Parameters:
240a1cb98faSBarry Smith + comm - The communicator for the `DM` object
2411df5d5c5SMatthew G. Knepley . dim - The spatial dimension
2421df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells
2431df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces)
2441df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2451df5d5c5SMatthew G. Knepley 
2461df5d5c5SMatthew G. Knepley   Output Parameter:
247a1cb98faSBarry Smith . dm - The `DM` object
2481df5d5c5SMatthew G. Knepley 
2491df5d5c5SMatthew G. Knepley   Level: beginner
2501df5d5c5SMatthew G. Knepley 
251a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
2521df5d5c5SMatthew G. Knepley @*/
253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
254d71ae5a4SJacob Faibussowitsch {
2551df5d5c5SMatthew G. Knepley   DM          dm;
2561df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
2571df5d5c5SMatthew G. Knepley 
2581df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
2599566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
2609566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
2619566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2629566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
263ce78fa2fSMatthew G. Knepley   switch (dim) {
264ce78fa2fSMatthew G. Knepley   case 2:
2659566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
2669566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
267ce78fa2fSMatthew G. Knepley     break;
268ce78fa2fSMatthew G. Knepley   case 3:
2699566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
2709566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
271ce78fa2fSMatthew G. Knepley     break;
272d71ae5a4SJacob Faibussowitsch   default:
273d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
274ce78fa2fSMatthew G. Knepley   }
2751df5d5c5SMatthew G. Knepley   if (rank) {
2761df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
2779566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
2781df5d5c5SMatthew G. Knepley   } else {
2791df5d5c5SMatthew G. Knepley     switch (dim) {
2801df5d5c5SMatthew G. Knepley     case 2:
2811df5d5c5SMatthew G. Knepley       if (simplex) {
2821df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
2831df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
2841df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
2851df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
2861df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
2871df5d5c5SMatthew G. Knepley 
2889566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2891df5d5c5SMatthew G. Knepley       } else {
2901df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
2911df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
2921df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
2931df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2941df5d5c5SMatthew 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};
2951df5d5c5SMatthew G. Knepley 
2969566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2971df5d5c5SMatthew G. Knepley       }
2981df5d5c5SMatthew G. Knepley       break;
2991df5d5c5SMatthew G. Knepley     case 3:
3001df5d5c5SMatthew G. Knepley       if (simplex) {
3011df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
3021df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
3031df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
3041df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3051df5d5c5SMatthew 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};
3061df5d5c5SMatthew G. Knepley 
3079566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3081df5d5c5SMatthew G. Knepley       } else {
3091df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
3101df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3111df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
3121df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3139371c9d4SSatish 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};
3141df5d5c5SMatthew G. Knepley 
3159566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3161df5d5c5SMatthew G. Knepley       }
3171df5d5c5SMatthew G. Knepley       break;
318d71ae5a4SJacob Faibussowitsch     default:
319d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
3201df5d5c5SMatthew G. Knepley     }
3211df5d5c5SMatthew G. Knepley   }
3221df5d5c5SMatthew G. Knepley   *newdm = dm;
3231df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
3241df5d5c5SMatthew G. Knepley     DM          rdm;
3251df5d5c5SMatthew G. Knepley     const char *name;
3261df5d5c5SMatthew G. Knepley 
3279566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
3289566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
3299566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
3309566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
3319566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
3329566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3331df5d5c5SMatthew G. Knepley     *newdm = rdm;
3341df5d5c5SMatthew G. Knepley   }
3351df5d5c5SMatthew G. Knepley   if (interpolate) {
3365fd9971aSMatthew G. Knepley     DM idm;
3371df5d5c5SMatthew G. Knepley 
3389566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
3399566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3401df5d5c5SMatthew G. Knepley     *newdm = idm;
3411df5d5c5SMatthew G. Knepley   }
3421df5d5c5SMatthew G. Knepley   PetscFunctionReturn(0);
3431df5d5c5SMatthew G. Knepley }
3441df5d5c5SMatthew G. Knepley 
345d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
346d71ae5a4SJacob Faibussowitsch {
3479318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3489318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3499318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3509318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3519318fe57SMatthew G. Knepley   Vec            coordinates;
3529318fe57SMatthew G. Knepley   PetscSection   coordSection;
3539318fe57SMatthew G. Knepley   PetscScalar   *coords;
3549318fe57SMatthew G. Knepley   PetscInt       coordSize;
3559318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3569318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
357552f7358SJed Brown 
3589318fe57SMatthew G. Knepley   PetscFunctionBegin;
3599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3609318fe57SMatthew G. Knepley   if (markerSeparate) {
3619318fe57SMatthew G. Knepley     markerRight = 2;
3629318fe57SMatthew G. Knepley     markerLeft  = 1;
3639318fe57SMatthew G. Knepley   }
3649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
365c5853193SPierre Jolivet   if (rank == 0) {
3669566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
3679566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3689566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
3699566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
3709318fe57SMatthew G. Knepley   }
3719566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
3729566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
3739318fe57SMatthew G. Knepley   /* Build coordinates */
3749566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
3759566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
3769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
3779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
3789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
3799318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
3809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
3819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
3829318fe57SMatthew G. Knepley   }
3839566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
3849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
3859566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
3869566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
3879566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
3889566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
3899566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
3909566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
3919318fe57SMatthew G. Knepley   coords[0] = lower[0];
3929318fe57SMatthew G. Knepley   coords[1] = upper[0];
3939566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
3949566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
3959566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
3969318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
3979318fe57SMatthew G. Knepley }
39826492d91SMatthew G. Knepley 
399d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
400d71ae5a4SJacob Faibussowitsch {
4011df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
4021df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
403552f7358SJed Brown   PetscInt       markerTop      = 1;
404552f7358SJed Brown   PetscInt       markerBottom   = 1;
405552f7358SJed Brown   PetscInt       markerRight    = 1;
406552f7358SJed Brown   PetscInt       markerLeft     = 1;
407552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
408552f7358SJed Brown   Vec            coordinates;
409552f7358SJed Brown   PetscSection   coordSection;
410552f7358SJed Brown   PetscScalar   *coords;
411552f7358SJed Brown   PetscInt       coordSize;
412552f7358SJed Brown   PetscMPIInt    rank;
413552f7358SJed Brown   PetscInt       v, vx, vy;
414552f7358SJed Brown 
415552f7358SJed Brown   PetscFunctionBegin;
4169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
417552f7358SJed Brown   if (markerSeparate) {
4181df21d24SMatthew G. Knepley     markerTop    = 3;
4191df21d24SMatthew G. Knepley     markerBottom = 1;
4201df21d24SMatthew G. Knepley     markerRight  = 2;
4211df21d24SMatthew G. Knepley     markerLeft   = 4;
422552f7358SJed Brown   }
4239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
424dd400576SPatrick Sanan   if (rank == 0) {
425552f7358SJed Brown     PetscInt e, ex, ey;
426552f7358SJed Brown 
4279566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
42848a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
4299566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
430552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
431552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
432552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
433552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
434da80777bSKarl Rupp         PetscInt cone[2];
435552f7358SJed Brown 
4369371c9d4SSatish Balay         cone[0] = vertex;
4379371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
4389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
439552f7358SJed Brown         if (vx == edges[0]) {
4409566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
4419566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
442552f7358SJed Brown           if (ey == edges[1] - 1) {
4439566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
4449566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
445552f7358SJed Brown           }
446552f7358SJed Brown         } else if (vx == 0) {
4479566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
4489566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
449552f7358SJed Brown           if (ey == edges[1] - 1) {
4509566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
4519566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
452552f7358SJed Brown           }
453552f7358SJed Brown         }
454552f7358SJed Brown       }
455552f7358SJed Brown     }
456552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
457552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
458552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
459552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
460da80777bSKarl Rupp         PetscInt cone[2];
461552f7358SJed Brown 
4629371c9d4SSatish Balay         cone[0] = vertex;
4639371c9d4SSatish Balay         cone[1] = vertex + 1;
4649566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
465552f7358SJed Brown         if (vy == edges[1]) {
4669566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
4679566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
468552f7358SJed Brown           if (ex == edges[0] - 1) {
4699566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
4709566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
471552f7358SJed Brown           }
472552f7358SJed Brown         } else if (vy == 0) {
4739566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
4749566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
475552f7358SJed Brown           if (ex == edges[0] - 1) {
4769566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
4779566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
478552f7358SJed Brown           }
479552f7358SJed Brown         }
480552f7358SJed Brown       }
481552f7358SJed Brown     }
482552f7358SJed Brown   }
4839566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4849566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
485552f7358SJed Brown   /* Build coordinates */
4869566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
4879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4889566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4899566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
4909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
491552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
4929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
4939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
494552f7358SJed Brown   }
4959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4979566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4989566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4999566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
5009566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
5019566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
5029566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
503552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
504552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
505552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
506552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
507552f7358SJed Brown     }
508552f7358SJed Brown   }
5099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
5109566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
512552f7358SJed Brown   PetscFunctionReturn(0);
513552f7358SJed Brown }
514552f7358SJed Brown 
515d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
516d71ae5a4SJacob Faibussowitsch {
5179e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
5187b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
519c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
520c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
521c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
522c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
523c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
524c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
525c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
526552f7358SJed Brown   Vec          coordinates;
527552f7358SJed Brown   PetscSection coordSection;
528552f7358SJed Brown   PetscScalar *coords;
529552f7358SJed Brown   PetscInt     coordSize;
530552f7358SJed Brown   PetscMPIInt  rank;
531552f7358SJed Brown   PetscInt     v, vx, vy, vz;
5327b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
533552f7358SJed Brown 
534552f7358SJed Brown   PetscFunctionBegin;
5351dca8a05SBarry 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");
5369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
537c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
538c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
539c2df9bbfSMatthew G. Knepley     markerBottom = 1;
540c2df9bbfSMatthew G. Knepley     markerTop    = 2;
541c2df9bbfSMatthew G. Knepley     markerFront  = 3;
542c2df9bbfSMatthew G. Knepley     markerBack   = 4;
543c2df9bbfSMatthew G. Knepley     markerRight  = 5;
544c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
545c2df9bbfSMatthew G. Knepley   }
5469371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
5479371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
5489371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
5499e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
550dd400576SPatrick Sanan   if (rank == 0) {
551552f7358SJed Brown     PetscInt f;
552552f7358SJed Brown 
5539566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
55448a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
5559566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5567b59f5a9SMichael Lange 
5577b59f5a9SMichael Lange     /* Side 0 (Top) */
5587b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5597b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5607b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
5619371c9d4SSatish Balay         cone[0] = voffset;
5629371c9d4SSatish Balay         cone[1] = voffset + 1;
5639371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
5649371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
5659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
566c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
567c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
568c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
569c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
570c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
5717b59f5a9SMichael Lange         iface++;
572552f7358SJed Brown       }
573552f7358SJed Brown     }
5747b59f5a9SMichael Lange 
5757b59f5a9SMichael Lange     /* Side 1 (Bottom) */
5767b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5777b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5787b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
5799371c9d4SSatish Balay         cone[0] = voffset + 1;
5809371c9d4SSatish Balay         cone[1] = voffset;
5819371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
5829371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
5839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
584c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
585c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
586c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
587c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
588c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
5897b59f5a9SMichael Lange         iface++;
590552f7358SJed Brown       }
591552f7358SJed Brown     }
5927b59f5a9SMichael Lange 
5937b59f5a9SMichael Lange     /* Side 2 (Front) */
5947b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5957b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5967b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
5979371c9d4SSatish Balay         cone[0] = voffset;
5989371c9d4SSatish Balay         cone[1] = voffset + 1;
5999371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
6009371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
6019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
602c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
603c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
604c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
605c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
606c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
6077b59f5a9SMichael Lange         iface++;
608552f7358SJed Brown       }
6097b59f5a9SMichael Lange     }
6107b59f5a9SMichael Lange 
6117b59f5a9SMichael Lange     /* Side 3 (Back) */
6127b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6137b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6147b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
6159371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6169371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
6179371c9d4SSatish Balay         cone[2] = voffset + 1;
6189371c9d4SSatish Balay         cone[3] = voffset;
6199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
620c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
621c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
622c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
623c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
624c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
6257b59f5a9SMichael Lange         iface++;
6267b59f5a9SMichael Lange       }
6277b59f5a9SMichael Lange     }
6287b59f5a9SMichael Lange 
6297b59f5a9SMichael Lange     /* Side 4 (Left) */
6307b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6317b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
6327b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
6339371c9d4SSatish Balay         cone[0] = voffset;
6349371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
6359371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
6369371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
638c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
639c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
640c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
641c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
642c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
6437b59f5a9SMichael Lange         iface++;
6447b59f5a9SMichael Lange       }
6457b59f5a9SMichael Lange     }
6467b59f5a9SMichael Lange 
6477b59f5a9SMichael Lange     /* Side 5 (Right) */
6487b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6497b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
650aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
6519371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6529371c9d4SSatish Balay         cone[1] = voffset;
6539371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6549371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
6559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
656c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
657c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
658c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
659c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
660c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
6617b59f5a9SMichael Lange         iface++;
6627b59f5a9SMichael Lange       }
663552f7358SJed Brown     }
664552f7358SJed Brown   }
6659566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6669566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
667552f7358SJed Brown   /* Build coordinates */
6689566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
6699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6709566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
6729566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
673552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
6749566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
6759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
676552f7358SJed Brown   }
6779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6799566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6819566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6829566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
6839566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6849566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
685552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
686552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
687552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
688552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
689552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
690552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
691552f7358SJed Brown       }
692552f7358SJed Brown     }
693552f7358SJed Brown   }
6949566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6959566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6969566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
697552f7358SJed Brown   PetscFunctionReturn(0);
698552f7358SJed Brown }
699552f7358SJed Brown 
700d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
701d71ae5a4SJacob Faibussowitsch {
7029318fe57SMatthew G. Knepley   PetscFunctionBegin;
7039318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
7049566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
7059566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
7069318fe57SMatthew G. Knepley   switch (dim) {
707d71ae5a4SJacob Faibussowitsch   case 1:
708d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
709d71ae5a4SJacob Faibussowitsch     break;
710d71ae5a4SJacob Faibussowitsch   case 2:
711d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
712d71ae5a4SJacob Faibussowitsch     break;
713d71ae5a4SJacob Faibussowitsch   case 3:
714d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
715d71ae5a4SJacob Faibussowitsch     break;
716d71ae5a4SJacob Faibussowitsch   default:
717d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
7189318fe57SMatthew G. Knepley   }
7199566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
7209318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7219318fe57SMatthew G. Knepley }
7229318fe57SMatthew G. Knepley 
7239318fe57SMatthew G. Knepley /*@C
7249318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
7259318fe57SMatthew G. Knepley 
7269318fe57SMatthew G. Knepley   Collective
7279318fe57SMatthew G. Knepley 
7289318fe57SMatthew G. Knepley   Input Parameters:
729a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
7309318fe57SMatthew G. Knepley . dim         - The spatial dimension of the box, so the resulting mesh is has dimension dim-1
7319318fe57SMatthew G. Knepley . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
7329318fe57SMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
7339318fe57SMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
7349318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7359318fe57SMatthew G. Knepley 
7369318fe57SMatthew G. Knepley   Output Parameter:
737a1cb98faSBarry Smith . dm  - The `DM` object
7389318fe57SMatthew G. Knepley 
7399318fe57SMatthew G. Knepley   Level: beginner
7409318fe57SMatthew G. Knepley 
741a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
7429318fe57SMatthew G. Knepley @*/
743d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
744d71ae5a4SJacob Faibussowitsch {
7459318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
7469318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
7479318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
7489318fe57SMatthew G. Knepley 
7499318fe57SMatthew G. Knepley   PetscFunctionBegin;
7509566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
7519566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
7529566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
7539318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7549318fe57SMatthew G. Knepley }
7559318fe57SMatthew G. Knepley 
756d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
757d71ae5a4SJacob Faibussowitsch {
758fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
759fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
760fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
761fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
762fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
763fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
764fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
765fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
766fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
767fdbf62faSLisandro Dalcin 
768fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7699318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
770fdbf62faSLisandro Dalcin 
7719566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
7729566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
7739566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
774fdbf62faSLisandro Dalcin 
7759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
776dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
777dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
778fdbf62faSLisandro Dalcin 
7799371c9d4SSatish Balay   numPoints[0] = numVerts;
7809371c9d4SSatish Balay   numPoints[1] = numCells;
7819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
7829566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
783ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
784ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
7859371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
7869371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
7879371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
7889371c9d4SSatish Balay   }
789ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
7909566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
7919566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
792fdbf62faSLisandro Dalcin 
7939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
7949371c9d4SSatish Balay   if (markerSeparate) {
7959371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
7969371c9d4SSatish Balay     markerRight = faceMarkerRight;
7979371c9d4SSatish Balay   }
798dd400576SPatrick Sanan   if (!wrap && rank == 0) {
7999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
8009566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
8019566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
8029566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
8039566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
804fdbf62faSLisandro Dalcin   }
805fdbf62faSLisandro Dalcin   if (wrap) {
806fdbf62faSLisandro Dalcin     L       = upper - lower;
807fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
8084fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
809fdbf62faSLisandro Dalcin   }
8109566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
811fdbf62faSLisandro Dalcin   PetscFunctionReturn(0);
812fdbf62faSLisandro Dalcin }
813fdbf62faSLisandro Dalcin 
814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
815d71ae5a4SJacob Faibussowitsch {
8169318fe57SMatthew G. Knepley   DM      boundary, vol;
817c22d3578SMatthew G. Knepley   DMLabel bdlabel;
818d6218766SMatthew G. Knepley 
819d6218766SMatthew G. Knepley   PetscFunctionBegin;
8209318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
821c22d3578SMatthew 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");
8229566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
8239566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
8249566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
8259566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
826c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
827c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
8285de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
82969d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
8309566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
831d6218766SMatthew G. Knepley   PetscFunctionReturn(0);
832d6218766SMatthew G. Knepley }
833d6218766SMatthew G. Knepley 
834d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
835d71ae5a4SJacob Faibussowitsch {
836ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
837f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
838f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
839f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
840f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
841f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
842f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
8433dfda0b1SToby Isaac   PetscInt    dim;
844d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
8453dfda0b1SToby Isaac   PetscMPIInt rank;
8463dfda0b1SToby Isaac 
8473dfda0b1SToby Isaac   PetscFunctionBegin;
8489566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8499566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8509566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8519566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
8529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
8539371c9d4SSatish 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) {
8549371c9d4SSatish Balay     if (cutMarker) {
8559371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
8569371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
8579371c9d4SSatish Balay     }
858d8211ee3SMatthew G. Knepley   }
8593dfda0b1SToby Isaac   switch (dim) {
8603dfda0b1SToby Isaac   case 2:
861f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
862f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
863f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
864f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
8653dfda0b1SToby Isaac     break;
8663dfda0b1SToby Isaac   case 3:
867f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
868f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
869f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
870f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
871f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
872f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
8733dfda0b1SToby Isaac     break;
874d71ae5a4SJacob Faibussowitsch   default:
875d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
8763dfda0b1SToby Isaac   }
8779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
878f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
879f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
880f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
881f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
882f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
883f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
884f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
8853dfda0b1SToby Isaac   }
8863dfda0b1SToby Isaac   {
887dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
888dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
889dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
890dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
891dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
892dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
8933dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
8943dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
8953dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
8963dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
8973dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
8983dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
8993dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
9003dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
9013dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
9023dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
9033dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
9043dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
9053dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
9063dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
9073dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
9083dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
9093dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
9103dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
9113dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
9123dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
9133dfda0b1SToby Isaac     Vec            coordinates;
9143dfda0b1SToby Isaac     PetscSection   coordSection;
9153dfda0b1SToby Isaac     PetscScalar   *coords;
9163dfda0b1SToby Isaac     PetscInt       coordSize;
9173dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
9183dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
9193dfda0b1SToby Isaac 
9209566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
92148a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
92248a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
92348a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
9249566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
9253dfda0b1SToby Isaac     /* Build cells */
9263dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9273dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9283dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
9293dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
9303dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
9313dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
9323dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9333dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
9343dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9353dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
9363dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
937b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
93842206facSLisandro Dalcin           PetscInt cone[6];
9393dfda0b1SToby Isaac 
9403dfda0b1SToby Isaac           /* no boundary twisting in 3D */
9419371c9d4SSatish Balay           cone[0] = faceB;
9429371c9d4SSatish Balay           cone[1] = faceT;
9439371c9d4SSatish Balay           cone[2] = faceF;
9449371c9d4SSatish Balay           cone[3] = faceK;
9459371c9d4SSatish Balay           cone[4] = faceR;
9469371c9d4SSatish Balay           cone[5] = faceL;
9479566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
9489566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
9499566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9509566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9519566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9523dfda0b1SToby Isaac         }
9533dfda0b1SToby Isaac       }
9543dfda0b1SToby Isaac     }
9553dfda0b1SToby Isaac     /* Build x faces */
9563dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9573dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9583dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
9593dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9603dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9613dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
9623dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
9633dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
964b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9653dfda0b1SToby Isaac           PetscInt cone[4];
9663dfda0b1SToby Isaac 
9673dfda0b1SToby Isaac           if (dim == 3) {
9683dfda0b1SToby Isaac             /* markers */
9693dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
9703dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
9719566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
9729566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
9739371c9d4SSatish Balay               } else if (fx == 0) {
9749566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
9759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
9763dfda0b1SToby Isaac               }
9773dfda0b1SToby Isaac             }
9783dfda0b1SToby Isaac           }
9799371c9d4SSatish Balay           cone[0] = edgeB;
9809371c9d4SSatish Balay           cone[1] = edgeR;
9819371c9d4SSatish Balay           cone[2] = edgeT;
9829371c9d4SSatish Balay           cone[3] = edgeL;
9839566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
9849566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
9853dfda0b1SToby Isaac         }
9863dfda0b1SToby Isaac       }
9873dfda0b1SToby Isaac     }
9883dfda0b1SToby Isaac     /* Build y faces */
9893dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
99042206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
9913dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
9923dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9933dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9943dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
9953dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
9963dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
997b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9983dfda0b1SToby Isaac           PetscInt cone[4];
9993dfda0b1SToby Isaac 
10003dfda0b1SToby Isaac           if (dim == 3) {
10013dfda0b1SToby Isaac             /* markers */
10023dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
10033dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
10049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
10059566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
10069371c9d4SSatish Balay               } else if (fy == 0) {
10079566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
10089566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
10093dfda0b1SToby Isaac               }
10103dfda0b1SToby Isaac             }
10113dfda0b1SToby Isaac           }
10129371c9d4SSatish Balay           cone[0] = edgeB;
10139371c9d4SSatish Balay           cone[1] = edgeR;
10149371c9d4SSatish Balay           cone[2] = edgeT;
10159371c9d4SSatish Balay           cone[3] = edgeL;
10169566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10179566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10183dfda0b1SToby Isaac         }
10193dfda0b1SToby Isaac       }
10203dfda0b1SToby Isaac     }
10213dfda0b1SToby Isaac     /* Build z faces */
10223dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
10233dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
10243dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
10253dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
10263dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
10273dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
10283dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
10293dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1030b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
10313dfda0b1SToby Isaac           PetscInt cone[4];
10323dfda0b1SToby Isaac 
10333dfda0b1SToby Isaac           if (dim == 2) {
10349371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
10359371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
10369371c9d4SSatish Balay               ornt[1] = -1;
10379371c9d4SSatish Balay             }
10389371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
10399371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
10409371c9d4SSatish Balay               ornt[2] = 0;
10419371c9d4SSatish Balay             }
10429566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
10439566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1044d1c88043SMatthew G. Knepley           } else {
10453dfda0b1SToby Isaac             /* markers */
10463dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
10473dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
10489566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
10499566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
10509371c9d4SSatish Balay               } else if (fz == 0) {
10519566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
10529566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
10533dfda0b1SToby Isaac               }
10543dfda0b1SToby Isaac             }
10553dfda0b1SToby Isaac           }
10569371c9d4SSatish Balay           cone[0] = edgeB;
10579371c9d4SSatish Balay           cone[1] = edgeR;
10589371c9d4SSatish Balay           cone[2] = edgeT;
10599371c9d4SSatish Balay           cone[3] = edgeL;
10609566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10619566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10623dfda0b1SToby Isaac         }
10633dfda0b1SToby Isaac       }
10643dfda0b1SToby Isaac     }
10653dfda0b1SToby Isaac     /* Build Z edges*/
10663dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
10673dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10683dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
10693dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
10703dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
10713dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
10723dfda0b1SToby Isaac           PetscInt       cone[2];
10733dfda0b1SToby Isaac 
10749371c9d4SSatish Balay           cone[0] = vertexB;
10759371c9d4SSatish Balay           cone[1] = vertexT;
1076c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
10773dfda0b1SToby Isaac           if (dim == 3) {
10783dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
10793dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
10809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1081c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1082c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1083c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
10849566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1085c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1086c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10873dfda0b1SToby Isaac               }
10883dfda0b1SToby Isaac             }
10893dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
10903dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
10919566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1092c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1093c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1094c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
10959566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1096c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1097c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
10983dfda0b1SToby Isaac               }
10993dfda0b1SToby Isaac             }
11003dfda0b1SToby Isaac           }
11013dfda0b1SToby Isaac         }
11023dfda0b1SToby Isaac       }
11033dfda0b1SToby Isaac     }
11043dfda0b1SToby Isaac     /* Build Y edges*/
11053dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
11063dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
11073dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
11083dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
11093dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
11103dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
11113dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
11123dfda0b1SToby Isaac           PetscInt       cone[2];
11133dfda0b1SToby Isaac 
11149371c9d4SSatish Balay           cone[0] = vertexF;
11159371c9d4SSatish Balay           cone[1] = vertexK;
11169566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11173dfda0b1SToby Isaac           if (dim == 2) {
11183dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
11193dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11209566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
11219566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
11229566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1123c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1124d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11259566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
11269566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
11279566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1128c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11293dfda0b1SToby Isaac               }
1130d8211ee3SMatthew G. Knepley             } else {
11314c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
11329566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11339566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1134c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11353dfda0b1SToby Isaac               }
1136d8211ee3SMatthew G. Knepley             }
1137d8211ee3SMatthew G. Knepley           } else {
11383dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
11393dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1141c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1142c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1143d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11449566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1145c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1146c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11473dfda0b1SToby Isaac               }
11483dfda0b1SToby Isaac             }
11493dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11503dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
11519566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1152c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1153c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1154d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
11559566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1156c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1157c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11583dfda0b1SToby Isaac               }
11593dfda0b1SToby Isaac             }
11603dfda0b1SToby Isaac           }
11613dfda0b1SToby Isaac         }
11623dfda0b1SToby Isaac       }
11633dfda0b1SToby Isaac     }
11643dfda0b1SToby Isaac     /* Build X edges*/
11653dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
11663dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
11673dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
11683dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
11693dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
11703dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
11713dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
11723dfda0b1SToby Isaac           PetscInt       cone[2];
11733dfda0b1SToby Isaac 
11749371c9d4SSatish Balay           cone[0] = vertexL;
11759371c9d4SSatish Balay           cone[1] = vertexR;
11769566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11773dfda0b1SToby Isaac           if (dim == 2) {
11783dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
11793dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
11819566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
11829566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1183c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1184d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
11859566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
11869566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
11879566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1188c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11893dfda0b1SToby Isaac               }
1190d8211ee3SMatthew G. Knepley             } else {
11914c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
11929566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11939566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1194c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11953dfda0b1SToby Isaac               }
1196d8211ee3SMatthew G. Knepley             }
1197d8211ee3SMatthew G. Knepley           } else {
11983dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11993dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
12009566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1201c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1202c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1203c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
12049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1205c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1206c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
12073dfda0b1SToby Isaac               }
12083dfda0b1SToby Isaac             }
12093dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
12103dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
12119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1212c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1213c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1214c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
12159566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1216c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1217c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
12183dfda0b1SToby Isaac               }
12193dfda0b1SToby Isaac             }
12203dfda0b1SToby Isaac           }
12213dfda0b1SToby Isaac         }
12223dfda0b1SToby Isaac       }
12233dfda0b1SToby Isaac     }
12249566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
12259566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
12263dfda0b1SToby Isaac     /* Build coordinates */
12279566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
12289566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
12299566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
12309566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
12313dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
12329566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
12339566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
12343dfda0b1SToby Isaac     }
12359566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
12369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
12379566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
12389566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
12399566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
12409566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
12419566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
12429566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
12433dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
12443dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
12453dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
12463dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
12473dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1248ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
12493dfda0b1SToby Isaac         }
12503dfda0b1SToby Isaac       }
12513dfda0b1SToby Isaac     }
12529566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12539566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
12549566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
12553dfda0b1SToby Isaac   }
12563dfda0b1SToby Isaac   PetscFunctionReturn(0);
12573dfda0b1SToby Isaac }
12583dfda0b1SToby Isaac 
1259d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1260d71ae5a4SJacob Faibussowitsch {
12619318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
12629318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1263552f7358SJed Brown 
1264552f7358SJed Brown   PetscFunctionBegin;
12659318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
12669318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
12679566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
12689371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
12699371c9d4SSatish Balay     fac[d] = faces[d];
12709371c9d4SSatish Balay     bdt[d] = periodicity[d];
12719371c9d4SSatish Balay   }
12729566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
12739371c9d4SSatish 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))) {
12746858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
12756858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1276552f7358SJed Brown 
12779318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
12786858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
12799318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
12809318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1281768d5fceSMatthew G. Knepley       }
12826858538eSMatthew G. Knepley     }
12834fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1284768d5fceSMatthew G. Knepley   }
12859566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
12869318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
12879318fe57SMatthew G. Knepley }
12889318fe57SMatthew G. Knepley 
1289d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1290d71ae5a4SJacob Faibussowitsch {
12919318fe57SMatthew G. Knepley   PetscFunctionBegin;
12929566063dSJacob Faibussowitsch   if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
12939566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
12949566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
12959318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1296768d5fceSMatthew G. Knepley     DM udm;
1297768d5fceSMatthew G. Knepley 
12989566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
12999566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
130069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1301768d5fceSMatthew G. Knepley   }
1302768d5fceSMatthew G. Knepley   PetscFunctionReturn(0);
1303c8c68bd8SToby Isaac }
1304c8c68bd8SToby Isaac 
1305768d5fceSMatthew G. Knepley /*@C
1306768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1307768d5fceSMatthew G. Knepley 
1308d083f849SBarry Smith   Collective
1309768d5fceSMatthew G. Knepley 
1310768d5fceSMatthew G. Knepley   Input Parameters:
1311a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
1312768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1313a1cb98faSBarry Smith . simplex     - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
1314fdbf62faSLisandro Dalcin . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
1315768d5fceSMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
1316768d5fceSMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
1317a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE`
1318768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
1319768d5fceSMatthew G. Knepley 
1320768d5fceSMatthew G. Knepley   Output Parameter:
1321a1cb98faSBarry Smith . dm  - The `DM` object
1322768d5fceSMatthew G. Knepley 
1323768d5fceSMatthew G. Knepley   Level: beginner
1324768d5fceSMatthew G. Knepley 
1325a1cb98faSBarry Smith   Note:
1326a1cb98faSBarry Smith    To customize this mesh using options, use
1327a1cb98faSBarry Smith .vb
1328a1cb98faSBarry Smith   DMCreate(comm, &dm);
1329a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1330a1cb98faSBarry Smith   DMSetFromOptions(dm);
1331a1cb98faSBarry Smith .ve
1332a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`.
1333a1cb98faSBarry Smith 
1334a1cb98faSBarry Smith   Here is the numbering returned for 2 faces in each direction for tensor cells:
1335a1cb98faSBarry Smith .vb
1336a1cb98faSBarry Smith  10---17---11---18----12
1337a1cb98faSBarry Smith   |         |         |
1338a1cb98faSBarry Smith   |         |         |
1339a1cb98faSBarry Smith  20    2   22    3    24
1340a1cb98faSBarry Smith   |         |         |
1341a1cb98faSBarry Smith   |         |         |
1342a1cb98faSBarry Smith   7---15----8---16----9
1343a1cb98faSBarry Smith   |         |         |
1344a1cb98faSBarry Smith   |         |         |
1345a1cb98faSBarry Smith  19    0   21    1   23
1346a1cb98faSBarry Smith   |         |         |
1347a1cb98faSBarry Smith   |         |         |
1348a1cb98faSBarry Smith   4---13----5---14----6
1349a1cb98faSBarry Smith .ve
1350a1cb98faSBarry Smith and for simplicial cells
1351a1cb98faSBarry Smith .vb
1352a1cb98faSBarry Smith  14----8---15----9----16
1353a1cb98faSBarry Smith   |\     5  |\      7 |
1354a1cb98faSBarry Smith   | \       | \       |
1355a1cb98faSBarry Smith  13   2    14    3    15
1356a1cb98faSBarry Smith   | 4   \   | 6   \   |
1357a1cb98faSBarry Smith   |       \ |       \ |
1358a1cb98faSBarry Smith  11----6---12----7----13
1359a1cb98faSBarry Smith   |\        |\        |
1360a1cb98faSBarry Smith   | \    1  | \     3 |
1361a1cb98faSBarry Smith  10   0    11    1    12
1362a1cb98faSBarry Smith   | 0   \   | 2   \   |
1363a1cb98faSBarry Smith   |       \ |       \ |
1364a1cb98faSBarry Smith   8----4----9----5----10
1365a1cb98faSBarry Smith .ve
1366a1cb98faSBarry Smith 
1367a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1368768d5fceSMatthew G. Knepley @*/
1369d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm)
1370d71ae5a4SJacob Faibussowitsch {
13719318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1372fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1373fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1374fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1375552f7358SJed Brown 
1376768d5fceSMatthew G. Knepley   PetscFunctionBegin;
13779566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
13789566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
13799566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
13807ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
13819318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
13829318fe57SMatthew G. Knepley }
1383fdbf62faSLisandro Dalcin 
1384d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1385d71ae5a4SJacob Faibussowitsch {
13869318fe57SMatthew G. Knepley   DM       bdm, vol;
13879318fe57SMatthew G. Knepley   PetscInt i;
13889318fe57SMatthew G. Knepley 
13899318fe57SMatthew G. Knepley   PetscFunctionBegin;
139008401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
13919566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
13929566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
13939566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
13949566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
13959566063dSJacob Faibussowitsch   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
13969566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
139769d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
13989318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
13999318fe57SMatthew G. Knepley     Vec          v;
14009318fe57SMatthew G. Knepley     PetscScalar *x;
14019318fe57SMatthew G. Knepley     PetscInt     cDim, n;
14029318fe57SMatthew G. Knepley 
14039566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
14049566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
14059566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
14069566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
14079318fe57SMatthew G. Knepley     x += cDim;
14089318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
14099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
14109566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
14119318fe57SMatthew G. Knepley   }
1412552f7358SJed Brown   PetscFunctionReturn(0);
1413552f7358SJed Brown }
1414552f7358SJed Brown 
141500dabe28SStefano Zampini /*@
141600dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
141700dabe28SStefano Zampini 
1418d083f849SBarry Smith   Collective
141900dabe28SStefano Zampini 
142000dabe28SStefano Zampini   Input Parameters:
1421a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
142200dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
142300dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
142400dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
1425a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE`
1426a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
142700dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
142800dabe28SStefano Zampini 
142900dabe28SStefano Zampini   Output Parameter:
1430a1cb98faSBarry Smith . dm  - The `DM` object
143100dabe28SStefano Zampini 
143200dabe28SStefano Zampini   Level: beginner
143300dabe28SStefano Zampini 
1434a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
143500dabe28SStefano Zampini @*/
1436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1437d71ae5a4SJacob Faibussowitsch {
14389318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
143900dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
144000dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
144100dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
144200dabe28SStefano Zampini 
144300dabe28SStefano Zampini   PetscFunctionBegin;
14449566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14459566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14469566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1447d410b0cfSMatthew G. Knepley   if (!interpolate) {
1448d410b0cfSMatthew G. Knepley     DM udm;
144900dabe28SStefano Zampini 
14509566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
145169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
145200dabe28SStefano Zampini   }
14537ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
145400dabe28SStefano Zampini   PetscFunctionReturn(0);
145500dabe28SStefano Zampini }
145600dabe28SStefano Zampini 
1457a9074c1eSMatthew G. Knepley /*@C
1458a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
1459a9074c1eSMatthew G. Knepley 
1460d083f849SBarry Smith   Logically Collective on dm
1461a9074c1eSMatthew G. Knepley 
1462a9074c1eSMatthew G. Knepley   Input Parameters:
1463a9074c1eSMatthew G. Knepley + dm - the DM context
1464a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1465a9074c1eSMatthew G. Knepley 
1466a1cb98faSBarry Smith   Level: advanced
1467a1cb98faSBarry Smith 
1468a1cb98faSBarry Smith   Note:
1469a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1470a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1471a9074c1eSMatthew G. Knepley 
1472a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
1473a9074c1eSMatthew G. Knepley @*/
1474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1475d71ae5a4SJacob Faibussowitsch {
1476a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1477a9074c1eSMatthew G. Knepley 
1478a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1479a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
14819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
1482a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1483a9074c1eSMatthew G. Knepley }
1484a9074c1eSMatthew G. Knepley 
14859318fe57SMatthew G. Knepley /* Remap geometry to cylinder
148661a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
148761a622f3SMatthew G. Knepley 
14889318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
14899318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
14909318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
14910510c589SMatthew G. Knepley 
14929318fe57SMatthew G. Knepley        phi     = arctan(y/x)
14939318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
14949318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
14950510c589SMatthew G. Knepley 
14969318fe57SMatthew G. Knepley      so we remap them using
14970510c589SMatthew G. Knepley 
14989318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
14999318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
15000510c589SMatthew G. Knepley 
15019318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
15029318fe57SMatthew G. Knepley */
1503d71ae5a4SJacob 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[])
1504d71ae5a4SJacob Faibussowitsch {
15059318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
15069318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
150722cc497dSMatthew G. Knepley 
15089318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
15099318fe57SMatthew G. Knepley     f0[0] = u[0];
15109318fe57SMatthew G. Knepley     f0[1] = u[1];
15119318fe57SMatthew G. Knepley   } else {
15129318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
15130510c589SMatthew G. Knepley 
15149318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
15159318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
15169318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
15179318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
15189318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
15199318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
15209318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
15219318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
15229318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
15239318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
15249318fe57SMatthew G. Knepley     } else {
15259318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
15269318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
15279318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
15289318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
15299318fe57SMatthew G. Knepley     }
15309318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
15319318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
15329318fe57SMatthew G. Knepley   }
15339318fe57SMatthew G. Knepley   f0[2] = u[2];
15349318fe57SMatthew G. Knepley }
15350510c589SMatthew G. Knepley 
1536d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ)
1537d71ae5a4SJacob Faibussowitsch {
15380510c589SMatthew G. Knepley   const PetscInt dim = 3;
15399318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1540d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
15410510c589SMatthew G. Knepley 
15420510c589SMatthew G. Knepley   PetscFunctionBegin;
15439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15449566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
15450510c589SMatthew G. Knepley   /* Create topology */
15460510c589SMatthew G. Knepley   {
15470510c589SMatthew G. Knepley     PetscInt cone[8], c;
15480510c589SMatthew G. Knepley 
1549dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1550dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1551006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1552ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1553dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1554006a8963SMatthew G. Knepley     }
15559566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
15569566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
15579566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1558dd400576SPatrick Sanan     if (rank == 0) {
1559006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
15609371c9d4SSatish Balay         cone[0] = 15;
15619371c9d4SSatish Balay         cone[1] = 18;
15629371c9d4SSatish Balay         cone[2] = 17;
15639371c9d4SSatish Balay         cone[3] = 16;
15649371c9d4SSatish Balay         cone[4] = 31;
15659371c9d4SSatish Balay         cone[5] = 32;
15669371c9d4SSatish Balay         cone[6] = 33;
15679371c9d4SSatish Balay         cone[7] = 34;
15689566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
15699371c9d4SSatish Balay         cone[0] = 16;
15709371c9d4SSatish Balay         cone[1] = 17;
15719371c9d4SSatish Balay         cone[2] = 24;
15729371c9d4SSatish Balay         cone[3] = 23;
15739371c9d4SSatish Balay         cone[4] = 32;
15749371c9d4SSatish Balay         cone[5] = 36;
15759371c9d4SSatish Balay         cone[6] = 37;
15769371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
15779566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
15789371c9d4SSatish Balay         cone[0] = 18;
15799371c9d4SSatish Balay         cone[1] = 27;
15809371c9d4SSatish Balay         cone[2] = 24;
15819371c9d4SSatish Balay         cone[3] = 17;
15829371c9d4SSatish Balay         cone[4] = 34;
15839371c9d4SSatish Balay         cone[5] = 33;
15849371c9d4SSatish Balay         cone[6] = 37;
15859371c9d4SSatish Balay         cone[7] = 38;
15869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
15879371c9d4SSatish Balay         cone[0] = 29;
15889371c9d4SSatish Balay         cone[1] = 27;
15899371c9d4SSatish Balay         cone[2] = 18;
15909371c9d4SSatish Balay         cone[3] = 15;
15919371c9d4SSatish Balay         cone[4] = 35;
15929371c9d4SSatish Balay         cone[5] = 31;
15939371c9d4SSatish Balay         cone[6] = 34;
15949371c9d4SSatish Balay         cone[7] = 38;
15959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
15969371c9d4SSatish Balay         cone[0] = 29;
15979371c9d4SSatish Balay         cone[1] = 15;
15989371c9d4SSatish Balay         cone[2] = 16;
15999371c9d4SSatish Balay         cone[3] = 23;
16009371c9d4SSatish Balay         cone[4] = 35;
16019371c9d4SSatish Balay         cone[5] = 36;
16029371c9d4SSatish Balay         cone[6] = 32;
16039371c9d4SSatish Balay         cone[7] = 31;
16049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1605006a8963SMatthew G. Knepley 
16069371c9d4SSatish Balay         cone[0] = 31;
16079371c9d4SSatish Balay         cone[1] = 34;
16089371c9d4SSatish Balay         cone[2] = 33;
16099371c9d4SSatish Balay         cone[3] = 32;
16109371c9d4SSatish Balay         cone[4] = 19;
16119371c9d4SSatish Balay         cone[5] = 22;
16129371c9d4SSatish Balay         cone[6] = 21;
16139371c9d4SSatish Balay         cone[7] = 20;
16149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
16159371c9d4SSatish Balay         cone[0] = 32;
16169371c9d4SSatish Balay         cone[1] = 33;
16179371c9d4SSatish Balay         cone[2] = 37;
16189371c9d4SSatish Balay         cone[3] = 36;
16199371c9d4SSatish Balay         cone[4] = 22;
16209371c9d4SSatish Balay         cone[5] = 25;
16219371c9d4SSatish Balay         cone[6] = 26;
16229371c9d4SSatish Balay         cone[7] = 21;
16239566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
16249371c9d4SSatish Balay         cone[0] = 34;
16259371c9d4SSatish Balay         cone[1] = 38;
16269371c9d4SSatish Balay         cone[2] = 37;
16279371c9d4SSatish Balay         cone[3] = 33;
16289371c9d4SSatish Balay         cone[4] = 20;
16299371c9d4SSatish Balay         cone[5] = 21;
16309371c9d4SSatish Balay         cone[6] = 26;
16319371c9d4SSatish Balay         cone[7] = 28;
16329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
16339371c9d4SSatish Balay         cone[0] = 35;
16349371c9d4SSatish Balay         cone[1] = 38;
16359371c9d4SSatish Balay         cone[2] = 34;
16369371c9d4SSatish Balay         cone[3] = 31;
16379371c9d4SSatish Balay         cone[4] = 30;
16389371c9d4SSatish Balay         cone[5] = 19;
16399371c9d4SSatish Balay         cone[6] = 20;
16409371c9d4SSatish Balay         cone[7] = 28;
16419566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
16429371c9d4SSatish Balay         cone[0] = 35;
16439371c9d4SSatish Balay         cone[1] = 31;
16449371c9d4SSatish Balay         cone[2] = 32;
16459371c9d4SSatish Balay         cone[3] = 36;
16469371c9d4SSatish Balay         cone[4] = 30;
16479371c9d4SSatish Balay         cone[5] = 25;
16489371c9d4SSatish Balay         cone[6] = 22;
16499371c9d4SSatish Balay         cone[7] = 19;
16509566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
1651ae8bcbbbSMatthew G. Knepley 
16529371c9d4SSatish Balay         cone[0] = 19;
16539371c9d4SSatish Balay         cone[1] = 20;
16549371c9d4SSatish Balay         cone[2] = 21;
16559371c9d4SSatish Balay         cone[3] = 22;
16569371c9d4SSatish Balay         cone[4] = 15;
16579371c9d4SSatish Balay         cone[5] = 16;
16589371c9d4SSatish Balay         cone[6] = 17;
16599371c9d4SSatish Balay         cone[7] = 18;
16609566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
16619371c9d4SSatish Balay         cone[0] = 22;
16629371c9d4SSatish Balay         cone[1] = 21;
16639371c9d4SSatish Balay         cone[2] = 26;
16649371c9d4SSatish Balay         cone[3] = 25;
16659371c9d4SSatish Balay         cone[4] = 16;
16669371c9d4SSatish Balay         cone[5] = 23;
16679371c9d4SSatish Balay         cone[6] = 24;
16689371c9d4SSatish Balay         cone[7] = 17;
16699566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
16709371c9d4SSatish Balay         cone[0] = 20;
16719371c9d4SSatish Balay         cone[1] = 28;
16729371c9d4SSatish Balay         cone[2] = 26;
16739371c9d4SSatish Balay         cone[3] = 21;
16749371c9d4SSatish Balay         cone[4] = 18;
16759371c9d4SSatish Balay         cone[5] = 17;
16769371c9d4SSatish Balay         cone[6] = 24;
16779371c9d4SSatish Balay         cone[7] = 27;
16789566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
16799371c9d4SSatish Balay         cone[0] = 30;
16809371c9d4SSatish Balay         cone[1] = 28;
16819371c9d4SSatish Balay         cone[2] = 20;
16829371c9d4SSatish Balay         cone[3] = 19;
16839371c9d4SSatish Balay         cone[4] = 29;
16849371c9d4SSatish Balay         cone[5] = 15;
16859371c9d4SSatish Balay         cone[6] = 18;
16869371c9d4SSatish Balay         cone[7] = 27;
16879566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
16889371c9d4SSatish Balay         cone[0] = 30;
16899371c9d4SSatish Balay         cone[1] = 19;
16909371c9d4SSatish Balay         cone[2] = 22;
16919371c9d4SSatish Balay         cone[3] = 25;
16929371c9d4SSatish Balay         cone[4] = 29;
16939371c9d4SSatish Balay         cone[5] = 23;
16949371c9d4SSatish Balay         cone[6] = 16;
16959371c9d4SSatish Balay         cone[7] = 15;
16969566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
1697006a8963SMatthew G. Knepley       } else {
16989371c9d4SSatish Balay         cone[0] = 5;
16999371c9d4SSatish Balay         cone[1] = 8;
17009371c9d4SSatish Balay         cone[2] = 7;
17019371c9d4SSatish Balay         cone[3] = 6;
17029371c9d4SSatish Balay         cone[4] = 9;
17039371c9d4SSatish Balay         cone[5] = 12;
17049371c9d4SSatish Balay         cone[6] = 11;
17059371c9d4SSatish Balay         cone[7] = 10;
17069566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
17079371c9d4SSatish Balay         cone[0] = 6;
17089371c9d4SSatish Balay         cone[1] = 7;
17099371c9d4SSatish Balay         cone[2] = 14;
17109371c9d4SSatish Balay         cone[3] = 13;
17119371c9d4SSatish Balay         cone[4] = 12;
17129371c9d4SSatish Balay         cone[5] = 15;
17139371c9d4SSatish Balay         cone[6] = 16;
17149371c9d4SSatish Balay         cone[7] = 11;
17159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
17169371c9d4SSatish Balay         cone[0] = 8;
17179371c9d4SSatish Balay         cone[1] = 17;
17189371c9d4SSatish Balay         cone[2] = 14;
17199371c9d4SSatish Balay         cone[3] = 7;
17209371c9d4SSatish Balay         cone[4] = 10;
17219371c9d4SSatish Balay         cone[5] = 11;
17229371c9d4SSatish Balay         cone[6] = 16;
17239371c9d4SSatish Balay         cone[7] = 18;
17249566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
17259371c9d4SSatish Balay         cone[0] = 19;
17269371c9d4SSatish Balay         cone[1] = 17;
17279371c9d4SSatish Balay         cone[2] = 8;
17289371c9d4SSatish Balay         cone[3] = 5;
17299371c9d4SSatish Balay         cone[4] = 20;
17309371c9d4SSatish Balay         cone[5] = 9;
17319371c9d4SSatish Balay         cone[6] = 10;
17329371c9d4SSatish Balay         cone[7] = 18;
17339566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
17349371c9d4SSatish Balay         cone[0] = 19;
17359371c9d4SSatish Balay         cone[1] = 5;
17369371c9d4SSatish Balay         cone[2] = 6;
17379371c9d4SSatish Balay         cone[3] = 13;
17389371c9d4SSatish Balay         cone[4] = 20;
17399371c9d4SSatish Balay         cone[5] = 15;
17409371c9d4SSatish Balay         cone[6] = 12;
17419371c9d4SSatish Balay         cone[7] = 9;
17429566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1743006a8963SMatthew G. Knepley       }
1744d8c47e87SMatthew G. Knepley     }
17459566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
17469566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
17470510c589SMatthew G. Knepley   }
1748dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
17490510c589SMatthew G. Knepley   {
17500510c589SMatthew G. Knepley     Vec             coordinates;
17510510c589SMatthew G. Knepley     PetscSection    coordSection;
17520510c589SMatthew G. Knepley     PetscScalar    *coords;
17530510c589SMatthew G. Knepley     PetscInt        coordSize, v;
17540510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
17550510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
17560510c589SMatthew G. Knepley 
17570510c589SMatthew G. Knepley     /* Build coordinates */
17589566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
17599566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
17609566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
17619566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
17620510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
17639566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
17649566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
17650510c589SMatthew G. Knepley     }
17669566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
17679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
17689566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
17699566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
17709566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
17719566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
17729566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
17739566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1774dd400576SPatrick Sanan     if (rank == 0) {
17759371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
17769371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
17779371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
17789371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
17799371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
17809371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
17819371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
17829371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
17839371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
17849371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
17859371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
17869371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
17879371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
17889371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
17899371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
17909371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
17919371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
17929371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
17939371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
17949371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
17959371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
17969371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
17979371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
17989371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
17999371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
18009371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
18019371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
18029371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
18039371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
18049371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
18059371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
18069371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
18079371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
18089371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
18099371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
18109371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
18119371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
18129371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
18139371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
18149371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
18159371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
18169371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
18179371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
18189371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
18199371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
18209371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
18219371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
18229371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
1823ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
18249371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
18259371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
18269371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
18279371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
18289371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
18299371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
18309371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
18319371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
18329371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
18339371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
18349371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
18359371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
18369371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
18379371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
18389371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
18399371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
18409371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
18419371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
18429371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
18439371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
18449371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
18459371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
18469371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
18479371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
1848ae8bcbbbSMatthew G. Knepley       }
1849d8c47e87SMatthew G. Knepley     }
18509566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18519566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18529566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18530510c589SMatthew G. Knepley   }
1854006a8963SMatthew G. Knepley   /* Create periodicity */
1855006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
18566858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
18576858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1858006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
1859ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
18606858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
1861006a8963SMatthew G. Knepley 
18626858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
18636858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
18644fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1865006a8963SMatthew G. Knepley   }
1866dbc1dc17SMatthew G. Knepley   {
18679318fe57SMatthew G. Knepley     DM          cdm;
18689318fe57SMatthew G. Knepley     PetscDS     cds;
18699318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1870dbc1dc17SMatthew G. Knepley 
18719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
18729566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
18739566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
18749566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
1875dbc1dc17SMatthew G. Knepley   }
18769318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
18779566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
18780510c589SMatthew G. Knepley   PetscFunctionReturn(0);
18790510c589SMatthew G. Knepley }
18800510c589SMatthew G. Knepley 
188124119c2aSMatthew G. Knepley /*@
18829318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
188324119c2aSMatthew G. Knepley 
1884d083f849SBarry Smith   Collective
188524119c2aSMatthew G. Knepley 
188624119c2aSMatthew G. Knepley   Input Parameters:
1887a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
18889318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
188924119c2aSMatthew G. Knepley 
189024119c2aSMatthew G. Knepley   Output Parameter:
189124119c2aSMatthew G. Knepley . dm  - The DM object
189224119c2aSMatthew G. Knepley 
189324119c2aSMatthew G. Knepley   Level: beginner
189424119c2aSMatthew G. Knepley 
1895a1cb98faSBarry Smith   Note:
1896a1cb98faSBarry Smith   Here is the output numbering looking from the bottom of the cylinder:
1897a1cb98faSBarry Smith .vb
1898a1cb98faSBarry Smith        17-----14
1899a1cb98faSBarry Smith         |     |
1900a1cb98faSBarry Smith         |  2  |
1901a1cb98faSBarry Smith         |     |
1902a1cb98faSBarry Smith  17-----8-----7-----14
1903a1cb98faSBarry Smith   |     |     |     |
1904a1cb98faSBarry Smith   |  3  |  0  |  1  |
1905a1cb98faSBarry Smith   |     |     |     |
1906a1cb98faSBarry Smith  19-----5-----6-----13
1907a1cb98faSBarry Smith         |     |
1908a1cb98faSBarry Smith         |  4  |
1909a1cb98faSBarry Smith         |     |
1910a1cb98faSBarry Smith        19-----13
1911a1cb98faSBarry Smith 
1912a1cb98faSBarry Smith  and up through the top
1913a1cb98faSBarry Smith 
1914a1cb98faSBarry Smith        18-----16
1915a1cb98faSBarry Smith         |     |
1916a1cb98faSBarry Smith         |  2  |
1917a1cb98faSBarry Smith         |     |
1918a1cb98faSBarry Smith  18----10----11-----16
1919a1cb98faSBarry Smith   |     |     |     |
1920a1cb98faSBarry Smith   |  3  |  0  |  1  |
1921a1cb98faSBarry Smith   |     |     |     |
1922a1cb98faSBarry Smith  20-----9----12-----15
1923a1cb98faSBarry Smith         |     |
1924a1cb98faSBarry Smith         |  4  |
1925a1cb98faSBarry Smith         |     |
1926a1cb98faSBarry Smith        20-----15
1927a1cb98faSBarry Smith .ve
1928a1cb98faSBarry Smith 
1929a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
193024119c2aSMatthew G. Knepley @*/
1931d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm)
1932d71ae5a4SJacob Faibussowitsch {
19339318fe57SMatthew G. Knepley   PetscFunctionBegin;
19349318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
19359566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
19369566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
19379566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
19389318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
19399318fe57SMatthew G. Knepley }
19409318fe57SMatthew G. Knepley 
1941d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
1942d71ae5a4SJacob Faibussowitsch {
194324119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1944412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
19459fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
194624119c2aSMatthew G. Knepley 
194724119c2aSMatthew G. Knepley   PetscFunctionBegin;
194863a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
19499566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
19509566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1951412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
19529566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
195324119c2aSMatthew G. Knepley   /* Create topology */
195424119c2aSMatthew G. Knepley   {
195524119c2aSMatthew G. Knepley     PetscInt cone[6], c;
195624119c2aSMatthew G. Knepley 
1957dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
1958dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
19599566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19609566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
19619566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
196224119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19639371c9d4SSatish Balay       cone[0] = c + n * 1;
19649371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
19659371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
19669371c9d4SSatish Balay       cone[3] = c + n * 2;
19679371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
19689371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
19699566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
19709566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
197124119c2aSMatthew G. Knepley     }
19729566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
19739566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
197424119c2aSMatthew G. Knepley   }
197548a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
197624119c2aSMatthew G. Knepley   /* Create cylinder geometry */
197724119c2aSMatthew G. Knepley   {
197824119c2aSMatthew G. Knepley     Vec          coordinates;
197924119c2aSMatthew G. Knepley     PetscSection coordSection;
198024119c2aSMatthew G. Knepley     PetscScalar *coords;
1981412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
198224119c2aSMatthew G. Knepley 
198324119c2aSMatthew G. Knepley     /* Build coordinates */
19849566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
19859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
19869566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
19879566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
198824119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
19899566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
19909566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
199124119c2aSMatthew G. Knepley     }
19929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
19939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
19949566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
19959566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
19969566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
19979566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
19989566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
19999566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
200024119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
20019371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
20029371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
20039371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
20049371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
20059371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
20069371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
200724119c2aSMatthew G. Knepley     }
2008dd400576SPatrick Sanan     if (rank == 0) {
20099371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
20109371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
20119371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
20129371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
20139371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
20149371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
20159fe9f049SMatthew G. Knepley     }
20169566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
20179566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
20189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
201924119c2aSMatthew G. Knepley   }
20209318fe57SMatthew G. Knepley   /* Interpolate */
20219566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
20229318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
20239318fe57SMatthew G. Knepley }
20249318fe57SMatthew G. Knepley 
20259318fe57SMatthew G. Knepley /*@
20269318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
20279318fe57SMatthew G. Knepley 
20289318fe57SMatthew G. Knepley   Collective
20299318fe57SMatthew G. Knepley 
20309318fe57SMatthew G. Knepley   Input Parameters:
2031a1cb98faSBarry Smith + comm - The communicator for the `DM` object
20329318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
20339318fe57SMatthew G. Knepley - interpolate - Create edges and faces
20349318fe57SMatthew G. Knepley 
20359318fe57SMatthew G. Knepley   Output Parameter:
2036a1cb98faSBarry Smith . dm  - The `DM` object
20379318fe57SMatthew G. Knepley 
20389318fe57SMatthew G. Knepley   Level: beginner
20399318fe57SMatthew G. Knepley 
2040a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
20419318fe57SMatthew G. Knepley @*/
2042d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2043d71ae5a4SJacob Faibussowitsch {
20449318fe57SMatthew G. Knepley   PetscFunctionBegin;
20459318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
20469566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20479566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20489566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
204924119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
205024119c2aSMatthew G. Knepley }
205124119c2aSMatthew G. Knepley 
2052d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2053d71ae5a4SJacob Faibussowitsch {
205465a81367SMatthew G. Knepley   PetscReal prod = 0.0;
205565a81367SMatthew G. Knepley   PetscInt  i;
205665a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
205765a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
205865a81367SMatthew G. Knepley }
2059d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2060d71ae5a4SJacob Faibussowitsch {
206165a81367SMatthew G. Knepley   PetscReal prod = 0.0;
206265a81367SMatthew G. Knepley   PetscInt  i;
206365a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
206465a81367SMatthew G. Knepley   return prod;
206565a81367SMatthew G. Knepley }
206665a81367SMatthew G. Knepley 
206751a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2068d71ae5a4SJacob 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[])
2069d71ae5a4SJacob Faibussowitsch {
207051a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
207151a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
207251a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
207351a74b61SMatthew G. Knepley 
207451a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
207551a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
207651a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
207751a74b61SMatthew G. Knepley }
207851a74b61SMatthew G. Knepley 
2079d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2080d71ae5a4SJacob Faibussowitsch {
208165a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
208265a81367SMatthew G. Knepley   PetscSection   coordSection;
208365a81367SMatthew G. Knepley   Vec            coordinates;
208465a81367SMatthew G. Knepley   PetscScalar   *coords;
208565a81367SMatthew G. Knepley   PetscReal     *coordsIn;
2086064cae4fSPierre Jolivet   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e;
208765a81367SMatthew G. Knepley   PetscMPIInt    rank;
208865a81367SMatthew G. Knepley 
208965a81367SMatthew G. Knepley   PetscFunctionBegin;
20909318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
20919566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
20929566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
20939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
209465a81367SMatthew G. Knepley   switch (dim) {
209565a81367SMatthew G. Knepley   case 2:
209665a81367SMatthew G. Knepley     if (simplex) {
209751a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
209851a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
209965a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
210051a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
210165a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
210265a81367SMatthew G. Knepley       PetscInt        cone[3];
210365a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
210465a81367SMatthew G. Knepley 
21059371c9d4SSatish Balay       vertex[0] *= R / radius;
21069371c9d4SSatish Balay       vertex[1] *= R / radius;
21079371c9d4SSatish Balay       vertex[2] *= R / radius;
2108dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2109dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
211065a81367SMatthew G. Knepley       firstVertex = numCells;
211151a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
211265a81367SMatthew G. Knepley 
211365a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
211465a81367SMatthew G. Knepley 
211565a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
211651a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
211765a81367SMatthew G. Knepley       */
211865a81367SMatthew G. Knepley       /* Construct vertices */
21199566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2120dd400576SPatrick Sanan       if (rank == 0) {
212165a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
212265a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
212365a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
212465a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
212565a81367SMatthew G. Knepley               ++i;
212665a81367SMatthew G. Knepley             }
212765a81367SMatthew G. Knepley           }
212865a81367SMatthew G. Knepley         }
212945da822fSValeria Barra       }
213065a81367SMatthew G. Knepley       /* Construct graph */
21319566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
213265a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
213365a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
21349371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
21359371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
21369371c9d4SSatish Balay             ++k;
21379371c9d4SSatish Balay           }
213865a81367SMatthew G. Knepley         }
213963a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
214065a81367SMatthew G. Knepley       }
214165a81367SMatthew G. Knepley       /* Build Topology */
21429566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
214348a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
21449566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
214565a81367SMatthew G. Knepley       /* Cells */
214665a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
214765a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
214865a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
214965a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
21509371c9d4SSatish Balay               cone[0] = firstVertex + i;
21519371c9d4SSatish Balay               cone[1] = firstVertex + j;
21529371c9d4SSatish Balay               cone[2] = firstVertex + k;
215365a81367SMatthew G. Knepley               /* Check orientation */
215465a81367SMatthew G. Knepley               {
21559371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
21569371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
21579371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
21589371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
21599371c9d4SSatish Balay                 };
216065a81367SMatthew G. Knepley                 PetscReal normal[3];
216165a81367SMatthew G. Knepley                 PetscInt  e, f;
216265a81367SMatthew G. Knepley 
216365a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
216465a81367SMatthew G. Knepley                   normal[d] = 0.0;
216565a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
2166ad540459SPierre 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]);
216765a81367SMatthew G. Knepley                   }
216865a81367SMatthew G. Knepley                 }
21699371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
21709371c9d4SSatish Balay                   PetscInt tmp = cone[1];
21719371c9d4SSatish Balay                   cone[1]      = cone[2];
21729371c9d4SSatish Balay                   cone[2]      = tmp;
217365a81367SMatthew G. Knepley                 }
217465a81367SMatthew G. Knepley               }
21759566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
217665a81367SMatthew G. Knepley             }
217765a81367SMatthew G. Knepley           }
217865a81367SMatthew G. Knepley         }
217965a81367SMatthew G. Knepley       }
21809566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
21819566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
21829566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
218365a81367SMatthew G. Knepley     } else {
21842829fed8SMatthew G. Knepley       /*
21852829fed8SMatthew G. Knepley         12-21--13
21862829fed8SMatthew G. Knepley          |     |
21872829fed8SMatthew G. Knepley         25  4  24
21882829fed8SMatthew G. Knepley          |     |
21892829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
21902829fed8SMatthew G. Knepley    |     |     |     |
21912829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
21922829fed8SMatthew G. Knepley    |     |     |     |
21932829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
21942829fed8SMatthew G. Knepley          |     |
21952829fed8SMatthew G. Knepley         20  1  19
21962829fed8SMatthew G. Knepley          |     |
21972829fed8SMatthew G. Knepley         10-18--11
21982829fed8SMatthew G. Knepley          |     |
21992829fed8SMatthew G. Knepley         23  2  22
22002829fed8SMatthew G. Knepley          |     |
22012829fed8SMatthew G. Knepley         12-21--13
22022829fed8SMatthew G. Knepley        */
22032829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
22042829fed8SMatthew G. Knepley 
2205dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2206dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2207dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
220865a81367SMatthew G. Knepley       firstVertex = numCells;
220965a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
22102829fed8SMatthew G. Knepley       /* Build Topology */
22119566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
221248a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
221348a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
22149566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2215dd400576SPatrick Sanan       if (rank == 0) {
22162829fed8SMatthew G. Knepley         /* Cell 0 */
22179371c9d4SSatish Balay         cone[0] = 14;
22189371c9d4SSatish Balay         cone[1] = 15;
22199371c9d4SSatish Balay         cone[2] = 16;
22209371c9d4SSatish Balay         cone[3] = 17;
22219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
22229371c9d4SSatish Balay         ornt[0] = 0;
22239371c9d4SSatish Balay         ornt[1] = 0;
22249371c9d4SSatish Balay         ornt[2] = 0;
22259371c9d4SSatish Balay         ornt[3] = 0;
22269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
22272829fed8SMatthew G. Knepley         /* Cell 1 */
22289371c9d4SSatish Balay         cone[0] = 18;
22299371c9d4SSatish Balay         cone[1] = 19;
22309371c9d4SSatish Balay         cone[2] = 14;
22319371c9d4SSatish Balay         cone[3] = 20;
22329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
22339371c9d4SSatish Balay         ornt[0] = 0;
22349371c9d4SSatish Balay         ornt[1] = 0;
22359371c9d4SSatish Balay         ornt[2] = -1;
22369371c9d4SSatish Balay         ornt[3] = 0;
22379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
22382829fed8SMatthew G. Knepley         /* Cell 2 */
22399371c9d4SSatish Balay         cone[0] = 21;
22409371c9d4SSatish Balay         cone[1] = 22;
22419371c9d4SSatish Balay         cone[2] = 18;
22429371c9d4SSatish Balay         cone[3] = 23;
22439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
22449371c9d4SSatish Balay         ornt[0] = 0;
22459371c9d4SSatish Balay         ornt[1] = 0;
22469371c9d4SSatish Balay         ornt[2] = -1;
22479371c9d4SSatish Balay         ornt[3] = 0;
22489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
22492829fed8SMatthew G. Knepley         /* Cell 3 */
22509371c9d4SSatish Balay         cone[0] = 19;
22519371c9d4SSatish Balay         cone[1] = 22;
22529371c9d4SSatish Balay         cone[2] = 24;
22539371c9d4SSatish Balay         cone[3] = 15;
22549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
22559371c9d4SSatish Balay         ornt[0] = -1;
22569371c9d4SSatish Balay         ornt[1] = -1;
22579371c9d4SSatish Balay         ornt[2] = 0;
22589371c9d4SSatish Balay         ornt[3] = -1;
22599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
22602829fed8SMatthew G. Knepley         /* Cell 4 */
22619371c9d4SSatish Balay         cone[0] = 16;
22629371c9d4SSatish Balay         cone[1] = 24;
22639371c9d4SSatish Balay         cone[2] = 21;
22649371c9d4SSatish Balay         cone[3] = 25;
22659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
22669371c9d4SSatish Balay         ornt[0] = -1;
22679371c9d4SSatish Balay         ornt[1] = -1;
22689371c9d4SSatish Balay         ornt[2] = -1;
22699371c9d4SSatish Balay         ornt[3] = 0;
22709566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
22712829fed8SMatthew G. Knepley         /* Cell 5 */
22729371c9d4SSatish Balay         cone[0] = 20;
22739371c9d4SSatish Balay         cone[1] = 17;
22749371c9d4SSatish Balay         cone[2] = 25;
22759371c9d4SSatish Balay         cone[3] = 23;
22769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
22779371c9d4SSatish Balay         ornt[0] = -1;
22789371c9d4SSatish Balay         ornt[1] = -1;
22799371c9d4SSatish Balay         ornt[2] = -1;
22809371c9d4SSatish Balay         ornt[3] = -1;
22819566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
22822829fed8SMatthew G. Knepley         /* Edges */
22839371c9d4SSatish Balay         cone[0] = 6;
22849371c9d4SSatish Balay         cone[1] = 7;
22859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
22869371c9d4SSatish Balay         cone[0] = 7;
22879371c9d4SSatish Balay         cone[1] = 8;
22889566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
22899371c9d4SSatish Balay         cone[0] = 8;
22909371c9d4SSatish Balay         cone[1] = 9;
22919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
22929371c9d4SSatish Balay         cone[0] = 9;
22939371c9d4SSatish Balay         cone[1] = 6;
22949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
22959371c9d4SSatish Balay         cone[0] = 10;
22969371c9d4SSatish Balay         cone[1] = 11;
22979566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
22989371c9d4SSatish Balay         cone[0] = 11;
22999371c9d4SSatish Balay         cone[1] = 7;
23009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
23019371c9d4SSatish Balay         cone[0] = 6;
23029371c9d4SSatish Balay         cone[1] = 10;
23039566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
23049371c9d4SSatish Balay         cone[0] = 12;
23059371c9d4SSatish Balay         cone[1] = 13;
23069566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
23079371c9d4SSatish Balay         cone[0] = 13;
23089371c9d4SSatish Balay         cone[1] = 11;
23099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
23109371c9d4SSatish Balay         cone[0] = 10;
23119371c9d4SSatish Balay         cone[1] = 12;
23129566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
23139371c9d4SSatish Balay         cone[0] = 13;
23149371c9d4SSatish Balay         cone[1] = 8;
23159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
23169371c9d4SSatish Balay         cone[0] = 12;
23179371c9d4SSatish Balay         cone[1] = 9;
23189566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
231945da822fSValeria Barra       }
23209566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
23219566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
23222829fed8SMatthew G. Knepley       /* Build coordinates */
23239566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2324dd400576SPatrick Sanan       if (rank == 0) {
23259371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
23269371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
23279371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
23289371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
23299371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
23309371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
23319371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
23329371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
23339371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
23349371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
23359371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
23369371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
23379371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
23389371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
23399371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
23409371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
23419371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
23429371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
23439371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
23449371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
23459371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
23469371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
23479371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
23489371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
234965a81367SMatthew G. Knepley       }
235045da822fSValeria Barra     }
235165a81367SMatthew G. Knepley     break;
235265a81367SMatthew G. Knepley   case 3:
2353116ded15SMatthew G. Knepley     if (simplex) {
2354116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
235551a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
235651a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
235751a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2358116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2359116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
23609371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
23619371c9d4SSatish Balay         {0, 1, 2, 3},
23629371c9d4SSatish Balay         {0, 2, 3, 1},
23639371c9d4SSatish Balay         {0, 3, 1, 2},
23649371c9d4SSatish Balay         {1, 0, 3, 2},
23659371c9d4SSatish Balay         {1, 2, 0, 3},
23669371c9d4SSatish Balay         {1, 3, 2, 0},
23679371c9d4SSatish Balay         {2, 0, 1, 3},
23689371c9d4SSatish Balay         {2, 1, 3, 0},
23699371c9d4SSatish Balay         {2, 3, 0, 1},
23709371c9d4SSatish Balay         {3, 0, 2, 1},
23719371c9d4SSatish Balay         {3, 1, 0, 2},
23729371c9d4SSatish Balay         {3, 2, 1, 0}
23739371c9d4SSatish Balay       };
2374116ded15SMatthew G. Knepley       PetscInt  cone[4];
2375116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2376116ded15SMatthew G. Knepley 
23779371c9d4SSatish Balay       vertexA[0] *= R;
23789371c9d4SSatish Balay       vertexA[1] *= R;
23799371c9d4SSatish Balay       vertexA[2] *= R;
23809371c9d4SSatish Balay       vertexA[3] *= R;
23819371c9d4SSatish Balay       vertexB[0] *= R;
23829371c9d4SSatish Balay       vertexB[1] *= R;
23839371c9d4SSatish Balay       vertexB[2] *= R;
23849371c9d4SSatish Balay       vertexB[3] *= R;
23859371c9d4SSatish Balay       vertexC[0] *= R;
23869371c9d4SSatish Balay       vertexC[1] *= R;
23879371c9d4SSatish Balay       vertexC[2] *= R;
23889371c9d4SSatish Balay       vertexC[3] *= R;
2389dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2390dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2391116ded15SMatthew G. Knepley       firstVertex = numCells;
2392116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2393116ded15SMatthew G. Knepley 
2394116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2395116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2396116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2397116ded15SMatthew G. Knepley 
2398116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
23996333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2400116ded15SMatthew G. Knepley 
2401116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2402116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2403116ded15SMatthew G. Knepley       */
2404116ded15SMatthew G. Knepley       /* Construct vertices */
24059566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2406116ded15SMatthew G. Knepley       i = 0;
2407dd400576SPatrick Sanan       if (rank == 0) {
2408116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2409116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2410116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2411116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2412116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2413116ded15SMatthew G. Knepley                 ++i;
2414116ded15SMatthew G. Knepley               }
2415116ded15SMatthew G. Knepley             }
2416116ded15SMatthew G. Knepley           }
2417116ded15SMatthew G. Knepley         }
2418116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2419116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2420116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2421116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2422116ded15SMatthew G. Knepley             ++i;
2423116ded15SMatthew G. Knepley           }
2424116ded15SMatthew G. Knepley         }
2425116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2426116ded15SMatthew G. Knepley           s[3] = 1;
2427116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2428116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2429116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2430116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2431116ded15SMatthew G. Knepley                 ++i;
2432116ded15SMatthew G. Knepley               }
2433116ded15SMatthew G. Knepley             }
2434116ded15SMatthew G. Knepley           }
2435116ded15SMatthew G. Knepley         }
243645da822fSValeria Barra       }
243763a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2438116ded15SMatthew G. Knepley       /* Construct graph */
24399566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2440116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2441116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
24429371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
24439371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
24449371c9d4SSatish Balay             ++k;
24459371c9d4SSatish Balay           }
2446116ded15SMatthew G. Knepley         }
244763a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2448116ded15SMatthew G. Knepley       }
2449116ded15SMatthew G. Knepley       /* Build Topology */
24509566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
245148a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
24529566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2453116ded15SMatthew G. Knepley       /* Cells */
2454dd400576SPatrick Sanan       if (rank == 0) {
2455116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2456116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2457116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2458116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
24599371c9d4SSatish 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]) {
24609371c9d4SSatish Balay                   cone[0] = firstVertex + i;
24619371c9d4SSatish Balay                   cone[1] = firstVertex + j;
24629371c9d4SSatish Balay                   cone[2] = firstVertex + k;
24639371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2464116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2465116ded15SMatthew G. Knepley                   {
24669371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
24679371c9d4SSatish 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}}},
2468116ded15SMatthew G. Knepley 
24699371c9d4SSatish 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}}},
2470116ded15SMatthew G. Knepley 
24719371c9d4SSatish 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}}},
2472116ded15SMatthew G. Knepley 
24739371c9d4SSatish 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}} }
24749371c9d4SSatish Balay                     };
2475116ded15SMatthew G. Knepley                     PetscReal normal[4];
2476116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2477116ded15SMatthew G. Knepley 
2478116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2479116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2480116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2481116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2482116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2483116ded15SMatthew 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]);
2484116ded15SMatthew G. Knepley                           }
2485116ded15SMatthew G. Knepley                         }
2486116ded15SMatthew G. Knepley                       }
2487116ded15SMatthew G. Knepley                     }
24889371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
24899371c9d4SSatish Balay                       PetscInt tmp = cone[1];
24909371c9d4SSatish Balay                       cone[1]      = cone[2];
24919371c9d4SSatish Balay                       cone[2]      = tmp;
24929371c9d4SSatish Balay                     }
2493116ded15SMatthew G. Knepley                   }
24949566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2495116ded15SMatthew G. Knepley                 }
2496116ded15SMatthew G. Knepley               }
2497116ded15SMatthew G. Knepley             }
2498116ded15SMatthew G. Knepley           }
2499116ded15SMatthew G. Knepley         }
250045da822fSValeria Barra       }
25019566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
25029566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
25039566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2504116ded15SMatthew G. Knepley     }
2505f4d061e9SPierre Jolivet     break;
2506d71ae5a4SJacob Faibussowitsch   default:
2507d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
250865a81367SMatthew G. Knepley   }
250965a81367SMatthew G. Knepley   /* Create coordinates */
25109566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
25119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
25129566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
25139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
25142829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
25159566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
25169566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
25172829fed8SMatthew G. Knepley   }
25189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
25199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25209566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25219566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
25229566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25239566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25249566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
25259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
25269371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
2527ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
25289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
25299566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
25309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
25319566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
253251a74b61SMatthew G. Knepley   {
253351a74b61SMatthew G. Knepley     DM          cdm;
253451a74b61SMatthew G. Knepley     PetscDS     cds;
25359318fe57SMatthew G. Knepley     PetscScalar c = R;
253651a74b61SMatthew G. Knepley 
25379566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
25389566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
25399566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
25409566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
254151a74b61SMatthew G. Knepley   }
25429318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
25439566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
25449318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
25459318fe57SMatthew G. Knepley }
25469318fe57SMatthew G. Knepley 
2547b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
2548b7f5c055SJed Brown 
2549b7f5c055SJed Brown /*
2550b7f5c055SJed Brown  The Schwarz P implicit surface is
2551b7f5c055SJed Brown 
2552b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2553b7f5c055SJed Brown */
2554d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2555d71ae5a4SJacob Faibussowitsch {
2556b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2557b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2558b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
2559b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2560b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
2561ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
2562b7f5c055SJed Brown   }
2563b7f5c055SJed Brown }
2564b7f5c055SJed Brown 
25654663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2566d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2567d71ae5a4SJacob Faibussowitsch {
2568ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
25694663dae6SJed Brown   return 0;
25704663dae6SJed Brown }
25714663dae6SJed Brown 
2572b7f5c055SJed Brown /*
2573b7f5c055SJed Brown  The Gyroid implicit surface is
2574b7f5c055SJed Brown 
2575b7f5c055SJed 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)
2576b7f5c055SJed Brown 
2577b7f5c055SJed Brown */
2578d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2579d71ae5a4SJacob Faibussowitsch {
2580b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2581b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2582b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2583b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2584b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2585b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2586b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2587b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2588b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2589b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2590b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2591b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2592b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2593b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2594b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2595b7f5c055SJed Brown }
2596b7f5c055SJed Brown 
25974663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2598d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2599d71ae5a4SJacob Faibussowitsch {
26004663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
26014663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
26024663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
26034663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
26044663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
26054663dae6SJed Brown   return 0;
26064663dae6SJed Brown }
26074663dae6SJed Brown 
2608b7f5c055SJed Brown /*
2609b7f5c055SJed Brown    We wish to solve
2610b7f5c055SJed Brown 
2611b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2612b7f5c055SJed Brown 
2613b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2614b7f5c055SJed 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
2615b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2616b7f5c055SJed Brown 
2617b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2618b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2619b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2620b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2621b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2622b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2623b7f5c055SJed Brown 
2624b7f5c055SJed Brown      f(y) = 0                       1 equation
2625b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2626b7f5c055SJed Brown 
2627b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2628b7f5c055SJed Brown */
2629d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
2630d71ae5a4SJacob Faibussowitsch {
2631b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2632b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
26332f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
26349371c9d4SSatish Balay   PetscReal n_y[3][3] = {
26359371c9d4SSatish Balay     {0, 0, 0},
26369371c9d4SSatish Balay     {0, 0, 0},
26379371c9d4SSatish Balay     {0, 0, 0}
26389371c9d4SSatish Balay   };
2639b7f5c055SJed Brown 
2640b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2641b7f5c055SJed Brown 
2642b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
2643b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2644ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
2645b7f5c055SJed Brown 
2646b7f5c055SJed Brown   // Define the Householder reflector
2647b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2648b7f5c055SJed Brown   n[0] += norm * sign;
2649b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
2650b7f5c055SJed Brown 
2651b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2652b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2653b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2654b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2655b7f5c055SJed Brown 
2656b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2657b7f5c055SJed Brown     n[i] /= norm;
2658b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
2659b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2660b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2661b7f5c055SJed Brown     }
2662b7f5c055SJed Brown   }
2663b7f5c055SJed Brown 
2664b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2665b7f5c055SJed 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];
2666b7f5c055SJed Brown 
2667b7f5c055SJed Brown   res[0] = f;
2668b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2669b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2670b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2671b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
2672b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
2673b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2674b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2675b7f5c055SJed Brown   }
2676b7f5c055SJed Brown }
2677b7f5c055SJed Brown 
2678b7f5c055SJed Brown /*
2679b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2680b7f5c055SJed Brown */
2681d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
2682d71ae5a4SJacob Faibussowitsch {
2683b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2684b7f5c055SJed Brown 
2685b7f5c055SJed Brown   PetscFunctionBegin;
2686b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
2687b7f5c055SJed Brown     PetscScalar res[3], J[9];
2688b7f5c055SJed Brown     PetscReal   resnorm;
2689b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2690b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2691b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
269263a3b9bcSJacob 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])));
2693b7f5c055SJed Brown     }
2694b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2695b7f5c055SJed Brown 
2696b7f5c055SJed Brown     // Take the Newton step
26979566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2698b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2699b7f5c055SJed Brown   }
2700b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
2701b7f5c055SJed Brown   PetscFunctionReturn(0);
2702b7f5c055SJed Brown }
2703b7f5c055SJed Brown 
2704b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2705b7f5c055SJed Brown 
2706d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
2707d71ae5a4SJacob Faibussowitsch {
2708b7f5c055SJed Brown   PetscMPIInt rank;
2709b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2710b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
2711b7f5c055SJed Brown   PetscInt            *cells_flat = NULL;
2712b7f5c055SJed Brown   PetscReal           *vtxCoords  = NULL;
2713b7f5c055SJed Brown   TPSEvaluateFunc      evalFunc   = NULL;
27144663dae6SJed Brown   PetscSimplePointFunc normalFunc = NULL;
2715b7f5c055SJed Brown   DMLabel              label;
2716b7f5c055SJed Brown 
2717b7f5c055SJed Brown   PetscFunctionBegin;
27189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
271963a3b9bcSJacob 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);
2720b7f5c055SJed Brown   switch (tpstype) {
2721b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2722b7f5c055SJed 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");
2723c5853193SPierre Jolivet     if (rank == 0) {
2724b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2725b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2726b7f5c055SJed Brown       PetscReal L = 1;
2727b7f5c055SJed Brown 
2728b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
2729b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
2730b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
2731b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
2732b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2733b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
27349566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
27359566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
27369566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
27379566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
2738b7f5c055SJed Brown       // x-normal pipes
2739b7f5c055SJed Brown       vcount = 0;
2740b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
2741b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2742b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2743b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2744b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
2745b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2746b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2747b7f5c055SJed Brown             }
2748b7f5c055SJed Brown           }
2749b7f5c055SJed Brown         }
2750b7f5c055SJed Brown       }
2751b7f5c055SJed Brown       // y-normal pipes
2752b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2753b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
2754b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2755b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2756b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2757b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
2758b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2759b7f5c055SJed Brown             }
2760b7f5c055SJed Brown           }
2761b7f5c055SJed Brown         }
2762b7f5c055SJed Brown       }
2763b7f5c055SJed Brown       // z-normal pipes
2764b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2765b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2766b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
2767b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2768b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2769b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2770b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
2771b7f5c055SJed Brown             }
2772b7f5c055SJed Brown           }
2773b7f5c055SJed Brown         }
2774b7f5c055SJed Brown       }
2775b7f5c055SJed Brown       // junctions
2776b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2777b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2778b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2779b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
2780b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2781b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
2782b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
2783b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
2784b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
2785b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
2786b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
2787b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
2788b7f5c055SJed Brown                 }
2789b7f5c055SJed Brown               }
2790b7f5c055SJed Brown             }
2791b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2792b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
2793b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
2794b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
2795b7f5c055SJed Brown             };
2796b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
27979371c9d4SSatish 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};
2798b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
27999371c9d4SSatish 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};
2800b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
2801b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2802b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
2803b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
2804b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
2805b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
2806b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
2807b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
2808b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
2809b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
2810b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
2811b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2812b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2813b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
2814b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
2815b7f5c055SJed Brown                   numEdges++;
2816b7f5c055SJed Brown                 }
2817b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2818b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2819b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
2820b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
2821b7f5c055SJed Brown                   numEdges++;
2822b7f5c055SJed Brown                 }
2823b7f5c055SJed Brown               }
2824b7f5c055SJed Brown             }
2825b7f5c055SJed Brown           }
2826b7f5c055SJed Brown         }
2827b7f5c055SJed Brown       }
282863a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
2829b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
2830b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2831b7f5c055SJed Brown     }
2832b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
28334663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
2834b7f5c055SJed Brown     break;
2835b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2836c5853193SPierre Jolivet     if (rank == 0) {
2837b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2838b7f5c055SJed Brown       //
2839b7f5c055SJed 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)
2840b7f5c055SJed Brown       //
2841b7f5c055SJed Brown       // on the cell [0,2]^3.
2842b7f5c055SJed Brown       //
2843b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2844b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2845b7f5c055SJed Brown       // like a boomerang:
2846b7f5c055SJed Brown       //
2847b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2848b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2849b7f5c055SJed Brown       //                                                              //
2850b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2851b7f5c055SJed Brown       //      \                                   /            \      //
2852b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2853b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2854b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2855b7f5c055SJed Brown       //                                                              //
2856b7f5c055SJed Brown       //                                                              //
2857b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2858b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2859b7f5c055SJed Brown       //                                                              //
2860b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2861b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2862b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2863b7f5c055SJed Brown       //            \                       /                \        //
2864b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2865b7f5c055SJed Brown       //
2866b7f5c055SJed Brown       //
2867b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2868b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2869b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2870b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2871b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2872b7f5c055SJed Brown       //
2873b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2874b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2875b7f5c055SJed Brown       //
2876b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2877b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2878b7f5c055SJed Brown 
2879b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
2880b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
2881b7f5c055SJed Brown       PetscInt extentPlus[3];
2882b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
28839371c9d4SSatish 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;
28849371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
28859371c9d4SSatish Balay   /* face to vertex within the coarse discretization of a single gyroid block */
2886b7f5c055SJed Brown   /* layer 0 */
28879371c9d4SSatish Balay         {A,           C,           K,           G          },
28889371c9d4SSatish Balay         {C,           B,           II,          K          },
28899371c9d4SSatish Balay         {D,           A,           H,           L          },
28909371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
28919371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
28929371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
28939371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
28949371c9d4SSatish Balay         {B,           F,           M,           II         },
2895b7f5c055SJed Brown  /* layer 1 */
28969371c9d4SSatish Balay         {G,           K,           Q,           O          },
28979371c9d4SSatish Balay         {K,           II,          P,           Q          },
28989371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
28999371c9d4SSatish Balay         {J,           L,           R,           P          },
29009371c9d4SSatish Balay         {N,           J,           P,           S          },
29019371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
29029371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
29039371c9d4SSatish Balay         {II,          M,           T,           P          },
2904b7f5c055SJed Brown  /* layer 2 */
29059371c9d4SSatish Balay         {O,           Q,           Y,           U          },
29069371c9d4SSatish Balay         {Q,           P,           W,           Y          },
29079371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
29089371c9d4SSatish Balay         {P,           R,           Ap,          W          },
29099371c9d4SSatish Balay         {S,           P,           X,           Bp         },
29109371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
29119371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
29129371c9d4SSatish Balay         {P,           T,           Z,           X          },
2913b7f5c055SJed Brown  /* layer 3 */
29149371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
29159371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
29169371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
29179371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
29189371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
29199371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
29209371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
29219371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
2922b7f5c055SJed Brown  /* layer 4 */
29239371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
29249371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
29259371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
29269371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
29279371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
29289371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
29299371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
29309371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
2931b7f5c055SJed Brown  /* layer 5 */
29329371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
29339371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
29349371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
29359371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
29369371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
29379371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
29389371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
29399371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
2940b7f5c055SJed Brown  /* layer 6 */
29419371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
29429371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
29439371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
29449371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
29459371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
29469371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
29479371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
29489371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
2949b7f5c055SJed Brown  /* layer 7 (the top is the periodic image of the bottom of layer 0) */
29509371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
29519371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
29529371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
29539371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
29549371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
29559371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
29569371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
29579371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
2958b7f5c055SJed Brown       };
2959b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
29609371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
2961bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
2962bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
2963bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
2964bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
2965bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
2966bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
2967b7f5c055SJed Brown 
2968bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
2969bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
2970bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
2971bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
2972bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
2973bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
2974bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
2975bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
2976b7f5c055SJed Brown 
2977bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
2978bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
2979bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
2980bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
2981bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
2982bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
2983b7f5c055SJed Brown 
2984bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
2985bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
2986bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
2987bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
2988bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
2989bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
2990bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
2991bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
2992b7f5c055SJed Brown 
2993bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
2994bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
2995bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
2996bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
2997bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
2998bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
2999b7f5c055SJed Brown 
3000bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
3001bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
3002bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
3003bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
3004bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
3005bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
3006bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
3007bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
3008b7f5c055SJed Brown 
3009bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
3010bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
3011bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
3012bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
3013bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
3014bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
3015b7f5c055SJed Brown 
3016bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3017bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3018bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3019bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3020bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3021bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3022bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3023bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3024b7f5c055SJed Brown       };
3025b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3026b7f5c055SJed Brown       PetscBool *seen;
3027b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3028b7f5c055SJed Brown       PetscInt   count;
3029b7f5c055SJed Brown 
3030b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3031b7f5c055SJed Brown       numBlocks = 1;
3032b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3033b7f5c055SJed Brown       numBlocksPlus = 1;
3034b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3035b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
30369566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
30379566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3038b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3039b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3040b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3041b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3042b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3043b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3044b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3045b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3046b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3047b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3048b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3049b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3050b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3051b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3052b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3053b7f5c055SJed Brown 
3054b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3055b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3056b7f5c055SJed Brown               }
3057b7f5c055SJed Brown             }
3058b7f5c055SJed Brown           }
3059b7f5c055SJed Brown         }
3060b7f5c055SJed Brown       }
30619371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
30629371c9d4SSatish Balay         if (seen[i]) numVertices++;
3063b7f5c055SJed Brown       count = 0;
30649566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
30659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3066b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3067b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3068b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3069b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3070b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3071b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3072b7f5c055SJed Brown 
3073b7f5c055SJed Brown               if (seen[vIdx]) {
3074b7f5c055SJed Brown                 PetscInt thisVert;
3075b7f5c055SJed Brown 
3076b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3077b7f5c055SJed Brown 
3078b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3079b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3080b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3081b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3082b7f5c055SJed Brown               }
3083b7f5c055SJed Brown             }
3084b7f5c055SJed Brown           }
3085b7f5c055SJed Brown         }
3086b7f5c055SJed Brown       }
3087b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3088b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3089ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3090b7f5c055SJed Brown         }
3091b7f5c055SJed Brown       }
30929566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
30939566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3094b7f5c055SJed Brown       cells_flat = cells[0][0];
3095b7f5c055SJed Brown       numEdges   = 0;
3096b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3097b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3098b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3099b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3100b7f5c055SJed Brown 
3101b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3102b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3103b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3104b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3105b7f5c055SJed Brown             }
3106b7f5c055SJed Brown           }
3107b7f5c055SJed Brown         }
3108b7f5c055SJed Brown       }
31099566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
31109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3111b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3112b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3113b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3114b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3115b7f5c055SJed Brown 
3116b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3117b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3118b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3119b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3120b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3121b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3122b7f5c055SJed Brown               }
3123b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3124b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3125b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3126b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3127b7f5c055SJed Brown               }
3128b7f5c055SJed Brown             }
3129b7f5c055SJed Brown           }
3130b7f5c055SJed Brown         }
3131b7f5c055SJed Brown       }
3132b7f5c055SJed Brown     }
3133b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
31344663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3135b7f5c055SJed Brown     break;
3136b7f5c055SJed Brown   }
3137b7f5c055SJed Brown 
31389566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3139c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
31409566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
31419566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3142b7f5c055SJed Brown   {
3143b7f5c055SJed Brown     DM idm;
31449566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
314569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3146b7f5c055SJed Brown   }
3147c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
31489566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
31499566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3150b7f5c055SJed Brown 
31519566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
31529566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3153b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3154b7f5c055SJed Brown     PetscInt        njoin;
3155b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
31569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
315763a3b9bcSJacob 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]);
31589566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
31599566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3160b7f5c055SJed Brown   }
31619566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
31629566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
31631436d7faSJed Brown   if (tps_distribute) {
31641436d7faSJed Brown     DM               pdm = NULL;
31651436d7faSJed Brown     PetscPartitioner part;
31661436d7faSJed Brown 
31679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
31689566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
31699566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
317048a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
31711436d7faSJed Brown     // Do not auto-distribute again
31729566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
31731436d7faSJed Brown   }
3174b7f5c055SJed Brown 
31759566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3176b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3177b7f5c055SJed Brown     PetscInt     m;
3178b7f5c055SJed Brown     DM           dmf;
3179b7f5c055SJed Brown     Vec          X;
3180b7f5c055SJed Brown     PetscScalar *x;
31819566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
318269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3183b7f5c055SJed Brown 
31849566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
31859566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
31869566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
318748a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
31889566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3189b7f5c055SJed Brown   }
3190b7f5c055SJed Brown 
3191b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
31929566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
31939566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3194b7f5c055SJed Brown 
3195b7f5c055SJed Brown   if (thickness > 0) {
31964663dae6SJed Brown     DM              edm, cdm, ecdm;
31974663dae6SJed Brown     DMPlexTransform tr;
31984663dae6SJed Brown     const char     *prefix;
31994663dae6SJed Brown     PetscOptions    options;
32004663dae6SJed Brown     // Code from DMPlexExtrude
32014663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
32024663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
32034663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
32044663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
32054663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
32064663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
32074663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
32084663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
32094663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
32104663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
32114663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
32124663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
32134663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
32144663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
32154663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
32164663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
32174663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
32184663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
32194663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
32204663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
32214663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
32224663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
32234663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
32244663dae6SJed Brown     if (edm) {
32254663dae6SJed Brown       ((DM_Plex *)edm->data)->printFEM    = ((DM_Plex *)dm->data)->printFEM;
32264663dae6SJed Brown       ((DM_Plex *)edm->data)->printL2     = ((DM_Plex *)dm->data)->printL2;
3227f5867de0SMatthew G. Knepley       ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate;
32284663dae6SJed Brown     }
322969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3230b7f5c055SJed Brown   }
3231b7f5c055SJed Brown   PetscFunctionReturn(0);
3232b7f5c055SJed Brown }
3233b7f5c055SJed Brown 
3234b7f5c055SJed Brown /*@
3235b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3236b7f5c055SJed Brown 
3237b7f5c055SJed Brown   Collective
3238b7f5c055SJed Brown 
3239b7f5c055SJed Brown   Input Parameters:
3240a1cb98faSBarry Smith + comm   - The communicator for the `DM` object
3241b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
3242b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
3243b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
32441436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3245817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
32461436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
3247817da375SSatish Balay - thickness - Thickness in normal direction
3248b7f5c055SJed Brown 
3249b7f5c055SJed Brown   Output Parameter:
3250a1cb98faSBarry Smith . dm  - The `DM` object
3251a1cb98faSBarry Smith 
3252a1cb98faSBarry Smith   Level: beginner
3253b7f5c055SJed Brown 
3254b7f5c055SJed Brown   Notes:
3255b7f5c055SJed Brown   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is is the simplest member of the triply-periodic minimal surfaces.
3256b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
3257b7f5c055SJed Brown   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.
3258b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3259b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3260b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3261b7f5c055SJed Brown 
3262b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
3263b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
3264b7f5c055SJed Brown 
3265a1cb98faSBarry Smith   Developer Note:
3266b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3267b7f5c055SJed Brown 
3268a1cb98faSBarry Smith   References:
3269a1cb98faSBarry Smith . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017.
3270a1cb98faSBarry Smith     https://doi.org/10.1016/j.polymer.2017.11.049
3271b7f5c055SJed Brown 
3272a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3273b7f5c055SJed Brown @*/
3274d71ae5a4SJacob 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)
3275d71ae5a4SJacob Faibussowitsch {
3276b7f5c055SJed Brown   PetscFunctionBegin;
32779566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32789566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32799566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
3280b7f5c055SJed Brown   PetscFunctionReturn(0);
3281b7f5c055SJed Brown }
3282b7f5c055SJed Brown 
32839318fe57SMatthew G. Knepley /*@
32849318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
32859318fe57SMatthew G. Knepley 
32869318fe57SMatthew G. Knepley   Collective
32879318fe57SMatthew G. Knepley 
32889318fe57SMatthew G. Knepley   Input Parameters:
3289a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
32909318fe57SMatthew G. Knepley . dim     - The dimension
32919318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
32929318fe57SMatthew G. Knepley - R       - The radius
32939318fe57SMatthew G. Knepley 
32949318fe57SMatthew G. Knepley   Output Parameter:
3295a1cb98faSBarry Smith . dm  - The `DM` object
32969318fe57SMatthew G. Knepley 
32979318fe57SMatthew G. Knepley   Level: beginner
32989318fe57SMatthew G. Knepley 
3299a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
33009318fe57SMatthew G. Knepley @*/
3301d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
3302d71ae5a4SJacob Faibussowitsch {
33039318fe57SMatthew G. Knepley   PetscFunctionBegin;
33049318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
33059566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
33069566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
33079566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
33089318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
33099318fe57SMatthew G. Knepley }
33109318fe57SMatthew G. Knepley 
3311d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
3312d71ae5a4SJacob Faibussowitsch {
33139318fe57SMatthew G. Knepley   DM      sdm, vol;
33149318fe57SMatthew G. Knepley   DMLabel bdlabel;
33159318fe57SMatthew G. Knepley 
33169318fe57SMatthew G. Knepley   PetscFunctionBegin;
33179566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
33189566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
33199566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_"));
33209566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
33219566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
33229566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
33239566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
33249566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
332569d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
33269566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
33279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
33289566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
33299566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
333051a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
333151a74b61SMatthew G. Knepley }
333251a74b61SMatthew G. Knepley 
333351a74b61SMatthew G. Knepley /*@
333451a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
333551a74b61SMatthew G. Knepley 
333651a74b61SMatthew G. Knepley   Collective
333751a74b61SMatthew G. Knepley 
333851a74b61SMatthew G. Knepley   Input Parameters:
3339a1cb98faSBarry Smith + comm  - The communicator for the `DM` object
334051a74b61SMatthew G. Knepley . dim   - The dimension
334151a74b61SMatthew G. Knepley - R     - The radius
334251a74b61SMatthew G. Knepley 
334351a74b61SMatthew G. Knepley   Output Parameter:
3344a1cb98faSBarry Smith . dm  - The `DM` object
334551a74b61SMatthew G. Knepley 
3346a1cb98faSBarry Smith   Options Database Key:
334751a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
334851a74b61SMatthew G. Knepley 
334951a74b61SMatthew G. Knepley   Level: beginner
335051a74b61SMatthew G. Knepley 
3351a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
335251a74b61SMatthew G. Knepley @*/
3353d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
3354d71ae5a4SJacob Faibussowitsch {
335551a74b61SMatthew G. Knepley   PetscFunctionBegin;
33569566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
33579566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
33589566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
33592829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
33602829fed8SMatthew G. Knepley }
33612829fed8SMatthew G. Knepley 
3362d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
3363d71ae5a4SJacob Faibussowitsch {
33640a6ba040SMatthew G. Knepley   PetscFunctionBegin;
33659318fe57SMatthew G. Knepley   switch (ct) {
33669371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
33679318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
33689318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
33699318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
33709318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
33719318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
33729318fe57SMatthew G. Knepley 
33739566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
33749566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33759371c9d4SSatish Balay   } break;
33769371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
33779318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
33789318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
33799318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
33809318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
33819318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
33829318fe57SMatthew G. Knepley 
33839566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33849566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33859371c9d4SSatish Balay   } break;
33869371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3387b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3388b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3389b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3390b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3391b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3392b5a892a1SMatthew G. Knepley 
33939566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33949566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33959371c9d4SSatish Balay   } break;
33969371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
33979318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
33989318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
33999318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
34009318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
34019318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
34029318fe57SMatthew G. Knepley 
34039566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34049566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34059371c9d4SSatish Balay   } break;
34069371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
34079318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34089318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34099318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34109318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34119318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
34129318fe57SMatthew G. Knepley 
34139566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34149566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34159371c9d4SSatish Balay   } break;
34169371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
34179318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34189318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34199318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34209318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34219318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
34229318fe57SMatthew G. Knepley 
34239566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34249566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34259371c9d4SSatish Balay   } break;
34269371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
34279318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34289318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3429f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34309318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3431f0edb160SMatthew 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};
34329318fe57SMatthew G. Knepley 
34339566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34349566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34359371c9d4SSatish Balay   } break;
34369371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
34379318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34389318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3439f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34409318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34419371c9d4SSatish 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};
34429318fe57SMatthew G. Knepley 
34439566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34449566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34459371c9d4SSatish Balay   } break;
34469371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
34479318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34489318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3449f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34509318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34519371c9d4SSatish 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};
34529318fe57SMatthew G. Knepley 
34539566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34549566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34559371c9d4SSatish Balay   } break;
34569371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
34579318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34589318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
34599318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34609318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34619371c9d4SSatish 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};
34629318fe57SMatthew G. Knepley 
34639566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34649566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34659371c9d4SSatish Balay   } break;
34669371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
34679318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34689318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
34699318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34709318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34719371c9d4SSatish 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};
34729318fe57SMatthew G. Knepley 
34739566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34749566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34759371c9d4SSatish Balay   } break;
34769371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
34779318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
34789318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3479f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
34809318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34819371c9d4SSatish 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};
34829318fe57SMatthew G. Knepley 
34839566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34849566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34859371c9d4SSatish Balay   } break;
3486d71ae5a4SJacob Faibussowitsch   default:
3487d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
34889318fe57SMatthew G. Knepley   }
34899318fe57SMatthew G. Knepley   {
34909318fe57SMatthew G. Knepley     PetscInt Nv, v;
34919318fe57SMatthew G. Knepley 
34929318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
34939566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
34949566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
34959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
34969566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
34979318fe57SMatthew G. Knepley   }
34989566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
34999566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
35000a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
35010a6ba040SMatthew G. Knepley }
35020a6ba040SMatthew G. Knepley 
35039318fe57SMatthew G. Knepley /*@
3504a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
35059318fe57SMatthew G. Knepley 
35069318fe57SMatthew G. Knepley   Collective
35079318fe57SMatthew G. Knepley 
35089318fe57SMatthew G. Knepley   Input Parameters:
35099318fe57SMatthew G. Knepley + comm - The communicator
35109318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
35119318fe57SMatthew G. Knepley 
35129318fe57SMatthew G. Knepley   Output Parameter:
35139318fe57SMatthew G. Knepley . refdm - The reference cell
35149318fe57SMatthew G. Knepley 
35159318fe57SMatthew G. Knepley   Level: intermediate
35169318fe57SMatthew G. Knepley 
3517a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()`
35189318fe57SMatthew G. Knepley @*/
3519d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
3520d71ae5a4SJacob Faibussowitsch {
35210a6ba040SMatthew G. Knepley   PetscFunctionBegin;
35229566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
35239566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
35249566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
35259318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35269318fe57SMatthew G. Knepley }
352779a015ccSMatthew G. Knepley 
3528d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
3529d71ae5a4SJacob Faibussowitsch {
35309318fe57SMatthew G. Knepley   DM        plex;
35319318fe57SMatthew G. Knepley   DMLabel   label;
35329318fe57SMatthew G. Knepley   PetscBool hasLabel;
35330a6ba040SMatthew G. Knepley 
3534c22d3578SMatthew G. Knepley   PetscFunctionBegin;
35359566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
35369318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
35379566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
35389566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
35399566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
35409566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
35411c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
35429566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
35439318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35449318fe57SMatthew G. Knepley }
3545acdc6f61SToby Isaac 
3546669647acSMatthew G. Knepley /*
3547669647acSMatthew 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.
3548669647acSMatthew G. Knepley 
3549669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
3550669647acSMatthew G. Knepley */
3551d71ae5a4SJacob 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[])
3552d71ae5a4SJacob Faibussowitsch {
3553669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
3554669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
3555669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
3556669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
3557669647acSMatthew G. Knepley 
3558669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
3559669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
3560669647acSMatthew G. Knepley }
3561669647acSMatthew G. Knepley 
3562669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
35639318fe57SMatthew G. Knepley 
3564d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
3565d71ae5a4SJacob Faibussowitsch {
35669318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
35679318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
35689318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
35699318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3570cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
35719318fe57SMatthew G. Knepley   MPI_Comm       comm;
3572ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3573ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3574ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
35759318fe57SMatthew G. Knepley 
35769318fe57SMatthew G. Knepley   PetscFunctionBegin;
35779566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
35789318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
35799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
35809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
35819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
35829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
35839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
35849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
35859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
358663a3b9bcSJacob Faibussowitsch   PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim);
35879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
35889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
35899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
35909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
35919566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
35929318fe57SMatthew G. Knepley 
359361a622f3SMatthew G. Knepley   switch (cell) {
359461a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
359561a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
359661a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
359761a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
359861a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
359961a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
3600d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
3601d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
3602d71ae5a4SJacob Faibussowitsch     break;
3603d71ae5a4SJacob Faibussowitsch   default:
3604d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
3605d71ae5a4SJacob Faibussowitsch     break;
360661a622f3SMatthew G. Knepley   }
360761a622f3SMatthew G. Knepley 
36089318fe57SMatthew G. Knepley   if (fflg) {
36099318fe57SMatthew G. Knepley     DM dmnew;
36109318fe57SMatthew G. Knepley 
36119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew));
36125de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
361369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36149318fe57SMatthew G. Knepley   } else if (refDomain) {
36159566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
36169318fe57SMatthew G. Knepley   } else if (bdfflg) {
36179318fe57SMatthew G. Knepley     DM bdm, dmnew;
36189318fe57SMatthew G. Knepley 
36199566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm));
36209566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
36219566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
36229566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
36239566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
36245de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
362569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36269318fe57SMatthew G. Knepley   } else {
36279566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
36289318fe57SMatthew G. Knepley     switch (shape) {
3629669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
3630669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
36319318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
36329318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
36339318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
36349318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3635669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
36369318fe57SMatthew G. Knepley       PetscInt       i, n;
36379318fe57SMatthew G. Knepley 
36389318fe57SMatthew G. Knepley       n = dim;
36399318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
36409566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36419318fe57SMatthew G. Knepley       n = 3;
36429566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
364363a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36449318fe57SMatthew G. Knepley       n = 3;
36459566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
364663a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36479318fe57SMatthew G. Knepley       n = 3;
36489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
364963a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
3650669647acSMatthew G. Knepley 
3651669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
3652669647acSMatthew G. Knepley       if (isAnnular)
3653669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
3654669647acSMatthew G. Knepley 
36559318fe57SMatthew G. Knepley       switch (cell) {
365661a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
36579566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3658d410b0cfSMatthew G. Knepley         if (!interpolate) {
3659d410b0cfSMatthew G. Knepley           DM udm;
3660d410b0cfSMatthew G. Knepley 
36619566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
366269d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
3663d410b0cfSMatthew G. Knepley         }
36649318fe57SMatthew G. Knepley         break;
3665d71ae5a4SJacob Faibussowitsch       default:
3666d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate));
3667d71ae5a4SJacob Faibussowitsch         break;
36689318fe57SMatthew G. Knepley       }
3669669647acSMatthew G. Knepley       if (isAnnular) {
3670669647acSMatthew G. Knepley         DM          cdm;
3671669647acSMatthew G. Knepley         PetscDS     cds;
3672669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
3673669647acSMatthew G. Knepley 
3674669647acSMatthew G. Knepley         // Fix coordinates for annular region
3675669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
3676669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
3677669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
3678669647acSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL));
3679669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
3680669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
3681669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
3682669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
3683669647acSMatthew G. Knepley       }
36849371c9d4SSatish Balay     } break;
36859371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
36869318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
36879318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
36889318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
36899318fe57SMatthew G. Knepley       PetscInt  i, n;
36909318fe57SMatthew G. Knepley 
36919318fe57SMatthew G. Knepley       n = dim + 1;
36929318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
36939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36949318fe57SMatthew G. Knepley       n = 3;
36959566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
369663a3b9bcSJacob 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);
36979318fe57SMatthew G. Knepley       n = 3;
36989566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
369963a3b9bcSJacob 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);
37009566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
37019371c9d4SSatish Balay     } break;
37029371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
37039318fe57SMatthew G. Knepley       PetscReal R = 1.0;
37049318fe57SMatthew G. Knepley 
37059566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
37069566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
37079371c9d4SSatish Balay     } break;
37089371c9d4SSatish Balay     case DM_SHAPE_BALL: {
37099318fe57SMatthew G. Knepley       PetscReal R = 1.0;
37109318fe57SMatthew G. Knepley 
37119566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
37129566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
37139371c9d4SSatish Balay     } break;
37149371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
37159318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
37169318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
37179318fe57SMatthew G. Knepley 
37189566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
37199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
37209318fe57SMatthew G. Knepley       switch (cell) {
3721d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
3722d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
3723d71ae5a4SJacob Faibussowitsch         break;
3724d71ae5a4SJacob Faibussowitsch       default:
3725d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt));
3726d71ae5a4SJacob Faibussowitsch         break;
37279318fe57SMatthew G. Knepley       }
37289371c9d4SSatish Balay     } break;
3729b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
37309371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
3731b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
3732b7f5c055SJed Brown       PetscReal      thickness   = 0.;
3733b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3734b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
37351436d7faSJed Brown       PetscBool      tps_distribute;
37369566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
37379566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
37389566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
37399566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
37409566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
37419566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
37429566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
37439566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
37449371c9d4SSatish Balay     } break;
37459371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
374605bd46c0SStefano Zampini       DM        dmnew;
374705bd46c0SStefano Zampini       PetscReal rl = 0.0;
374805bd46c0SStefano Zampini 
374905bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
375005bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
37515de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
375269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
37539371c9d4SSatish Balay     } break;
3754d71ae5a4SJacob Faibussowitsch     default:
3755d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
37569318fe57SMatthew G. Knepley     }
37579318fe57SMatthew G. Knepley   }
37589566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
375948a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
37600a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
37610a6ba040SMatthew G. Knepley }
37620a6ba040SMatthew G. Knepley 
3763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3764d71ae5a4SJacob Faibussowitsch {
37650a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
37667f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
37679318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
37680a6ba040SMatthew G. Knepley 
37690a6ba040SMatthew G. Knepley   PetscFunctionBegin;
37700a6ba040SMatthew G. Knepley   /* Handle viewing */
37719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
37729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
37739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
37749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
3775f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
37769566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
37779566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
37789318fe57SMatthew G. Knepley   /* Labeling */
37799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
37809566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3781953fc75cSMatthew G. Knepley   /* Point Location */
37829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
37830848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
37849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
37852e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
37869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3787b29cfa1cSToby Isaac   /* Projection behavior */
3788d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
37899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3790f12cf164SMatthew G. Knepley   /* Checking structure */
3791f12cf164SMatthew G. Knepley   {
37927f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
3793f12cf164SMatthew G. Knepley 
37947f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
37957f9d8d6cSVaclav Hapla     if (all) {
37967f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
37977f9d8d6cSVaclav Hapla     } else {
37989566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
37997f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
38009566063dSJacob 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));
38017f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
38029566063dSJacob 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));
38037f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
38049566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
38057f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
38069566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
3807d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
38089566063dSJacob 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));
38097f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
38107f9d8d6cSVaclav Hapla     }
38119566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
38129566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3813f12cf164SMatthew G. Knepley   }
38149318fe57SMatthew G. Knepley   {
38159318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
38164f3833eaSMatthew G. Knepley 
38179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
38189318fe57SMatthew G. Knepley     if (flg) {
38199318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
38209318fe57SMatthew G. Knepley 
38219566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
38229566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
38239566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
38249566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
38259318fe57SMatthew G. Knepley     }
38269318fe57SMatthew G. Knepley   }
38279566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
382868d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
382968d4fef7SMatthew G. Knepley }
383068d4fef7SMatthew G. Knepley 
3831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
3832d71ae5a4SJacob Faibussowitsch {
3833c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
3834c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
3835c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
3836c506a872SMatthew G. Knepley   PetscBool flg;
3837c506a872SMatthew G. Knepley 
3838c506a872SMatthew G. Knepley   PetscFunctionBegin;
3839c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
3840c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
3841c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
3842c506a872SMatthew G. Knepley   if (numOvLabels) {
3843c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
3844c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
3845c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
3846c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
3847c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
3848c506a872SMatthew G. Knepley     }
3849c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
3850c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
3851c506a872SMatthew 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);
3852c506a872SMatthew G. Knepley 
3853c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
3854c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
3855c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
3856c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
3857c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
3858c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
3859c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
3860c506a872SMatthew G. Knepley     }
3861c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
3862c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
3863c506a872SMatthew 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);
3864c506a872SMatthew G. Knepley   }
3865c506a872SMatthew G. Knepley   PetscFunctionReturn(0);
3866c506a872SMatthew G. Knepley }
3867c506a872SMatthew G. Knepley 
3868d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3869d71ae5a4SJacob Faibussowitsch {
3870bdf63967SMatthew G. Knepley   PetscFunctionList        ordlist;
3871bdf63967SMatthew G. Knepley   char                     oname[256];
3872d410b0cfSMatthew G. Knepley   PetscReal                volume    = -1.0;
38739318fe57SMatthew G. Knepley   PetscInt                 prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3874e600fa54SMatthew G. Knepley   PetscBool                uniformOrig, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute, interpolate = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, ignoreModel = PETSC_FALSE, flg;
38756bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
387668d4fef7SMatthew G. Knepley 
387768d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3878d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
3879dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
38809318fe57SMatthew G. Knepley   /* Handle automatic creation */
38819566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
38826bc1bd01Sksagiyam   if (dim < 0) {
38836bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
38846bc1bd01Sksagiyam     created = PETSC_TRUE;
38856bc1bd01Sksagiyam   }
38866bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
3887d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
38889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3889d89e6e46SMatthew G. Knepley   if (flg) {
3890d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3891d89e6e46SMatthew G. Knepley 
38929566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
3893d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3894d89e6e46SMatthew G. Knepley       DM udm;
3895d89e6e46SMatthew G. Knepley 
38969566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
389769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
3898d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3899d89e6e46SMatthew G. Knepley       DM idm;
3900d89e6e46SMatthew G. Knepley 
39019566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
390269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
3903d89e6e46SMatthew G. Knepley     }
3904d89e6e46SMatthew G. Knepley   }
39059b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
39069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3907ad540459SPierre Jolivet   if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel;
39089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
39099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
39109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
39119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
39129566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
39139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
39149318fe57SMatthew G. Knepley   if (flg) {
39159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
39169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
39179318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
39189318fe57SMatthew G. Knepley   }
39199b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
39209b44eab4SMatthew G. Knepley     DM             rdm;
39219b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
39229b44eab4SMatthew G. Knepley 
3923dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39249566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
392569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
3926dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
392761a622f3SMatthew G. Knepley     if (coordFunc && remap) {
39289566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
39299b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
39309b44eab4SMatthew G. Knepley     }
39319b44eab4SMatthew G. Knepley   }
39329566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
39339318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
39349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
39359318fe57SMatthew G. Knepley   if (extLayers) {
39369318fe57SMatthew G. Knepley     DM edm;
39379318fe57SMatthew G. Knepley 
39389566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
393969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
394048d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
3941dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3942d410b0cfSMatthew G. Knepley     extLayers = 0;
39435e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
39449318fe57SMatthew G. Knepley   }
3945bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
39466bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
39479566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
39486bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
39499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
39506bc1bd01Sksagiyam   if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) {
3951bdf63967SMatthew G. Knepley     DM pdm;
3952bdf63967SMatthew G. Knepley     IS perm;
3953bdf63967SMatthew G. Knepley 
39549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
39559566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
39569566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
395769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
3958dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3959bdf63967SMatthew G. Knepley   }
39609b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
39619566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
3962c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
3963dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
39649b44eab4SMatthew G. Knepley   if (distribute) {
39659b44eab4SMatthew G. Knepley     DM               pdm = NULL;
39669b44eab4SMatthew G. Knepley     PetscPartitioner part;
39679b44eab4SMatthew G. Knepley 
39689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
39699566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
39709566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm));
397148a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
39729b44eab4SMatthew G. Knepley   }
39739318fe57SMatthew G. Knepley   /* Create coordinate space */
39749318fe57SMatthew G. Knepley   if (created) {
397561a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
39769318fe57SMatthew G. Knepley     PetscInt  degree = 1;
3977*5515ebd3SMatthew G. Knepley     PetscInt  height = 0;
3978*5515ebd3SMatthew G. Knepley     DM        cdm;
39796858538eSMatthew G. Knepley     PetscBool flg;
39809318fe57SMatthew G. Knepley 
39819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
39829566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
39839566063dSJacob Faibussowitsch     if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
3984*5515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
398561a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
398661a622f3SMatthew G. Knepley       PetscDS      cds;
398761a622f3SMatthew G. Knepley       PetscObject  obj;
398861a622f3SMatthew G. Knepley       PetscClassId id;
398961a622f3SMatthew G. Knepley 
39909566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
39919566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
39929566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
399361a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
399461a622f3SMatthew G. Knepley         PetscContainer dummy;
399561a622f3SMatthew G. Knepley 
39969566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
39979566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
39989566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
39999566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
40009566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
400161a622f3SMatthew G. Knepley       }
400261a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
400361a622f3SMatthew G. Knepley     }
40046858538eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg));
4005*5515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
4006*5515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
40079566063dSJacob Faibussowitsch     PetscCall(DMLocalizeCoordinates(dm));
40089318fe57SMatthew G. Knepley   }
400968d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
401061a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
40119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
40129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
40139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
40149566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
401568d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
4016acdc6f61SToby Isaac     DM *dms, coarseDM;
401768d4fef7SMatthew G. Knepley 
40189566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
40199566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
40209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
40219566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
402268d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
40239566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
402468d4fef7SMatthew G. Knepley     if (refine == 1) {
40259566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
40269566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
402768d4fef7SMatthew G. Knepley     } else {
40289566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
40299566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
40309566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
40319566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
403268d4fef7SMatthew G. Knepley     }
40339566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
40349566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
403568d4fef7SMatthew G. Knepley     /* Free DMs */
403668d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
4037dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40389566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
403968d4fef7SMatthew G. Knepley     }
40409566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
404168d4fef7SMatthew G. Knepley   } else {
404268d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
40439318fe57SMatthew G. Knepley       DM             rdm;
404451a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
404568d4fef7SMatthew G. Knepley 
4046dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40479566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
404868d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
404969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
4050dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
405161a622f3SMatthew G. Knepley       if (coordFunc && remap) {
40529566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
405351a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
405451a74b61SMatthew G. Knepley       }
405568d4fef7SMatthew G. Knepley     }
405668d4fef7SMatthew G. Knepley   }
40573cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
40589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
40599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
4060b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
4061b653a561SMatthew G. Knepley     DM *dms;
4062b653a561SMatthew G. Knepley 
40639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
40649566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
4065b653a561SMatthew G. Knepley     /* Free DMs */
4066b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
4067dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40689566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
4069b653a561SMatthew G. Knepley     }
40709566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
4071b653a561SMatthew G. Knepley   } else {
4072b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
40739318fe57SMatthew G. Knepley       DM             cdm;
40749318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
40753cf6fe12SMatthew G. Knepley 
4076dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40779566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
40783cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
407969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
4080dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40819318fe57SMatthew G. Knepley       if (coordFunc) {
40829566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
40839318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
40849318fe57SMatthew G. Knepley       }
40853cf6fe12SMatthew G. Knepley     }
4086b653a561SMatthew G. Knepley   }
4087909dfd52SMatthew G. Knepley   /* Handle ghost cells */
40889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
4089909dfd52SMatthew G. Knepley   if (ghostCells) {
4090909dfd52SMatthew G. Knepley     DM   gdm;
4091909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
4092909dfd52SMatthew G. Knepley 
4093909dfd52SMatthew G. Knepley     lname[0] = '\0';
40949566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
40959566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
409669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
4097909dfd52SMatthew G. Knepley   }
40986913077dSMatthew G. Knepley   /* Handle 1D order */
40996bc1bd01Sksagiyam   if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) {
41006913077dSMatthew G. Knepley     DM           cdm, rdm;
41016913077dSMatthew G. Knepley     PetscDS      cds;
41026913077dSMatthew G. Knepley     PetscObject  obj;
41036913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
41046913077dSMatthew G. Knepley     IS           perm;
41056bc1bd01Sksagiyam     PetscInt     Nf;
41066913077dSMatthew G. Knepley     PetscBool    distributed;
41076913077dSMatthew G. Knepley 
41089566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
41099566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
41109566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
41119566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
41126913077dSMatthew G. Knepley     if (Nf) {
41139566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
41149566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
41156913077dSMatthew G. Knepley     }
41166bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
41179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
41189566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
411969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
41209566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
41216913077dSMatthew G. Knepley     }
41226913077dSMatthew G. Knepley   }
41233cf6fe12SMatthew G. Knepley /* Handle */
4124dd4c3f67SMatthew G. Knepley non_refine:
4125dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4126d0609cedSBarry Smith   PetscOptionsHeadEnd();
41270a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
41280a6ba040SMatthew G. Knepley }
41290a6ba040SMatthew G. Knepley 
4130d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
4131d71ae5a4SJacob Faibussowitsch {
4132552f7358SJed Brown   PetscFunctionBegin;
41339566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
41349566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
41359566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
41369566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
41379566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
41389566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
4139552f7358SJed Brown   PetscFunctionReturn(0);
4140552f7358SJed Brown }
4141552f7358SJed Brown 
4142d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
4143d71ae5a4SJacob Faibussowitsch {
4144552f7358SJed Brown   PetscFunctionBegin;
41459566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
41469566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
41479566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
4148552f7358SJed Brown   PetscFunctionReturn(0);
4149552f7358SJed Brown }
4150552f7358SJed Brown 
4151d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4152d71ae5a4SJacob Faibussowitsch {
4153793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4154793f3fe5SMatthew G. Knepley 
4155793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
41569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4157793f3fe5SMatthew G. Knepley   if (depth == 1) {
41589566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
41599566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
41609566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
41619371c9d4SSatish Balay     else {
41629371c9d4SSatish Balay       *pStart = 0;
41639371c9d4SSatish Balay       *pEnd   = 0;
41649371c9d4SSatish Balay     }
4165793f3fe5SMatthew G. Knepley   } else {
41669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4167793f3fe5SMatthew G. Knepley   }
4168793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
4169793f3fe5SMatthew G. Knepley }
4170793f3fe5SMatthew G. Knepley 
4171d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
4172d71ae5a4SJacob Faibussowitsch {
4173502a2867SDave May   PetscSF            sf;
41740a19bb7dSprj-   PetscInt           niranks, njranks, n;
41750a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
41760a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4177502a2867SDave May 
41782f356facSMatthew G. Knepley   PetscFunctionBegin;
41799566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
41800a19bb7dSprj-   if (!data->neighbors) {
41819566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
41829566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
41839566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
41849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
41859566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
41869566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
41870a19bb7dSprj-     n = njranks + niranks;
41889566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
41890a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
41909566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
41910a19bb7dSprj-   }
41920a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
41930a19bb7dSprj-   if (ranks) {
41940a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
41950a19bb7dSprj-     else *ranks = NULL;
41960a19bb7dSprj-   }
4197502a2867SDave May   PetscFunctionReturn(0);
4198502a2867SDave May }
4199502a2867SDave May 
42001eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
42011eb70e55SToby Isaac 
4202d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
4203d71ae5a4SJacob Faibussowitsch {
4204552f7358SJed Brown   PetscFunctionBegin;
4205552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
42062c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
4207552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
420838221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
4209552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
42101bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
421166ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
4212552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
4213552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
4214184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
42150298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
4216552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
4217f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
42180a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
4219552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
4220bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
4221bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
4222b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
42235a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
4224552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
42250a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
42260a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
4227b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
4228d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
42290298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
42300298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
42310298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
42320298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
4233552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
4234552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
42352adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
4236793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
4237552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
42380709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
42390709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
4240bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
42418c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
4242ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
42430709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
4244b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
42452a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
424628d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
42479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
42489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
42499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
42509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
42519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
42529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
42539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
42546bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
42556bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
42569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
4257c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
4258c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
4259552f7358SJed Brown   PetscFunctionReturn(0);
4260552f7358SJed Brown }
4261552f7358SJed Brown 
4262d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
4263d71ae5a4SJacob Faibussowitsch {
426463a16f15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
426563a16f15SMatthew G. Knepley 
426663a16f15SMatthew G. Knepley   PetscFunctionBegin;
426763a16f15SMatthew G. Knepley   mesh->refct++;
426863a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
42699566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
42709566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
427163a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
427263a16f15SMatthew G. Knepley }
427363a16f15SMatthew G. Knepley 
42748818961aSMatthew G Knepley /*MC
4275a1cb98faSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
42768818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
42778818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
4278a1cb98faSBarry Smith                     ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
42798818961aSMatthew G Knepley 
4280e5893cccSMatthew G. Knepley   Options Database Keys:
4281250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
4282250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
4283250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
4284250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
4285250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
4286250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
4287250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
4288ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
4289f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
4290f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
4291d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
4292f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
4293250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
4294f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
4295f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
4296f12cf164SMatthew 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
4297f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
4298f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
4299e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
4300e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
4301e5893cccSMatthew G. Knepley 
43028818961aSMatthew G Knepley   Level: intermediate
43038818961aSMatthew G Knepley 
4304a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
43058818961aSMatthew G Knepley M*/
43068818961aSMatthew G Knepley 
4307d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
4308d71ae5a4SJacob Faibussowitsch {
4309552f7358SJed Brown   DM_Plex *mesh;
4310412e9a14SMatthew G. Knepley   PetscInt unit;
4311552f7358SJed Brown 
4312552f7358SJed Brown   PetscFunctionBegin;
4313552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
43144dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
4315552f7358SJed Brown   dm->data = mesh;
4316552f7358SJed Brown 
4317552f7358SJed Brown   mesh->refct = 1;
43189566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
43199566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
4320552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
4321552f7358SJed Brown   mesh->refinementLimit        = -1.0;
4322e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
43236bc1bd01Sksagiyam   mesh->reorderDefault         = DMPLEX_REORDER_DEFAULT_NOTSET;
43241d1f2f2aSksagiyam   mesh->distributionName       = NULL;
43257d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
43267d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
4327552f7358SJed Brown 
43289566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
43292e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
4330d9deefdfSMatthew G. Knepley 
43318865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
4332552f7358SJed Brown 
4333df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
4334ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
43356113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
4336552f7358SJed Brown 
43379566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
4338552f7358SJed Brown   PetscFunctionReturn(0);
4339552f7358SJed Brown }
4340552f7358SJed Brown 
4341552f7358SJed Brown /*@
4342a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
4343552f7358SJed Brown 
4344d083f849SBarry Smith   Collective
4345552f7358SJed Brown 
4346552f7358SJed Brown   Input Parameter:
4347a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
4348552f7358SJed Brown 
4349552f7358SJed Brown   Output Parameter:
4350a1cb98faSBarry Smith . mesh  - The `DMPLEX` object
4351552f7358SJed Brown 
4352552f7358SJed Brown   Level: beginner
4353552f7358SJed Brown 
4354a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`
4355552f7358SJed Brown @*/
4356d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
4357d71ae5a4SJacob Faibussowitsch {
4358552f7358SJed Brown   PetscFunctionBegin;
4359552f7358SJed Brown   PetscValidPointer(mesh, 2);
43609566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
43619566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
4362552f7358SJed Brown   PetscFunctionReturn(0);
4363552f7358SJed Brown }
4364552f7358SJed Brown 
4365b09969d6SVaclav Hapla /*@C
4366a1cb98faSBarry Smith   DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
4367a1cb98faSBarry Smith 
4368a1cb98faSBarry Smith   Collective on dm
4369b09969d6SVaclav Hapla 
4370b09969d6SVaclav Hapla   Input Parameters:
4371a1cb98faSBarry Smith + dm - The `DM`
4372b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4373a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
4374a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE`
4375b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
43765e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4377b09969d6SVaclav Hapla 
4378be8c289dSNicolas Barral   Output Parameters:
4379a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership
4380be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4381b09969d6SVaclav Hapla 
4382b09969d6SVaclav Hapla   Level: advanced
4383b09969d6SVaclav Hapla 
4384a1cb98faSBarry Smith   Notes:
4385a1cb98faSBarry Smith   Two triangles sharing a face
4386a1cb98faSBarry Smith .vb
4387a1cb98faSBarry Smith 
4388a1cb98faSBarry Smith         2
4389a1cb98faSBarry Smith       / | \
4390a1cb98faSBarry Smith      /  |  \
4391a1cb98faSBarry Smith     /   |   \
4392a1cb98faSBarry Smith    0  0 | 1  3
4393a1cb98faSBarry Smith     \   |   /
4394a1cb98faSBarry Smith      \  |  /
4395a1cb98faSBarry Smith       \ | /
4396a1cb98faSBarry Smith         1
4397a1cb98faSBarry Smith .ve
4398a1cb98faSBarry Smith would have input
4399a1cb98faSBarry Smith .vb
4400a1cb98faSBarry Smith   numCells = 2, numVertices = 4
4401a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
4402a1cb98faSBarry Smith .ve
4403a1cb98faSBarry Smith which would result in the `DMPLEX`
4404a1cb98faSBarry Smith .vb
4405a1cb98faSBarry Smith 
4406a1cb98faSBarry Smith         4
4407a1cb98faSBarry Smith       / | \
4408a1cb98faSBarry Smith      /  |  \
4409a1cb98faSBarry Smith     /   |   \
4410a1cb98faSBarry Smith    2  0 | 1  5
4411a1cb98faSBarry Smith     \   |   /
4412a1cb98faSBarry Smith      \  |  /
4413a1cb98faSBarry Smith       \ | /
4414a1cb98faSBarry Smith         3
4415a1cb98faSBarry Smith .ve
4416a1cb98faSBarry Smith 
4417a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
4418a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
4419a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
4420a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
4421a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
4422a1cb98faSBarry Smith 
4423a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
4424a1cb98faSBarry Smith 
4425a1cb98faSBarry Smith   Fortran Note:
4426a1cb98faSBarry Smith   Not currently supported in Fortran.
4427a1cb98faSBarry Smith 
4428a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
4429a1cb98faSBarry Smith           `PetscSF`
4430b09969d6SVaclav Hapla @*/
4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
4432d71ae5a4SJacob Faibussowitsch {
44332464107aSksagiyam   PetscSF     sfPoint;
44342464107aSksagiyam   PetscLayout layout;
443582fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
4436a47d0d45SMatthew G. Knepley 
4437a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
443825b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
44399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
444025b6865aSVaclav Hapla   /* Get/check global number of vertices */
444125b6865aSVaclav Hapla   {
444225b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
444325b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
444425b6865aSVaclav Hapla 
444525b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
444625b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
44479371c9d4SSatish Balay     for (i = 0; i < len; i++)
44489371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
444925b6865aSVaclav Hapla     ++NVerticesInCells;
44509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
445125b6865aSVaclav Hapla 
445225b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
44539371c9d4SSatish Balay     else
44549371c9d4SSatish 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);
445525b6865aSVaclav Hapla   }
44569079aca8SVaclav Hapla   /* Count locally unique vertices */
44579079aca8SVaclav Hapla   {
44589079aca8SVaclav Hapla     PetscHSetI vhash;
44599079aca8SVaclav Hapla     PetscInt   off = 0;
44609079aca8SVaclav Hapla 
44619566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
4462a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
446348a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
4464a47d0d45SMatthew G. Knepley     }
44659566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
44669566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
4467ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
44689566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
44699566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
447063a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
4471a47d0d45SMatthew G. Knepley   }
44729566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
4473a47d0d45SMatthew G. Knepley   /* Create cones */
44749566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
44759566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
44769566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
44779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4478a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
4479a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
4480a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
4481a47d0d45SMatthew G. Knepley       PetscInt       lv;
4482a47d0d45SMatthew G. Knepley 
44839079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
44849079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
44859566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
448663a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
4487961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
4488a47d0d45SMatthew G. Knepley     }
4489a47d0d45SMatthew G. Knepley   }
44902464107aSksagiyam   /* Build point sf */
44919566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
44929566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
44939566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
44949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44959566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
44969566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
44979566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
44989566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
44992464107aSksagiyam   if (dm->sf) {
45002464107aSksagiyam     const char *prefix;
45012464107aSksagiyam 
45029566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
45039566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
45042464107aSksagiyam   }
45059566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
45069566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
45079566063dSJacob Faibussowitsch   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4508a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
45099566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
45109566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
45119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4512a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4513a47d0d45SMatthew G. Knepley }
4514a47d0d45SMatthew G. Knepley 
4515b09969d6SVaclav Hapla /*@C
4516a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4517a1cb98faSBarry Smith 
4518a1cb98faSBarry Smith   Collective on dm
4519b09969d6SVaclav Hapla 
4520b09969d6SVaclav Hapla   Input Parameters:
4521a1cb98faSBarry Smith + dm - The `DM`
4522b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4523a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership
4524b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4525b09969d6SVaclav Hapla 
4526b09969d6SVaclav Hapla   Level: advanced
4527b09969d6SVaclav Hapla 
4528a1cb98faSBarry Smith   Fortran Note:
4529b09969d6SVaclav Hapla   Not currently supported in Fortran.
4530b09969d6SVaclav Hapla 
4531a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
4532b09969d6SVaclav Hapla @*/
4533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
4534d71ae5a4SJacob Faibussowitsch {
4535a47d0d45SMatthew G. Knepley   PetscSection coordSection;
4536a47d0d45SMatthew G. Knepley   Vec          coordinates;
4537a47d0d45SMatthew G. Knepley   PetscScalar *coords;
45381edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4539a47d0d45SMatthew G. Knepley 
4540a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
45429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
45431dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
45449566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
45459566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
45461dca8a05SBarry 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);
45479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
45489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
45499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
45509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
45511edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
45529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
45539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4554a47d0d45SMatthew G. Knepley   }
45559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
45569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
45579566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
45589566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
45599566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
45609566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
45619566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
45629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4563a47d0d45SMatthew G. Knepley   {
4564a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4565a47d0d45SMatthew G. Knepley 
4566a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
45679566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
45689566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
456921016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
457021016a8bSBarry Smith     {
457121016a8bSBarry Smith       PetscScalar *svertexCoords;
457221016a8bSBarry Smith       PetscInt     i;
45739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
45743612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
45759566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45769566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45779566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
457821016a8bSBarry Smith     }
457921016a8bSBarry Smith #else
45809566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
45819566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
458221016a8bSBarry Smith #endif
45839566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
4584a47d0d45SMatthew G. Knepley   }
45859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
45869566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
45879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
45889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4589a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4590a47d0d45SMatthew G. Knepley }
4591a47d0d45SMatthew G. Knepley 
4592c3edce3dSSatish Balay /*@
4593a1cb98faSBarry Smith   DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output)
4594a1cb98faSBarry Smith 
4595a1cb98faSBarry Smith   Collective
4596a47d0d45SMatthew G. Knepley 
4597a47d0d45SMatthew G. Knepley   Input Parameters:
4598a47d0d45SMatthew G. Knepley + comm - The communicator
4599a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4600a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
4601a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`
4602a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE`
4603a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4604a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4605a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4606a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4607a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4608a47d0d45SMatthew G. Knepley 
4609d8d19677SJose E. Roman   Output Parameters:
4610a1cb98faSBarry Smith + dm - The `DM`
4611a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership
4612be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4613a47d0d45SMatthew G. Knepley 
4614b09969d6SVaclav Hapla   Level: intermediate
4615a47d0d45SMatthew G. Knepley 
4616a1cb98faSBarry Smith   Notes:
4617a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
4618a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
4619a1cb98faSBarry Smith 
4620a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
4621a1cb98faSBarry Smith 
4622a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
4623a1cb98faSBarry Smith 
4624a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
4625a47d0d45SMatthew G. Knepley @*/
4626d71ae5a4SJacob 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)
4627d71ae5a4SJacob Faibussowitsch {
4628a47d0d45SMatthew G. Knepley   PetscSF sfVert;
4629a47d0d45SMatthew G. Knepley 
4630a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
46319566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
46329566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4633a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4634064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
46359566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
46369566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4637a47d0d45SMatthew G. Knepley   if (interpolate) {
46385fd9971aSMatthew G. Knepley     DM idm;
4639a47d0d45SMatthew G. Knepley 
46409566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
46419566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
4642a47d0d45SMatthew G. Knepley     *dm = idm;
4643a47d0d45SMatthew G. Knepley   }
46449566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
464518d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
46469566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
4647a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4648a47d0d45SMatthew G. Knepley }
4649a47d0d45SMatthew G. Knepley 
4650b09969d6SVaclav Hapla /*@C
4651a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
4652a1cb98faSBarry Smith 
4653a1cb98faSBarry Smith   Collective on dm
46549298eaa6SMatthew G Knepley 
46559298eaa6SMatthew G Knepley   Input Parameters:
4656a1cb98faSBarry Smith + dm - The `DM`
4657b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4658a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
46599298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
46605e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
46619298eaa6SMatthew G Knepley 
4662b09969d6SVaclav Hapla   Level: advanced
46639298eaa6SMatthew G Knepley 
4664b09969d6SVaclav Hapla   Notes:
4665b09969d6SVaclav Hapla   Two triangles sharing a face
4666a1cb98faSBarry Smith .vb
46679298eaa6SMatthew G Knepley 
4668a1cb98faSBarry Smith         2
4669a1cb98faSBarry Smith       / | \
4670a1cb98faSBarry Smith      /  |  \
4671a1cb98faSBarry Smith     /   |   \
4672a1cb98faSBarry Smith    0  0 | 1  3
4673a1cb98faSBarry Smith     \   |   /
4674a1cb98faSBarry Smith      \  |  /
4675a1cb98faSBarry Smith       \ | /
4676a1cb98faSBarry Smith         1
4677a1cb98faSBarry Smith .ve
4678a1cb98faSBarry Smith would have input
4679a1cb98faSBarry Smith .vb
4680a1cb98faSBarry Smith   numCells = 2, numVertices = 4
4681a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
4682a1cb98faSBarry Smith .ve
4683a1cb98faSBarry Smith which would result in the `DMPLEX`
4684a1cb98faSBarry Smith .vb
4685a1cb98faSBarry Smith 
4686a1cb98faSBarry Smith         4
4687a1cb98faSBarry Smith       / | \
4688a1cb98faSBarry Smith      /  |  \
4689a1cb98faSBarry Smith     /   |   \
4690a1cb98faSBarry Smith    2  0 | 1  5
4691a1cb98faSBarry Smith     \   |   /
4692a1cb98faSBarry Smith      \  |  /
4693a1cb98faSBarry Smith       \ | /
4694a1cb98faSBarry Smith         3
4695a1cb98faSBarry Smith .ve
4696a1cb98faSBarry Smith 
4697a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
469825b6865aSVaclav Hapla 
4699b09969d6SVaclav Hapla   Not currently supported in Fortran.
47009298eaa6SMatthew G Knepley 
4701a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
4702b09969d6SVaclav Hapla @*/
4703d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
4704d71ae5a4SJacob Faibussowitsch {
4705961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
4706b09969d6SVaclav Hapla 
4707b09969d6SVaclav Hapla   PetscFunctionBegin;
47089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
47099566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
471025b6865aSVaclav Hapla   /* Get/check global number of vertices */
471125b6865aSVaclav Hapla   {
471225b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
471325b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
471425b6865aSVaclav Hapla 
471525b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
471625b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
47179371c9d4SSatish Balay     for (i = 0; i < len; i++)
47189371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
471925b6865aSVaclav Hapla     ++NVerticesInCells;
472025b6865aSVaclav Hapla 
472125b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
47229371c9d4SSatish Balay     else
47239371c9d4SSatish 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);
472425b6865aSVaclav Hapla   }
47259566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
472648a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
47279566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
47289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4729b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4730ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
4731b09969d6SVaclav Hapla   }
47329566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
47339566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
47349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4735b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4736b09969d6SVaclav Hapla }
4737b09969d6SVaclav Hapla 
4738b09969d6SVaclav Hapla /*@C
4739a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4740a1cb98faSBarry Smith 
4741a1cb98faSBarry Smith   Collective on dm
4742b09969d6SVaclav Hapla 
4743b09969d6SVaclav Hapla   Input Parameters:
4744a1cb98faSBarry Smith + dm - The `DM`
4745b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4746b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4747b09969d6SVaclav Hapla 
4748b09969d6SVaclav Hapla   Level: advanced
4749b09969d6SVaclav Hapla 
4750a1cb98faSBarry Smith   Fortran Note:
4751b09969d6SVaclav Hapla   Not currently supported in Fortran.
4752b09969d6SVaclav Hapla 
4753a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
4754b09969d6SVaclav Hapla @*/
4755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
4756d71ae5a4SJacob Faibussowitsch {
4757b09969d6SVaclav Hapla   PetscSection coordSection;
4758b09969d6SVaclav Hapla   Vec          coordinates;
4759b09969d6SVaclav Hapla   DM           cdm;
4760b09969d6SVaclav Hapla   PetscScalar *coords;
47611edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
4762b09969d6SVaclav Hapla 
4763b09969d6SVaclav Hapla   PetscFunctionBegin;
47649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
47659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
47661dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
47679566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
47689566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
47699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
47709566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
47719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
47721edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
47739566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
47749566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4775b09969d6SVaclav Hapla   }
47769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4777b09969d6SVaclav Hapla 
47789566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
47799566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
47809566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
47819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
47829566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
47831edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
4784ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
4785b09969d6SVaclav Hapla   }
47869566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
47879566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
47889566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
47899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4790b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4791b09969d6SVaclav Hapla }
4792b09969d6SVaclav Hapla 
4793b09969d6SVaclav Hapla /*@
4794a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
47953df08285SMatthew G. Knepley 
4796a1cb98faSBarry Smith   Collective
4797b09969d6SVaclav Hapla 
4798b09969d6SVaclav Hapla   Input Parameters:
4799b09969d6SVaclav Hapla + comm - The communicator
4800b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
48013df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
4802a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
48033df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4804b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
48053df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4806b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
48073df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4808b09969d6SVaclav Hapla 
4809b09969d6SVaclav Hapla   Output Parameter:
4810a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
481125b6865aSVaclav Hapla 
4812b09969d6SVaclav Hapla   Level: intermediate
4813b09969d6SVaclav Hapla 
4814a1cb98faSBarry Smith   Notes:
4815a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
4816a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
4817a1cb98faSBarry Smith 
4818a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
4819a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
4820a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
4821a1cb98faSBarry Smith 
4822a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
48239298eaa6SMatthew G Knepley @*/
4824d71ae5a4SJacob 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)
4825d71ae5a4SJacob Faibussowitsch {
48263df08285SMatthew G. Knepley   PetscMPIInt rank;
48279298eaa6SMatthew G Knepley 
48289298eaa6SMatthew G Knepley   PetscFunctionBegin;
482928b400f6SJacob 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.");
48309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
48319566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
48329566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
48339566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
4834c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
48359566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
48369298eaa6SMatthew G Knepley   if (interpolate) {
48375fd9971aSMatthew G. Knepley     DM idm;
48389298eaa6SMatthew G Knepley 
48399566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
48409566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
48419298eaa6SMatthew G Knepley     *dm = idm;
48429298eaa6SMatthew G Knepley   }
4843c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
48449566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
48459298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
48469298eaa6SMatthew G Knepley }
48479298eaa6SMatthew G Knepley 
4848939f6067SMatthew G. Knepley /*@
4849939f6067SMatthew G. Knepley   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a DM
4850939f6067SMatthew G. Knepley 
4851939f6067SMatthew G. Knepley   Input Parameters:
4852c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4853939f6067SMatthew G. Knepley . depth - The depth of the DAG
4854367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4855939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4856939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4857939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4858367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4859939f6067SMatthew G. Knepley 
4860939f6067SMatthew G. Knepley   Output Parameter:
4861939f6067SMatthew G. Knepley . dm - The DM
4862939f6067SMatthew G. Knepley 
4863a1cb98faSBarry Smith   Note:
4864a1cb98faSBarry Smith   Two triangles sharing a face would have input
4865a1cb98faSBarry Smith .vb
4866a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4867a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4868a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4869a1cb98faSBarry Smith .ve
4870939f6067SMatthew G. Knepley which would result in the DMPlex
4871a1cb98faSBarry Smith .vb
4872a1cb98faSBarry Smith         4
4873a1cb98faSBarry Smith       / | \
4874a1cb98faSBarry Smith      /  |  \
4875a1cb98faSBarry Smith     /   |   \
4876a1cb98faSBarry Smith    2  0 | 1  5
4877a1cb98faSBarry Smith     \   |   /
4878a1cb98faSBarry Smith      \  |  /
4879a1cb98faSBarry Smith       \ | /
4880a1cb98faSBarry Smith         3
4881a1cb98faSBarry Smith .ve
4882a1cb98faSBarry Smith  Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
4883939f6067SMatthew G. Knepley 
4884939f6067SMatthew G. Knepley   Level: advanced
4885939f6067SMatthew G. Knepley 
4886a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
4887939f6067SMatthew G. Knepley @*/
4888d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
4889d71ae5a4SJacob Faibussowitsch {
48909298eaa6SMatthew G Knepley   Vec          coordinates;
48919298eaa6SMatthew G Knepley   PetscSection coordSection;
48929298eaa6SMatthew G Knepley   PetscScalar *coords;
4893811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
48949298eaa6SMatthew G Knepley 
48959298eaa6SMatthew G Knepley   PetscFunctionBegin;
48969566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
48979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
489863a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
48999298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
49009566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
49019298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
49029566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
4903ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
490497e052ccSToby Isaac   }
49051dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
49069566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
49079298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
49089566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
49099566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
49109298eaa6SMatthew G Knepley   }
49119566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
49129566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
49139298eaa6SMatthew G Knepley   /* Build coordinates */
49149566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
49159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
49169566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
49179566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
49189298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
49199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
49209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
49219298eaa6SMatthew G Knepley   }
49229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
49239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
49249566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
49259566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
49269566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
49279566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
49289566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
49299318fe57SMatthew G. Knepley   if (vertexCoords) {
49309566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
49319298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
49329298eaa6SMatthew G Knepley       PetscInt off;
49339298eaa6SMatthew G Knepley 
49349566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
4935ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
49369298eaa6SMatthew G Knepley     }
49379318fe57SMatthew G. Knepley   }
49389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
49399566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
49409566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
49419298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
49429298eaa6SMatthew G Knepley }
49438415267dSToby Isaac 
4944ca522641SMatthew G. Knepley /*@C
4945a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
4946a1cb98faSBarry Smith 
4947a1cb98faSBarry Smith   Collective
49488ca92349SMatthew G. Knepley 
49498ca92349SMatthew G. Knepley + comm        - The MPI communicator
49508ca92349SMatthew G. Knepley . filename    - Name of the .dat file
49518ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
49528ca92349SMatthew G. Knepley 
49538ca92349SMatthew G. Knepley   Output Parameter:
4954a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
49558ca92349SMatthew G. Knepley 
49568ca92349SMatthew G. Knepley   Level: beginner
49578ca92349SMatthew G. Knepley 
4958a1cb98faSBarry Smith   Note:
4959a1cb98faSBarry Smith   The format is the simplest possible:
4960a1cb98faSBarry Smith .vb
4961a1cb98faSBarry Smith   Ne
4962a1cb98faSBarry Smith   v0 v1 ... vk
4963a1cb98faSBarry Smith   Nv
4964a1cb98faSBarry Smith   x y z marker
4965a1cb98faSBarry Smith .ve
4966a1cb98faSBarry Smith 
4967a1cb98faSBarry Smith   Developer Note:
4968a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
4969a1cb98faSBarry Smith 
4970a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
49718ca92349SMatthew G. Knepley @*/
4972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
4973d71ae5a4SJacob Faibussowitsch {
49748ca92349SMatthew G. Knepley   DMLabel      marker;
49758ca92349SMatthew G. Knepley   PetscViewer  viewer;
49768ca92349SMatthew G. Knepley   Vec          coordinates;
49778ca92349SMatthew G. Knepley   PetscSection coordSection;
49788ca92349SMatthew G. Knepley   PetscScalar *coords;
49798ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
49808ca92349SMatthew G. Knepley   PetscInt     dim = 3, cdim = 3, coordSize, v, c, d;
49818ca92349SMatthew G. Knepley   PetscMPIInt  rank;
4982f8d5e320SMatthew G. Knepley   int          snum, Nv, Nc, Ncn, Nl;
49838ca92349SMatthew G. Knepley 
49848ca92349SMatthew G. Knepley   PetscFunctionBegin;
49859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
49869566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
49879566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
49889566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
49899566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
4990dd400576SPatrick Sanan   if (rank == 0) {
49919566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4992f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
499308401ef6SPierre Jolivet     PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
499425ce1634SJed Brown   } else {
4995f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
49968ca92349SMatthew G. Knepley   }
49979566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
49989566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
49999566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
50009566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
50019566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
50028ca92349SMatthew G. Knepley   /* Read topology */
5003dd400576SPatrick Sanan   if (rank == 0) {
5004f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
5005f8d5e320SMatthew G. Knepley     PetscInt cone[8];
50068ca92349SMatthew G. Knepley     int      vbuf[8], v;
50078ca92349SMatthew G. Knepley 
50089371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
50099371c9d4SSatish Balay       format[c * 3 + 0] = '%';
50109371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
50119371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
50129371c9d4SSatish Balay     }
5013f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
50149566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
50159566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
50168ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
50179566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
5018f8d5e320SMatthew G. Knepley       switch (Ncn) {
5019d71ae5a4SJacob Faibussowitsch       case 2:
5020d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
5021d71ae5a4SJacob Faibussowitsch         break;
5022d71ae5a4SJacob Faibussowitsch       case 3:
5023d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
5024d71ae5a4SJacob Faibussowitsch         break;
5025d71ae5a4SJacob Faibussowitsch       case 4:
5026d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
5027d71ae5a4SJacob Faibussowitsch         break;
5028d71ae5a4SJacob Faibussowitsch       case 6:
5029d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
5030d71ae5a4SJacob Faibussowitsch         break;
5031d71ae5a4SJacob Faibussowitsch       case 8:
5032d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
5033d71ae5a4SJacob Faibussowitsch         break;
5034d71ae5a4SJacob Faibussowitsch       default:
5035d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
5036f8d5e320SMatthew G. Knepley       }
503708401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5038f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
50398ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
5040f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
50418ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
50428ca92349SMatthew G. Knepley         cone[1]      = cone[3];
50438ca92349SMatthew G. Knepley         cone[3]      = tmp;
50448ca92349SMatthew G. Knepley       }
50459566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
50468ca92349SMatthew G. Knepley     }
50478ca92349SMatthew G. Knepley   }
50489566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
50499566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
50508ca92349SMatthew G. Knepley   /* Read coordinates */
50519566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
50529566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
50539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
50549566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
50558ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
50569566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
50579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
50588ca92349SMatthew G. Knepley   }
50599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
50609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
50619566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
50629566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
50639566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
50649566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
50659566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
50669566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5067dd400576SPatrick Sanan   if (rank == 0) {
5068f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
50698ca92349SMatthew G. Knepley     double x[3];
5070f8d5e320SMatthew G. Knepley     int    l, val[3];
50718ca92349SMatthew G. Knepley 
5072f8d5e320SMatthew G. Knepley     if (Nl) {
50739371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
50749371c9d4SSatish Balay         format[l * 3 + 0] = '%';
50759371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
50769371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
50779371c9d4SSatish Balay       }
5078f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
50799566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50809566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
5081f8d5e320SMatthew G. Knepley     }
50828ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
50839566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
5084f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
508508401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5086f8d5e320SMatthew G. Knepley       switch (Nl) {
5087d71ae5a4SJacob Faibussowitsch       case 0:
5088d71ae5a4SJacob Faibussowitsch         snum = 0;
5089d71ae5a4SJacob Faibussowitsch         break;
5090d71ae5a4SJacob Faibussowitsch       case 1:
5091d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
5092d71ae5a4SJacob Faibussowitsch         break;
5093d71ae5a4SJacob Faibussowitsch       case 2:
5094d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
5095d71ae5a4SJacob Faibussowitsch         break;
5096d71ae5a4SJacob Faibussowitsch       case 3:
5097d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
5098d71ae5a4SJacob Faibussowitsch         break;
5099d71ae5a4SJacob Faibussowitsch       default:
5100d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
5101f8d5e320SMatthew G. Knepley       }
510208401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
51038ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
51049566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
51058ca92349SMatthew G. Knepley     }
51068ca92349SMatthew G. Knepley   }
51079566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
51089566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
51099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
51109566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
51118ca92349SMatthew G. Knepley   if (interpolate) {
51128ca92349SMatthew G. Knepley     DM      idm;
51138ca92349SMatthew G. Knepley     DMLabel bdlabel;
51148ca92349SMatthew G. Knepley 
51159566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
51169566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
51178ca92349SMatthew G. Knepley     *dm = idm;
51188ca92349SMatthew G. Knepley 
5119f8d5e320SMatthew G. Knepley     if (!Nl) {
51209566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
51219566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
51229566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
51239566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
51248ca92349SMatthew G. Knepley     }
5125f8d5e320SMatthew G. Knepley   }
51268ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
51278ca92349SMatthew G. Knepley }
51288ca92349SMatthew G. Knepley 
51298ca92349SMatthew G. Knepley /*@C
5130a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
5131a1cb98faSBarry Smith 
5132a1cb98faSBarry Smith   Collective
5133ca522641SMatthew G. Knepley 
5134ca522641SMatthew G. Knepley   Input Parameters:
5135ca522641SMatthew G. Knepley + comm - The communicator
5136ca522641SMatthew G. Knepley . filename - A file name
5137a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
5138ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
5139ca522641SMatthew G. Knepley 
5140ca522641SMatthew G. Knepley   Output Parameter:
5141a1cb98faSBarry Smith . dm - The `DM`
5142ca522641SMatthew G. Knepley 
5143a1cb98faSBarry Smith   Options Database Key:
5144a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
514502ef0d99SVaclav Hapla 
5146bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
5147bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
5148bca97951SVaclav Hapla 
5149ca522641SMatthew G. Knepley   Level: beginner
5150ca522641SMatthew G. Knepley 
5151a1cb98faSBarry Smith   Notes:
5152a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
5153a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
5154a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
5155a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
5156a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
5157a1cb98faSBarry Smith 
5158a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
5159ca522641SMatthew G. Knepley @*/
5160d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
5161d71ae5a4SJacob Faibussowitsch {
5162ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
5163ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
5164ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
5165ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
5166ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
5167ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
5168ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
5169ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
5170ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
5171ef3a5affSJacob Faibussowitsch   const char  extMed[]       = ".med";
5172ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
5173ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
5174ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
5175ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
5176ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
5177ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
5178ca522641SMatthew G. Knepley   size_t      len;
5179c1cad2e7SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
5180ca522641SMatthew G. Knepley   PetscMPIInt rank;
5181ca522641SMatthew G. Knepley 
5182ca522641SMatthew G. Knepley   PetscFunctionBegin;
51835d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
51840d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
5185cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
51869566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
51879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
51889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
51899566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
519028b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
5191ef3a5affSJacob Faibussowitsch 
51929371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
51939371c9d4SSatish Balay   do { \
5194274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
5195274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
5196274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
5197274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
5198ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
5199ef3a5affSJacob Faibussowitsch     } else { \
5200274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
5201ef3a5affSJacob Faibussowitsch     } \
5202ef3a5affSJacob Faibussowitsch   } while (0)
5203ef3a5affSJacob Faibussowitsch 
5204ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
5205ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
5206ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
5207ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
5208ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
5209ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
5210ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
5211ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
5212ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
5213ef3a5affSJacob Faibussowitsch   CheckExtension(extMed, isMed);
5214ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
5215ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
5216ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
5217ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
5218ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
5219ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
5220ef3a5affSJacob Faibussowitsch 
5221ef3a5affSJacob Faibussowitsch #undef CheckExtension
5222ef3a5affSJacob Faibussowitsch 
5223de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
52249566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
5225ca522641SMatthew G. Knepley   } else if (isCGNS) {
52269566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
522790c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
52289566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
52292f0bd6dcSMichael Lange   } else if (isFluent) {
52309566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
5231cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
52329c48423bSVaclav Hapla     PetscBool   load_hdf5_xdmf = PETSC_FALSE;
5233cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
5234cc2f8f65SMatthew G. Knepley 
523543b242b4SVaclav 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 */
52369566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf));
52379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
52389566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
52399566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
52409566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
52419566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
52429566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
52439566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
5244cd7e8a5eSksagiyam 
52459566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
52469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52479566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
52489566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
52499566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
52509566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer));
52519566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
52525fd9971aSMatthew G. Knepley 
52535fd9971aSMatthew G. Knepley     if (interpolate) {
52545fd9971aSMatthew G. Knepley       DM idm;
52555fd9971aSMatthew G. Knepley 
52569566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
52579566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52585fd9971aSMatthew G. Knepley       *dm = idm;
52595fd9971aSMatthew G. Knepley     }
5260707dd687SMichael Lange   } else if (isMed) {
52619566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
5262f2801cd6SMatthew G. Knepley   } else if (isPLY) {
52639566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
5264c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
52659566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
52669566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
52677bee2925SMatthew Knepley     if (!interpolate) {
52687bee2925SMatthew Knepley       DM udm;
52697bee2925SMatthew Knepley 
52709566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
52719566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52727bee2925SMatthew Knepley       *dm = udm;
52737bee2925SMatthew Knepley     }
52748ca92349SMatthew G. Knepley   } else if (isCV) {
52759566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
527698921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
52779566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
52789566063dSJacob Faibussowitsch   if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52799566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
5280ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
5281ca522641SMatthew G. Knepley }
52829f6c5813SMatthew G. Knepley /*@C
52839f6c5813SMatthew 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.
52849f6c5813SMatthew G. Knepley 
52859f6c5813SMatthew G. Knepley   Input Parameter:
52869f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform`
52879f6c5813SMatthew G. Knepley 
52889f6c5813SMatthew G. Knepley   Output Parameter:
52899f6c5813SMatthew G. Knepley . dm - The `DM`
52909f6c5813SMatthew G. Knepley 
52919f6c5813SMatthew G. Knepley   Notes:
52929f6c5813SMatthew G. Knepley   An emphemeral mesh is one that is not stored concretely, as in the default Plex implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh.
52939f6c5813SMatthew G. Knepley 
52949f6c5813SMatthew G. Knepley   Level: beginner
52959f6c5813SMatthew G. Knepley 
52969f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
52979f6c5813SMatthew G. Knepley @*/
52989f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm)
52999f6c5813SMatthew G. Knepley {
53009f6c5813SMatthew G. Knepley   DM       bdm;
53019f6c5813SMatthew G. Knepley   PetscInt Nl;
53029f6c5813SMatthew G. Knepley 
53039f6c5813SMatthew G. Knepley   PetscFunctionBegin;
53049f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
53059f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
53069f6c5813SMatthew G. Knepley   PetscCall(DMSetFromOptions(*dm));
53079f6c5813SMatthew G. Knepley 
53089f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
53099f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
53109f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
53119f6c5813SMatthew G. Knepley 
53129f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformGetDM(tr, &bdm));
53139f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
53149f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
53159f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
53169f6c5813SMatthew G. Knepley     const char *lname;
53179f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
53189f6c5813SMatthew G. Knepley 
53199f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
53209f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
53219f6c5813SMatthew G. Knepley     if (isDepth) continue;
53229f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
53239f6c5813SMatthew G. Knepley     if (isCellType) continue;
53249f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
53259f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
53269f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
53279f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
53289f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
53299f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
53309f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
53319f6c5813SMatthew G. Knepley   }
53329f6c5813SMatthew G. Knepley   PetscFunctionReturn(0);
53339f6c5813SMatthew G. Knepley }
5334