xref: /petsc/src/dm/impls/plex/plexcreate.c (revision dd4c3f67496275a10180fa3e9c7ac555daec1908)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h>   /*I   "petscdmplex.h"   I*/
40c312b8eSJed Brown #include <petscsf.h>
54663dae6SJed Brown #include <petscdmplextransform.h>
69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h>
7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
9552f7358SJed Brown 
10b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1158cd63d5SVaclav Hapla 
129318fe57SMatthew G. Knepley /* External function declarations here */
139318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
149318fe57SMatthew G. Knepley 
15e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
16d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
17d71ae5a4SJacob Faibussowitsch {
184fb89dddSMatthew G. Knepley   const PetscReal         *maxCell, *Lstart, *L;
196858538eSMatthew G. Knepley   PetscBool                dist;
206bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
21e600fa54SMatthew G. Knepley 
22e600fa54SMatthew G. Knepley   PetscFunctionBegin;
23e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
244fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
254fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
26e600fa54SMatthew G. Knepley   }
279566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
289566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
296bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
306bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
31e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
321baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
33e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
34e600fa54SMatthew G. Knepley }
35e600fa54SMatthew G. Knepley 
369318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
379318fe57SMatthew G. Knepley    - Share the DM_Plex structure
389318fe57SMatthew G. Knepley    - Share the coordinates
399318fe57SMatthew G. Knepley    - Share the SF
409318fe57SMatthew G. Knepley */
41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
42d71ae5a4SJacob Faibussowitsch {
439318fe57SMatthew G. Knepley   PetscSF          sf;
449318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
459318fe57SMatthew G. Knepley   Vec              coords;
464fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
479318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
489318fe57SMatthew G. Knepley 
499318fe57SMatthew G. Knepley   PetscFunctionBegin;
509318fe57SMatthew G. Knepley   if (dm == dmNew) {
519566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
529318fe57SMatthew G. Knepley     PetscFunctionReturn(0);
539318fe57SMatthew G. Knepley   }
549318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
559566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
569566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
589566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
599566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
609566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
629566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
656858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
666858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
676858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
686858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
699318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
706858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
716858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
7261a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
734fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
744fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
759566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
769566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
779318fe57SMatthew G. Knepley   dm->data = dmNew->data;
789318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
799566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
809566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
819566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
829566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
839566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
849318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
859318fe57SMatthew G. Knepley }
869318fe57SMatthew G. Knepley 
879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
889318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
899318fe57SMatthew G. Knepley    - Swap the coordinates
909318fe57SMatthew G. Knepley    - Swap the point PetscSF
919318fe57SMatthew G. Knepley */
92d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
93d71ae5a4SJacob Faibussowitsch {
949318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
959318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
969318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
979318fe57SMatthew G. Knepley   DMField     fieldTmp;
989318fe57SMatthew G. Knepley   void       *tmp;
999318fe57SMatthew G. Knepley   DMLabelLink listTmp;
1009318fe57SMatthew G. Knepley   DMLabel     depthTmp;
1019318fe57SMatthew G. Knepley   PetscInt    tmpI;
1029318fe57SMatthew G. Knepley 
1039318fe57SMatthew G. Knepley   PetscFunctionBegin;
1049318fe57SMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
1059566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
1069566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
1079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
1089566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
1099566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
1109566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
1119318fe57SMatthew G. Knepley 
1129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
1139566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
1149566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
1169566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
1179566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1189318fe57SMatthew G. Knepley 
1199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
1209566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
1219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
1229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
1239566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
1249566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1259318fe57SMatthew G. Knepley 
1266858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
1276858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
1286858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1296858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
1306858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
1316858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1326858538eSMatthew G. Knepley 
1336858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
1346858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
1356858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
1366858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
1376858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
1386858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1396858538eSMatthew G. Knepley 
1406858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
1416858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
1426858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
1436858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
1446858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
1456858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
1469318fe57SMatthew G. Knepley   tmp                       = dmA->data;
1479318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
1489318fe57SMatthew G. Knepley   dmB->data                 = tmp;
1499318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
1509318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
1519318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
1529318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
1539318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
1549318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
1559318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
1569318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
1579318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
1589318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
1599318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
1609318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
1619318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1629318fe57SMatthew G. Knepley }
1639318fe57SMatthew G. Knepley 
164d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
165d71ae5a4SJacob Faibussowitsch {
1669318fe57SMatthew G. Knepley   DM idm;
1679318fe57SMatthew G. Knepley 
1689318fe57SMatthew G. Knepley   PetscFunctionBegin;
1699566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
1709566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
17169d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
1729318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1739318fe57SMatthew G. Knepley }
1749318fe57SMatthew G. Knepley 
1759318fe57SMatthew G. Knepley /*@C
1769318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
1779318fe57SMatthew G. Knepley 
1789318fe57SMatthew G. Knepley   Collective
1799318fe57SMatthew G. Knepley 
1809318fe57SMatthew G. Knepley   Input Parameters:
1819318fe57SMatthew G. Knepley + DM        - The DM
1824f9ab2b4SJed Brown . degree    - The degree of the finite element or PETSC_DECIDE
1839318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
1849318fe57SMatthew G. Knepley 
1859318fe57SMatthew G. Knepley   Level: advanced
1869318fe57SMatthew G. Knepley 
187db781477SPatrick Sanan .seealso: `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
1889318fe57SMatthew G. Knepley @*/
189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc)
190d71ae5a4SJacob Faibussowitsch {
1919318fe57SMatthew G. Knepley   DM_Plex     *mesh = (DM_Plex *)dm->data;
1929318fe57SMatthew G. Knepley   DM           cdm;
1939318fe57SMatthew G. Knepley   PetscDS      cds;
1949318fe57SMatthew G. Knepley   PetscFE      fe;
1959318fe57SMatthew G. Knepley   PetscClassId id;
1969318fe57SMatthew G. Knepley 
1979318fe57SMatthew G. Knepley   PetscFunctionBegin;
1989566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
1999566063dSJacob Faibussowitsch   PetscCall(DMGetDS(cdm, &cds));
2009566063dSJacob Faibussowitsch   PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe));
2019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
2029318fe57SMatthew G. Knepley   if (id != PETSCFE_CLASSID) {
2039318fe57SMatthew G. Knepley     PetscBool simplex;
2049318fe57SMatthew G. Knepley     PetscInt dim, dE, qorder;
2059318fe57SMatthew G. Knepley 
2069566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
2079566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dm, &dE));
2089318fe57SMatthew G. Knepley     qorder = degree;
209d0609cedSBarry Smith     PetscObjectOptionsBegin((PetscObject)cdm);
2109566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
211d0609cedSBarry Smith     PetscOptionsEnd();
2124f9ab2b4SJed Brown     if (degree == PETSC_DECIDE) fe = NULL;
2134f9ab2b4SJed Brown     else {
2148c4475acSStefano Zampini       PetscCall(DMPlexIsSimplex(dm, &simplex));
2159566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe));
2164f9ab2b4SJed Brown     }
2179566063dSJacob Faibussowitsch     PetscCall(DMProjectCoordinates(dm, fe));
2189566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2199318fe57SMatthew G. Knepley   }
2209318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2219318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
2229318fe57SMatthew G. Knepley }
2239318fe57SMatthew G. Knepley 
2241df5d5c5SMatthew G. Knepley /*@
2251df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2261df5d5c5SMatthew G. Knepley 
227d083f849SBarry Smith   Collective
2281df5d5c5SMatthew G. Knepley 
2291df5d5c5SMatthew G. Knepley   Input Parameters:
2301df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object
2311df5d5c5SMatthew G. Knepley . dim - The spatial dimension
2321df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells
2331df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces)
2341df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2351df5d5c5SMatthew G. Knepley 
2361df5d5c5SMatthew G. Knepley   Output Parameter:
2371df5d5c5SMatthew G. Knepley . dm - The DM object
2381df5d5c5SMatthew G. Knepley 
2391df5d5c5SMatthew G. Knepley   Level: beginner
2401df5d5c5SMatthew G. Knepley 
241db781477SPatrick Sanan .seealso: `DMSetType()`, `DMCreate()`
2421df5d5c5SMatthew G. Knepley @*/
243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
244d71ae5a4SJacob Faibussowitsch {
2451df5d5c5SMatthew G. Knepley   DM          dm;
2461df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
2471df5d5c5SMatthew G. Knepley 
2481df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
2499566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
2509566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
2519566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
253ce78fa2fSMatthew G. Knepley   switch (dim) {
254ce78fa2fSMatthew G. Knepley   case 2:
2559566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
2569566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
257ce78fa2fSMatthew G. Knepley     break;
258ce78fa2fSMatthew G. Knepley   case 3:
2599566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
2609566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
261ce78fa2fSMatthew G. Knepley     break;
262d71ae5a4SJacob Faibussowitsch   default:
263d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
264ce78fa2fSMatthew G. Knepley   }
2651df5d5c5SMatthew G. Knepley   if (rank) {
2661df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
2679566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
2681df5d5c5SMatthew G. Knepley   } else {
2691df5d5c5SMatthew G. Knepley     switch (dim) {
2701df5d5c5SMatthew G. Knepley     case 2:
2711df5d5c5SMatthew G. Knepley       if (simplex) {
2721df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
2731df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
2741df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
2751df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
2761df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
2771df5d5c5SMatthew G. Knepley 
2789566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2791df5d5c5SMatthew G. Knepley       } else {
2801df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
2811df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
2821df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
2831df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2841df5d5c5SMatthew 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};
2851df5d5c5SMatthew G. Knepley 
2869566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2871df5d5c5SMatthew G. Knepley       }
2881df5d5c5SMatthew G. Knepley       break;
2891df5d5c5SMatthew G. Knepley     case 3:
2901df5d5c5SMatthew G. Knepley       if (simplex) {
2911df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
2921df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
2931df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
2941df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2951df5d5c5SMatthew 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};
2961df5d5c5SMatthew G. Knepley 
2979566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2981df5d5c5SMatthew G. Knepley       } else {
2991df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
3001df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3011df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
3021df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3039371c9d4SSatish 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};
3041df5d5c5SMatthew G. Knepley 
3059566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3061df5d5c5SMatthew G. Knepley       }
3071df5d5c5SMatthew G. Knepley       break;
308d71ae5a4SJacob Faibussowitsch     default:
309d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
3101df5d5c5SMatthew G. Knepley     }
3111df5d5c5SMatthew G. Knepley   }
3121df5d5c5SMatthew G. Knepley   *newdm = dm;
3131df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
3141df5d5c5SMatthew G. Knepley     DM          rdm;
3151df5d5c5SMatthew G. Knepley     const char *name;
3161df5d5c5SMatthew G. Knepley 
3179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
3189566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
3199566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
3209566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
3219566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
3229566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3231df5d5c5SMatthew G. Knepley     *newdm = rdm;
3241df5d5c5SMatthew G. Knepley   }
3251df5d5c5SMatthew G. Knepley   if (interpolate) {
3265fd9971aSMatthew G. Knepley     DM idm;
3271df5d5c5SMatthew G. Knepley 
3289566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
3299566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3301df5d5c5SMatthew G. Knepley     *newdm = idm;
3311df5d5c5SMatthew G. Knepley   }
3321df5d5c5SMatthew G. Knepley   PetscFunctionReturn(0);
3331df5d5c5SMatthew G. Knepley }
3341df5d5c5SMatthew G. Knepley 
335d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
336d71ae5a4SJacob Faibussowitsch {
3379318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3389318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3399318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3409318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3419318fe57SMatthew G. Knepley   Vec            coordinates;
3429318fe57SMatthew G. Knepley   PetscSection   coordSection;
3439318fe57SMatthew G. Knepley   PetscScalar   *coords;
3449318fe57SMatthew G. Knepley   PetscInt       coordSize;
3459318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3469318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
347552f7358SJed Brown 
3489318fe57SMatthew G. Knepley   PetscFunctionBegin;
3499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3509318fe57SMatthew G. Knepley   if (markerSeparate) {
3519318fe57SMatthew G. Knepley     markerRight = 2;
3529318fe57SMatthew G. Knepley     markerLeft  = 1;
3539318fe57SMatthew G. Knepley   }
3549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
355c5853193SPierre Jolivet   if (rank == 0) {
3569566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
3579566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3589566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
3599566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
3609318fe57SMatthew G. Knepley   }
3619566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
3629566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
3639318fe57SMatthew G. Knepley   /* Build coordinates */
3649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
3659566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
3669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
3679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
3689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
3699318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
3709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
3719566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
3729318fe57SMatthew G. Knepley   }
3739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
3749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
3759566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
3769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
3779566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
3789566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
3799566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
3809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
3819318fe57SMatthew G. Knepley   coords[0] = lower[0];
3829318fe57SMatthew G. Knepley   coords[1] = upper[0];
3839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
3849566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
3859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
3869318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
3879318fe57SMatthew G. Knepley }
38826492d91SMatthew G. Knepley 
389d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
390d71ae5a4SJacob Faibussowitsch {
3911df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
3921df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
393552f7358SJed Brown   PetscInt       markerTop      = 1;
394552f7358SJed Brown   PetscInt       markerBottom   = 1;
395552f7358SJed Brown   PetscInt       markerRight    = 1;
396552f7358SJed Brown   PetscInt       markerLeft     = 1;
397552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
398552f7358SJed Brown   Vec            coordinates;
399552f7358SJed Brown   PetscSection   coordSection;
400552f7358SJed Brown   PetscScalar   *coords;
401552f7358SJed Brown   PetscInt       coordSize;
402552f7358SJed Brown   PetscMPIInt    rank;
403552f7358SJed Brown   PetscInt       v, vx, vy;
404552f7358SJed Brown 
405552f7358SJed Brown   PetscFunctionBegin;
4069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
407552f7358SJed Brown   if (markerSeparate) {
4081df21d24SMatthew G. Knepley     markerTop    = 3;
4091df21d24SMatthew G. Knepley     markerBottom = 1;
4101df21d24SMatthew G. Knepley     markerRight  = 2;
4111df21d24SMatthew G. Knepley     markerLeft   = 4;
412552f7358SJed Brown   }
4139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
414dd400576SPatrick Sanan   if (rank == 0) {
415552f7358SJed Brown     PetscInt e, ex, ey;
416552f7358SJed Brown 
4179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
41848a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
4199566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
420552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
421552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
422552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
423552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
424da80777bSKarl Rupp         PetscInt cone[2];
425552f7358SJed Brown 
4269371c9d4SSatish Balay         cone[0] = vertex;
4279371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
4289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
429552f7358SJed Brown         if (vx == edges[0]) {
4309566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
4319566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
432552f7358SJed Brown           if (ey == edges[1] - 1) {
4339566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
4349566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
435552f7358SJed Brown           }
436552f7358SJed Brown         } else if (vx == 0) {
4379566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
4389566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
439552f7358SJed Brown           if (ey == edges[1] - 1) {
4409566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
4419566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
442552f7358SJed Brown           }
443552f7358SJed Brown         }
444552f7358SJed Brown       }
445552f7358SJed Brown     }
446552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
447552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
448552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
449552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
450da80777bSKarl Rupp         PetscInt cone[2];
451552f7358SJed Brown 
4529371c9d4SSatish Balay         cone[0] = vertex;
4539371c9d4SSatish Balay         cone[1] = vertex + 1;
4549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
455552f7358SJed Brown         if (vy == edges[1]) {
4569566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
4579566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
458552f7358SJed Brown           if (ex == edges[0] - 1) {
4599566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
4609566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
461552f7358SJed Brown           }
462552f7358SJed Brown         } else if (vy == 0) {
4639566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
4649566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
465552f7358SJed Brown           if (ex == edges[0] - 1) {
4669566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
4679566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
468552f7358SJed Brown           }
469552f7358SJed Brown         }
470552f7358SJed Brown       }
471552f7358SJed Brown     }
472552f7358SJed Brown   }
4739566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4749566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
475552f7358SJed Brown   /* Build coordinates */
4769566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
4779566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
4809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
481552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
4829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
4839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
484552f7358SJed Brown   }
4859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4879566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4899566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4909566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
4919566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
4929566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
493552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
494552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
495552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
496552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
497552f7358SJed Brown     }
498552f7358SJed Brown   }
4999566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
5009566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
502552f7358SJed Brown   PetscFunctionReturn(0);
503552f7358SJed Brown }
504552f7358SJed Brown 
505d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
506d71ae5a4SJacob Faibussowitsch {
5079e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
5087b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
509c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
510c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
511c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
512c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
513c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
514c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
515c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
516552f7358SJed Brown   Vec          coordinates;
517552f7358SJed Brown   PetscSection coordSection;
518552f7358SJed Brown   PetscScalar *coords;
519552f7358SJed Brown   PetscInt     coordSize;
520552f7358SJed Brown   PetscMPIInt  rank;
521552f7358SJed Brown   PetscInt     v, vx, vy, vz;
5227b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
523552f7358SJed Brown 
524552f7358SJed Brown   PetscFunctionBegin;
5251dca8a05SBarry 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");
5269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
527c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
528c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
529c2df9bbfSMatthew G. Knepley     markerBottom = 1;
530c2df9bbfSMatthew G. Knepley     markerTop    = 2;
531c2df9bbfSMatthew G. Knepley     markerFront  = 3;
532c2df9bbfSMatthew G. Knepley     markerBack   = 4;
533c2df9bbfSMatthew G. Knepley     markerRight  = 5;
534c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
535c2df9bbfSMatthew G. Knepley   }
5369371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
5379371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
5389371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
5399e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
540dd400576SPatrick Sanan   if (rank == 0) {
541552f7358SJed Brown     PetscInt f;
542552f7358SJed Brown 
5439566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
54448a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
5459566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5467b59f5a9SMichael Lange 
5477b59f5a9SMichael Lange     /* Side 0 (Top) */
5487b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5497b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5507b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
5519371c9d4SSatish Balay         cone[0] = voffset;
5529371c9d4SSatish Balay         cone[1] = voffset + 1;
5539371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
5549371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
5559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
556c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
557c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
558c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
559c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
560c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
5617b59f5a9SMichael Lange         iface++;
562552f7358SJed Brown       }
563552f7358SJed Brown     }
5647b59f5a9SMichael Lange 
5657b59f5a9SMichael Lange     /* Side 1 (Bottom) */
5667b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5677b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5687b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
5699371c9d4SSatish Balay         cone[0] = voffset + 1;
5709371c9d4SSatish Balay         cone[1] = voffset;
5719371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
5729371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
5739566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
574c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
575c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
576c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
577c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
578c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
5797b59f5a9SMichael Lange         iface++;
580552f7358SJed Brown       }
581552f7358SJed Brown     }
5827b59f5a9SMichael Lange 
5837b59f5a9SMichael Lange     /* Side 2 (Front) */
5847b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5857b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5867b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
5879371c9d4SSatish Balay         cone[0] = voffset;
5889371c9d4SSatish Balay         cone[1] = voffset + 1;
5899371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
5909371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
5919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
592c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
593c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
594c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
595c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
596c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
5977b59f5a9SMichael Lange         iface++;
598552f7358SJed Brown       }
5997b59f5a9SMichael Lange     }
6007b59f5a9SMichael Lange 
6017b59f5a9SMichael Lange     /* Side 3 (Back) */
6027b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6037b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6047b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
6059371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6069371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
6079371c9d4SSatish Balay         cone[2] = voffset + 1;
6089371c9d4SSatish Balay         cone[3] = voffset;
6099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
610c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
611c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
612c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
613c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
614c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
6157b59f5a9SMichael Lange         iface++;
6167b59f5a9SMichael Lange       }
6177b59f5a9SMichael Lange     }
6187b59f5a9SMichael Lange 
6197b59f5a9SMichael Lange     /* Side 4 (Left) */
6207b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6217b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
6227b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
6239371c9d4SSatish Balay         cone[0] = voffset;
6249371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
6259371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
6269371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
628c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
629c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
630c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
631c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
632c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
6337b59f5a9SMichael Lange         iface++;
6347b59f5a9SMichael Lange       }
6357b59f5a9SMichael Lange     }
6367b59f5a9SMichael Lange 
6377b59f5a9SMichael Lange     /* Side 5 (Right) */
6387b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6397b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
640aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
6419371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6429371c9d4SSatish Balay         cone[1] = voffset;
6439371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6449371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
6459566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
646c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
647c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
648c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
649c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
650c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
6517b59f5a9SMichael Lange         iface++;
6527b59f5a9SMichael Lange       }
653552f7358SJed Brown     }
654552f7358SJed Brown   }
6559566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6569566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
657552f7358SJed Brown   /* Build coordinates */
6589566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
6599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
6629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
663552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
6649566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
6659566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
666552f7358SJed Brown   }
6679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6699566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6719566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6729566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
6739566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6749566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
675552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
676552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
677552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
678552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
679552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
680552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
681552f7358SJed Brown       }
682552f7358SJed Brown     }
683552f7358SJed Brown   }
6849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6859566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
687552f7358SJed Brown   PetscFunctionReturn(0);
688552f7358SJed Brown }
689552f7358SJed Brown 
690d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
691d71ae5a4SJacob Faibussowitsch {
6929318fe57SMatthew G. Knepley   PetscFunctionBegin;
6939318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6949566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
6959566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
6969318fe57SMatthew G. Knepley   switch (dim) {
697d71ae5a4SJacob Faibussowitsch   case 1:
698d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
699d71ae5a4SJacob Faibussowitsch     break;
700d71ae5a4SJacob Faibussowitsch   case 2:
701d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
702d71ae5a4SJacob Faibussowitsch     break;
703d71ae5a4SJacob Faibussowitsch   case 3:
704d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
705d71ae5a4SJacob Faibussowitsch     break;
706d71ae5a4SJacob Faibussowitsch   default:
707d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
7089318fe57SMatthew G. Knepley   }
7099566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
7109318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7119318fe57SMatthew G. Knepley }
7129318fe57SMatthew G. Knepley 
7139318fe57SMatthew G. Knepley /*@C
7149318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
7159318fe57SMatthew G. Knepley 
7169318fe57SMatthew G. Knepley   Collective
7179318fe57SMatthew G. Knepley 
7189318fe57SMatthew G. Knepley   Input Parameters:
7199318fe57SMatthew G. Knepley + comm        - The communicator for the DM object
7209318fe57SMatthew G. Knepley . dim         - The spatial dimension of the box, so the resulting mesh is has dimension dim-1
7219318fe57SMatthew 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
7229318fe57SMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
7239318fe57SMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
7249318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7259318fe57SMatthew G. Knepley 
7269318fe57SMatthew G. Knepley   Output Parameter:
7279318fe57SMatthew G. Knepley . dm  - The DM object
7289318fe57SMatthew G. Knepley 
7299318fe57SMatthew G. Knepley   Level: beginner
7309318fe57SMatthew G. Knepley 
731db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
7329318fe57SMatthew G. Knepley @*/
733d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
734d71ae5a4SJacob Faibussowitsch {
7359318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
7369318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
7379318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
7389318fe57SMatthew G. Knepley 
7399318fe57SMatthew G. Knepley   PetscFunctionBegin;
7409566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
7419566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
7429566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
7439318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7449318fe57SMatthew G. Knepley }
7459318fe57SMatthew G. Knepley 
746d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
747d71ae5a4SJacob Faibussowitsch {
748fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
749fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
750fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
751fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
752fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
753fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
754fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
755fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
756fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
757fdbf62faSLisandro Dalcin 
758fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7599318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
760fdbf62faSLisandro Dalcin 
7619566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
7629566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
7639566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
764fdbf62faSLisandro Dalcin 
7659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
766dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
767dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
768fdbf62faSLisandro Dalcin 
7699371c9d4SSatish Balay   numPoints[0] = numVerts;
7709371c9d4SSatish Balay   numPoints[1] = numCells;
7719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
7729566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
773ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
774ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
7759371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
7769371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
7779371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
7789371c9d4SSatish Balay   }
779ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
7809566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
7819566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
782fdbf62faSLisandro Dalcin 
7839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
7849371c9d4SSatish Balay   if (markerSeparate) {
7859371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
7869371c9d4SSatish Balay     markerRight = faceMarkerRight;
7879371c9d4SSatish Balay   }
788dd400576SPatrick Sanan   if (!wrap && rank == 0) {
7899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
7909566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
7919566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
7929566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
7939566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
794fdbf62faSLisandro Dalcin   }
795fdbf62faSLisandro Dalcin   if (wrap) {
796fdbf62faSLisandro Dalcin     L       = upper - lower;
797fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
7984fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
799fdbf62faSLisandro Dalcin   }
8009566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
801fdbf62faSLisandro Dalcin   PetscFunctionReturn(0);
802fdbf62faSLisandro Dalcin }
803fdbf62faSLisandro Dalcin 
804d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
805d71ae5a4SJacob Faibussowitsch {
8069318fe57SMatthew G. Knepley   DM      boundary, vol;
807c22d3578SMatthew G. Knepley   DMLabel bdlabel;
808d6218766SMatthew G. Knepley 
809d6218766SMatthew G. Knepley   PetscFunctionBegin;
8109318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
811c22d3578SMatthew 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");
8129566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
8139566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
8149566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
8159566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
816c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
817c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
8185de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
81969d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
8209566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
821d6218766SMatthew G. Knepley   PetscFunctionReturn(0);
822d6218766SMatthew G. Knepley }
823d6218766SMatthew G. Knepley 
824d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
825d71ae5a4SJacob Faibussowitsch {
826ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
827f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
828f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
829f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
830f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
831f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
832f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
8333dfda0b1SToby Isaac   PetscInt    dim;
834d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
8353dfda0b1SToby Isaac   PetscMPIInt rank;
8363dfda0b1SToby Isaac 
8373dfda0b1SToby Isaac   PetscFunctionBegin;
8389566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8409566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8419566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
8429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
8439371c9d4SSatish 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) {
8449371c9d4SSatish Balay     if (cutMarker) {
8459371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
8469371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
8479371c9d4SSatish Balay     }
848d8211ee3SMatthew G. Knepley   }
8493dfda0b1SToby Isaac   switch (dim) {
8503dfda0b1SToby Isaac   case 2:
851f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
852f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
853f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
854f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
8553dfda0b1SToby Isaac     break;
8563dfda0b1SToby Isaac   case 3:
857f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
858f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
859f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
860f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
861f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
862f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
8633dfda0b1SToby Isaac     break;
864d71ae5a4SJacob Faibussowitsch   default:
865d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
8663dfda0b1SToby Isaac   }
8679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
868f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
869f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
870f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
871f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
872f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
873f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
874f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
8753dfda0b1SToby Isaac   }
8763dfda0b1SToby Isaac   {
877dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
878dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
879dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
880dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
881dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
882dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
8833dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
8843dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
8853dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
8863dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
8873dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
8883dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
8893dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
8903dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
8913dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
8923dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
8933dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
8943dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
8953dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
8963dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
8973dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
8983dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
8993dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
9003dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
9013dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
9023dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
9033dfda0b1SToby Isaac     Vec            coordinates;
9043dfda0b1SToby Isaac     PetscSection   coordSection;
9053dfda0b1SToby Isaac     PetscScalar   *coords;
9063dfda0b1SToby Isaac     PetscInt       coordSize;
9073dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
9083dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
9093dfda0b1SToby Isaac 
9109566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
91148a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
91248a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
91348a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
9149566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
9153dfda0b1SToby Isaac     /* Build cells */
9163dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9173dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9183dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
9193dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
9203dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
9213dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
9223dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9233dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
9243dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9253dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
9263dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
927b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
92842206facSLisandro Dalcin           PetscInt cone[6];
9293dfda0b1SToby Isaac 
9303dfda0b1SToby Isaac           /* no boundary twisting in 3D */
9319371c9d4SSatish Balay           cone[0] = faceB;
9329371c9d4SSatish Balay           cone[1] = faceT;
9339371c9d4SSatish Balay           cone[2] = faceF;
9349371c9d4SSatish Balay           cone[3] = faceK;
9359371c9d4SSatish Balay           cone[4] = faceR;
9369371c9d4SSatish Balay           cone[5] = faceL;
9379566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
9389566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
9399566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9409566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9419566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9423dfda0b1SToby Isaac         }
9433dfda0b1SToby Isaac       }
9443dfda0b1SToby Isaac     }
9453dfda0b1SToby Isaac     /* Build x faces */
9463dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9473dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9483dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
9493dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9503dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9513dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
9523dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
9533dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
954b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9553dfda0b1SToby Isaac           PetscInt cone[4];
9563dfda0b1SToby Isaac 
9573dfda0b1SToby Isaac           if (dim == 3) {
9583dfda0b1SToby Isaac             /* markers */
9593dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
9603dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
9619566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
9629566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
9639371c9d4SSatish Balay               } else if (fx == 0) {
9649566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
9659566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
9663dfda0b1SToby Isaac               }
9673dfda0b1SToby Isaac             }
9683dfda0b1SToby Isaac           }
9699371c9d4SSatish Balay           cone[0] = edgeB;
9709371c9d4SSatish Balay           cone[1] = edgeR;
9719371c9d4SSatish Balay           cone[2] = edgeT;
9729371c9d4SSatish Balay           cone[3] = edgeL;
9739566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
9749566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
9753dfda0b1SToby Isaac         }
9763dfda0b1SToby Isaac       }
9773dfda0b1SToby Isaac     }
9783dfda0b1SToby Isaac     /* Build y faces */
9793dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
98042206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
9813dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
9823dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9833dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9843dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
9853dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
9863dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
987b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9883dfda0b1SToby Isaac           PetscInt cone[4];
9893dfda0b1SToby Isaac 
9903dfda0b1SToby Isaac           if (dim == 3) {
9913dfda0b1SToby Isaac             /* markers */
9923dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
9933dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
9949566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
9959566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
9969371c9d4SSatish Balay               } else if (fy == 0) {
9979566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
9989566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
9993dfda0b1SToby Isaac               }
10003dfda0b1SToby Isaac             }
10013dfda0b1SToby Isaac           }
10029371c9d4SSatish Balay           cone[0] = edgeB;
10039371c9d4SSatish Balay           cone[1] = edgeR;
10049371c9d4SSatish Balay           cone[2] = edgeT;
10059371c9d4SSatish Balay           cone[3] = edgeL;
10069566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10079566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10083dfda0b1SToby Isaac         }
10093dfda0b1SToby Isaac       }
10103dfda0b1SToby Isaac     }
10113dfda0b1SToby Isaac     /* Build z faces */
10123dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
10133dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
10143dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
10153dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
10163dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
10173dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
10183dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
10193dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1020b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
10213dfda0b1SToby Isaac           PetscInt cone[4];
10223dfda0b1SToby Isaac 
10233dfda0b1SToby Isaac           if (dim == 2) {
10249371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
10259371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
10269371c9d4SSatish Balay               ornt[1] = -1;
10279371c9d4SSatish Balay             }
10289371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
10299371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
10309371c9d4SSatish Balay               ornt[2] = 0;
10319371c9d4SSatish Balay             }
10329566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
10339566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1034d1c88043SMatthew G. Knepley           } else {
10353dfda0b1SToby Isaac             /* markers */
10363dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
10373dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
10389566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
10399566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
10409371c9d4SSatish Balay               } else if (fz == 0) {
10419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
10429566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
10433dfda0b1SToby Isaac               }
10443dfda0b1SToby Isaac             }
10453dfda0b1SToby Isaac           }
10469371c9d4SSatish Balay           cone[0] = edgeB;
10479371c9d4SSatish Balay           cone[1] = edgeR;
10489371c9d4SSatish Balay           cone[2] = edgeT;
10499371c9d4SSatish Balay           cone[3] = edgeL;
10509566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10519566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10523dfda0b1SToby Isaac         }
10533dfda0b1SToby Isaac       }
10543dfda0b1SToby Isaac     }
10553dfda0b1SToby Isaac     /* Build Z edges*/
10563dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
10573dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10583dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
10593dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
10603dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
10613dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
10623dfda0b1SToby Isaac           PetscInt       cone[2];
10633dfda0b1SToby Isaac 
10649371c9d4SSatish Balay           cone[0] = vertexB;
10659371c9d4SSatish Balay           cone[1] = vertexT;
1066c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
10673dfda0b1SToby Isaac           if (dim == 3) {
10683dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
10693dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
10709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1071c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1072c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1073c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
10749566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1075c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1076c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10773dfda0b1SToby Isaac               }
10783dfda0b1SToby Isaac             }
10793dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
10803dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
10819566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1082c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1083c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1084c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
10859566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1086c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1087c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
10883dfda0b1SToby Isaac               }
10893dfda0b1SToby Isaac             }
10903dfda0b1SToby Isaac           }
10913dfda0b1SToby Isaac         }
10923dfda0b1SToby Isaac       }
10933dfda0b1SToby Isaac     }
10943dfda0b1SToby Isaac     /* Build Y edges*/
10953dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
10963dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10973dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
10983dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
10993dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
11003dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
11013dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
11023dfda0b1SToby Isaac           PetscInt       cone[2];
11033dfda0b1SToby Isaac 
11049371c9d4SSatish Balay           cone[0] = vertexF;
11059371c9d4SSatish Balay           cone[1] = vertexK;
11069566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11073dfda0b1SToby Isaac           if (dim == 2) {
11083dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
11093dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
11119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
11129566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1113c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1114d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11159566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
11169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
11179566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1118c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11193dfda0b1SToby Isaac               }
1120d8211ee3SMatthew G. Knepley             } else {
11214c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
11229566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11239566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1124c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11253dfda0b1SToby Isaac               }
1126d8211ee3SMatthew G. Knepley             }
1127d8211ee3SMatthew G. Knepley           } else {
11283dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
11293dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11309566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1131c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1132c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1133d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11349566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1135c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1136c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11373dfda0b1SToby Isaac               }
11383dfda0b1SToby Isaac             }
11393dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11403dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
11419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1142c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1143c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1144d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
11459566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1146c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1147c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11483dfda0b1SToby Isaac               }
11493dfda0b1SToby Isaac             }
11503dfda0b1SToby Isaac           }
11513dfda0b1SToby Isaac         }
11523dfda0b1SToby Isaac       }
11533dfda0b1SToby Isaac     }
11543dfda0b1SToby Isaac     /* Build X edges*/
11553dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
11563dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
11573dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
11583dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
11593dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
11603dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
11613dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
11623dfda0b1SToby Isaac           PetscInt       cone[2];
11633dfda0b1SToby Isaac 
11649371c9d4SSatish Balay           cone[0] = vertexL;
11659371c9d4SSatish Balay           cone[1] = vertexR;
11669566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11673dfda0b1SToby Isaac           if (dim == 2) {
11683dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
11693dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
11719566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
11729566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1173c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1174d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
11759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
11769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
11779566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1178c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11793dfda0b1SToby Isaac               }
1180d8211ee3SMatthew G. Knepley             } else {
11814c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
11829566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11839566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1184c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11853dfda0b1SToby Isaac               }
1186d8211ee3SMatthew G. Knepley             }
1187d8211ee3SMatthew G. Knepley           } else {
11883dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11893dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11909566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1191c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1192c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1193c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
11949566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1195c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1196c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
11973dfda0b1SToby Isaac               }
11983dfda0b1SToby Isaac             }
11993dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
12003dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
12019566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1202c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1203c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1204c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
12059566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1206c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1207c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
12083dfda0b1SToby Isaac               }
12093dfda0b1SToby Isaac             }
12103dfda0b1SToby Isaac           }
12113dfda0b1SToby Isaac         }
12123dfda0b1SToby Isaac       }
12133dfda0b1SToby Isaac     }
12149566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
12159566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
12163dfda0b1SToby Isaac     /* Build coordinates */
12179566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
12189566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
12199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
12209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
12213dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
12229566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
12239566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
12243dfda0b1SToby Isaac     }
12259566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
12269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
12279566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
12289566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
12299566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
12309566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
12319566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
12329566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
12333dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
12343dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
12353dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
12363dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
12373dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1238ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
12393dfda0b1SToby Isaac         }
12403dfda0b1SToby Isaac       }
12413dfda0b1SToby Isaac     }
12429566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12439566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
12449566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
12453dfda0b1SToby Isaac   }
12463dfda0b1SToby Isaac   PetscFunctionReturn(0);
12473dfda0b1SToby Isaac }
12483dfda0b1SToby Isaac 
1249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1250d71ae5a4SJacob Faibussowitsch {
12519318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
12529318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1253552f7358SJed Brown 
1254552f7358SJed Brown   PetscFunctionBegin;
12559318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
12569318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
12579566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
12589371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
12599371c9d4SSatish Balay     fac[d] = faces[d];
12609371c9d4SSatish Balay     bdt[d] = periodicity[d];
12619371c9d4SSatish Balay   }
12629566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
12639371c9d4SSatish 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))) {
12646858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
12656858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1266552f7358SJed Brown 
12679318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
12686858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
12699318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
12709318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1271768d5fceSMatthew G. Knepley       }
12726858538eSMatthew G. Knepley     }
12734fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1274768d5fceSMatthew G. Knepley   }
12759566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
12769318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
12779318fe57SMatthew G. Knepley }
12789318fe57SMatthew G. Knepley 
1279d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1280d71ae5a4SJacob Faibussowitsch {
12819318fe57SMatthew G. Knepley   PetscFunctionBegin;
12829566063dSJacob Faibussowitsch   if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
12839566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
12849566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
12859318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1286768d5fceSMatthew G. Knepley     DM udm;
1287768d5fceSMatthew G. Knepley 
12889566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
12899566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
129069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1291768d5fceSMatthew G. Knepley   }
1292768d5fceSMatthew G. Knepley   PetscFunctionReturn(0);
1293c8c68bd8SToby Isaac }
1294c8c68bd8SToby Isaac 
1295768d5fceSMatthew G. Knepley /*@C
1296768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1297768d5fceSMatthew G. Knepley 
1298d083f849SBarry Smith   Collective
1299768d5fceSMatthew G. Knepley 
1300768d5fceSMatthew G. Knepley   Input Parameters:
1301768d5fceSMatthew G. Knepley + comm        - The communicator for the DM object
1302768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1303768d5fceSMatthew G. Knepley . simplex     - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells
1304fdbf62faSLisandro Dalcin . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
1305768d5fceSMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
1306768d5fceSMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
1307fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1308768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
1309768d5fceSMatthew G. Knepley 
1310768d5fceSMatthew G. Knepley   Output Parameter:
1311768d5fceSMatthew G. Knepley . dm  - The DM object
1312768d5fceSMatthew G. Knepley 
13139318fe57SMatthew G. Knepley   Note: If you want to customize this mesh using options, you just need to
13149318fe57SMatthew G. Knepley $  DMCreate(comm, &dm);
13159318fe57SMatthew G. Knepley $  DMSetType(dm, DMPLEX);
13169318fe57SMatthew G. Knepley $  DMSetFromOptions(dm);
13179318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page.
13181367e252SJed Brown 
13191367e252SJed Brown   Here is the numbering returned for 2 faces in each direction for tensor cells:
1320768d5fceSMatthew G. Knepley $ 10---17---11---18----12
1321768d5fceSMatthew G. Knepley $  |         |         |
1322768d5fceSMatthew G. Knepley $  |         |         |
1323768d5fceSMatthew G. Knepley $ 20    2   22    3    24
1324768d5fceSMatthew G. Knepley $  |         |         |
1325768d5fceSMatthew G. Knepley $  |         |         |
1326768d5fceSMatthew G. Knepley $  7---15----8---16----9
1327768d5fceSMatthew G. Knepley $  |         |         |
1328768d5fceSMatthew G. Knepley $  |         |         |
1329768d5fceSMatthew G. Knepley $ 19    0   21    1   23
1330768d5fceSMatthew G. Knepley $  |         |         |
1331768d5fceSMatthew G. Knepley $  |         |         |
1332768d5fceSMatthew G. Knepley $  4---13----5---14----6
1333768d5fceSMatthew G. Knepley 
1334768d5fceSMatthew G. Knepley and for simplicial cells
1335768d5fceSMatthew G. Knepley 
1336768d5fceSMatthew G. Knepley $ 14----8---15----9----16
1337768d5fceSMatthew G. Knepley $  |\     5  |\      7 |
1338768d5fceSMatthew G. Knepley $  | \       | \       |
1339768d5fceSMatthew G. Knepley $ 13   2    14    3    15
1340768d5fceSMatthew G. Knepley $  | 4   \   | 6   \   |
1341768d5fceSMatthew G. Knepley $  |       \ |       \ |
1342768d5fceSMatthew G. Knepley $ 11----6---12----7----13
1343768d5fceSMatthew G. Knepley $  |\        |\        |
1344768d5fceSMatthew G. Knepley $  | \    1  | \     3 |
1345768d5fceSMatthew G. Knepley $ 10   0    11    1    12
1346768d5fceSMatthew G. Knepley $  | 0   \   | 2   \   |
1347768d5fceSMatthew G. Knepley $  |       \ |       \ |
1348768d5fceSMatthew G. Knepley $  8----4----9----5----10
1349768d5fceSMatthew G. Knepley 
1350768d5fceSMatthew G. Knepley   Level: beginner
1351768d5fceSMatthew G. Knepley 
1352db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1353768d5fceSMatthew G. Knepley @*/
1354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm)
1355d71ae5a4SJacob Faibussowitsch {
13569318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1357fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1358fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1359fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1360552f7358SJed Brown 
1361768d5fceSMatthew G. Knepley   PetscFunctionBegin;
13629566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
13639566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
13649566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
13657ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
13669318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
13679318fe57SMatthew G. Knepley }
1368fdbf62faSLisandro Dalcin 
1369d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1370d71ae5a4SJacob Faibussowitsch {
13719318fe57SMatthew G. Knepley   DM       bdm, vol;
13729318fe57SMatthew G. Knepley   PetscInt i;
13739318fe57SMatthew G. Knepley 
13749318fe57SMatthew G. Knepley   PetscFunctionBegin;
137508401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
13769566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
13779566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
13789566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
13799566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
13809566063dSJacob Faibussowitsch   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
13819566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
138269d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
13839318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
13849318fe57SMatthew G. Knepley     Vec          v;
13859318fe57SMatthew G. Knepley     PetscScalar *x;
13869318fe57SMatthew G. Knepley     PetscInt     cDim, n;
13879318fe57SMatthew G. Knepley 
13889566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
13899566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
13909566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
13919566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
13929318fe57SMatthew G. Knepley     x += cDim;
13939318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
13949566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
13959566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
13969318fe57SMatthew G. Knepley   }
1397552f7358SJed Brown   PetscFunctionReturn(0);
1398552f7358SJed Brown }
1399552f7358SJed Brown 
140000dabe28SStefano Zampini /*@
140100dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
140200dabe28SStefano Zampini 
1403d083f849SBarry Smith   Collective
140400dabe28SStefano Zampini 
140500dabe28SStefano Zampini   Input Parameters:
140600dabe28SStefano Zampini + comm        - The communicator for the DM object
140700dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
140800dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
140900dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
141000dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1411d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
141200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
141300dabe28SStefano Zampini 
141400dabe28SStefano Zampini   Output Parameter:
141500dabe28SStefano Zampini . dm  - The DM object
141600dabe28SStefano Zampini 
141700dabe28SStefano Zampini   Level: beginner
141800dabe28SStefano Zampini 
1419db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
142000dabe28SStefano Zampini @*/
1421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1422d71ae5a4SJacob Faibussowitsch {
14239318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
142400dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
142500dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
142600dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
142700dabe28SStefano Zampini 
142800dabe28SStefano Zampini   PetscFunctionBegin;
14299566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14309566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14319566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1432d410b0cfSMatthew G. Knepley   if (!interpolate) {
1433d410b0cfSMatthew G. Knepley     DM udm;
143400dabe28SStefano Zampini 
14359566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
143669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
143700dabe28SStefano Zampini   }
14387ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
143900dabe28SStefano Zampini   PetscFunctionReturn(0);
144000dabe28SStefano Zampini }
144100dabe28SStefano Zampini 
1442a9074c1eSMatthew G. Knepley /*@C
1443a9074c1eSMatthew G. Knepley   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database.
1444a9074c1eSMatthew G. Knepley 
1445d083f849SBarry Smith   Logically Collective on dm
1446a9074c1eSMatthew G. Knepley 
1447a9074c1eSMatthew G. Knepley   Input Parameters:
1448a9074c1eSMatthew G. Knepley + dm - the DM context
1449a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1450a9074c1eSMatthew G. Knepley 
1451a9074c1eSMatthew G. Knepley   Notes:
1452a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1453a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1454a9074c1eSMatthew G. Knepley 
1455a9074c1eSMatthew G. Knepley   Level: advanced
1456a9074c1eSMatthew G. Knepley 
1457db781477SPatrick Sanan .seealso: `SNESSetFromOptions()`
1458a9074c1eSMatthew G. Knepley @*/
1459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1460d71ae5a4SJacob Faibussowitsch {
1461a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1462a9074c1eSMatthew G. Knepley 
1463a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1464a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14659566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
14669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
1467a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1468a9074c1eSMatthew G. Knepley }
1469a9074c1eSMatthew G. Knepley 
14709318fe57SMatthew G. Knepley /* Remap geometry to cylinder
147161a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
147261a622f3SMatthew G. Knepley 
14739318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
14749318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
14759318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
14760510c589SMatthew G. Knepley 
14779318fe57SMatthew G. Knepley        phi     = arctan(y/x)
14789318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
14799318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
14800510c589SMatthew G. Knepley 
14819318fe57SMatthew G. Knepley      so we remap them using
14820510c589SMatthew G. Knepley 
14839318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
14849318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
14850510c589SMatthew G. Knepley 
14869318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
14879318fe57SMatthew G. Knepley */
1488d71ae5a4SJacob Faibussowitsch static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
1489d71ae5a4SJacob Faibussowitsch {
14909318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
14919318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
149222cc497dSMatthew G. Knepley 
14939318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
14949318fe57SMatthew G. Knepley     f0[0] = u[0];
14959318fe57SMatthew G. Knepley     f0[1] = u[1];
14969318fe57SMatthew G. Knepley   } else {
14979318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
14980510c589SMatthew G. Knepley 
14999318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
15009318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
15019318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
15029318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
15039318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
15049318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
15059318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
15069318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
15079318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
15089318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
15099318fe57SMatthew G. Knepley     } else {
15109318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
15119318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
15129318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
15139318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
15149318fe57SMatthew G. Knepley     }
15159318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
15169318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
15179318fe57SMatthew G. Knepley   }
15189318fe57SMatthew G. Knepley   f0[2] = u[2];
15199318fe57SMatthew G. Knepley }
15200510c589SMatthew G. Knepley 
1521d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ)
1522d71ae5a4SJacob Faibussowitsch {
15230510c589SMatthew G. Knepley   const PetscInt dim = 3;
15249318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1525d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
15260510c589SMatthew G. Knepley 
15270510c589SMatthew G. Knepley   PetscFunctionBegin;
15289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15299566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
15300510c589SMatthew G. Knepley   /* Create topology */
15310510c589SMatthew G. Knepley   {
15320510c589SMatthew G. Knepley     PetscInt cone[8], c;
15330510c589SMatthew G. Knepley 
1534dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1535dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1536006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1537ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1538dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1539006a8963SMatthew G. Knepley     }
15409566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
15419566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
15429566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1543dd400576SPatrick Sanan     if (rank == 0) {
1544006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
15459371c9d4SSatish Balay         cone[0] = 15;
15469371c9d4SSatish Balay         cone[1] = 18;
15479371c9d4SSatish Balay         cone[2] = 17;
15489371c9d4SSatish Balay         cone[3] = 16;
15499371c9d4SSatish Balay         cone[4] = 31;
15509371c9d4SSatish Balay         cone[5] = 32;
15519371c9d4SSatish Balay         cone[6] = 33;
15529371c9d4SSatish Balay         cone[7] = 34;
15539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
15549371c9d4SSatish Balay         cone[0] = 16;
15559371c9d4SSatish Balay         cone[1] = 17;
15569371c9d4SSatish Balay         cone[2] = 24;
15579371c9d4SSatish Balay         cone[3] = 23;
15589371c9d4SSatish Balay         cone[4] = 32;
15599371c9d4SSatish Balay         cone[5] = 36;
15609371c9d4SSatish Balay         cone[6] = 37;
15619371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
15629566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
15639371c9d4SSatish Balay         cone[0] = 18;
15649371c9d4SSatish Balay         cone[1] = 27;
15659371c9d4SSatish Balay         cone[2] = 24;
15669371c9d4SSatish Balay         cone[3] = 17;
15679371c9d4SSatish Balay         cone[4] = 34;
15689371c9d4SSatish Balay         cone[5] = 33;
15699371c9d4SSatish Balay         cone[6] = 37;
15709371c9d4SSatish Balay         cone[7] = 38;
15719566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
15729371c9d4SSatish Balay         cone[0] = 29;
15739371c9d4SSatish Balay         cone[1] = 27;
15749371c9d4SSatish Balay         cone[2] = 18;
15759371c9d4SSatish Balay         cone[3] = 15;
15769371c9d4SSatish Balay         cone[4] = 35;
15779371c9d4SSatish Balay         cone[5] = 31;
15789371c9d4SSatish Balay         cone[6] = 34;
15799371c9d4SSatish Balay         cone[7] = 38;
15809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
15819371c9d4SSatish Balay         cone[0] = 29;
15829371c9d4SSatish Balay         cone[1] = 15;
15839371c9d4SSatish Balay         cone[2] = 16;
15849371c9d4SSatish Balay         cone[3] = 23;
15859371c9d4SSatish Balay         cone[4] = 35;
15869371c9d4SSatish Balay         cone[5] = 36;
15879371c9d4SSatish Balay         cone[6] = 32;
15889371c9d4SSatish Balay         cone[7] = 31;
15899566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1590006a8963SMatthew G. Knepley 
15919371c9d4SSatish Balay         cone[0] = 31;
15929371c9d4SSatish Balay         cone[1] = 34;
15939371c9d4SSatish Balay         cone[2] = 33;
15949371c9d4SSatish Balay         cone[3] = 32;
15959371c9d4SSatish Balay         cone[4] = 19;
15969371c9d4SSatish Balay         cone[5] = 22;
15979371c9d4SSatish Balay         cone[6] = 21;
15989371c9d4SSatish Balay         cone[7] = 20;
15999566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
16009371c9d4SSatish Balay         cone[0] = 32;
16019371c9d4SSatish Balay         cone[1] = 33;
16029371c9d4SSatish Balay         cone[2] = 37;
16039371c9d4SSatish Balay         cone[3] = 36;
16049371c9d4SSatish Balay         cone[4] = 22;
16059371c9d4SSatish Balay         cone[5] = 25;
16069371c9d4SSatish Balay         cone[6] = 26;
16079371c9d4SSatish Balay         cone[7] = 21;
16089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
16099371c9d4SSatish Balay         cone[0] = 34;
16109371c9d4SSatish Balay         cone[1] = 38;
16119371c9d4SSatish Balay         cone[2] = 37;
16129371c9d4SSatish Balay         cone[3] = 33;
16139371c9d4SSatish Balay         cone[4] = 20;
16149371c9d4SSatish Balay         cone[5] = 21;
16159371c9d4SSatish Balay         cone[6] = 26;
16169371c9d4SSatish Balay         cone[7] = 28;
16179566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
16189371c9d4SSatish Balay         cone[0] = 35;
16199371c9d4SSatish Balay         cone[1] = 38;
16209371c9d4SSatish Balay         cone[2] = 34;
16219371c9d4SSatish Balay         cone[3] = 31;
16229371c9d4SSatish Balay         cone[4] = 30;
16239371c9d4SSatish Balay         cone[5] = 19;
16249371c9d4SSatish Balay         cone[6] = 20;
16259371c9d4SSatish Balay         cone[7] = 28;
16269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
16279371c9d4SSatish Balay         cone[0] = 35;
16289371c9d4SSatish Balay         cone[1] = 31;
16299371c9d4SSatish Balay         cone[2] = 32;
16309371c9d4SSatish Balay         cone[3] = 36;
16319371c9d4SSatish Balay         cone[4] = 30;
16329371c9d4SSatish Balay         cone[5] = 25;
16339371c9d4SSatish Balay         cone[6] = 22;
16349371c9d4SSatish Balay         cone[7] = 19;
16359566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
1636ae8bcbbbSMatthew G. Knepley 
16379371c9d4SSatish Balay         cone[0] = 19;
16389371c9d4SSatish Balay         cone[1] = 20;
16399371c9d4SSatish Balay         cone[2] = 21;
16409371c9d4SSatish Balay         cone[3] = 22;
16419371c9d4SSatish Balay         cone[4] = 15;
16429371c9d4SSatish Balay         cone[5] = 16;
16439371c9d4SSatish Balay         cone[6] = 17;
16449371c9d4SSatish Balay         cone[7] = 18;
16459566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
16469371c9d4SSatish Balay         cone[0] = 22;
16479371c9d4SSatish Balay         cone[1] = 21;
16489371c9d4SSatish Balay         cone[2] = 26;
16499371c9d4SSatish Balay         cone[3] = 25;
16509371c9d4SSatish Balay         cone[4] = 16;
16519371c9d4SSatish Balay         cone[5] = 23;
16529371c9d4SSatish Balay         cone[6] = 24;
16539371c9d4SSatish Balay         cone[7] = 17;
16549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
16559371c9d4SSatish Balay         cone[0] = 20;
16569371c9d4SSatish Balay         cone[1] = 28;
16579371c9d4SSatish Balay         cone[2] = 26;
16589371c9d4SSatish Balay         cone[3] = 21;
16599371c9d4SSatish Balay         cone[4] = 18;
16609371c9d4SSatish Balay         cone[5] = 17;
16619371c9d4SSatish Balay         cone[6] = 24;
16629371c9d4SSatish Balay         cone[7] = 27;
16639566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
16649371c9d4SSatish Balay         cone[0] = 30;
16659371c9d4SSatish Balay         cone[1] = 28;
16669371c9d4SSatish Balay         cone[2] = 20;
16679371c9d4SSatish Balay         cone[3] = 19;
16689371c9d4SSatish Balay         cone[4] = 29;
16699371c9d4SSatish Balay         cone[5] = 15;
16709371c9d4SSatish Balay         cone[6] = 18;
16719371c9d4SSatish Balay         cone[7] = 27;
16729566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
16739371c9d4SSatish Balay         cone[0] = 30;
16749371c9d4SSatish Balay         cone[1] = 19;
16759371c9d4SSatish Balay         cone[2] = 22;
16769371c9d4SSatish Balay         cone[3] = 25;
16779371c9d4SSatish Balay         cone[4] = 29;
16789371c9d4SSatish Balay         cone[5] = 23;
16799371c9d4SSatish Balay         cone[6] = 16;
16809371c9d4SSatish Balay         cone[7] = 15;
16819566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
1682006a8963SMatthew G. Knepley       } else {
16839371c9d4SSatish Balay         cone[0] = 5;
16849371c9d4SSatish Balay         cone[1] = 8;
16859371c9d4SSatish Balay         cone[2] = 7;
16869371c9d4SSatish Balay         cone[3] = 6;
16879371c9d4SSatish Balay         cone[4] = 9;
16889371c9d4SSatish Balay         cone[5] = 12;
16899371c9d4SSatish Balay         cone[6] = 11;
16909371c9d4SSatish Balay         cone[7] = 10;
16919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
16929371c9d4SSatish Balay         cone[0] = 6;
16939371c9d4SSatish Balay         cone[1] = 7;
16949371c9d4SSatish Balay         cone[2] = 14;
16959371c9d4SSatish Balay         cone[3] = 13;
16969371c9d4SSatish Balay         cone[4] = 12;
16979371c9d4SSatish Balay         cone[5] = 15;
16989371c9d4SSatish Balay         cone[6] = 16;
16999371c9d4SSatish Balay         cone[7] = 11;
17009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
17019371c9d4SSatish Balay         cone[0] = 8;
17029371c9d4SSatish Balay         cone[1] = 17;
17039371c9d4SSatish Balay         cone[2] = 14;
17049371c9d4SSatish Balay         cone[3] = 7;
17059371c9d4SSatish Balay         cone[4] = 10;
17069371c9d4SSatish Balay         cone[5] = 11;
17079371c9d4SSatish Balay         cone[6] = 16;
17089371c9d4SSatish Balay         cone[7] = 18;
17099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
17109371c9d4SSatish Balay         cone[0] = 19;
17119371c9d4SSatish Balay         cone[1] = 17;
17129371c9d4SSatish Balay         cone[2] = 8;
17139371c9d4SSatish Balay         cone[3] = 5;
17149371c9d4SSatish Balay         cone[4] = 20;
17159371c9d4SSatish Balay         cone[5] = 9;
17169371c9d4SSatish Balay         cone[6] = 10;
17179371c9d4SSatish Balay         cone[7] = 18;
17189566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
17199371c9d4SSatish Balay         cone[0] = 19;
17209371c9d4SSatish Balay         cone[1] = 5;
17219371c9d4SSatish Balay         cone[2] = 6;
17229371c9d4SSatish Balay         cone[3] = 13;
17239371c9d4SSatish Balay         cone[4] = 20;
17249371c9d4SSatish Balay         cone[5] = 15;
17259371c9d4SSatish Balay         cone[6] = 12;
17269371c9d4SSatish Balay         cone[7] = 9;
17279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1728006a8963SMatthew G. Knepley       }
1729d8c47e87SMatthew G. Knepley     }
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
17319566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
17320510c589SMatthew G. Knepley   }
1733dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
17340510c589SMatthew G. Knepley   {
17350510c589SMatthew G. Knepley     Vec             coordinates;
17360510c589SMatthew G. Knepley     PetscSection    coordSection;
17370510c589SMatthew G. Knepley     PetscScalar    *coords;
17380510c589SMatthew G. Knepley     PetscInt        coordSize, v;
17390510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
17400510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
17410510c589SMatthew G. Knepley 
17420510c589SMatthew G. Knepley     /* Build coordinates */
17439566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
17449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
17459566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
17469566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
17470510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
17489566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
17499566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
17500510c589SMatthew G. Knepley     }
17519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
17529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
17539566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
17549566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
17559566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
17569566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
17579566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
17589566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1759dd400576SPatrick Sanan     if (rank == 0) {
17609371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
17619371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
17629371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
17639371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
17649371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
17659371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
17669371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
17679371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
17689371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
17699371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
17709371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
17719371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
17729371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
17739371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
17749371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
17759371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
17769371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
17779371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
17789371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
17799371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
17809371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
17819371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
17829371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
17839371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
17849371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
17859371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
17869371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
17879371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
17889371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
17899371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
17909371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
17919371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
17929371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
17939371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
17949371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
17959371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
17969371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
17979371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
17989371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
17999371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
18009371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
18019371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
18029371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
18039371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
18049371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
18059371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
18069371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
18079371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
1808ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
18099371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
18109371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
18119371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
18129371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
18139371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
18149371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
18159371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
18169371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
18179371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
18189371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
18199371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
18209371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
18219371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
18229371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
18239371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
18249371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
18259371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
18269371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
18279371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
18289371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
18299371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
18309371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
18319371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
18329371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
1833ae8bcbbbSMatthew G. Knepley       }
1834d8c47e87SMatthew G. Knepley     }
18359566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18369566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18379566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18380510c589SMatthew G. Knepley   }
1839006a8963SMatthew G. Knepley   /* Create periodicity */
1840006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
18416858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
18426858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1843006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
1844ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
18456858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
1846006a8963SMatthew G. Knepley 
18476858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
18486858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
18494fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1850006a8963SMatthew G. Knepley   }
1851dbc1dc17SMatthew G. Knepley   {
18529318fe57SMatthew G. Knepley     DM          cdm;
18539318fe57SMatthew G. Knepley     PetscDS     cds;
18549318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1855dbc1dc17SMatthew G. Knepley 
18569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
18579566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
18589566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
18599566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
1860dbc1dc17SMatthew G. Knepley   }
18619318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
18629566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
18630510c589SMatthew G. Knepley   PetscFunctionReturn(0);
18640510c589SMatthew G. Knepley }
18650510c589SMatthew G. Knepley 
186624119c2aSMatthew G. Knepley /*@
18679318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
186824119c2aSMatthew G. Knepley 
1869d083f849SBarry Smith   Collective
187024119c2aSMatthew G. Knepley 
187124119c2aSMatthew G. Knepley   Input Parameters:
187224119c2aSMatthew G. Knepley + comm      - The communicator for the DM object
18739318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
187424119c2aSMatthew G. Knepley 
187524119c2aSMatthew G. Knepley   Output Parameter:
187624119c2aSMatthew G. Knepley . dm  - The DM object
187724119c2aSMatthew G. Knepley 
18789318fe57SMatthew G. Knepley   Note:
18799318fe57SMatthew G. Knepley   Here is the output numbering looking from the bottom of the cylinder:
18809318fe57SMatthew G. Knepley $       17-----14
18819318fe57SMatthew G. Knepley $        |     |
18829318fe57SMatthew G. Knepley $        |  2  |
18839318fe57SMatthew G. Knepley $        |     |
18849318fe57SMatthew G. Knepley $ 17-----8-----7-----14
18859318fe57SMatthew G. Knepley $  |     |     |     |
18869318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
18879318fe57SMatthew G. Knepley $  |     |     |     |
18889318fe57SMatthew G. Knepley $ 19-----5-----6-----13
18899318fe57SMatthew G. Knepley $        |     |
18909318fe57SMatthew G. Knepley $        |  4  |
18919318fe57SMatthew G. Knepley $        |     |
18929318fe57SMatthew G. Knepley $       19-----13
18939318fe57SMatthew G. Knepley $
18949318fe57SMatthew G. Knepley $ and up through the top
18959318fe57SMatthew G. Knepley $
18969318fe57SMatthew G. Knepley $       18-----16
18979318fe57SMatthew G. Knepley $        |     |
18989318fe57SMatthew G. Knepley $        |  2  |
18999318fe57SMatthew G. Knepley $        |     |
19009318fe57SMatthew G. Knepley $ 18----10----11-----16
19019318fe57SMatthew G. Knepley $  |     |     |     |
19029318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
19039318fe57SMatthew G. Knepley $  |     |     |     |
19049318fe57SMatthew G. Knepley $ 20-----9----12-----15
19059318fe57SMatthew G. Knepley $        |     |
19069318fe57SMatthew G. Knepley $        |  4  |
19079318fe57SMatthew G. Knepley $        |     |
19089318fe57SMatthew G. Knepley $       20-----15
19099318fe57SMatthew G. Knepley 
191024119c2aSMatthew G. Knepley   Level: beginner
191124119c2aSMatthew G. Knepley 
1912db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
191324119c2aSMatthew G. Knepley @*/
1914d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm)
1915d71ae5a4SJacob Faibussowitsch {
19169318fe57SMatthew G. Knepley   PetscFunctionBegin;
19179318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
19189566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
19199566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
19209566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
19219318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
19229318fe57SMatthew G. Knepley }
19239318fe57SMatthew G. Knepley 
1924d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
1925d71ae5a4SJacob Faibussowitsch {
192624119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1927412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
19289fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
192924119c2aSMatthew G. Knepley 
193024119c2aSMatthew G. Knepley   PetscFunctionBegin;
193163a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
19329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
19339566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1934412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
19359566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
193624119c2aSMatthew G. Knepley   /* Create topology */
193724119c2aSMatthew G. Knepley   {
193824119c2aSMatthew G. Knepley     PetscInt cone[6], c;
193924119c2aSMatthew G. Knepley 
1940dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
1941dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
19429566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19439566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
19449566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
194524119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19469371c9d4SSatish Balay       cone[0] = c + n * 1;
19479371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
19489371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
19499371c9d4SSatish Balay       cone[3] = c + n * 2;
19509371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
19519371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
19529566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
19539566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
195424119c2aSMatthew G. Knepley     }
19559566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
19569566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
195724119c2aSMatthew G. Knepley   }
195848a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
195924119c2aSMatthew G. Knepley   /* Create cylinder geometry */
196024119c2aSMatthew G. Knepley   {
196124119c2aSMatthew G. Knepley     Vec          coordinates;
196224119c2aSMatthew G. Knepley     PetscSection coordSection;
196324119c2aSMatthew G. Knepley     PetscScalar *coords;
1964412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
196524119c2aSMatthew G. Knepley 
196624119c2aSMatthew G. Knepley     /* Build coordinates */
19679566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
19689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
19699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
19709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
197124119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
19729566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
19739566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
197424119c2aSMatthew G. Knepley     }
19759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
19769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
19779566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
19789566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
19799566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
19809566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
19819566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
19829566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
198324119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19849371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19859371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19869371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
19879371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19889371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19899371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
199024119c2aSMatthew G. Knepley     }
1991dd400576SPatrick Sanan     if (rank == 0) {
19929371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
19939371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
19949371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
19959371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
19969371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
19979371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
19989fe9f049SMatthew G. Knepley     }
19999566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
20009566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
20019566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
200224119c2aSMatthew G. Knepley   }
20039318fe57SMatthew G. Knepley   /* Interpolate */
20049566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
20059318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
20069318fe57SMatthew G. Knepley }
20079318fe57SMatthew G. Knepley 
20089318fe57SMatthew G. Knepley /*@
20099318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
20109318fe57SMatthew G. Knepley 
20119318fe57SMatthew G. Knepley   Collective
20129318fe57SMatthew G. Knepley 
20139318fe57SMatthew G. Knepley   Input Parameters:
20149318fe57SMatthew G. Knepley + comm - The communicator for the DM object
20159318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
20169318fe57SMatthew G. Knepley - interpolate - Create edges and faces
20179318fe57SMatthew G. Knepley 
20189318fe57SMatthew G. Knepley   Output Parameter:
20199318fe57SMatthew G. Knepley . dm  - The DM object
20209318fe57SMatthew G. Knepley 
20219318fe57SMatthew G. Knepley   Level: beginner
20229318fe57SMatthew G. Knepley 
2023db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
20249318fe57SMatthew G. Knepley @*/
2025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2026d71ae5a4SJacob Faibussowitsch {
20279318fe57SMatthew G. Knepley   PetscFunctionBegin;
20289318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
20299566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20309566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20319566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
203224119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
203324119c2aSMatthew G. Knepley }
203424119c2aSMatthew G. Knepley 
2035d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2036d71ae5a4SJacob Faibussowitsch {
203765a81367SMatthew G. Knepley   PetscReal prod = 0.0;
203865a81367SMatthew G. Knepley   PetscInt  i;
203965a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
204065a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
204165a81367SMatthew G. Knepley }
2042d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2043d71ae5a4SJacob Faibussowitsch {
204465a81367SMatthew G. Knepley   PetscReal prod = 0.0;
204565a81367SMatthew G. Knepley   PetscInt  i;
204665a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
204765a81367SMatthew G. Knepley   return prod;
204865a81367SMatthew G. Knepley }
204965a81367SMatthew G. Knepley 
205051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2051d71ae5a4SJacob Faibussowitsch static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
2052d71ae5a4SJacob Faibussowitsch {
205351a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
205451a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
205551a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
205651a74b61SMatthew G. Knepley 
205751a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
205851a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
205951a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
206051a74b61SMatthew G. Knepley }
206151a74b61SMatthew G. Knepley 
2062d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2063d71ae5a4SJacob Faibussowitsch {
206465a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
206565a81367SMatthew G. Knepley   PetscSection   coordSection;
206665a81367SMatthew G. Knepley   Vec            coordinates;
206765a81367SMatthew G. Knepley   PetscScalar   *coords;
206865a81367SMatthew G. Knepley   PetscReal     *coordsIn;
2069064cae4fSPierre Jolivet   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e;
207065a81367SMatthew G. Knepley   PetscMPIInt    rank;
207165a81367SMatthew G. Knepley 
207265a81367SMatthew G. Knepley   PetscFunctionBegin;
20739318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
20749566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
20759566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
20769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
207765a81367SMatthew G. Knepley   switch (dim) {
207865a81367SMatthew G. Knepley   case 2:
207965a81367SMatthew G. Knepley     if (simplex) {
208051a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
208151a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
208265a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
208351a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
208465a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
208565a81367SMatthew G. Knepley       PetscInt        cone[3];
208665a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
208765a81367SMatthew G. Knepley 
20889371c9d4SSatish Balay       vertex[0] *= R / radius;
20899371c9d4SSatish Balay       vertex[1] *= R / radius;
20909371c9d4SSatish Balay       vertex[2] *= R / radius;
2091dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2092dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
209365a81367SMatthew G. Knepley       firstVertex = numCells;
209451a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
209565a81367SMatthew G. Knepley 
209665a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
209765a81367SMatthew G. Knepley 
209865a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
209951a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
210065a81367SMatthew G. Knepley       */
210165a81367SMatthew G. Knepley       /* Construct vertices */
21029566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2103dd400576SPatrick Sanan       if (rank == 0) {
210465a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
210565a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
210665a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
210765a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
210865a81367SMatthew G. Knepley               ++i;
210965a81367SMatthew G. Knepley             }
211065a81367SMatthew G. Knepley           }
211165a81367SMatthew G. Knepley         }
211245da822fSValeria Barra       }
211365a81367SMatthew G. Knepley       /* Construct graph */
21149566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
211565a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
211665a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
21179371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
21189371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
21199371c9d4SSatish Balay             ++k;
21209371c9d4SSatish Balay           }
212165a81367SMatthew G. Knepley         }
212263a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
212365a81367SMatthew G. Knepley       }
212465a81367SMatthew G. Knepley       /* Build Topology */
21259566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
212648a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
21279566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
212865a81367SMatthew G. Knepley       /* Cells */
212965a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
213065a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
213165a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
213265a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
21339371c9d4SSatish Balay               cone[0] = firstVertex + i;
21349371c9d4SSatish Balay               cone[1] = firstVertex + j;
21359371c9d4SSatish Balay               cone[2] = firstVertex + k;
213665a81367SMatthew G. Knepley               /* Check orientation */
213765a81367SMatthew G. Knepley               {
21389371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
21399371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
21409371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
21419371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
21429371c9d4SSatish Balay                 };
214365a81367SMatthew G. Knepley                 PetscReal normal[3];
214465a81367SMatthew G. Knepley                 PetscInt  e, f;
214565a81367SMatthew G. Knepley 
214665a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
214765a81367SMatthew G. Knepley                   normal[d] = 0.0;
214865a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
2149ad540459SPierre Jolivet                     for (f = 0; f < embedDim; ++f) normal[d] += epsilon[d][e][f] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]);
215065a81367SMatthew G. Knepley                   }
215165a81367SMatthew G. Knepley                 }
21529371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
21539371c9d4SSatish Balay                   PetscInt tmp = cone[1];
21549371c9d4SSatish Balay                   cone[1]      = cone[2];
21559371c9d4SSatish Balay                   cone[2]      = tmp;
215665a81367SMatthew G. Knepley                 }
215765a81367SMatthew G. Knepley               }
21589566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
215965a81367SMatthew G. Knepley             }
216065a81367SMatthew G. Knepley           }
216165a81367SMatthew G. Knepley         }
216265a81367SMatthew G. Knepley       }
21639566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
21649566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
21659566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
216665a81367SMatthew G. Knepley     } else {
21672829fed8SMatthew G. Knepley       /*
21682829fed8SMatthew G. Knepley         12-21--13
21692829fed8SMatthew G. Knepley          |     |
21702829fed8SMatthew G. Knepley         25  4  24
21712829fed8SMatthew G. Knepley          |     |
21722829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
21732829fed8SMatthew G. Knepley    |     |     |     |
21742829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
21752829fed8SMatthew G. Knepley    |     |     |     |
21762829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
21772829fed8SMatthew G. Knepley          |     |
21782829fed8SMatthew G. Knepley         20  1  19
21792829fed8SMatthew G. Knepley          |     |
21802829fed8SMatthew G. Knepley         10-18--11
21812829fed8SMatthew G. Knepley          |     |
21822829fed8SMatthew G. Knepley         23  2  22
21832829fed8SMatthew G. Knepley          |     |
21842829fed8SMatthew G. Knepley         12-21--13
21852829fed8SMatthew G. Knepley        */
21862829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
21872829fed8SMatthew G. Knepley 
2188dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2189dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2190dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
219165a81367SMatthew G. Knepley       firstVertex = numCells;
219265a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
21932829fed8SMatthew G. Knepley       /* Build Topology */
21949566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
219548a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
219648a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
21979566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2198dd400576SPatrick Sanan       if (rank == 0) {
21992829fed8SMatthew G. Knepley         /* Cell 0 */
22009371c9d4SSatish Balay         cone[0] = 14;
22019371c9d4SSatish Balay         cone[1] = 15;
22029371c9d4SSatish Balay         cone[2] = 16;
22039371c9d4SSatish Balay         cone[3] = 17;
22049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
22059371c9d4SSatish Balay         ornt[0] = 0;
22069371c9d4SSatish Balay         ornt[1] = 0;
22079371c9d4SSatish Balay         ornt[2] = 0;
22089371c9d4SSatish Balay         ornt[3] = 0;
22099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
22102829fed8SMatthew G. Knepley         /* Cell 1 */
22119371c9d4SSatish Balay         cone[0] = 18;
22129371c9d4SSatish Balay         cone[1] = 19;
22139371c9d4SSatish Balay         cone[2] = 14;
22149371c9d4SSatish Balay         cone[3] = 20;
22159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
22169371c9d4SSatish Balay         ornt[0] = 0;
22179371c9d4SSatish Balay         ornt[1] = 0;
22189371c9d4SSatish Balay         ornt[2] = -1;
22199371c9d4SSatish Balay         ornt[3] = 0;
22209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
22212829fed8SMatthew G. Knepley         /* Cell 2 */
22229371c9d4SSatish Balay         cone[0] = 21;
22239371c9d4SSatish Balay         cone[1] = 22;
22249371c9d4SSatish Balay         cone[2] = 18;
22259371c9d4SSatish Balay         cone[3] = 23;
22269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
22279371c9d4SSatish Balay         ornt[0] = 0;
22289371c9d4SSatish Balay         ornt[1] = 0;
22299371c9d4SSatish Balay         ornt[2] = -1;
22309371c9d4SSatish Balay         ornt[3] = 0;
22319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
22322829fed8SMatthew G. Knepley         /* Cell 3 */
22339371c9d4SSatish Balay         cone[0] = 19;
22349371c9d4SSatish Balay         cone[1] = 22;
22359371c9d4SSatish Balay         cone[2] = 24;
22369371c9d4SSatish Balay         cone[3] = 15;
22379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
22389371c9d4SSatish Balay         ornt[0] = -1;
22399371c9d4SSatish Balay         ornt[1] = -1;
22409371c9d4SSatish Balay         ornt[2] = 0;
22419371c9d4SSatish Balay         ornt[3] = -1;
22429566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
22432829fed8SMatthew G. Knepley         /* Cell 4 */
22449371c9d4SSatish Balay         cone[0] = 16;
22459371c9d4SSatish Balay         cone[1] = 24;
22469371c9d4SSatish Balay         cone[2] = 21;
22479371c9d4SSatish Balay         cone[3] = 25;
22489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
22499371c9d4SSatish Balay         ornt[0] = -1;
22509371c9d4SSatish Balay         ornt[1] = -1;
22519371c9d4SSatish Balay         ornt[2] = -1;
22529371c9d4SSatish Balay         ornt[3] = 0;
22539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
22542829fed8SMatthew G. Knepley         /* Cell 5 */
22559371c9d4SSatish Balay         cone[0] = 20;
22569371c9d4SSatish Balay         cone[1] = 17;
22579371c9d4SSatish Balay         cone[2] = 25;
22589371c9d4SSatish Balay         cone[3] = 23;
22599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
22609371c9d4SSatish Balay         ornt[0] = -1;
22619371c9d4SSatish Balay         ornt[1] = -1;
22629371c9d4SSatish Balay         ornt[2] = -1;
22639371c9d4SSatish Balay         ornt[3] = -1;
22649566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
22652829fed8SMatthew G. Knepley         /* Edges */
22669371c9d4SSatish Balay         cone[0] = 6;
22679371c9d4SSatish Balay         cone[1] = 7;
22689566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
22699371c9d4SSatish Balay         cone[0] = 7;
22709371c9d4SSatish Balay         cone[1] = 8;
22719566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
22729371c9d4SSatish Balay         cone[0] = 8;
22739371c9d4SSatish Balay         cone[1] = 9;
22749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
22759371c9d4SSatish Balay         cone[0] = 9;
22769371c9d4SSatish Balay         cone[1] = 6;
22779566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
22789371c9d4SSatish Balay         cone[0] = 10;
22799371c9d4SSatish Balay         cone[1] = 11;
22809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
22819371c9d4SSatish Balay         cone[0] = 11;
22829371c9d4SSatish Balay         cone[1] = 7;
22839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
22849371c9d4SSatish Balay         cone[0] = 6;
22859371c9d4SSatish Balay         cone[1] = 10;
22869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
22879371c9d4SSatish Balay         cone[0] = 12;
22889371c9d4SSatish Balay         cone[1] = 13;
22899566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
22909371c9d4SSatish Balay         cone[0] = 13;
22919371c9d4SSatish Balay         cone[1] = 11;
22929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
22939371c9d4SSatish Balay         cone[0] = 10;
22949371c9d4SSatish Balay         cone[1] = 12;
22959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
22969371c9d4SSatish Balay         cone[0] = 13;
22979371c9d4SSatish Balay         cone[1] = 8;
22989566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
22999371c9d4SSatish Balay         cone[0] = 12;
23009371c9d4SSatish Balay         cone[1] = 9;
23019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
230245da822fSValeria Barra       }
23039566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
23049566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
23052829fed8SMatthew G. Knepley       /* Build coordinates */
23069566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2307dd400576SPatrick Sanan       if (rank == 0) {
23089371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
23099371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
23109371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
23119371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
23129371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
23139371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
23149371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
23159371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
23169371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
23179371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
23189371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
23199371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
23209371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
23219371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
23229371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
23239371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
23249371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
23259371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
23269371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
23279371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
23289371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
23299371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
23309371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
23319371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
233265a81367SMatthew G. Knepley       }
233345da822fSValeria Barra     }
233465a81367SMatthew G. Knepley     break;
233565a81367SMatthew G. Knepley   case 3:
2336116ded15SMatthew G. Knepley     if (simplex) {
2337116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
233851a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
233951a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
234051a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2341116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2342116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
23439371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
23449371c9d4SSatish Balay         {0, 1, 2, 3},
23459371c9d4SSatish Balay         {0, 2, 3, 1},
23469371c9d4SSatish Balay         {0, 3, 1, 2},
23479371c9d4SSatish Balay         {1, 0, 3, 2},
23489371c9d4SSatish Balay         {1, 2, 0, 3},
23499371c9d4SSatish Balay         {1, 3, 2, 0},
23509371c9d4SSatish Balay         {2, 0, 1, 3},
23519371c9d4SSatish Balay         {2, 1, 3, 0},
23529371c9d4SSatish Balay         {2, 3, 0, 1},
23539371c9d4SSatish Balay         {3, 0, 2, 1},
23549371c9d4SSatish Balay         {3, 1, 0, 2},
23559371c9d4SSatish Balay         {3, 2, 1, 0}
23569371c9d4SSatish Balay       };
2357116ded15SMatthew G. Knepley       PetscInt  cone[4];
2358116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2359116ded15SMatthew G. Knepley 
23609371c9d4SSatish Balay       vertexA[0] *= R;
23619371c9d4SSatish Balay       vertexA[1] *= R;
23629371c9d4SSatish Balay       vertexA[2] *= R;
23639371c9d4SSatish Balay       vertexA[3] *= R;
23649371c9d4SSatish Balay       vertexB[0] *= R;
23659371c9d4SSatish Balay       vertexB[1] *= R;
23669371c9d4SSatish Balay       vertexB[2] *= R;
23679371c9d4SSatish Balay       vertexB[3] *= R;
23689371c9d4SSatish Balay       vertexC[0] *= R;
23699371c9d4SSatish Balay       vertexC[1] *= R;
23709371c9d4SSatish Balay       vertexC[2] *= R;
23719371c9d4SSatish Balay       vertexC[3] *= R;
2372dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2373dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2374116ded15SMatthew G. Knepley       firstVertex = numCells;
2375116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2376116ded15SMatthew G. Knepley 
2377116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2378116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2379116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2380116ded15SMatthew G. Knepley 
2381116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
23826333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2383116ded15SMatthew G. Knepley 
2384116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2385116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2386116ded15SMatthew G. Knepley       */
2387116ded15SMatthew G. Knepley       /* Construct vertices */
23889566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2389116ded15SMatthew G. Knepley       i = 0;
2390dd400576SPatrick Sanan       if (rank == 0) {
2391116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2392116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2393116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2394116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2395116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2396116ded15SMatthew G. Knepley                 ++i;
2397116ded15SMatthew G. Knepley               }
2398116ded15SMatthew G. Knepley             }
2399116ded15SMatthew G. Knepley           }
2400116ded15SMatthew G. Knepley         }
2401116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2402116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2403116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2404116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2405116ded15SMatthew G. Knepley             ++i;
2406116ded15SMatthew G. Knepley           }
2407116ded15SMatthew G. Knepley         }
2408116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2409116ded15SMatthew G. Knepley           s[3] = 1;
2410116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2411116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2412116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2413116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2414116ded15SMatthew G. Knepley                 ++i;
2415116ded15SMatthew G. Knepley               }
2416116ded15SMatthew G. Knepley             }
2417116ded15SMatthew G. Knepley           }
2418116ded15SMatthew G. Knepley         }
241945da822fSValeria Barra       }
242063a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2421116ded15SMatthew G. Knepley       /* Construct graph */
24229566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2423116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2424116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
24259371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
24269371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
24279371c9d4SSatish Balay             ++k;
24289371c9d4SSatish Balay           }
2429116ded15SMatthew G. Knepley         }
243063a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2431116ded15SMatthew G. Knepley       }
2432116ded15SMatthew G. Knepley       /* Build Topology */
24339566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
243448a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
24359566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2436116ded15SMatthew G. Knepley       /* Cells */
2437dd400576SPatrick Sanan       if (rank == 0) {
2438116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2439116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2440116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2441116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
24429371c9d4SSatish 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]) {
24439371c9d4SSatish Balay                   cone[0] = firstVertex + i;
24449371c9d4SSatish Balay                   cone[1] = firstVertex + j;
24459371c9d4SSatish Balay                   cone[2] = firstVertex + k;
24469371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2447116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2448116ded15SMatthew G. Knepley                   {
24499371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
24509371c9d4SSatish 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}}},
2451116ded15SMatthew G. Knepley 
24529371c9d4SSatish 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}}},
2453116ded15SMatthew G. Knepley 
24549371c9d4SSatish 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}}},
2455116ded15SMatthew G. Knepley 
24569371c9d4SSatish 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}} }
24579371c9d4SSatish Balay                     };
2458116ded15SMatthew G. Knepley                     PetscReal normal[4];
2459116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2460116ded15SMatthew G. Knepley 
2461116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2462116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2463116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2464116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2465116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2466116ded15SMatthew 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]);
2467116ded15SMatthew G. Knepley                           }
2468116ded15SMatthew G. Knepley                         }
2469116ded15SMatthew G. Knepley                       }
2470116ded15SMatthew G. Knepley                     }
24719371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
24729371c9d4SSatish Balay                       PetscInt tmp = cone[1];
24739371c9d4SSatish Balay                       cone[1]      = cone[2];
24749371c9d4SSatish Balay                       cone[2]      = tmp;
24759371c9d4SSatish Balay                     }
2476116ded15SMatthew G. Knepley                   }
24779566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2478116ded15SMatthew G. Knepley                 }
2479116ded15SMatthew G. Knepley               }
2480116ded15SMatthew G. Knepley             }
2481116ded15SMatthew G. Knepley           }
2482116ded15SMatthew G. Knepley         }
248345da822fSValeria Barra       }
24849566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
24859566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
24869566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2487116ded15SMatthew G. Knepley     }
2488f4d061e9SPierre Jolivet     break;
2489d71ae5a4SJacob Faibussowitsch   default:
2490d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
249165a81367SMatthew G. Knepley   }
249265a81367SMatthew G. Knepley   /* Create coordinates */
24939566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
24949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
24959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
24969566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
24972829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
24989566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
24999566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
25002829fed8SMatthew G. Knepley   }
25019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
25029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25039566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25049566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
25059566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25069566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25079566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
25089566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
25099371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
2510ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
25119566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
25129566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
25139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
25149566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
251551a74b61SMatthew G. Knepley   {
251651a74b61SMatthew G. Knepley     DM          cdm;
251751a74b61SMatthew G. Knepley     PetscDS     cds;
25189318fe57SMatthew G. Knepley     PetscScalar c = R;
251951a74b61SMatthew G. Knepley 
25209566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
25219566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
25229566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
25239566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
252451a74b61SMatthew G. Knepley   }
25259318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
25269566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
25279318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
25289318fe57SMatthew G. Knepley }
25299318fe57SMatthew G. Knepley 
2530b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
2531b7f5c055SJed Brown 
2532b7f5c055SJed Brown /*
2533b7f5c055SJed Brown  The Schwarz P implicit surface is
2534b7f5c055SJed Brown 
2535b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2536b7f5c055SJed Brown */
2537d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2538d71ae5a4SJacob Faibussowitsch {
2539b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2540b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2541b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
2542b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2543b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
2544ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
2545b7f5c055SJed Brown   }
2546b7f5c055SJed Brown }
2547b7f5c055SJed Brown 
25484663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2549d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2550d71ae5a4SJacob Faibussowitsch {
2551ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
25524663dae6SJed Brown   return 0;
25534663dae6SJed Brown }
25544663dae6SJed Brown 
2555b7f5c055SJed Brown /*
2556b7f5c055SJed Brown  The Gyroid implicit surface is
2557b7f5c055SJed Brown 
2558b7f5c055SJed 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)
2559b7f5c055SJed Brown 
2560b7f5c055SJed Brown */
2561d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2562d71ae5a4SJacob Faibussowitsch {
2563b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2564b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2565b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2566b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2567b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2568b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2569b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2570b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2571b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2572b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2573b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2574b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2575b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2576b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2577b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2578b7f5c055SJed Brown }
2579b7f5c055SJed Brown 
25804663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2581d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2582d71ae5a4SJacob Faibussowitsch {
25834663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
25844663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
25854663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
25864663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
25874663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
25884663dae6SJed Brown   return 0;
25894663dae6SJed Brown }
25904663dae6SJed Brown 
2591b7f5c055SJed Brown /*
2592b7f5c055SJed Brown    We wish to solve
2593b7f5c055SJed Brown 
2594b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2595b7f5c055SJed Brown 
2596b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2597b7f5c055SJed 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
2598b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2599b7f5c055SJed Brown 
2600b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2601b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2602b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2603b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2604b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2605b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2606b7f5c055SJed Brown 
2607b7f5c055SJed Brown      f(y) = 0                       1 equation
2608b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2609b7f5c055SJed Brown 
2610b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2611b7f5c055SJed Brown */
2612d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
2613d71ae5a4SJacob Faibussowitsch {
2614b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2615b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
26162f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
26179371c9d4SSatish Balay   PetscReal n_y[3][3] = {
26189371c9d4SSatish Balay     {0, 0, 0},
26199371c9d4SSatish Balay     {0, 0, 0},
26209371c9d4SSatish Balay     {0, 0, 0}
26219371c9d4SSatish Balay   };
2622b7f5c055SJed Brown 
2623b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2624b7f5c055SJed Brown 
2625b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
2626b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2627ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
2628b7f5c055SJed Brown 
2629b7f5c055SJed Brown   // Define the Householder reflector
2630b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2631b7f5c055SJed Brown   n[0] += norm * sign;
2632b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
2633b7f5c055SJed Brown 
2634b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2635b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2636b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2637b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2638b7f5c055SJed Brown 
2639b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2640b7f5c055SJed Brown     n[i] /= norm;
2641b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
2642b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2643b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2644b7f5c055SJed Brown     }
2645b7f5c055SJed Brown   }
2646b7f5c055SJed Brown 
2647b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2648b7f5c055SJed 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];
2649b7f5c055SJed Brown 
2650b7f5c055SJed Brown   res[0] = f;
2651b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2652b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2653b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2654b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
2655b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
2656b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2657b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2658b7f5c055SJed Brown   }
2659b7f5c055SJed Brown }
2660b7f5c055SJed Brown 
2661b7f5c055SJed Brown /*
2662b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2663b7f5c055SJed Brown */
2664d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
2665d71ae5a4SJacob Faibussowitsch {
2666b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2667b7f5c055SJed Brown 
2668b7f5c055SJed Brown   PetscFunctionBegin;
2669b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
2670b7f5c055SJed Brown     PetscScalar res[3], J[9];
2671b7f5c055SJed Brown     PetscReal   resnorm;
2672b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2673b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2674b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
267563a3b9bcSJacob 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])));
2676b7f5c055SJed Brown     }
2677b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2678b7f5c055SJed Brown 
2679b7f5c055SJed Brown     // Take the Newton step
26809566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2681b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2682b7f5c055SJed Brown   }
2683b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
2684b7f5c055SJed Brown   PetscFunctionReturn(0);
2685b7f5c055SJed Brown }
2686b7f5c055SJed Brown 
2687b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2688b7f5c055SJed Brown 
2689d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
2690d71ae5a4SJacob Faibussowitsch {
2691b7f5c055SJed Brown   PetscMPIInt rank;
2692b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2693b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
2694b7f5c055SJed Brown   PetscInt            *cells_flat = NULL;
2695b7f5c055SJed Brown   PetscReal           *vtxCoords  = NULL;
2696b7f5c055SJed Brown   TPSEvaluateFunc      evalFunc   = NULL;
26974663dae6SJed Brown   PetscSimplePointFunc normalFunc = NULL;
2698b7f5c055SJed Brown   DMLabel              label;
2699b7f5c055SJed Brown 
2700b7f5c055SJed Brown   PetscFunctionBegin;
27019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
270263a3b9bcSJacob 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);
2703b7f5c055SJed Brown   switch (tpstype) {
2704b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2705b7f5c055SJed 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");
2706c5853193SPierre Jolivet     if (rank == 0) {
2707b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2708b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2709b7f5c055SJed Brown       PetscReal L = 1;
2710b7f5c055SJed Brown 
2711b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
2712b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
2713b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
2714b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
2715b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2716b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
27179566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
27189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
27199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
27209566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
2721b7f5c055SJed Brown       // x-normal pipes
2722b7f5c055SJed Brown       vcount = 0;
2723b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
2724b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2725b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2726b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2727b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
2728b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2729b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2730b7f5c055SJed Brown             }
2731b7f5c055SJed Brown           }
2732b7f5c055SJed Brown         }
2733b7f5c055SJed Brown       }
2734b7f5c055SJed Brown       // y-normal pipes
2735b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2736b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
2737b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2738b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2739b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2740b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
2741b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2742b7f5c055SJed Brown             }
2743b7f5c055SJed Brown           }
2744b7f5c055SJed Brown         }
2745b7f5c055SJed Brown       }
2746b7f5c055SJed Brown       // z-normal pipes
2747b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2748b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2749b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
2750b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2751b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2752b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2753b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
2754b7f5c055SJed Brown             }
2755b7f5c055SJed Brown           }
2756b7f5c055SJed Brown         }
2757b7f5c055SJed Brown       }
2758b7f5c055SJed Brown       // junctions
2759b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2760b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2761b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2762b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
2763b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2764b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
2765b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
2766b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
2767b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
2768b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
2769b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
2770b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
2771b7f5c055SJed Brown                 }
2772b7f5c055SJed Brown               }
2773b7f5c055SJed Brown             }
2774b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2775b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
2776b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
2777b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
2778b7f5c055SJed Brown             };
2779b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
27809371c9d4SSatish 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};
2781b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
27829371c9d4SSatish 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};
2783b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
2784b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2785b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
2786b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
2787b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
2788b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
2789b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
2790b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
2791b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
2792b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
2793b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
2794b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2795b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2796b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
2797b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
2798b7f5c055SJed Brown                   numEdges++;
2799b7f5c055SJed Brown                 }
2800b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2801b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2802b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
2803b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
2804b7f5c055SJed Brown                   numEdges++;
2805b7f5c055SJed Brown                 }
2806b7f5c055SJed Brown               }
2807b7f5c055SJed Brown             }
2808b7f5c055SJed Brown           }
2809b7f5c055SJed Brown         }
2810b7f5c055SJed Brown       }
281163a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
2812b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
2813b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2814b7f5c055SJed Brown     }
2815b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
28164663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
2817b7f5c055SJed Brown     break;
2818b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2819c5853193SPierre Jolivet     if (rank == 0) {
2820b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2821b7f5c055SJed Brown       //
2822b7f5c055SJed 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)
2823b7f5c055SJed Brown       //
2824b7f5c055SJed Brown       // on the cell [0,2]^3.
2825b7f5c055SJed Brown       //
2826b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2827b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2828b7f5c055SJed Brown       // like a boomerang:
2829b7f5c055SJed Brown       //
2830b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2831b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2832b7f5c055SJed Brown       //                                                              //
2833b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2834b7f5c055SJed Brown       //      \                                   /            \      //
2835b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2836b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2837b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2838b7f5c055SJed Brown       //                                                              //
2839b7f5c055SJed Brown       //                                                              //
2840b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2841b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2842b7f5c055SJed Brown       //                                                              //
2843b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2844b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2845b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2846b7f5c055SJed Brown       //            \                       /                \        //
2847b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2848b7f5c055SJed Brown       //
2849b7f5c055SJed Brown       //
2850b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2851b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2852b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2853b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2854b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2855b7f5c055SJed Brown       //
2856b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2857b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2858b7f5c055SJed Brown       //
2859b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2860b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2861b7f5c055SJed Brown 
2862b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
2863b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
2864b7f5c055SJed Brown       PetscInt extentPlus[3];
2865b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
28669371c9d4SSatish 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;
28679371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
28689371c9d4SSatish Balay   /* face to vertex within the coarse discretization of a single gyroid block */
2869b7f5c055SJed Brown   /* layer 0 */
28709371c9d4SSatish Balay         {A,           C,           K,           G          },
28719371c9d4SSatish Balay         {C,           B,           II,          K          },
28729371c9d4SSatish Balay         {D,           A,           H,           L          },
28739371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
28749371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
28759371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
28769371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
28779371c9d4SSatish Balay         {B,           F,           M,           II         },
2878b7f5c055SJed Brown  /* layer 1 */
28799371c9d4SSatish Balay         {G,           K,           Q,           O          },
28809371c9d4SSatish Balay         {K,           II,          P,           Q          },
28819371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
28829371c9d4SSatish Balay         {J,           L,           R,           P          },
28839371c9d4SSatish Balay         {N,           J,           P,           S          },
28849371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
28859371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
28869371c9d4SSatish Balay         {II,          M,           T,           P          },
2887b7f5c055SJed Brown  /* layer 2 */
28889371c9d4SSatish Balay         {O,           Q,           Y,           U          },
28899371c9d4SSatish Balay         {Q,           P,           W,           Y          },
28909371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
28919371c9d4SSatish Balay         {P,           R,           Ap,          W          },
28929371c9d4SSatish Balay         {S,           P,           X,           Bp         },
28939371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
28949371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
28959371c9d4SSatish Balay         {P,           T,           Z,           X          },
2896b7f5c055SJed Brown  /* layer 3 */
28979371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
28989371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
28999371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
29009371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
29019371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
29029371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
29039371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
29049371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
2905b7f5c055SJed Brown  /* layer 4 */
29069371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
29079371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
29089371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
29099371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
29109371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
29119371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
29129371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
29139371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
2914b7f5c055SJed Brown  /* layer 5 */
29159371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
29169371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
29179371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
29189371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
29199371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
29209371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
29219371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
29229371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
2923b7f5c055SJed Brown  /* layer 6 */
29249371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
29259371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
29269371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
29279371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
29289371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
29299371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
29309371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
29319371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
2932b7f5c055SJed Brown  /* layer 7 (the top is the periodic image of the bottom of layer 0) */
29339371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
29349371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
29359371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
29369371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
29379371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
29389371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
29399371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
29409371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
2941b7f5c055SJed Brown       };
2942b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
29439371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
2944bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
2945bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
2946bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
2947bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
2948bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
2949bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
2950b7f5c055SJed Brown 
2951bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
2952bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
2953bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
2954bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
2955bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
2956bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
2957bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
2958bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
2959b7f5c055SJed Brown 
2960bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
2961bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
2962bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
2963bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
2964bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
2965bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
2966b7f5c055SJed Brown 
2967bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
2968bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
2969bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
2970bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
2971bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
2972bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
2973bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
2974bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
2975b7f5c055SJed Brown 
2976bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
2977bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
2978bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
2979bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
2980bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
2981bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
2982b7f5c055SJed Brown 
2983bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
2984bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
2985bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
2986bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
2987bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
2988bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
2989bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
2990bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
2991b7f5c055SJed Brown 
2992bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
2993bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
2994bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
2995bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
2996bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
2997bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
2998b7f5c055SJed Brown 
2999bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3000bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3001bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3002bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3003bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3004bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3005bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3006bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3007b7f5c055SJed Brown       };
3008b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3009b7f5c055SJed Brown       PetscBool *seen;
3010b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3011b7f5c055SJed Brown       PetscInt   count;
3012b7f5c055SJed Brown 
3013b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3014b7f5c055SJed Brown       numBlocks = 1;
3015b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3016b7f5c055SJed Brown       numBlocksPlus = 1;
3017b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3018b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
30199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
30209566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3021b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3022b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3023b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3024b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3025b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3026b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3027b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3028b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3029b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3030b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3031b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3032b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3033b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3034b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3035b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3036b7f5c055SJed Brown 
3037b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3038b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3039b7f5c055SJed Brown               }
3040b7f5c055SJed Brown             }
3041b7f5c055SJed Brown           }
3042b7f5c055SJed Brown         }
3043b7f5c055SJed Brown       }
30449371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
30459371c9d4SSatish Balay         if (seen[i]) numVertices++;
3046b7f5c055SJed Brown       count = 0;
30479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
30489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3049b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3050b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3051b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3052b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3053b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3054b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3055b7f5c055SJed Brown 
3056b7f5c055SJed Brown               if (seen[vIdx]) {
3057b7f5c055SJed Brown                 PetscInt thisVert;
3058b7f5c055SJed Brown 
3059b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3060b7f5c055SJed Brown 
3061b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3062b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3063b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3064b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3065b7f5c055SJed Brown               }
3066b7f5c055SJed Brown             }
3067b7f5c055SJed Brown           }
3068b7f5c055SJed Brown         }
3069b7f5c055SJed Brown       }
3070b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3071b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3072ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3073b7f5c055SJed Brown         }
3074b7f5c055SJed Brown       }
30759566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
30769566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3077b7f5c055SJed Brown       cells_flat = cells[0][0];
3078b7f5c055SJed Brown       numEdges   = 0;
3079b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3080b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3081b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3082b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3083b7f5c055SJed Brown 
3084b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3085b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3086b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3087b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3088b7f5c055SJed Brown             }
3089b7f5c055SJed Brown           }
3090b7f5c055SJed Brown         }
3091b7f5c055SJed Brown       }
30929566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
30939566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3094b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3095b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3096b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3097b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3098b7f5c055SJed Brown 
3099b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3100b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3101b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3102b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3103b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3104b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3105b7f5c055SJed Brown               }
3106b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3107b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3108b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3109b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3110b7f5c055SJed Brown               }
3111b7f5c055SJed Brown             }
3112b7f5c055SJed Brown           }
3113b7f5c055SJed Brown         }
3114b7f5c055SJed Brown       }
3115b7f5c055SJed Brown     }
3116b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
31174663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3118b7f5c055SJed Brown     break;
3119b7f5c055SJed Brown   }
3120b7f5c055SJed Brown 
31219566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3122c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
31239566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
31249566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3125b7f5c055SJed Brown   {
3126b7f5c055SJed Brown     DM idm;
31279566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
312869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3129b7f5c055SJed Brown   }
3130c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
31319566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
31329566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3133b7f5c055SJed Brown 
31349566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
31359566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3136b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3137b7f5c055SJed Brown     PetscInt        njoin;
3138b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
31399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
314063a3b9bcSJacob 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]);
31419566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
31429566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3143b7f5c055SJed Brown   }
31449566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
31459566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
31461436d7faSJed Brown   if (tps_distribute) {
31471436d7faSJed Brown     DM               pdm = NULL;
31481436d7faSJed Brown     PetscPartitioner part;
31491436d7faSJed Brown 
31509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
31519566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
31529566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
315348a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
31541436d7faSJed Brown     // Do not auto-distribute again
31559566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
31561436d7faSJed Brown   }
3157b7f5c055SJed Brown 
31589566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3159b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3160b7f5c055SJed Brown     PetscInt     m;
3161b7f5c055SJed Brown     DM           dmf;
3162b7f5c055SJed Brown     Vec          X;
3163b7f5c055SJed Brown     PetscScalar *x;
31649566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
316569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3166b7f5c055SJed Brown 
31679566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
31689566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
31699566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
317048a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
31719566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3172b7f5c055SJed Brown   }
3173b7f5c055SJed Brown 
3174b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
31759566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
31769566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3177b7f5c055SJed Brown 
3178b7f5c055SJed Brown   if (thickness > 0) {
31794663dae6SJed Brown     DM              edm, cdm, ecdm;
31804663dae6SJed Brown     DMPlexTransform tr;
31814663dae6SJed Brown     const char     *prefix;
31824663dae6SJed Brown     PetscOptions    options;
31834663dae6SJed Brown     // Code from DMPlexExtrude
31844663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
31854663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
31864663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
31874663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
31884663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
31894663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
31904663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
31914663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
31924663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
31934663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
31944663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
31954663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
31964663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
31974663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
31984663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
31994663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
32004663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
32014663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
32024663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
32034663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
32044663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
32054663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
32064663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
32074663dae6SJed Brown     if (edm) {
32084663dae6SJed Brown       ((DM_Plex *)edm->data)->printFEM    = ((DM_Plex *)dm->data)->printFEM;
32094663dae6SJed Brown       ((DM_Plex *)edm->data)->printL2     = ((DM_Plex *)dm->data)->printL2;
3210f5867de0SMatthew G. Knepley       ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate;
32114663dae6SJed Brown     }
321269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3213b7f5c055SJed Brown   }
3214b7f5c055SJed Brown   PetscFunctionReturn(0);
3215b7f5c055SJed Brown }
3216b7f5c055SJed Brown 
3217b7f5c055SJed Brown /*@
3218b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3219b7f5c055SJed Brown 
3220b7f5c055SJed Brown   Collective
3221b7f5c055SJed Brown 
3222b7f5c055SJed Brown   Input Parameters:
3223b7f5c055SJed Brown + comm   - The communicator for the DM object
3224b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
3225b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
3226b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
32271436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3228817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
32291436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
3230817da375SSatish Balay - thickness - Thickness in normal direction
3231b7f5c055SJed Brown 
3232b7f5c055SJed Brown   Output Parameter:
3233b7f5c055SJed Brown . dm  - The DM object
3234b7f5c055SJed Brown 
3235b7f5c055SJed Brown   Notes:
3236b7f5c055SJed 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.
3237b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
3238b7f5c055SJed 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.
3239b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3240b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3241b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3242b7f5c055SJed Brown 
3243b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
3244b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
3245b7f5c055SJed Brown 
3246b7f5c055SJed Brown   References:
3247606c0280SSatish 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
3248b7f5c055SJed Brown 
3249b7f5c055SJed Brown   Developer Notes:
3250b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3251b7f5c055SJed Brown 
3252b7f5c055SJed Brown   Level: beginner
3253b7f5c055SJed Brown 
3254db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3255b7f5c055SJed Brown @*/
3256d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm)
3257d71ae5a4SJacob Faibussowitsch {
3258b7f5c055SJed Brown   PetscFunctionBegin;
32599566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32609566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32619566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
3262b7f5c055SJed Brown   PetscFunctionReturn(0);
3263b7f5c055SJed Brown }
3264b7f5c055SJed Brown 
32659318fe57SMatthew G. Knepley /*@
32669318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
32679318fe57SMatthew G. Knepley 
32689318fe57SMatthew G. Knepley   Collective
32699318fe57SMatthew G. Knepley 
32709318fe57SMatthew G. Knepley   Input Parameters:
32719318fe57SMatthew G. Knepley + comm    - The communicator for the DM object
32729318fe57SMatthew G. Knepley . dim     - The dimension
32739318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
32749318fe57SMatthew G. Knepley - R       - The radius
32759318fe57SMatthew G. Knepley 
32769318fe57SMatthew G. Knepley   Output Parameter:
32779318fe57SMatthew G. Knepley . dm  - The DM object
32789318fe57SMatthew G. Knepley 
32799318fe57SMatthew G. Knepley   Level: beginner
32809318fe57SMatthew G. Knepley 
3281db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
32829318fe57SMatthew G. Knepley @*/
3283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
3284d71ae5a4SJacob Faibussowitsch {
32859318fe57SMatthew G. Knepley   PetscFunctionBegin;
32869318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
32879566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32889566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32899566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
32909318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
32919318fe57SMatthew G. Knepley }
32929318fe57SMatthew G. Knepley 
3293d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
3294d71ae5a4SJacob Faibussowitsch {
32959318fe57SMatthew G. Knepley   DM      sdm, vol;
32969318fe57SMatthew G. Knepley   DMLabel bdlabel;
32979318fe57SMatthew G. Knepley 
32989318fe57SMatthew G. Knepley   PetscFunctionBegin;
32999566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
33009566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
33019566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_"));
33029566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
33039566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
33049566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
33059566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
33069566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
330769d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
33089566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
33099566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
33109566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
33119566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
331251a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
331351a74b61SMatthew G. Knepley }
331451a74b61SMatthew G. Knepley 
331551a74b61SMatthew G. Knepley /*@
331651a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
331751a74b61SMatthew G. Knepley 
331851a74b61SMatthew G. Knepley   Collective
331951a74b61SMatthew G. Knepley 
332051a74b61SMatthew G. Knepley   Input Parameters:
332151a74b61SMatthew G. Knepley + comm  - The communicator for the DM object
332251a74b61SMatthew G. Knepley . dim   - The dimension
332351a74b61SMatthew G. Knepley - R     - The radius
332451a74b61SMatthew G. Knepley 
332551a74b61SMatthew G. Knepley   Output Parameter:
332651a74b61SMatthew G. Knepley . dm  - The DM object
332751a74b61SMatthew G. Knepley 
332851a74b61SMatthew G. Knepley   Options Database Keys:
332951a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
333051a74b61SMatthew G. Knepley 
333151a74b61SMatthew G. Knepley   Level: beginner
333251a74b61SMatthew G. Knepley 
3333db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
333451a74b61SMatthew G. Knepley @*/
3335d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
3336d71ae5a4SJacob Faibussowitsch {
333751a74b61SMatthew G. Knepley   PetscFunctionBegin;
33389566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
33399566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
33409566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
33412829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
33422829fed8SMatthew G. Knepley }
33432829fed8SMatthew G. Knepley 
3344d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
3345d71ae5a4SJacob Faibussowitsch {
33460a6ba040SMatthew G. Knepley   PetscFunctionBegin;
33479318fe57SMatthew G. Knepley   switch (ct) {
33489371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
33499318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
33509318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
33519318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
33529318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
33539318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
33549318fe57SMatthew G. Knepley 
33559566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
33569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33579371c9d4SSatish Balay   } break;
33589371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
33599318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
33609318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
33619318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
33629318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
33639318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
33649318fe57SMatthew G. Knepley 
33659566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33679371c9d4SSatish Balay   } break;
33689371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3369b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3370b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3371b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3372b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3373b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3374b5a892a1SMatthew G. Knepley 
33759566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33769566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33779371c9d4SSatish Balay   } break;
33789371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
33799318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
33809318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
33819318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
33829318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
33839318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
33849318fe57SMatthew G. Knepley 
33859566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33869566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33879371c9d4SSatish Balay   } break;
33889371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
33899318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33909318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
33919318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
33929318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
33939318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
33949318fe57SMatthew G. Knepley 
33959566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33979371c9d4SSatish Balay   } break;
33989371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
33999318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34009318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34019318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34029318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34039318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
34049318fe57SMatthew G. Knepley 
34059566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34079371c9d4SSatish Balay   } break;
34089371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
34099318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34109318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3411f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34129318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3413f0edb160SMatthew 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};
34149318fe57SMatthew G. Knepley 
34159566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34169566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34179371c9d4SSatish Balay   } break;
34189371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
34199318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34209318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3421f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34229318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34239371c9d4SSatish 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};
34249318fe57SMatthew G. Knepley 
34259566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34269566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34279371c9d4SSatish Balay   } break;
34289371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
34299318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34309318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3431f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34329318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34339371c9d4SSatish 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};
34349318fe57SMatthew G. Knepley 
34359566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34369566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34379371c9d4SSatish Balay   } break;
34389371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
34399318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34409318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
34419318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34429318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34439371c9d4SSatish Balay     PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0};
34449318fe57SMatthew G. Knepley 
34459566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34479371c9d4SSatish Balay   } break;
34489371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
34499318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34509318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
34519318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34529318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34539371c9d4SSatish 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};
34549318fe57SMatthew G. Knepley 
34559566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34579371c9d4SSatish Balay   } break;
34589371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
34599318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
34609318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3461f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
34629318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34639371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0};
34649318fe57SMatthew G. Knepley 
34659566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34679371c9d4SSatish Balay   } break;
3468d71ae5a4SJacob Faibussowitsch   default:
3469d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
34709318fe57SMatthew G. Knepley   }
34719318fe57SMatthew G. Knepley   {
34729318fe57SMatthew G. Knepley     PetscInt Nv, v;
34739318fe57SMatthew G. Knepley 
34749318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
34759566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
34769566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
34779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
34789566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
34799318fe57SMatthew G. Knepley   }
34809566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
34819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
34820a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
34830a6ba040SMatthew G. Knepley }
34840a6ba040SMatthew G. Knepley 
34859318fe57SMatthew G. Knepley /*@
34869318fe57SMatthew G. Knepley   DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell
34879318fe57SMatthew G. Knepley 
34889318fe57SMatthew G. Knepley   Collective
34899318fe57SMatthew G. Knepley 
34909318fe57SMatthew G. Knepley   Input Parameters:
34919318fe57SMatthew G. Knepley + comm - The communicator
34929318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
34939318fe57SMatthew G. Knepley 
34949318fe57SMatthew G. Knepley   Output Parameter:
34959318fe57SMatthew G. Knepley . refdm - The reference cell
34969318fe57SMatthew G. Knepley 
34979318fe57SMatthew G. Knepley   Level: intermediate
34989318fe57SMatthew G. Knepley 
3499db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()`
35009318fe57SMatthew G. Knepley @*/
3501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
3502d71ae5a4SJacob Faibussowitsch {
35030a6ba040SMatthew G. Knepley   PetscFunctionBegin;
35049566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
35059566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
35069566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
35079318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35089318fe57SMatthew G. Knepley }
350979a015ccSMatthew G. Knepley 
3510d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
3511d71ae5a4SJacob Faibussowitsch {
35129318fe57SMatthew G. Knepley   DM        plex;
35139318fe57SMatthew G. Knepley   DMLabel   label;
35149318fe57SMatthew G. Knepley   PetscBool hasLabel;
35150a6ba040SMatthew G. Knepley 
3516c22d3578SMatthew G. Knepley   PetscFunctionBegin;
35179566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
35189318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
35199566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
35209566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
35219566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
35229566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
35231c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
35249566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
35259318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35269318fe57SMatthew G. Knepley }
3527acdc6f61SToby Isaac 
3528669647acSMatthew G. Knepley /*
3529669647acSMatthew G. Knepley   We use the last coordinate as the radius, the inner radius is lower[dim-1] and the outer radius is upper[dim-1]. Then we map the first coordinate around the circle.
3530669647acSMatthew G. Knepley 
3531669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
3532669647acSMatthew G. Knepley */
3533d71ae5a4SJacob Faibussowitsch static void boxToAnnulus(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
3534d71ae5a4SJacob Faibussowitsch {
3535669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
3536669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
3537669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
3538669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
3539669647acSMatthew G. Knepley 
3540669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
3541669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
3542669647acSMatthew G. Knepley }
3543669647acSMatthew G. Knepley 
3544669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
35459318fe57SMatthew G. Knepley 
3546d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
3547d71ae5a4SJacob Faibussowitsch {
35489318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
35499318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
35509318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
35519318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3552cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
35539318fe57SMatthew G. Knepley   MPI_Comm       comm;
3554ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3555ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3556ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
35579318fe57SMatthew G. Knepley 
35589318fe57SMatthew G. Knepley   PetscFunctionBegin;
35599566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
35609318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
35619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
35629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
35639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
35649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
35659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
35669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
35679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
356863a3b9bcSJacob Faibussowitsch   PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim);
35699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
35709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
35719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
35729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
35739566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
35749318fe57SMatthew G. Knepley 
357561a622f3SMatthew G. Knepley   switch (cell) {
357661a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
357761a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
357861a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
357961a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
358061a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
358161a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
3582d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
3583d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
3584d71ae5a4SJacob Faibussowitsch     break;
3585d71ae5a4SJacob Faibussowitsch   default:
3586d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
3587d71ae5a4SJacob Faibussowitsch     break;
358861a622f3SMatthew G. Knepley   }
358961a622f3SMatthew G. Knepley 
35909318fe57SMatthew G. Knepley   if (fflg) {
35919318fe57SMatthew G. Knepley     DM dmnew;
35929318fe57SMatthew G. Knepley 
35939566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew));
35945de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
359569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
35969318fe57SMatthew G. Knepley   } else if (refDomain) {
35979566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
35989318fe57SMatthew G. Knepley   } else if (bdfflg) {
35999318fe57SMatthew G. Knepley     DM bdm, dmnew;
36009318fe57SMatthew G. Knepley 
36019566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm));
36029566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
36039566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
36049566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
36059566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
36065de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
360769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36089318fe57SMatthew G. Knepley   } else {
36099566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
36109318fe57SMatthew G. Knepley     switch (shape) {
3611669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
3612669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
36139318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
36149318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
36159318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
36169318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3617669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
36189318fe57SMatthew G. Knepley       PetscInt       i, n;
36199318fe57SMatthew G. Knepley 
36209318fe57SMatthew G. Knepley       n = dim;
36219318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
36229566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36239318fe57SMatthew G. Knepley       n = 3;
36249566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
362563a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36269318fe57SMatthew G. Knepley       n = 3;
36279566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
362863a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36299318fe57SMatthew G. Knepley       n = 3;
36309566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
363163a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
3632669647acSMatthew G. Knepley 
3633669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
3634669647acSMatthew G. Knepley       if (isAnnular)
3635669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
3636669647acSMatthew G. Knepley 
36379318fe57SMatthew G. Knepley       switch (cell) {
363861a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
36399566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3640d410b0cfSMatthew G. Knepley         if (!interpolate) {
3641d410b0cfSMatthew G. Knepley           DM udm;
3642d410b0cfSMatthew G. Knepley 
36439566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
364469d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
3645d410b0cfSMatthew G. Knepley         }
36469318fe57SMatthew G. Knepley         break;
3647d71ae5a4SJacob Faibussowitsch       default:
3648d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate));
3649d71ae5a4SJacob Faibussowitsch         break;
36509318fe57SMatthew G. Knepley       }
3651669647acSMatthew G. Knepley       if (isAnnular) {
3652669647acSMatthew G. Knepley         DM          cdm;
3653669647acSMatthew G. Knepley         PetscDS     cds;
3654669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
3655669647acSMatthew G. Knepley 
3656669647acSMatthew G. Knepley         // Fix coordinates for annular region
3657669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
3658669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
3659669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
3660669647acSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL));
3661669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
3662669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
3663669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
3664669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
3665669647acSMatthew G. Knepley       }
36669371c9d4SSatish Balay     } break;
36679371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
36689318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
36699318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
36709318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
36719318fe57SMatthew G. Knepley       PetscInt  i, n;
36729318fe57SMatthew G. Knepley 
36739318fe57SMatthew G. Knepley       n = dim + 1;
36749318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
36759566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36769318fe57SMatthew G. Knepley       n = 3;
36779566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
367863a3b9bcSJacob 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);
36799318fe57SMatthew G. Knepley       n = 3;
36809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
368163a3b9bcSJacob 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);
36829566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
36839371c9d4SSatish Balay     } break;
36849371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
36859318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36869318fe57SMatthew G. Knepley 
36879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
36889566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
36899371c9d4SSatish Balay     } break;
36909371c9d4SSatish Balay     case DM_SHAPE_BALL: {
36919318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36929318fe57SMatthew G. Knepley 
36939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
36949566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
36959371c9d4SSatish Balay     } break;
36969371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
36979318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
36989318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
36999318fe57SMatthew G. Knepley 
37009566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
37019566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
37029318fe57SMatthew G. Knepley       switch (cell) {
3703d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
3704d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
3705d71ae5a4SJacob Faibussowitsch         break;
3706d71ae5a4SJacob Faibussowitsch       default:
3707d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt));
3708d71ae5a4SJacob Faibussowitsch         break;
37099318fe57SMatthew G. Knepley       }
37109371c9d4SSatish Balay     } break;
3711b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
37129371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
3713b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
3714b7f5c055SJed Brown       PetscReal      thickness   = 0.;
3715b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3716b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
37171436d7faSJed Brown       PetscBool      tps_distribute;
37189566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
37199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
37209566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
37219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
37229566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
37239566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
37249566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
37259566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
37269371c9d4SSatish Balay     } break;
37279371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
372805bd46c0SStefano Zampini       DM        dmnew;
372905bd46c0SStefano Zampini       PetscReal rl = 0.0;
373005bd46c0SStefano Zampini 
373105bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
373205bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
37335de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
373469d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
37359371c9d4SSatish Balay     } break;
3736d71ae5a4SJacob Faibussowitsch     default:
3737d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
37389318fe57SMatthew G. Knepley     }
37399318fe57SMatthew G. Knepley   }
37409566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
374148a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
37420a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
37430a6ba040SMatthew G. Knepley }
37440a6ba040SMatthew G. Knepley 
3745d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3746d71ae5a4SJacob Faibussowitsch {
37470a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
37487f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
37499318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
37500a6ba040SMatthew G. Knepley 
37510a6ba040SMatthew G. Knepley   PetscFunctionBegin;
37520a6ba040SMatthew G. Knepley   /* Handle viewing */
37539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
37549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
37559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
37569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
3757f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
37589566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
37599566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
37609318fe57SMatthew G. Knepley   /* Labeling */
37619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
37629566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3763953fc75cSMatthew G. Knepley   /* Point Location */
37649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
37650848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
37669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
37672e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
37689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3769b29cfa1cSToby Isaac   /* Projection behavior */
3770d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
37719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3772f12cf164SMatthew G. Knepley   /* Checking structure */
3773f12cf164SMatthew G. Knepley   {
37747f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
3775f12cf164SMatthew G. Knepley 
37767f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
37777f9d8d6cSVaclav Hapla     if (all) {
37787f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
37797f9d8d6cSVaclav Hapla     } else {
37809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
37817f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
37829566063dSJacob 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));
37837f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
37849566063dSJacob 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));
37857f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
37869566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
37877f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
37889566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
3789d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
37909566063dSJacob 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));
37917f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
37927f9d8d6cSVaclav Hapla     }
37939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
37949566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3795f12cf164SMatthew G. Knepley   }
37969318fe57SMatthew G. Knepley   {
37979318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
37984f3833eaSMatthew G. Knepley 
37999566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
38009318fe57SMatthew G. Knepley     if (flg) {
38019318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
38029318fe57SMatthew G. Knepley 
38039566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
38049566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
38059566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
38069566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
38079318fe57SMatthew G. Knepley     }
38089318fe57SMatthew G. Knepley   }
38099566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
381068d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
381168d4fef7SMatthew G. Knepley }
381268d4fef7SMatthew G. Knepley 
3813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
3814d71ae5a4SJacob Faibussowitsch {
3815c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
3816c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
3817c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
3818c506a872SMatthew G. Knepley   PetscBool flg;
3819c506a872SMatthew G. Knepley 
3820c506a872SMatthew G. Knepley   PetscFunctionBegin;
3821c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
3822c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
3823c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
3824c506a872SMatthew G. Knepley   if (numOvLabels) {
3825c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
3826c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
3827c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
3828c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
3829c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
3830c506a872SMatthew G. Knepley     }
3831c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
3832c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
3833c506a872SMatthew 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);
3834c506a872SMatthew G. Knepley 
3835c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
3836c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
3837c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
3838c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
3839c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
3840c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
3841c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
3842c506a872SMatthew G. Knepley     }
3843c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
3844c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
3845c506a872SMatthew 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);
3846c506a872SMatthew G. Knepley   }
3847c506a872SMatthew G. Knepley   PetscFunctionReturn(0);
3848c506a872SMatthew G. Knepley }
3849c506a872SMatthew G. Knepley 
3850d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3851d71ae5a4SJacob Faibussowitsch {
3852bdf63967SMatthew G. Knepley   PetscFunctionList        ordlist;
3853bdf63967SMatthew G. Knepley   char                     oname[256];
3854d410b0cfSMatthew G. Knepley   PetscReal                volume    = -1.0;
38559318fe57SMatthew G. Knepley   PetscInt                 prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3856e600fa54SMatthew 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;
38576bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
385868d4fef7SMatthew G. Knepley 
385968d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3860d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
3861*dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
38629318fe57SMatthew G. Knepley   /* Handle automatic creation */
38639566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
38646bc1bd01Sksagiyam   if (dim < 0) {
38656bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
38666bc1bd01Sksagiyam     created = PETSC_TRUE;
38676bc1bd01Sksagiyam   }
38686bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
3869d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
38709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3871d89e6e46SMatthew G. Knepley   if (flg) {
3872d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3873d89e6e46SMatthew G. Knepley 
38749566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
3875d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3876d89e6e46SMatthew G. Knepley       DM udm;
3877d89e6e46SMatthew G. Knepley 
38789566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
387969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
3880d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3881d89e6e46SMatthew G. Knepley       DM idm;
3882d89e6e46SMatthew G. Knepley 
38839566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
388469d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
3885d89e6e46SMatthew G. Knepley     }
3886d89e6e46SMatthew G. Knepley   }
38879b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
38889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3889ad540459SPierre Jolivet   if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel;
38909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
38919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
38929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
38939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
38949566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
38959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
38969318fe57SMatthew G. Knepley   if (flg) {
38979566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
38989566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
38999318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
39009318fe57SMatthew G. Knepley   }
39019b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
39029b44eab4SMatthew G. Knepley     DM             rdm;
39039b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
39049b44eab4SMatthew G. Knepley 
3905dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39069566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
390769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
3908dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
390961a622f3SMatthew G. Knepley     if (coordFunc && remap) {
39109566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
39119b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
39129b44eab4SMatthew G. Knepley     }
39139b44eab4SMatthew G. Knepley   }
39149566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
39159318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
39169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
39179318fe57SMatthew G. Knepley   if (extLayers) {
39189318fe57SMatthew G. Knepley     DM edm;
39199318fe57SMatthew G. Knepley 
39209566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
392169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
392248d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
3923dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3924d410b0cfSMatthew G. Knepley     extLayers = 0;
39255e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
39269318fe57SMatthew G. Knepley   }
3927bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
39286bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
39299566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
39306bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
39319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
39326bc1bd01Sksagiyam   if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) {
3933bdf63967SMatthew G. Knepley     DM pdm;
3934bdf63967SMatthew G. Knepley     IS perm;
3935bdf63967SMatthew G. Knepley 
39369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
39379566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
39389566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
393969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
3940dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3941bdf63967SMatthew G. Knepley   }
39429b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
39439566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
3944c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
3945dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
39469b44eab4SMatthew G. Knepley   if (distribute) {
39479b44eab4SMatthew G. Knepley     DM               pdm = NULL;
39489b44eab4SMatthew G. Knepley     PetscPartitioner part;
39499b44eab4SMatthew G. Knepley 
39509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
39519566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
39529566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm));
395348a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
39549b44eab4SMatthew G. Knepley   }
39559318fe57SMatthew G. Knepley   /* Create coordinate space */
39569318fe57SMatthew G. Knepley   if (created) {
395761a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
39589318fe57SMatthew G. Knepley     PetscInt  degree = 1;
39596858538eSMatthew G. Knepley     PetscBool flg;
39609318fe57SMatthew G. Knepley 
39619566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
39629566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
39639566063dSJacob Faibussowitsch     if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
396461a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
396561a622f3SMatthew G. Knepley       DM           cdm;
396661a622f3SMatthew G. Knepley       PetscDS      cds;
396761a622f3SMatthew G. Knepley       PetscObject  obj;
396861a622f3SMatthew G. Knepley       PetscClassId id;
396961a622f3SMatthew G. Knepley 
39709566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDM(dm, &cdm));
39719566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
39729566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
39739566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
397461a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
397561a622f3SMatthew G. Knepley         PetscContainer dummy;
397661a622f3SMatthew G. Knepley 
39779566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
39789566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
39799566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
39809566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
39819566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
398261a622f3SMatthew G. Knepley       }
398361a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
398461a622f3SMatthew G. Knepley     }
39856858538eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg));
39869566063dSJacob Faibussowitsch     PetscCall(DMLocalizeCoordinates(dm));
39879318fe57SMatthew G. Knepley   }
398868d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
398961a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
39909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
39919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
39929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
39939566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
399468d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
3995acdc6f61SToby Isaac     DM *dms, coarseDM;
399668d4fef7SMatthew G. Knepley 
39979566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
39989566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
39999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
40009566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
400168d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
40029566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
400368d4fef7SMatthew G. Knepley     if (refine == 1) {
40049566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
40059566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
400668d4fef7SMatthew G. Knepley     } else {
40079566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
40089566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
40099566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
40109566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
401168d4fef7SMatthew G. Knepley     }
40129566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
40139566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
401468d4fef7SMatthew G. Knepley     /* Free DMs */
401568d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
4016dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40179566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
401868d4fef7SMatthew G. Knepley     }
40199566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
402068d4fef7SMatthew G. Knepley   } else {
402168d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
40229318fe57SMatthew G. Knepley       DM             rdm;
402351a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
402468d4fef7SMatthew G. Knepley 
4025dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40269566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
402768d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
402869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
4029dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
403061a622f3SMatthew G. Knepley       if (coordFunc && remap) {
40319566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
403251a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
403351a74b61SMatthew G. Knepley       }
403468d4fef7SMatthew G. Knepley     }
403568d4fef7SMatthew G. Knepley   }
40363cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
40379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
40389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
4039b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
4040b653a561SMatthew G. Knepley     DM *dms;
4041b653a561SMatthew G. Knepley 
40429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
40439566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
4044b653a561SMatthew G. Knepley     /* Free DMs */
4045b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
4046dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40479566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
4048b653a561SMatthew G. Knepley     }
40499566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
4050b653a561SMatthew G. Knepley   } else {
4051b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
40529318fe57SMatthew G. Knepley       DM             cdm;
40539318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
40543cf6fe12SMatthew G. Knepley 
4055dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40569566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
40573cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
405869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
4059dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40609318fe57SMatthew G. Knepley       if (coordFunc) {
40619566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
40629318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
40639318fe57SMatthew G. Knepley       }
40643cf6fe12SMatthew G. Knepley     }
4065b653a561SMatthew G. Knepley   }
4066909dfd52SMatthew G. Knepley   /* Handle ghost cells */
40679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
4068909dfd52SMatthew G. Knepley   if (ghostCells) {
4069909dfd52SMatthew G. Knepley     DM   gdm;
4070909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
4071909dfd52SMatthew G. Knepley 
4072909dfd52SMatthew G. Knepley     lname[0] = '\0';
40739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
40749566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
407569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
4076909dfd52SMatthew G. Knepley   }
40776913077dSMatthew G. Knepley   /* Handle 1D order */
40786bc1bd01Sksagiyam   if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) {
40796913077dSMatthew G. Knepley     DM           cdm, rdm;
40806913077dSMatthew G. Knepley     PetscDS      cds;
40816913077dSMatthew G. Knepley     PetscObject  obj;
40826913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
40836913077dSMatthew G. Knepley     IS           perm;
40846bc1bd01Sksagiyam     PetscInt     Nf;
40856913077dSMatthew G. Knepley     PetscBool    distributed;
40866913077dSMatthew G. Knepley 
40879566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
40889566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
40899566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
40909566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
40916913077dSMatthew G. Knepley     if (Nf) {
40929566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
40939566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
40946913077dSMatthew G. Knepley     }
40956bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
40969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
40979566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
409869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
40999566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
41006913077dSMatthew G. Knepley     }
41016913077dSMatthew G. Knepley   }
41023cf6fe12SMatthew G. Knepley /* Handle */
4103*dd4c3f67SMatthew G. Knepley non_refine:
4104dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4105d0609cedSBarry Smith   PetscOptionsHeadEnd();
41060a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
41070a6ba040SMatthew G. Knepley }
41080a6ba040SMatthew G. Knepley 
4109d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
4110d71ae5a4SJacob Faibussowitsch {
4111552f7358SJed Brown   PetscFunctionBegin;
41129566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
41139566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
41149566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
41159566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
41169566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
41179566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
4118552f7358SJed Brown   PetscFunctionReturn(0);
4119552f7358SJed Brown }
4120552f7358SJed Brown 
4121d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
4122d71ae5a4SJacob Faibussowitsch {
4123552f7358SJed Brown   PetscFunctionBegin;
41249566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
41259566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
41269566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
4127552f7358SJed Brown   PetscFunctionReturn(0);
4128552f7358SJed Brown }
4129552f7358SJed Brown 
4130d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4131d71ae5a4SJacob Faibussowitsch {
4132793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4133793f3fe5SMatthew G. Knepley 
4134793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
41359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4136793f3fe5SMatthew G. Knepley   if (depth == 1) {
41379566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
41389566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
41399566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
41409371c9d4SSatish Balay     else {
41419371c9d4SSatish Balay       *pStart = 0;
41429371c9d4SSatish Balay       *pEnd   = 0;
41439371c9d4SSatish Balay     }
4144793f3fe5SMatthew G. Knepley   } else {
41459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4146793f3fe5SMatthew G. Knepley   }
4147793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
4148793f3fe5SMatthew G. Knepley }
4149793f3fe5SMatthew G. Knepley 
4150d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
4151d71ae5a4SJacob Faibussowitsch {
4152502a2867SDave May   PetscSF            sf;
41530a19bb7dSprj-   PetscInt           niranks, njranks, n;
41540a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
41550a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4156502a2867SDave May 
41572f356facSMatthew G. Knepley   PetscFunctionBegin;
41589566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
41590a19bb7dSprj-   if (!data->neighbors) {
41609566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
41619566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
41629566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
41639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
41649566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
41659566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
41660a19bb7dSprj-     n = njranks + niranks;
41679566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
41680a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
41699566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
41700a19bb7dSprj-   }
41710a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
41720a19bb7dSprj-   if (ranks) {
41730a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
41740a19bb7dSprj-     else *ranks = NULL;
41750a19bb7dSprj-   }
4176502a2867SDave May   PetscFunctionReturn(0);
4177502a2867SDave May }
4178502a2867SDave May 
41791eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
41801eb70e55SToby Isaac 
4181d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
4182d71ae5a4SJacob Faibussowitsch {
4183552f7358SJed Brown   PetscFunctionBegin;
4184552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
41852c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
4186552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
418738221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
4188552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
41891bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
419066ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
4191552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
4192552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
4193184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
41940298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
4195552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
4196f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
41970a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
4198552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
4199bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
4200bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
4201b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
42025a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
4203552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
42040a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
42050a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
4206b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
4207d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
42080298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
42090298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
42100298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
42110298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
4212552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
4213552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
42142adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
4215793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
4216552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
42170709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
42180709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
4219bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
42208c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
4221ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
42220709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
4223b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
42242a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
422528d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
42269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
42279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
42289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
42299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
42309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
42319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
42329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
42336bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
42346bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
42359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
4236c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
4237c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
4238552f7358SJed Brown   PetscFunctionReturn(0);
4239552f7358SJed Brown }
4240552f7358SJed Brown 
4241d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
4242d71ae5a4SJacob Faibussowitsch {
424363a16f15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
424463a16f15SMatthew G. Knepley 
424563a16f15SMatthew G. Knepley   PetscFunctionBegin;
424663a16f15SMatthew G. Knepley   mesh->refct++;
424763a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
42489566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
42499566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
425063a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
425163a16f15SMatthew G. Knepley }
425263a16f15SMatthew G. Knepley 
42538818961aSMatthew G Knepley /*MC
42548818961aSMatthew G Knepley   DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
42558818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
42568818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
42578818961aSMatthew G Knepley                     ownership of the underlying DMPlex points. This is specified by another PetscSection object.
42588818961aSMatthew G Knepley 
4259e5893cccSMatthew G. Knepley   Options Database Keys:
4260250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
4261250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
4262250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
4263250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
4264250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
4265250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
4266250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
4267ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
4268f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
4269f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
4270d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
4271f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
4272250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
4273f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
4274f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
4275f12cf164SMatthew 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
4276f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
4277f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
4278e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
4279e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
4280e5893cccSMatthew G. Knepley 
42818818961aSMatthew G Knepley   Level: intermediate
42828818961aSMatthew G Knepley 
4283db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`
42848818961aSMatthew G Knepley M*/
42858818961aSMatthew G Knepley 
4286d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
4287d71ae5a4SJacob Faibussowitsch {
4288552f7358SJed Brown   DM_Plex *mesh;
4289412e9a14SMatthew G. Knepley   PetscInt unit;
4290552f7358SJed Brown 
4291552f7358SJed Brown   PetscFunctionBegin;
4292552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42934dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
4294552f7358SJed Brown   dm->data = mesh;
4295552f7358SJed Brown 
4296552f7358SJed Brown   mesh->refct = 1;
42979566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
42989566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
4299552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
4300552f7358SJed Brown   mesh->refinementLimit        = -1.0;
4301e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
43026bc1bd01Sksagiyam   mesh->reorderDefault         = DMPLEX_REORDER_DEFAULT_NOTSET;
43031d1f2f2aSksagiyam   mesh->distributionName       = NULL;
43047d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
43057d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
4306552f7358SJed Brown 
43079566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
43082e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
4309d9deefdfSMatthew G. Knepley 
43108865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
4311552f7358SJed Brown 
4312df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
4313ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
43146113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
4315552f7358SJed Brown 
43169566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
4317552f7358SJed Brown   PetscFunctionReturn(0);
4318552f7358SJed Brown }
4319552f7358SJed Brown 
4320552f7358SJed Brown /*@
4321552f7358SJed Brown   DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
4322552f7358SJed Brown 
4323d083f849SBarry Smith   Collective
4324552f7358SJed Brown 
4325552f7358SJed Brown   Input Parameter:
4326552f7358SJed Brown . comm - The communicator for the DMPlex object
4327552f7358SJed Brown 
4328552f7358SJed Brown   Output Parameter:
4329552f7358SJed Brown . mesh  - The DMPlex object
4330552f7358SJed Brown 
4331552f7358SJed Brown   Level: beginner
4332552f7358SJed Brown 
4333552f7358SJed Brown @*/
4334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
4335d71ae5a4SJacob Faibussowitsch {
4336552f7358SJed Brown   PetscFunctionBegin;
4337552f7358SJed Brown   PetscValidPointer(mesh, 2);
43389566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
43399566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
4340552f7358SJed Brown   PetscFunctionReturn(0);
4341552f7358SJed Brown }
4342552f7358SJed Brown 
4343b09969d6SVaclav Hapla /*@C
4344b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output)
4345b09969d6SVaclav Hapla 
4346b09969d6SVaclav Hapla   Input Parameters:
4347b09969d6SVaclav Hapla + dm - The DM
4348b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4349325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE
4350325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE
4351b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
43525e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4353b09969d6SVaclav Hapla 
4354be8c289dSNicolas Barral   Output Parameters:
4355be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership
4356be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4357b09969d6SVaclav Hapla 
4358b09969d6SVaclav Hapla   Notes:
4359b09969d6SVaclav Hapla   Two triangles sharing a face
4360b09969d6SVaclav Hapla $
4361b09969d6SVaclav Hapla $        2
4362b09969d6SVaclav Hapla $      / | \
4363b09969d6SVaclav Hapla $     /  |  \
4364b09969d6SVaclav Hapla $    /   |   \
4365b09969d6SVaclav Hapla $   0  0 | 1  3
4366b09969d6SVaclav Hapla $    \   |   /
4367b09969d6SVaclav Hapla $     \  |  /
4368b09969d6SVaclav Hapla $      \ | /
4369b09969d6SVaclav Hapla $        1
4370b09969d6SVaclav Hapla would have input
4371b09969d6SVaclav Hapla $  numCells = 2, numVertices = 4
4372b09969d6SVaclav Hapla $  cells = [0 1 2  1 3 2]
4373b09969d6SVaclav Hapla $
4374b09969d6SVaclav Hapla which would result in the DMPlex
4375b09969d6SVaclav Hapla $
4376b09969d6SVaclav Hapla $        4
4377b09969d6SVaclav Hapla $      / | \
4378b09969d6SVaclav Hapla $     /  |  \
4379b09969d6SVaclav Hapla $    /   |   \
4380b09969d6SVaclav Hapla $   2  0 | 1  5
4381b09969d6SVaclav Hapla $    \   |   /
4382b09969d6SVaclav Hapla $     \  |  /
4383b09969d6SVaclav Hapla $      \ | /
4384b09969d6SVaclav Hapla $        3
4385b09969d6SVaclav Hapla 
438625b6865aSVaclav Hapla   Vertices are implicitly numbered consecutively 0,...,NVertices.
438725b6865aSVaclav Hapla   Each rank owns a chunk of numVertices consecutive vertices.
438825b6865aSVaclav Hapla   If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout.
4389325d53feSBarry Smith   If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
4390325d53feSBarry Smith   If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks.
439125b6865aSVaclav Hapla 
4392b09969d6SVaclav Hapla   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
4393b09969d6SVaclav Hapla 
4394b09969d6SVaclav Hapla   Not currently supported in Fortran.
4395b09969d6SVaclav Hapla 
4396b09969d6SVaclav Hapla   Level: advanced
4397b09969d6SVaclav Hapla 
4398db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`
4399b09969d6SVaclav Hapla @*/
4400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
4401d71ae5a4SJacob Faibussowitsch {
44022464107aSksagiyam   PetscSF     sfPoint;
44032464107aSksagiyam   PetscLayout layout;
440482fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
4405a47d0d45SMatthew G. Knepley 
4406a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
440725b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
44089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
440925b6865aSVaclav Hapla   /* Get/check global number of vertices */
441025b6865aSVaclav Hapla   {
441125b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
441225b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
441325b6865aSVaclav Hapla 
441425b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
441525b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
44169371c9d4SSatish Balay     for (i = 0; i < len; i++)
44179371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
441825b6865aSVaclav Hapla     ++NVerticesInCells;
44199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
442025b6865aSVaclav Hapla 
442125b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
44229371c9d4SSatish Balay     else
44239371c9d4SSatish 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);
442425b6865aSVaclav Hapla   }
44259079aca8SVaclav Hapla   /* Count locally unique vertices */
44269079aca8SVaclav Hapla   {
44279079aca8SVaclav Hapla     PetscHSetI vhash;
44289079aca8SVaclav Hapla     PetscInt   off = 0;
44299079aca8SVaclav Hapla 
44309566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
4431a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
443248a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
4433a47d0d45SMatthew G. Knepley     }
44349566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
44359566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
4436ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
44379566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
44389566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
443963a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
4440a47d0d45SMatthew G. Knepley   }
44419566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
4442a47d0d45SMatthew G. Knepley   /* Create cones */
44439566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
44449566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
44459566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
44469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4447a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
4448a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
4449a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
4450a47d0d45SMatthew G. Knepley       PetscInt       lv;
4451a47d0d45SMatthew G. Knepley 
44529079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
44539079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
44549566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
445563a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
4456961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
4457a47d0d45SMatthew G. Knepley     }
4458a47d0d45SMatthew G. Knepley   }
44592464107aSksagiyam   /* Build point sf */
44609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
44619566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
44629566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
44639566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44649566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
44659566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
44669566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
44679566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
44682464107aSksagiyam   if (dm->sf) {
44692464107aSksagiyam     const char *prefix;
44702464107aSksagiyam 
44719566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
44729566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
44732464107aSksagiyam   }
44749566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
44759566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
44769566063dSJacob Faibussowitsch   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4477a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
44789566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
44799566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
44809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4481a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4482a47d0d45SMatthew G. Knepley }
4483a47d0d45SMatthew G. Knepley 
4484b09969d6SVaclav Hapla /*@C
4485b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4486b09969d6SVaclav Hapla 
4487b09969d6SVaclav Hapla   Input Parameters:
4488b09969d6SVaclav Hapla + dm - The DM
4489b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4490b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership
4491b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4492b09969d6SVaclav Hapla 
4493b09969d6SVaclav Hapla   Level: advanced
4494b09969d6SVaclav Hapla 
4495b09969d6SVaclav Hapla   Notes:
4496b09969d6SVaclav Hapla   Not currently supported in Fortran.
4497b09969d6SVaclav Hapla 
4498db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
4499b09969d6SVaclav Hapla @*/
4500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
4501d71ae5a4SJacob Faibussowitsch {
4502a47d0d45SMatthew G. Knepley   PetscSection coordSection;
4503a47d0d45SMatthew G. Knepley   Vec          coordinates;
4504a47d0d45SMatthew G. Knepley   PetscScalar *coords;
45051edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4506a47d0d45SMatthew G. Knepley 
4507a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
45099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
45101dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
45119566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
45129566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
45131dca8a05SBarry 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);
45149566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
45159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
45169566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
45179566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
45181edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
45199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
45209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4521a47d0d45SMatthew G. Knepley   }
45229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
45239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
45249566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
45259566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
45269566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
45279566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
45289566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
45299566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4530a47d0d45SMatthew G. Knepley   {
4531a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4532a47d0d45SMatthew G. Knepley 
4533a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
45349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
45359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
453621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
453721016a8bSBarry Smith     {
453821016a8bSBarry Smith       PetscScalar *svertexCoords;
453921016a8bSBarry Smith       PetscInt     i;
45409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
45413612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
45429566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45439566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45449566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
454521016a8bSBarry Smith     }
454621016a8bSBarry Smith #else
45479566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
45489566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
454921016a8bSBarry Smith #endif
45509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
4551a47d0d45SMatthew G. Knepley   }
45529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
45539566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
45549566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
45559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4556a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4557a47d0d45SMatthew G. Knepley }
4558a47d0d45SMatthew G. Knepley 
4559c3edce3dSSatish Balay /*@
4560b09969d6SVaclav Hapla   DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output)
4561a47d0d45SMatthew G. Knepley 
4562a47d0d45SMatthew G. Knepley   Input Parameters:
4563a47d0d45SMatthew G. Knepley + comm - The communicator
4564a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4565a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
456625b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE
456725b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE
4568a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4569a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4570a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4571a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4572a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4573a47d0d45SMatthew G. Knepley 
4574d8d19677SJose E. Roman   Output Parameters:
457518d54ad4SMichael Lange + dm - The DM
4576be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership
4577be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4578a47d0d45SMatthew G. Knepley 
4579b09969d6SVaclav Hapla   Notes:
4580b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(),
4581b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel()
4582a47d0d45SMatthew G. Knepley 
458325b6865aSVaclav Hapla   See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters.
458425b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters.
458525b6865aSVaclav Hapla 
4586b09969d6SVaclav Hapla   Level: intermediate
4587a47d0d45SMatthew G. Knepley 
4588db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
4589a47d0d45SMatthew G. Knepley @*/
4590d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
4591d71ae5a4SJacob Faibussowitsch {
4592a47d0d45SMatthew G. Knepley   PetscSF sfVert;
4593a47d0d45SMatthew G. Knepley 
4594a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45959566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
45969566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4597a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4598064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
45999566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
46009566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4601a47d0d45SMatthew G. Knepley   if (interpolate) {
46025fd9971aSMatthew G. Knepley     DM idm;
4603a47d0d45SMatthew G. Knepley 
46049566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
46059566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
4606a47d0d45SMatthew G. Knepley     *dm = idm;
4607a47d0d45SMatthew G. Knepley   }
46089566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
460918d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
46109566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
4611a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4612a47d0d45SMatthew G. Knepley }
4613a47d0d45SMatthew G. Knepley 
4614b09969d6SVaclav Hapla /*@C
4615b09969d6SVaclav Hapla   DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output)
46169298eaa6SMatthew G Knepley 
46179298eaa6SMatthew G Knepley   Input Parameters:
4618b09969d6SVaclav Hapla + dm - The DM
4619b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4620325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE
46219298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
46225e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
46239298eaa6SMatthew G Knepley 
4624b09969d6SVaclav Hapla   Level: advanced
46259298eaa6SMatthew G Knepley 
4626b09969d6SVaclav Hapla   Notes:
4627b09969d6SVaclav Hapla   Two triangles sharing a face
46289298eaa6SMatthew G Knepley $
46299298eaa6SMatthew G Knepley $        2
46309298eaa6SMatthew G Knepley $      / | \
46319298eaa6SMatthew G Knepley $     /  |  \
46329298eaa6SMatthew G Knepley $    /   |   \
46339298eaa6SMatthew G Knepley $   0  0 | 1  3
46349298eaa6SMatthew G Knepley $    \   |   /
46359298eaa6SMatthew G Knepley $     \  |  /
46369298eaa6SMatthew G Knepley $      \ | /
46379298eaa6SMatthew G Knepley $        1
46389298eaa6SMatthew G Knepley would have input
46399298eaa6SMatthew G Knepley $  numCells = 2, numVertices = 4
46409298eaa6SMatthew G Knepley $  cells = [0 1 2  1 3 2]
46419298eaa6SMatthew G Knepley $
46429298eaa6SMatthew G Knepley which would result in the DMPlex
46439298eaa6SMatthew G Knepley $
46449298eaa6SMatthew G Knepley $        4
46459298eaa6SMatthew G Knepley $      / | \
46469298eaa6SMatthew G Knepley $     /  |  \
46479298eaa6SMatthew G Knepley $    /   |   \
46489298eaa6SMatthew G Knepley $   2  0 | 1  5
46499298eaa6SMatthew G Knepley $    \   |   /
46509298eaa6SMatthew G Knepley $     \  |  /
46519298eaa6SMatthew G Knepley $      \ | /
46529298eaa6SMatthew G Knepley $        3
46539298eaa6SMatthew G Knepley 
4654325d53feSBarry Smith   If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1.
465525b6865aSVaclav Hapla 
4656b09969d6SVaclav Hapla   Not currently supported in Fortran.
46579298eaa6SMatthew G Knepley 
4658db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
4659b09969d6SVaclav Hapla @*/
4660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
4661d71ae5a4SJacob Faibussowitsch {
4662961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
4663b09969d6SVaclav Hapla 
4664b09969d6SVaclav Hapla   PetscFunctionBegin;
46659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
46669566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
466725b6865aSVaclav Hapla   /* Get/check global number of vertices */
466825b6865aSVaclav Hapla   {
466925b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
467025b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
467125b6865aSVaclav Hapla 
467225b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
467325b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
46749371c9d4SSatish Balay     for (i = 0; i < len; i++)
46759371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
467625b6865aSVaclav Hapla     ++NVerticesInCells;
467725b6865aSVaclav Hapla 
467825b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
46799371c9d4SSatish Balay     else
46809371c9d4SSatish 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);
468125b6865aSVaclav Hapla   }
46829566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
468348a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
46849566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
46859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4686b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4687ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
4688b09969d6SVaclav Hapla   }
46899566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
46909566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
46919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4692b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4693b09969d6SVaclav Hapla }
4694b09969d6SVaclav Hapla 
4695b09969d6SVaclav Hapla /*@C
4696b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4697b09969d6SVaclav Hapla 
4698b09969d6SVaclav Hapla   Input Parameters:
4699b09969d6SVaclav Hapla + dm - The DM
4700b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4701b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4702b09969d6SVaclav Hapla 
4703b09969d6SVaclav Hapla   Level: advanced
4704b09969d6SVaclav Hapla 
4705b09969d6SVaclav Hapla   Notes:
4706b09969d6SVaclav Hapla   Not currently supported in Fortran.
4707b09969d6SVaclav Hapla 
4708db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
4709b09969d6SVaclav Hapla @*/
4710d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
4711d71ae5a4SJacob Faibussowitsch {
4712b09969d6SVaclav Hapla   PetscSection coordSection;
4713b09969d6SVaclav Hapla   Vec          coordinates;
4714b09969d6SVaclav Hapla   DM           cdm;
4715b09969d6SVaclav Hapla   PetscScalar *coords;
47161edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
4717b09969d6SVaclav Hapla 
4718b09969d6SVaclav Hapla   PetscFunctionBegin;
47199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
47209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
47211dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
47229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
47239566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
47249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
47259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
47269566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
47271edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
47289566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
47299566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4730b09969d6SVaclav Hapla   }
47319566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4732b09969d6SVaclav Hapla 
47339566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
47349566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
47359566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
47369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
47379566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
47381edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
4739ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
4740b09969d6SVaclav Hapla   }
47419566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
47429566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
47439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
47449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4745b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4746b09969d6SVaclav Hapla }
4747b09969d6SVaclav Hapla 
4748b09969d6SVaclav Hapla /*@
47493df08285SMatthew 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
47503df08285SMatthew G. Knepley 
47513df08285SMatthew G. Knepley   Collective on comm
4752b09969d6SVaclav Hapla 
4753b09969d6SVaclav Hapla   Input Parameters:
4754b09969d6SVaclav Hapla + comm - The communicator
4755b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
47563df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
47573df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0
47583df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4759b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
47603df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4761b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
47623df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4763b09969d6SVaclav Hapla 
4764b09969d6SVaclav Hapla   Output Parameter:
47653df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0
4766b09969d6SVaclav Hapla 
4767b09969d6SVaclav Hapla   Notes:
4768b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(),
4769b09969d6SVaclav Hapla   DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList()
4770b09969d6SVaclav Hapla 
477125b6865aSVaclav Hapla   See DMPlexBuildFromCellList() for an example and details about the topology-related parameters.
477225b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters.
47733df08285SMatthew G. Knepley   See DMPlexCreateFromCellListParallelPetsc() for parallel input
477425b6865aSVaclav Hapla 
4775b09969d6SVaclav Hapla   Level: intermediate
4776b09969d6SVaclav Hapla 
4777db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
47789298eaa6SMatthew G Knepley @*/
4779d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], DM *dm)
4780d71ae5a4SJacob Faibussowitsch {
47813df08285SMatthew G. Knepley   PetscMPIInt rank;
47829298eaa6SMatthew G Knepley 
47839298eaa6SMatthew G Knepley   PetscFunctionBegin;
478428b400f6SJacob 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.");
47859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
47869566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
47879566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
47889566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
4789c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
47909566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
47919298eaa6SMatthew G Knepley   if (interpolate) {
47925fd9971aSMatthew G. Knepley     DM idm;
47939298eaa6SMatthew G Knepley 
47949566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
47959566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
47969298eaa6SMatthew G Knepley     *dm = idm;
47979298eaa6SMatthew G Knepley   }
4798c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
47999566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
48009298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
48019298eaa6SMatthew G Knepley }
48029298eaa6SMatthew G Knepley 
4803939f6067SMatthew G. Knepley /*@
4804939f6067SMatthew 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
4805939f6067SMatthew G. Knepley 
4806939f6067SMatthew G. Knepley   Input Parameters:
4807c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4808939f6067SMatthew G. Knepley . depth - The depth of the DAG
4809367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4810939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4811939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4812939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4813367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4814939f6067SMatthew G. Knepley 
4815939f6067SMatthew G. Knepley   Output Parameter:
4816939f6067SMatthew G. Knepley . dm - The DM
4817939f6067SMatthew G. Knepley 
4818939f6067SMatthew G. Knepley   Note: Two triangles sharing a face would have input
4819939f6067SMatthew G. Knepley $  depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4820939f6067SMatthew G. Knepley $  cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4821939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4822939f6067SMatthew G. Knepley $
4823939f6067SMatthew G. Knepley which would result in the DMPlex
4824939f6067SMatthew G. Knepley $
4825939f6067SMatthew G. Knepley $        4
4826939f6067SMatthew G. Knepley $      / | \
4827939f6067SMatthew G. Knepley $     /  |  \
4828939f6067SMatthew G. Knepley $    /   |   \
4829939f6067SMatthew G. Knepley $   2  0 | 1  5
4830939f6067SMatthew G. Knepley $    \   |   /
4831939f6067SMatthew G. Knepley $     \  |  /
4832939f6067SMatthew G. Knepley $      \ | /
4833939f6067SMatthew G. Knepley $        3
4834939f6067SMatthew G. Knepley $
4835a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc()
4836939f6067SMatthew G. Knepley 
4837939f6067SMatthew G. Knepley   Level: advanced
4838939f6067SMatthew G. Knepley 
4839db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
4840939f6067SMatthew G. Knepley @*/
4841d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
4842d71ae5a4SJacob Faibussowitsch {
48439298eaa6SMatthew G Knepley   Vec          coordinates;
48449298eaa6SMatthew G Knepley   PetscSection coordSection;
48459298eaa6SMatthew G Knepley   PetscScalar *coords;
4846811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
48479298eaa6SMatthew G Knepley 
48489298eaa6SMatthew G Knepley   PetscFunctionBegin;
48499566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
48509566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
485163a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
48529298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
48539566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
48549298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
48559566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
4856ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
485797e052ccSToby Isaac   }
48581dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
48599566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
48609298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
48619566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
48629566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
48639298eaa6SMatthew G Knepley   }
48649566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
48659566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
48669298eaa6SMatthew G Knepley   /* Build coordinates */
48679566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
48689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
48699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
48709566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
48719298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
48729566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
48739566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
48749298eaa6SMatthew G Knepley   }
48759566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
48769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
48779566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
48789566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
48799566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
48809566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
48819566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
48829318fe57SMatthew G. Knepley   if (vertexCoords) {
48839566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
48849298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
48859298eaa6SMatthew G Knepley       PetscInt off;
48869298eaa6SMatthew G Knepley 
48879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
4888ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
48899298eaa6SMatthew G Knepley     }
48909318fe57SMatthew G. Knepley   }
48919566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
48929566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
48939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
48949298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
48959298eaa6SMatthew G Knepley }
48968415267dSToby Isaac 
4897ca522641SMatthew G. Knepley /*@C
48988ca92349SMatthew G. Knepley   DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file.
48998ca92349SMatthew G. Knepley 
49008ca92349SMatthew G. Knepley + comm        - The MPI communicator
49018ca92349SMatthew G. Knepley . filename    - Name of the .dat file
49028ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
49038ca92349SMatthew G. Knepley 
49048ca92349SMatthew G. Knepley   Output Parameter:
49058ca92349SMatthew G. Knepley . dm  - The DM object representing the mesh
49068ca92349SMatthew G. Knepley 
49078ca92349SMatthew G. Knepley   Note: The format is the simplest possible:
49088ca92349SMatthew G. Knepley $ Ne
49098ca92349SMatthew G. Knepley $ v0 v1 ... vk
49108ca92349SMatthew G. Knepley $ Nv
49118ca92349SMatthew G. Knepley $ x y z marker
49128ca92349SMatthew G. Knepley 
49138ca92349SMatthew G. Knepley   Level: beginner
49148ca92349SMatthew G. Knepley 
4915db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
49168ca92349SMatthew G. Knepley @*/
4917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
4918d71ae5a4SJacob Faibussowitsch {
49198ca92349SMatthew G. Knepley   DMLabel      marker;
49208ca92349SMatthew G. Knepley   PetscViewer  viewer;
49218ca92349SMatthew G. Knepley   Vec          coordinates;
49228ca92349SMatthew G. Knepley   PetscSection coordSection;
49238ca92349SMatthew G. Knepley   PetscScalar *coords;
49248ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
49258ca92349SMatthew G. Knepley   PetscInt     dim = 3, cdim = 3, coordSize, v, c, d;
49268ca92349SMatthew G. Knepley   PetscMPIInt  rank;
4927f8d5e320SMatthew G. Knepley   int          snum, Nv, Nc, Ncn, Nl;
49288ca92349SMatthew G. Knepley 
49298ca92349SMatthew G. Knepley   PetscFunctionBegin;
49309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
49319566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
49329566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
49339566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
49349566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
4935dd400576SPatrick Sanan   if (rank == 0) {
49369566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4937f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
493808401ef6SPierre Jolivet     PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
493925ce1634SJed Brown   } else {
4940f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
49418ca92349SMatthew G. Knepley   }
49429566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
49439566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
49449566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
49459566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
49469566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
49478ca92349SMatthew G. Knepley   /* Read topology */
4948dd400576SPatrick Sanan   if (rank == 0) {
4949f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
4950f8d5e320SMatthew G. Knepley     PetscInt cone[8];
49518ca92349SMatthew G. Knepley     int      vbuf[8], v;
49528ca92349SMatthew G. Knepley 
49539371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
49549371c9d4SSatish Balay       format[c * 3 + 0] = '%';
49559371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
49569371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
49579371c9d4SSatish Balay     }
4958f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
49599566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
49609566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
49618ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
49629566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
4963f8d5e320SMatthew G. Knepley       switch (Ncn) {
4964d71ae5a4SJacob Faibussowitsch       case 2:
4965d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
4966d71ae5a4SJacob Faibussowitsch         break;
4967d71ae5a4SJacob Faibussowitsch       case 3:
4968d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
4969d71ae5a4SJacob Faibussowitsch         break;
4970d71ae5a4SJacob Faibussowitsch       case 4:
4971d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
4972d71ae5a4SJacob Faibussowitsch         break;
4973d71ae5a4SJacob Faibussowitsch       case 6:
4974d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
4975d71ae5a4SJacob Faibussowitsch         break;
4976d71ae5a4SJacob Faibussowitsch       case 8:
4977d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
4978d71ae5a4SJacob Faibussowitsch         break;
4979d71ae5a4SJacob Faibussowitsch       default:
4980d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
4981f8d5e320SMatthew G. Knepley       }
498208401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4983f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
49848ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
4985f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
49868ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
49878ca92349SMatthew G. Knepley         cone[1]      = cone[3];
49888ca92349SMatthew G. Knepley         cone[3]      = tmp;
49898ca92349SMatthew G. Knepley       }
49909566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
49918ca92349SMatthew G. Knepley     }
49928ca92349SMatthew G. Knepley   }
49939566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
49949566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
49958ca92349SMatthew G. Knepley   /* Read coordinates */
49969566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
49979566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
49989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
49999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
50008ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
50019566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
50029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
50038ca92349SMatthew G. Knepley   }
50049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
50059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
50069566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
50079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
50089566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
50099566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
50109566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
50119566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5012dd400576SPatrick Sanan   if (rank == 0) {
5013f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
50148ca92349SMatthew G. Knepley     double x[3];
5015f8d5e320SMatthew G. Knepley     int    l, val[3];
50168ca92349SMatthew G. Knepley 
5017f8d5e320SMatthew G. Knepley     if (Nl) {
50189371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
50199371c9d4SSatish Balay         format[l * 3 + 0] = '%';
50209371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
50219371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
50229371c9d4SSatish Balay       }
5023f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
50249566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50259566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
5026f8d5e320SMatthew G. Knepley     }
50278ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
50289566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
5029f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
503008401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5031f8d5e320SMatthew G. Knepley       switch (Nl) {
5032d71ae5a4SJacob Faibussowitsch       case 0:
5033d71ae5a4SJacob Faibussowitsch         snum = 0;
5034d71ae5a4SJacob Faibussowitsch         break;
5035d71ae5a4SJacob Faibussowitsch       case 1:
5036d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
5037d71ae5a4SJacob Faibussowitsch         break;
5038d71ae5a4SJacob Faibussowitsch       case 2:
5039d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
5040d71ae5a4SJacob Faibussowitsch         break;
5041d71ae5a4SJacob Faibussowitsch       case 3:
5042d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
5043d71ae5a4SJacob Faibussowitsch         break;
5044d71ae5a4SJacob Faibussowitsch       default:
5045d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
5046f8d5e320SMatthew G. Knepley       }
504708401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
50488ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
50499566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
50508ca92349SMatthew G. Knepley     }
50518ca92349SMatthew G. Knepley   }
50529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
50539566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
50549566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
50559566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
50568ca92349SMatthew G. Knepley   if (interpolate) {
50578ca92349SMatthew G. Knepley     DM      idm;
50588ca92349SMatthew G. Knepley     DMLabel bdlabel;
50598ca92349SMatthew G. Knepley 
50609566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
50619566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
50628ca92349SMatthew G. Knepley     *dm = idm;
50638ca92349SMatthew G. Knepley 
5064f8d5e320SMatthew G. Knepley     if (!Nl) {
50659566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50669566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
50679566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
50689566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
50698ca92349SMatthew G. Knepley     }
5070f8d5e320SMatthew G. Knepley   }
50718ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
50728ca92349SMatthew G. Knepley }
50738ca92349SMatthew G. Knepley 
50748ca92349SMatthew G. Knepley /*@C
5075ca522641SMatthew G. Knepley   DMPlexCreateFromFile - This takes a filename and produces a DM
5076ca522641SMatthew G. Knepley 
5077ca522641SMatthew G. Knepley   Input Parameters:
5078ca522641SMatthew G. Knepley + comm - The communicator
5079ca522641SMatthew G. Knepley . filename - A file name
5080cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats
5081ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
5082ca522641SMatthew G. Knepley 
5083ca522641SMatthew G. Knepley   Output Parameter:
5084ca522641SMatthew G. Knepley . dm - The DM
5085ca522641SMatthew G. Knepley 
508602ef0d99SVaclav Hapla   Options Database Keys:
508702ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5
508802ef0d99SVaclav Hapla 
5089bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
5090bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
5091bca97951SVaclav Hapla 
5092cd7e8a5eSksagiyam   Notes:
5093cd7e8a5eSksagiyam   Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex
5094cd7e8a5eSksagiyam   meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName()
5095cd7e8a5eSksagiyam   before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object.
5096cd7e8a5eSksagiyam   The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally
5097cd7e8a5eSksagiyam   calls DMLoad(). Currently, name is ignored for other viewer types and/or formats.
5098cd7e8a5eSksagiyam 
5099ca522641SMatthew G. Knepley   Level: beginner
5100ca522641SMatthew G. Knepley 
5101db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
5102ca522641SMatthew G. Knepley @*/
5103d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
5104d71ae5a4SJacob Faibussowitsch {
5105ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
5106ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
5107ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
5108ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
5109ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
5110ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
5111ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
5112ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
5113ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
5114ef3a5affSJacob Faibussowitsch   const char  extMed[]       = ".med";
5115ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
5116ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
5117ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
5118ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
5119ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
5120ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
5121ca522641SMatthew G. Knepley   size_t      len;
5122c1cad2e7SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
5123ca522641SMatthew G. Knepley   PetscMPIInt rank;
5124ca522641SMatthew G. Knepley 
5125ca522641SMatthew G. Knepley   PetscFunctionBegin;
51265d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
51270d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
5128cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
51299566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
51309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
51319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
51329566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
513328b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
5134ef3a5affSJacob Faibussowitsch 
51359371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
51369371c9d4SSatish Balay   do { \
5137274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
5138274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
5139274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
5140274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
5141ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
5142ef3a5affSJacob Faibussowitsch     } else { \
5143274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
5144ef3a5affSJacob Faibussowitsch     } \
5145ef3a5affSJacob Faibussowitsch   } while (0)
5146ef3a5affSJacob Faibussowitsch 
5147ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
5148ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
5149ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
5150ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
5151ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
5152ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
5153ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
5154ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
5155ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
5156ef3a5affSJacob Faibussowitsch   CheckExtension(extMed, isMed);
5157ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
5158ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
5159ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
5160ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
5161ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
5162ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
5163ef3a5affSJacob Faibussowitsch 
5164ef3a5affSJacob Faibussowitsch #undef CheckExtension
5165ef3a5affSJacob Faibussowitsch 
5166de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
51679566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
5168ca522641SMatthew G. Knepley   } else if (isCGNS) {
51699566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
517090c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
51719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
51722f0bd6dcSMichael Lange   } else if (isFluent) {
51739566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
5174cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
51759c48423bSVaclav Hapla     PetscBool   load_hdf5_xdmf = PETSC_FALSE;
5176cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
5177cc2f8f65SMatthew G. Knepley 
517843b242b4SVaclav 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 */
51799566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf));
51809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
51819566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
51829566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
51839566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
51849566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
51859566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
51869566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
5187cd7e8a5eSksagiyam 
51889566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
51899566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
51909566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
51919566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
51929566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
51939566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer));
51949566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
51955fd9971aSMatthew G. Knepley 
51965fd9971aSMatthew G. Knepley     if (interpolate) {
51975fd9971aSMatthew G. Knepley       DM idm;
51985fd9971aSMatthew G. Knepley 
51999566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
52009566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52015fd9971aSMatthew G. Knepley       *dm = idm;
52025fd9971aSMatthew G. Knepley     }
5203707dd687SMichael Lange   } else if (isMed) {
52049566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
5205f2801cd6SMatthew G. Knepley   } else if (isPLY) {
52069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
5207c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
52089566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
52099566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
52107bee2925SMatthew Knepley     if (!interpolate) {
52117bee2925SMatthew Knepley       DM udm;
52127bee2925SMatthew Knepley 
52139566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
52149566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52157bee2925SMatthew Knepley       *dm = udm;
52167bee2925SMatthew Knepley     }
52178ca92349SMatthew G. Knepley   } else if (isCV) {
52189566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
521998921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
52209566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
52219566063dSJacob Faibussowitsch   if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
5223ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
5224ca522641SMatthew G. Knepley }
52259f6c5813SMatthew G. Knepley /*@C
52269f6c5813SMatthew G. Knepley   DMPlexCreateEphemeral - This takes a `DMPlexTransform` and a base `DMPlex` and produces an ephemeral `DM`, meaning one that is created on the fly in response to queries.
52279f6c5813SMatthew G. Knepley 
52289f6c5813SMatthew G. Knepley   Input Parameter:
52299f6c5813SMatthew G. Knepley . tr - The `DMPlexTransform`
52309f6c5813SMatthew G. Knepley 
52319f6c5813SMatthew G. Knepley   Output Parameter:
52329f6c5813SMatthew G. Knepley . dm - The `DM`
52339f6c5813SMatthew G. Knepley 
52349f6c5813SMatthew G. Knepley   Notes:
52359f6c5813SMatthew G. Knepley   An emphemeral mesh is one that is not stored concretely, as in the default Plex implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh.
52369f6c5813SMatthew G. Knepley 
52379f6c5813SMatthew G. Knepley   Level: beginner
52389f6c5813SMatthew G. Knepley 
52399f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
52409f6c5813SMatthew G. Knepley @*/
52419f6c5813SMatthew G. Knepley PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, DM *dm)
52429f6c5813SMatthew G. Knepley {
52439f6c5813SMatthew G. Knepley   DM       bdm;
52449f6c5813SMatthew G. Knepley   PetscInt Nl;
52459f6c5813SMatthew G. Knepley 
52469f6c5813SMatthew G. Knepley   PetscFunctionBegin;
52479f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
52489f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
52499f6c5813SMatthew G. Knepley   PetscCall(DMSetFromOptions(*dm));
52509f6c5813SMatthew G. Knepley 
52519f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
52529f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
52539f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
52549f6c5813SMatthew G. Knepley 
52559f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformGetDM(tr, &bdm));
52569f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
52579f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
52589f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
52599f6c5813SMatthew G. Knepley     const char *lname;
52609f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
52619f6c5813SMatthew G. Knepley 
52629f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
52639f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
52649f6c5813SMatthew G. Knepley     if (isDepth) continue;
52659f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
52669f6c5813SMatthew G. Knepley     if (isCellType) continue;
52679f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
52689f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
52699f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
52709f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
52719f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
52729f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
52739f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
52749f6c5813SMatthew G. Knepley   }
52759f6c5813SMatthew G. Knepley   PetscFunctionReturn(0);
52769f6c5813SMatthew G. Knepley }
5277