xref: /petsc/src/dm/impls/plex/plexcreate.c (revision 69d8a87b57872cb4586ea620a05b6507f496830b)
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>
6b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
7b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
8552f7358SJed Brown 
9b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1058cd63d5SVaclav Hapla 
119318fe57SMatthew G. Knepley /* External function declarations here */
129318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
139318fe57SMatthew G. Knepley 
14e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
159371c9d4SSatish Balay PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) {
164fb89dddSMatthew G. Knepley   const PetscReal         *maxCell, *Lstart, *L;
176858538eSMatthew G. Knepley   PetscBool                dist;
186bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
19e600fa54SMatthew G. Knepley 
20e600fa54SMatthew G. Knepley   PetscFunctionBegin;
21e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
224fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
234fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
24e600fa54SMatthew G. Knepley   }
259566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
269566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
276bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
286bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
29e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
301baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
31e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
32e600fa54SMatthew G. Knepley }
33e600fa54SMatthew G. Knepley 
349318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
359318fe57SMatthew G. Knepley    - Share the DM_Plex structure
369318fe57SMatthew G. Knepley    - Share the coordinates
379318fe57SMatthew G. Knepley    - Share the SF
389318fe57SMatthew G. Knepley */
39*69d8a87bSksagiyam PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) {
409318fe57SMatthew G. Knepley   PetscSF          sf;
419318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
429318fe57SMatthew G. Knepley   Vec              coords;
434fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
449318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
459318fe57SMatthew G. Knepley 
469318fe57SMatthew G. Knepley   PetscFunctionBegin;
479318fe57SMatthew G. Knepley   if (dm == dmNew) {
489566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
499318fe57SMatthew G. Knepley     PetscFunctionReturn(0);
509318fe57SMatthew G. Knepley   }
519318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
529566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
539566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
549566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
559566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
569566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
579566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
609566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
619566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
626858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
636858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
646858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
656858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
669318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
676858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
686858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
6961a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
704fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
714fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
729566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
739566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
749318fe57SMatthew G. Knepley   dm->data = dmNew->data;
759318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
769566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
779566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
789566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
799566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
809566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
819318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
829318fe57SMatthew G. Knepley }
839318fe57SMatthew G. Knepley 
849318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
859318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
869318fe57SMatthew G. Knepley    - Swap the coordinates
879318fe57SMatthew G. Knepley    - Swap the point PetscSF
889318fe57SMatthew G. Knepley */
899371c9d4SSatish Balay static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) {
909318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
919318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
929318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
939318fe57SMatthew G. Knepley   DMField     fieldTmp;
949318fe57SMatthew G. Knepley   void       *tmp;
959318fe57SMatthew G. Knepley   DMLabelLink listTmp;
969318fe57SMatthew G. Knepley   DMLabel     depthTmp;
979318fe57SMatthew G. Knepley   PetscInt    tmpI;
989318fe57SMatthew G. Knepley 
999318fe57SMatthew G. Knepley   PetscFunctionBegin;
1009318fe57SMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
1019566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
1029566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
1039566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
1049566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
1059566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
1069566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
1079318fe57SMatthew G. Knepley 
1089566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
1099566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
1109566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1119566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
1129566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
1139566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1149318fe57SMatthew G. Knepley 
1159566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
1169566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
1179566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
1189566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
1199566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
1209566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1219318fe57SMatthew G. Knepley 
1226858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
1236858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
1246858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1256858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
1266858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
1276858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1286858538eSMatthew G. Knepley 
1296858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
1306858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
1316858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
1326858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
1336858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
1346858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1356858538eSMatthew G. Knepley 
1366858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
1376858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
1386858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
1396858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
1406858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
1416858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
1429318fe57SMatthew G. Knepley   tmp                       = dmA->data;
1439318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
1449318fe57SMatthew G. Knepley   dmB->data                 = tmp;
1459318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
1469318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
1479318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
1489318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
1499318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
1509318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
1519318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
1529318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
1539318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
1549318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
1559318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
1569318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
1579318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1589318fe57SMatthew G. Knepley }
1599318fe57SMatthew G. Knepley 
1609371c9d4SSatish Balay static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) {
1619318fe57SMatthew G. Knepley   DM idm;
1629318fe57SMatthew G. Knepley 
1639318fe57SMatthew G. Knepley   PetscFunctionBegin;
1649566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
1659566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
166*69d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
1679318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1689318fe57SMatthew G. Knepley }
1699318fe57SMatthew G. Knepley 
1709318fe57SMatthew G. Knepley /*@C
1719318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
1729318fe57SMatthew G. Knepley 
1739318fe57SMatthew G. Knepley   Collective
1749318fe57SMatthew G. Knepley 
1759318fe57SMatthew G. Knepley   Input Parameters:
1769318fe57SMatthew G. Knepley + DM        - The DM
1774f9ab2b4SJed Brown . degree    - The degree of the finite element or PETSC_DECIDE
1789318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
1799318fe57SMatthew G. Knepley 
1809318fe57SMatthew G. Knepley   Level: advanced
1819318fe57SMatthew G. Knepley 
182db781477SPatrick Sanan .seealso: `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
1839318fe57SMatthew G. Knepley @*/
1849371c9d4SSatish Balay PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc) {
1859318fe57SMatthew G. Knepley   DM_Plex     *mesh = (DM_Plex *)dm->data;
1869318fe57SMatthew G. Knepley   DM           cdm;
1879318fe57SMatthew G. Knepley   PetscDS      cds;
1889318fe57SMatthew G. Knepley   PetscFE      fe;
1899318fe57SMatthew G. Knepley   PetscClassId id;
1909318fe57SMatthew G. Knepley 
1919318fe57SMatthew G. Knepley   PetscFunctionBegin;
1929566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
1939566063dSJacob Faibussowitsch   PetscCall(DMGetDS(cdm, &cds));
1949566063dSJacob Faibussowitsch   PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe));
1959566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1969318fe57SMatthew G. Knepley   if (id != PETSCFE_CLASSID) {
1979318fe57SMatthew G. Knepley     PetscBool simplex;
1989318fe57SMatthew G. Knepley     PetscInt  dim, dE, qorder;
1999318fe57SMatthew G. Knepley 
2009566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
2019566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dm, &dE));
2029318fe57SMatthew G. Knepley     qorder = degree;
203d0609cedSBarry Smith     PetscObjectOptionsBegin((PetscObject)cdm);
2049566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
205d0609cedSBarry Smith     PetscOptionsEnd();
2064f9ab2b4SJed Brown     if (degree == PETSC_DECIDE) fe = NULL;
2074f9ab2b4SJed Brown     else {
2088c4475acSStefano Zampini       PetscCall(DMPlexIsSimplex(dm, &simplex));
2099566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe));
2104f9ab2b4SJed Brown     }
2119566063dSJacob Faibussowitsch     PetscCall(DMProjectCoordinates(dm, fe));
2129566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2139318fe57SMatthew G. Knepley   }
2149318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2159318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
2169318fe57SMatthew G. Knepley }
2179318fe57SMatthew G. Knepley 
2181df5d5c5SMatthew G. Knepley /*@
2191df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2201df5d5c5SMatthew G. Knepley 
221d083f849SBarry Smith   Collective
2221df5d5c5SMatthew G. Knepley 
2231df5d5c5SMatthew G. Knepley   Input Parameters:
2241df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object
2251df5d5c5SMatthew G. Knepley . dim - The spatial dimension
2261df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells
2271df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces)
2281df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2291df5d5c5SMatthew G. Knepley 
2301df5d5c5SMatthew G. Knepley   Output Parameter:
2311df5d5c5SMatthew G. Knepley . dm - The DM object
2321df5d5c5SMatthew G. Knepley 
2331df5d5c5SMatthew G. Knepley   Level: beginner
2341df5d5c5SMatthew G. Knepley 
235db781477SPatrick Sanan .seealso: `DMSetType()`, `DMCreate()`
2361df5d5c5SMatthew G. Knepley @*/
2379371c9d4SSatish Balay PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) {
2381df5d5c5SMatthew G. Knepley   DM          dm;
2391df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
2401df5d5c5SMatthew G. Knepley 
2411df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
2429566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
2439566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
2449566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
246ce78fa2fSMatthew G. Knepley   switch (dim) {
247ce78fa2fSMatthew G. Knepley   case 2:
2489566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
2499566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
250ce78fa2fSMatthew G. Knepley     break;
251ce78fa2fSMatthew G. Knepley   case 3:
2529566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
2539566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
254ce78fa2fSMatthew G. Knepley     break;
2559371c9d4SSatish Balay   default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
256ce78fa2fSMatthew G. Knepley   }
2571df5d5c5SMatthew G. Knepley   if (rank) {
2581df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
2599566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
2601df5d5c5SMatthew G. Knepley   } else {
2611df5d5c5SMatthew G. Knepley     switch (dim) {
2621df5d5c5SMatthew G. Knepley     case 2:
2631df5d5c5SMatthew G. Knepley       if (simplex) {
2641df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
2651df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
2661df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
2671df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
2681df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
2691df5d5c5SMatthew G. Knepley 
2709566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2711df5d5c5SMatthew G. Knepley       } else {
2721df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
2731df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
2741df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
2751df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2761df5d5c5SMatthew 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};
2771df5d5c5SMatthew G. Knepley 
2789566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2791df5d5c5SMatthew G. Knepley       }
2801df5d5c5SMatthew G. Knepley       break;
2811df5d5c5SMatthew G. Knepley     case 3:
2821df5d5c5SMatthew G. Knepley       if (simplex) {
2831df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
2841df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
2851df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
2861df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2871df5d5c5SMatthew 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};
2881df5d5c5SMatthew G. Knepley 
2899566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2901df5d5c5SMatthew G. Knepley       } else {
2911df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
2921df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2931df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
2941df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2959371c9d4SSatish 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};
2961df5d5c5SMatthew G. Knepley 
2979566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2981df5d5c5SMatthew G. Knepley       }
2991df5d5c5SMatthew G. Knepley       break;
3009371c9d4SSatish Balay     default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
3011df5d5c5SMatthew G. Knepley     }
3021df5d5c5SMatthew G. Knepley   }
3031df5d5c5SMatthew G. Knepley   *newdm = dm;
3041df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
3051df5d5c5SMatthew G. Knepley     DM          rdm;
3061df5d5c5SMatthew G. Knepley     const char *name;
3071df5d5c5SMatthew G. Knepley 
3089566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
3099566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
3109566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
3119566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
3129566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
3139566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3141df5d5c5SMatthew G. Knepley     *newdm = rdm;
3151df5d5c5SMatthew G. Knepley   }
3161df5d5c5SMatthew G. Knepley   if (interpolate) {
3175fd9971aSMatthew G. Knepley     DM idm;
3181df5d5c5SMatthew G. Knepley 
3199566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
3209566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3211df5d5c5SMatthew G. Knepley     *newdm = idm;
3221df5d5c5SMatthew G. Knepley   }
3231df5d5c5SMatthew G. Knepley   PetscFunctionReturn(0);
3241df5d5c5SMatthew G. Knepley }
3251df5d5c5SMatthew G. Knepley 
3269371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) {
3279318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3289318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3299318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3309318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3319318fe57SMatthew G. Knepley   Vec            coordinates;
3329318fe57SMatthew G. Knepley   PetscSection   coordSection;
3339318fe57SMatthew G. Knepley   PetscScalar   *coords;
3349318fe57SMatthew G. Knepley   PetscInt       coordSize;
3359318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3369318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
337552f7358SJed Brown 
3389318fe57SMatthew G. Knepley   PetscFunctionBegin;
3399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3409318fe57SMatthew G. Knepley   if (markerSeparate) {
3419318fe57SMatthew G. Knepley     markerRight = 2;
3429318fe57SMatthew G. Knepley     markerLeft  = 1;
3439318fe57SMatthew G. Knepley   }
3449566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
345c5853193SPierre Jolivet   if (rank == 0) {
3469566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
3479566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3489566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
3499566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
3509318fe57SMatthew G. Knepley   }
3519566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
3529566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
3539318fe57SMatthew G. Knepley   /* Build coordinates */
3549566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
3559566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
3569566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
3579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
3589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
3599318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
3609566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
3619566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
3629318fe57SMatthew G. Knepley   }
3639566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
3649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
3659566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
3669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
3679566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
3689566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
3699566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
3709566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
3719318fe57SMatthew G. Knepley   coords[0] = lower[0];
3729318fe57SMatthew G. Knepley   coords[1] = upper[0];
3739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
3749566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
3759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
3769318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
3779318fe57SMatthew G. Knepley }
37826492d91SMatthew G. Knepley 
3799371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) {
3801df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
3811df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
382552f7358SJed Brown   PetscInt       markerTop      = 1;
383552f7358SJed Brown   PetscInt       markerBottom   = 1;
384552f7358SJed Brown   PetscInt       markerRight    = 1;
385552f7358SJed Brown   PetscInt       markerLeft     = 1;
386552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
387552f7358SJed Brown   Vec            coordinates;
388552f7358SJed Brown   PetscSection   coordSection;
389552f7358SJed Brown   PetscScalar   *coords;
390552f7358SJed Brown   PetscInt       coordSize;
391552f7358SJed Brown   PetscMPIInt    rank;
392552f7358SJed Brown   PetscInt       v, vx, vy;
393552f7358SJed Brown 
394552f7358SJed Brown   PetscFunctionBegin;
3959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
396552f7358SJed Brown   if (markerSeparate) {
3971df21d24SMatthew G. Knepley     markerTop    = 3;
3981df21d24SMatthew G. Knepley     markerBottom = 1;
3991df21d24SMatthew G. Knepley     markerRight  = 2;
4001df21d24SMatthew G. Knepley     markerLeft   = 4;
401552f7358SJed Brown   }
4029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
403dd400576SPatrick Sanan   if (rank == 0) {
404552f7358SJed Brown     PetscInt e, ex, ey;
405552f7358SJed Brown 
4069566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
4079371c9d4SSatish Balay     for (e = 0; e < numEdges; ++e) { PetscCall(DMPlexSetConeSize(dm, e, 2)); }
4089566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
409552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
410552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
411552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
412552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
413da80777bSKarl Rupp         PetscInt cone[2];
414552f7358SJed Brown 
4159371c9d4SSatish Balay         cone[0] = vertex;
4169371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
4179566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
418552f7358SJed Brown         if (vx == edges[0]) {
4199566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
4209566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
421552f7358SJed Brown           if (ey == edges[1] - 1) {
4229566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
4239566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
424552f7358SJed Brown           }
425552f7358SJed Brown         } else if (vx == 0) {
4269566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
4279566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
428552f7358SJed Brown           if (ey == edges[1] - 1) {
4299566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
4309566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
431552f7358SJed Brown           }
432552f7358SJed Brown         }
433552f7358SJed Brown       }
434552f7358SJed Brown     }
435552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
436552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
437552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
438552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
439da80777bSKarl Rupp         PetscInt cone[2];
440552f7358SJed Brown 
4419371c9d4SSatish Balay         cone[0] = vertex;
4429371c9d4SSatish Balay         cone[1] = vertex + 1;
4439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
444552f7358SJed Brown         if (vy == edges[1]) {
4459566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
4469566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
447552f7358SJed Brown           if (ex == edges[0] - 1) {
4489566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
4499566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
450552f7358SJed Brown           }
451552f7358SJed Brown         } else if (vy == 0) {
4529566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
4539566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
454552f7358SJed Brown           if (ex == edges[0] - 1) {
4559566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
4569566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
457552f7358SJed Brown           }
458552f7358SJed Brown         }
459552f7358SJed Brown       }
460552f7358SJed Brown     }
461552f7358SJed Brown   }
4629566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4639566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
464552f7358SJed Brown   /* Build coordinates */
4659566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
4669566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
4699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
470552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
4719566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
4729566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
473552f7358SJed Brown   }
4749566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4769566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4779566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4789566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4799566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
4809566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
4819566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
482552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
483552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
484552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
485552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
486552f7358SJed Brown     }
487552f7358SJed Brown   }
4889566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
4899566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
4909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
491552f7358SJed Brown   PetscFunctionReturn(0);
492552f7358SJed Brown }
493552f7358SJed Brown 
4949371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) {
4959e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
4967b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
497c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
498c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
499c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
500c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
501c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
502c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
503c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
504552f7358SJed Brown   Vec          coordinates;
505552f7358SJed Brown   PetscSection coordSection;
506552f7358SJed Brown   PetscScalar *coords;
507552f7358SJed Brown   PetscInt     coordSize;
508552f7358SJed Brown   PetscMPIInt  rank;
509552f7358SJed Brown   PetscInt     v, vx, vy, vz;
5107b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
511552f7358SJed Brown 
512552f7358SJed Brown   PetscFunctionBegin;
5131dca8a05SBarry 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");
5149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
515c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
516c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
517c2df9bbfSMatthew G. Knepley     markerBottom = 1;
518c2df9bbfSMatthew G. Knepley     markerTop    = 2;
519c2df9bbfSMatthew G. Knepley     markerFront  = 3;
520c2df9bbfSMatthew G. Knepley     markerBack   = 4;
521c2df9bbfSMatthew G. Knepley     markerRight  = 5;
522c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
523c2df9bbfSMatthew G. Knepley   }
5249371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
5259371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
5269371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
5279e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
528dd400576SPatrick Sanan   if (rank == 0) {
529552f7358SJed Brown     PetscInt f;
530552f7358SJed Brown 
5319566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
5329371c9d4SSatish Balay     for (f = 0; f < numFaces; ++f) { PetscCall(DMPlexSetConeSize(dm, f, 4)); }
5339566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5347b59f5a9SMichael Lange 
5357b59f5a9SMichael Lange     /* Side 0 (Top) */
5367b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5377b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5387b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
5399371c9d4SSatish Balay         cone[0] = voffset;
5409371c9d4SSatish Balay         cone[1] = voffset + 1;
5419371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
5429371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
5439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
544c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
545c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
546c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
547c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
548c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
5497b59f5a9SMichael Lange         iface++;
550552f7358SJed Brown       }
551552f7358SJed Brown     }
5527b59f5a9SMichael Lange 
5537b59f5a9SMichael Lange     /* Side 1 (Bottom) */
5547b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5557b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5567b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
5579371c9d4SSatish Balay         cone[0] = voffset + 1;
5589371c9d4SSatish Balay         cone[1] = voffset;
5599371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
5609371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
5619566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
562c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
563c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
564c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
565c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
566c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
5677b59f5a9SMichael Lange         iface++;
568552f7358SJed Brown       }
569552f7358SJed Brown     }
5707b59f5a9SMichael Lange 
5717b59f5a9SMichael Lange     /* Side 2 (Front) */
5727b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5737b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5747b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
5759371c9d4SSatish Balay         cone[0] = voffset;
5769371c9d4SSatish Balay         cone[1] = voffset + 1;
5779371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
5789371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
5799566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
580c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
581c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
582c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
583c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
584c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
5857b59f5a9SMichael Lange         iface++;
586552f7358SJed Brown       }
5877b59f5a9SMichael Lange     }
5887b59f5a9SMichael Lange 
5897b59f5a9SMichael Lange     /* Side 3 (Back) */
5907b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5917b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5927b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
5939371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
5949371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
5959371c9d4SSatish Balay         cone[2] = voffset + 1;
5969371c9d4SSatish Balay         cone[3] = voffset;
5979566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
598c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
599c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
600c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
601c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
602c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
6037b59f5a9SMichael Lange         iface++;
6047b59f5a9SMichael Lange       }
6057b59f5a9SMichael Lange     }
6067b59f5a9SMichael Lange 
6077b59f5a9SMichael Lange     /* Side 4 (Left) */
6087b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6097b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
6107b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
6119371c9d4SSatish Balay         cone[0] = voffset;
6129371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
6139371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
6149371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
616c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
617c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
618c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
619c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
620c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
6217b59f5a9SMichael Lange         iface++;
6227b59f5a9SMichael Lange       }
6237b59f5a9SMichael Lange     }
6247b59f5a9SMichael Lange 
6257b59f5a9SMichael Lange     /* Side 5 (Right) */
6267b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6277b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
628aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
6299371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6309371c9d4SSatish Balay         cone[1] = voffset;
6319371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6329371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
6339566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
634c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
635c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
636c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
637c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
638c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
6397b59f5a9SMichael Lange         iface++;
6407b59f5a9SMichael Lange       }
641552f7358SJed Brown     }
642552f7358SJed Brown   }
6439566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6449566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
645552f7358SJed Brown   /* Build coordinates */
6469566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
6479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
6509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
651552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
6529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
6539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
654552f7358SJed Brown   }
6559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6579566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6589566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6599566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6609566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
6619566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
663552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
664552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
665552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
666552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
667552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
668552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
669552f7358SJed Brown       }
670552f7358SJed Brown     }
671552f7358SJed Brown   }
6729566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6739566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
675552f7358SJed Brown   PetscFunctionReturn(0);
676552f7358SJed Brown }
677552f7358SJed Brown 
6789371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) {
6799318fe57SMatthew G. Knepley   PetscFunctionBegin;
6809318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6819566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
6829566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
6839318fe57SMatthew G. Knepley   switch (dim) {
6849566063dSJacob Faibussowitsch   case 1: PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); break;
6859566063dSJacob Faibussowitsch   case 2: PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); break;
6869566063dSJacob Faibussowitsch   case 3: PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); break;
68763a3b9bcSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
6889318fe57SMatthew G. Knepley   }
6899566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
6909318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
6919318fe57SMatthew G. Knepley }
6929318fe57SMatthew G. Knepley 
6939318fe57SMatthew G. Knepley /*@C
6949318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
6959318fe57SMatthew G. Knepley 
6969318fe57SMatthew G. Knepley   Collective
6979318fe57SMatthew G. Knepley 
6989318fe57SMatthew G. Knepley   Input Parameters:
6999318fe57SMatthew G. Knepley + comm        - The communicator for the DM object
7009318fe57SMatthew G. Knepley . dim         - The spatial dimension of the box, so the resulting mesh is has dimension dim-1
7019318fe57SMatthew 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
7029318fe57SMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
7039318fe57SMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
7049318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7059318fe57SMatthew G. Knepley 
7069318fe57SMatthew G. Knepley   Output Parameter:
7079318fe57SMatthew G. Knepley . dm  - The DM object
7089318fe57SMatthew G. Knepley 
7099318fe57SMatthew G. Knepley   Level: beginner
7109318fe57SMatthew G. Knepley 
711db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
7129318fe57SMatthew G. Knepley @*/
7139371c9d4SSatish Balay PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) {
7149318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
7159318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
7169318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
7179318fe57SMatthew G. Knepley 
7189318fe57SMatthew G. Knepley   PetscFunctionBegin;
7199566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
7209566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
7219566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
7229318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7239318fe57SMatthew G. Knepley }
7249318fe57SMatthew G. Knepley 
7259371c9d4SSatish Balay static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) {
726fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
727fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
728fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
729fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
730fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
731fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
732fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
733fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
734fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
735fdbf62faSLisandro Dalcin 
736fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7379318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
738fdbf62faSLisandro Dalcin 
7399566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
7409566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
7419566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
742fdbf62faSLisandro Dalcin 
7439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
744dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
745dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
746fdbf62faSLisandro Dalcin 
7479371c9d4SSatish Balay   numPoints[0] = numVerts;
7489371c9d4SSatish Balay   numPoints[1] = numCells;
7499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
7509566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
751fdbf62faSLisandro Dalcin   for (i = 0; i < numCells; ++i) { coneSize[i] = 2; }
752fdbf62faSLisandro Dalcin   for (i = 0; i < numVerts; ++i) { coneSize[numCells + i] = 0; }
7539371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
7549371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
7559371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
7569371c9d4SSatish Balay   }
757fdbf62faSLisandro Dalcin   for (i = 0; i < numVerts; ++i) { vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); }
7589566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
7599566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
760fdbf62faSLisandro Dalcin 
7619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
7629371c9d4SSatish Balay   if (markerSeparate) {
7639371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
7649371c9d4SSatish Balay     markerRight = faceMarkerRight;
7659371c9d4SSatish Balay   }
766dd400576SPatrick Sanan   if (!wrap && rank == 0) {
7679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
7689566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
7699566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
7709566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
7719566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
772fdbf62faSLisandro Dalcin   }
773fdbf62faSLisandro Dalcin   if (wrap) {
774fdbf62faSLisandro Dalcin     L       = upper - lower;
775fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
7764fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
777fdbf62faSLisandro Dalcin   }
7789566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
779fdbf62faSLisandro Dalcin   PetscFunctionReturn(0);
780fdbf62faSLisandro Dalcin }
781fdbf62faSLisandro Dalcin 
7829371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) {
7839318fe57SMatthew G. Knepley   DM      boundary, vol;
784c22d3578SMatthew G. Knepley   DMLabel bdlabel;
785d6218766SMatthew G. Knepley 
786d6218766SMatthew G. Knepley   PetscFunctionBegin;
7879318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
788c22d3578SMatthew 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");
7899566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
7909566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
7919566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
7929566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
793c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
794c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
7955de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
796*69d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
7979566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
798d6218766SMatthew G. Knepley   PetscFunctionReturn(0);
799d6218766SMatthew G. Knepley }
800d6218766SMatthew G. Knepley 
8019371c9d4SSatish Balay static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) {
802ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
803f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
804f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
805f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
806f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
807f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
808f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
8093dfda0b1SToby Isaac   PetscInt    dim;
810d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
8113dfda0b1SToby Isaac   PetscMPIInt rank;
8123dfda0b1SToby Isaac 
8133dfda0b1SToby Isaac   PetscFunctionBegin;
8149566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8169566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8179566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
8189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
8199371c9d4SSatish 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) {
8209371c9d4SSatish Balay     if (cutMarker) {
8219371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
8229371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
8239371c9d4SSatish Balay     }
824d8211ee3SMatthew G. Knepley   }
8253dfda0b1SToby Isaac   switch (dim) {
8263dfda0b1SToby Isaac   case 2:
827f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
828f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
829f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
830f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
8313dfda0b1SToby Isaac     break;
8323dfda0b1SToby Isaac   case 3:
833f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
834f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
835f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
836f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
837f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
838f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
8393dfda0b1SToby Isaac     break;
8409371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
8413dfda0b1SToby Isaac   }
8429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
843f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
844f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
845f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
846f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
847f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
848f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
849f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
8503dfda0b1SToby Isaac   }
8513dfda0b1SToby Isaac   {
852dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
853dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
854dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
855dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
856dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
857dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
8583dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
8593dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
8603dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
8613dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
8623dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
8633dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
8643dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
8653dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
8663dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
8673dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
8683dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
8693dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
8703dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
8713dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
8723dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
8733dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
8743dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
8753dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
8763dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
8773dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
8783dfda0b1SToby Isaac     Vec            coordinates;
8793dfda0b1SToby Isaac     PetscSection   coordSection;
8803dfda0b1SToby Isaac     PetscScalar   *coords;
8813dfda0b1SToby Isaac     PetscInt       coordSize;
8823dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
8833dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
8843dfda0b1SToby Isaac 
8859566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
8869371c9d4SSatish Balay     for (c = 0; c < numCells; c++) { PetscCall(DMPlexSetConeSize(dm, c, 6)); }
8879371c9d4SSatish Balay     for (f = firstXFace; f < firstXFace + numFaces; ++f) { PetscCall(DMPlexSetConeSize(dm, f, 4)); }
8889371c9d4SSatish Balay     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) { PetscCall(DMPlexSetConeSize(dm, e, 2)); }
8899566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
8903dfda0b1SToby Isaac     /* Build cells */
8913dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
8923dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
8933dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
8943dfda0b1SToby Isaac           PetscInt cell    = (fz * numYEdges + fy) * numXEdges + fx;
8953dfda0b1SToby Isaac           PetscInt faceB   = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
8963dfda0b1SToby Isaac           PetscInt faceT   = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
8973dfda0b1SToby Isaac           PetscInt faceF   = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
8983dfda0b1SToby Isaac           PetscInt faceK   = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
8993dfda0b1SToby Isaac           PetscInt faceL   = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9003dfda0b1SToby Isaac           PetscInt faceR   = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
9013dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
902b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
90342206facSLisandro Dalcin           PetscInt cone[6];
9043dfda0b1SToby Isaac 
9053dfda0b1SToby Isaac           /* no boundary twisting in 3D */
9069371c9d4SSatish Balay           cone[0] = faceB;
9079371c9d4SSatish Balay           cone[1] = faceT;
9089371c9d4SSatish Balay           cone[2] = faceF;
9099371c9d4SSatish Balay           cone[3] = faceK;
9109371c9d4SSatish Balay           cone[4] = faceR;
9119371c9d4SSatish Balay           cone[5] = faceL;
9129566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
9139566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
9149566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9159566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9169566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9173dfda0b1SToby Isaac         }
9183dfda0b1SToby Isaac       }
9193dfda0b1SToby Isaac     }
9203dfda0b1SToby Isaac     /* Build x faces */
9213dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9223dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9233dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
9243dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9253dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9263dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
9273dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
9283dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
929b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9303dfda0b1SToby Isaac           PetscInt cone[4];
9313dfda0b1SToby Isaac 
9323dfda0b1SToby Isaac           if (dim == 3) {
9333dfda0b1SToby Isaac             /* markers */
9343dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
9353dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
9369566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
9379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
9389371c9d4SSatish Balay               } else if (fx == 0) {
9399566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
9409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
9413dfda0b1SToby Isaac               }
9423dfda0b1SToby Isaac             }
9433dfda0b1SToby Isaac           }
9449371c9d4SSatish Balay           cone[0] = edgeB;
9459371c9d4SSatish Balay           cone[1] = edgeR;
9469371c9d4SSatish Balay           cone[2] = edgeT;
9479371c9d4SSatish Balay           cone[3] = edgeL;
9489566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
9499566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
9503dfda0b1SToby Isaac         }
9513dfda0b1SToby Isaac       }
9523dfda0b1SToby Isaac     }
9533dfda0b1SToby Isaac     /* Build y faces */
9543dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
95542206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
9563dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
9573dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9583dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9593dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
9603dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
9613dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
962b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9633dfda0b1SToby Isaac           PetscInt cone[4];
9643dfda0b1SToby Isaac 
9653dfda0b1SToby Isaac           if (dim == 3) {
9663dfda0b1SToby Isaac             /* markers */
9673dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
9683dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
9699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
9709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
9719371c9d4SSatish Balay               } else if (fy == 0) {
9729566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
9739566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
9743dfda0b1SToby Isaac               }
9753dfda0b1SToby Isaac             }
9763dfda0b1SToby Isaac           }
9779371c9d4SSatish Balay           cone[0] = edgeB;
9789371c9d4SSatish Balay           cone[1] = edgeR;
9799371c9d4SSatish Balay           cone[2] = edgeT;
9809371c9d4SSatish Balay           cone[3] = edgeL;
9819566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
9829566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
9833dfda0b1SToby Isaac         }
9843dfda0b1SToby Isaac       }
9853dfda0b1SToby Isaac     }
9863dfda0b1SToby Isaac     /* Build z faces */
9873dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
9883dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
9893dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
9903dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
9913dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
9923dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
9933dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
9943dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
995b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9963dfda0b1SToby Isaac           PetscInt cone[4];
9973dfda0b1SToby Isaac 
9983dfda0b1SToby Isaac           if (dim == 2) {
9999371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
10009371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
10019371c9d4SSatish Balay               ornt[1] = -1;
10029371c9d4SSatish Balay             }
10039371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
10049371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
10059371c9d4SSatish Balay               ornt[2] = 0;
10069371c9d4SSatish Balay             }
10079566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
10089566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1009d1c88043SMatthew G. Knepley           } else {
10103dfda0b1SToby Isaac             /* markers */
10113dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
10123dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
10139566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
10149566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
10159371c9d4SSatish Balay               } else if (fz == 0) {
10169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
10179566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
10183dfda0b1SToby Isaac               }
10193dfda0b1SToby Isaac             }
10203dfda0b1SToby Isaac           }
10219371c9d4SSatish Balay           cone[0] = edgeB;
10229371c9d4SSatish Balay           cone[1] = edgeR;
10239371c9d4SSatish Balay           cone[2] = edgeT;
10249371c9d4SSatish Balay           cone[3] = edgeL;
10259566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10269566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10273dfda0b1SToby Isaac         }
10283dfda0b1SToby Isaac       }
10293dfda0b1SToby Isaac     }
10303dfda0b1SToby Isaac     /* Build Z edges*/
10313dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
10323dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10333dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
10343dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
10353dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
10363dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
10373dfda0b1SToby Isaac           PetscInt       cone[2];
10383dfda0b1SToby Isaac 
10399371c9d4SSatish Balay           cone[0] = vertexB;
10409371c9d4SSatish Balay           cone[1] = vertexT;
1041c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
10423dfda0b1SToby Isaac           if (dim == 3) {
10433dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
10443dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
10459566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1046c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1047c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1048c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
10499566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1050c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1051c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10523dfda0b1SToby Isaac               }
10533dfda0b1SToby Isaac             }
10543dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
10553dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
10569566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1057c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1058c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1059c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
10609566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1061c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1062c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
10633dfda0b1SToby Isaac               }
10643dfda0b1SToby Isaac             }
10653dfda0b1SToby Isaac           }
10663dfda0b1SToby Isaac         }
10673dfda0b1SToby Isaac       }
10683dfda0b1SToby Isaac     }
10693dfda0b1SToby Isaac     /* Build Y edges*/
10703dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
10713dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10723dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
10733dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
10743dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
10753dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
10763dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
10773dfda0b1SToby Isaac           PetscInt       cone[2];
10783dfda0b1SToby Isaac 
10799371c9d4SSatish Balay           cone[0] = vertexF;
10809371c9d4SSatish Balay           cone[1] = vertexK;
10819566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
10823dfda0b1SToby Isaac           if (dim == 2) {
10833dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
10843dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
10859566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
10869566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
10879566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1088c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1089d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
10909566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
10919566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
10929566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1093c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10943dfda0b1SToby Isaac               }
1095d8211ee3SMatthew G. Knepley             } else {
10964c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
10979566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
10989566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1099c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11003dfda0b1SToby Isaac               }
1101d8211ee3SMatthew G. Knepley             }
1102d8211ee3SMatthew G. Knepley           } else {
11033dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
11043dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11059566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1106c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1107c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1108d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1110c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1111c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11123dfda0b1SToby Isaac               }
11133dfda0b1SToby Isaac             }
11143dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11153dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
11169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1117c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1118c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1119d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
11209566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1121c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1122c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11233dfda0b1SToby Isaac               }
11243dfda0b1SToby Isaac             }
11253dfda0b1SToby Isaac           }
11263dfda0b1SToby Isaac         }
11273dfda0b1SToby Isaac       }
11283dfda0b1SToby Isaac     }
11293dfda0b1SToby Isaac     /* Build X edges*/
11303dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
11313dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
11323dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
11333dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
11343dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
11353dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
11363dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
11373dfda0b1SToby Isaac           PetscInt       cone[2];
11383dfda0b1SToby Isaac 
11399371c9d4SSatish Balay           cone[0] = vertexL;
11409371c9d4SSatish Balay           cone[1] = vertexR;
11419566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11423dfda0b1SToby Isaac           if (dim == 2) {
11433dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
11443dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11459566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
11469566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
11479566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1148c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1149d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
11509566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
11519566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
11529566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1153c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11543dfda0b1SToby Isaac               }
1155d8211ee3SMatthew G. Knepley             } else {
11564c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
11579566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11589566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1159c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11603dfda0b1SToby Isaac               }
1161d8211ee3SMatthew G. Knepley             }
1162d8211ee3SMatthew G. Knepley           } else {
11633dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11643dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11659566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1166c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1167c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1168c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
11699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1170c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1171c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
11723dfda0b1SToby Isaac               }
11733dfda0b1SToby Isaac             }
11743dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11753dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
11769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1177c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1178c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1179c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
11809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1181c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1182c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11833dfda0b1SToby Isaac               }
11843dfda0b1SToby Isaac             }
11853dfda0b1SToby Isaac           }
11863dfda0b1SToby Isaac         }
11873dfda0b1SToby Isaac       }
11883dfda0b1SToby Isaac     }
11899566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
11909566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
11913dfda0b1SToby Isaac     /* Build coordinates */
11929566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
11939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
11949566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
11959566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
11963dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
11979566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
11989566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
11993dfda0b1SToby Isaac     }
12009566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
12019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
12029566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
12039566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
12049566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
12059566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
12069566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
12079566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
12083dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
12093dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
12103dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
12113dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
12123dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
12139371c9d4SSatish Balay           if (dim == 3) { coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; }
12143dfda0b1SToby Isaac         }
12153dfda0b1SToby Isaac       }
12163dfda0b1SToby Isaac     }
12179566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12189566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
12199566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
12203dfda0b1SToby Isaac   }
12213dfda0b1SToby Isaac   PetscFunctionReturn(0);
12223dfda0b1SToby Isaac }
12233dfda0b1SToby Isaac 
12249371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) {
12259318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
12269318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1227552f7358SJed Brown 
1228552f7358SJed Brown   PetscFunctionBegin;
12299318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
12309318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
12319566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
12329371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
12339371c9d4SSatish Balay     fac[d] = faces[d];
12349371c9d4SSatish Balay     bdt[d] = periodicity[d];
12359371c9d4SSatish Balay   }
12369566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
12379371c9d4SSatish 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))) {
12386858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
12396858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1240552f7358SJed Brown 
12419318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
12426858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
12439318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
12449318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1245768d5fceSMatthew G. Knepley       }
12466858538eSMatthew G. Knepley     }
12474fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1248768d5fceSMatthew G. Knepley   }
12499566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
12509318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
12519318fe57SMatthew G. Knepley }
12529318fe57SMatthew G. Knepley 
12539371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) {
12549318fe57SMatthew G. Knepley   PetscFunctionBegin;
12559566063dSJacob Faibussowitsch   if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
12569566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
12579566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
12589318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1259768d5fceSMatthew G. Knepley     DM udm;
1260768d5fceSMatthew G. Knepley 
12619566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
12629566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
1263*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1264768d5fceSMatthew G. Knepley   }
1265768d5fceSMatthew G. Knepley   PetscFunctionReturn(0);
1266c8c68bd8SToby Isaac }
1267c8c68bd8SToby Isaac 
1268768d5fceSMatthew G. Knepley /*@C
1269768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1270768d5fceSMatthew G. Knepley 
1271d083f849SBarry Smith   Collective
1272768d5fceSMatthew G. Knepley 
1273768d5fceSMatthew G. Knepley   Input Parameters:
1274768d5fceSMatthew G. Knepley + comm        - The communicator for the DM object
1275768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1276768d5fceSMatthew G. Knepley . simplex     - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells
1277fdbf62faSLisandro Dalcin . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
1278768d5fceSMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
1279768d5fceSMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
1280fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1281768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
1282768d5fceSMatthew G. Knepley 
1283768d5fceSMatthew G. Knepley   Output Parameter:
1284768d5fceSMatthew G. Knepley . dm  - The DM object
1285768d5fceSMatthew G. Knepley 
12869318fe57SMatthew G. Knepley   Note: If you want to customize this mesh using options, you just need to
12879318fe57SMatthew G. Knepley $  DMCreate(comm, &dm);
12889318fe57SMatthew G. Knepley $  DMSetType(dm, DMPLEX);
12899318fe57SMatthew G. Knepley $  DMSetFromOptions(dm);
12909318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page.
12911367e252SJed Brown 
12921367e252SJed Brown   Here is the numbering returned for 2 faces in each direction for tensor cells:
1293768d5fceSMatthew G. Knepley $ 10---17---11---18----12
1294768d5fceSMatthew G. Knepley $  |         |         |
1295768d5fceSMatthew G. Knepley $  |         |         |
1296768d5fceSMatthew G. Knepley $ 20    2   22    3    24
1297768d5fceSMatthew G. Knepley $  |         |         |
1298768d5fceSMatthew G. Knepley $  |         |         |
1299768d5fceSMatthew G. Knepley $  7---15----8---16----9
1300768d5fceSMatthew G. Knepley $  |         |         |
1301768d5fceSMatthew G. Knepley $  |         |         |
1302768d5fceSMatthew G. Knepley $ 19    0   21    1   23
1303768d5fceSMatthew G. Knepley $  |         |         |
1304768d5fceSMatthew G. Knepley $  |         |         |
1305768d5fceSMatthew G. Knepley $  4---13----5---14----6
1306768d5fceSMatthew G. Knepley 
1307768d5fceSMatthew G. Knepley and for simplicial cells
1308768d5fceSMatthew G. Knepley 
1309768d5fceSMatthew G. Knepley $ 14----8---15----9----16
1310768d5fceSMatthew G. Knepley $  |\     5  |\      7 |
1311768d5fceSMatthew G. Knepley $  | \       | \       |
1312768d5fceSMatthew G. Knepley $ 13   2    14    3    15
1313768d5fceSMatthew G. Knepley $  | 4   \   | 6   \   |
1314768d5fceSMatthew G. Knepley $  |       \ |       \ |
1315768d5fceSMatthew G. Knepley $ 11----6---12----7----13
1316768d5fceSMatthew G. Knepley $  |\        |\        |
1317768d5fceSMatthew G. Knepley $  | \    1  | \     3 |
1318768d5fceSMatthew G. Knepley $ 10   0    11    1    12
1319768d5fceSMatthew G. Knepley $  | 0   \   | 2   \   |
1320768d5fceSMatthew G. Knepley $  |       \ |       \ |
1321768d5fceSMatthew G. Knepley $  8----4----9----5----10
1322768d5fceSMatthew G. Knepley 
1323768d5fceSMatthew G. Knepley   Level: beginner
1324768d5fceSMatthew G. Knepley 
1325db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1326768d5fceSMatthew G. Knepley @*/
13279371c9d4SSatish Balay 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) {
13289318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1329fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1330fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1331fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1332552f7358SJed Brown 
1333768d5fceSMatthew G. Knepley   PetscFunctionBegin;
13349566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
13359566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
13369566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
13377ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
13389318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
13399318fe57SMatthew G. Knepley }
1340fdbf62faSLisandro Dalcin 
13419371c9d4SSatish Balay static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) {
13429318fe57SMatthew G. Knepley   DM       bdm, vol;
13439318fe57SMatthew G. Knepley   PetscInt i;
13449318fe57SMatthew G. Knepley 
13459318fe57SMatthew G. Knepley   PetscFunctionBegin;
134608401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
13479566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
13489566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
13499566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
13509566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
13519566063dSJacob Faibussowitsch   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
13529566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
1353*69d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
13549318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
13559318fe57SMatthew G. Knepley     Vec          v;
13569318fe57SMatthew G. Knepley     PetscScalar *x;
13579318fe57SMatthew G. Knepley     PetscInt     cDim, n;
13589318fe57SMatthew G. Knepley 
13599566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
13609566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
13619566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
13629566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
13639318fe57SMatthew G. Knepley     x += cDim;
13649318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
13659566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
13669566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
13679318fe57SMatthew G. Knepley   }
1368552f7358SJed Brown   PetscFunctionReturn(0);
1369552f7358SJed Brown }
1370552f7358SJed Brown 
137100dabe28SStefano Zampini /*@
137200dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
137300dabe28SStefano Zampini 
1374d083f849SBarry Smith   Collective
137500dabe28SStefano Zampini 
137600dabe28SStefano Zampini   Input Parameters:
137700dabe28SStefano Zampini + comm        - The communicator for the DM object
137800dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
137900dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
138000dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
138100dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1382d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
138300dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
138400dabe28SStefano Zampini 
138500dabe28SStefano Zampini   Output Parameter:
138600dabe28SStefano Zampini . dm  - The DM object
138700dabe28SStefano Zampini 
138800dabe28SStefano Zampini   Level: beginner
138900dabe28SStefano Zampini 
1390db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
139100dabe28SStefano Zampini @*/
13929371c9d4SSatish Balay PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) {
13939318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
139400dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
139500dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
139600dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
139700dabe28SStefano Zampini 
139800dabe28SStefano Zampini   PetscFunctionBegin;
13999566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14009566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14019566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1402d410b0cfSMatthew G. Knepley   if (!interpolate) {
1403d410b0cfSMatthew G. Knepley     DM udm;
140400dabe28SStefano Zampini 
14059566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
1406*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
140700dabe28SStefano Zampini   }
14087ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
140900dabe28SStefano Zampini   PetscFunctionReturn(0);
141000dabe28SStefano Zampini }
141100dabe28SStefano Zampini 
1412a9074c1eSMatthew G. Knepley /*@C
1413a9074c1eSMatthew G. Knepley   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database.
1414a9074c1eSMatthew G. Knepley 
1415d083f849SBarry Smith   Logically Collective on dm
1416a9074c1eSMatthew G. Knepley 
1417a9074c1eSMatthew G. Knepley   Input Parameters:
1418a9074c1eSMatthew G. Knepley + dm - the DM context
1419a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1420a9074c1eSMatthew G. Knepley 
1421a9074c1eSMatthew G. Knepley   Notes:
1422a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1423a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1424a9074c1eSMatthew G. Knepley 
1425a9074c1eSMatthew G. Knepley   Level: advanced
1426a9074c1eSMatthew G. Knepley 
1427db781477SPatrick Sanan .seealso: `SNESSetFromOptions()`
1428a9074c1eSMatthew G. Knepley @*/
14299371c9d4SSatish Balay PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) {
1430a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1431a9074c1eSMatthew G. Knepley 
1432a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1433a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14349566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
14359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
1436a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1437a9074c1eSMatthew G. Knepley }
1438a9074c1eSMatthew G. Knepley 
14399318fe57SMatthew G. Knepley /* Remap geometry to cylinder
144061a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
144161a622f3SMatthew G. Knepley 
14429318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
14439318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
14449318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
14450510c589SMatthew G. Knepley 
14469318fe57SMatthew G. Knepley        phi     = arctan(y/x)
14479318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
14489318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
14490510c589SMatthew G. Knepley 
14509318fe57SMatthew G. Knepley      so we remap them using
14510510c589SMatthew G. Knepley 
14529318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
14539318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
14540510c589SMatthew G. Knepley 
14559318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
14569318fe57SMatthew G. Knepley */
14579371c9d4SSatish Balay 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[]) {
14589318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
14599318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
146022cc497dSMatthew G. Knepley 
14619318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
14629318fe57SMatthew G. Knepley     f0[0] = u[0];
14639318fe57SMatthew G. Knepley     f0[1] = u[1];
14649318fe57SMatthew G. Knepley   } else {
14659318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
14660510c589SMatthew G. Knepley 
14679318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
14689318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
14699318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
14709318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
14719318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
14729318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
14739318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
14749318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
14759318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
14769318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
14779318fe57SMatthew G. Knepley     } else {
14789318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
14799318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
14809318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
14819318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
14829318fe57SMatthew G. Knepley     }
14839318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
14849318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
14859318fe57SMatthew G. Knepley   }
14869318fe57SMatthew G. Knepley   f0[2] = u[2];
14879318fe57SMatthew G. Knepley }
14880510c589SMatthew G. Knepley 
14899371c9d4SSatish Balay static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) {
14900510c589SMatthew G. Knepley   const PetscInt dim = 3;
14919318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1492d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
14930510c589SMatthew G. Knepley 
14940510c589SMatthew G. Knepley   PetscFunctionBegin;
14959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
14969566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
14970510c589SMatthew G. Knepley   /* Create topology */
14980510c589SMatthew G. Knepley   {
14990510c589SMatthew G. Knepley     PetscInt cone[8], c;
15000510c589SMatthew G. Knepley 
1501dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1502dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1503006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1504ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1505dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1506006a8963SMatthew G. Knepley     }
15079566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
15089566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
15099566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1510dd400576SPatrick Sanan     if (rank == 0) {
1511006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
15129371c9d4SSatish Balay         cone[0] = 15;
15139371c9d4SSatish Balay         cone[1] = 18;
15149371c9d4SSatish Balay         cone[2] = 17;
15159371c9d4SSatish Balay         cone[3] = 16;
15169371c9d4SSatish Balay         cone[4] = 31;
15179371c9d4SSatish Balay         cone[5] = 32;
15189371c9d4SSatish Balay         cone[6] = 33;
15199371c9d4SSatish Balay         cone[7] = 34;
15209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
15219371c9d4SSatish Balay         cone[0] = 16;
15229371c9d4SSatish Balay         cone[1] = 17;
15239371c9d4SSatish Balay         cone[2] = 24;
15249371c9d4SSatish Balay         cone[3] = 23;
15259371c9d4SSatish Balay         cone[4] = 32;
15269371c9d4SSatish Balay         cone[5] = 36;
15279371c9d4SSatish Balay         cone[6] = 37;
15289371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
15299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
15309371c9d4SSatish Balay         cone[0] = 18;
15319371c9d4SSatish Balay         cone[1] = 27;
15329371c9d4SSatish Balay         cone[2] = 24;
15339371c9d4SSatish Balay         cone[3] = 17;
15349371c9d4SSatish Balay         cone[4] = 34;
15359371c9d4SSatish Balay         cone[5] = 33;
15369371c9d4SSatish Balay         cone[6] = 37;
15379371c9d4SSatish Balay         cone[7] = 38;
15389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
15399371c9d4SSatish Balay         cone[0] = 29;
15409371c9d4SSatish Balay         cone[1] = 27;
15419371c9d4SSatish Balay         cone[2] = 18;
15429371c9d4SSatish Balay         cone[3] = 15;
15439371c9d4SSatish Balay         cone[4] = 35;
15449371c9d4SSatish Balay         cone[5] = 31;
15459371c9d4SSatish Balay         cone[6] = 34;
15469371c9d4SSatish Balay         cone[7] = 38;
15479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
15489371c9d4SSatish Balay         cone[0] = 29;
15499371c9d4SSatish Balay         cone[1] = 15;
15509371c9d4SSatish Balay         cone[2] = 16;
15519371c9d4SSatish Balay         cone[3] = 23;
15529371c9d4SSatish Balay         cone[4] = 35;
15539371c9d4SSatish Balay         cone[5] = 36;
15549371c9d4SSatish Balay         cone[6] = 32;
15559371c9d4SSatish Balay         cone[7] = 31;
15569566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1557006a8963SMatthew G. Knepley 
15589371c9d4SSatish Balay         cone[0] = 31;
15599371c9d4SSatish Balay         cone[1] = 34;
15609371c9d4SSatish Balay         cone[2] = 33;
15619371c9d4SSatish Balay         cone[3] = 32;
15629371c9d4SSatish Balay         cone[4] = 19;
15639371c9d4SSatish Balay         cone[5] = 22;
15649371c9d4SSatish Balay         cone[6] = 21;
15659371c9d4SSatish Balay         cone[7] = 20;
15669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
15679371c9d4SSatish Balay         cone[0] = 32;
15689371c9d4SSatish Balay         cone[1] = 33;
15699371c9d4SSatish Balay         cone[2] = 37;
15709371c9d4SSatish Balay         cone[3] = 36;
15719371c9d4SSatish Balay         cone[4] = 22;
15729371c9d4SSatish Balay         cone[5] = 25;
15739371c9d4SSatish Balay         cone[6] = 26;
15749371c9d4SSatish Balay         cone[7] = 21;
15759566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
15769371c9d4SSatish Balay         cone[0] = 34;
15779371c9d4SSatish Balay         cone[1] = 38;
15789371c9d4SSatish Balay         cone[2] = 37;
15799371c9d4SSatish Balay         cone[3] = 33;
15809371c9d4SSatish Balay         cone[4] = 20;
15819371c9d4SSatish Balay         cone[5] = 21;
15829371c9d4SSatish Balay         cone[6] = 26;
15839371c9d4SSatish Balay         cone[7] = 28;
15849566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
15859371c9d4SSatish Balay         cone[0] = 35;
15869371c9d4SSatish Balay         cone[1] = 38;
15879371c9d4SSatish Balay         cone[2] = 34;
15889371c9d4SSatish Balay         cone[3] = 31;
15899371c9d4SSatish Balay         cone[4] = 30;
15909371c9d4SSatish Balay         cone[5] = 19;
15919371c9d4SSatish Balay         cone[6] = 20;
15929371c9d4SSatish Balay         cone[7] = 28;
15939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
15949371c9d4SSatish Balay         cone[0] = 35;
15959371c9d4SSatish Balay         cone[1] = 31;
15969371c9d4SSatish Balay         cone[2] = 32;
15979371c9d4SSatish Balay         cone[3] = 36;
15989371c9d4SSatish Balay         cone[4] = 30;
15999371c9d4SSatish Balay         cone[5] = 25;
16009371c9d4SSatish Balay         cone[6] = 22;
16019371c9d4SSatish Balay         cone[7] = 19;
16029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
1603ae8bcbbbSMatthew G. Knepley 
16049371c9d4SSatish Balay         cone[0] = 19;
16059371c9d4SSatish Balay         cone[1] = 20;
16069371c9d4SSatish Balay         cone[2] = 21;
16079371c9d4SSatish Balay         cone[3] = 22;
16089371c9d4SSatish Balay         cone[4] = 15;
16099371c9d4SSatish Balay         cone[5] = 16;
16109371c9d4SSatish Balay         cone[6] = 17;
16119371c9d4SSatish Balay         cone[7] = 18;
16129566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
16139371c9d4SSatish Balay         cone[0] = 22;
16149371c9d4SSatish Balay         cone[1] = 21;
16159371c9d4SSatish Balay         cone[2] = 26;
16169371c9d4SSatish Balay         cone[3] = 25;
16179371c9d4SSatish Balay         cone[4] = 16;
16189371c9d4SSatish Balay         cone[5] = 23;
16199371c9d4SSatish Balay         cone[6] = 24;
16209371c9d4SSatish Balay         cone[7] = 17;
16219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
16229371c9d4SSatish Balay         cone[0] = 20;
16239371c9d4SSatish Balay         cone[1] = 28;
16249371c9d4SSatish Balay         cone[2] = 26;
16259371c9d4SSatish Balay         cone[3] = 21;
16269371c9d4SSatish Balay         cone[4] = 18;
16279371c9d4SSatish Balay         cone[5] = 17;
16289371c9d4SSatish Balay         cone[6] = 24;
16299371c9d4SSatish Balay         cone[7] = 27;
16309566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
16319371c9d4SSatish Balay         cone[0] = 30;
16329371c9d4SSatish Balay         cone[1] = 28;
16339371c9d4SSatish Balay         cone[2] = 20;
16349371c9d4SSatish Balay         cone[3] = 19;
16359371c9d4SSatish Balay         cone[4] = 29;
16369371c9d4SSatish Balay         cone[5] = 15;
16379371c9d4SSatish Balay         cone[6] = 18;
16389371c9d4SSatish Balay         cone[7] = 27;
16399566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
16409371c9d4SSatish Balay         cone[0] = 30;
16419371c9d4SSatish Balay         cone[1] = 19;
16429371c9d4SSatish Balay         cone[2] = 22;
16439371c9d4SSatish Balay         cone[3] = 25;
16449371c9d4SSatish Balay         cone[4] = 29;
16459371c9d4SSatish Balay         cone[5] = 23;
16469371c9d4SSatish Balay         cone[6] = 16;
16479371c9d4SSatish Balay         cone[7] = 15;
16489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
1649006a8963SMatthew G. Knepley       } else {
16509371c9d4SSatish Balay         cone[0] = 5;
16519371c9d4SSatish Balay         cone[1] = 8;
16529371c9d4SSatish Balay         cone[2] = 7;
16539371c9d4SSatish Balay         cone[3] = 6;
16549371c9d4SSatish Balay         cone[4] = 9;
16559371c9d4SSatish Balay         cone[5] = 12;
16569371c9d4SSatish Balay         cone[6] = 11;
16579371c9d4SSatish Balay         cone[7] = 10;
16589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
16599371c9d4SSatish Balay         cone[0] = 6;
16609371c9d4SSatish Balay         cone[1] = 7;
16619371c9d4SSatish Balay         cone[2] = 14;
16629371c9d4SSatish Balay         cone[3] = 13;
16639371c9d4SSatish Balay         cone[4] = 12;
16649371c9d4SSatish Balay         cone[5] = 15;
16659371c9d4SSatish Balay         cone[6] = 16;
16669371c9d4SSatish Balay         cone[7] = 11;
16679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
16689371c9d4SSatish Balay         cone[0] = 8;
16699371c9d4SSatish Balay         cone[1] = 17;
16709371c9d4SSatish Balay         cone[2] = 14;
16719371c9d4SSatish Balay         cone[3] = 7;
16729371c9d4SSatish Balay         cone[4] = 10;
16739371c9d4SSatish Balay         cone[5] = 11;
16749371c9d4SSatish Balay         cone[6] = 16;
16759371c9d4SSatish Balay         cone[7] = 18;
16769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
16779371c9d4SSatish Balay         cone[0] = 19;
16789371c9d4SSatish Balay         cone[1] = 17;
16799371c9d4SSatish Balay         cone[2] = 8;
16809371c9d4SSatish Balay         cone[3] = 5;
16819371c9d4SSatish Balay         cone[4] = 20;
16829371c9d4SSatish Balay         cone[5] = 9;
16839371c9d4SSatish Balay         cone[6] = 10;
16849371c9d4SSatish Balay         cone[7] = 18;
16859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
16869371c9d4SSatish Balay         cone[0] = 19;
16879371c9d4SSatish Balay         cone[1] = 5;
16889371c9d4SSatish Balay         cone[2] = 6;
16899371c9d4SSatish Balay         cone[3] = 13;
16909371c9d4SSatish Balay         cone[4] = 20;
16919371c9d4SSatish Balay         cone[5] = 15;
16929371c9d4SSatish Balay         cone[6] = 12;
16939371c9d4SSatish Balay         cone[7] = 9;
16949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1695006a8963SMatthew G. Knepley       }
1696d8c47e87SMatthew G. Knepley     }
16979566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
16989566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
16990510c589SMatthew G. Knepley   }
1700dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
17010510c589SMatthew G. Knepley   {
17020510c589SMatthew G. Knepley     Vec             coordinates;
17030510c589SMatthew G. Knepley     PetscSection    coordSection;
17040510c589SMatthew G. Knepley     PetscScalar    *coords;
17050510c589SMatthew G. Knepley     PetscInt        coordSize, v;
17060510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
17070510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
17080510c589SMatthew G. Knepley 
17090510c589SMatthew G. Knepley     /* Build coordinates */
17109566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
17119566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
17129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
17139566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
17140510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
17159566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
17169566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
17170510c589SMatthew G. Knepley     }
17189566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
17199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
17209566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
17219566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
17229566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
17239566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
17249566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
17259566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1726dd400576SPatrick Sanan     if (rank == 0) {
17279371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
17289371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
17299371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
17309371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
17319371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
17329371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
17339371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
17349371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
17359371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
17369371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
17379371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
17389371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
17399371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
17409371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
17419371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
17429371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
17439371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
17449371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
17459371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
17469371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
17479371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
17489371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
17499371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
17509371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
17519371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
17529371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
17539371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
17549371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
17559371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
17569371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
17579371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
17589371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
17599371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
17609371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
17619371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
17629371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
17639371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
17649371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
17659371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
17669371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
17679371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
17689371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
17699371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
17709371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
17719371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
17729371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
17739371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
17749371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
1775ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
17769371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
17779371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
17789371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
17799371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
17809371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
17819371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
17829371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
17839371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
17849371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
17859371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
17869371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
17879371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
17889371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
17899371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
17909371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
17919371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
17929371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
17939371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
17949371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
17959371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
17969371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
17979371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
17989371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
17999371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
1800ae8bcbbbSMatthew G. Knepley       }
1801d8c47e87SMatthew G. Knepley     }
18029566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18039566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18049566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18050510c589SMatthew G. Knepley   }
1806006a8963SMatthew G. Knepley   /* Create periodicity */
1807006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
18086858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
18096858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1810006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
1811ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
18126858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
1813006a8963SMatthew G. Knepley 
18146858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
18156858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
18164fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1817006a8963SMatthew G. Knepley   }
1818dbc1dc17SMatthew G. Knepley   {
18199318fe57SMatthew G. Knepley     DM          cdm;
18209318fe57SMatthew G. Knepley     PetscDS     cds;
18219318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1822dbc1dc17SMatthew G. Knepley 
18239566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
18249566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
18259566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
18269566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
1827dbc1dc17SMatthew G. Knepley   }
18289318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
18299566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
18300510c589SMatthew G. Knepley   PetscFunctionReturn(0);
18310510c589SMatthew G. Knepley }
18320510c589SMatthew G. Knepley 
183324119c2aSMatthew G. Knepley /*@
18349318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
183524119c2aSMatthew G. Knepley 
1836d083f849SBarry Smith   Collective
183724119c2aSMatthew G. Knepley 
183824119c2aSMatthew G. Knepley   Input Parameters:
183924119c2aSMatthew G. Knepley + comm      - The communicator for the DM object
18409318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
184124119c2aSMatthew G. Knepley 
184224119c2aSMatthew G. Knepley   Output Parameter:
184324119c2aSMatthew G. Knepley . dm  - The DM object
184424119c2aSMatthew G. Knepley 
18459318fe57SMatthew G. Knepley   Note:
18469318fe57SMatthew G. Knepley   Here is the output numbering looking from the bottom of the cylinder:
18479318fe57SMatthew G. Knepley $       17-----14
18489318fe57SMatthew G. Knepley $        |     |
18499318fe57SMatthew G. Knepley $        |  2  |
18509318fe57SMatthew G. Knepley $        |     |
18519318fe57SMatthew G. Knepley $ 17-----8-----7-----14
18529318fe57SMatthew G. Knepley $  |     |     |     |
18539318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
18549318fe57SMatthew G. Knepley $  |     |     |     |
18559318fe57SMatthew G. Knepley $ 19-----5-----6-----13
18569318fe57SMatthew G. Knepley $        |     |
18579318fe57SMatthew G. Knepley $        |  4  |
18589318fe57SMatthew G. Knepley $        |     |
18599318fe57SMatthew G. Knepley $       19-----13
18609318fe57SMatthew G. Knepley $
18619318fe57SMatthew G. Knepley $ and up through the top
18629318fe57SMatthew G. Knepley $
18639318fe57SMatthew G. Knepley $       18-----16
18649318fe57SMatthew G. Knepley $        |     |
18659318fe57SMatthew G. Knepley $        |  2  |
18669318fe57SMatthew G. Knepley $        |     |
18679318fe57SMatthew G. Knepley $ 18----10----11-----16
18689318fe57SMatthew G. Knepley $  |     |     |     |
18699318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
18709318fe57SMatthew G. Knepley $  |     |     |     |
18719318fe57SMatthew G. Knepley $ 20-----9----12-----15
18729318fe57SMatthew G. Knepley $        |     |
18739318fe57SMatthew G. Knepley $        |  4  |
18749318fe57SMatthew G. Knepley $        |     |
18759318fe57SMatthew G. Knepley $       20-----15
18769318fe57SMatthew G. Knepley 
187724119c2aSMatthew G. Knepley   Level: beginner
187824119c2aSMatthew G. Knepley 
1879db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
188024119c2aSMatthew G. Knepley @*/
18819371c9d4SSatish Balay PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) {
18829318fe57SMatthew G. Knepley   PetscFunctionBegin;
18839318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
18849566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
18859566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
18869566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
18879318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
18889318fe57SMatthew G. Knepley }
18899318fe57SMatthew G. Knepley 
18909371c9d4SSatish Balay static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) {
189124119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1892412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
18939fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
189424119c2aSMatthew G. Knepley 
189524119c2aSMatthew G. Knepley   PetscFunctionBegin;
189663a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
18979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
18989566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1899412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
19009566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
190124119c2aSMatthew G. Knepley   /* Create topology */
190224119c2aSMatthew G. Knepley   {
190324119c2aSMatthew G. Knepley     PetscInt cone[6], c;
190424119c2aSMatthew G. Knepley 
1905dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
1906dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
19079566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19089566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
19099566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
191024119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19119371c9d4SSatish Balay       cone[0] = c + n * 1;
19129371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
19139371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
19149371c9d4SSatish Balay       cone[3] = c + n * 2;
19159371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
19169371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
19179566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
19189566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
191924119c2aSMatthew G. Knepley     }
19209566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
19219566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
192224119c2aSMatthew G. Knepley   }
19239371c9d4SSatish Balay   for (v = numCells; v < numCells + numVertices; ++v) { PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); }
192424119c2aSMatthew G. Knepley   /* Create cylinder geometry */
192524119c2aSMatthew G. Knepley   {
192624119c2aSMatthew G. Knepley     Vec          coordinates;
192724119c2aSMatthew G. Knepley     PetscSection coordSection;
192824119c2aSMatthew G. Knepley     PetscScalar *coords;
1929412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
193024119c2aSMatthew G. Knepley 
193124119c2aSMatthew G. Knepley     /* Build coordinates */
19329566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
19339566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
19349566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
19359566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
193624119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
19379566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
19389566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
193924119c2aSMatthew G. Knepley     }
19409566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
19419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
19429566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
19439566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
19449566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
19459566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
19469566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
19479566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
194824119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19499371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19509371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19519371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
19529371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19539371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19549371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
195524119c2aSMatthew G. Knepley     }
1956dd400576SPatrick Sanan     if (rank == 0) {
19579371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
19589371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
19599371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
19609371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
19619371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
19629371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
19639fe9f049SMatthew G. Knepley     }
19649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
19659566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
19669566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
196724119c2aSMatthew G. Knepley   }
19689318fe57SMatthew G. Knepley   /* Interpolate */
19699566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
19709318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
19719318fe57SMatthew G. Knepley }
19729318fe57SMatthew G. Knepley 
19739318fe57SMatthew G. Knepley /*@
19749318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
19759318fe57SMatthew G. Knepley 
19769318fe57SMatthew G. Knepley   Collective
19779318fe57SMatthew G. Knepley 
19789318fe57SMatthew G. Knepley   Input Parameters:
19799318fe57SMatthew G. Knepley + comm - The communicator for the DM object
19809318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
19819318fe57SMatthew G. Knepley - interpolate - Create edges and faces
19829318fe57SMatthew G. Knepley 
19839318fe57SMatthew G. Knepley   Output Parameter:
19849318fe57SMatthew G. Knepley . dm  - The DM object
19859318fe57SMatthew G. Knepley 
19869318fe57SMatthew G. Knepley   Level: beginner
19879318fe57SMatthew G. Knepley 
1988db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
19899318fe57SMatthew G. Knepley @*/
19909371c9d4SSatish Balay PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) {
19919318fe57SMatthew G. Knepley   PetscFunctionBegin;
19929318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
19939566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
19949566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
19959566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
199624119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
199724119c2aSMatthew G. Knepley }
199824119c2aSMatthew G. Knepley 
19999371c9d4SSatish Balay static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) {
200065a81367SMatthew G. Knepley   PetscReal prod = 0.0;
200165a81367SMatthew G. Knepley   PetscInt  i;
200265a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
200365a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
200465a81367SMatthew G. Knepley }
20059371c9d4SSatish Balay static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) {
200665a81367SMatthew G. Knepley   PetscReal prod = 0.0;
200765a81367SMatthew G. Knepley   PetscInt  i;
200865a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
200965a81367SMatthew G. Knepley   return prod;
201065a81367SMatthew G. Knepley }
201165a81367SMatthew G. Knepley 
201251a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
20139371c9d4SSatish Balay 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[]) {
201451a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
201551a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
201651a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
201751a74b61SMatthew G. Knepley 
201851a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
201951a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
202051a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
202151a74b61SMatthew G. Knepley }
202251a74b61SMatthew G. Knepley 
20239371c9d4SSatish Balay static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) {
202465a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
202565a81367SMatthew G. Knepley   PetscSection   coordSection;
202665a81367SMatthew G. Knepley   Vec            coordinates;
202765a81367SMatthew G. Knepley   PetscScalar   *coords;
202865a81367SMatthew G. Knepley   PetscReal     *coordsIn;
202965a81367SMatthew G. Knepley   PetscInt       numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e;
203065a81367SMatthew G. Knepley   PetscMPIInt    rank;
203165a81367SMatthew G. Knepley 
203265a81367SMatthew G. Knepley   PetscFunctionBegin;
20339318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
20349566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
20359566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
20369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
203765a81367SMatthew G. Knepley   switch (dim) {
203865a81367SMatthew G. Knepley   case 2:
203965a81367SMatthew G. Knepley     if (simplex) {
204051a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
204151a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
204265a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
204351a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
204465a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
204565a81367SMatthew G. Knepley       PetscInt        cone[3];
204665a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
204765a81367SMatthew G. Knepley 
20489371c9d4SSatish Balay       vertex[0] *= R / radius;
20499371c9d4SSatish Balay       vertex[1] *= R / radius;
20509371c9d4SSatish Balay       vertex[2] *= R / radius;
2051dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2052dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
205365a81367SMatthew G. Knepley       firstVertex = numCells;
205451a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
205565a81367SMatthew G. Knepley 
205665a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
205765a81367SMatthew G. Knepley 
205865a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
205951a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
206065a81367SMatthew G. Knepley       */
206165a81367SMatthew G. Knepley       /* Construct vertices */
20629566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2063dd400576SPatrick Sanan       if (rank == 0) {
206465a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
206565a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
206665a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
206765a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
206865a81367SMatthew G. Knepley               ++i;
206965a81367SMatthew G. Knepley             }
207065a81367SMatthew G. Knepley           }
207165a81367SMatthew G. Knepley         }
207245da822fSValeria Barra       }
207365a81367SMatthew G. Knepley       /* Construct graph */
20749566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
207565a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
207665a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
20779371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
20789371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
20799371c9d4SSatish Balay             ++k;
20809371c9d4SSatish Balay           }
208165a81367SMatthew G. Knepley         }
208263a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
208365a81367SMatthew G. Knepley       }
208465a81367SMatthew G. Knepley       /* Build Topology */
20859566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
20869371c9d4SSatish Balay       for (c = 0; c < numCells; c++) { PetscCall(DMPlexSetConeSize(dm, c, embedDim)); }
20879566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
208865a81367SMatthew G. Knepley       /* Cells */
208965a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
209065a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
209165a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
209265a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
20939371c9d4SSatish Balay               cone[0] = firstVertex + i;
20949371c9d4SSatish Balay               cone[1] = firstVertex + j;
20959371c9d4SSatish Balay               cone[2] = firstVertex + k;
209665a81367SMatthew G. Knepley               /* Check orientation */
209765a81367SMatthew G. Knepley               {
20989371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
20999371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
21009371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
21019371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
21029371c9d4SSatish Balay                 };
210365a81367SMatthew G. Knepley                 PetscReal normal[3];
210465a81367SMatthew G. Knepley                 PetscInt  e, f;
210565a81367SMatthew G. Knepley 
210665a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
210765a81367SMatthew G. Knepley                   normal[d] = 0.0;
210865a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
21099371c9d4SSatish Balay                     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]); }
211065a81367SMatthew G. Knepley                   }
211165a81367SMatthew G. Knepley                 }
21129371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
21139371c9d4SSatish Balay                   PetscInt tmp = cone[1];
21149371c9d4SSatish Balay                   cone[1]      = cone[2];
21159371c9d4SSatish Balay                   cone[2]      = tmp;
211665a81367SMatthew G. Knepley                 }
211765a81367SMatthew G. Knepley               }
21189566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
211965a81367SMatthew G. Knepley             }
212065a81367SMatthew G. Knepley           }
212165a81367SMatthew G. Knepley         }
212265a81367SMatthew G. Knepley       }
21239566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
21249566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
21259566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
212665a81367SMatthew G. Knepley     } else {
21272829fed8SMatthew G. Knepley       /*
21282829fed8SMatthew G. Knepley         12-21--13
21292829fed8SMatthew G. Knepley          |     |
21302829fed8SMatthew G. Knepley         25  4  24
21312829fed8SMatthew G. Knepley          |     |
21322829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
21332829fed8SMatthew G. Knepley    |     |     |     |
21342829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
21352829fed8SMatthew G. Knepley    |     |     |     |
21362829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
21372829fed8SMatthew G. Knepley          |     |
21382829fed8SMatthew G. Knepley         20  1  19
21392829fed8SMatthew G. Knepley          |     |
21402829fed8SMatthew G. Knepley         10-18--11
21412829fed8SMatthew G. Knepley          |     |
21422829fed8SMatthew G. Knepley         23  2  22
21432829fed8SMatthew G. Knepley          |     |
21442829fed8SMatthew G. Knepley         12-21--13
21452829fed8SMatthew G. Knepley        */
21462829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
21472829fed8SMatthew G. Knepley 
2148dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2149dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2150dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
215165a81367SMatthew G. Knepley       firstVertex = numCells;
215265a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
21532829fed8SMatthew G. Knepley       /* Build Topology */
21549566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
21559371c9d4SSatish Balay       for (c = 0; c < numCells; c++) { PetscCall(DMPlexSetConeSize(dm, c, 4)); }
21569371c9d4SSatish Balay       for (e = firstEdge; e < firstEdge + numEdges; ++e) { PetscCall(DMPlexSetConeSize(dm, e, 2)); }
21579566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2158dd400576SPatrick Sanan       if (rank == 0) {
21592829fed8SMatthew G. Knepley         /* Cell 0 */
21609371c9d4SSatish Balay         cone[0] = 14;
21619371c9d4SSatish Balay         cone[1] = 15;
21629371c9d4SSatish Balay         cone[2] = 16;
21639371c9d4SSatish Balay         cone[3] = 17;
21649566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
21659371c9d4SSatish Balay         ornt[0] = 0;
21669371c9d4SSatish Balay         ornt[1] = 0;
21679371c9d4SSatish Balay         ornt[2] = 0;
21689371c9d4SSatish Balay         ornt[3] = 0;
21699566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
21702829fed8SMatthew G. Knepley         /* Cell 1 */
21719371c9d4SSatish Balay         cone[0] = 18;
21729371c9d4SSatish Balay         cone[1] = 19;
21739371c9d4SSatish Balay         cone[2] = 14;
21749371c9d4SSatish Balay         cone[3] = 20;
21759566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
21769371c9d4SSatish Balay         ornt[0] = 0;
21779371c9d4SSatish Balay         ornt[1] = 0;
21789371c9d4SSatish Balay         ornt[2] = -1;
21799371c9d4SSatish Balay         ornt[3] = 0;
21809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
21812829fed8SMatthew G. Knepley         /* Cell 2 */
21829371c9d4SSatish Balay         cone[0] = 21;
21839371c9d4SSatish Balay         cone[1] = 22;
21849371c9d4SSatish Balay         cone[2] = 18;
21859371c9d4SSatish Balay         cone[3] = 23;
21869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
21879371c9d4SSatish Balay         ornt[0] = 0;
21889371c9d4SSatish Balay         ornt[1] = 0;
21899371c9d4SSatish Balay         ornt[2] = -1;
21909371c9d4SSatish Balay         ornt[3] = 0;
21919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
21922829fed8SMatthew G. Knepley         /* Cell 3 */
21939371c9d4SSatish Balay         cone[0] = 19;
21949371c9d4SSatish Balay         cone[1] = 22;
21959371c9d4SSatish Balay         cone[2] = 24;
21969371c9d4SSatish Balay         cone[3] = 15;
21979566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
21989371c9d4SSatish Balay         ornt[0] = -1;
21999371c9d4SSatish Balay         ornt[1] = -1;
22009371c9d4SSatish Balay         ornt[2] = 0;
22019371c9d4SSatish Balay         ornt[3] = -1;
22029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
22032829fed8SMatthew G. Knepley         /* Cell 4 */
22049371c9d4SSatish Balay         cone[0] = 16;
22059371c9d4SSatish Balay         cone[1] = 24;
22069371c9d4SSatish Balay         cone[2] = 21;
22079371c9d4SSatish Balay         cone[3] = 25;
22089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
22099371c9d4SSatish Balay         ornt[0] = -1;
22109371c9d4SSatish Balay         ornt[1] = -1;
22119371c9d4SSatish Balay         ornt[2] = -1;
22129371c9d4SSatish Balay         ornt[3] = 0;
22139566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
22142829fed8SMatthew G. Knepley         /* Cell 5 */
22159371c9d4SSatish Balay         cone[0] = 20;
22169371c9d4SSatish Balay         cone[1] = 17;
22179371c9d4SSatish Balay         cone[2] = 25;
22189371c9d4SSatish Balay         cone[3] = 23;
22199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
22209371c9d4SSatish Balay         ornt[0] = -1;
22219371c9d4SSatish Balay         ornt[1] = -1;
22229371c9d4SSatish Balay         ornt[2] = -1;
22239371c9d4SSatish Balay         ornt[3] = -1;
22249566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
22252829fed8SMatthew G. Knepley         /* Edges */
22269371c9d4SSatish Balay         cone[0] = 6;
22279371c9d4SSatish Balay         cone[1] = 7;
22289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
22299371c9d4SSatish Balay         cone[0] = 7;
22309371c9d4SSatish Balay         cone[1] = 8;
22319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
22329371c9d4SSatish Balay         cone[0] = 8;
22339371c9d4SSatish Balay         cone[1] = 9;
22349566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
22359371c9d4SSatish Balay         cone[0] = 9;
22369371c9d4SSatish Balay         cone[1] = 6;
22379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
22389371c9d4SSatish Balay         cone[0] = 10;
22399371c9d4SSatish Balay         cone[1] = 11;
22409566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
22419371c9d4SSatish Balay         cone[0] = 11;
22429371c9d4SSatish Balay         cone[1] = 7;
22439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
22449371c9d4SSatish Balay         cone[0] = 6;
22459371c9d4SSatish Balay         cone[1] = 10;
22469566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
22479371c9d4SSatish Balay         cone[0] = 12;
22489371c9d4SSatish Balay         cone[1] = 13;
22499566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
22509371c9d4SSatish Balay         cone[0] = 13;
22519371c9d4SSatish Balay         cone[1] = 11;
22529566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
22539371c9d4SSatish Balay         cone[0] = 10;
22549371c9d4SSatish Balay         cone[1] = 12;
22559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
22569371c9d4SSatish Balay         cone[0] = 13;
22579371c9d4SSatish Balay         cone[1] = 8;
22589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
22599371c9d4SSatish Balay         cone[0] = 12;
22609371c9d4SSatish Balay         cone[1] = 9;
22619566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
226245da822fSValeria Barra       }
22639566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
22649566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
22652829fed8SMatthew G. Knepley       /* Build coordinates */
22669566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2267dd400576SPatrick Sanan       if (rank == 0) {
22689371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
22699371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
22709371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
22719371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
22729371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
22739371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
22749371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
22759371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
22769371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
22779371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
22789371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
22799371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
22809371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
22819371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
22829371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
22839371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
22849371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
22859371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
22869371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
22879371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
22889371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
22899371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
22909371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
22919371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
229265a81367SMatthew G. Knepley       }
229345da822fSValeria Barra     }
229465a81367SMatthew G. Knepley     break;
229565a81367SMatthew G. Knepley   case 3:
2296116ded15SMatthew G. Knepley     if (simplex) {
2297116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
229851a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
229951a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
230051a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2301116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2302116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
23039371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
23049371c9d4SSatish Balay                {0, 1, 2, 3},
23059371c9d4SSatish Balay                {0, 2, 3, 1},
23069371c9d4SSatish Balay                {0, 3, 1, 2},
23079371c9d4SSatish Balay                {1, 0, 3, 2},
23089371c9d4SSatish Balay                {1, 2, 0, 3},
23099371c9d4SSatish Balay                {1, 3, 2, 0},
23109371c9d4SSatish Balay                {2, 0, 1, 3},
23119371c9d4SSatish Balay                {2, 1, 3, 0},
23129371c9d4SSatish Balay                {2, 3, 0, 1},
23139371c9d4SSatish Balay                {3, 0, 2, 1},
23149371c9d4SSatish Balay                {3, 1, 0, 2},
23159371c9d4SSatish Balay                {3, 2, 1, 0}
23169371c9d4SSatish Balay       };
2317116ded15SMatthew G. Knepley       PetscInt  cone[4];
2318116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2319116ded15SMatthew G. Knepley 
23209371c9d4SSatish Balay       vertexA[0] *= R;
23219371c9d4SSatish Balay       vertexA[1] *= R;
23229371c9d4SSatish Balay       vertexA[2] *= R;
23239371c9d4SSatish Balay       vertexA[3] *= R;
23249371c9d4SSatish Balay       vertexB[0] *= R;
23259371c9d4SSatish Balay       vertexB[1] *= R;
23269371c9d4SSatish Balay       vertexB[2] *= R;
23279371c9d4SSatish Balay       vertexB[3] *= R;
23289371c9d4SSatish Balay       vertexC[0] *= R;
23299371c9d4SSatish Balay       vertexC[1] *= R;
23309371c9d4SSatish Balay       vertexC[2] *= R;
23319371c9d4SSatish Balay       vertexC[3] *= R;
2332dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2333dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2334116ded15SMatthew G. Knepley       firstVertex = numCells;
2335116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2336116ded15SMatthew G. Knepley 
2337116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2338116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2339116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2340116ded15SMatthew G. Knepley 
2341116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
23426333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2343116ded15SMatthew G. Knepley 
2344116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2345116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2346116ded15SMatthew G. Knepley       */
2347116ded15SMatthew G. Knepley       /* Construct vertices */
23489566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2349116ded15SMatthew G. Knepley       i = 0;
2350dd400576SPatrick Sanan       if (rank == 0) {
2351116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2352116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2353116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2354116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2355116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2356116ded15SMatthew G. Knepley                 ++i;
2357116ded15SMatthew G. Knepley               }
2358116ded15SMatthew G. Knepley             }
2359116ded15SMatthew G. Knepley           }
2360116ded15SMatthew G. Knepley         }
2361116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2362116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2363116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2364116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2365116ded15SMatthew G. Knepley             ++i;
2366116ded15SMatthew G. Knepley           }
2367116ded15SMatthew G. Knepley         }
2368116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2369116ded15SMatthew G. Knepley           s[3] = 1;
2370116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2371116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2372116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2373116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2374116ded15SMatthew G. Knepley                 ++i;
2375116ded15SMatthew G. Knepley               }
2376116ded15SMatthew G. Knepley             }
2377116ded15SMatthew G. Knepley           }
2378116ded15SMatthew G. Knepley         }
237945da822fSValeria Barra       }
238063a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2381116ded15SMatthew G. Knepley       /* Construct graph */
23829566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2383116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2384116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
23859371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
23869371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
23879371c9d4SSatish Balay             ++k;
23889371c9d4SSatish Balay           }
2389116ded15SMatthew G. Knepley         }
239063a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2391116ded15SMatthew G. Knepley       }
2392116ded15SMatthew G. Knepley       /* Build Topology */
23939566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
23949371c9d4SSatish Balay       for (c = 0; c < numCells; c++) { PetscCall(DMPlexSetConeSize(dm, c, embedDim)); }
23959566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2396116ded15SMatthew G. Knepley       /* Cells */
2397dd400576SPatrick Sanan       if (rank == 0) {
2398116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2399116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2400116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2401116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
24029371c9d4SSatish 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]) {
24039371c9d4SSatish Balay                   cone[0] = firstVertex + i;
24049371c9d4SSatish Balay                   cone[1] = firstVertex + j;
24059371c9d4SSatish Balay                   cone[2] = firstVertex + k;
24069371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2407116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2408116ded15SMatthew G. Knepley                   {
24099371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
24109371c9d4SSatish 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}}},
2411116ded15SMatthew G. Knepley 
24129371c9d4SSatish 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}}},
2413116ded15SMatthew G. Knepley 
24149371c9d4SSatish 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}}},
2415116ded15SMatthew G. Knepley 
24169371c9d4SSatish 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}} }
24179371c9d4SSatish Balay                     };
2418116ded15SMatthew G. Knepley                     PetscReal normal[4];
2419116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2420116ded15SMatthew G. Knepley 
2421116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2422116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2423116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2424116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2425116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2426116ded15SMatthew 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]);
2427116ded15SMatthew G. Knepley                           }
2428116ded15SMatthew G. Knepley                         }
2429116ded15SMatthew G. Knepley                       }
2430116ded15SMatthew G. Knepley                     }
24319371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
24329371c9d4SSatish Balay                       PetscInt tmp = cone[1];
24339371c9d4SSatish Balay                       cone[1]      = cone[2];
24349371c9d4SSatish Balay                       cone[2]      = tmp;
24359371c9d4SSatish Balay                     }
2436116ded15SMatthew G. Knepley                   }
24379566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2438116ded15SMatthew G. Knepley                 }
2439116ded15SMatthew G. Knepley               }
2440116ded15SMatthew G. Knepley             }
2441116ded15SMatthew G. Knepley           }
2442116ded15SMatthew G. Knepley         }
244345da822fSValeria Barra       }
24449566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
24459566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
24469566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2447116ded15SMatthew G. Knepley       break;
2448116ded15SMatthew G. Knepley     }
244963a3b9bcSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
245065a81367SMatthew G. Knepley   }
245165a81367SMatthew G. Knepley   /* Create coordinates */
24529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
24539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
24549566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
24559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
24562829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
24579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
24589566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
24592829fed8SMatthew G. Knepley   }
24609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
24619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
24629566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
24639566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
24649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
24659566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
24669566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
24679566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
24689371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
24699371c9d4SSatish Balay     for (d = 0; d < embedDim; ++d) { coords[v * embedDim + d] = coordsIn[v * embedDim + d]; }
24709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
24719566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
24729566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
24739566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
247451a74b61SMatthew G. Knepley   {
247551a74b61SMatthew G. Knepley     DM          cdm;
247651a74b61SMatthew G. Knepley     PetscDS     cds;
24779318fe57SMatthew G. Knepley     PetscScalar c = R;
247851a74b61SMatthew G. Knepley 
24799566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
24809566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
24819566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
24829566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
248351a74b61SMatthew G. Knepley   }
24849318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
24859566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
24869318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
24879318fe57SMatthew G. Knepley }
24889318fe57SMatthew G. Knepley 
2489b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
2490b7f5c055SJed Brown 
2491b7f5c055SJed Brown /*
2492b7f5c055SJed Brown  The Schwarz P implicit surface is
2493b7f5c055SJed Brown 
2494b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2495b7f5c055SJed Brown */
24969371c9d4SSatish Balay static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) {
2497b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2498b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2499b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
2500b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2501b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
25029371c9d4SSatish Balay     for (PetscInt j = 0; j < 3; j++) { hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; }
2503b7f5c055SJed Brown   }
2504b7f5c055SJed Brown }
2505b7f5c055SJed Brown 
25064663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
25074663dae6SJed Brown static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) {
25089371c9d4SSatish Balay   for (PetscInt i = 0; i < 3; i++) { u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); }
25094663dae6SJed Brown   return 0;
25104663dae6SJed Brown }
25114663dae6SJed Brown 
2512b7f5c055SJed Brown /*
2513b7f5c055SJed Brown  The Gyroid implicit surface is
2514b7f5c055SJed Brown 
2515b7f5c055SJed 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)
2516b7f5c055SJed Brown 
2517b7f5c055SJed Brown */
25189371c9d4SSatish Balay static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) {
2519b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2520b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2521b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2522b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2523b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2524b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2525b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2526b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2527b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2528b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2529b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2530b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2531b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2532b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2533b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2534b7f5c055SJed Brown }
2535b7f5c055SJed Brown 
25364663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
25374663dae6SJed Brown static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) {
25384663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
25394663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
25404663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
25414663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
25424663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
25434663dae6SJed Brown   return 0;
25444663dae6SJed Brown }
25454663dae6SJed Brown 
2546b7f5c055SJed Brown /*
2547b7f5c055SJed Brown    We wish to solve
2548b7f5c055SJed Brown 
2549b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2550b7f5c055SJed Brown 
2551b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2552b7f5c055SJed 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
2553b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2554b7f5c055SJed Brown 
2555b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2556b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2557b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2558b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2559b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2560b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2561b7f5c055SJed Brown 
2562b7f5c055SJed Brown      f(y) = 0                       1 equation
2563b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2564b7f5c055SJed Brown 
2565b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2566b7f5c055SJed Brown */
25679371c9d4SSatish Balay static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) {
2568b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2569b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
25702f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
25719371c9d4SSatish Balay   PetscReal n_y[3][3] = {
25729371c9d4SSatish Balay     {0, 0, 0},
25739371c9d4SSatish Balay     {0, 0, 0},
25749371c9d4SSatish Balay     {0, 0, 0}
25759371c9d4SSatish Balay   };
2576b7f5c055SJed Brown 
2577b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2578b7f5c055SJed Brown 
2579b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
2580b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
25819371c9d4SSatish Balay   for (PetscInt i = 0; i < 3; i++) { norm_y[i] = 1. / norm * n[i] * n_y[i][i]; }
2582b7f5c055SJed Brown 
2583b7f5c055SJed Brown   // Define the Householder reflector
2584b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2585b7f5c055SJed Brown   n[0] += norm * sign;
2586b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
2587b7f5c055SJed Brown 
2588b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2589b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2590b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2591b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2592b7f5c055SJed Brown 
2593b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2594b7f5c055SJed Brown     n[i] /= norm;
2595b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
2596b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2597b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2598b7f5c055SJed Brown     }
2599b7f5c055SJed Brown   }
2600b7f5c055SJed Brown 
2601b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2602b7f5c055SJed 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];
2603b7f5c055SJed Brown 
2604b7f5c055SJed Brown   res[0] = f;
2605b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2606b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2607b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2608b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
2609b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
2610b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2611b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2612b7f5c055SJed Brown   }
2613b7f5c055SJed Brown }
2614b7f5c055SJed Brown 
2615b7f5c055SJed Brown /*
2616b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2617b7f5c055SJed Brown */
26189371c9d4SSatish Balay static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) {
2619b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2620b7f5c055SJed Brown 
2621b7f5c055SJed Brown   PetscFunctionBegin;
2622b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
2623b7f5c055SJed Brown     PetscScalar res[3], J[9];
2624b7f5c055SJed Brown     PetscReal   resnorm;
2625b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2626b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2627b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
262863a3b9bcSJacob 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])));
2629b7f5c055SJed Brown     }
2630b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2631b7f5c055SJed Brown 
2632b7f5c055SJed Brown     // Take the Newton step
26339566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2634b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2635b7f5c055SJed Brown   }
2636b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
2637b7f5c055SJed Brown   PetscFunctionReturn(0);
2638b7f5c055SJed Brown }
2639b7f5c055SJed Brown 
2640b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2641b7f5c055SJed Brown 
26429371c9d4SSatish Balay static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) {
2643b7f5c055SJed Brown   PetscMPIInt rank;
2644b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2645b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
2646b7f5c055SJed Brown   PetscInt            *cells_flat = NULL;
2647b7f5c055SJed Brown   PetscReal           *vtxCoords  = NULL;
2648b7f5c055SJed Brown   TPSEvaluateFunc      evalFunc   = NULL;
26494663dae6SJed Brown   PetscSimplePointFunc normalFunc = NULL;
2650b7f5c055SJed Brown   DMLabel              label;
2651b7f5c055SJed Brown 
2652b7f5c055SJed Brown   PetscFunctionBegin;
26539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
265463a3b9bcSJacob 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);
2655b7f5c055SJed Brown   switch (tpstype) {
2656b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2657b7f5c055SJed 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");
2658c5853193SPierre Jolivet     if (rank == 0) {
2659b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2660b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2661b7f5c055SJed Brown       PetscReal L = 1;
2662b7f5c055SJed Brown 
2663b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
2664b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
2665b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
2666b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
2667b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2668b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
26699566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
26709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
26719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
26729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
2673b7f5c055SJed Brown       // x-normal pipes
2674b7f5c055SJed Brown       vcount = 0;
2675b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
2676b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2677b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2678b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2679b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
2680b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2681b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2682b7f5c055SJed Brown             }
2683b7f5c055SJed Brown           }
2684b7f5c055SJed Brown         }
2685b7f5c055SJed Brown       }
2686b7f5c055SJed Brown       // y-normal pipes
2687b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2688b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
2689b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2690b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2691b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2692b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
2693b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2694b7f5c055SJed Brown             }
2695b7f5c055SJed Brown           }
2696b7f5c055SJed Brown         }
2697b7f5c055SJed Brown       }
2698b7f5c055SJed Brown       // z-normal pipes
2699b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2700b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2701b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
2702b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2703b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2704b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2705b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
2706b7f5c055SJed Brown             }
2707b7f5c055SJed Brown           }
2708b7f5c055SJed Brown         }
2709b7f5c055SJed Brown       }
2710b7f5c055SJed Brown       // junctions
2711b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2712b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2713b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2714b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
2715b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2716b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
2717b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
2718b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
2719b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
2720b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
2721b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
2722b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
2723b7f5c055SJed Brown                 }
2724b7f5c055SJed Brown               }
2725b7f5c055SJed Brown             }
2726b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2727b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
2728b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
2729b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
2730b7f5c055SJed Brown             };
2731b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
27329371c9d4SSatish 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};
2733b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
27349371c9d4SSatish 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};
2735b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
2736b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2737b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
2738b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
2739b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
2740b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
2741b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
2742b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
2743b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
2744b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
2745b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
2746b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2747b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2748b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
2749b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
2750b7f5c055SJed Brown                   numEdges++;
2751b7f5c055SJed Brown                 }
2752b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2753b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2754b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
2755b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
2756b7f5c055SJed Brown                   numEdges++;
2757b7f5c055SJed Brown                 }
2758b7f5c055SJed Brown               }
2759b7f5c055SJed Brown             }
2760b7f5c055SJed Brown           }
2761b7f5c055SJed Brown         }
2762b7f5c055SJed Brown       }
276363a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
2764b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
2765b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2766b7f5c055SJed Brown     }
2767b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
27684663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
2769b7f5c055SJed Brown     break;
2770b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2771c5853193SPierre Jolivet     if (rank == 0) {
2772b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2773b7f5c055SJed Brown       //
2774b7f5c055SJed 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)
2775b7f5c055SJed Brown       //
2776b7f5c055SJed Brown       // on the cell [0,2]^3.
2777b7f5c055SJed Brown       //
2778b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2779b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2780b7f5c055SJed Brown       // like a boomerang:
2781b7f5c055SJed Brown       //
2782b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2783b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2784b7f5c055SJed Brown       //                                                              //
2785b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2786b7f5c055SJed Brown       //      \                                   /            \      //
2787b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2788b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2789b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2790b7f5c055SJed Brown       //                                                              //
2791b7f5c055SJed Brown       //                                                              //
2792b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2793b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2794b7f5c055SJed Brown       //                                                              //
2795b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2796b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2797b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2798b7f5c055SJed Brown       //            \                       /                \        //
2799b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2800b7f5c055SJed Brown       //
2801b7f5c055SJed Brown       //
2802b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2803b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2804b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2805b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2806b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2807b7f5c055SJed Brown       //
2808b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2809b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2810b7f5c055SJed Brown       //
2811b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2812b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2813b7f5c055SJed Brown 
2814b7f5c055SJed Brown       PetscInt       facesPerBlock = 64;
2815b7f5c055SJed Brown       PetscInt       vertsPerBlock = 56;
2816b7f5c055SJed Brown       PetscInt       extentPlus[3];
2817b7f5c055SJed Brown       PetscInt       numBlocks, numBlocksPlus;
28189371c9d4SSatish 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;
28199371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
28209371c9d4SSatish Balay   /* face to vertex within the coarse discretization of a single gyroid block */
2821b7f5c055SJed Brown   /* layer 0 */
28229371c9d4SSatish Balay         {A,           C,           K,           G          },
28239371c9d4SSatish Balay         {C,           B,           II,          K          },
28249371c9d4SSatish Balay         {D,           A,           H,           L          },
28259371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
28269371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
28279371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
28289371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
28299371c9d4SSatish Balay         {B,           F,           M,           II         },
2830b7f5c055SJed Brown  /* layer 1 */
28319371c9d4SSatish Balay         {G,           K,           Q,           O          },
28329371c9d4SSatish Balay         {K,           II,          P,           Q          },
28339371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
28349371c9d4SSatish Balay         {J,           L,           R,           P          },
28359371c9d4SSatish Balay         {N,           J,           P,           S          },
28369371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
28379371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
28389371c9d4SSatish Balay         {II,          M,           T,           P          },
2839b7f5c055SJed Brown  /* layer 2 */
28409371c9d4SSatish Balay         {O,           Q,           Y,           U          },
28419371c9d4SSatish Balay         {Q,           P,           W,           Y          },
28429371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
28439371c9d4SSatish Balay         {P,           R,           Ap,          W          },
28449371c9d4SSatish Balay         {S,           P,           X,           Bp         },
28459371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
28469371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
28479371c9d4SSatish Balay         {P,           T,           Z,           X          },
2848b7f5c055SJed Brown  /* layer 3 */
28499371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
28509371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
28519371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
28529371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
28539371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
28549371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
28559371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
28569371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
2857b7f5c055SJed Brown  /* layer 4 */
28589371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
28599371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
28609371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
28619371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
28629371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
28639371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
28649371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
28659371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
2866b7f5c055SJed Brown  /* layer 5 */
28679371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
28689371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
28699371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
28709371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
28719371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
28729371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
28739371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
28749371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
2875b7f5c055SJed Brown  /* layer 6 */
28769371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
28779371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
28789371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
28799371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
28809371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
28819371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
28829371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
28839371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
2884b7f5c055SJed Brown  /* layer 7 (the top is the periodic image of the bottom of layer 0) */
28859371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
28869371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
28879371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
28889371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
28899371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
28909371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
28919371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
28929371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
2893b7f5c055SJed Brown       };
2894b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
28959371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
2896bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
2897bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
2898bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
2899bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
2900bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
2901bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
2902b7f5c055SJed Brown 
2903bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
2904bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
2905bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
2906bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
2907bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
2908bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
2909bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
2910bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
2911b7f5c055SJed Brown 
2912bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
2913bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
2914bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
2915bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
2916bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
2917bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
2918b7f5c055SJed Brown 
2919bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
2920bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
2921bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
2922bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
2923bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
2924bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
2925bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
2926bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
2927b7f5c055SJed Brown 
2928bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
2929bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
2930bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
2931bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
2932bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
2933bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
2934b7f5c055SJed Brown 
2935bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
2936bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
2937bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
2938bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
2939bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
2940bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
2941bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
2942bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
2943b7f5c055SJed Brown 
2944bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
2945bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
2946bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
2947bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
2948bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
2949bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
2950b7f5c055SJed Brown 
2951bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
2952bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
2953bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
2954bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
2955bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
2956bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
2957bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
2958bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
2959b7f5c055SJed Brown       };
2960b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
2961b7f5c055SJed Brown       PetscBool *seen;
2962b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
2963b7f5c055SJed Brown       PetscInt   count;
2964b7f5c055SJed Brown 
2965b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
2966b7f5c055SJed Brown       numBlocks = 1;
2967b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
2968b7f5c055SJed Brown       numBlocksPlus = 1;
2969b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
2970b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
29719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
29729566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
2973b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
2974b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2975b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
2976b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
2977b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
2978b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
2979b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
2980b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
2981b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
2982b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
2983b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
2984b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
2985b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
2986b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
2987b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
2988b7f5c055SJed Brown 
2989b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
2990b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
2991b7f5c055SJed Brown               }
2992b7f5c055SJed Brown             }
2993b7f5c055SJed Brown           }
2994b7f5c055SJed Brown         }
2995b7f5c055SJed Brown       }
29969371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
29979371c9d4SSatish Balay         if (seen[i]) numVertices++;
2998b7f5c055SJed Brown       count = 0;
29999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
30009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3001b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3002b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3003b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3004b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3005b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3006b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3007b7f5c055SJed Brown 
3008b7f5c055SJed Brown               if (seen[vIdx]) {
3009b7f5c055SJed Brown                 PetscInt thisVert;
3010b7f5c055SJed Brown 
3011b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3012b7f5c055SJed Brown 
3013b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3014b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3015b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3016b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3017b7f5c055SJed Brown               }
3018b7f5c055SJed Brown             }
3019b7f5c055SJed Brown           }
3020b7f5c055SJed Brown         }
3021b7f5c055SJed Brown       }
3022b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3023b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
30249371c9d4SSatish Balay           for (PetscInt v = 0; v < 4; v++) { cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; }
3025b7f5c055SJed Brown         }
3026b7f5c055SJed Brown       }
30279566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
30289566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3029b7f5c055SJed Brown       cells_flat = cells[0][0];
3030b7f5c055SJed Brown       numEdges   = 0;
3031b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3032b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3033b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3034b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3035b7f5c055SJed Brown 
3036b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3037b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3038b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3039b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3040b7f5c055SJed Brown             }
3041b7f5c055SJed Brown           }
3042b7f5c055SJed Brown         }
3043b7f5c055SJed Brown       }
30449566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
30459566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3046b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3047b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3048b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3049b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3050b7f5c055SJed Brown 
3051b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3052b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3053b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3054b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3055b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3056b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3057b7f5c055SJed Brown               }
3058b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3059b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3060b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3061b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3062b7f5c055SJed Brown               }
3063b7f5c055SJed Brown             }
3064b7f5c055SJed Brown           }
3065b7f5c055SJed Brown         }
3066b7f5c055SJed Brown       }
3067b7f5c055SJed Brown     }
3068b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
30694663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3070b7f5c055SJed Brown     break;
3071b7f5c055SJed Brown   }
3072b7f5c055SJed Brown 
30739566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3074c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
30759566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
30769566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3077b7f5c055SJed Brown   {
3078b7f5c055SJed Brown     DM idm;
30799566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
3080*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3081b7f5c055SJed Brown   }
3082c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
30839566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
30849566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3085b7f5c055SJed Brown 
30869566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
30879566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3088b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3089b7f5c055SJed Brown     PetscInt        njoin;
3090b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
30919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
309263a3b9bcSJacob 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]);
30939566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
30949566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3095b7f5c055SJed Brown   }
30969566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
30979566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
30981436d7faSJed Brown   if (tps_distribute) {
30991436d7faSJed Brown     DM               pdm = NULL;
31001436d7faSJed Brown     PetscPartitioner part;
31011436d7faSJed Brown 
31029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
31039566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
31049566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
3105*69d8a87bSksagiyam     if (pdm) { PetscCall(DMPlexReplace_Internal(dm, &pdm)); }
31061436d7faSJed Brown     // Do not auto-distribute again
31079566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
31081436d7faSJed Brown   }
3109b7f5c055SJed Brown 
31109566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3111b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3112b7f5c055SJed Brown     PetscInt     m;
3113b7f5c055SJed Brown     DM           dmf;
3114b7f5c055SJed Brown     Vec          X;
3115b7f5c055SJed Brown     PetscScalar *x;
31169566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
3117*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3118b7f5c055SJed Brown 
31199566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
31209566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
31219566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
31229371c9d4SSatish Balay     for (PetscInt i = 0; i < m; i += 3) { PetscCall(TPSNearestPoint(evalFunc, &x[i])); }
31239566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3124b7f5c055SJed Brown   }
3125b7f5c055SJed Brown 
3126b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
31279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
31289566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3129b7f5c055SJed Brown 
3130b7f5c055SJed Brown   if (thickness > 0) {
31314663dae6SJed Brown     DM              edm, cdm, ecdm;
31324663dae6SJed Brown     DMPlexTransform tr;
31334663dae6SJed Brown     const char     *prefix;
31344663dae6SJed Brown     PetscOptions    options;
31354663dae6SJed Brown     // Code from DMPlexExtrude
31364663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
31374663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
31384663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
31394663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
31404663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
31414663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
31424663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
31434663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
31444663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
31454663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
31464663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
31474663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
31484663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
31494663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
31504663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
31514663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
31524663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
31534663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
31544663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
31554663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
31564663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
31574663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
31584663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
31594663dae6SJed Brown     if (edm) {
31604663dae6SJed Brown       ((DM_Plex *)edm->data)->printFEM    = ((DM_Plex *)dm->data)->printFEM;
31614663dae6SJed Brown       ((DM_Plex *)edm->data)->printL2     = ((DM_Plex *)dm->data)->printL2;
3162f5867de0SMatthew G. Knepley       ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate;
31634663dae6SJed Brown     }
3164*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3165b7f5c055SJed Brown   }
3166b7f5c055SJed Brown   PetscFunctionReturn(0);
3167b7f5c055SJed Brown }
3168b7f5c055SJed Brown 
3169b7f5c055SJed Brown /*@
3170b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3171b7f5c055SJed Brown 
3172b7f5c055SJed Brown   Collective
3173b7f5c055SJed Brown 
3174b7f5c055SJed Brown   Input Parameters:
3175b7f5c055SJed Brown + comm   - The communicator for the DM object
3176b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
3177b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
3178b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
31791436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3180817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
31811436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
3182817da375SSatish Balay - thickness - Thickness in normal direction
3183b7f5c055SJed Brown 
3184b7f5c055SJed Brown   Output Parameter:
3185b7f5c055SJed Brown . dm  - The DM object
3186b7f5c055SJed Brown 
3187b7f5c055SJed Brown   Notes:
3188b7f5c055SJed 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.
3189b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
3190b7f5c055SJed 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.
3191b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3192b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3193b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3194b7f5c055SJed Brown 
3195b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
3196b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
3197b7f5c055SJed Brown 
3198b7f5c055SJed Brown   References:
3199606c0280SSatish 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
3200b7f5c055SJed Brown 
3201b7f5c055SJed Brown   Developer Notes:
3202b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3203b7f5c055SJed Brown 
3204b7f5c055SJed Brown   Level: beginner
3205b7f5c055SJed Brown 
3206db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3207b7f5c055SJed Brown @*/
32089371c9d4SSatish Balay PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm) {
3209b7f5c055SJed Brown   PetscFunctionBegin;
32109566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32119566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32129566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
3213b7f5c055SJed Brown   PetscFunctionReturn(0);
3214b7f5c055SJed Brown }
3215b7f5c055SJed Brown 
32169318fe57SMatthew G. Knepley /*@
32179318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
32189318fe57SMatthew G. Knepley 
32199318fe57SMatthew G. Knepley   Collective
32209318fe57SMatthew G. Knepley 
32219318fe57SMatthew G. Knepley   Input Parameters:
32229318fe57SMatthew G. Knepley + comm    - The communicator for the DM object
32239318fe57SMatthew G. Knepley . dim     - The dimension
32249318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
32259318fe57SMatthew G. Knepley - R       - The radius
32269318fe57SMatthew G. Knepley 
32279318fe57SMatthew G. Knepley   Output Parameter:
32289318fe57SMatthew G. Knepley . dm  - The DM object
32299318fe57SMatthew G. Knepley 
32309318fe57SMatthew G. Knepley   Level: beginner
32319318fe57SMatthew G. Knepley 
3232db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
32339318fe57SMatthew G. Knepley @*/
32349371c9d4SSatish Balay PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) {
32359318fe57SMatthew G. Knepley   PetscFunctionBegin;
32369318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
32379566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32389566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32399566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
32409318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
32419318fe57SMatthew G. Knepley }
32429318fe57SMatthew G. Knepley 
32439371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) {
32449318fe57SMatthew G. Knepley   DM      sdm, vol;
32459318fe57SMatthew G. Knepley   DMLabel bdlabel;
32469318fe57SMatthew G. Knepley 
32479318fe57SMatthew G. Knepley   PetscFunctionBegin;
32489566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
32499566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
32509566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_"));
32519566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
32529566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
32539566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
32549566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
32559566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
3256*69d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
32579566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
32589566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
32599566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
32609566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
326151a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
326251a74b61SMatthew G. Knepley }
326351a74b61SMatthew G. Knepley 
326451a74b61SMatthew G. Knepley /*@
326551a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
326651a74b61SMatthew G. Knepley 
326751a74b61SMatthew G. Knepley   Collective
326851a74b61SMatthew G. Knepley 
326951a74b61SMatthew G. Knepley   Input Parameters:
327051a74b61SMatthew G. Knepley + comm  - The communicator for the DM object
327151a74b61SMatthew G. Knepley . dim   - The dimension
327251a74b61SMatthew G. Knepley - R     - The radius
327351a74b61SMatthew G. Knepley 
327451a74b61SMatthew G. Knepley   Output Parameter:
327551a74b61SMatthew G. Knepley . dm  - The DM object
327651a74b61SMatthew G. Knepley 
327751a74b61SMatthew G. Knepley   Options Database Keys:
327851a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
327951a74b61SMatthew G. Knepley 
328051a74b61SMatthew G. Knepley   Level: beginner
328151a74b61SMatthew G. Knepley 
3282db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
328351a74b61SMatthew G. Knepley @*/
32849371c9d4SSatish Balay PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) {
328551a74b61SMatthew G. Knepley   PetscFunctionBegin;
32869566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32879566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32889566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
32892829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
32902829fed8SMatthew G. Knepley }
32912829fed8SMatthew G. Knepley 
32929371c9d4SSatish Balay static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) {
32930a6ba040SMatthew G. Knepley   PetscFunctionBegin;
32949318fe57SMatthew G. Knepley   switch (ct) {
32959371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
32969318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
32979318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
32989318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
32999318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
33009318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
33019318fe57SMatthew G. Knepley 
33029566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
33039566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33049371c9d4SSatish Balay   } break;
33059371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
33069318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
33079318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
33089318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
33099318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
33109318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
33119318fe57SMatthew G. Knepley 
33129566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33139566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33149371c9d4SSatish Balay   } break;
33159371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3316b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3317b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3318b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3319b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3320b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3321b5a892a1SMatthew G. Knepley 
33229566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33239566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33249371c9d4SSatish Balay   } break;
33259371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
33269318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
33279318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
33289318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
33299318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
33309318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
33319318fe57SMatthew G. Knepley 
33329566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33339566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33349371c9d4SSatish Balay   } break;
33359371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
33369318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33379318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
33389318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
33399318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
33409318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
33419318fe57SMatthew G. Knepley 
33429566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33439566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33449371c9d4SSatish Balay   } break;
33459371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
33469318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33479318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
33489318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
33499318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
33509318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
33519318fe57SMatthew G. Knepley 
33529566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33539566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33549371c9d4SSatish Balay   } break;
33559371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
33569318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33579318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3358f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
33599318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3360f0edb160SMatthew 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};
33619318fe57SMatthew G. Knepley 
33629566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
33639566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33649371c9d4SSatish Balay   } break;
33659371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
33669318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
33679318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3368f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
33699318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
33709371c9d4SSatish 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};
33719318fe57SMatthew G. Knepley 
33729566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
33739566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33749371c9d4SSatish Balay   } break;
33759371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
33769318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
33779318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3378f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
33799318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
33809371c9d4SSatish 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};
33819318fe57SMatthew G. Knepley 
33829566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
33839566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33849371c9d4SSatish Balay   } break;
33859371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
33869318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
33879318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
33889318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
33899318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
33909371c9d4SSatish 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};
33919318fe57SMatthew G. Knepley 
33929566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
33939566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33949371c9d4SSatish Balay   } break;
33959371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
33969318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
33979318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
33989318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
33999318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34009371c9d4SSatish 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};
34019318fe57SMatthew G. Knepley 
34029566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34039566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34049371c9d4SSatish Balay   } break;
34059371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
34069318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
34079318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3408f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
34099318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34109371c9d4SSatish 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};
34119318fe57SMatthew G. Knepley 
34129566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34139566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34149371c9d4SSatish Balay   } break;
341598921bdaSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
34169318fe57SMatthew G. Knepley   }
34179318fe57SMatthew G. Knepley   {
34189318fe57SMatthew G. Knepley     PetscInt Nv, v;
34199318fe57SMatthew G. Knepley 
34209318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
34219566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
34229566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
34239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
34249566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
34259318fe57SMatthew G. Knepley   }
34269566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
34279566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
34280a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
34290a6ba040SMatthew G. Knepley }
34300a6ba040SMatthew G. Knepley 
34319318fe57SMatthew G. Knepley /*@
34329318fe57SMatthew G. Knepley   DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell
34339318fe57SMatthew G. Knepley 
34349318fe57SMatthew G. Knepley   Collective
34359318fe57SMatthew G. Knepley 
34369318fe57SMatthew G. Knepley   Input Parameters:
34379318fe57SMatthew G. Knepley + comm - The communicator
34389318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
34399318fe57SMatthew G. Knepley 
34409318fe57SMatthew G. Knepley   Output Parameter:
34419318fe57SMatthew G. Knepley . refdm - The reference cell
34429318fe57SMatthew G. Knepley 
34439318fe57SMatthew G. Knepley   Level: intermediate
34449318fe57SMatthew G. Knepley 
3445db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()`
34469318fe57SMatthew G. Knepley @*/
34479371c9d4SSatish Balay PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) {
34480a6ba040SMatthew G. Knepley   PetscFunctionBegin;
34499566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
34509566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
34519566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
34529318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
34539318fe57SMatthew G. Knepley }
345479a015ccSMatthew G. Knepley 
34559371c9d4SSatish Balay static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) {
34569318fe57SMatthew G. Knepley   DM        plex;
34579318fe57SMatthew G. Knepley   DMLabel   label;
34589318fe57SMatthew G. Knepley   PetscBool hasLabel;
34590a6ba040SMatthew G. Knepley 
3460c22d3578SMatthew G. Knepley   PetscFunctionBegin;
34619566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
34629318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
34639566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
34649566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
34659566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
34669566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
34671c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
34689566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
34699318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
34709318fe57SMatthew G. Knepley }
3471acdc6f61SToby Isaac 
347205bd46c0SStefano Zampini const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
34739318fe57SMatthew G. Knepley 
34749371c9d4SSatish Balay static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) {
34759318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
34769318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
34779318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
34789318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3479cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
34809318fe57SMatthew G. Knepley   MPI_Comm       comm;
3481ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3482ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3483ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
34849318fe57SMatthew G. Knepley 
34859318fe57SMatthew G. Knepley   PetscFunctionBegin;
34869566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
34879318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
34889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
34899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
34909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
34919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
34929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
34939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
34949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
349563a3b9bcSJacob Faibussowitsch   PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim);
34969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
34979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
34989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
34999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
35009566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
35019318fe57SMatthew G. Knepley 
350261a622f3SMatthew G. Knepley   switch (cell) {
350361a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
350461a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
350561a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
350661a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
350761a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
350861a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
35099371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: *useCoordSpace = PETSC_TRUE; break;
351061a622f3SMatthew G. Knepley   default: *useCoordSpace = PETSC_FALSE; break;
351161a622f3SMatthew G. Knepley   }
351261a622f3SMatthew G. Knepley 
35139318fe57SMatthew G. Knepley   if (fflg) {
35149318fe57SMatthew G. Knepley     DM dmnew;
35159318fe57SMatthew G. Knepley 
35169566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew));
35175de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
3518*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
35199318fe57SMatthew G. Knepley   } else if (refDomain) {
35209566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
35219318fe57SMatthew G. Knepley   } else if (bdfflg) {
35229318fe57SMatthew G. Knepley     DM bdm, dmnew;
35239318fe57SMatthew G. Knepley 
35249566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm));
35259566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
35269566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
35279566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
35289566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
35295de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
3530*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
35319318fe57SMatthew G. Knepley   } else {
35329566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
35339318fe57SMatthew G. Knepley     switch (shape) {
35349371c9d4SSatish Balay     case DM_SHAPE_BOX: {
35359318fe57SMatthew G. Knepley       PetscInt       faces[3] = {0, 0, 0};
35369318fe57SMatthew G. Knepley       PetscReal      lower[3] = {0, 0, 0};
35379318fe57SMatthew G. Knepley       PetscReal      upper[3] = {1, 1, 1};
35389318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]   = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
35399318fe57SMatthew G. Knepley       PetscInt       i, n;
35409318fe57SMatthew G. Knepley 
35419318fe57SMatthew G. Knepley       n = dim;
35429318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
35439566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
35449318fe57SMatthew G. Knepley       n = 3;
35459566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
354663a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
35479318fe57SMatthew G. Knepley       n = 3;
35489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
354963a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
35509318fe57SMatthew G. Knepley       n = 3;
35519566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
355263a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
35539318fe57SMatthew G. Knepley       switch (cell) {
355461a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
35559566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3556d410b0cfSMatthew G. Knepley         if (!interpolate) {
3557d410b0cfSMatthew G. Knepley           DM udm;
3558d410b0cfSMatthew G. Knepley 
35599566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
3560*69d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
3561d410b0cfSMatthew G. Knepley         }
35629318fe57SMatthew G. Knepley         break;
35639371c9d4SSatish Balay       default: PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate)); break;
35649318fe57SMatthew G. Knepley       }
35659371c9d4SSatish Balay     } break;
35669371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
35679318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
35689318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
35699318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
35709318fe57SMatthew G. Knepley       PetscInt  i, n;
35719318fe57SMatthew G. Knepley 
35729318fe57SMatthew G. Knepley       n = dim + 1;
35739318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
35749566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
35759318fe57SMatthew G. Knepley       n = 3;
35769566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
357763a3b9bcSJacob 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);
35789318fe57SMatthew G. Knepley       n = 3;
35799566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
358063a3b9bcSJacob 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);
35819566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
35829371c9d4SSatish Balay     } break;
35839371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
35849318fe57SMatthew G. Knepley       PetscReal R = 1.0;
35859318fe57SMatthew G. Knepley 
35869566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
35879566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
35889371c9d4SSatish Balay     } break;
35899371c9d4SSatish Balay     case DM_SHAPE_BALL: {
35909318fe57SMatthew G. Knepley       PetscReal R = 1.0;
35919318fe57SMatthew G. Knepley 
35929566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
35939566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
35949371c9d4SSatish Balay     } break;
35959371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
35969318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
35979318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
35989318fe57SMatthew G. Knepley 
35999566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
36009566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
36019318fe57SMatthew G. Knepley       switch (cell) {
36029371c9d4SSatish Balay       case DM_POLYTOPE_TRI_PRISM_TENSOR: PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); break;
36039371c9d4SSatish Balay       default: PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt)); break;
36049318fe57SMatthew G. Knepley       }
36059371c9d4SSatish Balay     } break;
3606b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
36079371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
3608b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
3609b7f5c055SJed Brown       PetscReal      thickness   = 0.;
3610b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3611b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
36121436d7faSJed Brown       PetscBool      tps_distribute;
36139566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
36149566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
36159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
36169566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
36179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
36189566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
36199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
36209566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
36219371c9d4SSatish Balay     } break;
36229371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
362305bd46c0SStefano Zampini       DM        dmnew;
362405bd46c0SStefano Zampini       PetscReal rl = 0.0;
362505bd46c0SStefano Zampini 
362605bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
362705bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
36285de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
3629*69d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36309371c9d4SSatish Balay     } break;
363198921bdaSJacob Faibussowitsch     default: SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
36329318fe57SMatthew G. Knepley     }
36339318fe57SMatthew G. Knepley   }
36349566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
36359371c9d4SSatish Balay   if (!((PetscObject)dm)->name && nameflg) { PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); }
36360a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
36370a6ba040SMatthew G. Knepley }
36380a6ba040SMatthew G. Knepley 
36399371c9d4SSatish Balay PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) {
36400a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
36417f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
36429318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
36430a6ba040SMatthew G. Knepley 
36440a6ba040SMatthew G. Knepley   PetscFunctionBegin;
36450a6ba040SMatthew G. Knepley   /* Handle viewing */
36469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
36479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
36489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
36499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
3650f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
36519566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
36529566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
36539318fe57SMatthew G. Knepley   /* Labeling */
36549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
36559566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3656953fc75cSMatthew G. Knepley   /* Point Location */
36579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
36580848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
36599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
36602e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
36619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3662b29cfa1cSToby Isaac   /* Projection behavior */
36639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
36649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3665f12cf164SMatthew G. Knepley   /* Checking structure */
3666f12cf164SMatthew G. Knepley   {
36677f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
3668f12cf164SMatthew G. Knepley 
36697f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
36707f9d8d6cSVaclav Hapla     if (all) {
36717f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
36727f9d8d6cSVaclav Hapla     } else {
36739566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
36747f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
36759566063dSJacob 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));
36767f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
36779566063dSJacob 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));
36787f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
36799566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
36807f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
36819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
36827f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL));
36839566063dSJacob 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));
36847f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
36857f9d8d6cSVaclav Hapla     }
36869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
36879566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3688f12cf164SMatthew G. Knepley   }
36899318fe57SMatthew G. Knepley   {
36909318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
36914f3833eaSMatthew G. Knepley 
36929566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
36939318fe57SMatthew G. Knepley     if (flg) {
36949318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
36959318fe57SMatthew G. Knepley 
36969566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
36979566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
36989566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
36999566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
37009318fe57SMatthew G. Knepley     }
37019318fe57SMatthew G. Knepley   }
37029566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
370368d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
370468d4fef7SMatthew G. Knepley }
370568d4fef7SMatthew G. Knepley 
37069371c9d4SSatish Balay PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) {
3707c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
3708c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
3709c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
3710c506a872SMatthew G. Knepley   PetscBool flg;
3711c506a872SMatthew G. Knepley 
3712c506a872SMatthew G. Knepley   PetscFunctionBegin;
3713c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
3714c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
3715c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
3716c506a872SMatthew G. Knepley   if (numOvLabels) {
3717c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
3718c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
3719c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
3720c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
3721c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
3722c506a872SMatthew G. Knepley     }
3723c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
3724c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
3725c506a872SMatthew 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);
3726c506a872SMatthew G. Knepley 
3727c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
3728c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
3729c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
3730c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
3731c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
3732c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
3733c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
3734c506a872SMatthew G. Knepley     }
3735c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
3736c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
3737c506a872SMatthew 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);
3738c506a872SMatthew G. Knepley   }
3739c506a872SMatthew G. Knepley   PetscFunctionReturn(0);
3740c506a872SMatthew G. Knepley }
3741c506a872SMatthew G. Knepley 
37429371c9d4SSatish Balay static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) {
3743bdf63967SMatthew G. Knepley   PetscFunctionList        ordlist;
3744bdf63967SMatthew G. Knepley   char                     oname[256];
3745d410b0cfSMatthew G. Knepley   PetscReal                volume    = -1.0;
37469318fe57SMatthew G. Knepley   PetscInt                 prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3747e600fa54SMatthew 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;
37486bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
374968d4fef7SMatthew G. Knepley 
375068d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3751d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
37529318fe57SMatthew G. Knepley   /* Handle automatic creation */
37539566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
37546bc1bd01Sksagiyam   if (dim < 0) {
37556bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
37566bc1bd01Sksagiyam     created = PETSC_TRUE;
37576bc1bd01Sksagiyam   }
37586bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
3759d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
37609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3761d89e6e46SMatthew G. Knepley   if (flg) {
3762d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3763d89e6e46SMatthew G. Knepley 
37649566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
3765d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3766d89e6e46SMatthew G. Knepley       DM udm;
3767d89e6e46SMatthew G. Knepley 
37689566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
3769*69d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
3770d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3771d89e6e46SMatthew G. Knepley       DM idm;
3772d89e6e46SMatthew G. Knepley 
37739566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
3774*69d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
3775d89e6e46SMatthew G. Knepley     }
3776d89e6e46SMatthew G. Knepley   }
37779b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
37789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3779c1cad2e7SMatthew G. Knepley   if (flg) { ((DM_Plex *)dm->data)->ignoreModel = ignoreModel; }
37809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
37819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
37829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
37839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
37849566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
37859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
37869318fe57SMatthew G. Knepley   if (flg) {
37879566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
37889566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
37899318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
37909318fe57SMatthew G. Knepley   }
37919b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
37929b44eab4SMatthew G. Knepley     DM             rdm;
37939b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
37949b44eab4SMatthew G. Knepley 
3795dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
37969566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
3797*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
3798dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
379961a622f3SMatthew G. Knepley     if (coordFunc && remap) {
38009566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
38019b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
38029b44eab4SMatthew G. Knepley     }
38039b44eab4SMatthew G. Knepley   }
38049566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
38059318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
38069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
38079318fe57SMatthew G. Knepley   if (extLayers) {
38089318fe57SMatthew G. Knepley     DM edm;
38099318fe57SMatthew G. Knepley 
38109566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
3811*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
381248d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
3813dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3814d410b0cfSMatthew G. Knepley     extLayers = 0;
38159318fe57SMatthew G. Knepley   }
3816bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
38176bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
38189566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
38196bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
38209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
38216bc1bd01Sksagiyam   if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) {
3822bdf63967SMatthew G. Knepley     DM pdm;
3823bdf63967SMatthew G. Knepley     IS perm;
3824bdf63967SMatthew G. Knepley 
38259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
38269566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
38279566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
3828*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
3829dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3830bdf63967SMatthew G. Knepley   }
38319b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
38329566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
3833c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
3834dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
38359b44eab4SMatthew G. Knepley   if (distribute) {
38369b44eab4SMatthew G. Knepley     DM               pdm = NULL;
38379b44eab4SMatthew G. Knepley     PetscPartitioner part;
38389b44eab4SMatthew G. Knepley 
38399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
38409566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
38419566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm));
3842*69d8a87bSksagiyam     if (pdm) { PetscCall(DMPlexReplace_Internal(dm, &pdm)); }
38439b44eab4SMatthew G. Knepley   }
38449318fe57SMatthew G. Knepley   /* Create coordinate space */
38459318fe57SMatthew G. Knepley   if (created) {
384661a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
38479318fe57SMatthew G. Knepley     PetscInt  degree = 1;
38486858538eSMatthew G. Knepley     PetscBool flg;
38499318fe57SMatthew G. Knepley 
38509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
38519566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
38529566063dSJacob Faibussowitsch     if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
385361a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
385461a622f3SMatthew G. Knepley       DM           cdm;
385561a622f3SMatthew G. Knepley       PetscDS      cds;
385661a622f3SMatthew G. Knepley       PetscObject  obj;
385761a622f3SMatthew G. Knepley       PetscClassId id;
385861a622f3SMatthew G. Knepley 
38599566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDM(dm, &cdm));
38609566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
38619566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
38629566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
386361a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
386461a622f3SMatthew G. Knepley         PetscContainer dummy;
386561a622f3SMatthew G. Knepley 
38669566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
38679566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
38689566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
38699566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
38709566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
387161a622f3SMatthew G. Knepley       }
387261a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
387361a622f3SMatthew G. Knepley     }
38746858538eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg));
38759566063dSJacob Faibussowitsch     PetscCall(DMLocalizeCoordinates(dm));
38769318fe57SMatthew G. Knepley   }
387768d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
387861a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
38799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
38809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
38819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
38829566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
388368d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
3884acdc6f61SToby Isaac     DM *dms, coarseDM;
388568d4fef7SMatthew G. Knepley 
38869566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
38879566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
38889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
38899566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
389068d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
38919566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
389268d4fef7SMatthew G. Knepley     if (refine == 1) {
38939566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
38949566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
389568d4fef7SMatthew G. Knepley     } else {
38969566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
38979566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
38989566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
38999566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
390068d4fef7SMatthew G. Knepley     }
39019566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
39029566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
390368d4fef7SMatthew G. Knepley     /* Free DMs */
390468d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
3905dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
39069566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
390768d4fef7SMatthew G. Knepley     }
39089566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
390968d4fef7SMatthew G. Knepley   } else {
391068d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
39119318fe57SMatthew G. Knepley       DM             rdm;
391251a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
391368d4fef7SMatthew G. Knepley 
3914dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39159566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
391668d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
3917*69d8a87bSksagiyam       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));
392151a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
392251a74b61SMatthew G. Knepley       }
392368d4fef7SMatthew G. Knepley     }
392468d4fef7SMatthew G. Knepley   }
39253cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
39269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
39279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
3928b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
3929b653a561SMatthew G. Knepley     DM *dms;
3930b653a561SMatthew G. Knepley 
39319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
39329566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
3933b653a561SMatthew G. Knepley     /* Free DMs */
3934b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
3935dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
39369566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
3937b653a561SMatthew G. Knepley     }
39389566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
3939b653a561SMatthew G. Knepley   } else {
3940b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
39419318fe57SMatthew G. Knepley       DM             cdm;
39429318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
39433cf6fe12SMatthew G. Knepley 
3944dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39459566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
39463cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
3947*69d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
3948dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39499318fe57SMatthew G. Knepley       if (coordFunc) {
39509566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
39519318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
39529318fe57SMatthew G. Knepley       }
39533cf6fe12SMatthew G. Knepley     }
3954b653a561SMatthew G. Knepley   }
3955909dfd52SMatthew G. Knepley   /* Handle ghost cells */
39569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
3957909dfd52SMatthew G. Knepley   if (ghostCells) {
3958909dfd52SMatthew G. Knepley     DM   gdm;
3959909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
3960909dfd52SMatthew G. Knepley 
3961909dfd52SMatthew G. Knepley     lname[0] = '\0';
39629566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
39639566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
3964*69d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
3965909dfd52SMatthew G. Knepley   }
39666913077dSMatthew G. Knepley   /* Handle 1D order */
39676bc1bd01Sksagiyam   if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) {
39686913077dSMatthew G. Knepley     DM           cdm, rdm;
39696913077dSMatthew G. Knepley     PetscDS      cds;
39706913077dSMatthew G. Knepley     PetscObject  obj;
39716913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
39726913077dSMatthew G. Knepley     IS           perm;
39736bc1bd01Sksagiyam     PetscInt     Nf;
39746913077dSMatthew G. Knepley     PetscBool    distributed;
39756913077dSMatthew G. Knepley 
39769566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
39779566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
39789566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
39799566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
39806913077dSMatthew G. Knepley     if (Nf) {
39819566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
39829566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
39836913077dSMatthew G. Knepley     }
39846bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
39859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
39869566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
3987*69d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
39889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
39896913077dSMatthew G. Knepley     }
39906913077dSMatthew G. Knepley   }
39913cf6fe12SMatthew G. Knepley   /* Handle */
3992dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3993d0609cedSBarry Smith   PetscOptionsHeadEnd();
39940a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
39950a6ba040SMatthew G. Knepley }
39960a6ba040SMatthew G. Knepley 
39979371c9d4SSatish Balay static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) {
3998552f7358SJed Brown   PetscFunctionBegin;
39999566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
40009566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
40019566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
40029566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
40039566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
40049566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
4005552f7358SJed Brown   PetscFunctionReturn(0);
4006552f7358SJed Brown }
4007552f7358SJed Brown 
40089371c9d4SSatish Balay static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) {
4009552f7358SJed Brown   PetscFunctionBegin;
40109566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
40119566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
40129566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
4013552f7358SJed Brown   PetscFunctionReturn(0);
4014552f7358SJed Brown }
4015552f7358SJed Brown 
40169371c9d4SSatish Balay static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) {
4017793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4018793f3fe5SMatthew G. Knepley 
4019793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
40209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4021793f3fe5SMatthew G. Knepley   if (depth == 1) {
40229566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
40239566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
40249566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
40259371c9d4SSatish Balay     else {
40269371c9d4SSatish Balay       *pStart = 0;
40279371c9d4SSatish Balay       *pEnd   = 0;
40289371c9d4SSatish Balay     }
4029793f3fe5SMatthew G. Knepley   } else {
40309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4031793f3fe5SMatthew G. Knepley   }
4032793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
4033793f3fe5SMatthew G. Knepley }
4034793f3fe5SMatthew G. Knepley 
40359371c9d4SSatish Balay static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) {
4036502a2867SDave May   PetscSF            sf;
40370a19bb7dSprj-   PetscInt           niranks, njranks, n;
40380a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
40390a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4040502a2867SDave May 
40412f356facSMatthew G. Knepley   PetscFunctionBegin;
40429566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
40430a19bb7dSprj-   if (!data->neighbors) {
40449566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
40459566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
40469566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
40479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
40489566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
40499566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
40500a19bb7dSprj-     n = njranks + niranks;
40519566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
40520a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
40539566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
40540a19bb7dSprj-   }
40550a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
40560a19bb7dSprj-   if (ranks) {
40570a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
40580a19bb7dSprj-     else *ranks = NULL;
40590a19bb7dSprj-   }
4060502a2867SDave May   PetscFunctionReturn(0);
4061502a2867SDave May }
4062502a2867SDave May 
40631eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
40641eb70e55SToby Isaac 
40659371c9d4SSatish Balay static PetscErrorCode DMInitialize_Plex(DM dm) {
4066552f7358SJed Brown   PetscFunctionBegin;
4067552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
40682c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
4069552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
407038221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
4071552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
40721bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
407366ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
4074552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
4075552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
4076184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
40770298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
4078552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
4079f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
40800a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
4081552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
4082bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
4083bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
4084b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
40855a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
4086552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
40870a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
40880a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
4089b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
4090d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
40910298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
40920298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
40930298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
40940298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
4095552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
4096552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
40972adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
4098793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
4099552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
41000709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
41010709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
4102bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
41038c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
4104ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
41050709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
4106b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
41072a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
410828d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
41099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
41109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
41119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
41129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
41139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
41149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
41159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
41166bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
41176bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
41189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
4119c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
4120c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
4121552f7358SJed Brown   PetscFunctionReturn(0);
4122552f7358SJed Brown }
4123552f7358SJed Brown 
41249371c9d4SSatish Balay PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) {
412563a16f15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
412663a16f15SMatthew G. Knepley 
412763a16f15SMatthew G. Knepley   PetscFunctionBegin;
412863a16f15SMatthew G. Knepley   mesh->refct++;
412963a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
41309566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
41319566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
413263a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
413363a16f15SMatthew G. Knepley }
413463a16f15SMatthew G. Knepley 
41358818961aSMatthew G Knepley /*MC
41368818961aSMatthew G Knepley   DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
41378818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
41388818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
41398818961aSMatthew G Knepley                     ownership of the underlying DMPlex points. This is specified by another PetscSection object.
41408818961aSMatthew G Knepley 
4141e5893cccSMatthew G. Knepley   Options Database Keys:
4142250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
4143250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
4144250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
4145250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
4146250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
4147250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
4148250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
4149ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
4150f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
4151f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
4152f12cf164SMatthew G. Knepley . -dm_plex_max_projection_height     - Maxmimum mesh point height used to project locally
4153f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
4154250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
4155f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
4156f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
4157f12cf164SMatthew 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
4158f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
4159f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
4160e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
4161e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
4162e5893cccSMatthew G. Knepley 
41638818961aSMatthew G Knepley   Level: intermediate
41648818961aSMatthew G Knepley 
4165db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`
41668818961aSMatthew G Knepley M*/
41678818961aSMatthew G Knepley 
41689371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) {
4169552f7358SJed Brown   DM_Plex *mesh;
4170412e9a14SMatthew G. Knepley   PetscInt unit;
4171552f7358SJed Brown 
4172552f7358SJed Brown   PetscFunctionBegin;
4173552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41749566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(dm, &mesh));
4175552f7358SJed Brown   dm->data = mesh;
4176552f7358SJed Brown 
4177552f7358SJed Brown   mesh->refct = 1;
41789566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
41799566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
4180552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
4181552f7358SJed Brown   mesh->refinementLimit        = -1.0;
4182e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
41836bc1bd01Sksagiyam   mesh->reorderDefault         = DMPLEX_REORDER_DEFAULT_NOTSET;
41847d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
41857d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
4186552f7358SJed Brown 
41879566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
41882e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
4189d9deefdfSMatthew G. Knepley 
41908865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
4191552f7358SJed Brown 
4192df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
4193ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
41946113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
4195552f7358SJed Brown 
41969566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
4197552f7358SJed Brown   PetscFunctionReturn(0);
4198552f7358SJed Brown }
4199552f7358SJed Brown 
4200552f7358SJed Brown /*@
4201552f7358SJed Brown   DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
4202552f7358SJed Brown 
4203d083f849SBarry Smith   Collective
4204552f7358SJed Brown 
4205552f7358SJed Brown   Input Parameter:
4206552f7358SJed Brown . comm - The communicator for the DMPlex object
4207552f7358SJed Brown 
4208552f7358SJed Brown   Output Parameter:
4209552f7358SJed Brown . mesh  - The DMPlex object
4210552f7358SJed Brown 
4211552f7358SJed Brown   Level: beginner
4212552f7358SJed Brown 
4213552f7358SJed Brown @*/
42149371c9d4SSatish Balay PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) {
4215552f7358SJed Brown   PetscFunctionBegin;
4216552f7358SJed Brown   PetscValidPointer(mesh, 2);
42179566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
42189566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
4219552f7358SJed Brown   PetscFunctionReturn(0);
4220552f7358SJed Brown }
4221552f7358SJed Brown 
4222b09969d6SVaclav Hapla /*@C
4223b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output)
4224b09969d6SVaclav Hapla 
4225b09969d6SVaclav Hapla   Input Parameters:
4226b09969d6SVaclav Hapla + dm - The DM
4227b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4228325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE
4229325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE
4230b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
42315e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4232b09969d6SVaclav Hapla 
4233be8c289dSNicolas Barral   Output Parameters:
4234be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership
4235be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4236b09969d6SVaclav Hapla 
4237b09969d6SVaclav Hapla   Notes:
4238b09969d6SVaclav Hapla   Two triangles sharing a face
4239b09969d6SVaclav Hapla $
4240b09969d6SVaclav Hapla $        2
4241b09969d6SVaclav Hapla $      / | \
4242b09969d6SVaclav Hapla $     /  |  \
4243b09969d6SVaclav Hapla $    /   |   \
4244b09969d6SVaclav Hapla $   0  0 | 1  3
4245b09969d6SVaclav Hapla $    \   |   /
4246b09969d6SVaclav Hapla $     \  |  /
4247b09969d6SVaclav Hapla $      \ | /
4248b09969d6SVaclav Hapla $        1
4249b09969d6SVaclav Hapla would have input
4250b09969d6SVaclav Hapla $  numCells = 2, numVertices = 4
4251b09969d6SVaclav Hapla $  cells = [0 1 2  1 3 2]
4252b09969d6SVaclav Hapla $
4253b09969d6SVaclav Hapla which would result in the DMPlex
4254b09969d6SVaclav Hapla $
4255b09969d6SVaclav Hapla $        4
4256b09969d6SVaclav Hapla $      / | \
4257b09969d6SVaclav Hapla $     /  |  \
4258b09969d6SVaclav Hapla $    /   |   \
4259b09969d6SVaclav Hapla $   2  0 | 1  5
4260b09969d6SVaclav Hapla $    \   |   /
4261b09969d6SVaclav Hapla $     \  |  /
4262b09969d6SVaclav Hapla $      \ | /
4263b09969d6SVaclav Hapla $        3
4264b09969d6SVaclav Hapla 
426525b6865aSVaclav Hapla   Vertices are implicitly numbered consecutively 0,...,NVertices.
426625b6865aSVaclav Hapla   Each rank owns a chunk of numVertices consecutive vertices.
426725b6865aSVaclav Hapla   If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout.
4268325d53feSBarry Smith   If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
4269325d53feSBarry Smith   If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks.
427025b6865aSVaclav Hapla 
4271b09969d6SVaclav Hapla   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
4272b09969d6SVaclav Hapla 
4273b09969d6SVaclav Hapla   Not currently supported in Fortran.
4274b09969d6SVaclav Hapla 
4275b09969d6SVaclav Hapla   Level: advanced
4276b09969d6SVaclav Hapla 
4277db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`
4278b09969d6SVaclav Hapla @*/
42799371c9d4SSatish Balay PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) {
42802464107aSksagiyam   PetscSF     sfPoint;
42812464107aSksagiyam   PetscLayout layout;
428282fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
4283a47d0d45SMatthew G. Knepley 
4284a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
428525b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
42869566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
428725b6865aSVaclav Hapla   /* Get/check global number of vertices */
428825b6865aSVaclav Hapla   {
428925b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
429025b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
429125b6865aSVaclav Hapla 
429225b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
429325b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
42949371c9d4SSatish Balay     for (i = 0; i < len; i++)
42959371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
429625b6865aSVaclav Hapla     ++NVerticesInCells;
42979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
429825b6865aSVaclav Hapla 
429925b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
43009371c9d4SSatish Balay     else
43019371c9d4SSatish 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);
430225b6865aSVaclav Hapla   }
43039079aca8SVaclav Hapla   /* Count locally unique vertices */
43049079aca8SVaclav Hapla   {
43059079aca8SVaclav Hapla     PetscHSetI vhash;
43069079aca8SVaclav Hapla     PetscInt   off = 0;
43079079aca8SVaclav Hapla 
43089566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
4309a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
43109371c9d4SSatish Balay       for (p = 0; p < numCorners; ++p) { PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); }
4311a47d0d45SMatthew G. Knepley     }
43129566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
43139566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
4314be8c289dSNicolas Barral     else { verticesAdj = *verticesAdjSaved; }
43159566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
43169566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
431763a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
4318a47d0d45SMatthew G. Knepley   }
43199566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
4320a47d0d45SMatthew G. Knepley   /* Create cones */
43219566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
43229566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
43239566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
43249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4325a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
4326a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
4327a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
4328a47d0d45SMatthew G. Knepley       PetscInt       lv;
4329a47d0d45SMatthew G. Knepley 
43309079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
43319079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
43329566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
433363a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
4334961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
4335a47d0d45SMatthew G. Knepley     }
4336a47d0d45SMatthew G. Knepley   }
43372464107aSksagiyam   /* Build point sf */
43389566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
43399566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
43409566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
43419566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
43429566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
43439566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
43449566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
43459566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
43462464107aSksagiyam   if (dm->sf) {
43472464107aSksagiyam     const char *prefix;
43482464107aSksagiyam 
43499566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
43509566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
43512464107aSksagiyam   }
43529566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
43539566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
43549566063dSJacob Faibussowitsch   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4355a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
43569566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
43579566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
43589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4359a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4360a47d0d45SMatthew G. Knepley }
4361a47d0d45SMatthew G. Knepley 
4362b09969d6SVaclav Hapla /*@C
4363b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4364b09969d6SVaclav Hapla 
4365b09969d6SVaclav Hapla   Input Parameters:
4366b09969d6SVaclav Hapla + dm - The DM
4367b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4368b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership
4369b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4370b09969d6SVaclav Hapla 
4371b09969d6SVaclav Hapla   Level: advanced
4372b09969d6SVaclav Hapla 
4373b09969d6SVaclav Hapla   Notes:
4374b09969d6SVaclav Hapla   Not currently supported in Fortran.
4375b09969d6SVaclav Hapla 
4376db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
4377b09969d6SVaclav Hapla @*/
43789371c9d4SSatish Balay PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) {
4379a47d0d45SMatthew G. Knepley   PetscSection coordSection;
4380a47d0d45SMatthew G. Knepley   Vec          coordinates;
4381a47d0d45SMatthew G. Knepley   PetscScalar *coords;
43821edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4383a47d0d45SMatthew G. Knepley 
4384a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
43859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
43869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
43871dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
43889566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
43899566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
43901dca8a05SBarry 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);
43919566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
43929566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
43939566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
43949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
43951edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
43969566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
43979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4398a47d0d45SMatthew G. Knepley   }
43999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
44009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
44019566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
44029566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
44039566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
44049566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
44059566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
44069566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4407a47d0d45SMatthew G. Knepley   {
4408a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4409a47d0d45SMatthew G. Knepley 
4410a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
44119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
44129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
441321016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
441421016a8bSBarry Smith     {
441521016a8bSBarry Smith       PetscScalar *svertexCoords;
441621016a8bSBarry Smith       PetscInt     i;
44179566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
44183612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
44199566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
44209566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
44219566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
442221016a8bSBarry Smith     }
442321016a8bSBarry Smith #else
44249566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
44259566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
442621016a8bSBarry Smith #endif
44279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
4428a47d0d45SMatthew G. Knepley   }
44299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
44309566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
44319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
44329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4433a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4434a47d0d45SMatthew G. Knepley }
4435a47d0d45SMatthew G. Knepley 
4436c3edce3dSSatish Balay /*@
4437b09969d6SVaclav Hapla   DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output)
4438a47d0d45SMatthew G. Knepley 
4439a47d0d45SMatthew G. Knepley   Input Parameters:
4440a47d0d45SMatthew G. Knepley + comm - The communicator
4441a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4442a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
444325b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE
444425b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE
4445a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4446a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4447a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4448a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4449a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4450a47d0d45SMatthew G. Knepley 
4451d8d19677SJose E. Roman   Output Parameters:
445218d54ad4SMichael Lange + dm - The DM
4453be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership
4454be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4455a47d0d45SMatthew G. Knepley 
4456b09969d6SVaclav Hapla   Notes:
4457b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(),
4458b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel()
4459a47d0d45SMatthew G. Knepley 
446025b6865aSVaclav Hapla   See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters.
446125b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters.
446225b6865aSVaclav Hapla 
4463b09969d6SVaclav Hapla   Level: intermediate
4464a47d0d45SMatthew G. Knepley 
4465db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
4466a47d0d45SMatthew G. Knepley @*/
44679371c9d4SSatish Balay 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) {
4468a47d0d45SMatthew G. Knepley   PetscSF sfVert;
4469a47d0d45SMatthew G. Knepley 
4470a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
44719566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44729566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4473a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4474064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
44759566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
44769566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4477a47d0d45SMatthew G. Knepley   if (interpolate) {
44785fd9971aSMatthew G. Knepley     DM idm;
4479a47d0d45SMatthew G. Knepley 
44809566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
44819566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
4482a47d0d45SMatthew G. Knepley     *dm = idm;
4483a47d0d45SMatthew G. Knepley   }
44849566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
448518d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
44869566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
4487a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4488a47d0d45SMatthew G. Knepley }
4489a47d0d45SMatthew G. Knepley 
4490b09969d6SVaclav Hapla /*@C
4491b09969d6SVaclav Hapla   DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output)
44929298eaa6SMatthew G Knepley 
44939298eaa6SMatthew G Knepley   Input Parameters:
4494b09969d6SVaclav Hapla + dm - The DM
4495b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4496325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE
44979298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
44985e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
44999298eaa6SMatthew G Knepley 
4500b09969d6SVaclav Hapla   Level: advanced
45019298eaa6SMatthew G Knepley 
4502b09969d6SVaclav Hapla   Notes:
4503b09969d6SVaclav Hapla   Two triangles sharing a face
45049298eaa6SMatthew G Knepley $
45059298eaa6SMatthew G Knepley $        2
45069298eaa6SMatthew G Knepley $      / | \
45079298eaa6SMatthew G Knepley $     /  |  \
45089298eaa6SMatthew G Knepley $    /   |   \
45099298eaa6SMatthew G Knepley $   0  0 | 1  3
45109298eaa6SMatthew G Knepley $    \   |   /
45119298eaa6SMatthew G Knepley $     \  |  /
45129298eaa6SMatthew G Knepley $      \ | /
45139298eaa6SMatthew G Knepley $        1
45149298eaa6SMatthew G Knepley would have input
45159298eaa6SMatthew G Knepley $  numCells = 2, numVertices = 4
45169298eaa6SMatthew G Knepley $  cells = [0 1 2  1 3 2]
45179298eaa6SMatthew G Knepley $
45189298eaa6SMatthew G Knepley which would result in the DMPlex
45199298eaa6SMatthew G Knepley $
45209298eaa6SMatthew G Knepley $        4
45219298eaa6SMatthew G Knepley $      / | \
45229298eaa6SMatthew G Knepley $     /  |  \
45239298eaa6SMatthew G Knepley $    /   |   \
45249298eaa6SMatthew G Knepley $   2  0 | 1  5
45259298eaa6SMatthew G Knepley $    \   |   /
45269298eaa6SMatthew G Knepley $     \  |  /
45279298eaa6SMatthew G Knepley $      \ | /
45289298eaa6SMatthew G Knepley $        3
45299298eaa6SMatthew G Knepley 
4530325d53feSBarry Smith   If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1.
453125b6865aSVaclav Hapla 
4532b09969d6SVaclav Hapla   Not currently supported in Fortran.
45339298eaa6SMatthew G Knepley 
4534db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
4535b09969d6SVaclav Hapla @*/
45369371c9d4SSatish Balay PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) {
4537961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
4538b09969d6SVaclav Hapla 
4539b09969d6SVaclav Hapla   PetscFunctionBegin;
45409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
45419566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
454225b6865aSVaclav Hapla   /* Get/check global number of vertices */
454325b6865aSVaclav Hapla   {
454425b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
454525b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
454625b6865aSVaclav Hapla 
454725b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
454825b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
45499371c9d4SSatish Balay     for (i = 0; i < len; i++)
45509371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
455125b6865aSVaclav Hapla     ++NVerticesInCells;
455225b6865aSVaclav Hapla 
455325b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
45549371c9d4SSatish Balay     else
45559371c9d4SSatish 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);
455625b6865aSVaclav Hapla   }
45579566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
45589371c9d4SSatish Balay   for (c = 0; c < numCells; ++c) { PetscCall(DMPlexSetConeSize(dm, c, numCorners)); }
45599566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
45609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4561b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
45629371c9d4SSatish Balay     for (p = 0; p < numCorners; ++p) { cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; }
4563b09969d6SVaclav Hapla   }
45649566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
45659566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
45669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4567b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4568b09969d6SVaclav Hapla }
4569b09969d6SVaclav Hapla 
4570b09969d6SVaclav Hapla /*@C
4571b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4572b09969d6SVaclav Hapla 
4573b09969d6SVaclav Hapla   Input Parameters:
4574b09969d6SVaclav Hapla + dm - The DM
4575b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4576b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4577b09969d6SVaclav Hapla 
4578b09969d6SVaclav Hapla   Level: advanced
4579b09969d6SVaclav Hapla 
4580b09969d6SVaclav Hapla   Notes:
4581b09969d6SVaclav Hapla   Not currently supported in Fortran.
4582b09969d6SVaclav Hapla 
4583db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
4584b09969d6SVaclav Hapla @*/
45859371c9d4SSatish Balay PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) {
4586b09969d6SVaclav Hapla   PetscSection coordSection;
4587b09969d6SVaclav Hapla   Vec          coordinates;
4588b09969d6SVaclav Hapla   DM           cdm;
4589b09969d6SVaclav Hapla   PetscScalar *coords;
45901edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
4591b09969d6SVaclav Hapla 
4592b09969d6SVaclav Hapla   PetscFunctionBegin;
45939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
45949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
45951dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
45969566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
45979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
45989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
45999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
46009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
46011edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
46029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
46039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4604b09969d6SVaclav Hapla   }
46059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4606b09969d6SVaclav Hapla 
46079566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
46089566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
46099566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
46109566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
46119566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
46121edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
46139371c9d4SSatish Balay     for (d = 0; d < spaceDim; ++d) { coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; }
4614b09969d6SVaclav Hapla   }
46159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
46169566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
46179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
46189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4619b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4620b09969d6SVaclav Hapla }
4621b09969d6SVaclav Hapla 
4622b09969d6SVaclav Hapla /*@
46233df08285SMatthew 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
46243df08285SMatthew G. Knepley 
46253df08285SMatthew G. Knepley   Collective on comm
4626b09969d6SVaclav Hapla 
4627b09969d6SVaclav Hapla   Input Parameters:
4628b09969d6SVaclav Hapla + comm - The communicator
4629b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
46303df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
46313df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0
46323df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4633b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
46343df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4635b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
46363df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4637b09969d6SVaclav Hapla 
4638b09969d6SVaclav Hapla   Output Parameter:
46393df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0
4640b09969d6SVaclav Hapla 
4641b09969d6SVaclav Hapla   Notes:
4642b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(),
4643b09969d6SVaclav Hapla   DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList()
4644b09969d6SVaclav Hapla 
464525b6865aSVaclav Hapla   See DMPlexBuildFromCellList() for an example and details about the topology-related parameters.
464625b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters.
46473df08285SMatthew G. Knepley   See DMPlexCreateFromCellListParallelPetsc() for parallel input
464825b6865aSVaclav Hapla 
4649b09969d6SVaclav Hapla   Level: intermediate
4650b09969d6SVaclav Hapla 
4651db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
46529298eaa6SMatthew G Knepley @*/
46539371c9d4SSatish Balay 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) {
46543df08285SMatthew G. Knepley   PetscMPIInt rank;
46559298eaa6SMatthew G Knepley 
46569298eaa6SMatthew G Knepley   PetscFunctionBegin;
465728b400f6SJacob 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.");
46589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
46599566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
46609566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
46619566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
4662c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
46639566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
46649298eaa6SMatthew G Knepley   if (interpolate) {
46655fd9971aSMatthew G. Knepley     DM idm;
46669298eaa6SMatthew G Knepley 
46679566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
46689566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
46699298eaa6SMatthew G Knepley     *dm = idm;
46709298eaa6SMatthew G Knepley   }
4671c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
46729566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
46739298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
46749298eaa6SMatthew G Knepley }
46759298eaa6SMatthew G Knepley 
4676939f6067SMatthew G. Knepley /*@
4677939f6067SMatthew 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
4678939f6067SMatthew G. Knepley 
4679939f6067SMatthew G. Knepley   Input Parameters:
4680c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4681939f6067SMatthew G. Knepley . depth - The depth of the DAG
4682367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4683939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4684939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4685939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4686367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4687939f6067SMatthew G. Knepley 
4688939f6067SMatthew G. Knepley   Output Parameter:
4689939f6067SMatthew G. Knepley . dm - The DM
4690939f6067SMatthew G. Knepley 
4691939f6067SMatthew G. Knepley   Note: Two triangles sharing a face would have input
4692939f6067SMatthew G. Knepley $  depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4693939f6067SMatthew G. Knepley $  cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4694939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4695939f6067SMatthew G. Knepley $
4696939f6067SMatthew G. Knepley which would result in the DMPlex
4697939f6067SMatthew G. Knepley $
4698939f6067SMatthew G. Knepley $        4
4699939f6067SMatthew G. Knepley $      / | \
4700939f6067SMatthew G. Knepley $     /  |  \
4701939f6067SMatthew G. Knepley $    /   |   \
4702939f6067SMatthew G. Knepley $   2  0 | 1  5
4703939f6067SMatthew G. Knepley $    \   |   /
4704939f6067SMatthew G. Knepley $     \  |  /
4705939f6067SMatthew G. Knepley $      \ | /
4706939f6067SMatthew G. Knepley $        3
4707939f6067SMatthew G. Knepley $
4708a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc()
4709939f6067SMatthew G. Knepley 
4710939f6067SMatthew G. Knepley   Level: advanced
4711939f6067SMatthew G. Knepley 
4712db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
4713939f6067SMatthew G. Knepley @*/
47149371c9d4SSatish Balay PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) {
47159298eaa6SMatthew G Knepley   Vec          coordinates;
47169298eaa6SMatthew G Knepley   PetscSection coordSection;
47179298eaa6SMatthew G Knepley   PetscScalar *coords;
4718811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
47199298eaa6SMatthew G Knepley 
47209298eaa6SMatthew G Knepley   PetscFunctionBegin;
47219566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
47229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
472363a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
47249298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
47259566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
47269298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
47279566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
47289371c9d4SSatish Balay     if (firstVertex < 0 && !coneSize[p - pStart]) { firstVertex = p - pStart; }
472997e052ccSToby Isaac   }
47301dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
47319566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
47329298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
47339566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
47349566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
47359298eaa6SMatthew G Knepley   }
47369566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
47379566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
47389298eaa6SMatthew G Knepley   /* Build coordinates */
47399566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
47409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
47419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
47429566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
47439298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
47449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
47459566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
47469298eaa6SMatthew G Knepley   }
47479566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
47489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
47499566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
47509566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
47519566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
47529566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
47539566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
47549318fe57SMatthew G. Knepley   if (vertexCoords) {
47559566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
47569298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
47579298eaa6SMatthew G Knepley       PetscInt off;
47589298eaa6SMatthew G Knepley 
47599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
47609371c9d4SSatish Balay       for (d = 0; d < dimEmbed; ++d) { coords[off + d] = vertexCoords[v * dimEmbed + d]; }
47619298eaa6SMatthew G Knepley     }
47629318fe57SMatthew G. Knepley   }
47639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
47649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
47659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
47669298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
47679298eaa6SMatthew G Knepley }
47688415267dSToby Isaac 
4769ca522641SMatthew G. Knepley /*@C
47708ca92349SMatthew G. Knepley   DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file.
47718ca92349SMatthew G. Knepley 
47728ca92349SMatthew G. Knepley + comm        - The MPI communicator
47738ca92349SMatthew G. Knepley . filename    - Name of the .dat file
47748ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
47758ca92349SMatthew G. Knepley 
47768ca92349SMatthew G. Knepley   Output Parameter:
47778ca92349SMatthew G. Knepley . dm  - The DM object representing the mesh
47788ca92349SMatthew G. Knepley 
47798ca92349SMatthew G. Knepley   Note: The format is the simplest possible:
47808ca92349SMatthew G. Knepley $ Ne
47818ca92349SMatthew G. Knepley $ v0 v1 ... vk
47828ca92349SMatthew G. Knepley $ Nv
47838ca92349SMatthew G. Knepley $ x y z marker
47848ca92349SMatthew G. Knepley 
47858ca92349SMatthew G. Knepley   Level: beginner
47868ca92349SMatthew G. Knepley 
4787db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
47888ca92349SMatthew G. Knepley @*/
47899371c9d4SSatish Balay PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) {
47908ca92349SMatthew G. Knepley   DMLabel      marker;
47918ca92349SMatthew G. Knepley   PetscViewer  viewer;
47928ca92349SMatthew G. Knepley   Vec          coordinates;
47938ca92349SMatthew G. Knepley   PetscSection coordSection;
47948ca92349SMatthew G. Knepley   PetscScalar *coords;
47958ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
47968ca92349SMatthew G. Knepley   PetscInt     dim = 3, cdim = 3, coordSize, v, c, d;
47978ca92349SMatthew G. Knepley   PetscMPIInt  rank;
4798f8d5e320SMatthew G. Knepley   int          snum, Nv, Nc, Ncn, Nl;
47998ca92349SMatthew G. Knepley 
48008ca92349SMatthew G. Knepley   PetscFunctionBegin;
48019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
48029566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
48039566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
48049566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
48059566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
4806dd400576SPatrick Sanan   if (rank == 0) {
48079566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4808f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
480908401ef6SPierre Jolivet     PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
481025ce1634SJed Brown   } else {
4811f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
48128ca92349SMatthew G. Knepley   }
48139566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
48149566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
48159566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
48169566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
48179566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
48188ca92349SMatthew G. Knepley   /* Read topology */
4819dd400576SPatrick Sanan   if (rank == 0) {
4820f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
4821f8d5e320SMatthew G. Knepley     PetscInt cone[8];
48228ca92349SMatthew G. Knepley     int      vbuf[8], v;
48238ca92349SMatthew G. Knepley 
48249371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
48259371c9d4SSatish Balay       format[c * 3 + 0] = '%';
48269371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
48279371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
48289371c9d4SSatish Balay     }
4829f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
48309566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
48319566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
48328ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
48339566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
4834f8d5e320SMatthew G. Knepley       switch (Ncn) {
4835f8d5e320SMatthew G. Knepley       case 2: snum = sscanf(line, format, &vbuf[0], &vbuf[1]); break;
4836f8d5e320SMatthew G. Knepley       case 3: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); break;
4837f8d5e320SMatthew G. Knepley       case 4: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); break;
4838f8d5e320SMatthew G. Knepley       case 6: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); break;
4839f8d5e320SMatthew G. Knepley       case 8: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); break;
484063a3b9bcSJacob Faibussowitsch       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
4841f8d5e320SMatthew G. Knepley       }
484208401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4843f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
48448ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
4845f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
48468ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
48478ca92349SMatthew G. Knepley         cone[1]      = cone[3];
48488ca92349SMatthew G. Knepley         cone[3]      = tmp;
48498ca92349SMatthew G. Knepley       }
48509566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
48518ca92349SMatthew G. Knepley     }
48528ca92349SMatthew G. Knepley   }
48539566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
48549566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
48558ca92349SMatthew G. Knepley   /* Read coordinates */
48569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
48579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
48589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
48599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
48608ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
48619566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
48629566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
48638ca92349SMatthew G. Knepley   }
48649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
48659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
48669566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
48679566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
48689566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
48699566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
48709566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
48719566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4872dd400576SPatrick Sanan   if (rank == 0) {
4873f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
48748ca92349SMatthew G. Knepley     double x[3];
4875f8d5e320SMatthew G. Knepley     int    l, val[3];
48768ca92349SMatthew G. Knepley 
4877f8d5e320SMatthew G. Knepley     if (Nl) {
48789371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
48799371c9d4SSatish Balay         format[l * 3 + 0] = '%';
48809371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
48819371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
48829371c9d4SSatish Balay       }
4883f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
48849566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
48859566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
4886f8d5e320SMatthew G. Knepley     }
48878ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
48889566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
4889f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
489008401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4891f8d5e320SMatthew G. Knepley       switch (Nl) {
4892f8d5e320SMatthew G. Knepley       case 0: snum = 0; break;
4893f8d5e320SMatthew G. Knepley       case 1: snum = sscanf(line, format, &val[0]); break;
4894f8d5e320SMatthew G. Knepley       case 2: snum = sscanf(line, format, &val[0], &val[1]); break;
4895f8d5e320SMatthew G. Knepley       case 3: snum = sscanf(line, format, &val[0], &val[1], &val[2]); break;
489663a3b9bcSJacob Faibussowitsch       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
4897f8d5e320SMatthew G. Knepley       }
489808401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
48998ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
49009566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
49018ca92349SMatthew G. Knepley     }
49028ca92349SMatthew G. Knepley   }
49039566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
49049566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
49059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
49069566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
49078ca92349SMatthew G. Knepley   if (interpolate) {
49088ca92349SMatthew G. Knepley     DM      idm;
49098ca92349SMatthew G. Knepley     DMLabel bdlabel;
49108ca92349SMatthew G. Knepley 
49119566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
49129566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
49138ca92349SMatthew G. Knepley     *dm = idm;
49148ca92349SMatthew G. Knepley 
4915f8d5e320SMatthew G. Knepley     if (!Nl) {
49169566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
49179566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
49189566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
49199566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
49208ca92349SMatthew G. Knepley     }
4921f8d5e320SMatthew G. Knepley   }
49228ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
49238ca92349SMatthew G. Knepley }
49248ca92349SMatthew G. Knepley 
49258ca92349SMatthew G. Knepley /*@C
4926ca522641SMatthew G. Knepley   DMPlexCreateFromFile - This takes a filename and produces a DM
4927ca522641SMatthew G. Knepley 
4928ca522641SMatthew G. Knepley   Input Parameters:
4929ca522641SMatthew G. Knepley + comm - The communicator
4930ca522641SMatthew G. Knepley . filename - A file name
4931cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats
4932ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
4933ca522641SMatthew G. Knepley 
4934ca522641SMatthew G. Knepley   Output Parameter:
4935ca522641SMatthew G. Knepley . dm - The DM
4936ca522641SMatthew G. Knepley 
493702ef0d99SVaclav Hapla   Options Database Keys:
493802ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5
493902ef0d99SVaclav Hapla 
4940bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
4941bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
4942bca97951SVaclav Hapla 
4943cd7e8a5eSksagiyam   Notes:
4944cd7e8a5eSksagiyam   Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex
4945cd7e8a5eSksagiyam   meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName()
4946cd7e8a5eSksagiyam   before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object.
4947cd7e8a5eSksagiyam   The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally
4948cd7e8a5eSksagiyam   calls DMLoad(). Currently, name is ignored for other viewer types and/or formats.
4949cd7e8a5eSksagiyam 
4950ca522641SMatthew G. Knepley   Level: beginner
4951ca522641SMatthew G. Knepley 
4952db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
4953ca522641SMatthew G. Knepley @*/
49549371c9d4SSatish Balay PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) {
4955ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
4956ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
4957ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
4958ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
4959ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
4960ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
4961ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
4962ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
4963ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
4964ef3a5affSJacob Faibussowitsch   const char  extMed[]       = ".med";
4965ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
4966ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
4967ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
4968ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
4969ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
4970ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
4971ca522641SMatthew G. Knepley   size_t      len;
4972c1cad2e7SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
4973ca522641SMatthew G. Knepley   PetscMPIInt rank;
4974ca522641SMatthew G. Knepley 
4975ca522641SMatthew G. Knepley   PetscFunctionBegin;
49765d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
49770d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
4978cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
49799566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
49809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
49819566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
49829566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
498328b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
4984ef3a5affSJacob Faibussowitsch 
49859371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
49869371c9d4SSatish Balay   do { \
4987274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
4988274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
4989274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
4990274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
4991ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
4992ef3a5affSJacob Faibussowitsch     } else { \
4993274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
4994ef3a5affSJacob Faibussowitsch     } \
4995ef3a5affSJacob Faibussowitsch   } while (0)
4996ef3a5affSJacob Faibussowitsch 
4997ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
4998ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
4999ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
5000ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
5001ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
5002ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
5003ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
5004ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
5005ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
5006ef3a5affSJacob Faibussowitsch   CheckExtension(extMed, isMed);
5007ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
5008ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
5009ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
5010ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
5011ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
5012ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
5013ef3a5affSJacob Faibussowitsch 
5014ef3a5affSJacob Faibussowitsch #undef CheckExtension
5015ef3a5affSJacob Faibussowitsch 
5016de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
50179566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
5018ca522641SMatthew G. Knepley   } else if (isCGNS) {
50199566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
502090c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
50219566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
50222f0bd6dcSMichael Lange   } else if (isFluent) {
50239566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
5024cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
50259c48423bSVaclav Hapla     PetscBool   load_hdf5_xdmf = PETSC_FALSE;
5026cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
5027cc2f8f65SMatthew G. Knepley 
502843b242b4SVaclav 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 */
50299566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf));
50309566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
50319566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
50329566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
50339566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
50349566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
50359566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
50369566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
5037cd7e8a5eSksagiyam 
50389566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
50399566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
50409566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
50419566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
50429566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
50439566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer));
50449566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
50455fd9971aSMatthew G. Knepley 
50465fd9971aSMatthew G. Knepley     if (interpolate) {
50475fd9971aSMatthew G. Knepley       DM idm;
50485fd9971aSMatthew G. Knepley 
50499566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
50509566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
50515fd9971aSMatthew G. Knepley       *dm = idm;
50525fd9971aSMatthew G. Knepley     }
5053707dd687SMichael Lange   } else if (isMed) {
50549566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
5055f2801cd6SMatthew G. Knepley   } else if (isPLY) {
50569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
5057c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
50589566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
50599566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
50607bee2925SMatthew Knepley     if (!interpolate) {
50617bee2925SMatthew Knepley       DM udm;
50627bee2925SMatthew Knepley 
50639566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
50649566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
50657bee2925SMatthew Knepley       *dm = udm;
50667bee2925SMatthew Knepley     }
50678ca92349SMatthew G. Knepley   } else if (isCV) {
50689566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
506998921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
50709566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
50719566063dSJacob Faibussowitsch   if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
50729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
5073ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
5074ca522641SMatthew G. Knepley }
5075