xref: /petsc/src/dm/impls/plex/plexcreate.c (revision a1cb98fac0cdf0eb4d3e8a0c8b58f3fe8f800bc6)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h>   /*I   "petscdmplex.h"   I*/
40c312b8eSJed Brown #include <petscsf.h>
54663dae6SJed Brown #include <petscdmplextransform.h>
6b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
7b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
8552f7358SJed Brown 
9b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1058cd63d5SVaclav Hapla 
119318fe57SMatthew G. Knepley /* External function declarations here */
129318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
139318fe57SMatthew G. Knepley 
14e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
15d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
16d71ae5a4SJacob Faibussowitsch {
174fb89dddSMatthew G. Knepley   const PetscReal         *maxCell, *Lstart, *L;
186858538eSMatthew G. Knepley   PetscBool                dist;
196bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
20e600fa54SMatthew G. Knepley 
21e600fa54SMatthew G. Knepley   PetscFunctionBegin;
22e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
234fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
244fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
25e600fa54SMatthew G. Knepley   }
269566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
279566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
286bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
296bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
30e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
311baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
32e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
33e600fa54SMatthew G. Knepley }
34e600fa54SMatthew G. Knepley 
359318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
369318fe57SMatthew G. Knepley    - Share the DM_Plex structure
379318fe57SMatthew G. Knepley    - Share the coordinates
389318fe57SMatthew G. Knepley    - Share the SF
399318fe57SMatthew G. Knepley */
40d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
41d71ae5a4SJacob Faibussowitsch {
429318fe57SMatthew G. Knepley   PetscSF          sf;
439318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
449318fe57SMatthew G. Knepley   Vec              coords;
454fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
469318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
479318fe57SMatthew G. Knepley 
489318fe57SMatthew G. Knepley   PetscFunctionBegin;
499318fe57SMatthew G. Knepley   if (dm == dmNew) {
509566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
519318fe57SMatthew G. Knepley     PetscFunctionReturn(0);
529318fe57SMatthew G. Knepley   }
539318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
549566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
559566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
589566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
599566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
646858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
656858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
666858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
676858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
689318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
696858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
706858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
7161a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
724fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
734fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
749566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
759566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
769318fe57SMatthew G. Knepley   dm->data = dmNew->data;
779318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
789566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
799566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
809566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
819566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
829566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
839318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
849318fe57SMatthew G. Knepley }
859318fe57SMatthew G. Knepley 
869318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
879318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
889318fe57SMatthew G. Knepley    - Swap the coordinates
899318fe57SMatthew G. Knepley    - Swap the point PetscSF
909318fe57SMatthew G. Knepley */
91d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
92d71ae5a4SJacob Faibussowitsch {
939318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
949318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
959318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
969318fe57SMatthew G. Knepley   DMField     fieldTmp;
979318fe57SMatthew G. Knepley   void       *tmp;
989318fe57SMatthew G. Knepley   DMLabelLink listTmp;
999318fe57SMatthew G. Knepley   DMLabel     depthTmp;
1009318fe57SMatthew G. Knepley   PetscInt    tmpI;
1019318fe57SMatthew G. Knepley 
1029318fe57SMatthew G. Knepley   PetscFunctionBegin;
1039318fe57SMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
1049566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
1059566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
1069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
1079566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
1089566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
1099566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
1109318fe57SMatthew G. Knepley 
1119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
1129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
1139566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1149566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
1159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1179318fe57SMatthew G. Knepley 
1189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
1199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
1209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
1219566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
1229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
1239566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1249318fe57SMatthew G. Knepley 
1256858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
1266858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
1276858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1286858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
1296858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
1306858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1316858538eSMatthew G. Knepley 
1326858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
1336858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
1346858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
1356858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
1366858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
1376858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1386858538eSMatthew G. Knepley 
1396858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
1406858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
1416858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
1426858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
1436858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
1446858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
1459318fe57SMatthew G. Knepley   tmp                       = dmA->data;
1469318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
1479318fe57SMatthew G. Knepley   dmB->data                 = tmp;
1489318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
1499318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
1509318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
1519318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
1529318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
1539318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
1549318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
1559318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
1569318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
1579318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
1589318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
1599318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
1609318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1619318fe57SMatthew G. Knepley }
1629318fe57SMatthew G. Knepley 
163d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
164d71ae5a4SJacob Faibussowitsch {
1659318fe57SMatthew G. Knepley   DM idm;
1669318fe57SMatthew G. Knepley 
1679318fe57SMatthew G. Knepley   PetscFunctionBegin;
1689566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
1699566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
17069d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
1719318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1729318fe57SMatthew G. Knepley }
1739318fe57SMatthew G. Knepley 
1749318fe57SMatthew G. Knepley /*@C
1759318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
1769318fe57SMatthew G. Knepley 
177*a1cb98faSBarry Smith   Collective on dm
1789318fe57SMatthew G. Knepley 
1799318fe57SMatthew G. Knepley   Input Parameters:
1809318fe57SMatthew G. Knepley + DM        - The DM
1814f9ab2b4SJed Brown . degree    - The degree of the finite element or PETSC_DECIDE
1829318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
1839318fe57SMatthew G. Knepley 
1849318fe57SMatthew G. Knepley   Level: advanced
1859318fe57SMatthew G. Knepley 
186*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
1879318fe57SMatthew G. Knepley @*/
188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc)
189d71ae5a4SJacob Faibussowitsch {
1909318fe57SMatthew G. Knepley   DM_Plex     *mesh = (DM_Plex *)dm->data;
1919318fe57SMatthew G. Knepley   DM           cdm;
1929318fe57SMatthew G. Knepley   PetscDS      cds;
1939318fe57SMatthew G. Knepley   PetscFE      fe;
1949318fe57SMatthew G. Knepley   PetscClassId id;
1959318fe57SMatthew G. Knepley 
1969318fe57SMatthew G. Knepley   PetscFunctionBegin;
1979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
1989566063dSJacob Faibussowitsch   PetscCall(DMGetDS(cdm, &cds));
1999566063dSJacob Faibussowitsch   PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe));
2009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
2019318fe57SMatthew G. Knepley   if (id != PETSCFE_CLASSID) {
2029318fe57SMatthew G. Knepley     PetscBool simplex;
2039318fe57SMatthew G. Knepley     PetscInt  dim, dE, qorder;
2049318fe57SMatthew G. Knepley 
2059566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
2069566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dm, &dE));
2079318fe57SMatthew G. Knepley     qorder = degree;
208d0609cedSBarry Smith     PetscObjectOptionsBegin((PetscObject)cdm);
2099566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
210d0609cedSBarry Smith     PetscOptionsEnd();
2114f9ab2b4SJed Brown     if (degree == PETSC_DECIDE) fe = NULL;
2124f9ab2b4SJed Brown     else {
2138c4475acSStefano Zampini       PetscCall(DMPlexIsSimplex(dm, &simplex));
2149566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe));
2154f9ab2b4SJed Brown     }
2169566063dSJacob Faibussowitsch     PetscCall(DMProjectCoordinates(dm, fe));
2179566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2189318fe57SMatthew G. Knepley   }
2199318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2209318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
2219318fe57SMatthew G. Knepley }
2229318fe57SMatthew G. Knepley 
2231df5d5c5SMatthew G. Knepley /*@
2241df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2251df5d5c5SMatthew G. Knepley 
226d083f849SBarry Smith   Collective
2271df5d5c5SMatthew G. Knepley 
2281df5d5c5SMatthew G. Knepley   Input Parameters:
229*a1cb98faSBarry Smith + comm - The communicator for the `DM` object
2301df5d5c5SMatthew G. Knepley . dim - The spatial dimension
2311df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells
2321df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces)
2331df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2341df5d5c5SMatthew G. Knepley 
2351df5d5c5SMatthew G. Knepley   Output Parameter:
236*a1cb98faSBarry Smith . dm - The `DM` object
2371df5d5c5SMatthew G. Knepley 
2381df5d5c5SMatthew G. Knepley   Level: beginner
2391df5d5c5SMatthew G. Knepley 
240*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
2411df5d5c5SMatthew G. Knepley @*/
242d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
243d71ae5a4SJacob Faibussowitsch {
2441df5d5c5SMatthew G. Knepley   DM          dm;
2451df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
2461df5d5c5SMatthew G. Knepley 
2471df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
2489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
2499566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
2509566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
252ce78fa2fSMatthew G. Knepley   switch (dim) {
253ce78fa2fSMatthew G. Knepley   case 2:
2549566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
2559566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
256ce78fa2fSMatthew G. Knepley     break;
257ce78fa2fSMatthew G. Knepley   case 3:
2589566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
2599566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
260ce78fa2fSMatthew G. Knepley     break;
261d71ae5a4SJacob Faibussowitsch   default:
262d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
263ce78fa2fSMatthew G. Knepley   }
2641df5d5c5SMatthew G. Knepley   if (rank) {
2651df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
2669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
2671df5d5c5SMatthew G. Knepley   } else {
2681df5d5c5SMatthew G. Knepley     switch (dim) {
2691df5d5c5SMatthew G. Knepley     case 2:
2701df5d5c5SMatthew G. Knepley       if (simplex) {
2711df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
2721df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
2731df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
2741df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
2751df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
2761df5d5c5SMatthew G. Knepley 
2779566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2781df5d5c5SMatthew G. Knepley       } else {
2791df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
2801df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
2811df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
2821df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2831df5d5c5SMatthew 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};
2841df5d5c5SMatthew G. Knepley 
2859566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2861df5d5c5SMatthew G. Knepley       }
2871df5d5c5SMatthew G. Knepley       break;
2881df5d5c5SMatthew G. Knepley     case 3:
2891df5d5c5SMatthew G. Knepley       if (simplex) {
2901df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
2911df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
2921df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
2931df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2941df5d5c5SMatthew 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};
2951df5d5c5SMatthew G. Knepley 
2969566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2971df5d5c5SMatthew G. Knepley       } else {
2981df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
2991df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3001df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
3011df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3029371c9d4SSatish 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};
3031df5d5c5SMatthew G. Knepley 
3049566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3051df5d5c5SMatthew G. Knepley       }
3061df5d5c5SMatthew G. Knepley       break;
307d71ae5a4SJacob Faibussowitsch     default:
308d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
3091df5d5c5SMatthew G. Knepley     }
3101df5d5c5SMatthew G. Knepley   }
3111df5d5c5SMatthew G. Knepley   *newdm = dm;
3121df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
3131df5d5c5SMatthew G. Knepley     DM          rdm;
3141df5d5c5SMatthew G. Knepley     const char *name;
3151df5d5c5SMatthew G. Knepley 
3169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
3179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
3189566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
3199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
3209566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
3219566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3221df5d5c5SMatthew G. Knepley     *newdm = rdm;
3231df5d5c5SMatthew G. Knepley   }
3241df5d5c5SMatthew G. Knepley   if (interpolate) {
3255fd9971aSMatthew G. Knepley     DM idm;
3261df5d5c5SMatthew G. Knepley 
3279566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
3289566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3291df5d5c5SMatthew G. Knepley     *newdm = idm;
3301df5d5c5SMatthew G. Knepley   }
3311df5d5c5SMatthew G. Knepley   PetscFunctionReturn(0);
3321df5d5c5SMatthew G. Knepley }
3331df5d5c5SMatthew G. Knepley 
334d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
335d71ae5a4SJacob Faibussowitsch {
3369318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3379318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3389318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3399318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3409318fe57SMatthew G. Knepley   Vec            coordinates;
3419318fe57SMatthew G. Knepley   PetscSection   coordSection;
3429318fe57SMatthew G. Knepley   PetscScalar   *coords;
3439318fe57SMatthew G. Knepley   PetscInt       coordSize;
3449318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3459318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
346552f7358SJed Brown 
3479318fe57SMatthew G. Knepley   PetscFunctionBegin;
3489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3499318fe57SMatthew G. Knepley   if (markerSeparate) {
3509318fe57SMatthew G. Knepley     markerRight = 2;
3519318fe57SMatthew G. Knepley     markerLeft  = 1;
3529318fe57SMatthew G. Knepley   }
3539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
354c5853193SPierre Jolivet   if (rank == 0) {
3559566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
3569566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3579566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
3589566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
3599318fe57SMatthew G. Knepley   }
3609566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
3619566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
3629318fe57SMatthew G. Knepley   /* Build coordinates */
3639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
3649566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
3659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
3669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
3679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
3689318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
3699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
3709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
3719318fe57SMatthew G. Knepley   }
3729566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
3739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
3749566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
3759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
3769566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
3779566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
3789566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
3799566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
3809318fe57SMatthew G. Knepley   coords[0] = lower[0];
3819318fe57SMatthew G. Knepley   coords[1] = upper[0];
3829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
3839566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
3849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
3859318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
3869318fe57SMatthew G. Knepley }
38726492d91SMatthew G. Knepley 
388d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
389d71ae5a4SJacob Faibussowitsch {
3901df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
3911df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
392552f7358SJed Brown   PetscInt       markerTop      = 1;
393552f7358SJed Brown   PetscInt       markerBottom   = 1;
394552f7358SJed Brown   PetscInt       markerRight    = 1;
395552f7358SJed Brown   PetscInt       markerLeft     = 1;
396552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
397552f7358SJed Brown   Vec            coordinates;
398552f7358SJed Brown   PetscSection   coordSection;
399552f7358SJed Brown   PetscScalar   *coords;
400552f7358SJed Brown   PetscInt       coordSize;
401552f7358SJed Brown   PetscMPIInt    rank;
402552f7358SJed Brown   PetscInt       v, vx, vy;
403552f7358SJed Brown 
404552f7358SJed Brown   PetscFunctionBegin;
4059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
406552f7358SJed Brown   if (markerSeparate) {
4071df21d24SMatthew G. Knepley     markerTop    = 3;
4081df21d24SMatthew G. Knepley     markerBottom = 1;
4091df21d24SMatthew G. Knepley     markerRight  = 2;
4101df21d24SMatthew G. Knepley     markerLeft   = 4;
411552f7358SJed Brown   }
4129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
413dd400576SPatrick Sanan   if (rank == 0) {
414552f7358SJed Brown     PetscInt e, ex, ey;
415552f7358SJed Brown 
4169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
41748a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
4189566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
419552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
420552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
421552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
422552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
423da80777bSKarl Rupp         PetscInt cone[2];
424552f7358SJed Brown 
4259371c9d4SSatish Balay         cone[0] = vertex;
4269371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
4279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
428552f7358SJed Brown         if (vx == edges[0]) {
4299566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
4309566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
431552f7358SJed Brown           if (ey == edges[1] - 1) {
4329566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
4339566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
434552f7358SJed Brown           }
435552f7358SJed Brown         } else if (vx == 0) {
4369566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
4379566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
438552f7358SJed Brown           if (ey == edges[1] - 1) {
4399566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
4409566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
441552f7358SJed Brown           }
442552f7358SJed Brown         }
443552f7358SJed Brown       }
444552f7358SJed Brown     }
445552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
446552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
447552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
448552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
449da80777bSKarl Rupp         PetscInt cone[2];
450552f7358SJed Brown 
4519371c9d4SSatish Balay         cone[0] = vertex;
4529371c9d4SSatish Balay         cone[1] = vertex + 1;
4539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
454552f7358SJed Brown         if (vy == edges[1]) {
4559566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
4569566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
457552f7358SJed Brown           if (ex == edges[0] - 1) {
4589566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
4599566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
460552f7358SJed Brown           }
461552f7358SJed Brown         } else if (vy == 0) {
4629566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
4639566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
464552f7358SJed Brown           if (ex == edges[0] - 1) {
4659566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
4669566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
467552f7358SJed Brown           }
468552f7358SJed Brown         }
469552f7358SJed Brown       }
470552f7358SJed Brown     }
471552f7358SJed Brown   }
4729566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4739566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
474552f7358SJed Brown   /* Build coordinates */
4759566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
4769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
4799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
480552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
4819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
4829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
483552f7358SJed Brown   }
4849566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4869566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4879566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4889566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4899566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
4909566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
4919566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
492552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
493552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
494552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
495552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
496552f7358SJed Brown     }
497552f7358SJed Brown   }
4989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
4999566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
501552f7358SJed Brown   PetscFunctionReturn(0);
502552f7358SJed Brown }
503552f7358SJed Brown 
504d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
505d71ae5a4SJacob Faibussowitsch {
5069e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
5077b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
508c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
509c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
510c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
511c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
512c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
513c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
514c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
515552f7358SJed Brown   Vec          coordinates;
516552f7358SJed Brown   PetscSection coordSection;
517552f7358SJed Brown   PetscScalar *coords;
518552f7358SJed Brown   PetscInt     coordSize;
519552f7358SJed Brown   PetscMPIInt  rank;
520552f7358SJed Brown   PetscInt     v, vx, vy, vz;
5217b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
522552f7358SJed Brown 
523552f7358SJed Brown   PetscFunctionBegin;
5241dca8a05SBarry 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");
5259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
526c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
527c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
528c2df9bbfSMatthew G. Knepley     markerBottom = 1;
529c2df9bbfSMatthew G. Knepley     markerTop    = 2;
530c2df9bbfSMatthew G. Knepley     markerFront  = 3;
531c2df9bbfSMatthew G. Knepley     markerBack   = 4;
532c2df9bbfSMatthew G. Knepley     markerRight  = 5;
533c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
534c2df9bbfSMatthew G. Knepley   }
5359371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
5369371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
5379371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
5389e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
539dd400576SPatrick Sanan   if (rank == 0) {
540552f7358SJed Brown     PetscInt f;
541552f7358SJed Brown 
5429566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
54348a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
5449566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5457b59f5a9SMichael Lange 
5467b59f5a9SMichael Lange     /* Side 0 (Top) */
5477b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5487b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5497b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
5509371c9d4SSatish Balay         cone[0] = voffset;
5519371c9d4SSatish Balay         cone[1] = voffset + 1;
5529371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
5539371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
5549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
555c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
556c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
557c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
558c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
559c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
5607b59f5a9SMichael Lange         iface++;
561552f7358SJed Brown       }
562552f7358SJed Brown     }
5637b59f5a9SMichael Lange 
5647b59f5a9SMichael Lange     /* Side 1 (Bottom) */
5657b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5667b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5677b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
5689371c9d4SSatish Balay         cone[0] = voffset + 1;
5699371c9d4SSatish Balay         cone[1] = voffset;
5709371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
5719371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
5729566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
573c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
574c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
575c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
576c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
577c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
5787b59f5a9SMichael Lange         iface++;
579552f7358SJed Brown       }
580552f7358SJed Brown     }
5817b59f5a9SMichael Lange 
5827b59f5a9SMichael Lange     /* Side 2 (Front) */
5837b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5847b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5857b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
5869371c9d4SSatish Balay         cone[0] = voffset;
5879371c9d4SSatish Balay         cone[1] = voffset + 1;
5889371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
5899371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
5909566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
591c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
592c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
593c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
594c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
595c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
5967b59f5a9SMichael Lange         iface++;
597552f7358SJed Brown       }
5987b59f5a9SMichael Lange     }
5997b59f5a9SMichael Lange 
6007b59f5a9SMichael Lange     /* Side 3 (Back) */
6017b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6027b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6037b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
6049371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6059371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
6069371c9d4SSatish Balay         cone[2] = voffset + 1;
6079371c9d4SSatish Balay         cone[3] = voffset;
6089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
609c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
610c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
611c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
612c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
613c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
6147b59f5a9SMichael Lange         iface++;
6157b59f5a9SMichael Lange       }
6167b59f5a9SMichael Lange     }
6177b59f5a9SMichael Lange 
6187b59f5a9SMichael Lange     /* Side 4 (Left) */
6197b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6207b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
6217b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
6229371c9d4SSatish Balay         cone[0] = voffset;
6239371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
6249371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
6259371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
627c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
628c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
629c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
630c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
631c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
6327b59f5a9SMichael Lange         iface++;
6337b59f5a9SMichael Lange       }
6347b59f5a9SMichael Lange     }
6357b59f5a9SMichael Lange 
6367b59f5a9SMichael Lange     /* Side 5 (Right) */
6377b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6387b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
639aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
6409371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6419371c9d4SSatish Balay         cone[1] = voffset;
6429371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6439371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
6449566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
645c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
646c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
647c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
648c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
649c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
6507b59f5a9SMichael Lange         iface++;
6517b59f5a9SMichael Lange       }
652552f7358SJed Brown     }
653552f7358SJed Brown   }
6549566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6559566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
656552f7358SJed Brown   /* Build coordinates */
6579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
6589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
6619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
662552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
6639566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
6649566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
665552f7358SJed Brown   }
6669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6689566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6699566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6709566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6719566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
6729566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6739566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
674552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
675552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
676552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
677552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
678552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
679552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
680552f7358SJed Brown       }
681552f7358SJed Brown     }
682552f7358SJed Brown   }
6839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6849566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
686552f7358SJed Brown   PetscFunctionReturn(0);
687552f7358SJed Brown }
688552f7358SJed Brown 
689d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
690d71ae5a4SJacob Faibussowitsch {
6919318fe57SMatthew G. Knepley   PetscFunctionBegin;
6929318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6939566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
6949566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
6959318fe57SMatthew G. Knepley   switch (dim) {
696d71ae5a4SJacob Faibussowitsch   case 1:
697d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
698d71ae5a4SJacob Faibussowitsch     break;
699d71ae5a4SJacob Faibussowitsch   case 2:
700d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
701d71ae5a4SJacob Faibussowitsch     break;
702d71ae5a4SJacob Faibussowitsch   case 3:
703d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
704d71ae5a4SJacob Faibussowitsch     break;
705d71ae5a4SJacob Faibussowitsch   default:
706d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
7079318fe57SMatthew G. Knepley   }
7089566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
7099318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7109318fe57SMatthew G. Knepley }
7119318fe57SMatthew G. Knepley 
7129318fe57SMatthew G. Knepley /*@C
7139318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
7149318fe57SMatthew G. Knepley 
7159318fe57SMatthew G. Knepley   Collective
7169318fe57SMatthew G. Knepley 
7179318fe57SMatthew G. Knepley   Input Parameters:
718*a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
7199318fe57SMatthew G. Knepley . dim         - The spatial dimension of the box, so the resulting mesh is has dimension dim-1
7209318fe57SMatthew 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
7219318fe57SMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
7229318fe57SMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
7239318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7249318fe57SMatthew G. Knepley 
7259318fe57SMatthew G. Knepley   Output Parameter:
726*a1cb98faSBarry Smith . dm  - The `DM` object
7279318fe57SMatthew G. Knepley 
7289318fe57SMatthew G. Knepley   Level: beginner
7299318fe57SMatthew G. Knepley 
730*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
7319318fe57SMatthew G. Knepley @*/
732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
733d71ae5a4SJacob Faibussowitsch {
7349318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
7359318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
7369318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
7379318fe57SMatthew G. Knepley 
7389318fe57SMatthew G. Knepley   PetscFunctionBegin;
7399566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
7409566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
7419566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
7429318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7439318fe57SMatthew G. Knepley }
7449318fe57SMatthew G. Knepley 
745d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
746d71ae5a4SJacob Faibussowitsch {
747fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
748fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
749fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
750fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
751fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
752fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
753fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
754fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
755fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
756fdbf62faSLisandro Dalcin 
757fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7589318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
759fdbf62faSLisandro Dalcin 
7609566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
7619566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
7629566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
763fdbf62faSLisandro Dalcin 
7649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
765dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
766dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
767fdbf62faSLisandro Dalcin 
7689371c9d4SSatish Balay   numPoints[0] = numVerts;
7699371c9d4SSatish Balay   numPoints[1] = numCells;
7709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
7719566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
772ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
773ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
7749371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
7759371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
7769371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
7779371c9d4SSatish Balay   }
778ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
7799566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
7809566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
781fdbf62faSLisandro Dalcin 
7829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
7839371c9d4SSatish Balay   if (markerSeparate) {
7849371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
7859371c9d4SSatish Balay     markerRight = faceMarkerRight;
7869371c9d4SSatish Balay   }
787dd400576SPatrick Sanan   if (!wrap && rank == 0) {
7889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
7899566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
7909566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
7919566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
7929566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
793fdbf62faSLisandro Dalcin   }
794fdbf62faSLisandro Dalcin   if (wrap) {
795fdbf62faSLisandro Dalcin     L       = upper - lower;
796fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
7974fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
798fdbf62faSLisandro Dalcin   }
7999566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
800fdbf62faSLisandro Dalcin   PetscFunctionReturn(0);
801fdbf62faSLisandro Dalcin }
802fdbf62faSLisandro Dalcin 
803d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
804d71ae5a4SJacob Faibussowitsch {
8059318fe57SMatthew G. Knepley   DM      boundary, vol;
806c22d3578SMatthew G. Knepley   DMLabel bdlabel;
807d6218766SMatthew G. Knepley 
808d6218766SMatthew G. Knepley   PetscFunctionBegin;
8099318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
810c22d3578SMatthew 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");
8119566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
8129566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
8139566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
8149566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
815c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
816c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
8175de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
81869d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
8199566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
820d6218766SMatthew G. Knepley   PetscFunctionReturn(0);
821d6218766SMatthew G. Knepley }
822d6218766SMatthew G. Knepley 
823d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
824d71ae5a4SJacob Faibussowitsch {
825ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
826f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
827f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
828f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
829f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
830f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
831f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
8323dfda0b1SToby Isaac   PetscInt    dim;
833d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
8343dfda0b1SToby Isaac   PetscMPIInt rank;
8353dfda0b1SToby Isaac 
8363dfda0b1SToby Isaac   PetscFunctionBegin;
8379566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8399566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8409566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
8419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
8429371c9d4SSatish 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) {
8439371c9d4SSatish Balay     if (cutMarker) {
8449371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
8459371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
8469371c9d4SSatish Balay     }
847d8211ee3SMatthew G. Knepley   }
8483dfda0b1SToby Isaac   switch (dim) {
8493dfda0b1SToby Isaac   case 2:
850f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
851f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
852f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
853f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
8543dfda0b1SToby Isaac     break;
8553dfda0b1SToby Isaac   case 3:
856f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
857f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
858f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
859f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
860f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
861f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
8623dfda0b1SToby Isaac     break;
863d71ae5a4SJacob Faibussowitsch   default:
864d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
8653dfda0b1SToby Isaac   }
8669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
867f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
868f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
869f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
870f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
871f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
872f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
873f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
8743dfda0b1SToby Isaac   }
8753dfda0b1SToby Isaac   {
876dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
877dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
878dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
879dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
880dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
881dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
8823dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
8833dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
8843dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
8853dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
8863dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
8873dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
8883dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
8893dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
8903dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
8913dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
8923dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
8933dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
8943dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
8953dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
8963dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
8973dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
8983dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
8993dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
9003dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
9013dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
9023dfda0b1SToby Isaac     Vec            coordinates;
9033dfda0b1SToby Isaac     PetscSection   coordSection;
9043dfda0b1SToby Isaac     PetscScalar   *coords;
9053dfda0b1SToby Isaac     PetscInt       coordSize;
9063dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
9073dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
9083dfda0b1SToby Isaac 
9099566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
91048a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
91148a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
91248a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
9139566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
9143dfda0b1SToby Isaac     /* Build cells */
9153dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9163dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9173dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
9183dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
9193dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
9203dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
9213dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9223dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
9233dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9243dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
9253dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
926b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
92742206facSLisandro Dalcin           PetscInt cone[6];
9283dfda0b1SToby Isaac 
9293dfda0b1SToby Isaac           /* no boundary twisting in 3D */
9309371c9d4SSatish Balay           cone[0] = faceB;
9319371c9d4SSatish Balay           cone[1] = faceT;
9329371c9d4SSatish Balay           cone[2] = faceF;
9339371c9d4SSatish Balay           cone[3] = faceK;
9349371c9d4SSatish Balay           cone[4] = faceR;
9359371c9d4SSatish Balay           cone[5] = faceL;
9369566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
9379566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
9389566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9399566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9409566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9413dfda0b1SToby Isaac         }
9423dfda0b1SToby Isaac       }
9433dfda0b1SToby Isaac     }
9443dfda0b1SToby Isaac     /* Build x faces */
9453dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9463dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9473dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
9483dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9493dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9503dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
9513dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
9523dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
953b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9543dfda0b1SToby Isaac           PetscInt cone[4];
9553dfda0b1SToby Isaac 
9563dfda0b1SToby Isaac           if (dim == 3) {
9573dfda0b1SToby Isaac             /* markers */
9583dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
9593dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
9609566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
9619566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
9629371c9d4SSatish Balay               } else if (fx == 0) {
9639566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
9649566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
9653dfda0b1SToby Isaac               }
9663dfda0b1SToby Isaac             }
9673dfda0b1SToby Isaac           }
9689371c9d4SSatish Balay           cone[0] = edgeB;
9699371c9d4SSatish Balay           cone[1] = edgeR;
9709371c9d4SSatish Balay           cone[2] = edgeT;
9719371c9d4SSatish Balay           cone[3] = edgeL;
9729566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
9739566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
9743dfda0b1SToby Isaac         }
9753dfda0b1SToby Isaac       }
9763dfda0b1SToby Isaac     }
9773dfda0b1SToby Isaac     /* Build y faces */
9783dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
97942206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
9803dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
9813dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9823dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9833dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
9843dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
9853dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
986b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9873dfda0b1SToby Isaac           PetscInt cone[4];
9883dfda0b1SToby Isaac 
9893dfda0b1SToby Isaac           if (dim == 3) {
9903dfda0b1SToby Isaac             /* markers */
9913dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
9923dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
9939566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
9949566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
9959371c9d4SSatish Balay               } else if (fy == 0) {
9969566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
9979566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
9983dfda0b1SToby Isaac               }
9993dfda0b1SToby Isaac             }
10003dfda0b1SToby Isaac           }
10019371c9d4SSatish Balay           cone[0] = edgeB;
10029371c9d4SSatish Balay           cone[1] = edgeR;
10039371c9d4SSatish Balay           cone[2] = edgeT;
10049371c9d4SSatish Balay           cone[3] = edgeL;
10059566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10069566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10073dfda0b1SToby Isaac         }
10083dfda0b1SToby Isaac       }
10093dfda0b1SToby Isaac     }
10103dfda0b1SToby Isaac     /* Build z faces */
10113dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
10123dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
10133dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
10143dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
10153dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
10163dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
10173dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
10183dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1019b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
10203dfda0b1SToby Isaac           PetscInt cone[4];
10213dfda0b1SToby Isaac 
10223dfda0b1SToby Isaac           if (dim == 2) {
10239371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
10249371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
10259371c9d4SSatish Balay               ornt[1] = -1;
10269371c9d4SSatish Balay             }
10279371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
10289371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
10299371c9d4SSatish Balay               ornt[2] = 0;
10309371c9d4SSatish Balay             }
10319566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
10329566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1033d1c88043SMatthew G. Knepley           } else {
10343dfda0b1SToby Isaac             /* markers */
10353dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
10363dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
10379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
10389566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
10399371c9d4SSatish Balay               } else if (fz == 0) {
10409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
10419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
10423dfda0b1SToby Isaac               }
10433dfda0b1SToby Isaac             }
10443dfda0b1SToby Isaac           }
10459371c9d4SSatish Balay           cone[0] = edgeB;
10469371c9d4SSatish Balay           cone[1] = edgeR;
10479371c9d4SSatish Balay           cone[2] = edgeT;
10489371c9d4SSatish Balay           cone[3] = edgeL;
10499566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10509566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10513dfda0b1SToby Isaac         }
10523dfda0b1SToby Isaac       }
10533dfda0b1SToby Isaac     }
10543dfda0b1SToby Isaac     /* Build Z edges*/
10553dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
10563dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10573dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
10583dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
10593dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
10603dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
10613dfda0b1SToby Isaac           PetscInt       cone[2];
10623dfda0b1SToby Isaac 
10639371c9d4SSatish Balay           cone[0] = vertexB;
10649371c9d4SSatish Balay           cone[1] = vertexT;
1065c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
10663dfda0b1SToby Isaac           if (dim == 3) {
10673dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
10683dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
10699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1070c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1071c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1072c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
10739566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1074c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1075c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10763dfda0b1SToby Isaac               }
10773dfda0b1SToby Isaac             }
10783dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
10793dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
10809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1081c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1082c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1083c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
10849566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1085c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1086c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
10873dfda0b1SToby Isaac               }
10883dfda0b1SToby Isaac             }
10893dfda0b1SToby Isaac           }
10903dfda0b1SToby Isaac         }
10913dfda0b1SToby Isaac       }
10923dfda0b1SToby Isaac     }
10933dfda0b1SToby Isaac     /* Build Y edges*/
10943dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
10953dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10963dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
10973dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
10983dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
10993dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
11003dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
11013dfda0b1SToby Isaac           PetscInt       cone[2];
11023dfda0b1SToby Isaac 
11039371c9d4SSatish Balay           cone[0] = vertexF;
11049371c9d4SSatish Balay           cone[1] = vertexK;
11059566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11063dfda0b1SToby Isaac           if (dim == 2) {
11073dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
11083dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
11109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
11119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1112c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1113d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11149566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
11159566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
11169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1117c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11183dfda0b1SToby Isaac               }
1119d8211ee3SMatthew G. Knepley             } else {
11204c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
11219566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11229566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1123c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11243dfda0b1SToby Isaac               }
1125d8211ee3SMatthew G. Knepley             }
1126d8211ee3SMatthew G. Knepley           } else {
11273dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
11283dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11299566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1130c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1131c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1132d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1134c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1135c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11363dfda0b1SToby Isaac               }
11373dfda0b1SToby Isaac             }
11383dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11393dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
11409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1141c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1142c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1143d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
11449566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1145c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1146c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11473dfda0b1SToby Isaac               }
11483dfda0b1SToby Isaac             }
11493dfda0b1SToby Isaac           }
11503dfda0b1SToby Isaac         }
11513dfda0b1SToby Isaac       }
11523dfda0b1SToby Isaac     }
11533dfda0b1SToby Isaac     /* Build X edges*/
11543dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
11553dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
11563dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
11573dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
11583dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
11593dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
11603dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
11613dfda0b1SToby Isaac           PetscInt       cone[2];
11623dfda0b1SToby Isaac 
11639371c9d4SSatish Balay           cone[0] = vertexL;
11649371c9d4SSatish Balay           cone[1] = vertexR;
11659566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11663dfda0b1SToby Isaac           if (dim == 2) {
11673dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
11683dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
11709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
11719566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1172c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1173d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
11749566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
11759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
11769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1177c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11783dfda0b1SToby Isaac               }
1179d8211ee3SMatthew G. Knepley             } else {
11804c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
11819566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11829566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1183c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11843dfda0b1SToby Isaac               }
1185d8211ee3SMatthew G. Knepley             }
1186d8211ee3SMatthew G. Knepley           } else {
11873dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11883dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11899566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1190c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1191c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1192c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
11939566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1194c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1195c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
11963dfda0b1SToby Isaac               }
11973dfda0b1SToby Isaac             }
11983dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11993dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
12009566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1201c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1202c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1203c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
12049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1205c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1206c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
12073dfda0b1SToby Isaac               }
12083dfda0b1SToby Isaac             }
12093dfda0b1SToby Isaac           }
12103dfda0b1SToby Isaac         }
12113dfda0b1SToby Isaac       }
12123dfda0b1SToby Isaac     }
12139566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
12149566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
12153dfda0b1SToby Isaac     /* Build coordinates */
12169566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
12179566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
12189566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
12199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
12203dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
12219566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
12229566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
12233dfda0b1SToby Isaac     }
12249566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
12259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
12269566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
12279566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
12289566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
12299566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
12309566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
12319566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
12323dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
12333dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
12343dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
12353dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
12363dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1237ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
12383dfda0b1SToby Isaac         }
12393dfda0b1SToby Isaac       }
12403dfda0b1SToby Isaac     }
12419566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12429566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
12439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
12443dfda0b1SToby Isaac   }
12453dfda0b1SToby Isaac   PetscFunctionReturn(0);
12463dfda0b1SToby Isaac }
12473dfda0b1SToby Isaac 
1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1249d71ae5a4SJacob Faibussowitsch {
12509318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
12519318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1252552f7358SJed Brown 
1253552f7358SJed Brown   PetscFunctionBegin;
12549318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
12559318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
12569566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
12579371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
12589371c9d4SSatish Balay     fac[d] = faces[d];
12599371c9d4SSatish Balay     bdt[d] = periodicity[d];
12609371c9d4SSatish Balay   }
12619566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
12629371c9d4SSatish 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))) {
12636858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
12646858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1265552f7358SJed Brown 
12669318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
12676858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
12689318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
12699318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1270768d5fceSMatthew G. Knepley       }
12716858538eSMatthew G. Knepley     }
12724fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1273768d5fceSMatthew G. Knepley   }
12749566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
12759318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
12769318fe57SMatthew G. Knepley }
12779318fe57SMatthew G. Knepley 
1278d71ae5a4SJacob 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)
1279d71ae5a4SJacob Faibussowitsch {
12809318fe57SMatthew G. Knepley   PetscFunctionBegin;
12819566063dSJacob Faibussowitsch   if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
12829566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
12839566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
12849318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1285768d5fceSMatthew G. Knepley     DM udm;
1286768d5fceSMatthew G. Knepley 
12879566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
12889566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
128969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1290768d5fceSMatthew G. Knepley   }
1291768d5fceSMatthew G. Knepley   PetscFunctionReturn(0);
1292c8c68bd8SToby Isaac }
1293c8c68bd8SToby Isaac 
1294768d5fceSMatthew G. Knepley /*@C
1295768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1296768d5fceSMatthew G. Knepley 
1297d083f849SBarry Smith   Collective
1298768d5fceSMatthew G. Knepley 
1299768d5fceSMatthew G. Knepley   Input Parameters:
1300*a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
1301768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1302*a1cb98faSBarry Smith . simplex     - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
1303fdbf62faSLisandro Dalcin . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
1304768d5fceSMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
1305768d5fceSMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
1306*a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE`
1307768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
1308768d5fceSMatthew G. Knepley 
1309768d5fceSMatthew G. Knepley   Output Parameter:
1310*a1cb98faSBarry Smith . dm  - The `DM` object
1311768d5fceSMatthew G. Knepley 
1312768d5fceSMatthew G. Knepley   Level: beginner
1313768d5fceSMatthew G. Knepley 
1314*a1cb98faSBarry Smith   Note:
1315*a1cb98faSBarry Smith    To customize this mesh using options, use
1316*a1cb98faSBarry Smith .vb
1317*a1cb98faSBarry Smith   DMCreate(comm, &dm);
1318*a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1319*a1cb98faSBarry Smith   DMSetFromOptions(dm);
1320*a1cb98faSBarry Smith .ve
1321*a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`.
1322*a1cb98faSBarry Smith 
1323*a1cb98faSBarry Smith   Here is the numbering returned for 2 faces in each direction for tensor cells:
1324*a1cb98faSBarry Smith .vb
1325*a1cb98faSBarry Smith  10---17---11---18----12
1326*a1cb98faSBarry Smith   |         |         |
1327*a1cb98faSBarry Smith   |         |         |
1328*a1cb98faSBarry Smith  20    2   22    3    24
1329*a1cb98faSBarry Smith   |         |         |
1330*a1cb98faSBarry Smith   |         |         |
1331*a1cb98faSBarry Smith   7---15----8---16----9
1332*a1cb98faSBarry Smith   |         |         |
1333*a1cb98faSBarry Smith   |         |         |
1334*a1cb98faSBarry Smith  19    0   21    1   23
1335*a1cb98faSBarry Smith   |         |         |
1336*a1cb98faSBarry Smith   |         |         |
1337*a1cb98faSBarry Smith   4---13----5---14----6
1338*a1cb98faSBarry Smith .ve
1339*a1cb98faSBarry Smith and for simplicial cells
1340*a1cb98faSBarry Smith .vb
1341*a1cb98faSBarry Smith  14----8---15----9----16
1342*a1cb98faSBarry Smith   |\     5  |\      7 |
1343*a1cb98faSBarry Smith   | \       | \       |
1344*a1cb98faSBarry Smith  13   2    14    3    15
1345*a1cb98faSBarry Smith   | 4   \   | 6   \   |
1346*a1cb98faSBarry Smith   |       \ |       \ |
1347*a1cb98faSBarry Smith  11----6---12----7----13
1348*a1cb98faSBarry Smith   |\        |\        |
1349*a1cb98faSBarry Smith   | \    1  | \     3 |
1350*a1cb98faSBarry Smith  10   0    11    1    12
1351*a1cb98faSBarry Smith   | 0   \   | 2   \   |
1352*a1cb98faSBarry Smith   |       \ |       \ |
1353*a1cb98faSBarry Smith   8----4----9----5----10
1354*a1cb98faSBarry Smith .ve
1355*a1cb98faSBarry Smith 
1356*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1357768d5fceSMatthew G. Knepley @*/
1358d71ae5a4SJacob 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)
1359d71ae5a4SJacob Faibussowitsch {
13609318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1361fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1362fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1363fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1364552f7358SJed Brown 
1365768d5fceSMatthew G. Knepley   PetscFunctionBegin;
13669566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
13679566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
13689566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
13697ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
13709318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
13719318fe57SMatthew G. Knepley }
1372fdbf62faSLisandro Dalcin 
1373d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1374d71ae5a4SJacob Faibussowitsch {
13759318fe57SMatthew G. Knepley   DM       bdm, vol;
13769318fe57SMatthew G. Knepley   PetscInt i;
13779318fe57SMatthew G. Knepley 
13789318fe57SMatthew G. Knepley   PetscFunctionBegin;
137908401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
13809566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
13819566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
13829566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
13839566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
13849566063dSJacob Faibussowitsch   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
13859566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
138669d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
13879318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
13889318fe57SMatthew G. Knepley     Vec          v;
13899318fe57SMatthew G. Knepley     PetscScalar *x;
13909318fe57SMatthew G. Knepley     PetscInt     cDim, n;
13919318fe57SMatthew G. Knepley 
13929566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
13939566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
13949566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
13959566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
13969318fe57SMatthew G. Knepley     x += cDim;
13979318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
13989566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
13999566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
14009318fe57SMatthew G. Knepley   }
1401552f7358SJed Brown   PetscFunctionReturn(0);
1402552f7358SJed Brown }
1403552f7358SJed Brown 
140400dabe28SStefano Zampini /*@
140500dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
140600dabe28SStefano Zampini 
1407d083f849SBarry Smith   Collective
140800dabe28SStefano Zampini 
140900dabe28SStefano Zampini   Input Parameters:
1410*a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
141100dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
141200dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
141300dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
1414*a1cb98faSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or NULL for `DM_BOUNDARY_NONE`
1415*a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
141600dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
141700dabe28SStefano Zampini 
141800dabe28SStefano Zampini   Output Parameter:
1419*a1cb98faSBarry Smith . dm  - The `DM` object
142000dabe28SStefano Zampini 
142100dabe28SStefano Zampini   Level: beginner
142200dabe28SStefano Zampini 
1423*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
142400dabe28SStefano Zampini @*/
1425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1426d71ae5a4SJacob Faibussowitsch {
14279318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
142800dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
142900dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
143000dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
143100dabe28SStefano Zampini 
143200dabe28SStefano Zampini   PetscFunctionBegin;
14339566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14349566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14359566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1436d410b0cfSMatthew G. Knepley   if (!interpolate) {
1437d410b0cfSMatthew G. Knepley     DM udm;
143800dabe28SStefano Zampini 
14399566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
144069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
144100dabe28SStefano Zampini   }
14427ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
144300dabe28SStefano Zampini   PetscFunctionReturn(0);
144400dabe28SStefano Zampini }
144500dabe28SStefano Zampini 
1446a9074c1eSMatthew G. Knepley /*@C
1447*a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
1448a9074c1eSMatthew G. Knepley 
1449d083f849SBarry Smith   Logically Collective on dm
1450a9074c1eSMatthew G. Knepley 
1451a9074c1eSMatthew G. Knepley   Input Parameters:
1452a9074c1eSMatthew G. Knepley + dm - the DM context
1453a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1454a9074c1eSMatthew G. Knepley 
1455*a1cb98faSBarry Smith   Level: advanced
1456*a1cb98faSBarry Smith 
1457*a1cb98faSBarry Smith   Note:
1458a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1459a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1460a9074c1eSMatthew G. Knepley 
1461*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
1462a9074c1eSMatthew G. Knepley @*/
1463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1464d71ae5a4SJacob Faibussowitsch {
1465a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1466a9074c1eSMatthew G. Knepley 
1467a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1468a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14699566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
14709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
1471a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1472a9074c1eSMatthew G. Knepley }
1473a9074c1eSMatthew G. Knepley 
14749318fe57SMatthew G. Knepley /* Remap geometry to cylinder
147561a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
147661a622f3SMatthew G. Knepley 
14779318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
14789318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
14799318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
14800510c589SMatthew G. Knepley 
14819318fe57SMatthew G. Knepley        phi     = arctan(y/x)
14829318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
14839318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
14840510c589SMatthew G. Knepley 
14859318fe57SMatthew G. Knepley      so we remap them using
14860510c589SMatthew G. Knepley 
14879318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
14889318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
14890510c589SMatthew G. Knepley 
14909318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
14919318fe57SMatthew G. Knepley */
1492d71ae5a4SJacob 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[])
1493d71ae5a4SJacob Faibussowitsch {
14949318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
14959318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
149622cc497dSMatthew G. Knepley 
14979318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
14989318fe57SMatthew G. Knepley     f0[0] = u[0];
14999318fe57SMatthew G. Knepley     f0[1] = u[1];
15009318fe57SMatthew G. Knepley   } else {
15019318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
15020510c589SMatthew G. Knepley 
15039318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
15049318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
15059318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
15069318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
15079318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
15089318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
15099318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
15109318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
15119318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
15129318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
15139318fe57SMatthew G. Knepley     } else {
15149318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
15159318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
15169318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
15179318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
15189318fe57SMatthew G. Knepley     }
15199318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
15209318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
15219318fe57SMatthew G. Knepley   }
15229318fe57SMatthew G. Knepley   f0[2] = u[2];
15239318fe57SMatthew G. Knepley }
15240510c589SMatthew G. Knepley 
1525d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ)
1526d71ae5a4SJacob Faibussowitsch {
15270510c589SMatthew G. Knepley   const PetscInt dim = 3;
15289318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1529d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
15300510c589SMatthew G. Knepley 
15310510c589SMatthew G. Knepley   PetscFunctionBegin;
15329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15339566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
15340510c589SMatthew G. Knepley   /* Create topology */
15350510c589SMatthew G. Knepley   {
15360510c589SMatthew G. Knepley     PetscInt cone[8], c;
15370510c589SMatthew G. Knepley 
1538dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1539dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1540006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1541ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1542dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1543006a8963SMatthew G. Knepley     }
15449566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
15459566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
15469566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1547dd400576SPatrick Sanan     if (rank == 0) {
1548006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
15499371c9d4SSatish Balay         cone[0] = 15;
15509371c9d4SSatish Balay         cone[1] = 18;
15519371c9d4SSatish Balay         cone[2] = 17;
15529371c9d4SSatish Balay         cone[3] = 16;
15539371c9d4SSatish Balay         cone[4] = 31;
15549371c9d4SSatish Balay         cone[5] = 32;
15559371c9d4SSatish Balay         cone[6] = 33;
15569371c9d4SSatish Balay         cone[7] = 34;
15579566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
15589371c9d4SSatish Balay         cone[0] = 16;
15599371c9d4SSatish Balay         cone[1] = 17;
15609371c9d4SSatish Balay         cone[2] = 24;
15619371c9d4SSatish Balay         cone[3] = 23;
15629371c9d4SSatish Balay         cone[4] = 32;
15639371c9d4SSatish Balay         cone[5] = 36;
15649371c9d4SSatish Balay         cone[6] = 37;
15659371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
15669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
15679371c9d4SSatish Balay         cone[0] = 18;
15689371c9d4SSatish Balay         cone[1] = 27;
15699371c9d4SSatish Balay         cone[2] = 24;
15709371c9d4SSatish Balay         cone[3] = 17;
15719371c9d4SSatish Balay         cone[4] = 34;
15729371c9d4SSatish Balay         cone[5] = 33;
15739371c9d4SSatish Balay         cone[6] = 37;
15749371c9d4SSatish Balay         cone[7] = 38;
15759566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
15769371c9d4SSatish Balay         cone[0] = 29;
15779371c9d4SSatish Balay         cone[1] = 27;
15789371c9d4SSatish Balay         cone[2] = 18;
15799371c9d4SSatish Balay         cone[3] = 15;
15809371c9d4SSatish Balay         cone[4] = 35;
15819371c9d4SSatish Balay         cone[5] = 31;
15829371c9d4SSatish Balay         cone[6] = 34;
15839371c9d4SSatish Balay         cone[7] = 38;
15849566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
15859371c9d4SSatish Balay         cone[0] = 29;
15869371c9d4SSatish Balay         cone[1] = 15;
15879371c9d4SSatish Balay         cone[2] = 16;
15889371c9d4SSatish Balay         cone[3] = 23;
15899371c9d4SSatish Balay         cone[4] = 35;
15909371c9d4SSatish Balay         cone[5] = 36;
15919371c9d4SSatish Balay         cone[6] = 32;
15929371c9d4SSatish Balay         cone[7] = 31;
15939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1594006a8963SMatthew G. Knepley 
15959371c9d4SSatish Balay         cone[0] = 31;
15969371c9d4SSatish Balay         cone[1] = 34;
15979371c9d4SSatish Balay         cone[2] = 33;
15989371c9d4SSatish Balay         cone[3] = 32;
15999371c9d4SSatish Balay         cone[4] = 19;
16009371c9d4SSatish Balay         cone[5] = 22;
16019371c9d4SSatish Balay         cone[6] = 21;
16029371c9d4SSatish Balay         cone[7] = 20;
16039566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
16049371c9d4SSatish Balay         cone[0] = 32;
16059371c9d4SSatish Balay         cone[1] = 33;
16069371c9d4SSatish Balay         cone[2] = 37;
16079371c9d4SSatish Balay         cone[3] = 36;
16089371c9d4SSatish Balay         cone[4] = 22;
16099371c9d4SSatish Balay         cone[5] = 25;
16109371c9d4SSatish Balay         cone[6] = 26;
16119371c9d4SSatish Balay         cone[7] = 21;
16129566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
16139371c9d4SSatish Balay         cone[0] = 34;
16149371c9d4SSatish Balay         cone[1] = 38;
16159371c9d4SSatish Balay         cone[2] = 37;
16169371c9d4SSatish Balay         cone[3] = 33;
16179371c9d4SSatish Balay         cone[4] = 20;
16189371c9d4SSatish Balay         cone[5] = 21;
16199371c9d4SSatish Balay         cone[6] = 26;
16209371c9d4SSatish Balay         cone[7] = 28;
16219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
16229371c9d4SSatish Balay         cone[0] = 35;
16239371c9d4SSatish Balay         cone[1] = 38;
16249371c9d4SSatish Balay         cone[2] = 34;
16259371c9d4SSatish Balay         cone[3] = 31;
16269371c9d4SSatish Balay         cone[4] = 30;
16279371c9d4SSatish Balay         cone[5] = 19;
16289371c9d4SSatish Balay         cone[6] = 20;
16299371c9d4SSatish Balay         cone[7] = 28;
16309566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
16319371c9d4SSatish Balay         cone[0] = 35;
16329371c9d4SSatish Balay         cone[1] = 31;
16339371c9d4SSatish Balay         cone[2] = 32;
16349371c9d4SSatish Balay         cone[3] = 36;
16359371c9d4SSatish Balay         cone[4] = 30;
16369371c9d4SSatish Balay         cone[5] = 25;
16379371c9d4SSatish Balay         cone[6] = 22;
16389371c9d4SSatish Balay         cone[7] = 19;
16399566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
1640ae8bcbbbSMatthew G. Knepley 
16419371c9d4SSatish Balay         cone[0] = 19;
16429371c9d4SSatish Balay         cone[1] = 20;
16439371c9d4SSatish Balay         cone[2] = 21;
16449371c9d4SSatish Balay         cone[3] = 22;
16459371c9d4SSatish Balay         cone[4] = 15;
16469371c9d4SSatish Balay         cone[5] = 16;
16479371c9d4SSatish Balay         cone[6] = 17;
16489371c9d4SSatish Balay         cone[7] = 18;
16499566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
16509371c9d4SSatish Balay         cone[0] = 22;
16519371c9d4SSatish Balay         cone[1] = 21;
16529371c9d4SSatish Balay         cone[2] = 26;
16539371c9d4SSatish Balay         cone[3] = 25;
16549371c9d4SSatish Balay         cone[4] = 16;
16559371c9d4SSatish Balay         cone[5] = 23;
16569371c9d4SSatish Balay         cone[6] = 24;
16579371c9d4SSatish Balay         cone[7] = 17;
16589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
16599371c9d4SSatish Balay         cone[0] = 20;
16609371c9d4SSatish Balay         cone[1] = 28;
16619371c9d4SSatish Balay         cone[2] = 26;
16629371c9d4SSatish Balay         cone[3] = 21;
16639371c9d4SSatish Balay         cone[4] = 18;
16649371c9d4SSatish Balay         cone[5] = 17;
16659371c9d4SSatish Balay         cone[6] = 24;
16669371c9d4SSatish Balay         cone[7] = 27;
16679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
16689371c9d4SSatish Balay         cone[0] = 30;
16699371c9d4SSatish Balay         cone[1] = 28;
16709371c9d4SSatish Balay         cone[2] = 20;
16719371c9d4SSatish Balay         cone[3] = 19;
16729371c9d4SSatish Balay         cone[4] = 29;
16739371c9d4SSatish Balay         cone[5] = 15;
16749371c9d4SSatish Balay         cone[6] = 18;
16759371c9d4SSatish Balay         cone[7] = 27;
16769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
16779371c9d4SSatish Balay         cone[0] = 30;
16789371c9d4SSatish Balay         cone[1] = 19;
16799371c9d4SSatish Balay         cone[2] = 22;
16809371c9d4SSatish Balay         cone[3] = 25;
16819371c9d4SSatish Balay         cone[4] = 29;
16829371c9d4SSatish Balay         cone[5] = 23;
16839371c9d4SSatish Balay         cone[6] = 16;
16849371c9d4SSatish Balay         cone[7] = 15;
16859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
1686006a8963SMatthew G. Knepley       } else {
16879371c9d4SSatish Balay         cone[0] = 5;
16889371c9d4SSatish Balay         cone[1] = 8;
16899371c9d4SSatish Balay         cone[2] = 7;
16909371c9d4SSatish Balay         cone[3] = 6;
16919371c9d4SSatish Balay         cone[4] = 9;
16929371c9d4SSatish Balay         cone[5] = 12;
16939371c9d4SSatish Balay         cone[6] = 11;
16949371c9d4SSatish Balay         cone[7] = 10;
16959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
16969371c9d4SSatish Balay         cone[0] = 6;
16979371c9d4SSatish Balay         cone[1] = 7;
16989371c9d4SSatish Balay         cone[2] = 14;
16999371c9d4SSatish Balay         cone[3] = 13;
17009371c9d4SSatish Balay         cone[4] = 12;
17019371c9d4SSatish Balay         cone[5] = 15;
17029371c9d4SSatish Balay         cone[6] = 16;
17039371c9d4SSatish Balay         cone[7] = 11;
17049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
17059371c9d4SSatish Balay         cone[0] = 8;
17069371c9d4SSatish Balay         cone[1] = 17;
17079371c9d4SSatish Balay         cone[2] = 14;
17089371c9d4SSatish Balay         cone[3] = 7;
17099371c9d4SSatish Balay         cone[4] = 10;
17109371c9d4SSatish Balay         cone[5] = 11;
17119371c9d4SSatish Balay         cone[6] = 16;
17129371c9d4SSatish Balay         cone[7] = 18;
17139566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
17149371c9d4SSatish Balay         cone[0] = 19;
17159371c9d4SSatish Balay         cone[1] = 17;
17169371c9d4SSatish Balay         cone[2] = 8;
17179371c9d4SSatish Balay         cone[3] = 5;
17189371c9d4SSatish Balay         cone[4] = 20;
17199371c9d4SSatish Balay         cone[5] = 9;
17209371c9d4SSatish Balay         cone[6] = 10;
17219371c9d4SSatish Balay         cone[7] = 18;
17229566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
17239371c9d4SSatish Balay         cone[0] = 19;
17249371c9d4SSatish Balay         cone[1] = 5;
17259371c9d4SSatish Balay         cone[2] = 6;
17269371c9d4SSatish Balay         cone[3] = 13;
17279371c9d4SSatish Balay         cone[4] = 20;
17289371c9d4SSatish Balay         cone[5] = 15;
17299371c9d4SSatish Balay         cone[6] = 12;
17309371c9d4SSatish Balay         cone[7] = 9;
17319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1732006a8963SMatthew G. Knepley       }
1733d8c47e87SMatthew G. Knepley     }
17349566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
17359566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
17360510c589SMatthew G. Knepley   }
1737dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
17380510c589SMatthew G. Knepley   {
17390510c589SMatthew G. Knepley     Vec             coordinates;
17400510c589SMatthew G. Knepley     PetscSection    coordSection;
17410510c589SMatthew G. Knepley     PetscScalar    *coords;
17420510c589SMatthew G. Knepley     PetscInt        coordSize, v;
17430510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
17440510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
17450510c589SMatthew G. Knepley 
17460510c589SMatthew G. Knepley     /* Build coordinates */
17479566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
17489566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
17499566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
17509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
17510510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
17529566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
17539566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
17540510c589SMatthew G. Knepley     }
17559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
17569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
17579566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
17589566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
17599566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
17609566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
17619566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
17629566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1763dd400576SPatrick Sanan     if (rank == 0) {
17649371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
17659371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
17669371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
17679371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
17689371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
17699371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
17709371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
17719371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
17729371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
17739371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
17749371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
17759371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
17769371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
17779371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
17789371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
17799371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
17809371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
17819371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
17829371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
17839371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
17849371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
17859371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
17869371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
17879371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
17889371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
17899371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
17909371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
17919371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
17929371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
17939371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
17949371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
17959371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
17969371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
17979371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
17989371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
17999371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
18009371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
18019371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
18029371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
18039371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
18049371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
18059371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
18069371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
18079371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
18089371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
18099371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
18109371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
18119371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
1812ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
18139371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
18149371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
18159371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
18169371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
18179371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
18189371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
18199371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
18209371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
18219371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
18229371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
18239371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
18249371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
18259371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
18269371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
18279371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
18289371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
18299371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
18309371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
18319371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
18329371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
18339371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
18349371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
18359371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
18369371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
1837ae8bcbbbSMatthew G. Knepley       }
1838d8c47e87SMatthew G. Knepley     }
18399566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18409566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18419566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18420510c589SMatthew G. Knepley   }
1843006a8963SMatthew G. Knepley   /* Create periodicity */
1844006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
18456858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
18466858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1847006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
1848ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
18496858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
1850006a8963SMatthew G. Knepley 
18516858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
18526858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
18534fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1854006a8963SMatthew G. Knepley   }
1855dbc1dc17SMatthew G. Knepley   {
18569318fe57SMatthew G. Knepley     DM          cdm;
18579318fe57SMatthew G. Knepley     PetscDS     cds;
18589318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1859dbc1dc17SMatthew G. Knepley 
18609566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
18619566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
18629566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
18639566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
1864dbc1dc17SMatthew G. Knepley   }
18659318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
18669566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
18670510c589SMatthew G. Knepley   PetscFunctionReturn(0);
18680510c589SMatthew G. Knepley }
18690510c589SMatthew G. Knepley 
187024119c2aSMatthew G. Knepley /*@
18719318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
187224119c2aSMatthew G. Knepley 
1873d083f849SBarry Smith   Collective
187424119c2aSMatthew G. Knepley 
187524119c2aSMatthew G. Knepley   Input Parameters:
1876*a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
18779318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
187824119c2aSMatthew G. Knepley 
187924119c2aSMatthew G. Knepley   Output Parameter:
188024119c2aSMatthew G. Knepley . dm  - The DM object
188124119c2aSMatthew G. Knepley 
188224119c2aSMatthew G. Knepley   Level: beginner
188324119c2aSMatthew G. Knepley 
1884*a1cb98faSBarry Smith   Note:
1885*a1cb98faSBarry Smith   Here is the output numbering looking from the bottom of the cylinder:
1886*a1cb98faSBarry Smith .vb
1887*a1cb98faSBarry Smith        17-----14
1888*a1cb98faSBarry Smith         |     |
1889*a1cb98faSBarry Smith         |  2  |
1890*a1cb98faSBarry Smith         |     |
1891*a1cb98faSBarry Smith  17-----8-----7-----14
1892*a1cb98faSBarry Smith   |     |     |     |
1893*a1cb98faSBarry Smith   |  3  |  0  |  1  |
1894*a1cb98faSBarry Smith   |     |     |     |
1895*a1cb98faSBarry Smith  19-----5-----6-----13
1896*a1cb98faSBarry Smith         |     |
1897*a1cb98faSBarry Smith         |  4  |
1898*a1cb98faSBarry Smith         |     |
1899*a1cb98faSBarry Smith        19-----13
1900*a1cb98faSBarry Smith 
1901*a1cb98faSBarry Smith  and up through the top
1902*a1cb98faSBarry Smith 
1903*a1cb98faSBarry Smith        18-----16
1904*a1cb98faSBarry Smith         |     |
1905*a1cb98faSBarry Smith         |  2  |
1906*a1cb98faSBarry Smith         |     |
1907*a1cb98faSBarry Smith  18----10----11-----16
1908*a1cb98faSBarry Smith   |     |     |     |
1909*a1cb98faSBarry Smith   |  3  |  0  |  1  |
1910*a1cb98faSBarry Smith   |     |     |     |
1911*a1cb98faSBarry Smith  20-----9----12-----15
1912*a1cb98faSBarry Smith         |     |
1913*a1cb98faSBarry Smith         |  4  |
1914*a1cb98faSBarry Smith         |     |
1915*a1cb98faSBarry Smith        20-----15
1916*a1cb98faSBarry Smith .ve
1917*a1cb98faSBarry Smith 
1918*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
191924119c2aSMatthew G. Knepley @*/
1920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm)
1921d71ae5a4SJacob Faibussowitsch {
19229318fe57SMatthew G. Knepley   PetscFunctionBegin;
19239318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
19249566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
19259566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
19269566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
19279318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
19289318fe57SMatthew G. Knepley }
19299318fe57SMatthew G. Knepley 
1930d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
1931d71ae5a4SJacob Faibussowitsch {
193224119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1933412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
19349fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
193524119c2aSMatthew G. Knepley 
193624119c2aSMatthew G. Knepley   PetscFunctionBegin;
193763a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
19389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
19399566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1940412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
19419566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
194224119c2aSMatthew G. Knepley   /* Create topology */
194324119c2aSMatthew G. Knepley   {
194424119c2aSMatthew G. Knepley     PetscInt cone[6], c;
194524119c2aSMatthew G. Knepley 
1946dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
1947dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
19489566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19499566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
19509566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
195124119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19529371c9d4SSatish Balay       cone[0] = c + n * 1;
19539371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
19549371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
19559371c9d4SSatish Balay       cone[3] = c + n * 2;
19569371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
19579371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
19589566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
19599566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
196024119c2aSMatthew G. Knepley     }
19619566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
19629566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
196324119c2aSMatthew G. Knepley   }
196448a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
196524119c2aSMatthew G. Knepley   /* Create cylinder geometry */
196624119c2aSMatthew G. Knepley   {
196724119c2aSMatthew G. Knepley     Vec          coordinates;
196824119c2aSMatthew G. Knepley     PetscSection coordSection;
196924119c2aSMatthew G. Knepley     PetscScalar *coords;
1970412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
197124119c2aSMatthew G. Knepley 
197224119c2aSMatthew G. Knepley     /* Build coordinates */
19739566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
19749566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
19759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
19769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
197724119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
19789566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
19799566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
198024119c2aSMatthew G. Knepley     }
19819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
19829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
19839566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
19849566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
19859566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
19869566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
19879566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
19889566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
198924119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19909371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19919371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19929371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
19939371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19949371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19959371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
199624119c2aSMatthew G. Knepley     }
1997dd400576SPatrick Sanan     if (rank == 0) {
19989371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
19999371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
20009371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
20019371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
20029371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
20039371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
20049fe9f049SMatthew G. Knepley     }
20059566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
20069566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
20079566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
200824119c2aSMatthew G. Knepley   }
20099318fe57SMatthew G. Knepley   /* Interpolate */
20109566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
20119318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
20129318fe57SMatthew G. Knepley }
20139318fe57SMatthew G. Knepley 
20149318fe57SMatthew G. Knepley /*@
20159318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
20169318fe57SMatthew G. Knepley 
20179318fe57SMatthew G. Knepley   Collective
20189318fe57SMatthew G. Knepley 
20199318fe57SMatthew G. Knepley   Input Parameters:
2020*a1cb98faSBarry Smith + comm - The communicator for the `DM` object
20219318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
20229318fe57SMatthew G. Knepley - interpolate - Create edges and faces
20239318fe57SMatthew G. Knepley 
20249318fe57SMatthew G. Knepley   Output Parameter:
2025*a1cb98faSBarry Smith . dm  - The `DM` object
20269318fe57SMatthew G. Knepley 
20279318fe57SMatthew G. Knepley   Level: beginner
20289318fe57SMatthew G. Knepley 
2029*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
20309318fe57SMatthew G. Knepley @*/
2031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2032d71ae5a4SJacob Faibussowitsch {
20339318fe57SMatthew G. Knepley   PetscFunctionBegin;
20349318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
20359566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20369566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20379566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
203824119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
203924119c2aSMatthew G. Knepley }
204024119c2aSMatthew G. Knepley 
2041d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2042d71ae5a4SJacob Faibussowitsch {
204365a81367SMatthew G. Knepley   PetscReal prod = 0.0;
204465a81367SMatthew G. Knepley   PetscInt  i;
204565a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
204665a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
204765a81367SMatthew G. Knepley }
2048d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2049d71ae5a4SJacob Faibussowitsch {
205065a81367SMatthew G. Knepley   PetscReal prod = 0.0;
205165a81367SMatthew G. Knepley   PetscInt  i;
205265a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
205365a81367SMatthew G. Knepley   return prod;
205465a81367SMatthew G. Knepley }
205565a81367SMatthew G. Knepley 
205651a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2057d71ae5a4SJacob 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[])
2058d71ae5a4SJacob Faibussowitsch {
205951a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
206051a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
206151a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
206251a74b61SMatthew G. Knepley 
206351a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
206451a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
206551a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
206651a74b61SMatthew G. Knepley }
206751a74b61SMatthew G. Knepley 
2068d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2069d71ae5a4SJacob Faibussowitsch {
207065a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
207165a81367SMatthew G. Knepley   PetscSection   coordSection;
207265a81367SMatthew G. Knepley   Vec            coordinates;
207365a81367SMatthew G. Knepley   PetscScalar   *coords;
207465a81367SMatthew G. Knepley   PetscReal     *coordsIn;
2075064cae4fSPierre Jolivet   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e;
207665a81367SMatthew G. Knepley   PetscMPIInt    rank;
207765a81367SMatthew G. Knepley 
207865a81367SMatthew G. Knepley   PetscFunctionBegin;
20799318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
20809566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
20819566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
20829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
208365a81367SMatthew G. Knepley   switch (dim) {
208465a81367SMatthew G. Knepley   case 2:
208565a81367SMatthew G. Knepley     if (simplex) {
208651a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
208751a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
208865a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
208951a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
209065a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
209165a81367SMatthew G. Knepley       PetscInt        cone[3];
209265a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
209365a81367SMatthew G. Knepley 
20949371c9d4SSatish Balay       vertex[0] *= R / radius;
20959371c9d4SSatish Balay       vertex[1] *= R / radius;
20969371c9d4SSatish Balay       vertex[2] *= R / radius;
2097dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2098dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
209965a81367SMatthew G. Knepley       firstVertex = numCells;
210051a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
210165a81367SMatthew G. Knepley 
210265a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
210365a81367SMatthew G. Knepley 
210465a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
210551a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
210665a81367SMatthew G. Knepley       */
210765a81367SMatthew G. Knepley       /* Construct vertices */
21089566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2109dd400576SPatrick Sanan       if (rank == 0) {
211065a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
211165a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
211265a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
211365a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
211465a81367SMatthew G. Knepley               ++i;
211565a81367SMatthew G. Knepley             }
211665a81367SMatthew G. Knepley           }
211765a81367SMatthew G. Knepley         }
211845da822fSValeria Barra       }
211965a81367SMatthew G. Knepley       /* Construct graph */
21209566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
212165a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
212265a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
21239371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
21249371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
21259371c9d4SSatish Balay             ++k;
21269371c9d4SSatish Balay           }
212765a81367SMatthew G. Knepley         }
212863a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
212965a81367SMatthew G. Knepley       }
213065a81367SMatthew G. Knepley       /* Build Topology */
21319566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
213248a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
21339566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
213465a81367SMatthew G. Knepley       /* Cells */
213565a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
213665a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
213765a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
213865a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
21399371c9d4SSatish Balay               cone[0] = firstVertex + i;
21409371c9d4SSatish Balay               cone[1] = firstVertex + j;
21419371c9d4SSatish Balay               cone[2] = firstVertex + k;
214265a81367SMatthew G. Knepley               /* Check orientation */
214365a81367SMatthew G. Knepley               {
21449371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
21459371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
21469371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
21479371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
21489371c9d4SSatish Balay                 };
214965a81367SMatthew G. Knepley                 PetscReal normal[3];
215065a81367SMatthew G. Knepley                 PetscInt  e, f;
215165a81367SMatthew G. Knepley 
215265a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
215365a81367SMatthew G. Knepley                   normal[d] = 0.0;
215465a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
2155ad540459SPierre 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]);
215665a81367SMatthew G. Knepley                   }
215765a81367SMatthew G. Knepley                 }
21589371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
21599371c9d4SSatish Balay                   PetscInt tmp = cone[1];
21609371c9d4SSatish Balay                   cone[1]      = cone[2];
21619371c9d4SSatish Balay                   cone[2]      = tmp;
216265a81367SMatthew G. Knepley                 }
216365a81367SMatthew G. Knepley               }
21649566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
216565a81367SMatthew G. Knepley             }
216665a81367SMatthew G. Knepley           }
216765a81367SMatthew G. Knepley         }
216865a81367SMatthew G. Knepley       }
21699566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
21709566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
21719566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
217265a81367SMatthew G. Knepley     } else {
21732829fed8SMatthew G. Knepley       /*
21742829fed8SMatthew G. Knepley         12-21--13
21752829fed8SMatthew G. Knepley          |     |
21762829fed8SMatthew G. Knepley         25  4  24
21772829fed8SMatthew G. Knepley          |     |
21782829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
21792829fed8SMatthew G. Knepley    |     |     |     |
21802829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
21812829fed8SMatthew G. Knepley    |     |     |     |
21822829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
21832829fed8SMatthew G. Knepley          |     |
21842829fed8SMatthew G. Knepley         20  1  19
21852829fed8SMatthew G. Knepley          |     |
21862829fed8SMatthew G. Knepley         10-18--11
21872829fed8SMatthew G. Knepley          |     |
21882829fed8SMatthew G. Knepley         23  2  22
21892829fed8SMatthew G. Knepley          |     |
21902829fed8SMatthew G. Knepley         12-21--13
21912829fed8SMatthew G. Knepley        */
21922829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
21932829fed8SMatthew G. Knepley 
2194dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2195dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2196dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
219765a81367SMatthew G. Knepley       firstVertex = numCells;
219865a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
21992829fed8SMatthew G. Knepley       /* Build Topology */
22009566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
220148a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
220248a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
22039566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2204dd400576SPatrick Sanan       if (rank == 0) {
22052829fed8SMatthew G. Knepley         /* Cell 0 */
22069371c9d4SSatish Balay         cone[0] = 14;
22079371c9d4SSatish Balay         cone[1] = 15;
22089371c9d4SSatish Balay         cone[2] = 16;
22099371c9d4SSatish Balay         cone[3] = 17;
22109566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
22119371c9d4SSatish Balay         ornt[0] = 0;
22129371c9d4SSatish Balay         ornt[1] = 0;
22139371c9d4SSatish Balay         ornt[2] = 0;
22149371c9d4SSatish Balay         ornt[3] = 0;
22159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
22162829fed8SMatthew G. Knepley         /* Cell 1 */
22179371c9d4SSatish Balay         cone[0] = 18;
22189371c9d4SSatish Balay         cone[1] = 19;
22199371c9d4SSatish Balay         cone[2] = 14;
22209371c9d4SSatish Balay         cone[3] = 20;
22219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
22229371c9d4SSatish Balay         ornt[0] = 0;
22239371c9d4SSatish Balay         ornt[1] = 0;
22249371c9d4SSatish Balay         ornt[2] = -1;
22259371c9d4SSatish Balay         ornt[3] = 0;
22269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
22272829fed8SMatthew G. Knepley         /* Cell 2 */
22289371c9d4SSatish Balay         cone[0] = 21;
22299371c9d4SSatish Balay         cone[1] = 22;
22309371c9d4SSatish Balay         cone[2] = 18;
22319371c9d4SSatish Balay         cone[3] = 23;
22329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
22339371c9d4SSatish Balay         ornt[0] = 0;
22349371c9d4SSatish Balay         ornt[1] = 0;
22359371c9d4SSatish Balay         ornt[2] = -1;
22369371c9d4SSatish Balay         ornt[3] = 0;
22379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
22382829fed8SMatthew G. Knepley         /* Cell 3 */
22399371c9d4SSatish Balay         cone[0] = 19;
22409371c9d4SSatish Balay         cone[1] = 22;
22419371c9d4SSatish Balay         cone[2] = 24;
22429371c9d4SSatish Balay         cone[3] = 15;
22439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
22449371c9d4SSatish Balay         ornt[0] = -1;
22459371c9d4SSatish Balay         ornt[1] = -1;
22469371c9d4SSatish Balay         ornt[2] = 0;
22479371c9d4SSatish Balay         ornt[3] = -1;
22489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
22492829fed8SMatthew G. Knepley         /* Cell 4 */
22509371c9d4SSatish Balay         cone[0] = 16;
22519371c9d4SSatish Balay         cone[1] = 24;
22529371c9d4SSatish Balay         cone[2] = 21;
22539371c9d4SSatish Balay         cone[3] = 25;
22549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
22559371c9d4SSatish Balay         ornt[0] = -1;
22569371c9d4SSatish Balay         ornt[1] = -1;
22579371c9d4SSatish Balay         ornt[2] = -1;
22589371c9d4SSatish Balay         ornt[3] = 0;
22599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
22602829fed8SMatthew G. Knepley         /* Cell 5 */
22619371c9d4SSatish Balay         cone[0] = 20;
22629371c9d4SSatish Balay         cone[1] = 17;
22639371c9d4SSatish Balay         cone[2] = 25;
22649371c9d4SSatish Balay         cone[3] = 23;
22659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
22669371c9d4SSatish Balay         ornt[0] = -1;
22679371c9d4SSatish Balay         ornt[1] = -1;
22689371c9d4SSatish Balay         ornt[2] = -1;
22699371c9d4SSatish Balay         ornt[3] = -1;
22709566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
22712829fed8SMatthew G. Knepley         /* Edges */
22729371c9d4SSatish Balay         cone[0] = 6;
22739371c9d4SSatish Balay         cone[1] = 7;
22749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
22759371c9d4SSatish Balay         cone[0] = 7;
22769371c9d4SSatish Balay         cone[1] = 8;
22779566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
22789371c9d4SSatish Balay         cone[0] = 8;
22799371c9d4SSatish Balay         cone[1] = 9;
22809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
22819371c9d4SSatish Balay         cone[0] = 9;
22829371c9d4SSatish Balay         cone[1] = 6;
22839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
22849371c9d4SSatish Balay         cone[0] = 10;
22859371c9d4SSatish Balay         cone[1] = 11;
22869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
22879371c9d4SSatish Balay         cone[0] = 11;
22889371c9d4SSatish Balay         cone[1] = 7;
22899566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
22909371c9d4SSatish Balay         cone[0] = 6;
22919371c9d4SSatish Balay         cone[1] = 10;
22929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
22939371c9d4SSatish Balay         cone[0] = 12;
22949371c9d4SSatish Balay         cone[1] = 13;
22959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
22969371c9d4SSatish Balay         cone[0] = 13;
22979371c9d4SSatish Balay         cone[1] = 11;
22989566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
22999371c9d4SSatish Balay         cone[0] = 10;
23009371c9d4SSatish Balay         cone[1] = 12;
23019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
23029371c9d4SSatish Balay         cone[0] = 13;
23039371c9d4SSatish Balay         cone[1] = 8;
23049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
23059371c9d4SSatish Balay         cone[0] = 12;
23069371c9d4SSatish Balay         cone[1] = 9;
23079566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
230845da822fSValeria Barra       }
23099566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
23109566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
23112829fed8SMatthew G. Knepley       /* Build coordinates */
23129566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2313dd400576SPatrick Sanan       if (rank == 0) {
23149371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
23159371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
23169371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
23179371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
23189371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
23199371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
23209371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
23219371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
23229371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
23239371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
23249371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
23259371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
23269371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
23279371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
23289371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
23299371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
23309371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
23319371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
23329371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
23339371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
23349371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
23359371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
23369371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
23379371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
233865a81367SMatthew G. Knepley       }
233945da822fSValeria Barra     }
234065a81367SMatthew G. Knepley     break;
234165a81367SMatthew G. Knepley   case 3:
2342116ded15SMatthew G. Knepley     if (simplex) {
2343116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
234451a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
234551a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
234651a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2347116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2348116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
23499371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
23509371c9d4SSatish Balay         {0, 1, 2, 3},
23519371c9d4SSatish Balay         {0, 2, 3, 1},
23529371c9d4SSatish Balay         {0, 3, 1, 2},
23539371c9d4SSatish Balay         {1, 0, 3, 2},
23549371c9d4SSatish Balay         {1, 2, 0, 3},
23559371c9d4SSatish Balay         {1, 3, 2, 0},
23569371c9d4SSatish Balay         {2, 0, 1, 3},
23579371c9d4SSatish Balay         {2, 1, 3, 0},
23589371c9d4SSatish Balay         {2, 3, 0, 1},
23599371c9d4SSatish Balay         {3, 0, 2, 1},
23609371c9d4SSatish Balay         {3, 1, 0, 2},
23619371c9d4SSatish Balay         {3, 2, 1, 0}
23629371c9d4SSatish Balay       };
2363116ded15SMatthew G. Knepley       PetscInt  cone[4];
2364116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2365116ded15SMatthew G. Knepley 
23669371c9d4SSatish Balay       vertexA[0] *= R;
23679371c9d4SSatish Balay       vertexA[1] *= R;
23689371c9d4SSatish Balay       vertexA[2] *= R;
23699371c9d4SSatish Balay       vertexA[3] *= R;
23709371c9d4SSatish Balay       vertexB[0] *= R;
23719371c9d4SSatish Balay       vertexB[1] *= R;
23729371c9d4SSatish Balay       vertexB[2] *= R;
23739371c9d4SSatish Balay       vertexB[3] *= R;
23749371c9d4SSatish Balay       vertexC[0] *= R;
23759371c9d4SSatish Balay       vertexC[1] *= R;
23769371c9d4SSatish Balay       vertexC[2] *= R;
23779371c9d4SSatish Balay       vertexC[3] *= R;
2378dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2379dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2380116ded15SMatthew G. Knepley       firstVertex = numCells;
2381116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2382116ded15SMatthew G. Knepley 
2383116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2384116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2385116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2386116ded15SMatthew G. Knepley 
2387116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
23886333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2389116ded15SMatthew G. Knepley 
2390116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2391116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2392116ded15SMatthew G. Knepley       */
2393116ded15SMatthew G. Knepley       /* Construct vertices */
23949566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2395116ded15SMatthew G. Knepley       i = 0;
2396dd400576SPatrick Sanan       if (rank == 0) {
2397116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2398116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2399116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2400116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2401116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2402116ded15SMatthew G. Knepley                 ++i;
2403116ded15SMatthew G. Knepley               }
2404116ded15SMatthew G. Knepley             }
2405116ded15SMatthew G. Knepley           }
2406116ded15SMatthew G. Knepley         }
2407116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2408116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2409116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2410116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2411116ded15SMatthew G. Knepley             ++i;
2412116ded15SMatthew G. Knepley           }
2413116ded15SMatthew G. Knepley         }
2414116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2415116ded15SMatthew G. Knepley           s[3] = 1;
2416116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2417116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2418116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2419116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2420116ded15SMatthew G. Knepley                 ++i;
2421116ded15SMatthew G. Knepley               }
2422116ded15SMatthew G. Knepley             }
2423116ded15SMatthew G. Knepley           }
2424116ded15SMatthew G. Knepley         }
242545da822fSValeria Barra       }
242663a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2427116ded15SMatthew G. Knepley       /* Construct graph */
24289566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2429116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2430116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
24319371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
24329371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
24339371c9d4SSatish Balay             ++k;
24349371c9d4SSatish Balay           }
2435116ded15SMatthew G. Knepley         }
243663a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2437116ded15SMatthew G. Knepley       }
2438116ded15SMatthew G. Knepley       /* Build Topology */
24399566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
244048a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
24419566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2442116ded15SMatthew G. Knepley       /* Cells */
2443dd400576SPatrick Sanan       if (rank == 0) {
2444116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2445116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2446116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2447116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
24489371c9d4SSatish 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]) {
24499371c9d4SSatish Balay                   cone[0] = firstVertex + i;
24509371c9d4SSatish Balay                   cone[1] = firstVertex + j;
24519371c9d4SSatish Balay                   cone[2] = firstVertex + k;
24529371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2453116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2454116ded15SMatthew G. Knepley                   {
24559371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
24569371c9d4SSatish 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}}},
2457116ded15SMatthew G. Knepley 
24589371c9d4SSatish 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}}},
2459116ded15SMatthew G. Knepley 
24609371c9d4SSatish 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}}},
2461116ded15SMatthew G. Knepley 
24629371c9d4SSatish 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}} }
24639371c9d4SSatish Balay                     };
2464116ded15SMatthew G. Knepley                     PetscReal normal[4];
2465116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2466116ded15SMatthew G. Knepley 
2467116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2468116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2469116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2470116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2471116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2472116ded15SMatthew 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]);
2473116ded15SMatthew G. Knepley                           }
2474116ded15SMatthew G. Knepley                         }
2475116ded15SMatthew G. Knepley                       }
2476116ded15SMatthew G. Knepley                     }
24779371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
24789371c9d4SSatish Balay                       PetscInt tmp = cone[1];
24799371c9d4SSatish Balay                       cone[1]      = cone[2];
24809371c9d4SSatish Balay                       cone[2]      = tmp;
24819371c9d4SSatish Balay                     }
2482116ded15SMatthew G. Knepley                   }
24839566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2484116ded15SMatthew G. Knepley                 }
2485116ded15SMatthew G. Knepley               }
2486116ded15SMatthew G. Knepley             }
2487116ded15SMatthew G. Knepley           }
2488116ded15SMatthew G. Knepley         }
248945da822fSValeria Barra       }
24909566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
24919566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
24929566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2493116ded15SMatthew G. Knepley     }
2494f4d061e9SPierre Jolivet     break;
2495d71ae5a4SJacob Faibussowitsch   default:
2496d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
249765a81367SMatthew G. Knepley   }
249865a81367SMatthew G. Knepley   /* Create coordinates */
24999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
25009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
25019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
25029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
25032829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
25049566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
25059566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
25062829fed8SMatthew G. Knepley   }
25079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
25089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25099566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25109566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
25119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25129566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25139566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
25149566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
25159371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
2516ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
25179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
25189566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
25199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
25209566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
252151a74b61SMatthew G. Knepley   {
252251a74b61SMatthew G. Knepley     DM          cdm;
252351a74b61SMatthew G. Knepley     PetscDS     cds;
25249318fe57SMatthew G. Knepley     PetscScalar c = R;
252551a74b61SMatthew G. Knepley 
25269566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
25279566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
25289566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
25299566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
253051a74b61SMatthew G. Knepley   }
25319318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
25329566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
25339318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
25349318fe57SMatthew G. Knepley }
25359318fe57SMatthew G. Knepley 
2536b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
2537b7f5c055SJed Brown 
2538b7f5c055SJed Brown /*
2539b7f5c055SJed Brown  The Schwarz P implicit surface is
2540b7f5c055SJed Brown 
2541b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2542b7f5c055SJed Brown */
2543d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2544d71ae5a4SJacob Faibussowitsch {
2545b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2546b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2547b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
2548b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2549b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
2550ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
2551b7f5c055SJed Brown   }
2552b7f5c055SJed Brown }
2553b7f5c055SJed Brown 
25544663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2555d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2556d71ae5a4SJacob Faibussowitsch {
2557ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
25584663dae6SJed Brown   return 0;
25594663dae6SJed Brown }
25604663dae6SJed Brown 
2561b7f5c055SJed Brown /*
2562b7f5c055SJed Brown  The Gyroid implicit surface is
2563b7f5c055SJed Brown 
2564b7f5c055SJed 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)
2565b7f5c055SJed Brown 
2566b7f5c055SJed Brown */
2567d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2568d71ae5a4SJacob Faibussowitsch {
2569b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2570b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2571b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2572b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2573b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2574b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2575b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2576b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2577b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2578b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2579b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2580b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2581b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2582b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2583b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2584b7f5c055SJed Brown }
2585b7f5c055SJed Brown 
25864663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2587d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2588d71ae5a4SJacob Faibussowitsch {
25894663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
25904663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
25914663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
25924663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
25934663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
25944663dae6SJed Brown   return 0;
25954663dae6SJed Brown }
25964663dae6SJed Brown 
2597b7f5c055SJed Brown /*
2598b7f5c055SJed Brown    We wish to solve
2599b7f5c055SJed Brown 
2600b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2601b7f5c055SJed Brown 
2602b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2603b7f5c055SJed 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
2604b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2605b7f5c055SJed Brown 
2606b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2607b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2608b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2609b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2610b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2611b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2612b7f5c055SJed Brown 
2613b7f5c055SJed Brown      f(y) = 0                       1 equation
2614b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2615b7f5c055SJed Brown 
2616b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2617b7f5c055SJed Brown */
2618d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
2619d71ae5a4SJacob Faibussowitsch {
2620b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2621b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
26222f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
26239371c9d4SSatish Balay   PetscReal n_y[3][3] = {
26249371c9d4SSatish Balay     {0, 0, 0},
26259371c9d4SSatish Balay     {0, 0, 0},
26269371c9d4SSatish Balay     {0, 0, 0}
26279371c9d4SSatish Balay   };
2628b7f5c055SJed Brown 
2629b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2630b7f5c055SJed Brown 
2631b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
2632b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2633ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
2634b7f5c055SJed Brown 
2635b7f5c055SJed Brown   // Define the Householder reflector
2636b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2637b7f5c055SJed Brown   n[0] += norm * sign;
2638b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
2639b7f5c055SJed Brown 
2640b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2641b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2642b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2643b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2644b7f5c055SJed Brown 
2645b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2646b7f5c055SJed Brown     n[i] /= norm;
2647b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
2648b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2649b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2650b7f5c055SJed Brown     }
2651b7f5c055SJed Brown   }
2652b7f5c055SJed Brown 
2653b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2654b7f5c055SJed 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];
2655b7f5c055SJed Brown 
2656b7f5c055SJed Brown   res[0] = f;
2657b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2658b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2659b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2660b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
2661b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
2662b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2663b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2664b7f5c055SJed Brown   }
2665b7f5c055SJed Brown }
2666b7f5c055SJed Brown 
2667b7f5c055SJed Brown /*
2668b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2669b7f5c055SJed Brown */
2670d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
2671d71ae5a4SJacob Faibussowitsch {
2672b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2673b7f5c055SJed Brown 
2674b7f5c055SJed Brown   PetscFunctionBegin;
2675b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
2676b7f5c055SJed Brown     PetscScalar res[3], J[9];
2677b7f5c055SJed Brown     PetscReal   resnorm;
2678b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2679b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2680b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
268163a3b9bcSJacob 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])));
2682b7f5c055SJed Brown     }
2683b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2684b7f5c055SJed Brown 
2685b7f5c055SJed Brown     // Take the Newton step
26869566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2687b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2688b7f5c055SJed Brown   }
2689b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
2690b7f5c055SJed Brown   PetscFunctionReturn(0);
2691b7f5c055SJed Brown }
2692b7f5c055SJed Brown 
2693b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2694b7f5c055SJed Brown 
2695d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
2696d71ae5a4SJacob Faibussowitsch {
2697b7f5c055SJed Brown   PetscMPIInt rank;
2698b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2699b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
2700b7f5c055SJed Brown   PetscInt            *cells_flat = NULL;
2701b7f5c055SJed Brown   PetscReal           *vtxCoords  = NULL;
2702b7f5c055SJed Brown   TPSEvaluateFunc      evalFunc   = NULL;
27034663dae6SJed Brown   PetscSimplePointFunc normalFunc = NULL;
2704b7f5c055SJed Brown   DMLabel              label;
2705b7f5c055SJed Brown 
2706b7f5c055SJed Brown   PetscFunctionBegin;
27079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
270863a3b9bcSJacob 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);
2709b7f5c055SJed Brown   switch (tpstype) {
2710b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2711b7f5c055SJed 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");
2712c5853193SPierre Jolivet     if (rank == 0) {
2713b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2714b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2715b7f5c055SJed Brown       PetscReal L = 1;
2716b7f5c055SJed Brown 
2717b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
2718b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
2719b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
2720b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
2721b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2722b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
27239566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
27249566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
27259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
27269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
2727b7f5c055SJed Brown       // x-normal pipes
2728b7f5c055SJed Brown       vcount = 0;
2729b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
2730b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2731b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2732b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2733b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
2734b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2735b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2736b7f5c055SJed Brown             }
2737b7f5c055SJed Brown           }
2738b7f5c055SJed Brown         }
2739b7f5c055SJed Brown       }
2740b7f5c055SJed Brown       // y-normal pipes
2741b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2742b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
2743b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2744b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2745b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2746b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
2747b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2748b7f5c055SJed Brown             }
2749b7f5c055SJed Brown           }
2750b7f5c055SJed Brown         }
2751b7f5c055SJed Brown       }
2752b7f5c055SJed Brown       // z-normal pipes
2753b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2754b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2755b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
2756b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2757b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2758b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2759b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
2760b7f5c055SJed Brown             }
2761b7f5c055SJed Brown           }
2762b7f5c055SJed Brown         }
2763b7f5c055SJed Brown       }
2764b7f5c055SJed Brown       // junctions
2765b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2766b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2767b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2768b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
2769b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2770b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
2771b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
2772b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
2773b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
2774b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
2775b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
2776b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
2777b7f5c055SJed Brown                 }
2778b7f5c055SJed Brown               }
2779b7f5c055SJed Brown             }
2780b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2781b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
2782b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
2783b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
2784b7f5c055SJed Brown             };
2785b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
27869371c9d4SSatish 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};
2787b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
27889371c9d4SSatish 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};
2789b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
2790b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2791b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
2792b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
2793b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
2794b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
2795b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
2796b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
2797b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
2798b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
2799b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
2800b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2801b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2802b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
2803b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
2804b7f5c055SJed Brown                   numEdges++;
2805b7f5c055SJed Brown                 }
2806b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2807b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2808b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
2809b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
2810b7f5c055SJed Brown                   numEdges++;
2811b7f5c055SJed Brown                 }
2812b7f5c055SJed Brown               }
2813b7f5c055SJed Brown             }
2814b7f5c055SJed Brown           }
2815b7f5c055SJed Brown         }
2816b7f5c055SJed Brown       }
281763a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
2818b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
2819b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2820b7f5c055SJed Brown     }
2821b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
28224663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
2823b7f5c055SJed Brown     break;
2824b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2825c5853193SPierre Jolivet     if (rank == 0) {
2826b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2827b7f5c055SJed Brown       //
2828b7f5c055SJed 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)
2829b7f5c055SJed Brown       //
2830b7f5c055SJed Brown       // on the cell [0,2]^3.
2831b7f5c055SJed Brown       //
2832b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2833b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2834b7f5c055SJed Brown       // like a boomerang:
2835b7f5c055SJed Brown       //
2836b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2837b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2838b7f5c055SJed Brown       //                                                              //
2839b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2840b7f5c055SJed Brown       //      \                                   /            \      //
2841b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2842b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2843b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2844b7f5c055SJed Brown       //                                                              //
2845b7f5c055SJed Brown       //                                                              //
2846b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2847b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2848b7f5c055SJed Brown       //                                                              //
2849b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2850b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2851b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2852b7f5c055SJed Brown       //            \                       /                \        //
2853b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2854b7f5c055SJed Brown       //
2855b7f5c055SJed Brown       //
2856b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2857b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2858b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2859b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2860b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2861b7f5c055SJed Brown       //
2862b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2863b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2864b7f5c055SJed Brown       //
2865b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2866b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2867b7f5c055SJed Brown 
2868b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
2869b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
2870b7f5c055SJed Brown       PetscInt extentPlus[3];
2871b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
28729371c9d4SSatish 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;
28739371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
28749371c9d4SSatish Balay   /* face to vertex within the coarse discretization of a single gyroid block */
2875b7f5c055SJed Brown   /* layer 0 */
28769371c9d4SSatish Balay         {A,           C,           K,           G          },
28779371c9d4SSatish Balay         {C,           B,           II,          K          },
28789371c9d4SSatish Balay         {D,           A,           H,           L          },
28799371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
28809371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
28819371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
28829371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
28839371c9d4SSatish Balay         {B,           F,           M,           II         },
2884b7f5c055SJed Brown  /* layer 1 */
28859371c9d4SSatish Balay         {G,           K,           Q,           O          },
28869371c9d4SSatish Balay         {K,           II,          P,           Q          },
28879371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
28889371c9d4SSatish Balay         {J,           L,           R,           P          },
28899371c9d4SSatish Balay         {N,           J,           P,           S          },
28909371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
28919371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
28929371c9d4SSatish Balay         {II,          M,           T,           P          },
2893b7f5c055SJed Brown  /* layer 2 */
28949371c9d4SSatish Balay         {O,           Q,           Y,           U          },
28959371c9d4SSatish Balay         {Q,           P,           W,           Y          },
28969371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
28979371c9d4SSatish Balay         {P,           R,           Ap,          W          },
28989371c9d4SSatish Balay         {S,           P,           X,           Bp         },
28999371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
29009371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
29019371c9d4SSatish Balay         {P,           T,           Z,           X          },
2902b7f5c055SJed Brown  /* layer 3 */
29039371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
29049371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
29059371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
29069371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
29079371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
29089371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
29099371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
29109371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
2911b7f5c055SJed Brown  /* layer 4 */
29129371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
29139371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
29149371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
29159371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
29169371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
29179371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
29189371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
29199371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
2920b7f5c055SJed Brown  /* layer 5 */
29219371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
29229371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
29239371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
29249371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
29259371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
29269371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
29279371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
29289371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
2929b7f5c055SJed Brown  /* layer 6 */
29309371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
29319371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
29329371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
29339371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
29349371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
29359371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
29369371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
29379371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
2938b7f5c055SJed Brown  /* layer 7 (the top is the periodic image of the bottom of layer 0) */
29399371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
29409371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
29419371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
29429371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
29439371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
29449371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
29459371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
29469371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
2947b7f5c055SJed Brown       };
2948b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
29499371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
2950bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
2951bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
2952bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
2953bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
2954bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
2955bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
2956b7f5c055SJed Brown 
2957bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
2958bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
2959bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
2960bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
2961bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
2962bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
2963bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
2964bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
2965b7f5c055SJed Brown 
2966bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
2967bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
2968bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
2969bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
2970bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
2971bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
2972b7f5c055SJed Brown 
2973bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
2974bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
2975bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
2976bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
2977bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
2978bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
2979bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
2980bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
2981b7f5c055SJed Brown 
2982bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
2983bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
2984bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
2985bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
2986bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
2987bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
2988b7f5c055SJed Brown 
2989bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
2990bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
2991bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
2992bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
2993bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
2994bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
2995bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
2996bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
2997b7f5c055SJed Brown 
2998bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
2999bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
3000bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
3001bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
3002bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
3003bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
3004b7f5c055SJed Brown 
3005bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3006bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3007bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3008bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3009bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3010bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3011bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3012bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3013b7f5c055SJed Brown       };
3014b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3015b7f5c055SJed Brown       PetscBool *seen;
3016b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3017b7f5c055SJed Brown       PetscInt   count;
3018b7f5c055SJed Brown 
3019b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3020b7f5c055SJed Brown       numBlocks = 1;
3021b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3022b7f5c055SJed Brown       numBlocksPlus = 1;
3023b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3024b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
30259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
30269566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3027b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3028b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3029b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3030b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3031b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3032b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3033b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3034b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3035b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3036b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3037b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3038b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3039b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3040b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3041b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3042b7f5c055SJed Brown 
3043b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3044b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3045b7f5c055SJed Brown               }
3046b7f5c055SJed Brown             }
3047b7f5c055SJed Brown           }
3048b7f5c055SJed Brown         }
3049b7f5c055SJed Brown       }
30509371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
30519371c9d4SSatish Balay         if (seen[i]) numVertices++;
3052b7f5c055SJed Brown       count = 0;
30539566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
30549566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3055b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3056b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3057b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3058b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3059b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3060b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3061b7f5c055SJed Brown 
3062b7f5c055SJed Brown               if (seen[vIdx]) {
3063b7f5c055SJed Brown                 PetscInt thisVert;
3064b7f5c055SJed Brown 
3065b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3066b7f5c055SJed Brown 
3067b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3068b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3069b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3070b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3071b7f5c055SJed Brown               }
3072b7f5c055SJed Brown             }
3073b7f5c055SJed Brown           }
3074b7f5c055SJed Brown         }
3075b7f5c055SJed Brown       }
3076b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3077b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3078ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3079b7f5c055SJed Brown         }
3080b7f5c055SJed Brown       }
30819566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
30829566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3083b7f5c055SJed Brown       cells_flat = cells[0][0];
3084b7f5c055SJed Brown       numEdges   = 0;
3085b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3086b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3087b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3088b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3089b7f5c055SJed Brown 
3090b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3091b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3092b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3093b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3094b7f5c055SJed Brown             }
3095b7f5c055SJed Brown           }
3096b7f5c055SJed Brown         }
3097b7f5c055SJed Brown       }
30989566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
30999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3100b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3101b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3102b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3103b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3104b7f5c055SJed Brown 
3105b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3106b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3107b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3108b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3109b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3110b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3111b7f5c055SJed Brown               }
3112b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3113b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3114b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3115b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3116b7f5c055SJed Brown               }
3117b7f5c055SJed Brown             }
3118b7f5c055SJed Brown           }
3119b7f5c055SJed Brown         }
3120b7f5c055SJed Brown       }
3121b7f5c055SJed Brown     }
3122b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
31234663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3124b7f5c055SJed Brown     break;
3125b7f5c055SJed Brown   }
3126b7f5c055SJed Brown 
31279566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3128c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
31299566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
31309566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3131b7f5c055SJed Brown   {
3132b7f5c055SJed Brown     DM idm;
31339566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
313469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3135b7f5c055SJed Brown   }
3136c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
31379566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
31389566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3139b7f5c055SJed Brown 
31409566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
31419566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3142b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3143b7f5c055SJed Brown     PetscInt        njoin;
3144b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
31459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
314663a3b9bcSJacob 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]);
31479566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
31489566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3149b7f5c055SJed Brown   }
31509566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
31519566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
31521436d7faSJed Brown   if (tps_distribute) {
31531436d7faSJed Brown     DM               pdm = NULL;
31541436d7faSJed Brown     PetscPartitioner part;
31551436d7faSJed Brown 
31569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
31579566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
31589566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
315948a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
31601436d7faSJed Brown     // Do not auto-distribute again
31619566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
31621436d7faSJed Brown   }
3163b7f5c055SJed Brown 
31649566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3165b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3166b7f5c055SJed Brown     PetscInt     m;
3167b7f5c055SJed Brown     DM           dmf;
3168b7f5c055SJed Brown     Vec          X;
3169b7f5c055SJed Brown     PetscScalar *x;
31709566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
317169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3172b7f5c055SJed Brown 
31739566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
31749566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
31759566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
317648a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
31779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3178b7f5c055SJed Brown   }
3179b7f5c055SJed Brown 
3180b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
31819566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
31829566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3183b7f5c055SJed Brown 
3184b7f5c055SJed Brown   if (thickness > 0) {
31854663dae6SJed Brown     DM              edm, cdm, ecdm;
31864663dae6SJed Brown     DMPlexTransform tr;
31874663dae6SJed Brown     const char     *prefix;
31884663dae6SJed Brown     PetscOptions    options;
31894663dae6SJed Brown     // Code from DMPlexExtrude
31904663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
31914663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
31924663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
31934663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
31944663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
31954663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
31964663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
31974663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
31984663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
31994663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
32004663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
32014663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
32024663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
32034663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
32044663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
32054663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
32064663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
32074663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
32084663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
32094663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
32104663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
32114663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
32124663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
32134663dae6SJed Brown     if (edm) {
32144663dae6SJed Brown       ((DM_Plex *)edm->data)->printFEM    = ((DM_Plex *)dm->data)->printFEM;
32154663dae6SJed Brown       ((DM_Plex *)edm->data)->printL2     = ((DM_Plex *)dm->data)->printL2;
3216f5867de0SMatthew G. Knepley       ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate;
32174663dae6SJed Brown     }
321869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3219b7f5c055SJed Brown   }
3220b7f5c055SJed Brown   PetscFunctionReturn(0);
3221b7f5c055SJed Brown }
3222b7f5c055SJed Brown 
3223b7f5c055SJed Brown /*@
3224b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3225b7f5c055SJed Brown 
3226b7f5c055SJed Brown   Collective
3227b7f5c055SJed Brown 
3228b7f5c055SJed Brown   Input Parameters:
3229*a1cb98faSBarry Smith + comm   - The communicator for the `DM` object
3230b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
3231b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
3232b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
32331436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3234817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
32351436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
3236817da375SSatish Balay - thickness - Thickness in normal direction
3237b7f5c055SJed Brown 
3238b7f5c055SJed Brown   Output Parameter:
3239*a1cb98faSBarry Smith . dm  - The `DM` object
3240*a1cb98faSBarry Smith 
3241*a1cb98faSBarry Smith   Level: beginner
3242b7f5c055SJed Brown 
3243b7f5c055SJed Brown   Notes:
3244b7f5c055SJed 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.
3245b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
3246b7f5c055SJed 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.
3247b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3248b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3249b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3250b7f5c055SJed Brown 
3251b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
3252b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
3253b7f5c055SJed Brown 
3254*a1cb98faSBarry Smith   Developer Note:
3255b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3256b7f5c055SJed Brown 
3257*a1cb98faSBarry Smith   References:
3258*a1cb98faSBarry Smith . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017.
3259*a1cb98faSBarry Smith     https://doi.org/10.1016/j.polymer.2017.11.049
3260b7f5c055SJed Brown 
3261*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3262b7f5c055SJed Brown @*/
3263d71ae5a4SJacob 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)
3264d71ae5a4SJacob Faibussowitsch {
3265b7f5c055SJed Brown   PetscFunctionBegin;
32669566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32679566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32689566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
3269b7f5c055SJed Brown   PetscFunctionReturn(0);
3270b7f5c055SJed Brown }
3271b7f5c055SJed Brown 
32729318fe57SMatthew G. Knepley /*@
32739318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
32749318fe57SMatthew G. Knepley 
32759318fe57SMatthew G. Knepley   Collective
32769318fe57SMatthew G. Knepley 
32779318fe57SMatthew G. Knepley   Input Parameters:
3278*a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
32799318fe57SMatthew G. Knepley . dim     - The dimension
32809318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
32819318fe57SMatthew G. Knepley - R       - The radius
32829318fe57SMatthew G. Knepley 
32839318fe57SMatthew G. Knepley   Output Parameter:
3284*a1cb98faSBarry Smith . dm  - The `DM` object
32859318fe57SMatthew G. Knepley 
32869318fe57SMatthew G. Knepley   Level: beginner
32879318fe57SMatthew G. Knepley 
3288*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
32899318fe57SMatthew G. Knepley @*/
3290d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
3291d71ae5a4SJacob Faibussowitsch {
32929318fe57SMatthew G. Knepley   PetscFunctionBegin;
32939318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
32949566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32959566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32969566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
32979318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
32989318fe57SMatthew G. Knepley }
32999318fe57SMatthew G. Knepley 
3300d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
3301d71ae5a4SJacob Faibussowitsch {
33029318fe57SMatthew G. Knepley   DM      sdm, vol;
33039318fe57SMatthew G. Knepley   DMLabel bdlabel;
33049318fe57SMatthew G. Knepley 
33059318fe57SMatthew G. Knepley   PetscFunctionBegin;
33069566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
33079566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
33089566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_"));
33099566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
33109566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
33119566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
33129566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
33139566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
331469d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
33159566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
33169566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
33179566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
33189566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
331951a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
332051a74b61SMatthew G. Knepley }
332151a74b61SMatthew G. Knepley 
332251a74b61SMatthew G. Knepley /*@
332351a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
332451a74b61SMatthew G. Knepley 
332551a74b61SMatthew G. Knepley   Collective
332651a74b61SMatthew G. Knepley 
332751a74b61SMatthew G. Knepley   Input Parameters:
3328*a1cb98faSBarry Smith + comm  - The communicator for the `DM` object
332951a74b61SMatthew G. Knepley . dim   - The dimension
333051a74b61SMatthew G. Knepley - R     - The radius
333151a74b61SMatthew G. Knepley 
333251a74b61SMatthew G. Knepley   Output Parameter:
3333*a1cb98faSBarry Smith . dm  - The `DM` object
333451a74b61SMatthew G. Knepley 
3335*a1cb98faSBarry Smith   Options Database Key:
333651a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
333751a74b61SMatthew G. Knepley 
333851a74b61SMatthew G. Knepley   Level: beginner
333951a74b61SMatthew G. Knepley 
3340*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
334151a74b61SMatthew G. Knepley @*/
3342d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
3343d71ae5a4SJacob Faibussowitsch {
334451a74b61SMatthew G. Knepley   PetscFunctionBegin;
33459566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
33469566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
33479566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
33482829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
33492829fed8SMatthew G. Knepley }
33502829fed8SMatthew G. Knepley 
3351d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
3352d71ae5a4SJacob Faibussowitsch {
33530a6ba040SMatthew G. Knepley   PetscFunctionBegin;
33549318fe57SMatthew G. Knepley   switch (ct) {
33559371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
33569318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
33579318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
33589318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
33599318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
33609318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
33619318fe57SMatthew G. Knepley 
33629566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
33639566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33649371c9d4SSatish Balay   } break;
33659371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
33669318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
33679318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
33689318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
33699318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
33709318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
33719318fe57SMatthew G. Knepley 
33729566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33739566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33749371c9d4SSatish Balay   } break;
33759371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3376b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3377b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3378b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3379b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3380b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3381b5a892a1SMatthew G. Knepley 
33829566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33839566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33849371c9d4SSatish Balay   } break;
33859371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
33869318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
33879318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
33889318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
33899318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
33909318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
33919318fe57SMatthew G. Knepley 
33929566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33939566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33949371c9d4SSatish Balay   } break;
33959371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
33969318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33979318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
33989318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
33999318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34009318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
34019318fe57SMatthew G. Knepley 
34029566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34039566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34049371c9d4SSatish Balay   } break;
34059371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
34069318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34079318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34089318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34099318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34109318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
34119318fe57SMatthew G. Knepley 
34129566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34139566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34149371c9d4SSatish Balay   } break;
34159371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
34169318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34179318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3418f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34199318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3420f0edb160SMatthew 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};
34219318fe57SMatthew G. Knepley 
34229566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34239566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34249371c9d4SSatish Balay   } break;
34259371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
34269318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34279318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3428f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34299318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34309371c9d4SSatish 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};
34319318fe57SMatthew G. Knepley 
34329566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34339566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34349371c9d4SSatish Balay   } break;
34359371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
34369318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34379318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3438f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34399318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34409371c9d4SSatish 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};
34419318fe57SMatthew G. Knepley 
34429566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34439566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34449371c9d4SSatish Balay   } break;
34459371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
34469318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34479318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
34489318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34499318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34509371c9d4SSatish 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};
34519318fe57SMatthew G. Knepley 
34529566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34539566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34549371c9d4SSatish Balay   } break;
34559371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
34569318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34579318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
34589318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34599318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34609371c9d4SSatish 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};
34619318fe57SMatthew G. Knepley 
34629566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34639566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34649371c9d4SSatish Balay   } break;
34659371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
34669318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
34679318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3468f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
34699318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34709371c9d4SSatish 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};
34719318fe57SMatthew G. Knepley 
34729566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34739566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34749371c9d4SSatish Balay   } break;
3475d71ae5a4SJacob Faibussowitsch   default:
3476d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
34779318fe57SMatthew G. Knepley   }
34789318fe57SMatthew G. Knepley   {
34799318fe57SMatthew G. Knepley     PetscInt Nv, v;
34809318fe57SMatthew G. Knepley 
34819318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
34829566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
34839566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
34849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
34859566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
34869318fe57SMatthew G. Knepley   }
34879566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
34889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
34890a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
34900a6ba040SMatthew G. Knepley }
34910a6ba040SMatthew G. Knepley 
34929318fe57SMatthew G. Knepley /*@
3493*a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
34949318fe57SMatthew G. Knepley 
34959318fe57SMatthew G. Knepley   Collective
34969318fe57SMatthew G. Knepley 
34979318fe57SMatthew G. Knepley   Input Parameters:
34989318fe57SMatthew G. Knepley + comm - The communicator
34999318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
35009318fe57SMatthew G. Knepley 
35019318fe57SMatthew G. Knepley   Output Parameter:
35029318fe57SMatthew G. Knepley . refdm - The reference cell
35039318fe57SMatthew G. Knepley 
35049318fe57SMatthew G. Knepley   Level: intermediate
35059318fe57SMatthew G. Knepley 
3506*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()`
35079318fe57SMatthew G. Knepley @*/
3508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
3509d71ae5a4SJacob Faibussowitsch {
35100a6ba040SMatthew G. Knepley   PetscFunctionBegin;
35119566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
35129566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
35139566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
35149318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35159318fe57SMatthew G. Knepley }
351679a015ccSMatthew G. Knepley 
3517d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
3518d71ae5a4SJacob Faibussowitsch {
35199318fe57SMatthew G. Knepley   DM        plex;
35209318fe57SMatthew G. Knepley   DMLabel   label;
35219318fe57SMatthew G. Knepley   PetscBool hasLabel;
35220a6ba040SMatthew G. Knepley 
3523c22d3578SMatthew G. Knepley   PetscFunctionBegin;
35249566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
35259318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
35269566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
35279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
35289566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
35299566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
35301c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
35319566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
35329318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35339318fe57SMatthew G. Knepley }
3534acdc6f61SToby Isaac 
3535669647acSMatthew G. Knepley /*
3536669647acSMatthew 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.
3537669647acSMatthew G. Knepley 
3538669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
3539669647acSMatthew G. Knepley */
3540d71ae5a4SJacob 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[])
3541d71ae5a4SJacob Faibussowitsch {
3542669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
3543669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
3544669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
3545669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
3546669647acSMatthew G. Knepley 
3547669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
3548669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
3549669647acSMatthew G. Knepley }
3550669647acSMatthew G. Knepley 
3551669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
35529318fe57SMatthew G. Knepley 
3553d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
3554d71ae5a4SJacob Faibussowitsch {
35559318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
35569318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
35579318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
35589318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3559cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
35609318fe57SMatthew G. Knepley   MPI_Comm       comm;
3561ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3562ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3563ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
35649318fe57SMatthew G. Knepley 
35659318fe57SMatthew G. Knepley   PetscFunctionBegin;
35669566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
35679318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
35689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
35699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
35709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
35719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
35729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
35739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
35749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
357563a3b9bcSJacob Faibussowitsch   PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim);
35769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
35779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
35789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
35799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
35809566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
35819318fe57SMatthew G. Knepley 
358261a622f3SMatthew G. Knepley   switch (cell) {
358361a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
358461a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
358561a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
358661a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
358761a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
358861a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
3589d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
3590d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
3591d71ae5a4SJacob Faibussowitsch     break;
3592d71ae5a4SJacob Faibussowitsch   default:
3593d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
3594d71ae5a4SJacob Faibussowitsch     break;
359561a622f3SMatthew G. Knepley   }
359661a622f3SMatthew G. Knepley 
35979318fe57SMatthew G. Knepley   if (fflg) {
35989318fe57SMatthew G. Knepley     DM dmnew;
35999318fe57SMatthew G. Knepley 
36009566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew));
36015de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
360269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36039318fe57SMatthew G. Knepley   } else if (refDomain) {
36049566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
36059318fe57SMatthew G. Knepley   } else if (bdfflg) {
36069318fe57SMatthew G. Knepley     DM bdm, dmnew;
36079318fe57SMatthew G. Knepley 
36089566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm));
36099566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
36109566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
36119566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
36129566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
36135de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
361469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36159318fe57SMatthew G. Knepley   } else {
36169566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
36179318fe57SMatthew G. Knepley     switch (shape) {
3618669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
3619669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
36209318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
36219318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
36229318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
36239318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3624669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
36259318fe57SMatthew G. Knepley       PetscInt       i, n;
36269318fe57SMatthew G. Knepley 
36279318fe57SMatthew G. Knepley       n = dim;
36289318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
36299566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36309318fe57SMatthew G. Knepley       n = 3;
36319566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
363263a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36339318fe57SMatthew G. Knepley       n = 3;
36349566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
363563a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36369318fe57SMatthew G. Knepley       n = 3;
36379566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
363863a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
3639669647acSMatthew G. Knepley 
3640669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
3641669647acSMatthew G. Knepley       if (isAnnular)
3642669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
3643669647acSMatthew G. Knepley 
36449318fe57SMatthew G. Knepley       switch (cell) {
364561a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
36469566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3647d410b0cfSMatthew G. Knepley         if (!interpolate) {
3648d410b0cfSMatthew G. Knepley           DM udm;
3649d410b0cfSMatthew G. Knepley 
36509566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
365169d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
3652d410b0cfSMatthew G. Knepley         }
36539318fe57SMatthew G. Knepley         break;
3654d71ae5a4SJacob Faibussowitsch       default:
3655d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate));
3656d71ae5a4SJacob Faibussowitsch         break;
36579318fe57SMatthew G. Knepley       }
3658669647acSMatthew G. Knepley       if (isAnnular) {
3659669647acSMatthew G. Knepley         DM          cdm;
3660669647acSMatthew G. Knepley         PetscDS     cds;
3661669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
3662669647acSMatthew G. Knepley 
3663669647acSMatthew G. Knepley         // Fix coordinates for annular region
3664669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
3665669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
3666669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
3667669647acSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL));
3668669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
3669669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
3670669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
3671669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
3672669647acSMatthew G. Knepley       }
36739371c9d4SSatish Balay     } break;
36749371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
36759318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
36769318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
36779318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
36789318fe57SMatthew G. Knepley       PetscInt  i, n;
36799318fe57SMatthew G. Knepley 
36809318fe57SMatthew G. Knepley       n = dim + 1;
36819318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
36829566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36839318fe57SMatthew G. Knepley       n = 3;
36849566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
368563a3b9bcSJacob 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);
36869318fe57SMatthew G. Knepley       n = 3;
36879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
368863a3b9bcSJacob 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);
36899566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
36909371c9d4SSatish Balay     } break;
36919371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
36929318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36939318fe57SMatthew G. Knepley 
36949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
36959566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
36969371c9d4SSatish Balay     } break;
36979371c9d4SSatish Balay     case DM_SHAPE_BALL: {
36989318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36999318fe57SMatthew G. Knepley 
37009566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
37019566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
37029371c9d4SSatish Balay     } break;
37039371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
37049318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
37059318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
37069318fe57SMatthew G. Knepley 
37079566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
37089566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
37099318fe57SMatthew G. Knepley       switch (cell) {
3710d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
3711d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
3712d71ae5a4SJacob Faibussowitsch         break;
3713d71ae5a4SJacob Faibussowitsch       default:
3714d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt));
3715d71ae5a4SJacob Faibussowitsch         break;
37169318fe57SMatthew G. Knepley       }
37179371c9d4SSatish Balay     } break;
3718b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
37199371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
3720b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
3721b7f5c055SJed Brown       PetscReal      thickness   = 0.;
3722b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3723b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
37241436d7faSJed Brown       PetscBool      tps_distribute;
37259566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
37269566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
37279566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
37289566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
37299566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
37309566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
37319566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
37329566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
37339371c9d4SSatish Balay     } break;
37349371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
373505bd46c0SStefano Zampini       DM        dmnew;
373605bd46c0SStefano Zampini       PetscReal rl = 0.0;
373705bd46c0SStefano Zampini 
373805bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
373905bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
37405de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
374169d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
37429371c9d4SSatish Balay     } break;
3743d71ae5a4SJacob Faibussowitsch     default:
3744d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
37459318fe57SMatthew G. Knepley     }
37469318fe57SMatthew G. Knepley   }
37479566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
374848a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
37490a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
37500a6ba040SMatthew G. Knepley }
37510a6ba040SMatthew G. Knepley 
3752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3753d71ae5a4SJacob Faibussowitsch {
37540a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
37557f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
37569318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
37570a6ba040SMatthew G. Knepley 
37580a6ba040SMatthew G. Knepley   PetscFunctionBegin;
37590a6ba040SMatthew G. Knepley   /* Handle viewing */
37609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
37619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
37629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
37639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
3764f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
37659566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
37669566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
37679318fe57SMatthew G. Knepley   /* Labeling */
37689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
37699566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3770953fc75cSMatthew G. Knepley   /* Point Location */
37719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
37720848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
37739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
37742e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
37759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3776b29cfa1cSToby Isaac   /* Projection behavior */
3777d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
37789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3779f12cf164SMatthew G. Knepley   /* Checking structure */
3780f12cf164SMatthew G. Knepley   {
37817f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
3782f12cf164SMatthew G. Knepley 
37837f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
37847f9d8d6cSVaclav Hapla     if (all) {
37857f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
37867f9d8d6cSVaclav Hapla     } else {
37879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
37887f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
37899566063dSJacob 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));
37907f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
37919566063dSJacob 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));
37927f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
37939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
37947f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
37959566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
3796d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
37979566063dSJacob 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));
37987f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
37997f9d8d6cSVaclav Hapla     }
38009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
38019566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3802f12cf164SMatthew G. Knepley   }
38039318fe57SMatthew G. Knepley   {
38049318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
38054f3833eaSMatthew G. Knepley 
38069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
38079318fe57SMatthew G. Knepley     if (flg) {
38089318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
38099318fe57SMatthew G. Knepley 
38109566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
38119566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
38129566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
38139566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
38149318fe57SMatthew G. Knepley     }
38159318fe57SMatthew G. Knepley   }
38169566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
381768d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
381868d4fef7SMatthew G. Knepley }
381968d4fef7SMatthew G. Knepley 
3820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
3821d71ae5a4SJacob Faibussowitsch {
3822c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
3823c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
3824c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
3825c506a872SMatthew G. Knepley   PetscBool flg;
3826c506a872SMatthew G. Knepley 
3827c506a872SMatthew G. Knepley   PetscFunctionBegin;
3828c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
3829c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
3830c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
3831c506a872SMatthew G. Knepley   if (numOvLabels) {
3832c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
3833c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
3834c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
3835c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
3836c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
3837c506a872SMatthew G. Knepley     }
3838c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
3839c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
3840c506a872SMatthew 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);
3841c506a872SMatthew G. Knepley 
3842c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
3843c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
3844c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
3845c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
3846c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
3847c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
3848c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
3849c506a872SMatthew G. Knepley     }
3850c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
3851c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
3852c506a872SMatthew 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);
3853c506a872SMatthew G. Knepley   }
3854c506a872SMatthew G. Knepley   PetscFunctionReturn(0);
3855c506a872SMatthew G. Knepley }
3856c506a872SMatthew G. Knepley 
3857d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3858d71ae5a4SJacob Faibussowitsch {
3859bdf63967SMatthew G. Knepley   PetscFunctionList        ordlist;
3860bdf63967SMatthew G. Knepley   char                     oname[256];
3861d410b0cfSMatthew G. Knepley   PetscReal                volume    = -1.0;
38629318fe57SMatthew G. Knepley   PetscInt                 prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3863e600fa54SMatthew 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;
38646bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
386568d4fef7SMatthew G. Knepley 
386668d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3867d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
38689318fe57SMatthew G. Knepley   /* Handle automatic creation */
38699566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
38706bc1bd01Sksagiyam   if (dim < 0) {
38716bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
38726bc1bd01Sksagiyam     created = PETSC_TRUE;
38736bc1bd01Sksagiyam   }
38746bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
3875d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
38769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3877d89e6e46SMatthew G. Knepley   if (flg) {
3878d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3879d89e6e46SMatthew G. Knepley 
38809566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
3881d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3882d89e6e46SMatthew G. Knepley       DM udm;
3883d89e6e46SMatthew G. Knepley 
38849566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
388569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
3886d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3887d89e6e46SMatthew G. Knepley       DM idm;
3888d89e6e46SMatthew G. Knepley 
38899566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
389069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
3891d89e6e46SMatthew G. Knepley     }
3892d89e6e46SMatthew G. Knepley   }
38939b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
38949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3895ad540459SPierre Jolivet   if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel;
38969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
38979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
38989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
38999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
39009566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
39019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
39029318fe57SMatthew G. Knepley   if (flg) {
39039566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
39049566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
39059318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
39069318fe57SMatthew G. Knepley   }
39079b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
39089b44eab4SMatthew G. Knepley     DM             rdm;
39099b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
39109b44eab4SMatthew G. Knepley 
3911dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39129566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
391369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
3914dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
391561a622f3SMatthew G. Knepley     if (coordFunc && remap) {
39169566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
39179b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
39189b44eab4SMatthew G. Knepley     }
39199b44eab4SMatthew G. Knepley   }
39209566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
39219318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
39229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
39239318fe57SMatthew G. Knepley   if (extLayers) {
39249318fe57SMatthew G. Knepley     DM edm;
39259318fe57SMatthew G. Knepley 
39269566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
392769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
392848d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
3929dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3930d410b0cfSMatthew G. Knepley     extLayers = 0;
39319318fe57SMatthew G. Knepley   }
3932bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
39336bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
39349566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
39356bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
39369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
39376bc1bd01Sksagiyam   if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) {
3938bdf63967SMatthew G. Knepley     DM pdm;
3939bdf63967SMatthew G. Knepley     IS perm;
3940bdf63967SMatthew G. Knepley 
39419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
39429566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
39439566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
394469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
3945dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3946bdf63967SMatthew G. Knepley   }
39479b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
39489566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
3949c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
3950dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
39519b44eab4SMatthew G. Knepley   if (distribute) {
39529b44eab4SMatthew G. Knepley     DM               pdm = NULL;
39539b44eab4SMatthew G. Knepley     PetscPartitioner part;
39549b44eab4SMatthew G. Knepley 
39559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
39569566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
39579566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm));
395848a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
39599b44eab4SMatthew G. Knepley   }
39609318fe57SMatthew G. Knepley   /* Create coordinate space */
39619318fe57SMatthew G. Knepley   if (created) {
396261a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
39639318fe57SMatthew G. Knepley     PetscInt  degree = 1;
39646858538eSMatthew G. Knepley     PetscBool flg;
39659318fe57SMatthew G. Knepley 
39669566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
39679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
39689566063dSJacob Faibussowitsch     if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
396961a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
397061a622f3SMatthew G. Knepley       DM           cdm;
397161a622f3SMatthew G. Knepley       PetscDS      cds;
397261a622f3SMatthew G. Knepley       PetscObject  obj;
397361a622f3SMatthew G. Knepley       PetscClassId id;
397461a622f3SMatthew G. Knepley 
39759566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDM(dm, &cdm));
39769566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
39779566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
39789566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
397961a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
398061a622f3SMatthew G. Knepley         PetscContainer dummy;
398161a622f3SMatthew G. Knepley 
39829566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
39839566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
39849566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
39859566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
39869566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
398761a622f3SMatthew G. Knepley       }
398861a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
398961a622f3SMatthew G. Knepley     }
39906858538eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg));
39919566063dSJacob Faibussowitsch     PetscCall(DMLocalizeCoordinates(dm));
39929318fe57SMatthew G. Knepley   }
399368d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
399461a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
39959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
39969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
39979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
39989566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
399968d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
4000acdc6f61SToby Isaac     DM *dms, coarseDM;
400168d4fef7SMatthew G. Knepley 
40029566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
40039566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
40049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
40059566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
400668d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
40079566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
400868d4fef7SMatthew G. Knepley     if (refine == 1) {
40099566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
40109566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
401168d4fef7SMatthew G. Knepley     } else {
40129566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
40139566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
40149566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
40159566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
401668d4fef7SMatthew G. Knepley     }
40179566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
40189566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
401968d4fef7SMatthew G. Knepley     /* Free DMs */
402068d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
4021dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40229566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
402368d4fef7SMatthew G. Knepley     }
40249566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
402568d4fef7SMatthew G. Knepley   } else {
402668d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
40279318fe57SMatthew G. Knepley       DM             rdm;
402851a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
402968d4fef7SMatthew G. Knepley 
4030dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40319566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
403268d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
403369d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
4034dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
403561a622f3SMatthew G. Knepley       if (coordFunc && remap) {
40369566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
403751a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
403851a74b61SMatthew G. Knepley       }
403968d4fef7SMatthew G. Knepley     }
404068d4fef7SMatthew G. Knepley   }
40413cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
40429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
40439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
4044b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
4045b653a561SMatthew G. Knepley     DM *dms;
4046b653a561SMatthew G. Knepley 
40479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
40489566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
4049b653a561SMatthew G. Knepley     /* Free DMs */
4050b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
4051dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40529566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
4053b653a561SMatthew G. Knepley     }
40549566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
4055b653a561SMatthew G. Knepley   } else {
4056b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
40579318fe57SMatthew G. Knepley       DM             cdm;
40589318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
40593cf6fe12SMatthew G. Knepley 
4060dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40619566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
40623cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
406369d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
4064dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40659318fe57SMatthew G. Knepley       if (coordFunc) {
40669566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
40679318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
40689318fe57SMatthew G. Knepley       }
40693cf6fe12SMatthew G. Knepley     }
4070b653a561SMatthew G. Knepley   }
4071909dfd52SMatthew G. Knepley   /* Handle ghost cells */
40729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
4073909dfd52SMatthew G. Knepley   if (ghostCells) {
4074909dfd52SMatthew G. Knepley     DM   gdm;
4075909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
4076909dfd52SMatthew G. Knepley 
4077909dfd52SMatthew G. Knepley     lname[0] = '\0';
40789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
40799566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
408069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
4081909dfd52SMatthew G. Knepley   }
40826913077dSMatthew G. Knepley   /* Handle 1D order */
40836bc1bd01Sksagiyam   if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) {
40846913077dSMatthew G. Knepley     DM           cdm, rdm;
40856913077dSMatthew G. Knepley     PetscDS      cds;
40866913077dSMatthew G. Knepley     PetscObject  obj;
40876913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
40886913077dSMatthew G. Knepley     IS           perm;
40896bc1bd01Sksagiyam     PetscInt     Nf;
40906913077dSMatthew G. Knepley     PetscBool    distributed;
40916913077dSMatthew G. Knepley 
40929566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
40939566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
40949566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
40959566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
40966913077dSMatthew G. Knepley     if (Nf) {
40979566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
40989566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
40996913077dSMatthew G. Knepley     }
41006bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
41019566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
41029566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
410369d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
41049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
41056913077dSMatthew G. Knepley     }
41066913077dSMatthew G. Knepley   }
41073cf6fe12SMatthew G. Knepley   /* Handle */
4108dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4109d0609cedSBarry Smith   PetscOptionsHeadEnd();
41100a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
41110a6ba040SMatthew G. Knepley }
41120a6ba040SMatthew G. Knepley 
4113d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
4114d71ae5a4SJacob Faibussowitsch {
4115552f7358SJed Brown   PetscFunctionBegin;
41169566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
41179566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
41189566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
41199566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
41209566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
41219566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
4122552f7358SJed Brown   PetscFunctionReturn(0);
4123552f7358SJed Brown }
4124552f7358SJed Brown 
4125d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
4126d71ae5a4SJacob Faibussowitsch {
4127552f7358SJed Brown   PetscFunctionBegin;
41289566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
41299566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
41309566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
4131552f7358SJed Brown   PetscFunctionReturn(0);
4132552f7358SJed Brown }
4133552f7358SJed Brown 
4134d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4135d71ae5a4SJacob Faibussowitsch {
4136793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4137793f3fe5SMatthew G. Knepley 
4138793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
41399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4140793f3fe5SMatthew G. Knepley   if (depth == 1) {
41419566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
41429566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
41439566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
41449371c9d4SSatish Balay     else {
41459371c9d4SSatish Balay       *pStart = 0;
41469371c9d4SSatish Balay       *pEnd   = 0;
41479371c9d4SSatish Balay     }
4148793f3fe5SMatthew G. Knepley   } else {
41499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4150793f3fe5SMatthew G. Knepley   }
4151793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
4152793f3fe5SMatthew G. Knepley }
4153793f3fe5SMatthew G. Knepley 
4154d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
4155d71ae5a4SJacob Faibussowitsch {
4156502a2867SDave May   PetscSF            sf;
41570a19bb7dSprj-   PetscInt           niranks, njranks, n;
41580a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
41590a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4160502a2867SDave May 
41612f356facSMatthew G. Knepley   PetscFunctionBegin;
41629566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
41630a19bb7dSprj-   if (!data->neighbors) {
41649566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
41659566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
41669566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
41679566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
41689566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
41699566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
41700a19bb7dSprj-     n = njranks + niranks;
41719566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
41720a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
41739566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
41740a19bb7dSprj-   }
41750a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
41760a19bb7dSprj-   if (ranks) {
41770a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
41780a19bb7dSprj-     else *ranks = NULL;
41790a19bb7dSprj-   }
4180502a2867SDave May   PetscFunctionReturn(0);
4181502a2867SDave May }
4182502a2867SDave May 
41831eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
41841eb70e55SToby Isaac 
4185d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
4186d71ae5a4SJacob Faibussowitsch {
4187552f7358SJed Brown   PetscFunctionBegin;
4188552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
41892c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
4190552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
419138221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
4192552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
41931bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
419466ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
4195552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
4196552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
4197184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
41980298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
4199552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
4200f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
42010a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
4202552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
4203bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
4204bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
4205b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
42065a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
4207552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
42080a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
42090a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
4210b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
4211d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
42120298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
42130298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
42140298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
42150298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
4216552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
4217552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
42182adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
4219793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
4220552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
42210709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
42220709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
4223bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
42248c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
4225ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
42260709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
4227b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
42282a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
422928d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
42309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
42319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
42329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
42339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
42349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
42359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
42369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
42376bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
42386bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
42399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
4240c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
4241c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
4242552f7358SJed Brown   PetscFunctionReturn(0);
4243552f7358SJed Brown }
4244552f7358SJed Brown 
4245d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
4246d71ae5a4SJacob Faibussowitsch {
424763a16f15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
424863a16f15SMatthew G. Knepley 
424963a16f15SMatthew G. Knepley   PetscFunctionBegin;
425063a16f15SMatthew G. Knepley   mesh->refct++;
425163a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
42529566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
42539566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
425463a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
425563a16f15SMatthew G. Knepley }
425663a16f15SMatthew G. Knepley 
42578818961aSMatthew G Knepley /*MC
4258*a1cb98faSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
42598818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
42608818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
4261*a1cb98faSBarry Smith                     ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
42628818961aSMatthew G Knepley 
4263e5893cccSMatthew G. Knepley   Options Database Keys:
4264250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
4265250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
4266250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
4267250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
4268250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
4269250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
4270250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
4271ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
4272f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
4273f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
4274d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
4275f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
4276250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
4277f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
4278f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
4279f12cf164SMatthew 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
4280f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
4281f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
4282e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
4283e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
4284e5893cccSMatthew G. Knepley 
42858818961aSMatthew G Knepley   Level: intermediate
42868818961aSMatthew G Knepley 
4287*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
42888818961aSMatthew G Knepley M*/
42898818961aSMatthew G Knepley 
4290d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
4291d71ae5a4SJacob Faibussowitsch {
4292552f7358SJed Brown   DM_Plex *mesh;
4293412e9a14SMatthew G. Knepley   PetscInt unit;
4294552f7358SJed Brown 
4295552f7358SJed Brown   PetscFunctionBegin;
4296552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42974dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
4298552f7358SJed Brown   dm->data = mesh;
4299552f7358SJed Brown 
4300552f7358SJed Brown   mesh->refct = 1;
43019566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
43029566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
4303552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
4304552f7358SJed Brown   mesh->refinementLimit        = -1.0;
4305e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
43066bc1bd01Sksagiyam   mesh->reorderDefault         = DMPLEX_REORDER_DEFAULT_NOTSET;
43071d1f2f2aSksagiyam   mesh->distributionName       = NULL;
43087d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
43097d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
4310552f7358SJed Brown 
43119566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
43122e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
4313d9deefdfSMatthew G. Knepley 
43148865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
4315552f7358SJed Brown 
4316df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
4317ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
43186113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
4319552f7358SJed Brown 
43209566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
4321552f7358SJed Brown   PetscFunctionReturn(0);
4322552f7358SJed Brown }
4323552f7358SJed Brown 
4324552f7358SJed Brown /*@
4325*a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
4326552f7358SJed Brown 
4327d083f849SBarry Smith   Collective
4328552f7358SJed Brown 
4329552f7358SJed Brown   Input Parameter:
4330*a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
4331552f7358SJed Brown 
4332552f7358SJed Brown   Output Parameter:
4333*a1cb98faSBarry Smith . mesh  - The `DMPLEX` object
4334552f7358SJed Brown 
4335552f7358SJed Brown   Level: beginner
4336552f7358SJed Brown 
4337*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`
4338552f7358SJed Brown @*/
4339d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
4340d71ae5a4SJacob Faibussowitsch {
4341552f7358SJed Brown   PetscFunctionBegin;
4342552f7358SJed Brown   PetscValidPointer(mesh, 2);
43439566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
43449566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
4345552f7358SJed Brown   PetscFunctionReturn(0);
4346552f7358SJed Brown }
4347552f7358SJed Brown 
4348b09969d6SVaclav Hapla /*@C
4349*a1cb98faSBarry Smith   DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
4350*a1cb98faSBarry Smith 
4351*a1cb98faSBarry Smith   Collective on dm
4352b09969d6SVaclav Hapla 
4353b09969d6SVaclav Hapla   Input Parameters:
4354*a1cb98faSBarry Smith + dm - The `DM`
4355b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4356*a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
4357*a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE`
4358b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
43595e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4360b09969d6SVaclav Hapla 
4361be8c289dSNicolas Barral   Output Parameters:
4362*a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership
4363be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4364b09969d6SVaclav Hapla 
4365b09969d6SVaclav Hapla   Level: advanced
4366b09969d6SVaclav Hapla 
4367*a1cb98faSBarry Smith   Notes:
4368*a1cb98faSBarry Smith   Two triangles sharing a face
4369*a1cb98faSBarry Smith .vb
4370*a1cb98faSBarry Smith 
4371*a1cb98faSBarry Smith         2
4372*a1cb98faSBarry Smith       / | \
4373*a1cb98faSBarry Smith      /  |  \
4374*a1cb98faSBarry Smith     /   |   \
4375*a1cb98faSBarry Smith    0  0 | 1  3
4376*a1cb98faSBarry Smith     \   |   /
4377*a1cb98faSBarry Smith      \  |  /
4378*a1cb98faSBarry Smith       \ | /
4379*a1cb98faSBarry Smith         1
4380*a1cb98faSBarry Smith .ve
4381*a1cb98faSBarry Smith would have input
4382*a1cb98faSBarry Smith .vb
4383*a1cb98faSBarry Smith   numCells = 2, numVertices = 4
4384*a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
4385*a1cb98faSBarry Smith .ve
4386*a1cb98faSBarry Smith which would result in the `DMPLEX`
4387*a1cb98faSBarry Smith .vb
4388*a1cb98faSBarry Smith 
4389*a1cb98faSBarry Smith         4
4390*a1cb98faSBarry Smith       / | \
4391*a1cb98faSBarry Smith      /  |  \
4392*a1cb98faSBarry Smith     /   |   \
4393*a1cb98faSBarry Smith    2  0 | 1  5
4394*a1cb98faSBarry Smith     \   |   /
4395*a1cb98faSBarry Smith      \  |  /
4396*a1cb98faSBarry Smith       \ | /
4397*a1cb98faSBarry Smith         3
4398*a1cb98faSBarry Smith .ve
4399*a1cb98faSBarry Smith 
4400*a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
4401*a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
4402*a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
4403*a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
4404*a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
4405*a1cb98faSBarry Smith 
4406*a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
4407*a1cb98faSBarry Smith 
4408*a1cb98faSBarry Smith   Fortran Note:
4409*a1cb98faSBarry Smith   Not currently supported in Fortran.
4410*a1cb98faSBarry Smith 
4411*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
4412*a1cb98faSBarry Smith           `PetscSF`
4413b09969d6SVaclav Hapla @*/
4414d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
4415d71ae5a4SJacob Faibussowitsch {
44162464107aSksagiyam   PetscSF     sfPoint;
44172464107aSksagiyam   PetscLayout layout;
441882fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
4419a47d0d45SMatthew G. Knepley 
4420a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
442125b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
44229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
442325b6865aSVaclav Hapla   /* Get/check global number of vertices */
442425b6865aSVaclav Hapla   {
442525b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
442625b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
442725b6865aSVaclav Hapla 
442825b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
442925b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
44309371c9d4SSatish Balay     for (i = 0; i < len; i++)
44319371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
443225b6865aSVaclav Hapla     ++NVerticesInCells;
44339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
443425b6865aSVaclav Hapla 
443525b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
44369371c9d4SSatish Balay     else
44379371c9d4SSatish 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);
443825b6865aSVaclav Hapla   }
44399079aca8SVaclav Hapla   /* Count locally unique vertices */
44409079aca8SVaclav Hapla   {
44419079aca8SVaclav Hapla     PetscHSetI vhash;
44429079aca8SVaclav Hapla     PetscInt   off = 0;
44439079aca8SVaclav Hapla 
44449566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
4445a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
444648a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
4447a47d0d45SMatthew G. Knepley     }
44489566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
44499566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
4450ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
44519566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
44529566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
445363a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
4454a47d0d45SMatthew G. Knepley   }
44559566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
4456a47d0d45SMatthew G. Knepley   /* Create cones */
44579566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
44589566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
44599566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
44609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4461a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
4462a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
4463a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
4464a47d0d45SMatthew G. Knepley       PetscInt       lv;
4465a47d0d45SMatthew G. Knepley 
44669079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
44679079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
44689566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
446963a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
4470961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
4471a47d0d45SMatthew G. Knepley     }
4472a47d0d45SMatthew G. Knepley   }
44732464107aSksagiyam   /* Build point sf */
44749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
44759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
44769566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
44779566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44789566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
44799566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
44809566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
44819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
44822464107aSksagiyam   if (dm->sf) {
44832464107aSksagiyam     const char *prefix;
44842464107aSksagiyam 
44859566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
44869566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
44872464107aSksagiyam   }
44889566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
44899566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
44909566063dSJacob Faibussowitsch   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4491a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
44929566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
44939566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
44949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4495a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4496a47d0d45SMatthew G. Knepley }
4497a47d0d45SMatthew G. Knepley 
4498b09969d6SVaclav Hapla /*@C
4499*a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4500*a1cb98faSBarry Smith 
4501*a1cb98faSBarry Smith   Collective on dm
4502b09969d6SVaclav Hapla 
4503b09969d6SVaclav Hapla   Input Parameters:
4504*a1cb98faSBarry Smith + dm - The `DM`
4505b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4506*a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership
4507b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4508b09969d6SVaclav Hapla 
4509b09969d6SVaclav Hapla   Level: advanced
4510b09969d6SVaclav Hapla 
4511*a1cb98faSBarry Smith   Fortran Note:
4512b09969d6SVaclav Hapla   Not currently supported in Fortran.
4513b09969d6SVaclav Hapla 
4514*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
4515b09969d6SVaclav Hapla @*/
4516d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
4517d71ae5a4SJacob Faibussowitsch {
4518a47d0d45SMatthew G. Knepley   PetscSection coordSection;
4519a47d0d45SMatthew G. Knepley   Vec          coordinates;
4520a47d0d45SMatthew G. Knepley   PetscScalar *coords;
45211edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4522a47d0d45SMatthew G. Knepley 
4523a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
45259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
45261dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
45279566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
45289566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
45291dca8a05SBarry 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);
45309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
45319566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
45329566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
45339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
45341edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
45359566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
45369566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4537a47d0d45SMatthew G. Knepley   }
45389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
45399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
45409566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
45419566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
45429566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
45439566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
45449566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
45459566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4546a47d0d45SMatthew G. Knepley   {
4547a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4548a47d0d45SMatthew G. Knepley 
4549a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
45509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
45519566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
455221016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
455321016a8bSBarry Smith     {
455421016a8bSBarry Smith       PetscScalar *svertexCoords;
455521016a8bSBarry Smith       PetscInt     i;
45569566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
45573612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
45589566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45599566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45609566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
456121016a8bSBarry Smith     }
456221016a8bSBarry Smith #else
45639566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
45649566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
456521016a8bSBarry Smith #endif
45669566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
4567a47d0d45SMatthew G. Knepley   }
45689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
45699566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
45709566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
45719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4572a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4573a47d0d45SMatthew G. Knepley }
4574a47d0d45SMatthew G. Knepley 
4575c3edce3dSSatish Balay /*@
4576*a1cb98faSBarry Smith   DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output)
4577*a1cb98faSBarry Smith 
4578*a1cb98faSBarry Smith   Collective
4579a47d0d45SMatthew G. Knepley 
4580a47d0d45SMatthew G. Knepley   Input Parameters:
4581a47d0d45SMatthew G. Knepley + comm - The communicator
4582a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4583a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
4584*a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`
4585*a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE`
4586a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4587a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4588a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4589a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4590a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4591a47d0d45SMatthew G. Knepley 
4592d8d19677SJose E. Roman   Output Parameters:
4593*a1cb98faSBarry Smith + dm - The `DM`
4594*a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership
4595be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4596a47d0d45SMatthew G. Knepley 
4597b09969d6SVaclav Hapla   Level: intermediate
4598a47d0d45SMatthew G. Knepley 
4599*a1cb98faSBarry Smith   Notes:
4600*a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
4601*a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
4602*a1cb98faSBarry Smith 
4603*a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
4604*a1cb98faSBarry Smith 
4605*a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
4606*a1cb98faSBarry Smith 
4607*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
4608a47d0d45SMatthew G. Knepley @*/
4609d71ae5a4SJacob 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)
4610d71ae5a4SJacob Faibussowitsch {
4611a47d0d45SMatthew G. Knepley   PetscSF sfVert;
4612a47d0d45SMatthew G. Knepley 
4613a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
46149566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
46159566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4616a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4617064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
46189566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
46199566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4620a47d0d45SMatthew G. Knepley   if (interpolate) {
46215fd9971aSMatthew G. Knepley     DM idm;
4622a47d0d45SMatthew G. Knepley 
46239566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
46249566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
4625a47d0d45SMatthew G. Knepley     *dm = idm;
4626a47d0d45SMatthew G. Knepley   }
46279566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
462818d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
46299566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
4630a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4631a47d0d45SMatthew G. Knepley }
4632a47d0d45SMatthew G. Knepley 
4633b09969d6SVaclav Hapla /*@C
4634*a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
4635*a1cb98faSBarry Smith 
4636*a1cb98faSBarry Smith   Collective on dm
46379298eaa6SMatthew G Knepley 
46389298eaa6SMatthew G Knepley   Input Parameters:
4639*a1cb98faSBarry Smith + dm - The `DM`
4640b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4641*a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
46429298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
46435e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
46449298eaa6SMatthew G Knepley 
4645b09969d6SVaclav Hapla   Level: advanced
46469298eaa6SMatthew G Knepley 
4647b09969d6SVaclav Hapla   Notes:
4648b09969d6SVaclav Hapla   Two triangles sharing a face
4649*a1cb98faSBarry Smith .vb
46509298eaa6SMatthew G Knepley 
4651*a1cb98faSBarry Smith         2
4652*a1cb98faSBarry Smith       / | \
4653*a1cb98faSBarry Smith      /  |  \
4654*a1cb98faSBarry Smith     /   |   \
4655*a1cb98faSBarry Smith    0  0 | 1  3
4656*a1cb98faSBarry Smith     \   |   /
4657*a1cb98faSBarry Smith      \  |  /
4658*a1cb98faSBarry Smith       \ | /
4659*a1cb98faSBarry Smith         1
4660*a1cb98faSBarry Smith .ve
4661*a1cb98faSBarry Smith would have input
4662*a1cb98faSBarry Smith .vb
4663*a1cb98faSBarry Smith   numCells = 2, numVertices = 4
4664*a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
4665*a1cb98faSBarry Smith .ve
4666*a1cb98faSBarry Smith which would result in the `DMPLEX`
4667*a1cb98faSBarry Smith .vb
4668*a1cb98faSBarry Smith 
4669*a1cb98faSBarry Smith         4
4670*a1cb98faSBarry Smith       / | \
4671*a1cb98faSBarry Smith      /  |  \
4672*a1cb98faSBarry Smith     /   |   \
4673*a1cb98faSBarry Smith    2  0 | 1  5
4674*a1cb98faSBarry Smith     \   |   /
4675*a1cb98faSBarry Smith      \  |  /
4676*a1cb98faSBarry Smith       \ | /
4677*a1cb98faSBarry Smith         3
4678*a1cb98faSBarry Smith .ve
4679*a1cb98faSBarry Smith 
4680*a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
468125b6865aSVaclav Hapla 
4682b09969d6SVaclav Hapla   Not currently supported in Fortran.
46839298eaa6SMatthew G Knepley 
4684*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
4685b09969d6SVaclav Hapla @*/
4686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
4687d71ae5a4SJacob Faibussowitsch {
4688961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
4689b09969d6SVaclav Hapla 
4690b09969d6SVaclav Hapla   PetscFunctionBegin;
46919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
46929566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
469325b6865aSVaclav Hapla   /* Get/check global number of vertices */
469425b6865aSVaclav Hapla   {
469525b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
469625b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
469725b6865aSVaclav Hapla 
469825b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
469925b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
47009371c9d4SSatish Balay     for (i = 0; i < len; i++)
47019371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
470225b6865aSVaclav Hapla     ++NVerticesInCells;
470325b6865aSVaclav Hapla 
470425b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
47059371c9d4SSatish Balay     else
47069371c9d4SSatish 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);
470725b6865aSVaclav Hapla   }
47089566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
470948a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
47109566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
47119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4712b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4713ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
4714b09969d6SVaclav Hapla   }
47159566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
47169566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
47179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4718b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4719b09969d6SVaclav Hapla }
4720b09969d6SVaclav Hapla 
4721b09969d6SVaclav Hapla /*@C
4722*a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4723*a1cb98faSBarry Smith 
4724*a1cb98faSBarry Smith   Collective on dm
4725b09969d6SVaclav Hapla 
4726b09969d6SVaclav Hapla   Input Parameters:
4727*a1cb98faSBarry Smith + dm - The `DM`
4728b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4729b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4730b09969d6SVaclav Hapla 
4731b09969d6SVaclav Hapla   Level: advanced
4732b09969d6SVaclav Hapla 
4733*a1cb98faSBarry Smith   Fortran Note:
4734b09969d6SVaclav Hapla   Not currently supported in Fortran.
4735b09969d6SVaclav Hapla 
4736*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
4737b09969d6SVaclav Hapla @*/
4738d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
4739d71ae5a4SJacob Faibussowitsch {
4740b09969d6SVaclav Hapla   PetscSection coordSection;
4741b09969d6SVaclav Hapla   Vec          coordinates;
4742b09969d6SVaclav Hapla   DM           cdm;
4743b09969d6SVaclav Hapla   PetscScalar *coords;
47441edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
4745b09969d6SVaclav Hapla 
4746b09969d6SVaclav Hapla   PetscFunctionBegin;
47479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
47489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
47491dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
47509566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
47519566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
47529566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
47539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
47549566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
47551edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
47569566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
47579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4758b09969d6SVaclav Hapla   }
47599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4760b09969d6SVaclav Hapla 
47619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
47629566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
47639566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
47649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
47659566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
47661edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
4767ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
4768b09969d6SVaclav Hapla   }
47699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
47709566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
47719566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
47729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4773b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4774b09969d6SVaclav Hapla }
4775b09969d6SVaclav Hapla 
4776b09969d6SVaclav Hapla /*@
4777*a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
47783df08285SMatthew G. Knepley 
4779*a1cb98faSBarry Smith   Collective
4780b09969d6SVaclav Hapla 
4781b09969d6SVaclav Hapla   Input Parameters:
4782b09969d6SVaclav Hapla + comm - The communicator
4783b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
47843df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
4785*a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
47863df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4787b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
47883df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4789b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
47903df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4791b09969d6SVaclav Hapla 
4792b09969d6SVaclav Hapla   Output Parameter:
4793*a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
479425b6865aSVaclav Hapla 
4795b09969d6SVaclav Hapla   Level: intermediate
4796b09969d6SVaclav Hapla 
4797*a1cb98faSBarry Smith   Notes:
4798*a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
4799*a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
4800*a1cb98faSBarry Smith 
4801*a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
4802*a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
4803*a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
4804*a1cb98faSBarry Smith 
4805*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
48069298eaa6SMatthew G Knepley @*/
4807d71ae5a4SJacob 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)
4808d71ae5a4SJacob Faibussowitsch {
48093df08285SMatthew G. Knepley   PetscMPIInt rank;
48109298eaa6SMatthew G Knepley 
48119298eaa6SMatthew G Knepley   PetscFunctionBegin;
481228b400f6SJacob 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.");
48139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
48149566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
48159566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
48169566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
4817c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
48189566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
48199298eaa6SMatthew G Knepley   if (interpolate) {
48205fd9971aSMatthew G. Knepley     DM idm;
48219298eaa6SMatthew G Knepley 
48229566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
48239566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
48249298eaa6SMatthew G Knepley     *dm = idm;
48259298eaa6SMatthew G Knepley   }
4826c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
48279566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
48289298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
48299298eaa6SMatthew G Knepley }
48309298eaa6SMatthew G Knepley 
4831939f6067SMatthew G. Knepley /*@
4832939f6067SMatthew 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
4833939f6067SMatthew G. Knepley 
4834939f6067SMatthew G. Knepley   Input Parameters:
4835c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4836939f6067SMatthew G. Knepley . depth - The depth of the DAG
4837367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4838939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4839939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4840939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4841367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4842939f6067SMatthew G. Knepley 
4843939f6067SMatthew G. Knepley   Output Parameter:
4844939f6067SMatthew G. Knepley . dm - The DM
4845939f6067SMatthew G. Knepley 
4846*a1cb98faSBarry Smith   Note:
4847*a1cb98faSBarry Smith   Two triangles sharing a face would have input
4848*a1cb98faSBarry Smith .vb
4849*a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4850*a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4851*a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4852*a1cb98faSBarry Smith .ve
4853939f6067SMatthew G. Knepley which would result in the DMPlex
4854*a1cb98faSBarry Smith .vb
4855*a1cb98faSBarry Smith         4
4856*a1cb98faSBarry Smith       / | \
4857*a1cb98faSBarry Smith      /  |  \
4858*a1cb98faSBarry Smith     /   |   \
4859*a1cb98faSBarry Smith    2  0 | 1  5
4860*a1cb98faSBarry Smith     \   |   /
4861*a1cb98faSBarry Smith      \  |  /
4862*a1cb98faSBarry Smith       \ | /
4863*a1cb98faSBarry Smith         3
4864*a1cb98faSBarry Smith .ve
4865*a1cb98faSBarry Smith  Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
4866939f6067SMatthew G. Knepley 
4867939f6067SMatthew G. Knepley   Level: advanced
4868939f6067SMatthew G. Knepley 
4869*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
4870939f6067SMatthew G. Knepley @*/
4871d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
4872d71ae5a4SJacob Faibussowitsch {
48739298eaa6SMatthew G Knepley   Vec          coordinates;
48749298eaa6SMatthew G Knepley   PetscSection coordSection;
48759298eaa6SMatthew G Knepley   PetscScalar *coords;
4876811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
48779298eaa6SMatthew G Knepley 
48789298eaa6SMatthew G Knepley   PetscFunctionBegin;
48799566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
48809566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
488163a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
48829298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
48839566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
48849298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
48859566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
4886ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
488797e052ccSToby Isaac   }
48881dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
48899566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
48909298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
48919566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
48929566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
48939298eaa6SMatthew G Knepley   }
48949566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
48959566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
48969298eaa6SMatthew G Knepley   /* Build coordinates */
48979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
48989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
48999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
49009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
49019298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
49029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
49039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
49049298eaa6SMatthew G Knepley   }
49059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
49069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
49079566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
49089566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
49099566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
49109566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
49119566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
49129318fe57SMatthew G. Knepley   if (vertexCoords) {
49139566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
49149298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
49159298eaa6SMatthew G Knepley       PetscInt off;
49169298eaa6SMatthew G Knepley 
49179566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
4918ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
49199298eaa6SMatthew G Knepley     }
49209318fe57SMatthew G. Knepley   }
49219566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
49229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
49239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
49249298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
49259298eaa6SMatthew G Knepley }
49268415267dSToby Isaac 
4927ca522641SMatthew G. Knepley /*@C
4928*a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
4929*a1cb98faSBarry Smith 
4930*a1cb98faSBarry Smith   Collective
4931*a1cb98faSBarry Smith 
4932*a1cb98faSBarry Smith   Collective
49338ca92349SMatthew G. Knepley 
49348ca92349SMatthew G. Knepley + comm        - The MPI communicator
49358ca92349SMatthew G. Knepley . filename    - Name of the .dat file
49368ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
49378ca92349SMatthew G. Knepley 
49388ca92349SMatthew G. Knepley   Output Parameter:
4939*a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
49408ca92349SMatthew G. Knepley 
49418ca92349SMatthew G. Knepley   Level: beginner
49428ca92349SMatthew G. Knepley 
4943*a1cb98faSBarry Smith   Note:
4944*a1cb98faSBarry Smith   The format is the simplest possible:
4945*a1cb98faSBarry Smith .vb
4946*a1cb98faSBarry Smith   Ne
4947*a1cb98faSBarry Smith   v0 v1 ... vk
4948*a1cb98faSBarry Smith   Nv
4949*a1cb98faSBarry Smith   x y z marker
4950*a1cb98faSBarry Smith .ve
4951*a1cb98faSBarry Smith 
4952*a1cb98faSBarry Smith   Developer Note:
4953*a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
4954*a1cb98faSBarry Smith 
4955*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
49568ca92349SMatthew G. Knepley @*/
4957d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
4958d71ae5a4SJacob Faibussowitsch {
49598ca92349SMatthew G. Knepley   DMLabel      marker;
49608ca92349SMatthew G. Knepley   PetscViewer  viewer;
49618ca92349SMatthew G. Knepley   Vec          coordinates;
49628ca92349SMatthew G. Knepley   PetscSection coordSection;
49638ca92349SMatthew G. Knepley   PetscScalar *coords;
49648ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
49658ca92349SMatthew G. Knepley   PetscInt     dim = 3, cdim = 3, coordSize, v, c, d;
49668ca92349SMatthew G. Knepley   PetscMPIInt  rank;
4967f8d5e320SMatthew G. Knepley   int          snum, Nv, Nc, Ncn, Nl;
49688ca92349SMatthew G. Knepley 
49698ca92349SMatthew G. Knepley   PetscFunctionBegin;
49709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
49719566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
49729566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
49739566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
49749566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
4975dd400576SPatrick Sanan   if (rank == 0) {
49769566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4977f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
497808401ef6SPierre Jolivet     PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
497925ce1634SJed Brown   } else {
4980f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
49818ca92349SMatthew G. Knepley   }
49829566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
49839566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
49849566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
49859566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
49869566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
49878ca92349SMatthew G. Knepley   /* Read topology */
4988dd400576SPatrick Sanan   if (rank == 0) {
4989f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
4990f8d5e320SMatthew G. Knepley     PetscInt cone[8];
49918ca92349SMatthew G. Knepley     int      vbuf[8], v;
49928ca92349SMatthew G. Knepley 
49939371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
49949371c9d4SSatish Balay       format[c * 3 + 0] = '%';
49959371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
49969371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
49979371c9d4SSatish Balay     }
4998f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
49999566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
50009566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
50018ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
50029566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
5003f8d5e320SMatthew G. Knepley       switch (Ncn) {
5004d71ae5a4SJacob Faibussowitsch       case 2:
5005d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
5006d71ae5a4SJacob Faibussowitsch         break;
5007d71ae5a4SJacob Faibussowitsch       case 3:
5008d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
5009d71ae5a4SJacob Faibussowitsch         break;
5010d71ae5a4SJacob Faibussowitsch       case 4:
5011d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
5012d71ae5a4SJacob Faibussowitsch         break;
5013d71ae5a4SJacob Faibussowitsch       case 6:
5014d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
5015d71ae5a4SJacob Faibussowitsch         break;
5016d71ae5a4SJacob Faibussowitsch       case 8:
5017d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
5018d71ae5a4SJacob Faibussowitsch         break;
5019d71ae5a4SJacob Faibussowitsch       default:
5020d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
5021f8d5e320SMatthew G. Knepley       }
502208401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5023f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
50248ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
5025f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
50268ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
50278ca92349SMatthew G. Knepley         cone[1]      = cone[3];
50288ca92349SMatthew G. Knepley         cone[3]      = tmp;
50298ca92349SMatthew G. Knepley       }
50309566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
50318ca92349SMatthew G. Knepley     }
50328ca92349SMatthew G. Knepley   }
50339566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
50349566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
50358ca92349SMatthew G. Knepley   /* Read coordinates */
50369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
50379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
50389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
50399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
50408ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
50419566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
50429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
50438ca92349SMatthew G. Knepley   }
50449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
50459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
50469566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
50479566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
50489566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
50499566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
50509566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
50519566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5052dd400576SPatrick Sanan   if (rank == 0) {
5053f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
50548ca92349SMatthew G. Knepley     double x[3];
5055f8d5e320SMatthew G. Knepley     int    l, val[3];
50568ca92349SMatthew G. Knepley 
5057f8d5e320SMatthew G. Knepley     if (Nl) {
50589371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
50599371c9d4SSatish Balay         format[l * 3 + 0] = '%';
50609371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
50619371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
50629371c9d4SSatish Balay       }
5063f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
50649566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50659566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
5066f8d5e320SMatthew G. Knepley     }
50678ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
50689566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
5069f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
507008401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5071f8d5e320SMatthew G. Knepley       switch (Nl) {
5072d71ae5a4SJacob Faibussowitsch       case 0:
5073d71ae5a4SJacob Faibussowitsch         snum = 0;
5074d71ae5a4SJacob Faibussowitsch         break;
5075d71ae5a4SJacob Faibussowitsch       case 1:
5076d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
5077d71ae5a4SJacob Faibussowitsch         break;
5078d71ae5a4SJacob Faibussowitsch       case 2:
5079d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
5080d71ae5a4SJacob Faibussowitsch         break;
5081d71ae5a4SJacob Faibussowitsch       case 3:
5082d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
5083d71ae5a4SJacob Faibussowitsch         break;
5084d71ae5a4SJacob Faibussowitsch       default:
5085d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
5086f8d5e320SMatthew G. Knepley       }
508708401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
50888ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
50899566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
50908ca92349SMatthew G. Knepley     }
50918ca92349SMatthew G. Knepley   }
50929566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
50939566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
50949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
50959566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
50968ca92349SMatthew G. Knepley   if (interpolate) {
50978ca92349SMatthew G. Knepley     DM      idm;
50988ca92349SMatthew G. Knepley     DMLabel bdlabel;
50998ca92349SMatthew G. Knepley 
51009566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
51019566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
51028ca92349SMatthew G. Knepley     *dm = idm;
51038ca92349SMatthew G. Knepley 
5104f8d5e320SMatthew G. Knepley     if (!Nl) {
51059566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
51069566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
51079566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
51089566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
51098ca92349SMatthew G. Knepley     }
5110f8d5e320SMatthew G. Knepley   }
51118ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
51128ca92349SMatthew G. Knepley }
51138ca92349SMatthew G. Knepley 
51148ca92349SMatthew G. Knepley /*@C
5115*a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
5116*a1cb98faSBarry Smith 
5117*a1cb98faSBarry Smith   Collective
5118ca522641SMatthew G. Knepley 
5119ca522641SMatthew G. Knepley   Input Parameters:
5120ca522641SMatthew G. Knepley + comm - The communicator
5121ca522641SMatthew G. Knepley . filename - A file name
5122*a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
5123ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
5124ca522641SMatthew G. Knepley 
5125ca522641SMatthew G. Knepley   Output Parameter:
5126*a1cb98faSBarry Smith . dm - The `DM`
5127ca522641SMatthew G. Knepley 
5128*a1cb98faSBarry Smith   Options Database Key:
5129*a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
513002ef0d99SVaclav Hapla 
5131bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
5132bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
5133bca97951SVaclav Hapla 
5134ca522641SMatthew G. Knepley   Level: beginner
5135ca522641SMatthew G. Knepley 
5136*a1cb98faSBarry Smith   Notes:
5137*a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
5138*a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
5139*a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
5140*a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
5141*a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
5142*a1cb98faSBarry Smith 
5143*a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
5144ca522641SMatthew G. Knepley @*/
5145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
5146d71ae5a4SJacob Faibussowitsch {
5147ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
5148ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
5149ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
5150ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
5151ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
5152ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
5153ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
5154ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
5155ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
5156ef3a5affSJacob Faibussowitsch   const char  extMed[]       = ".med";
5157ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
5158ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
5159ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
5160ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
5161ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
5162ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
5163ca522641SMatthew G. Knepley   size_t      len;
5164c1cad2e7SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
5165ca522641SMatthew G. Knepley   PetscMPIInt rank;
5166ca522641SMatthew G. Knepley 
5167ca522641SMatthew G. Knepley   PetscFunctionBegin;
51685d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
51690d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
5170cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
51719566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
51729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
51739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
51749566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
517528b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
5176ef3a5affSJacob Faibussowitsch 
51779371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
51789371c9d4SSatish Balay   do { \
5179274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
5180274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
5181274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
5182274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
5183ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
5184ef3a5affSJacob Faibussowitsch     } else { \
5185274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
5186ef3a5affSJacob Faibussowitsch     } \
5187ef3a5affSJacob Faibussowitsch   } while (0)
5188ef3a5affSJacob Faibussowitsch 
5189ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
5190ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
5191ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
5192ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
5193ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
5194ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
5195ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
5196ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
5197ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
5198ef3a5affSJacob Faibussowitsch   CheckExtension(extMed, isMed);
5199ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
5200ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
5201ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
5202ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
5203ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
5204ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
5205ef3a5affSJacob Faibussowitsch 
5206ef3a5affSJacob Faibussowitsch #undef CheckExtension
5207ef3a5affSJacob Faibussowitsch 
5208de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
52099566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
5210ca522641SMatthew G. Knepley   } else if (isCGNS) {
52119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
521290c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
52139566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
52142f0bd6dcSMichael Lange   } else if (isFluent) {
52159566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
5216cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
52179c48423bSVaclav Hapla     PetscBool   load_hdf5_xdmf = PETSC_FALSE;
5218cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
5219cc2f8f65SMatthew G. Knepley 
522043b242b4SVaclav 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 */
52219566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf));
52229566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
52239566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
52249566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
52259566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
52269566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
52279566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
52289566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
5229cd7e8a5eSksagiyam 
52309566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
52319566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52329566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
52339566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
52349566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
52359566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer));
52369566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
52375fd9971aSMatthew G. Knepley 
52385fd9971aSMatthew G. Knepley     if (interpolate) {
52395fd9971aSMatthew G. Knepley       DM idm;
52405fd9971aSMatthew G. Knepley 
52419566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
52429566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52435fd9971aSMatthew G. Knepley       *dm = idm;
52445fd9971aSMatthew G. Knepley     }
5245707dd687SMichael Lange   } else if (isMed) {
52469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
5247f2801cd6SMatthew G. Knepley   } else if (isPLY) {
52489566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
5249c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
52509566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
52519566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
52527bee2925SMatthew Knepley     if (!interpolate) {
52537bee2925SMatthew Knepley       DM udm;
52547bee2925SMatthew Knepley 
52559566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
52569566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52577bee2925SMatthew Knepley       *dm = udm;
52587bee2925SMatthew Knepley     }
52598ca92349SMatthew G. Knepley   } else if (isCV) {
52609566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
526198921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
52629566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
52639566063dSJacob Faibussowitsch   if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
5265ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
5266ca522641SMatthew G. Knepley }
5267