xref: /petsc/src/dm/impls/plex/plexcreate.c (revision dc431b0c622bfdd860e6d0069e70d6077e15ef43)
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 
1789318fe57SMatthew G. Knepley   Collective
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 
187db781477SPatrick Sanan .seealso: `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);
209*dc431b0cSMatthew 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 {
213*dc431b0cSMatthew G. Knepley       DMPolytopeType ct;
214*dc431b0cSMatthew G. Knepley       PetscInt       cStart, cEnd, ctTmp;
215*dc431b0cSMatthew G. Knepley 
216*dc431b0cSMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
217*dc431b0cSMatthew G. Knepley       // Want to match cell types
218*dc431b0cSMatthew G. Knepley       if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
219*dc431b0cSMatthew G. Knepley       else ct = DM_POLYTOPE_UNKNOWN;
220*dc431b0cSMatthew G. Knepley       ctTmp = (PetscInt)ct;
221*dc431b0cSMatthew G. Knepley       PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &ctTmp, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
222*dc431b0cSMatthew G. Knepley       ct = (DMPolytopeType)ctTmp;
223*dc431b0cSMatthew G. Knepley       // Work around current bug
224*dc431b0cSMatthew G. Knepley       if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) fe = NULL;
225*dc431b0cSMatthew G. Knepley       else PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
2264f9ab2b4SJed Brown     }
227*dc431b0cSMatthew 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:
2401df5d5c5SMatthew G. Knepley + 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:
2471df5d5c5SMatthew G. Knepley . dm - The DM object
2481df5d5c5SMatthew G. Knepley 
2491df5d5c5SMatthew G. Knepley   Level: beginner
2501df5d5c5SMatthew G. Knepley 
251db781477SPatrick Sanan .seealso: `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:
7299318fe57SMatthew G. Knepley + 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:
7379318fe57SMatthew G. Knepley . dm  - The DM object
7389318fe57SMatthew G. Knepley 
7399318fe57SMatthew G. Knepley   Level: beginner
7409318fe57SMatthew G. Knepley 
741db781477SPatrick Sanan .seealso: `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:
1311768d5fceSMatthew G. Knepley + comm        - The communicator for the DM object
1312768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1313768d5fceSMatthew G. Knepley . 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)
1317fdbf62faSLisandro Dalcin . 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:
1321768d5fceSMatthew G. Knepley . dm  - The DM object
1322768d5fceSMatthew G. Knepley 
13239318fe57SMatthew G. Knepley   Note: If you want to customize this mesh using options, you just need to
13249318fe57SMatthew G. Knepley $  DMCreate(comm, &dm);
13259318fe57SMatthew G. Knepley $  DMSetType(dm, DMPLEX);
13269318fe57SMatthew G. Knepley $  DMSetFromOptions(dm);
13279318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page.
13281367e252SJed Brown 
13291367e252SJed Brown   Here is the numbering returned for 2 faces in each direction for tensor cells:
1330768d5fceSMatthew G. Knepley $ 10---17---11---18----12
1331768d5fceSMatthew G. Knepley $  |         |         |
1332768d5fceSMatthew G. Knepley $  |         |         |
1333768d5fceSMatthew G. Knepley $ 20    2   22    3    24
1334768d5fceSMatthew G. Knepley $  |         |         |
1335768d5fceSMatthew G. Knepley $  |         |         |
1336768d5fceSMatthew G. Knepley $  7---15----8---16----9
1337768d5fceSMatthew G. Knepley $  |         |         |
1338768d5fceSMatthew G. Knepley $  |         |         |
1339768d5fceSMatthew G. Knepley $ 19    0   21    1   23
1340768d5fceSMatthew G. Knepley $  |         |         |
1341768d5fceSMatthew G. Knepley $  |         |         |
1342768d5fceSMatthew G. Knepley $  4---13----5---14----6
1343768d5fceSMatthew G. Knepley 
1344768d5fceSMatthew G. Knepley and for simplicial cells
1345768d5fceSMatthew G. Knepley 
1346768d5fceSMatthew G. Knepley $ 14----8---15----9----16
1347768d5fceSMatthew G. Knepley $  |\     5  |\      7 |
1348768d5fceSMatthew G. Knepley $  | \       | \       |
1349768d5fceSMatthew G. Knepley $ 13   2    14    3    15
1350768d5fceSMatthew G. Knepley $  | 4   \   | 6   \   |
1351768d5fceSMatthew G. Knepley $  |       \ |       \ |
1352768d5fceSMatthew G. Knepley $ 11----6---12----7----13
1353768d5fceSMatthew G. Knepley $  |\        |\        |
1354768d5fceSMatthew G. Knepley $  | \    1  | \     3 |
1355768d5fceSMatthew G. Knepley $ 10   0    11    1    12
1356768d5fceSMatthew G. Knepley $  | 0   \   | 2   \   |
1357768d5fceSMatthew G. Knepley $  |       \ |       \ |
1358768d5fceSMatthew G. Knepley $  8----4----9----5----10
1359768d5fceSMatthew G. Knepley 
1360768d5fceSMatthew G. Knepley   Level: beginner
1361768d5fceSMatthew G. Knepley 
1362db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1363768d5fceSMatthew G. Knepley @*/
1364d71ae5a4SJacob 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)
1365d71ae5a4SJacob Faibussowitsch {
13669318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1367fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1368fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1369fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1370552f7358SJed Brown 
1371768d5fceSMatthew G. Knepley   PetscFunctionBegin;
13729566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
13739566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
13749566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
13757ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
13769318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
13779318fe57SMatthew G. Knepley }
1378fdbf62faSLisandro Dalcin 
1379d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1380d71ae5a4SJacob Faibussowitsch {
13819318fe57SMatthew G. Knepley   DM       bdm, vol;
13829318fe57SMatthew G. Knepley   PetscInt i;
13839318fe57SMatthew G. Knepley 
13849318fe57SMatthew G. Knepley   PetscFunctionBegin;
138508401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
13869566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
13879566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
13889566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
13899566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
13909566063dSJacob Faibussowitsch   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
13919566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
139269d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
13939318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
13949318fe57SMatthew G. Knepley     Vec          v;
13959318fe57SMatthew G. Knepley     PetscScalar *x;
13969318fe57SMatthew G. Knepley     PetscInt     cDim, n;
13979318fe57SMatthew G. Knepley 
13989566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
13999566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
14009566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
14019566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
14029318fe57SMatthew G. Knepley     x += cDim;
14039318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
14049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
14059566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
14069318fe57SMatthew G. Knepley   }
1407552f7358SJed Brown   PetscFunctionReturn(0);
1408552f7358SJed Brown }
1409552f7358SJed Brown 
141000dabe28SStefano Zampini /*@
141100dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
141200dabe28SStefano Zampini 
1413d083f849SBarry Smith   Collective
141400dabe28SStefano Zampini 
141500dabe28SStefano Zampini   Input Parameters:
141600dabe28SStefano Zampini + comm        - The communicator for the DM object
141700dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
141800dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
141900dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
142000dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1421d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
142200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
142300dabe28SStefano Zampini 
142400dabe28SStefano Zampini   Output Parameter:
142500dabe28SStefano Zampini . dm  - The DM object
142600dabe28SStefano Zampini 
142700dabe28SStefano Zampini   Level: beginner
142800dabe28SStefano Zampini 
1429db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
143000dabe28SStefano Zampini @*/
1431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1432d71ae5a4SJacob Faibussowitsch {
14339318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
143400dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
143500dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
143600dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
143700dabe28SStefano Zampini 
143800dabe28SStefano Zampini   PetscFunctionBegin;
14399566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14409566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14419566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1442d410b0cfSMatthew G. Knepley   if (!interpolate) {
1443d410b0cfSMatthew G. Knepley     DM udm;
144400dabe28SStefano Zampini 
14459566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
144669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
144700dabe28SStefano Zampini   }
14487ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
144900dabe28SStefano Zampini   PetscFunctionReturn(0);
145000dabe28SStefano Zampini }
145100dabe28SStefano Zampini 
1452a9074c1eSMatthew G. Knepley /*@C
1453a9074c1eSMatthew G. Knepley   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database.
1454a9074c1eSMatthew G. Knepley 
1455d083f849SBarry Smith   Logically Collective on dm
1456a9074c1eSMatthew G. Knepley 
1457a9074c1eSMatthew G. Knepley   Input Parameters:
1458a9074c1eSMatthew G. Knepley + dm - the DM context
1459a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1460a9074c1eSMatthew G. Knepley 
1461a9074c1eSMatthew G. Knepley   Notes:
1462a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1463a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1464a9074c1eSMatthew G. Knepley 
1465a9074c1eSMatthew G. Knepley   Level: advanced
1466a9074c1eSMatthew G. Knepley 
1467db781477SPatrick Sanan .seealso: `SNESSetFromOptions()`
1468a9074c1eSMatthew G. Knepley @*/
1469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1470d71ae5a4SJacob Faibussowitsch {
1471a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1472a9074c1eSMatthew G. Knepley 
1473a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1474a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
14769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
1477a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1478a9074c1eSMatthew G. Knepley }
1479a9074c1eSMatthew G. Knepley 
14809318fe57SMatthew G. Knepley /* Remap geometry to cylinder
148161a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
148261a622f3SMatthew G. Knepley 
14839318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
14849318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
14859318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
14860510c589SMatthew G. Knepley 
14879318fe57SMatthew G. Knepley        phi     = arctan(y/x)
14889318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
14899318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
14900510c589SMatthew G. Knepley 
14919318fe57SMatthew G. Knepley      so we remap them using
14920510c589SMatthew G. Knepley 
14939318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
14949318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
14950510c589SMatthew G. Knepley 
14969318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
14979318fe57SMatthew G. Knepley */
1498d71ae5a4SJacob 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[])
1499d71ae5a4SJacob Faibussowitsch {
15009318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
15019318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
150222cc497dSMatthew G. Knepley 
15039318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
15049318fe57SMatthew G. Knepley     f0[0] = u[0];
15059318fe57SMatthew G. Knepley     f0[1] = u[1];
15069318fe57SMatthew G. Knepley   } else {
15079318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
15080510c589SMatthew G. Knepley 
15099318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
15109318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
15119318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
15129318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
15139318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
15149318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
15159318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
15169318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
15179318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
15189318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
15199318fe57SMatthew G. Knepley     } else {
15209318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
15219318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
15229318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
15239318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
15249318fe57SMatthew G. Knepley     }
15259318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
15269318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
15279318fe57SMatthew G. Knepley   }
15289318fe57SMatthew G. Knepley   f0[2] = u[2];
15299318fe57SMatthew G. Knepley }
15300510c589SMatthew G. Knepley 
1531d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ)
1532d71ae5a4SJacob Faibussowitsch {
15330510c589SMatthew G. Knepley   const PetscInt dim = 3;
15349318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1535d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
15360510c589SMatthew G. Knepley 
15370510c589SMatthew G. Knepley   PetscFunctionBegin;
15389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15399566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
15400510c589SMatthew G. Knepley   /* Create topology */
15410510c589SMatthew G. Knepley   {
15420510c589SMatthew G. Knepley     PetscInt cone[8], c;
15430510c589SMatthew G. Knepley 
1544dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1545dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1546006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1547ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1548dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1549006a8963SMatthew G. Knepley     }
15509566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
15519566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
15529566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1553dd400576SPatrick Sanan     if (rank == 0) {
1554006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
15559371c9d4SSatish Balay         cone[0] = 15;
15569371c9d4SSatish Balay         cone[1] = 18;
15579371c9d4SSatish Balay         cone[2] = 17;
15589371c9d4SSatish Balay         cone[3] = 16;
15599371c9d4SSatish Balay         cone[4] = 31;
15609371c9d4SSatish Balay         cone[5] = 32;
15619371c9d4SSatish Balay         cone[6] = 33;
15629371c9d4SSatish Balay         cone[7] = 34;
15639566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
15649371c9d4SSatish Balay         cone[0] = 16;
15659371c9d4SSatish Balay         cone[1] = 17;
15669371c9d4SSatish Balay         cone[2] = 24;
15679371c9d4SSatish Balay         cone[3] = 23;
15689371c9d4SSatish Balay         cone[4] = 32;
15699371c9d4SSatish Balay         cone[5] = 36;
15709371c9d4SSatish Balay         cone[6] = 37;
15719371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
15729566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
15739371c9d4SSatish Balay         cone[0] = 18;
15749371c9d4SSatish Balay         cone[1] = 27;
15759371c9d4SSatish Balay         cone[2] = 24;
15769371c9d4SSatish Balay         cone[3] = 17;
15779371c9d4SSatish Balay         cone[4] = 34;
15789371c9d4SSatish Balay         cone[5] = 33;
15799371c9d4SSatish Balay         cone[6] = 37;
15809371c9d4SSatish Balay         cone[7] = 38;
15819566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
15829371c9d4SSatish Balay         cone[0] = 29;
15839371c9d4SSatish Balay         cone[1] = 27;
15849371c9d4SSatish Balay         cone[2] = 18;
15859371c9d4SSatish Balay         cone[3] = 15;
15869371c9d4SSatish Balay         cone[4] = 35;
15879371c9d4SSatish Balay         cone[5] = 31;
15889371c9d4SSatish Balay         cone[6] = 34;
15899371c9d4SSatish Balay         cone[7] = 38;
15909566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
15919371c9d4SSatish Balay         cone[0] = 29;
15929371c9d4SSatish Balay         cone[1] = 15;
15939371c9d4SSatish Balay         cone[2] = 16;
15949371c9d4SSatish Balay         cone[3] = 23;
15959371c9d4SSatish Balay         cone[4] = 35;
15969371c9d4SSatish Balay         cone[5] = 36;
15979371c9d4SSatish Balay         cone[6] = 32;
15989371c9d4SSatish Balay         cone[7] = 31;
15999566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1600006a8963SMatthew G. Knepley 
16019371c9d4SSatish Balay         cone[0] = 31;
16029371c9d4SSatish Balay         cone[1] = 34;
16039371c9d4SSatish Balay         cone[2] = 33;
16049371c9d4SSatish Balay         cone[3] = 32;
16059371c9d4SSatish Balay         cone[4] = 19;
16069371c9d4SSatish Balay         cone[5] = 22;
16079371c9d4SSatish Balay         cone[6] = 21;
16089371c9d4SSatish Balay         cone[7] = 20;
16099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
16109371c9d4SSatish Balay         cone[0] = 32;
16119371c9d4SSatish Balay         cone[1] = 33;
16129371c9d4SSatish Balay         cone[2] = 37;
16139371c9d4SSatish Balay         cone[3] = 36;
16149371c9d4SSatish Balay         cone[4] = 22;
16159371c9d4SSatish Balay         cone[5] = 25;
16169371c9d4SSatish Balay         cone[6] = 26;
16179371c9d4SSatish Balay         cone[7] = 21;
16189566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
16199371c9d4SSatish Balay         cone[0] = 34;
16209371c9d4SSatish Balay         cone[1] = 38;
16219371c9d4SSatish Balay         cone[2] = 37;
16229371c9d4SSatish Balay         cone[3] = 33;
16239371c9d4SSatish Balay         cone[4] = 20;
16249371c9d4SSatish Balay         cone[5] = 21;
16259371c9d4SSatish Balay         cone[6] = 26;
16269371c9d4SSatish Balay         cone[7] = 28;
16279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
16289371c9d4SSatish Balay         cone[0] = 35;
16299371c9d4SSatish Balay         cone[1] = 38;
16309371c9d4SSatish Balay         cone[2] = 34;
16319371c9d4SSatish Balay         cone[3] = 31;
16329371c9d4SSatish Balay         cone[4] = 30;
16339371c9d4SSatish Balay         cone[5] = 19;
16349371c9d4SSatish Balay         cone[6] = 20;
16359371c9d4SSatish Balay         cone[7] = 28;
16369566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
16379371c9d4SSatish Balay         cone[0] = 35;
16389371c9d4SSatish Balay         cone[1] = 31;
16399371c9d4SSatish Balay         cone[2] = 32;
16409371c9d4SSatish Balay         cone[3] = 36;
16419371c9d4SSatish Balay         cone[4] = 30;
16429371c9d4SSatish Balay         cone[5] = 25;
16439371c9d4SSatish Balay         cone[6] = 22;
16449371c9d4SSatish Balay         cone[7] = 19;
16459566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
1646ae8bcbbbSMatthew G. Knepley 
16479371c9d4SSatish Balay         cone[0] = 19;
16489371c9d4SSatish Balay         cone[1] = 20;
16499371c9d4SSatish Balay         cone[2] = 21;
16509371c9d4SSatish Balay         cone[3] = 22;
16519371c9d4SSatish Balay         cone[4] = 15;
16529371c9d4SSatish Balay         cone[5] = 16;
16539371c9d4SSatish Balay         cone[6] = 17;
16549371c9d4SSatish Balay         cone[7] = 18;
16559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
16569371c9d4SSatish Balay         cone[0] = 22;
16579371c9d4SSatish Balay         cone[1] = 21;
16589371c9d4SSatish Balay         cone[2] = 26;
16599371c9d4SSatish Balay         cone[3] = 25;
16609371c9d4SSatish Balay         cone[4] = 16;
16619371c9d4SSatish Balay         cone[5] = 23;
16629371c9d4SSatish Balay         cone[6] = 24;
16639371c9d4SSatish Balay         cone[7] = 17;
16649566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
16659371c9d4SSatish Balay         cone[0] = 20;
16669371c9d4SSatish Balay         cone[1] = 28;
16679371c9d4SSatish Balay         cone[2] = 26;
16689371c9d4SSatish Balay         cone[3] = 21;
16699371c9d4SSatish Balay         cone[4] = 18;
16709371c9d4SSatish Balay         cone[5] = 17;
16719371c9d4SSatish Balay         cone[6] = 24;
16729371c9d4SSatish Balay         cone[7] = 27;
16739566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
16749371c9d4SSatish Balay         cone[0] = 30;
16759371c9d4SSatish Balay         cone[1] = 28;
16769371c9d4SSatish Balay         cone[2] = 20;
16779371c9d4SSatish Balay         cone[3] = 19;
16789371c9d4SSatish Balay         cone[4] = 29;
16799371c9d4SSatish Balay         cone[5] = 15;
16809371c9d4SSatish Balay         cone[6] = 18;
16819371c9d4SSatish Balay         cone[7] = 27;
16829566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
16839371c9d4SSatish Balay         cone[0] = 30;
16849371c9d4SSatish Balay         cone[1] = 19;
16859371c9d4SSatish Balay         cone[2] = 22;
16869371c9d4SSatish Balay         cone[3] = 25;
16879371c9d4SSatish Balay         cone[4] = 29;
16889371c9d4SSatish Balay         cone[5] = 23;
16899371c9d4SSatish Balay         cone[6] = 16;
16909371c9d4SSatish Balay         cone[7] = 15;
16919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
1692006a8963SMatthew G. Knepley       } else {
16939371c9d4SSatish Balay         cone[0] = 5;
16949371c9d4SSatish Balay         cone[1] = 8;
16959371c9d4SSatish Balay         cone[2] = 7;
16969371c9d4SSatish Balay         cone[3] = 6;
16979371c9d4SSatish Balay         cone[4] = 9;
16989371c9d4SSatish Balay         cone[5] = 12;
16999371c9d4SSatish Balay         cone[6] = 11;
17009371c9d4SSatish Balay         cone[7] = 10;
17019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
17029371c9d4SSatish Balay         cone[0] = 6;
17039371c9d4SSatish Balay         cone[1] = 7;
17049371c9d4SSatish Balay         cone[2] = 14;
17059371c9d4SSatish Balay         cone[3] = 13;
17069371c9d4SSatish Balay         cone[4] = 12;
17079371c9d4SSatish Balay         cone[5] = 15;
17089371c9d4SSatish Balay         cone[6] = 16;
17099371c9d4SSatish Balay         cone[7] = 11;
17109566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
17119371c9d4SSatish Balay         cone[0] = 8;
17129371c9d4SSatish Balay         cone[1] = 17;
17139371c9d4SSatish Balay         cone[2] = 14;
17149371c9d4SSatish Balay         cone[3] = 7;
17159371c9d4SSatish Balay         cone[4] = 10;
17169371c9d4SSatish Balay         cone[5] = 11;
17179371c9d4SSatish Balay         cone[6] = 16;
17189371c9d4SSatish Balay         cone[7] = 18;
17199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
17209371c9d4SSatish Balay         cone[0] = 19;
17219371c9d4SSatish Balay         cone[1] = 17;
17229371c9d4SSatish Balay         cone[2] = 8;
17239371c9d4SSatish Balay         cone[3] = 5;
17249371c9d4SSatish Balay         cone[4] = 20;
17259371c9d4SSatish Balay         cone[5] = 9;
17269371c9d4SSatish Balay         cone[6] = 10;
17279371c9d4SSatish Balay         cone[7] = 18;
17289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
17299371c9d4SSatish Balay         cone[0] = 19;
17309371c9d4SSatish Balay         cone[1] = 5;
17319371c9d4SSatish Balay         cone[2] = 6;
17329371c9d4SSatish Balay         cone[3] = 13;
17339371c9d4SSatish Balay         cone[4] = 20;
17349371c9d4SSatish Balay         cone[5] = 15;
17359371c9d4SSatish Balay         cone[6] = 12;
17369371c9d4SSatish Balay         cone[7] = 9;
17379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1738006a8963SMatthew G. Knepley       }
1739d8c47e87SMatthew G. Knepley     }
17409566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
17419566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
17420510c589SMatthew G. Knepley   }
1743dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
17440510c589SMatthew G. Knepley   {
17450510c589SMatthew G. Knepley     Vec             coordinates;
17460510c589SMatthew G. Knepley     PetscSection    coordSection;
17470510c589SMatthew G. Knepley     PetscScalar    *coords;
17480510c589SMatthew G. Knepley     PetscInt        coordSize, v;
17490510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
17500510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
17510510c589SMatthew G. Knepley 
17520510c589SMatthew G. Knepley     /* Build coordinates */
17539566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
17549566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
17559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
17569566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
17570510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
17589566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
17599566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
17600510c589SMatthew G. Knepley     }
17619566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
17629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
17639566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
17649566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
17659566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
17669566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
17679566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
17689566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1769dd400576SPatrick Sanan     if (rank == 0) {
17709371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
17719371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
17729371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
17739371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
17749371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
17759371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
17769371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
17779371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
17789371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
17799371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
17809371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
17819371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
17829371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
17839371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
17849371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
17859371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
17869371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
17879371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
17889371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
17899371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
17909371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
17919371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
17929371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
17939371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
17949371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
17959371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
17969371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
17979371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
17989371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
17999371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
18009371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
18019371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
18029371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
18039371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
18049371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
18059371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
18069371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
18079371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
18089371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
18099371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
18109371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
18119371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
18129371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
18139371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
18149371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
18159371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
18169371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
18179371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
1818ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
18199371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
18209371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
18219371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
18229371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
18239371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
18249371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
18259371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
18269371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
18279371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
18289371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
18299371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
18309371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
18319371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
18329371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
18339371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
18349371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
18359371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
18369371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
18379371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
18389371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
18399371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
18409371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
18419371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
18429371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
1843ae8bcbbbSMatthew G. Knepley       }
1844d8c47e87SMatthew G. Knepley     }
18459566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18469566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18479566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18480510c589SMatthew G. Knepley   }
1849006a8963SMatthew G. Knepley   /* Create periodicity */
1850006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
18516858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
18526858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1853006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
1854ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
18556858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
1856006a8963SMatthew G. Knepley 
18576858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
18586858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
18594fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1860006a8963SMatthew G. Knepley   }
1861dbc1dc17SMatthew G. Knepley   {
18629318fe57SMatthew G. Knepley     DM          cdm;
18639318fe57SMatthew G. Knepley     PetscDS     cds;
18649318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1865dbc1dc17SMatthew G. Knepley 
18669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
18679566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
18689566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
18699566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
1870dbc1dc17SMatthew G. Knepley   }
18719318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
18729566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
18730510c589SMatthew G. Knepley   PetscFunctionReturn(0);
18740510c589SMatthew G. Knepley }
18750510c589SMatthew G. Knepley 
187624119c2aSMatthew G. Knepley /*@
18779318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
187824119c2aSMatthew G. Knepley 
1879d083f849SBarry Smith   Collective
188024119c2aSMatthew G. Knepley 
188124119c2aSMatthew G. Knepley   Input Parameters:
188224119c2aSMatthew G. Knepley + comm      - The communicator for the DM object
18839318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
188424119c2aSMatthew G. Knepley 
188524119c2aSMatthew G. Knepley   Output Parameter:
188624119c2aSMatthew G. Knepley . dm  - The DM object
188724119c2aSMatthew G. Knepley 
18889318fe57SMatthew G. Knepley   Note:
18899318fe57SMatthew G. Knepley   Here is the output numbering looking from the bottom of the cylinder:
18909318fe57SMatthew G. Knepley $       17-----14
18919318fe57SMatthew G. Knepley $        |     |
18929318fe57SMatthew G. Knepley $        |  2  |
18939318fe57SMatthew G. Knepley $        |     |
18949318fe57SMatthew G. Knepley $ 17-----8-----7-----14
18959318fe57SMatthew G. Knepley $  |     |     |     |
18969318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
18979318fe57SMatthew G. Knepley $  |     |     |     |
18989318fe57SMatthew G. Knepley $ 19-----5-----6-----13
18999318fe57SMatthew G. Knepley $        |     |
19009318fe57SMatthew G. Knepley $        |  4  |
19019318fe57SMatthew G. Knepley $        |     |
19029318fe57SMatthew G. Knepley $       19-----13
19039318fe57SMatthew G. Knepley $
19049318fe57SMatthew G. Knepley $ and up through the top
19059318fe57SMatthew G. Knepley $
19069318fe57SMatthew G. Knepley $       18-----16
19079318fe57SMatthew G. Knepley $        |     |
19089318fe57SMatthew G. Knepley $        |  2  |
19099318fe57SMatthew G. Knepley $        |     |
19109318fe57SMatthew G. Knepley $ 18----10----11-----16
19119318fe57SMatthew G. Knepley $  |     |     |     |
19129318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
19139318fe57SMatthew G. Knepley $  |     |     |     |
19149318fe57SMatthew G. Knepley $ 20-----9----12-----15
19159318fe57SMatthew G. Knepley $        |     |
19169318fe57SMatthew G. Knepley $        |  4  |
19179318fe57SMatthew G. Knepley $        |     |
19189318fe57SMatthew G. Knepley $       20-----15
19199318fe57SMatthew G. Knepley 
192024119c2aSMatthew G. Knepley   Level: beginner
192124119c2aSMatthew G. Knepley 
1922db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
192324119c2aSMatthew G. Knepley @*/
1924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm)
1925d71ae5a4SJacob Faibussowitsch {
19269318fe57SMatthew G. Knepley   PetscFunctionBegin;
19279318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
19289566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
19299566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
19309566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
19319318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
19329318fe57SMatthew G. Knepley }
19339318fe57SMatthew G. Knepley 
1934d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
1935d71ae5a4SJacob Faibussowitsch {
193624119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1937412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
19389fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
193924119c2aSMatthew G. Knepley 
194024119c2aSMatthew G. Knepley   PetscFunctionBegin;
194163a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
19429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
19439566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1944412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
19459566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
194624119c2aSMatthew G. Knepley   /* Create topology */
194724119c2aSMatthew G. Knepley   {
194824119c2aSMatthew G. Knepley     PetscInt cone[6], c;
194924119c2aSMatthew G. Knepley 
1950dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
1951dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
19529566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19539566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
19549566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
195524119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19569371c9d4SSatish Balay       cone[0] = c + n * 1;
19579371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
19589371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
19599371c9d4SSatish Balay       cone[3] = c + n * 2;
19609371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
19619371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
19629566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
19639566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
196424119c2aSMatthew G. Knepley     }
19659566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
19669566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
196724119c2aSMatthew G. Knepley   }
196848a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
196924119c2aSMatthew G. Knepley   /* Create cylinder geometry */
197024119c2aSMatthew G. Knepley   {
197124119c2aSMatthew G. Knepley     Vec          coordinates;
197224119c2aSMatthew G. Knepley     PetscSection coordSection;
197324119c2aSMatthew G. Knepley     PetscScalar *coords;
1974412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
197524119c2aSMatthew G. Knepley 
197624119c2aSMatthew G. Knepley     /* Build coordinates */
19779566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
19789566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
19799566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
19809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
198124119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
19829566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
19839566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
198424119c2aSMatthew G. Knepley     }
19859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
19869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
19879566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
19889566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
19899566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
19909566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
19919566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
19929566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
199324119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19949371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19959371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19969371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
19979371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19989371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19999371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
200024119c2aSMatthew G. Knepley     }
2001dd400576SPatrick Sanan     if (rank == 0) {
20029371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
20039371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
20049371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
20059371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
20069371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
20079371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
20089fe9f049SMatthew G. Knepley     }
20099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
20109566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
20119566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
201224119c2aSMatthew G. Knepley   }
20139318fe57SMatthew G. Knepley   /* Interpolate */
20149566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
20159318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
20169318fe57SMatthew G. Knepley }
20179318fe57SMatthew G. Knepley 
20189318fe57SMatthew G. Knepley /*@
20199318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
20209318fe57SMatthew G. Knepley 
20219318fe57SMatthew G. Knepley   Collective
20229318fe57SMatthew G. Knepley 
20239318fe57SMatthew G. Knepley   Input Parameters:
20249318fe57SMatthew G. Knepley + comm - The communicator for the DM object
20259318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
20269318fe57SMatthew G. Knepley - interpolate - Create edges and faces
20279318fe57SMatthew G. Knepley 
20289318fe57SMatthew G. Knepley   Output Parameter:
20299318fe57SMatthew G. Knepley . dm  - The DM object
20309318fe57SMatthew G. Knepley 
20319318fe57SMatthew G. Knepley   Level: beginner
20329318fe57SMatthew G. Knepley 
2033db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
20349318fe57SMatthew G. Knepley @*/
2035d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2036d71ae5a4SJacob Faibussowitsch {
20379318fe57SMatthew G. Knepley   PetscFunctionBegin;
20389318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
20399566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20409566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20419566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
204224119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
204324119c2aSMatthew G. Knepley }
204424119c2aSMatthew G. Knepley 
2045d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2046d71ae5a4SJacob Faibussowitsch {
204765a81367SMatthew G. Knepley   PetscReal prod = 0.0;
204865a81367SMatthew G. Knepley   PetscInt  i;
204965a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
205065a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
205165a81367SMatthew G. Knepley }
2052d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(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 += x[i] * y[i];
205765a81367SMatthew G. Knepley   return prod;
205865a81367SMatthew G. Knepley }
205965a81367SMatthew G. Knepley 
206051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2061d71ae5a4SJacob 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[])
2062d71ae5a4SJacob Faibussowitsch {
206351a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
206451a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
206551a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
206651a74b61SMatthew G. Knepley 
206751a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
206851a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
206951a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
207051a74b61SMatthew G. Knepley }
207151a74b61SMatthew G. Knepley 
2072d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2073d71ae5a4SJacob Faibussowitsch {
207465a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
207565a81367SMatthew G. Knepley   PetscSection   coordSection;
207665a81367SMatthew G. Knepley   Vec            coordinates;
207765a81367SMatthew G. Knepley   PetscScalar   *coords;
207865a81367SMatthew G. Knepley   PetscReal     *coordsIn;
2079064cae4fSPierre Jolivet   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e;
208065a81367SMatthew G. Knepley   PetscMPIInt    rank;
208165a81367SMatthew G. Knepley 
208265a81367SMatthew G. Knepley   PetscFunctionBegin;
20839318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
20849566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
20859566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
20869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
208765a81367SMatthew G. Knepley   switch (dim) {
208865a81367SMatthew G. Knepley   case 2:
208965a81367SMatthew G. Knepley     if (simplex) {
209051a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
209151a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
209265a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
209351a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
209465a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
209565a81367SMatthew G. Knepley       PetscInt        cone[3];
209665a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
209765a81367SMatthew G. Knepley 
20989371c9d4SSatish Balay       vertex[0] *= R / radius;
20999371c9d4SSatish Balay       vertex[1] *= R / radius;
21009371c9d4SSatish Balay       vertex[2] *= R / radius;
2101dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2102dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
210365a81367SMatthew G. Knepley       firstVertex = numCells;
210451a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
210565a81367SMatthew G. Knepley 
210665a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
210765a81367SMatthew G. Knepley 
210865a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
210951a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
211065a81367SMatthew G. Knepley       */
211165a81367SMatthew G. Knepley       /* Construct vertices */
21129566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2113dd400576SPatrick Sanan       if (rank == 0) {
211465a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
211565a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
211665a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
211765a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
211865a81367SMatthew G. Knepley               ++i;
211965a81367SMatthew G. Knepley             }
212065a81367SMatthew G. Knepley           }
212165a81367SMatthew G. Knepley         }
212245da822fSValeria Barra       }
212365a81367SMatthew G. Knepley       /* Construct graph */
21249566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
212565a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
212665a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
21279371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
21289371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
21299371c9d4SSatish Balay             ++k;
21309371c9d4SSatish Balay           }
213165a81367SMatthew G. Knepley         }
213263a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
213365a81367SMatthew G. Knepley       }
213465a81367SMatthew G. Knepley       /* Build Topology */
21359566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
213648a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
21379566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
213865a81367SMatthew G. Knepley       /* Cells */
213965a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
214065a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
214165a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
214265a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
21439371c9d4SSatish Balay               cone[0] = firstVertex + i;
21449371c9d4SSatish Balay               cone[1] = firstVertex + j;
21459371c9d4SSatish Balay               cone[2] = firstVertex + k;
214665a81367SMatthew G. Knepley               /* Check orientation */
214765a81367SMatthew G. Knepley               {
21489371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
21499371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
21509371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
21519371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
21529371c9d4SSatish Balay                 };
215365a81367SMatthew G. Knepley                 PetscReal normal[3];
215465a81367SMatthew G. Knepley                 PetscInt  e, f;
215565a81367SMatthew G. Knepley 
215665a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
215765a81367SMatthew G. Knepley                   normal[d] = 0.0;
215865a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
2159ad540459SPierre 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]);
216065a81367SMatthew G. Knepley                   }
216165a81367SMatthew G. Knepley                 }
21629371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
21639371c9d4SSatish Balay                   PetscInt tmp = cone[1];
21649371c9d4SSatish Balay                   cone[1]      = cone[2];
21659371c9d4SSatish Balay                   cone[2]      = tmp;
216665a81367SMatthew G. Knepley                 }
216765a81367SMatthew G. Knepley               }
21689566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
216965a81367SMatthew G. Knepley             }
217065a81367SMatthew G. Knepley           }
217165a81367SMatthew G. Knepley         }
217265a81367SMatthew G. Knepley       }
21739566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
21749566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
21759566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
217665a81367SMatthew G. Knepley     } else {
21772829fed8SMatthew G. Knepley       /*
21782829fed8SMatthew G. Knepley         12-21--13
21792829fed8SMatthew G. Knepley          |     |
21802829fed8SMatthew G. Knepley         25  4  24
21812829fed8SMatthew G. Knepley          |     |
21822829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
21832829fed8SMatthew G. Knepley    |     |     |     |
21842829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
21852829fed8SMatthew G. Knepley    |     |     |     |
21862829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
21872829fed8SMatthew G. Knepley          |     |
21882829fed8SMatthew G. Knepley         20  1  19
21892829fed8SMatthew G. Knepley          |     |
21902829fed8SMatthew G. Knepley         10-18--11
21912829fed8SMatthew G. Knepley          |     |
21922829fed8SMatthew G. Knepley         23  2  22
21932829fed8SMatthew G. Knepley          |     |
21942829fed8SMatthew G. Knepley         12-21--13
21952829fed8SMatthew G. Knepley        */
21962829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
21972829fed8SMatthew G. Knepley 
2198dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2199dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2200dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
220165a81367SMatthew G. Knepley       firstVertex = numCells;
220265a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
22032829fed8SMatthew G. Knepley       /* Build Topology */
22049566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
220548a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
220648a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
22079566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2208dd400576SPatrick Sanan       if (rank == 0) {
22092829fed8SMatthew G. Knepley         /* Cell 0 */
22109371c9d4SSatish Balay         cone[0] = 14;
22119371c9d4SSatish Balay         cone[1] = 15;
22129371c9d4SSatish Balay         cone[2] = 16;
22139371c9d4SSatish Balay         cone[3] = 17;
22149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
22159371c9d4SSatish Balay         ornt[0] = 0;
22169371c9d4SSatish Balay         ornt[1] = 0;
22179371c9d4SSatish Balay         ornt[2] = 0;
22189371c9d4SSatish Balay         ornt[3] = 0;
22199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
22202829fed8SMatthew G. Knepley         /* Cell 1 */
22219371c9d4SSatish Balay         cone[0] = 18;
22229371c9d4SSatish Balay         cone[1] = 19;
22239371c9d4SSatish Balay         cone[2] = 14;
22249371c9d4SSatish Balay         cone[3] = 20;
22259566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
22269371c9d4SSatish Balay         ornt[0] = 0;
22279371c9d4SSatish Balay         ornt[1] = 0;
22289371c9d4SSatish Balay         ornt[2] = -1;
22299371c9d4SSatish Balay         ornt[3] = 0;
22309566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
22312829fed8SMatthew G. Knepley         /* Cell 2 */
22329371c9d4SSatish Balay         cone[0] = 21;
22339371c9d4SSatish Balay         cone[1] = 22;
22349371c9d4SSatish Balay         cone[2] = 18;
22359371c9d4SSatish Balay         cone[3] = 23;
22369566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
22379371c9d4SSatish Balay         ornt[0] = 0;
22389371c9d4SSatish Balay         ornt[1] = 0;
22399371c9d4SSatish Balay         ornt[2] = -1;
22409371c9d4SSatish Balay         ornt[3] = 0;
22419566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
22422829fed8SMatthew G. Knepley         /* Cell 3 */
22439371c9d4SSatish Balay         cone[0] = 19;
22449371c9d4SSatish Balay         cone[1] = 22;
22459371c9d4SSatish Balay         cone[2] = 24;
22469371c9d4SSatish Balay         cone[3] = 15;
22479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
22489371c9d4SSatish Balay         ornt[0] = -1;
22499371c9d4SSatish Balay         ornt[1] = -1;
22509371c9d4SSatish Balay         ornt[2] = 0;
22519371c9d4SSatish Balay         ornt[3] = -1;
22529566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
22532829fed8SMatthew G. Knepley         /* Cell 4 */
22549371c9d4SSatish Balay         cone[0] = 16;
22559371c9d4SSatish Balay         cone[1] = 24;
22569371c9d4SSatish Balay         cone[2] = 21;
22579371c9d4SSatish Balay         cone[3] = 25;
22589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
22599371c9d4SSatish Balay         ornt[0] = -1;
22609371c9d4SSatish Balay         ornt[1] = -1;
22619371c9d4SSatish Balay         ornt[2] = -1;
22629371c9d4SSatish Balay         ornt[3] = 0;
22639566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
22642829fed8SMatthew G. Knepley         /* Cell 5 */
22659371c9d4SSatish Balay         cone[0] = 20;
22669371c9d4SSatish Balay         cone[1] = 17;
22679371c9d4SSatish Balay         cone[2] = 25;
22689371c9d4SSatish Balay         cone[3] = 23;
22699566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
22709371c9d4SSatish Balay         ornt[0] = -1;
22719371c9d4SSatish Balay         ornt[1] = -1;
22729371c9d4SSatish Balay         ornt[2] = -1;
22739371c9d4SSatish Balay         ornt[3] = -1;
22749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
22752829fed8SMatthew G. Knepley         /* Edges */
22769371c9d4SSatish Balay         cone[0] = 6;
22779371c9d4SSatish Balay         cone[1] = 7;
22789566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
22799371c9d4SSatish Balay         cone[0] = 7;
22809371c9d4SSatish Balay         cone[1] = 8;
22819566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
22829371c9d4SSatish Balay         cone[0] = 8;
22839371c9d4SSatish Balay         cone[1] = 9;
22849566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
22859371c9d4SSatish Balay         cone[0] = 9;
22869371c9d4SSatish Balay         cone[1] = 6;
22879566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
22889371c9d4SSatish Balay         cone[0] = 10;
22899371c9d4SSatish Balay         cone[1] = 11;
22909566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
22919371c9d4SSatish Balay         cone[0] = 11;
22929371c9d4SSatish Balay         cone[1] = 7;
22939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
22949371c9d4SSatish Balay         cone[0] = 6;
22959371c9d4SSatish Balay         cone[1] = 10;
22969566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
22979371c9d4SSatish Balay         cone[0] = 12;
22989371c9d4SSatish Balay         cone[1] = 13;
22999566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
23009371c9d4SSatish Balay         cone[0] = 13;
23019371c9d4SSatish Balay         cone[1] = 11;
23029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
23039371c9d4SSatish Balay         cone[0] = 10;
23049371c9d4SSatish Balay         cone[1] = 12;
23059566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
23069371c9d4SSatish Balay         cone[0] = 13;
23079371c9d4SSatish Balay         cone[1] = 8;
23089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
23099371c9d4SSatish Balay         cone[0] = 12;
23109371c9d4SSatish Balay         cone[1] = 9;
23119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
231245da822fSValeria Barra       }
23139566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
23149566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
23152829fed8SMatthew G. Knepley       /* Build coordinates */
23169566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2317dd400576SPatrick Sanan       if (rank == 0) {
23189371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
23199371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
23209371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
23219371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
23229371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
23239371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
23249371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
23259371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
23269371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
23279371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
23289371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
23299371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
23309371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
23319371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
23329371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
23339371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
23349371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
23359371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
23369371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
23379371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
23389371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
23399371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
23409371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
23419371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
234265a81367SMatthew G. Knepley       }
234345da822fSValeria Barra     }
234465a81367SMatthew G. Knepley     break;
234565a81367SMatthew G. Knepley   case 3:
2346116ded15SMatthew G. Knepley     if (simplex) {
2347116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
234851a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
234951a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
235051a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2351116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2352116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
23539371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
23549371c9d4SSatish Balay         {0, 1, 2, 3},
23559371c9d4SSatish Balay         {0, 2, 3, 1},
23569371c9d4SSatish Balay         {0, 3, 1, 2},
23579371c9d4SSatish Balay         {1, 0, 3, 2},
23589371c9d4SSatish Balay         {1, 2, 0, 3},
23599371c9d4SSatish Balay         {1, 3, 2, 0},
23609371c9d4SSatish Balay         {2, 0, 1, 3},
23619371c9d4SSatish Balay         {2, 1, 3, 0},
23629371c9d4SSatish Balay         {2, 3, 0, 1},
23639371c9d4SSatish Balay         {3, 0, 2, 1},
23649371c9d4SSatish Balay         {3, 1, 0, 2},
23659371c9d4SSatish Balay         {3, 2, 1, 0}
23669371c9d4SSatish Balay       };
2367116ded15SMatthew G. Knepley       PetscInt  cone[4];
2368116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2369116ded15SMatthew G. Knepley 
23709371c9d4SSatish Balay       vertexA[0] *= R;
23719371c9d4SSatish Balay       vertexA[1] *= R;
23729371c9d4SSatish Balay       vertexA[2] *= R;
23739371c9d4SSatish Balay       vertexA[3] *= R;
23749371c9d4SSatish Balay       vertexB[0] *= R;
23759371c9d4SSatish Balay       vertexB[1] *= R;
23769371c9d4SSatish Balay       vertexB[2] *= R;
23779371c9d4SSatish Balay       vertexB[3] *= R;
23789371c9d4SSatish Balay       vertexC[0] *= R;
23799371c9d4SSatish Balay       vertexC[1] *= R;
23809371c9d4SSatish Balay       vertexC[2] *= R;
23819371c9d4SSatish Balay       vertexC[3] *= R;
2382dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2383dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2384116ded15SMatthew G. Knepley       firstVertex = numCells;
2385116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2386116ded15SMatthew G. Knepley 
2387116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2388116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2389116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2390116ded15SMatthew G. Knepley 
2391116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
23926333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2393116ded15SMatthew G. Knepley 
2394116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2395116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2396116ded15SMatthew G. Knepley       */
2397116ded15SMatthew G. Knepley       /* Construct vertices */
23989566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2399116ded15SMatthew G. Knepley       i = 0;
2400dd400576SPatrick Sanan       if (rank == 0) {
2401116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2402116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2403116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2404116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2405116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2406116ded15SMatthew G. Knepley                 ++i;
2407116ded15SMatthew G. Knepley               }
2408116ded15SMatthew G. Knepley             }
2409116ded15SMatthew G. Knepley           }
2410116ded15SMatthew G. Knepley         }
2411116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2412116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2413116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2414116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2415116ded15SMatthew G. Knepley             ++i;
2416116ded15SMatthew G. Knepley           }
2417116ded15SMatthew G. Knepley         }
2418116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2419116ded15SMatthew G. Knepley           s[3] = 1;
2420116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2421116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2422116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2423116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2424116ded15SMatthew G. Knepley                 ++i;
2425116ded15SMatthew G. Knepley               }
2426116ded15SMatthew G. Knepley             }
2427116ded15SMatthew G. Knepley           }
2428116ded15SMatthew G. Knepley         }
242945da822fSValeria Barra       }
243063a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2431116ded15SMatthew G. Knepley       /* Construct graph */
24329566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2433116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2434116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
24359371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
24369371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
24379371c9d4SSatish Balay             ++k;
24389371c9d4SSatish Balay           }
2439116ded15SMatthew G. Knepley         }
244063a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2441116ded15SMatthew G. Knepley       }
2442116ded15SMatthew G. Knepley       /* Build Topology */
24439566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
244448a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
24459566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2446116ded15SMatthew G. Knepley       /* Cells */
2447dd400576SPatrick Sanan       if (rank == 0) {
2448116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2449116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2450116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2451116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
24529371c9d4SSatish 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]) {
24539371c9d4SSatish Balay                   cone[0] = firstVertex + i;
24549371c9d4SSatish Balay                   cone[1] = firstVertex + j;
24559371c9d4SSatish Balay                   cone[2] = firstVertex + k;
24569371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2457116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2458116ded15SMatthew G. Knepley                   {
24599371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
24609371c9d4SSatish 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}}},
2461116ded15SMatthew G. Knepley 
24629371c9d4SSatish 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}}},
2463116ded15SMatthew G. Knepley 
24649371c9d4SSatish 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}}},
2465116ded15SMatthew G. Knepley 
24669371c9d4SSatish 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}} }
24679371c9d4SSatish Balay                     };
2468116ded15SMatthew G. Knepley                     PetscReal normal[4];
2469116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2470116ded15SMatthew G. Knepley 
2471116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2472116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2473116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2474116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2475116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2476116ded15SMatthew 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]);
2477116ded15SMatthew G. Knepley                           }
2478116ded15SMatthew G. Knepley                         }
2479116ded15SMatthew G. Knepley                       }
2480116ded15SMatthew G. Knepley                     }
24819371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
24829371c9d4SSatish Balay                       PetscInt tmp = cone[1];
24839371c9d4SSatish Balay                       cone[1]      = cone[2];
24849371c9d4SSatish Balay                       cone[2]      = tmp;
24859371c9d4SSatish Balay                     }
2486116ded15SMatthew G. Knepley                   }
24879566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2488116ded15SMatthew G. Knepley                 }
2489116ded15SMatthew G. Knepley               }
2490116ded15SMatthew G. Knepley             }
2491116ded15SMatthew G. Knepley           }
2492116ded15SMatthew G. Knepley         }
249345da822fSValeria Barra       }
24949566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
24959566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
24969566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2497116ded15SMatthew G. Knepley     }
2498f4d061e9SPierre Jolivet     break;
2499d71ae5a4SJacob Faibussowitsch   default:
2500d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
250165a81367SMatthew G. Knepley   }
250265a81367SMatthew G. Knepley   /* Create coordinates */
25039566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
25049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
25059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
25069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
25072829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
25089566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
25099566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
25102829fed8SMatthew G. Knepley   }
25119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
25129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25139566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25149566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
25159566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25169566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25179566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
25189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
25199371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
2520ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
25219566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
25229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
25239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
25249566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
252551a74b61SMatthew G. Knepley   {
252651a74b61SMatthew G. Knepley     DM          cdm;
252751a74b61SMatthew G. Knepley     PetscDS     cds;
25289318fe57SMatthew G. Knepley     PetscScalar c = R;
252951a74b61SMatthew G. Knepley 
25309566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
25319566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
25329566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
25339566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
253451a74b61SMatthew G. Knepley   }
25359318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
25369566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
25379318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
25389318fe57SMatthew G. Knepley }
25399318fe57SMatthew G. Knepley 
2540b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
2541b7f5c055SJed Brown 
2542b7f5c055SJed Brown /*
2543b7f5c055SJed Brown  The Schwarz P implicit surface is
2544b7f5c055SJed Brown 
2545b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2546b7f5c055SJed Brown */
2547d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2548d71ae5a4SJacob Faibussowitsch {
2549b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2550b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2551b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
2552b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2553b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
2554ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
2555b7f5c055SJed Brown   }
2556b7f5c055SJed Brown }
2557b7f5c055SJed Brown 
25584663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2559d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2560d71ae5a4SJacob Faibussowitsch {
2561ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
25624663dae6SJed Brown   return 0;
25634663dae6SJed Brown }
25644663dae6SJed Brown 
2565b7f5c055SJed Brown /*
2566b7f5c055SJed Brown  The Gyroid implicit surface is
2567b7f5c055SJed Brown 
2568b7f5c055SJed 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)
2569b7f5c055SJed Brown 
2570b7f5c055SJed Brown */
2571d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2572d71ae5a4SJacob Faibussowitsch {
2573b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2574b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2575b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2576b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2577b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2578b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2579b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2580b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2581b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2582b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2583b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2584b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2585b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2586b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2587b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2588b7f5c055SJed Brown }
2589b7f5c055SJed Brown 
25904663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2591d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2592d71ae5a4SJacob Faibussowitsch {
25934663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
25944663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
25954663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
25964663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
25974663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
25984663dae6SJed Brown   return 0;
25994663dae6SJed Brown }
26004663dae6SJed Brown 
2601b7f5c055SJed Brown /*
2602b7f5c055SJed Brown    We wish to solve
2603b7f5c055SJed Brown 
2604b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2605b7f5c055SJed Brown 
2606b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2607b7f5c055SJed 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
2608b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2609b7f5c055SJed Brown 
2610b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2611b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2612b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2613b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2614b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2615b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2616b7f5c055SJed Brown 
2617b7f5c055SJed Brown      f(y) = 0                       1 equation
2618b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2619b7f5c055SJed Brown 
2620b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2621b7f5c055SJed Brown */
2622d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
2623d71ae5a4SJacob Faibussowitsch {
2624b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2625b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
26262f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
26279371c9d4SSatish Balay   PetscReal n_y[3][3] = {
26289371c9d4SSatish Balay     {0, 0, 0},
26299371c9d4SSatish Balay     {0, 0, 0},
26309371c9d4SSatish Balay     {0, 0, 0}
26319371c9d4SSatish Balay   };
2632b7f5c055SJed Brown 
2633b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2634b7f5c055SJed Brown 
2635b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
2636b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2637ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
2638b7f5c055SJed Brown 
2639b7f5c055SJed Brown   // Define the Householder reflector
2640b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2641b7f5c055SJed Brown   n[0] += norm * sign;
2642b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
2643b7f5c055SJed Brown 
2644b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2645b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2646b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2647b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2648b7f5c055SJed Brown 
2649b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2650b7f5c055SJed Brown     n[i] /= norm;
2651b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
2652b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2653b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2654b7f5c055SJed Brown     }
2655b7f5c055SJed Brown   }
2656b7f5c055SJed Brown 
2657b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2658b7f5c055SJed 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];
2659b7f5c055SJed Brown 
2660b7f5c055SJed Brown   res[0] = f;
2661b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2662b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2663b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2664b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
2665b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
2666b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2667b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2668b7f5c055SJed Brown   }
2669b7f5c055SJed Brown }
2670b7f5c055SJed Brown 
2671b7f5c055SJed Brown /*
2672b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2673b7f5c055SJed Brown */
2674d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
2675d71ae5a4SJacob Faibussowitsch {
2676b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2677b7f5c055SJed Brown 
2678b7f5c055SJed Brown   PetscFunctionBegin;
2679b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
2680b7f5c055SJed Brown     PetscScalar res[3], J[9];
2681b7f5c055SJed Brown     PetscReal   resnorm;
2682b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2683b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2684b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
268563a3b9bcSJacob 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])));
2686b7f5c055SJed Brown     }
2687b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2688b7f5c055SJed Brown 
2689b7f5c055SJed Brown     // Take the Newton step
26909566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2691b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2692b7f5c055SJed Brown   }
2693b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
2694b7f5c055SJed Brown   PetscFunctionReturn(0);
2695b7f5c055SJed Brown }
2696b7f5c055SJed Brown 
2697b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2698b7f5c055SJed Brown 
2699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
2700d71ae5a4SJacob Faibussowitsch {
2701b7f5c055SJed Brown   PetscMPIInt rank;
2702b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2703b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
2704b7f5c055SJed Brown   PetscInt            *cells_flat = NULL;
2705b7f5c055SJed Brown   PetscReal           *vtxCoords  = NULL;
2706b7f5c055SJed Brown   TPSEvaluateFunc      evalFunc   = NULL;
27074663dae6SJed Brown   PetscSimplePointFunc normalFunc = NULL;
2708b7f5c055SJed Brown   DMLabel              label;
2709b7f5c055SJed Brown 
2710b7f5c055SJed Brown   PetscFunctionBegin;
27119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
271263a3b9bcSJacob 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);
2713b7f5c055SJed Brown   switch (tpstype) {
2714b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2715b7f5c055SJed 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");
2716c5853193SPierre Jolivet     if (rank == 0) {
2717b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2718b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2719b7f5c055SJed Brown       PetscReal L = 1;
2720b7f5c055SJed Brown 
2721b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
2722b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
2723b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
2724b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
2725b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2726b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
27279566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
27289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
27299566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
27309566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
2731b7f5c055SJed Brown       // x-normal pipes
2732b7f5c055SJed Brown       vcount = 0;
2733b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
2734b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2735b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2736b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2737b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
2738b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2739b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2740b7f5c055SJed Brown             }
2741b7f5c055SJed Brown           }
2742b7f5c055SJed Brown         }
2743b7f5c055SJed Brown       }
2744b7f5c055SJed Brown       // y-normal pipes
2745b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2746b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
2747b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2748b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2749b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2750b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
2751b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2752b7f5c055SJed Brown             }
2753b7f5c055SJed Brown           }
2754b7f5c055SJed Brown         }
2755b7f5c055SJed Brown       }
2756b7f5c055SJed Brown       // z-normal pipes
2757b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2758b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2759b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
2760b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2761b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2762b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2763b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
2764b7f5c055SJed Brown             }
2765b7f5c055SJed Brown           }
2766b7f5c055SJed Brown         }
2767b7f5c055SJed Brown       }
2768b7f5c055SJed Brown       // junctions
2769b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2770b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2771b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2772b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
2773b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2774b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
2775b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
2776b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
2777b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
2778b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
2779b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
2780b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
2781b7f5c055SJed Brown                 }
2782b7f5c055SJed Brown               }
2783b7f5c055SJed Brown             }
2784b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2785b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
2786b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
2787b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
2788b7f5c055SJed Brown             };
2789b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
27909371c9d4SSatish 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};
2791b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
27929371c9d4SSatish 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};
2793b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
2794b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2795b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
2796b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
2797b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
2798b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
2799b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
2800b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
2801b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
2802b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
2803b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
2804b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2805b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2806b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
2807b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
2808b7f5c055SJed Brown                   numEdges++;
2809b7f5c055SJed Brown                 }
2810b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2811b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2812b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
2813b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
2814b7f5c055SJed Brown                   numEdges++;
2815b7f5c055SJed Brown                 }
2816b7f5c055SJed Brown               }
2817b7f5c055SJed Brown             }
2818b7f5c055SJed Brown           }
2819b7f5c055SJed Brown         }
2820b7f5c055SJed Brown       }
282163a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
2822b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
2823b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2824b7f5c055SJed Brown     }
2825b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
28264663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
2827b7f5c055SJed Brown     break;
2828b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2829c5853193SPierre Jolivet     if (rank == 0) {
2830b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2831b7f5c055SJed Brown       //
2832b7f5c055SJed 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)
2833b7f5c055SJed Brown       //
2834b7f5c055SJed Brown       // on the cell [0,2]^3.
2835b7f5c055SJed Brown       //
2836b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2837b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2838b7f5c055SJed Brown       // like a boomerang:
2839b7f5c055SJed Brown       //
2840b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2841b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2842b7f5c055SJed Brown       //                                                              //
2843b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2844b7f5c055SJed Brown       //      \                                   /            \      //
2845b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2846b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2847b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2848b7f5c055SJed Brown       //                                                              //
2849b7f5c055SJed Brown       //                                                              //
2850b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2851b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2852b7f5c055SJed Brown       //                                                              //
2853b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2854b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2855b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2856b7f5c055SJed Brown       //            \                       /                \        //
2857b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2858b7f5c055SJed Brown       //
2859b7f5c055SJed Brown       //
2860b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2861b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2862b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2863b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2864b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2865b7f5c055SJed Brown       //
2866b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2867b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2868b7f5c055SJed Brown       //
2869b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2870b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2871b7f5c055SJed Brown 
2872b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
2873b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
2874b7f5c055SJed Brown       PetscInt extentPlus[3];
2875b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
28769371c9d4SSatish 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;
28779371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
28789371c9d4SSatish Balay   /* face to vertex within the coarse discretization of a single gyroid block */
2879b7f5c055SJed Brown   /* layer 0 */
28809371c9d4SSatish Balay         {A,           C,           K,           G          },
28819371c9d4SSatish Balay         {C,           B,           II,          K          },
28829371c9d4SSatish Balay         {D,           A,           H,           L          },
28839371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
28849371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
28859371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
28869371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
28879371c9d4SSatish Balay         {B,           F,           M,           II         },
2888b7f5c055SJed Brown  /* layer 1 */
28899371c9d4SSatish Balay         {G,           K,           Q,           O          },
28909371c9d4SSatish Balay         {K,           II,          P,           Q          },
28919371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
28929371c9d4SSatish Balay         {J,           L,           R,           P          },
28939371c9d4SSatish Balay         {N,           J,           P,           S          },
28949371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
28959371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
28969371c9d4SSatish Balay         {II,          M,           T,           P          },
2897b7f5c055SJed Brown  /* layer 2 */
28989371c9d4SSatish Balay         {O,           Q,           Y,           U          },
28999371c9d4SSatish Balay         {Q,           P,           W,           Y          },
29009371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
29019371c9d4SSatish Balay         {P,           R,           Ap,          W          },
29029371c9d4SSatish Balay         {S,           P,           X,           Bp         },
29039371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
29049371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
29059371c9d4SSatish Balay         {P,           T,           Z,           X          },
2906b7f5c055SJed Brown  /* layer 3 */
29079371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
29089371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
29099371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
29109371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
29119371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
29129371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
29139371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
29149371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
2915b7f5c055SJed Brown  /* layer 4 */
29169371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
29179371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
29189371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
29199371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
29209371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
29219371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
29229371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
29239371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
2924b7f5c055SJed Brown  /* layer 5 */
29259371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
29269371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
29279371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
29289371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
29299371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
29309371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
29319371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
29329371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
2933b7f5c055SJed Brown  /* layer 6 */
29349371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
29359371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
29369371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
29379371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
29389371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
29399371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
29409371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
29419371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
2942b7f5c055SJed Brown  /* layer 7 (the top is the periodic image of the bottom of layer 0) */
29439371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
29449371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
29459371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
29469371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
29479371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
29489371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
29499371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
29509371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
2951b7f5c055SJed Brown       };
2952b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
29539371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
2954bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
2955bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
2956bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
2957bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
2958bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
2959bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
2960b7f5c055SJed Brown 
2961bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
2962bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
2963bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
2964bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
2965bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
2966bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
2967bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
2968bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
2969b7f5c055SJed Brown 
2970bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
2971bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
2972bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
2973bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
2974bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
2975bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
2976b7f5c055SJed Brown 
2977bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
2978bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
2979bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
2980bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
2981bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
2982bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
2983bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
2984bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
2985b7f5c055SJed Brown 
2986bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
2987bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
2988bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
2989bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
2990bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
2991bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
2992b7f5c055SJed Brown 
2993bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
2994bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
2995bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
2996bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
2997bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
2998bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
2999bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
3000bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
3001b7f5c055SJed Brown 
3002bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
3003bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
3004bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
3005bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
3006bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
3007bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
3008b7f5c055SJed Brown 
3009bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3010bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3011bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3012bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3013bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3014bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3015bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3016bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3017b7f5c055SJed Brown       };
3018b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3019b7f5c055SJed Brown       PetscBool *seen;
3020b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3021b7f5c055SJed Brown       PetscInt   count;
3022b7f5c055SJed Brown 
3023b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3024b7f5c055SJed Brown       numBlocks = 1;
3025b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3026b7f5c055SJed Brown       numBlocksPlus = 1;
3027b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3028b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
30299566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
30309566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3031b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3032b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3033b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3034b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3035b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3036b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3037b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3038b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3039b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3040b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3041b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3042b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3043b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3044b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3045b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3046b7f5c055SJed Brown 
3047b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3048b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3049b7f5c055SJed Brown               }
3050b7f5c055SJed Brown             }
3051b7f5c055SJed Brown           }
3052b7f5c055SJed Brown         }
3053b7f5c055SJed Brown       }
30549371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
30559371c9d4SSatish Balay         if (seen[i]) numVertices++;
3056b7f5c055SJed Brown       count = 0;
30579566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
30589566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3059b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3060b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3061b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3062b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3063b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3064b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3065b7f5c055SJed Brown 
3066b7f5c055SJed Brown               if (seen[vIdx]) {
3067b7f5c055SJed Brown                 PetscInt thisVert;
3068b7f5c055SJed Brown 
3069b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3070b7f5c055SJed Brown 
3071b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3072b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3073b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3074b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3075b7f5c055SJed Brown               }
3076b7f5c055SJed Brown             }
3077b7f5c055SJed Brown           }
3078b7f5c055SJed Brown         }
3079b7f5c055SJed Brown       }
3080b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3081b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3082ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3083b7f5c055SJed Brown         }
3084b7f5c055SJed Brown       }
30859566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
30869566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3087b7f5c055SJed Brown       cells_flat = cells[0][0];
3088b7f5c055SJed Brown       numEdges   = 0;
3089b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3090b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3091b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3092b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3093b7f5c055SJed Brown 
3094b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3095b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3096b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3097b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3098b7f5c055SJed Brown             }
3099b7f5c055SJed Brown           }
3100b7f5c055SJed Brown         }
3101b7f5c055SJed Brown       }
31029566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
31039566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3104b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3105b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3106b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3107b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3108b7f5c055SJed Brown 
3109b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3110b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3111b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3112b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3113b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3114b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3115b7f5c055SJed Brown               }
3116b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3117b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3118b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3119b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3120b7f5c055SJed Brown               }
3121b7f5c055SJed Brown             }
3122b7f5c055SJed Brown           }
3123b7f5c055SJed Brown         }
3124b7f5c055SJed Brown       }
3125b7f5c055SJed Brown     }
3126b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
31274663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3128b7f5c055SJed Brown     break;
3129b7f5c055SJed Brown   }
3130b7f5c055SJed Brown 
31319566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3132c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
31339566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
31349566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3135b7f5c055SJed Brown   {
3136b7f5c055SJed Brown     DM idm;
31379566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
313869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3139b7f5c055SJed Brown   }
3140c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
31419566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
31429566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3143b7f5c055SJed Brown 
31449566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
31459566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3146b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3147b7f5c055SJed Brown     PetscInt        njoin;
3148b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
31499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
315063a3b9bcSJacob 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]);
31519566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
31529566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3153b7f5c055SJed Brown   }
31549566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
31559566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
31561436d7faSJed Brown   if (tps_distribute) {
31571436d7faSJed Brown     DM               pdm = NULL;
31581436d7faSJed Brown     PetscPartitioner part;
31591436d7faSJed Brown 
31609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
31619566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
31629566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
316348a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
31641436d7faSJed Brown     // Do not auto-distribute again
31659566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
31661436d7faSJed Brown   }
3167b7f5c055SJed Brown 
31689566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3169b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3170b7f5c055SJed Brown     PetscInt     m;
3171b7f5c055SJed Brown     DM           dmf;
3172b7f5c055SJed Brown     Vec          X;
3173b7f5c055SJed Brown     PetscScalar *x;
31749566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
317569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3176b7f5c055SJed Brown 
31779566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
31789566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
31799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
318048a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
31819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3182b7f5c055SJed Brown   }
3183b7f5c055SJed Brown 
3184b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
31859566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
31869566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3187b7f5c055SJed Brown 
3188b7f5c055SJed Brown   if (thickness > 0) {
31894663dae6SJed Brown     DM              edm, cdm, ecdm;
31904663dae6SJed Brown     DMPlexTransform tr;
31914663dae6SJed Brown     const char     *prefix;
31924663dae6SJed Brown     PetscOptions    options;
31934663dae6SJed Brown     // Code from DMPlexExtrude
31944663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
31954663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
31964663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
31974663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
31984663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
31994663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
32004663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
32014663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
32024663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
32034663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
32044663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
32054663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
32064663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
32074663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
32084663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
32094663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
32104663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
32114663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
32124663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
32134663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
32144663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
32154663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
32164663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
32174663dae6SJed Brown     if (edm) {
32184663dae6SJed Brown       ((DM_Plex *)edm->data)->printFEM    = ((DM_Plex *)dm->data)->printFEM;
32194663dae6SJed Brown       ((DM_Plex *)edm->data)->printL2     = ((DM_Plex *)dm->data)->printL2;
3220f5867de0SMatthew G. Knepley       ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate;
32214663dae6SJed Brown     }
322269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3223b7f5c055SJed Brown   }
3224b7f5c055SJed Brown   PetscFunctionReturn(0);
3225b7f5c055SJed Brown }
3226b7f5c055SJed Brown 
3227b7f5c055SJed Brown /*@
3228b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3229b7f5c055SJed Brown 
3230b7f5c055SJed Brown   Collective
3231b7f5c055SJed Brown 
3232b7f5c055SJed Brown   Input Parameters:
3233b7f5c055SJed Brown + comm   - The communicator for the DM object
3234b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
3235b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
3236b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
32371436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3238817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
32391436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
3240817da375SSatish Balay - thickness - Thickness in normal direction
3241b7f5c055SJed Brown 
3242b7f5c055SJed Brown   Output Parameter:
3243b7f5c055SJed Brown . dm  - The DM object
3244b7f5c055SJed Brown 
3245b7f5c055SJed Brown   Notes:
3246b7f5c055SJed 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.
3247b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
3248b7f5c055SJed 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.
3249b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3250b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3251b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3252b7f5c055SJed Brown 
3253b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
3254b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
3255b7f5c055SJed Brown 
3256b7f5c055SJed Brown   References:
3257606c0280SSatish Balay . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. https://doi.org/10.1016/j.polymer.2017.11.049
3258b7f5c055SJed Brown 
3259b7f5c055SJed Brown   Developer Notes:
3260b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3261b7f5c055SJed Brown 
3262b7f5c055SJed Brown   Level: beginner
3263b7f5c055SJed Brown 
3264db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3265b7f5c055SJed Brown @*/
3266d71ae5a4SJacob 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)
3267d71ae5a4SJacob Faibussowitsch {
3268b7f5c055SJed Brown   PetscFunctionBegin;
32699566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32709566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32719566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
3272b7f5c055SJed Brown   PetscFunctionReturn(0);
3273b7f5c055SJed Brown }
3274b7f5c055SJed Brown 
32759318fe57SMatthew G. Knepley /*@
32769318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
32779318fe57SMatthew G. Knepley 
32789318fe57SMatthew G. Knepley   Collective
32799318fe57SMatthew G. Knepley 
32809318fe57SMatthew G. Knepley   Input Parameters:
32819318fe57SMatthew G. Knepley + comm    - The communicator for the DM object
32829318fe57SMatthew G. Knepley . dim     - The dimension
32839318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
32849318fe57SMatthew G. Knepley - R       - The radius
32859318fe57SMatthew G. Knepley 
32869318fe57SMatthew G. Knepley   Output Parameter:
32879318fe57SMatthew G. Knepley . dm  - The DM object
32889318fe57SMatthew G. Knepley 
32899318fe57SMatthew G. Knepley   Level: beginner
32909318fe57SMatthew G. Knepley 
3291db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
32929318fe57SMatthew G. Knepley @*/
3293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
3294d71ae5a4SJacob Faibussowitsch {
32959318fe57SMatthew G. Knepley   PetscFunctionBegin;
32969318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
32979566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32989566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32999566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
33009318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
33019318fe57SMatthew G. Knepley }
33029318fe57SMatthew G. Knepley 
3303d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
3304d71ae5a4SJacob Faibussowitsch {
33059318fe57SMatthew G. Knepley   DM      sdm, vol;
33069318fe57SMatthew G. Knepley   DMLabel bdlabel;
33079318fe57SMatthew G. Knepley 
33089318fe57SMatthew G. Knepley   PetscFunctionBegin;
33099566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
33109566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
33119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_"));
33129566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
33139566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
33149566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
33159566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
33169566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
331769d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
33189566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
33199566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
33209566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
33219566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
332251a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
332351a74b61SMatthew G. Knepley }
332451a74b61SMatthew G. Knepley 
332551a74b61SMatthew G. Knepley /*@
332651a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
332751a74b61SMatthew G. Knepley 
332851a74b61SMatthew G. Knepley   Collective
332951a74b61SMatthew G. Knepley 
333051a74b61SMatthew G. Knepley   Input Parameters:
333151a74b61SMatthew G. Knepley + comm  - The communicator for the DM object
333251a74b61SMatthew G. Knepley . dim   - The dimension
333351a74b61SMatthew G. Knepley - R     - The radius
333451a74b61SMatthew G. Knepley 
333551a74b61SMatthew G. Knepley   Output Parameter:
333651a74b61SMatthew G. Knepley . dm  - The DM object
333751a74b61SMatthew G. Knepley 
333851a74b61SMatthew G. Knepley   Options Database Keys:
333951a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
334051a74b61SMatthew G. Knepley 
334151a74b61SMatthew G. Knepley   Level: beginner
334251a74b61SMatthew G. Knepley 
3343db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
334451a74b61SMatthew G. Knepley @*/
3345d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
3346d71ae5a4SJacob Faibussowitsch {
334751a74b61SMatthew G. Knepley   PetscFunctionBegin;
33489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
33499566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
33509566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
33512829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
33522829fed8SMatthew G. Knepley }
33532829fed8SMatthew G. Knepley 
3354d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
3355d71ae5a4SJacob Faibussowitsch {
33560a6ba040SMatthew G. Knepley   PetscFunctionBegin;
33579318fe57SMatthew G. Knepley   switch (ct) {
33589371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
33599318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
33609318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
33619318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
33629318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
33639318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
33649318fe57SMatthew G. Knepley 
33659566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
33669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33679371c9d4SSatish Balay   } break;
33689371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
33699318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
33709318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
33719318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
33729318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
33739318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
33749318fe57SMatthew G. Knepley 
33759566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33769566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33779371c9d4SSatish Balay   } break;
33789371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3379b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3380b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3381b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3382b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3383b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3384b5a892a1SMatthew G. Knepley 
33859566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33869566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33879371c9d4SSatish Balay   } break;
33889371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
33899318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
33909318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
33919318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
33929318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
33939318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
33949318fe57SMatthew G. Knepley 
33959566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33979371c9d4SSatish Balay   } break;
33989371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
33999318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34009318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34019318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34029318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34039318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
34049318fe57SMatthew G. Knepley 
34059566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34079371c9d4SSatish Balay   } break;
34089371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
34099318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34109318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34119318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34129318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34139318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
34149318fe57SMatthew G. Knepley 
34159566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34169566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34179371c9d4SSatish Balay   } break;
34189371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
34199318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34209318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3421f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34229318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3423f0edb160SMatthew 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};
34249318fe57SMatthew G. Knepley 
34259566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34269566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34279371c9d4SSatish Balay   } break;
34289371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
34299318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34309318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3431f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34329318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34339371c9d4SSatish 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};
34349318fe57SMatthew G. Knepley 
34359566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34369566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34379371c9d4SSatish Balay   } break;
34389371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
34399318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34409318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3441f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34429318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34439371c9d4SSatish 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};
34449318fe57SMatthew G. Knepley 
34459566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34479371c9d4SSatish Balay   } break;
34489371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
34499318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34509318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
34519318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34529318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34539371c9d4SSatish 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};
34549318fe57SMatthew G. Knepley 
34559566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34579371c9d4SSatish Balay   } break;
34589371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
34599318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34609318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
34619318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34629318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34639371c9d4SSatish 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};
34649318fe57SMatthew G. Knepley 
34659566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34679371c9d4SSatish Balay   } break;
34689371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
34699318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
34709318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3471f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
34729318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34739371c9d4SSatish 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};
34749318fe57SMatthew G. Knepley 
34759566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34769566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34779371c9d4SSatish Balay   } break;
3478d71ae5a4SJacob Faibussowitsch   default:
3479d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
34809318fe57SMatthew G. Knepley   }
34819318fe57SMatthew G. Knepley   {
34829318fe57SMatthew G. Knepley     PetscInt Nv, v;
34839318fe57SMatthew G. Knepley 
34849318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
34859566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
34869566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
34879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
34889566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
34899318fe57SMatthew G. Knepley   }
34909566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
34919566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
34920a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
34930a6ba040SMatthew G. Knepley }
34940a6ba040SMatthew G. Knepley 
34959318fe57SMatthew G. Knepley /*@
34969318fe57SMatthew G. Knepley   DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell
34979318fe57SMatthew G. Knepley 
34989318fe57SMatthew G. Knepley   Collective
34999318fe57SMatthew G. Knepley 
35009318fe57SMatthew G. Knepley   Input Parameters:
35019318fe57SMatthew G. Knepley + comm - The communicator
35029318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
35039318fe57SMatthew G. Knepley 
35049318fe57SMatthew G. Knepley   Output Parameter:
35059318fe57SMatthew G. Knepley . refdm - The reference cell
35069318fe57SMatthew G. Knepley 
35079318fe57SMatthew G. Knepley   Level: intermediate
35089318fe57SMatthew G. Knepley 
3509db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()`
35109318fe57SMatthew G. Knepley @*/
3511d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
3512d71ae5a4SJacob Faibussowitsch {
35130a6ba040SMatthew G. Knepley   PetscFunctionBegin;
35149566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
35159566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
35169566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
35179318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35189318fe57SMatthew G. Knepley }
351979a015ccSMatthew G. Knepley 
3520d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
3521d71ae5a4SJacob Faibussowitsch {
35229318fe57SMatthew G. Knepley   DM        plex;
35239318fe57SMatthew G. Knepley   DMLabel   label;
35249318fe57SMatthew G. Knepley   PetscBool hasLabel;
35250a6ba040SMatthew G. Knepley 
3526c22d3578SMatthew G. Knepley   PetscFunctionBegin;
35279566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
35289318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
35299566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
35309566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
35319566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
35329566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
35331c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
35349566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
35359318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35369318fe57SMatthew G. Knepley }
3537acdc6f61SToby Isaac 
3538669647acSMatthew G. Knepley /*
3539669647acSMatthew 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.
3540669647acSMatthew G. Knepley 
3541669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
3542669647acSMatthew G. Knepley */
3543d71ae5a4SJacob 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[])
3544d71ae5a4SJacob Faibussowitsch {
3545669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
3546669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
3547669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
3548669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
3549669647acSMatthew G. Knepley 
3550669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
3551669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
3552669647acSMatthew G. Knepley }
3553669647acSMatthew G. Knepley 
3554669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
35559318fe57SMatthew G. Knepley 
3556d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
3557d71ae5a4SJacob Faibussowitsch {
35589318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
35599318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
35609318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
35619318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3562cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
35639318fe57SMatthew G. Knepley   MPI_Comm       comm;
3564ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3565ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3566ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
35679318fe57SMatthew G. Knepley 
35689318fe57SMatthew G. Knepley   PetscFunctionBegin;
35699566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
35709318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
35719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
35729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
35739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
35749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
35759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
35769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
35779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
357863a3b9bcSJacob Faibussowitsch   PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim);
35799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
35809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
35819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
35829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
35839566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
35849318fe57SMatthew G. Knepley 
358561a622f3SMatthew G. Knepley   switch (cell) {
358661a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
358761a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
358861a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
358961a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
359061a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
359161a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
3592d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
3593d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
3594d71ae5a4SJacob Faibussowitsch     break;
3595d71ae5a4SJacob Faibussowitsch   default:
3596d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
3597d71ae5a4SJacob Faibussowitsch     break;
359861a622f3SMatthew G. Knepley   }
359961a622f3SMatthew G. Knepley 
36009318fe57SMatthew G. Knepley   if (fflg) {
36019318fe57SMatthew G. Knepley     DM dmnew;
36029318fe57SMatthew G. Knepley 
36039566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew));
36045de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
360569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36069318fe57SMatthew G. Knepley   } else if (refDomain) {
36079566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
36089318fe57SMatthew G. Knepley   } else if (bdfflg) {
36099318fe57SMatthew G. Knepley     DM bdm, dmnew;
36109318fe57SMatthew G. Knepley 
36119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm));
36129566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
36139566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
36149566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
36159566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
36165de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
361769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36189318fe57SMatthew G. Knepley   } else {
36199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
36209318fe57SMatthew G. Knepley     switch (shape) {
3621669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
3622669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
36239318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
36249318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
36259318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
36269318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3627669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
36289318fe57SMatthew G. Knepley       PetscInt       i, n;
36299318fe57SMatthew G. Knepley 
36309318fe57SMatthew G. Knepley       n = dim;
36319318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
36329566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36339318fe57SMatthew G. Knepley       n = 3;
36349566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
363563a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36369318fe57SMatthew G. Knepley       n = 3;
36379566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
363863a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36399318fe57SMatthew G. Knepley       n = 3;
36409566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
364163a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
3642669647acSMatthew G. Knepley 
3643669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
3644669647acSMatthew G. Knepley       if (isAnnular)
3645669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
3646669647acSMatthew G. Knepley 
36479318fe57SMatthew G. Knepley       switch (cell) {
364861a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
36499566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3650d410b0cfSMatthew G. Knepley         if (!interpolate) {
3651d410b0cfSMatthew G. Knepley           DM udm;
3652d410b0cfSMatthew G. Knepley 
36539566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
365469d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
3655d410b0cfSMatthew G. Knepley         }
36569318fe57SMatthew G. Knepley         break;
3657d71ae5a4SJacob Faibussowitsch       default:
3658d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate));
3659d71ae5a4SJacob Faibussowitsch         break;
36609318fe57SMatthew G. Knepley       }
3661669647acSMatthew G. Knepley       if (isAnnular) {
3662669647acSMatthew G. Knepley         DM          cdm;
3663669647acSMatthew G. Knepley         PetscDS     cds;
3664669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
3665669647acSMatthew G. Knepley 
3666669647acSMatthew G. Knepley         // Fix coordinates for annular region
3667669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
3668669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
3669669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
3670669647acSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL));
3671669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
3672669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
3673669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
3674669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
3675669647acSMatthew G. Knepley       }
36769371c9d4SSatish Balay     } break;
36779371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
36789318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
36799318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
36809318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
36819318fe57SMatthew G. Knepley       PetscInt  i, n;
36829318fe57SMatthew G. Knepley 
36839318fe57SMatthew G. Knepley       n = dim + 1;
36849318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
36859566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36869318fe57SMatthew G. Knepley       n = 3;
36879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
368863a3b9bcSJacob 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);
36899318fe57SMatthew G. Knepley       n = 3;
36909566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
369163a3b9bcSJacob 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);
36929566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
36939371c9d4SSatish Balay     } break;
36949371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
36959318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36969318fe57SMatthew G. Knepley 
36979566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
36989566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
36999371c9d4SSatish Balay     } break;
37009371c9d4SSatish Balay     case DM_SHAPE_BALL: {
37019318fe57SMatthew G. Knepley       PetscReal R = 1.0;
37029318fe57SMatthew G. Knepley 
37039566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
37049566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
37059371c9d4SSatish Balay     } break;
37069371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
37079318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
37089318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
37099318fe57SMatthew G. Knepley 
37109566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
37119566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
37129318fe57SMatthew G. Knepley       switch (cell) {
3713d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
3714d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
3715d71ae5a4SJacob Faibussowitsch         break;
3716d71ae5a4SJacob Faibussowitsch       default:
3717d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt));
3718d71ae5a4SJacob Faibussowitsch         break;
37199318fe57SMatthew G. Knepley       }
37209371c9d4SSatish Balay     } break;
3721b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
37229371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
3723b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
3724b7f5c055SJed Brown       PetscReal      thickness   = 0.;
3725b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3726b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
37271436d7faSJed Brown       PetscBool      tps_distribute;
37289566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
37299566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
37309566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
37319566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
37329566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
37339566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
37349566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
37359566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
37369371c9d4SSatish Balay     } break;
37379371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
373805bd46c0SStefano Zampini       DM        dmnew;
373905bd46c0SStefano Zampini       PetscReal rl = 0.0;
374005bd46c0SStefano Zampini 
374105bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
374205bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
37435de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
374469d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
37459371c9d4SSatish Balay     } break;
3746d71ae5a4SJacob Faibussowitsch     default:
3747d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
37489318fe57SMatthew G. Knepley     }
37499318fe57SMatthew G. Knepley   }
37509566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
375148a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
37520a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
37530a6ba040SMatthew G. Knepley }
37540a6ba040SMatthew G. Knepley 
3755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3756d71ae5a4SJacob Faibussowitsch {
37570a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
37587f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
37599318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
37600a6ba040SMatthew G. Knepley 
37610a6ba040SMatthew G. Knepley   PetscFunctionBegin;
37620a6ba040SMatthew G. Knepley   /* Handle viewing */
37639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
37649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
37659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
37669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
3767f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
37689566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
37699566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
37709318fe57SMatthew G. Knepley   /* Labeling */
37719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
37729566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3773953fc75cSMatthew G. Knepley   /* Point Location */
37749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
37750848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
37769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
37772e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
37789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3779b29cfa1cSToby Isaac   /* Projection behavior */
3780d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
37819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3782f12cf164SMatthew G. Knepley   /* Checking structure */
3783f12cf164SMatthew G. Knepley   {
37847f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
3785f12cf164SMatthew G. Knepley 
37867f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
37877f9d8d6cSVaclav Hapla     if (all) {
37887f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
37897f9d8d6cSVaclav Hapla     } else {
37909566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
37917f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
37929566063dSJacob 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));
37937f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
37949566063dSJacob 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));
37957f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
37969566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
37977f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
37989566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
3799d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
38009566063dSJacob 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));
38017f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
38027f9d8d6cSVaclav Hapla     }
38039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
38049566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3805f12cf164SMatthew G. Knepley   }
38069318fe57SMatthew G. Knepley   {
38079318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
38084f3833eaSMatthew G. Knepley 
38099566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
38109318fe57SMatthew G. Knepley     if (flg) {
38119318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
38129318fe57SMatthew G. Knepley 
38139566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
38149566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
38159566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
38169566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
38179318fe57SMatthew G. Knepley     }
38189318fe57SMatthew G. Knepley   }
38199566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
382068d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
382168d4fef7SMatthew G. Knepley }
382268d4fef7SMatthew G. Knepley 
3823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
3824d71ae5a4SJacob Faibussowitsch {
3825c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
3826c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
3827c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
3828c506a872SMatthew G. Knepley   PetscBool flg;
3829c506a872SMatthew G. Knepley 
3830c506a872SMatthew G. Knepley   PetscFunctionBegin;
3831c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
3832c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
3833c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
3834c506a872SMatthew G. Knepley   if (numOvLabels) {
3835c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
3836c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
3837c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
3838c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
3839c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
3840c506a872SMatthew G. Knepley     }
3841c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
3842c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
3843c506a872SMatthew 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);
3844c506a872SMatthew G. Knepley 
3845c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
3846c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
3847c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
3848c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
3849c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
3850c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
3851c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
3852c506a872SMatthew G. Knepley     }
3853c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
3854c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
3855c506a872SMatthew 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);
3856c506a872SMatthew G. Knepley   }
3857c506a872SMatthew G. Knepley   PetscFunctionReturn(0);
3858c506a872SMatthew G. Knepley }
3859c506a872SMatthew G. Knepley 
3860d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3861d71ae5a4SJacob Faibussowitsch {
3862bdf63967SMatthew G. Knepley   PetscFunctionList        ordlist;
3863bdf63967SMatthew G. Knepley   char                     oname[256];
3864d410b0cfSMatthew G. Knepley   PetscReal                volume    = -1.0;
38659318fe57SMatthew G. Knepley   PetscInt                 prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3866e600fa54SMatthew 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;
38676bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
386868d4fef7SMatthew G. Knepley 
386968d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3870d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
3871dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
38729318fe57SMatthew G. Knepley   /* Handle automatic creation */
38739566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
38746bc1bd01Sksagiyam   if (dim < 0) {
38756bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
38766bc1bd01Sksagiyam     created = PETSC_TRUE;
38776bc1bd01Sksagiyam   }
38786bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
3879d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
38809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3881d89e6e46SMatthew G. Knepley   if (flg) {
3882d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3883d89e6e46SMatthew G. Knepley 
38849566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
3885d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3886d89e6e46SMatthew G. Knepley       DM udm;
3887d89e6e46SMatthew G. Knepley 
38889566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
388969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
3890d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3891d89e6e46SMatthew G. Knepley       DM idm;
3892d89e6e46SMatthew G. Knepley 
38939566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
389469d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
3895d89e6e46SMatthew G. Knepley     }
3896d89e6e46SMatthew G. Knepley   }
38979b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
38989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3899ad540459SPierre Jolivet   if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel;
39009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
39019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
39029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
39039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
39049566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
39059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
39069318fe57SMatthew G. Knepley   if (flg) {
39079566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
39089566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
39099318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
39109318fe57SMatthew G. Knepley   }
39119b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
39129b44eab4SMatthew G. Knepley     DM             rdm;
39139b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
39149b44eab4SMatthew G. Knepley 
3915dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39169566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
391769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
3918dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
391961a622f3SMatthew G. Knepley     if (coordFunc && remap) {
39209566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
39219b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
39229b44eab4SMatthew G. Knepley     }
39239b44eab4SMatthew G. Knepley   }
39249566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
39259318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
39269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
39279318fe57SMatthew G. Knepley   if (extLayers) {
39289318fe57SMatthew G. Knepley     DM edm;
39299318fe57SMatthew G. Knepley 
39309566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
393169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
393248d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
3933dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3934d410b0cfSMatthew G. Knepley     extLayers = 0;
39355e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
39369318fe57SMatthew G. Knepley   }
3937bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
39386bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
39399566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
39406bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
39419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
39426bc1bd01Sksagiyam   if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) {
3943bdf63967SMatthew G. Knepley     DM pdm;
3944bdf63967SMatthew G. Knepley     IS perm;
3945bdf63967SMatthew G. Knepley 
39469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
39479566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
39489566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
394969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
3950dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3951bdf63967SMatthew G. Knepley   }
39529b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
39539566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
3954c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
3955dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
39569b44eab4SMatthew G. Knepley   if (distribute) {
39579b44eab4SMatthew G. Knepley     DM               pdm = NULL;
39589b44eab4SMatthew G. Knepley     PetscPartitioner part;
39599b44eab4SMatthew G. Knepley 
39609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
39619566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
39629566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm));
396348a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
39649b44eab4SMatthew G. Knepley   }
39659318fe57SMatthew G. Knepley   /* Create coordinate space */
39669318fe57SMatthew G. Knepley   if (created) {
396761a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
39689318fe57SMatthew G. Knepley     PetscInt  degree = 1;
39696858538eSMatthew G. Knepley     PetscBool flg;
39709318fe57SMatthew G. Knepley 
39719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
39729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
39739566063dSJacob Faibussowitsch     if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
397461a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
397561a622f3SMatthew G. Knepley       DM           cdm;
397661a622f3SMatthew G. Knepley       PetscDS      cds;
397761a622f3SMatthew G. Knepley       PetscObject  obj;
397861a622f3SMatthew G. Knepley       PetscClassId id;
397961a622f3SMatthew G. Knepley 
39809566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDM(dm, &cdm));
39819566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
39829566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
39839566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
398461a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
398561a622f3SMatthew G. Knepley         PetscContainer dummy;
398661a622f3SMatthew G. Knepley 
39879566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
39889566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
39899566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
39909566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
39919566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
399261a622f3SMatthew G. Knepley       }
399361a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
399461a622f3SMatthew G. Knepley     }
39956858538eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg));
39969566063dSJacob Faibussowitsch     PetscCall(DMLocalizeCoordinates(dm));
39979318fe57SMatthew G. Knepley   }
399868d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
399961a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
40009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
40019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
40029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
40039566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
400468d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
4005acdc6f61SToby Isaac     DM *dms, coarseDM;
400668d4fef7SMatthew G. Knepley 
40079566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
40089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
40099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
40109566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
401168d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
40129566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
401368d4fef7SMatthew G. Knepley     if (refine == 1) {
40149566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
40159566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
401668d4fef7SMatthew G. Knepley     } else {
40179566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
40189566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
40199566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
40209566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
402168d4fef7SMatthew G. Knepley     }
40229566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
40239566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
402468d4fef7SMatthew G. Knepley     /* Free DMs */
402568d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
4026dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40279566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
402868d4fef7SMatthew G. Knepley     }
40299566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
403068d4fef7SMatthew G. Knepley   } else {
403168d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
40329318fe57SMatthew G. Knepley       DM             rdm;
403351a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
403468d4fef7SMatthew G. Knepley 
4035dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40369566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
403768d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
403869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
4039dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
404061a622f3SMatthew G. Knepley       if (coordFunc && remap) {
40419566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
404251a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
404351a74b61SMatthew G. Knepley       }
404468d4fef7SMatthew G. Knepley     }
404568d4fef7SMatthew G. Knepley   }
40463cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
40479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
40489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
4049b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
4050b653a561SMatthew G. Knepley     DM *dms;
4051b653a561SMatthew G. Knepley 
40529566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
40539566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
4054b653a561SMatthew G. Knepley     /* Free DMs */
4055b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
4056dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40579566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
4058b653a561SMatthew G. Knepley     }
40599566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
4060b653a561SMatthew G. Knepley   } else {
4061b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
40629318fe57SMatthew G. Knepley       DM             cdm;
40639318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
40643cf6fe12SMatthew G. Knepley 
4065dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40669566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
40673cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
406869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
4069dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40709318fe57SMatthew G. Knepley       if (coordFunc) {
40719566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
40729318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
40739318fe57SMatthew G. Knepley       }
40743cf6fe12SMatthew G. Knepley     }
4075b653a561SMatthew G. Knepley   }
4076909dfd52SMatthew G. Knepley   /* Handle ghost cells */
40779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
4078909dfd52SMatthew G. Knepley   if (ghostCells) {
4079909dfd52SMatthew G. Knepley     DM   gdm;
4080909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
4081909dfd52SMatthew G. Knepley 
4082909dfd52SMatthew G. Knepley     lname[0] = '\0';
40839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
40849566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
408569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
4086909dfd52SMatthew G. Knepley   }
40876913077dSMatthew G. Knepley   /* Handle 1D order */
40886bc1bd01Sksagiyam   if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) {
40896913077dSMatthew G. Knepley     DM           cdm, rdm;
40906913077dSMatthew G. Knepley     PetscDS      cds;
40916913077dSMatthew G. Knepley     PetscObject  obj;
40926913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
40936913077dSMatthew G. Knepley     IS           perm;
40946bc1bd01Sksagiyam     PetscInt     Nf;
40956913077dSMatthew G. Knepley     PetscBool    distributed;
40966913077dSMatthew G. Knepley 
40979566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
40989566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
40999566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
41009566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
41016913077dSMatthew G. Knepley     if (Nf) {
41029566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
41039566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
41046913077dSMatthew G. Knepley     }
41056bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
41069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
41079566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
410869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
41099566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
41106913077dSMatthew G. Knepley     }
41116913077dSMatthew G. Knepley   }
41123cf6fe12SMatthew G. Knepley /* Handle */
4113dd4c3f67SMatthew G. Knepley non_refine:
4114dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4115d0609cedSBarry Smith   PetscOptionsHeadEnd();
41160a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
41170a6ba040SMatthew G. Knepley }
41180a6ba040SMatthew G. Knepley 
4119d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
4120d71ae5a4SJacob Faibussowitsch {
4121552f7358SJed Brown   PetscFunctionBegin;
41229566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
41239566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
41249566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
41259566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
41269566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
41279566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
4128552f7358SJed Brown   PetscFunctionReturn(0);
4129552f7358SJed Brown }
4130552f7358SJed Brown 
4131d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
4132d71ae5a4SJacob Faibussowitsch {
4133552f7358SJed Brown   PetscFunctionBegin;
41349566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
41359566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
41369566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
4137552f7358SJed Brown   PetscFunctionReturn(0);
4138552f7358SJed Brown }
4139552f7358SJed Brown 
4140d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4141d71ae5a4SJacob Faibussowitsch {
4142793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4143793f3fe5SMatthew G. Knepley 
4144793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
41459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4146793f3fe5SMatthew G. Knepley   if (depth == 1) {
41479566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
41489566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
41499566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
41509371c9d4SSatish Balay     else {
41519371c9d4SSatish Balay       *pStart = 0;
41529371c9d4SSatish Balay       *pEnd   = 0;
41539371c9d4SSatish Balay     }
4154793f3fe5SMatthew G. Knepley   } else {
41559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4156793f3fe5SMatthew G. Knepley   }
4157793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
4158793f3fe5SMatthew G. Knepley }
4159793f3fe5SMatthew G. Knepley 
4160d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
4161d71ae5a4SJacob Faibussowitsch {
4162502a2867SDave May   PetscSF            sf;
41630a19bb7dSprj-   PetscInt           niranks, njranks, n;
41640a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
41650a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4166502a2867SDave May 
41672f356facSMatthew G. Knepley   PetscFunctionBegin;
41689566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
41690a19bb7dSprj-   if (!data->neighbors) {
41709566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
41719566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
41729566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
41739566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
41749566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
41759566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
41760a19bb7dSprj-     n = njranks + niranks;
41779566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
41780a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
41799566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
41800a19bb7dSprj-   }
41810a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
41820a19bb7dSprj-   if (ranks) {
41830a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
41840a19bb7dSprj-     else *ranks = NULL;
41850a19bb7dSprj-   }
4186502a2867SDave May   PetscFunctionReturn(0);
4187502a2867SDave May }
4188502a2867SDave May 
41891eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
41901eb70e55SToby Isaac 
4191d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
4192d71ae5a4SJacob Faibussowitsch {
4193552f7358SJed Brown   PetscFunctionBegin;
4194552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
41952c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
4196552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
419738221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
4198552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
41991bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
420066ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
4201552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
4202552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
4203184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
42040298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
4205552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
4206f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
42070a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
4208552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
4209bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
4210bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
4211b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
42125a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
4213552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
42140a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
42150a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
4216b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
4217d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
42180298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
42190298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
42200298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
42210298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
4222552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
4223552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
42242adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
4225793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
4226552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
42270709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
42280709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
4229bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
42308c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
4231ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
42320709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
4233b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
42342a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
423528d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
42369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
42379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
42389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
42399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
42409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
42419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
42429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
42436bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
42446bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
42459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
4246c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
4247c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
4248552f7358SJed Brown   PetscFunctionReturn(0);
4249552f7358SJed Brown }
4250552f7358SJed Brown 
4251d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
4252d71ae5a4SJacob Faibussowitsch {
425363a16f15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
425463a16f15SMatthew G. Knepley 
425563a16f15SMatthew G. Knepley   PetscFunctionBegin;
425663a16f15SMatthew G. Knepley   mesh->refct++;
425763a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
42589566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
42599566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
426063a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
426163a16f15SMatthew G. Knepley }
426263a16f15SMatthew G. Knepley 
42638818961aSMatthew G Knepley /*MC
42648818961aSMatthew G Knepley   DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
42658818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
42668818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
42678818961aSMatthew G Knepley                     ownership of the underlying DMPlex points. This is specified by another PetscSection object.
42688818961aSMatthew G Knepley 
4269e5893cccSMatthew G. Knepley   Options Database Keys:
4270250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
4271250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
4272250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
4273250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
4274250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
4275250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
4276250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
4277ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
4278f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
4279f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
4280d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
4281f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
4282250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
4283f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
4284f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
4285f12cf164SMatthew 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
4286f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
4287f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
4288e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
4289e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
4290e5893cccSMatthew G. Knepley 
42918818961aSMatthew G Knepley   Level: intermediate
42928818961aSMatthew G Knepley 
4293db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`
42948818961aSMatthew G Knepley M*/
42958818961aSMatthew G Knepley 
4296d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
4297d71ae5a4SJacob Faibussowitsch {
4298552f7358SJed Brown   DM_Plex *mesh;
4299412e9a14SMatthew G. Knepley   PetscInt unit;
4300552f7358SJed Brown 
4301552f7358SJed Brown   PetscFunctionBegin;
4302552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
43034dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
4304552f7358SJed Brown   dm->data = mesh;
4305552f7358SJed Brown 
4306552f7358SJed Brown   mesh->refct = 1;
43079566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
43089566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
4309552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
4310552f7358SJed Brown   mesh->refinementLimit        = -1.0;
4311e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
43126bc1bd01Sksagiyam   mesh->reorderDefault         = DMPLEX_REORDER_DEFAULT_NOTSET;
43131d1f2f2aSksagiyam   mesh->distributionName       = NULL;
43147d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
43157d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
4316552f7358SJed Brown 
43179566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
43182e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
4319d9deefdfSMatthew G. Knepley 
43208865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
4321552f7358SJed Brown 
4322df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
4323ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
43246113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
4325552f7358SJed Brown 
43269566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
4327552f7358SJed Brown   PetscFunctionReturn(0);
4328552f7358SJed Brown }
4329552f7358SJed Brown 
4330552f7358SJed Brown /*@
4331552f7358SJed Brown   DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
4332552f7358SJed Brown 
4333d083f849SBarry Smith   Collective
4334552f7358SJed Brown 
4335552f7358SJed Brown   Input Parameter:
4336552f7358SJed Brown . comm - The communicator for the DMPlex object
4337552f7358SJed Brown 
4338552f7358SJed Brown   Output Parameter:
4339552f7358SJed Brown . mesh  - The DMPlex object
4340552f7358SJed Brown 
4341552f7358SJed Brown   Level: beginner
4342552f7358SJed Brown 
4343552f7358SJed Brown @*/
4344d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
4345d71ae5a4SJacob Faibussowitsch {
4346552f7358SJed Brown   PetscFunctionBegin;
4347552f7358SJed Brown   PetscValidPointer(mesh, 2);
43489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
43499566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
4350552f7358SJed Brown   PetscFunctionReturn(0);
4351552f7358SJed Brown }
4352552f7358SJed Brown 
4353b09969d6SVaclav Hapla /*@C
4354b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output)
4355b09969d6SVaclav Hapla 
4356b09969d6SVaclav Hapla   Input Parameters:
4357b09969d6SVaclav Hapla + dm - The DM
4358b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4359325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE
4360325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE
4361b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
43625e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4363b09969d6SVaclav Hapla 
4364be8c289dSNicolas Barral   Output Parameters:
4365be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership
4366be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4367b09969d6SVaclav Hapla 
4368b09969d6SVaclav Hapla   Notes:
4369b09969d6SVaclav Hapla   Two triangles sharing a face
4370b09969d6SVaclav Hapla $
4371b09969d6SVaclav Hapla $        2
4372b09969d6SVaclav Hapla $      / | \
4373b09969d6SVaclav Hapla $     /  |  \
4374b09969d6SVaclav Hapla $    /   |   \
4375b09969d6SVaclav Hapla $   0  0 | 1  3
4376b09969d6SVaclav Hapla $    \   |   /
4377b09969d6SVaclav Hapla $     \  |  /
4378b09969d6SVaclav Hapla $      \ | /
4379b09969d6SVaclav Hapla $        1
4380b09969d6SVaclav Hapla would have input
4381b09969d6SVaclav Hapla $  numCells = 2, numVertices = 4
4382b09969d6SVaclav Hapla $  cells = [0 1 2  1 3 2]
4383b09969d6SVaclav Hapla $
4384b09969d6SVaclav Hapla which would result in the DMPlex
4385b09969d6SVaclav Hapla $
4386b09969d6SVaclav Hapla $        4
4387b09969d6SVaclav Hapla $      / | \
4388b09969d6SVaclav Hapla $     /  |  \
4389b09969d6SVaclav Hapla $    /   |   \
4390b09969d6SVaclav Hapla $   2  0 | 1  5
4391b09969d6SVaclav Hapla $    \   |   /
4392b09969d6SVaclav Hapla $     \  |  /
4393b09969d6SVaclav Hapla $      \ | /
4394b09969d6SVaclav Hapla $        3
4395b09969d6SVaclav Hapla 
439625b6865aSVaclav Hapla   Vertices are implicitly numbered consecutively 0,...,NVertices.
439725b6865aSVaclav Hapla   Each rank owns a chunk of numVertices consecutive vertices.
439825b6865aSVaclav Hapla   If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout.
4399325d53feSBarry Smith   If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
4400325d53feSBarry Smith   If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks.
440125b6865aSVaclav Hapla 
4402b09969d6SVaclav Hapla   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
4403b09969d6SVaclav Hapla 
4404b09969d6SVaclav Hapla   Not currently supported in Fortran.
4405b09969d6SVaclav Hapla 
4406b09969d6SVaclav Hapla   Level: advanced
4407b09969d6SVaclav Hapla 
4408db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`
4409b09969d6SVaclav Hapla @*/
4410d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
4411d71ae5a4SJacob Faibussowitsch {
44122464107aSksagiyam   PetscSF     sfPoint;
44132464107aSksagiyam   PetscLayout layout;
441482fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
4415a47d0d45SMatthew G. Knepley 
4416a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
441725b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
44189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
441925b6865aSVaclav Hapla   /* Get/check global number of vertices */
442025b6865aSVaclav Hapla   {
442125b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
442225b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
442325b6865aSVaclav Hapla 
442425b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
442525b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
44269371c9d4SSatish Balay     for (i = 0; i < len; i++)
44279371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
442825b6865aSVaclav Hapla     ++NVerticesInCells;
44299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
443025b6865aSVaclav Hapla 
443125b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
44329371c9d4SSatish Balay     else
44339371c9d4SSatish 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);
443425b6865aSVaclav Hapla   }
44359079aca8SVaclav Hapla   /* Count locally unique vertices */
44369079aca8SVaclav Hapla   {
44379079aca8SVaclav Hapla     PetscHSetI vhash;
44389079aca8SVaclav Hapla     PetscInt   off = 0;
44399079aca8SVaclav Hapla 
44409566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
4441a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
444248a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
4443a47d0d45SMatthew G. Knepley     }
44449566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
44459566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
4446ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
44479566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
44489566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
444963a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
4450a47d0d45SMatthew G. Knepley   }
44519566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
4452a47d0d45SMatthew G. Knepley   /* Create cones */
44539566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
44549566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
44559566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
44569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4457a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
4458a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
4459a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
4460a47d0d45SMatthew G. Knepley       PetscInt       lv;
4461a47d0d45SMatthew G. Knepley 
44629079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
44639079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
44649566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
446563a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
4466961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
4467a47d0d45SMatthew G. Knepley     }
4468a47d0d45SMatthew G. Knepley   }
44692464107aSksagiyam   /* Build point sf */
44709566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
44719566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
44729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
44739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44749566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
44759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
44769566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
44779566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
44782464107aSksagiyam   if (dm->sf) {
44792464107aSksagiyam     const char *prefix;
44802464107aSksagiyam 
44819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
44829566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
44832464107aSksagiyam   }
44849566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
44859566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
44869566063dSJacob Faibussowitsch   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4487a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
44889566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
44899566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
44909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4491a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4492a47d0d45SMatthew G. Knepley }
4493a47d0d45SMatthew G. Knepley 
4494b09969d6SVaclav Hapla /*@C
4495b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4496b09969d6SVaclav Hapla 
4497b09969d6SVaclav Hapla   Input Parameters:
4498b09969d6SVaclav Hapla + dm - The DM
4499b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4500b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership
4501b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4502b09969d6SVaclav Hapla 
4503b09969d6SVaclav Hapla   Level: advanced
4504b09969d6SVaclav Hapla 
4505b09969d6SVaclav Hapla   Notes:
4506b09969d6SVaclav Hapla   Not currently supported in Fortran.
4507b09969d6SVaclav Hapla 
4508db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
4509b09969d6SVaclav Hapla @*/
4510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
4511d71ae5a4SJacob Faibussowitsch {
4512a47d0d45SMatthew G. Knepley   PetscSection coordSection;
4513a47d0d45SMatthew G. Knepley   Vec          coordinates;
4514a47d0d45SMatthew G. Knepley   PetscScalar *coords;
45151edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4516a47d0d45SMatthew G. Knepley 
4517a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
45199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
45201dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
45219566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
45229566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
45231dca8a05SBarry 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);
45249566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
45259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
45269566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
45279566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
45281edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
45299566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
45309566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4531a47d0d45SMatthew G. Knepley   }
45329566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
45339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
45349566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
45359566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
45369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
45379566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
45389566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
45399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4540a47d0d45SMatthew G. Knepley   {
4541a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4542a47d0d45SMatthew G. Knepley 
4543a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
45449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
45459566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
454621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
454721016a8bSBarry Smith     {
454821016a8bSBarry Smith       PetscScalar *svertexCoords;
454921016a8bSBarry Smith       PetscInt     i;
45509566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
45513612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
45529566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45539566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45549566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
455521016a8bSBarry Smith     }
455621016a8bSBarry Smith #else
45579566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
45589566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
455921016a8bSBarry Smith #endif
45609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
4561a47d0d45SMatthew G. Knepley   }
45629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
45639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
45649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
45659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4566a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4567a47d0d45SMatthew G. Knepley }
4568a47d0d45SMatthew G. Knepley 
4569c3edce3dSSatish Balay /*@
4570b09969d6SVaclav Hapla   DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output)
4571a47d0d45SMatthew G. Knepley 
4572a47d0d45SMatthew G. Knepley   Input Parameters:
4573a47d0d45SMatthew G. Knepley + comm - The communicator
4574a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4575a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
457625b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE
457725b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE
4578a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4579a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4580a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4581a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4582a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4583a47d0d45SMatthew G. Knepley 
4584d8d19677SJose E. Roman   Output Parameters:
458518d54ad4SMichael Lange + dm - The DM
4586be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership
4587be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4588a47d0d45SMatthew G. Knepley 
4589b09969d6SVaclav Hapla   Notes:
4590b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(),
4591b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel()
4592a47d0d45SMatthew G. Knepley 
459325b6865aSVaclav Hapla   See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters.
459425b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters.
459525b6865aSVaclav Hapla 
4596b09969d6SVaclav Hapla   Level: intermediate
4597a47d0d45SMatthew G. Knepley 
4598db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
4599a47d0d45SMatthew G. Knepley @*/
4600d71ae5a4SJacob 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)
4601d71ae5a4SJacob Faibussowitsch {
4602a47d0d45SMatthew G. Knepley   PetscSF sfVert;
4603a47d0d45SMatthew G. Knepley 
4604a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
46059566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
46069566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4607a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4608064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
46099566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
46109566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4611a47d0d45SMatthew G. Knepley   if (interpolate) {
46125fd9971aSMatthew G. Knepley     DM idm;
4613a47d0d45SMatthew G. Knepley 
46149566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
46159566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
4616a47d0d45SMatthew G. Knepley     *dm = idm;
4617a47d0d45SMatthew G. Knepley   }
46189566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
461918d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
46209566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
4621a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4622a47d0d45SMatthew G. Knepley }
4623a47d0d45SMatthew G. Knepley 
4624b09969d6SVaclav Hapla /*@C
4625b09969d6SVaclav Hapla   DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output)
46269298eaa6SMatthew G Knepley 
46279298eaa6SMatthew G Knepley   Input Parameters:
4628b09969d6SVaclav Hapla + dm - The DM
4629b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4630325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE
46319298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
46325e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
46339298eaa6SMatthew G Knepley 
4634b09969d6SVaclav Hapla   Level: advanced
46359298eaa6SMatthew G Knepley 
4636b09969d6SVaclav Hapla   Notes:
4637b09969d6SVaclav Hapla   Two triangles sharing a face
46389298eaa6SMatthew G Knepley $
46399298eaa6SMatthew G Knepley $        2
46409298eaa6SMatthew G Knepley $      / | \
46419298eaa6SMatthew G Knepley $     /  |  \
46429298eaa6SMatthew G Knepley $    /   |   \
46439298eaa6SMatthew G Knepley $   0  0 | 1  3
46449298eaa6SMatthew G Knepley $    \   |   /
46459298eaa6SMatthew G Knepley $     \  |  /
46469298eaa6SMatthew G Knepley $      \ | /
46479298eaa6SMatthew G Knepley $        1
46489298eaa6SMatthew G Knepley would have input
46499298eaa6SMatthew G Knepley $  numCells = 2, numVertices = 4
46509298eaa6SMatthew G Knepley $  cells = [0 1 2  1 3 2]
46519298eaa6SMatthew G Knepley $
46529298eaa6SMatthew G Knepley which would result in the DMPlex
46539298eaa6SMatthew G Knepley $
46549298eaa6SMatthew G Knepley $        4
46559298eaa6SMatthew G Knepley $      / | \
46569298eaa6SMatthew G Knepley $     /  |  \
46579298eaa6SMatthew G Knepley $    /   |   \
46589298eaa6SMatthew G Knepley $   2  0 | 1  5
46599298eaa6SMatthew G Knepley $    \   |   /
46609298eaa6SMatthew G Knepley $     \  |  /
46619298eaa6SMatthew G Knepley $      \ | /
46629298eaa6SMatthew G Knepley $        3
46639298eaa6SMatthew G Knepley 
4664325d53feSBarry Smith   If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1.
466525b6865aSVaclav Hapla 
4666b09969d6SVaclav Hapla   Not currently supported in Fortran.
46679298eaa6SMatthew G Knepley 
4668db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
4669b09969d6SVaclav Hapla @*/
4670d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
4671d71ae5a4SJacob Faibussowitsch {
4672961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
4673b09969d6SVaclav Hapla 
4674b09969d6SVaclav Hapla   PetscFunctionBegin;
46759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
46769566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
467725b6865aSVaclav Hapla   /* Get/check global number of vertices */
467825b6865aSVaclav Hapla   {
467925b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
468025b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
468125b6865aSVaclav Hapla 
468225b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
468325b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
46849371c9d4SSatish Balay     for (i = 0; i < len; i++)
46859371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
468625b6865aSVaclav Hapla     ++NVerticesInCells;
468725b6865aSVaclav Hapla 
468825b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
46899371c9d4SSatish Balay     else
46909371c9d4SSatish 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);
469125b6865aSVaclav Hapla   }
46929566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
469348a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
46949566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
46959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4696b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4697ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
4698b09969d6SVaclav Hapla   }
46999566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
47009566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
47019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4702b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4703b09969d6SVaclav Hapla }
4704b09969d6SVaclav Hapla 
4705b09969d6SVaclav Hapla /*@C
4706b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4707b09969d6SVaclav Hapla 
4708b09969d6SVaclav Hapla   Input Parameters:
4709b09969d6SVaclav Hapla + dm - The DM
4710b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4711b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4712b09969d6SVaclav Hapla 
4713b09969d6SVaclav Hapla   Level: advanced
4714b09969d6SVaclav Hapla 
4715b09969d6SVaclav Hapla   Notes:
4716b09969d6SVaclav Hapla   Not currently supported in Fortran.
4717b09969d6SVaclav Hapla 
4718db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
4719b09969d6SVaclav Hapla @*/
4720d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
4721d71ae5a4SJacob Faibussowitsch {
4722b09969d6SVaclav Hapla   PetscSection coordSection;
4723b09969d6SVaclav Hapla   Vec          coordinates;
4724b09969d6SVaclav Hapla   DM           cdm;
4725b09969d6SVaclav Hapla   PetscScalar *coords;
47261edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
4727b09969d6SVaclav Hapla 
4728b09969d6SVaclav Hapla   PetscFunctionBegin;
47299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
47309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
47311dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
47329566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
47339566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
47349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
47359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
47369566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
47371edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
47389566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
47399566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4740b09969d6SVaclav Hapla   }
47419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4742b09969d6SVaclav Hapla 
47439566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
47449566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
47459566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
47469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
47479566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
47481edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
4749ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
4750b09969d6SVaclav Hapla   }
47519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
47529566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
47539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
47549566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4755b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4756b09969d6SVaclav Hapla }
4757b09969d6SVaclav Hapla 
4758b09969d6SVaclav Hapla /*@
47593df08285SMatthew G. Knepley   DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
47603df08285SMatthew G. Knepley 
47613df08285SMatthew G. Knepley   Collective on comm
4762b09969d6SVaclav Hapla 
4763b09969d6SVaclav Hapla   Input Parameters:
4764b09969d6SVaclav Hapla + comm - The communicator
4765b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
47663df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
47673df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0
47683df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4769b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
47703df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4771b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
47723df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4773b09969d6SVaclav Hapla 
4774b09969d6SVaclav Hapla   Output Parameter:
47753df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0
4776b09969d6SVaclav Hapla 
4777b09969d6SVaclav Hapla   Notes:
4778b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(),
4779b09969d6SVaclav Hapla   DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList()
4780b09969d6SVaclav Hapla 
478125b6865aSVaclav Hapla   See DMPlexBuildFromCellList() for an example and details about the topology-related parameters.
478225b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters.
47833df08285SMatthew G. Knepley   See DMPlexCreateFromCellListParallelPetsc() for parallel input
478425b6865aSVaclav Hapla 
4785b09969d6SVaclav Hapla   Level: intermediate
4786b09969d6SVaclav Hapla 
4787db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
47889298eaa6SMatthew G Knepley @*/
4789d71ae5a4SJacob 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)
4790d71ae5a4SJacob Faibussowitsch {
47913df08285SMatthew G. Knepley   PetscMPIInt rank;
47929298eaa6SMatthew G Knepley 
47939298eaa6SMatthew G Knepley   PetscFunctionBegin;
479428b400f6SJacob 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.");
47959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
47969566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
47979566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
47989566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
4799c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
48009566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
48019298eaa6SMatthew G Knepley   if (interpolate) {
48025fd9971aSMatthew G. Knepley     DM idm;
48039298eaa6SMatthew G Knepley 
48049566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
48059566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
48069298eaa6SMatthew G Knepley     *dm = idm;
48079298eaa6SMatthew G Knepley   }
4808c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
48099566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
48109298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
48119298eaa6SMatthew G Knepley }
48129298eaa6SMatthew G Knepley 
4813939f6067SMatthew G. Knepley /*@
4814939f6067SMatthew 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
4815939f6067SMatthew G. Knepley 
4816939f6067SMatthew G. Knepley   Input Parameters:
4817c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4818939f6067SMatthew G. Knepley . depth - The depth of the DAG
4819367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4820939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4821939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4822939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4823367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4824939f6067SMatthew G. Knepley 
4825939f6067SMatthew G. Knepley   Output Parameter:
4826939f6067SMatthew G. Knepley . dm - The DM
4827939f6067SMatthew G. Knepley 
4828939f6067SMatthew G. Knepley   Note: Two triangles sharing a face would have input
4829939f6067SMatthew G. Knepley $  depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4830939f6067SMatthew G. Knepley $  cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4831939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4832939f6067SMatthew G. Knepley $
4833939f6067SMatthew G. Knepley which would result in the DMPlex
4834939f6067SMatthew G. Knepley $
4835939f6067SMatthew G. Knepley $        4
4836939f6067SMatthew G. Knepley $      / | \
4837939f6067SMatthew G. Knepley $     /  |  \
4838939f6067SMatthew G. Knepley $    /   |   \
4839939f6067SMatthew G. Knepley $   2  0 | 1  5
4840939f6067SMatthew G. Knepley $    \   |   /
4841939f6067SMatthew G. Knepley $     \  |  /
4842939f6067SMatthew G. Knepley $      \ | /
4843939f6067SMatthew G. Knepley $        3
4844939f6067SMatthew G. Knepley $
4845a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc()
4846939f6067SMatthew G. Knepley 
4847939f6067SMatthew G. Knepley   Level: advanced
4848939f6067SMatthew G. Knepley 
4849db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
4850939f6067SMatthew G. Knepley @*/
4851d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
4852d71ae5a4SJacob Faibussowitsch {
48539298eaa6SMatthew G Knepley   Vec          coordinates;
48549298eaa6SMatthew G Knepley   PetscSection coordSection;
48559298eaa6SMatthew G Knepley   PetscScalar *coords;
4856811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
48579298eaa6SMatthew G Knepley 
48589298eaa6SMatthew G Knepley   PetscFunctionBegin;
48599566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
48609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
486163a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
48629298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
48639566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
48649298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
48659566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
4866ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
486797e052ccSToby Isaac   }
48681dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
48699566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
48709298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
48719566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
48729566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
48739298eaa6SMatthew G Knepley   }
48749566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
48759566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
48769298eaa6SMatthew G Knepley   /* Build coordinates */
48779566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
48789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
48799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
48809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
48819298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
48829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
48839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
48849298eaa6SMatthew G Knepley   }
48859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
48869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
48879566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
48889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
48899566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
48909566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
48919566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
48929318fe57SMatthew G. Knepley   if (vertexCoords) {
48939566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
48949298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
48959298eaa6SMatthew G Knepley       PetscInt off;
48969298eaa6SMatthew G Knepley 
48979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
4898ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
48999298eaa6SMatthew G Knepley     }
49009318fe57SMatthew G. Knepley   }
49019566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
49029566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
49039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
49049298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
49059298eaa6SMatthew G Knepley }
49068415267dSToby Isaac 
4907ca522641SMatthew G. Knepley /*@C
49088ca92349SMatthew G. Knepley   DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file.
49098ca92349SMatthew G. Knepley 
49108ca92349SMatthew G. Knepley + comm        - The MPI communicator
49118ca92349SMatthew G. Knepley . filename    - Name of the .dat file
49128ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
49138ca92349SMatthew G. Knepley 
49148ca92349SMatthew G. Knepley   Output Parameter:
49158ca92349SMatthew G. Knepley . dm  - The DM object representing the mesh
49168ca92349SMatthew G. Knepley 
49178ca92349SMatthew G. Knepley   Note: The format is the simplest possible:
49188ca92349SMatthew G. Knepley $ Ne
49198ca92349SMatthew G. Knepley $ v0 v1 ... vk
49208ca92349SMatthew G. Knepley $ Nv
49218ca92349SMatthew G. Knepley $ x y z marker
49228ca92349SMatthew G. Knepley 
49238ca92349SMatthew G. Knepley   Level: beginner
49248ca92349SMatthew G. Knepley 
4925db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
49268ca92349SMatthew G. Knepley @*/
4927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
4928d71ae5a4SJacob Faibussowitsch {
49298ca92349SMatthew G. Knepley   DMLabel      marker;
49308ca92349SMatthew G. Knepley   PetscViewer  viewer;
49318ca92349SMatthew G. Knepley   Vec          coordinates;
49328ca92349SMatthew G. Knepley   PetscSection coordSection;
49338ca92349SMatthew G. Knepley   PetscScalar *coords;
49348ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
49358ca92349SMatthew G. Knepley   PetscInt     dim = 3, cdim = 3, coordSize, v, c, d;
49368ca92349SMatthew G. Knepley   PetscMPIInt  rank;
4937f8d5e320SMatthew G. Knepley   int          snum, Nv, Nc, Ncn, Nl;
49388ca92349SMatthew G. Knepley 
49398ca92349SMatthew G. Knepley   PetscFunctionBegin;
49409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
49419566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
49429566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
49439566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
49449566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
4945dd400576SPatrick Sanan   if (rank == 0) {
49469566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4947f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
494808401ef6SPierre Jolivet     PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
494925ce1634SJed Brown   } else {
4950f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
49518ca92349SMatthew G. Knepley   }
49529566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
49539566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
49549566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
49559566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
49569566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
49578ca92349SMatthew G. Knepley   /* Read topology */
4958dd400576SPatrick Sanan   if (rank == 0) {
4959f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
4960f8d5e320SMatthew G. Knepley     PetscInt cone[8];
49618ca92349SMatthew G. Knepley     int      vbuf[8], v;
49628ca92349SMatthew G. Knepley 
49639371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
49649371c9d4SSatish Balay       format[c * 3 + 0] = '%';
49659371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
49669371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
49679371c9d4SSatish Balay     }
4968f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
49699566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
49709566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
49718ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
49729566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
4973f8d5e320SMatthew G. Knepley       switch (Ncn) {
4974d71ae5a4SJacob Faibussowitsch       case 2:
4975d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
4976d71ae5a4SJacob Faibussowitsch         break;
4977d71ae5a4SJacob Faibussowitsch       case 3:
4978d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
4979d71ae5a4SJacob Faibussowitsch         break;
4980d71ae5a4SJacob Faibussowitsch       case 4:
4981d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
4982d71ae5a4SJacob Faibussowitsch         break;
4983d71ae5a4SJacob Faibussowitsch       case 6:
4984d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
4985d71ae5a4SJacob Faibussowitsch         break;
4986d71ae5a4SJacob Faibussowitsch       case 8:
4987d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
4988d71ae5a4SJacob Faibussowitsch         break;
4989d71ae5a4SJacob Faibussowitsch       default:
4990d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
4991f8d5e320SMatthew G. Knepley       }
499208401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4993f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
49948ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
4995f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
49968ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
49978ca92349SMatthew G. Knepley         cone[1]      = cone[3];
49988ca92349SMatthew G. Knepley         cone[3]      = tmp;
49998ca92349SMatthew G. Knepley       }
50009566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
50018ca92349SMatthew G. Knepley     }
50028ca92349SMatthew G. Knepley   }
50039566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
50049566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
50058ca92349SMatthew G. Knepley   /* Read coordinates */
50069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
50079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
50089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
50099566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
50108ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
50119566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
50129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
50138ca92349SMatthew G. Knepley   }
50149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
50159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
50169566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
50179566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
50189566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
50199566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
50209566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
50219566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5022dd400576SPatrick Sanan   if (rank == 0) {
5023f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
50248ca92349SMatthew G. Knepley     double x[3];
5025f8d5e320SMatthew G. Knepley     int    l, val[3];
50268ca92349SMatthew G. Knepley 
5027f8d5e320SMatthew G. Knepley     if (Nl) {
50289371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
50299371c9d4SSatish Balay         format[l * 3 + 0] = '%';
50309371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
50319371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
50329371c9d4SSatish Balay       }
5033f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
50349566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50359566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
5036f8d5e320SMatthew G. Knepley     }
50378ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
50389566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
5039f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
504008401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5041f8d5e320SMatthew G. Knepley       switch (Nl) {
5042d71ae5a4SJacob Faibussowitsch       case 0:
5043d71ae5a4SJacob Faibussowitsch         snum = 0;
5044d71ae5a4SJacob Faibussowitsch         break;
5045d71ae5a4SJacob Faibussowitsch       case 1:
5046d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
5047d71ae5a4SJacob Faibussowitsch         break;
5048d71ae5a4SJacob Faibussowitsch       case 2:
5049d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
5050d71ae5a4SJacob Faibussowitsch         break;
5051d71ae5a4SJacob Faibussowitsch       case 3:
5052d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
5053d71ae5a4SJacob Faibussowitsch         break;
5054d71ae5a4SJacob Faibussowitsch       default:
5055d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
5056f8d5e320SMatthew G. Knepley       }
505708401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
50588ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
50599566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
50608ca92349SMatthew G. Knepley     }
50618ca92349SMatthew G. Knepley   }
50629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
50639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
50649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
50659566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
50668ca92349SMatthew G. Knepley   if (interpolate) {
50678ca92349SMatthew G. Knepley     DM      idm;
50688ca92349SMatthew G. Knepley     DMLabel bdlabel;
50698ca92349SMatthew G. Knepley 
50709566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
50719566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
50728ca92349SMatthew G. Knepley     *dm = idm;
50738ca92349SMatthew G. Knepley 
5074f8d5e320SMatthew G. Knepley     if (!Nl) {
50759566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50769566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
50779566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
50789566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
50798ca92349SMatthew G. Knepley     }
5080f8d5e320SMatthew G. Knepley   }
50818ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
50828ca92349SMatthew G. Knepley }
50838ca92349SMatthew G. Knepley 
50848ca92349SMatthew G. Knepley /*@C
5085ca522641SMatthew G. Knepley   DMPlexCreateFromFile - This takes a filename and produces a DM
5086ca522641SMatthew G. Knepley 
5087ca522641SMatthew G. Knepley   Input Parameters:
5088ca522641SMatthew G. Knepley + comm - The communicator
5089ca522641SMatthew G. Knepley . filename - A file name
5090cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats
5091ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
5092ca522641SMatthew G. Knepley 
5093ca522641SMatthew G. Knepley   Output Parameter:
5094ca522641SMatthew G. Knepley . dm - The DM
5095ca522641SMatthew G. Knepley 
509602ef0d99SVaclav Hapla   Options Database Keys:
509702ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5
509802ef0d99SVaclav Hapla 
5099bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
5100bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
5101bca97951SVaclav Hapla 
5102cd7e8a5eSksagiyam   Notes:
5103cd7e8a5eSksagiyam   Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex
5104cd7e8a5eSksagiyam   meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName()
5105cd7e8a5eSksagiyam   before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object.
5106cd7e8a5eSksagiyam   The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally
5107cd7e8a5eSksagiyam   calls DMLoad(). Currently, name is ignored for other viewer types and/or formats.
5108cd7e8a5eSksagiyam 
5109ca522641SMatthew G. Knepley   Level: beginner
5110ca522641SMatthew G. Knepley 
5111db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
5112ca522641SMatthew G. Knepley @*/
5113d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
5114d71ae5a4SJacob Faibussowitsch {
5115ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
5116ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
5117ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
5118ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
5119ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
5120ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
5121ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
5122ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
5123ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
5124ef3a5affSJacob Faibussowitsch   const char  extMed[]       = ".med";
5125ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
5126ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
5127ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
5128ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
5129ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
5130ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
5131ca522641SMatthew G. Knepley   size_t      len;
5132c1cad2e7SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
5133ca522641SMatthew G. Knepley   PetscMPIInt rank;
5134ca522641SMatthew G. Knepley 
5135ca522641SMatthew G. Knepley   PetscFunctionBegin;
51365d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
51370d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
5138cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
51399566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
51409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
51419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
51429566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
514328b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
5144ef3a5affSJacob Faibussowitsch 
51459371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
51469371c9d4SSatish Balay   do { \
5147274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
5148274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
5149274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
5150274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
5151ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
5152ef3a5affSJacob Faibussowitsch     } else { \
5153274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
5154ef3a5affSJacob Faibussowitsch     } \
5155ef3a5affSJacob Faibussowitsch   } while (0)
5156ef3a5affSJacob Faibussowitsch 
5157ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
5158ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
5159ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
5160ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
5161ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
5162ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
5163ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
5164ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
5165ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
5166ef3a5affSJacob Faibussowitsch   CheckExtension(extMed, isMed);
5167ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
5168ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
5169ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
5170ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
5171ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
5172ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
5173ef3a5affSJacob Faibussowitsch 
5174ef3a5affSJacob Faibussowitsch #undef CheckExtension
5175ef3a5affSJacob Faibussowitsch 
5176de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
51779566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
5178ca522641SMatthew G. Knepley   } else if (isCGNS) {
51799566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
518090c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
51819566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
51822f0bd6dcSMichael Lange   } else if (isFluent) {
51839566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
5184cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
51859c48423bSVaclav Hapla     PetscBool   load_hdf5_xdmf = PETSC_FALSE;
5186cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
5187cc2f8f65SMatthew G. Knepley 
518843b242b4SVaclav 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 */
51899566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf));
51909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
51919566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
51929566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
51939566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
51949566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
51959566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
51969566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
5197cd7e8a5eSksagiyam 
51989566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
51999566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52009566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
52019566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
52029566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
52039566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer));
52049566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
52055fd9971aSMatthew G. Knepley 
52065fd9971aSMatthew G. Knepley     if (interpolate) {
52075fd9971aSMatthew G. Knepley       DM idm;
52085fd9971aSMatthew G. Knepley 
52099566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
52109566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52115fd9971aSMatthew G. Knepley       *dm = idm;
52125fd9971aSMatthew G. Knepley     }
5213707dd687SMichael Lange   } else if (isMed) {
52149566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
5215f2801cd6SMatthew G. Knepley   } else if (isPLY) {
52169566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
5217c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
52189566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
52199566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
52207bee2925SMatthew Knepley     if (!interpolate) {
52217bee2925SMatthew Knepley       DM udm;
52227bee2925SMatthew Knepley 
52239566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
52249566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52257bee2925SMatthew Knepley       *dm = udm;
52267bee2925SMatthew Knepley     }
52278ca92349SMatthew G. Knepley   } else if (isCV) {
52289566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
522998921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
52309566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
52319566063dSJacob Faibussowitsch   if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
5233ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
5234ca522641SMatthew G. Knepley }
52359f6c5813SMatthew G. Knepley /*@C
52369f6c5813SMatthew 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.
52379f6c5813SMatthew G. Knepley 
52389f6c5813SMatthew G. Knepley   Input Parameter:
52399f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform`
52409f6c5813SMatthew G. Knepley 
52419f6c5813SMatthew G. Knepley   Output Parameter:
52429f6c5813SMatthew G. Knepley . dm - The `DM`
52439f6c5813SMatthew G. Knepley 
52449f6c5813SMatthew G. Knepley   Notes:
52459f6c5813SMatthew 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.
52469f6c5813SMatthew G. Knepley 
52479f6c5813SMatthew G. Knepley   Level: beginner
52489f6c5813SMatthew G. Knepley 
52499f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
52509f6c5813SMatthew G. Knepley @*/
52519f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm)
52529f6c5813SMatthew G. Knepley {
52539f6c5813SMatthew G. Knepley   DM       bdm;
52549f6c5813SMatthew G. Knepley   PetscInt Nl;
52559f6c5813SMatthew G. Knepley 
52569f6c5813SMatthew G. Knepley   PetscFunctionBegin;
52579f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
52589f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
52599f6c5813SMatthew G. Knepley   PetscCall(DMSetFromOptions(*dm));
52609f6c5813SMatthew G. Knepley 
52619f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
52629f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
52639f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
52649f6c5813SMatthew G. Knepley 
52659f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformGetDM(tr, &bdm));
52669f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
52679f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
52689f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
52699f6c5813SMatthew G. Knepley     const char *lname;
52709f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
52719f6c5813SMatthew G. Knepley 
52729f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
52739f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
52749f6c5813SMatthew G. Knepley     if (isDepth) continue;
52759f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
52769f6c5813SMatthew G. Knepley     if (isCellType) continue;
52779f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
52789f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
52799f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
52809f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
52819f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
52829f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
52839f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
52849f6c5813SMatthew G. Knepley   }
52859f6c5813SMatthew G. Knepley   PetscFunctionReturn(0);
52869f6c5813SMatthew G. Knepley }
5287