xref: /petsc/src/dm/impls/plex/plexcreate.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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>
5b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
6b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
7552f7358SJed Brown 
8b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
958cd63d5SVaclav Hapla 
109318fe57SMatthew G. Knepley /* External function declarations here */
119318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
129318fe57SMatthew G. Knepley 
13e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
14e600fa54SMatthew G. Knepley PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, DM dmout)
15e600fa54SMatthew G. Knepley {
16e600fa54SMatthew G. Knepley   const DMBoundaryType *bd;
17e600fa54SMatthew G. Knepley   const PetscReal      *maxCell, *L;
18e600fa54SMatthew G. Knepley   PetscBool             isper, dist;
19e600fa54SMatthew G. Knepley 
20e600fa54SMatthew G. Knepley   PetscFunctionBegin;
21e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
22*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetPeriodicity(dmin, &isper, &maxCell, &L, &bd));
23*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetPeriodicity(dmout, isper,  maxCell,  L,  bd));
24e600fa54SMatthew G. Knepley   }
25*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeGetDefault(dmin, &dist));
26*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeSetDefault(dmout, dist));
27e600fa54SMatthew G. Knepley   ((DM_Plex *) dmout->data)->useHashLocation = ((DM_Plex *) dmin->data)->useHashLocation;
28e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
29e600fa54SMatthew G. Knepley }
30e600fa54SMatthew G. Knepley 
319318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
329318fe57SMatthew G. Knepley    - Share the DM_Plex structure
339318fe57SMatthew G. Knepley    - Share the coordinates
349318fe57SMatthew G. Knepley    - Share the SF
359318fe57SMatthew G. Knepley */
369318fe57SMatthew G. Knepley static PetscErrorCode DMPlexReplace_Static(DM dm, DM *ndm)
379318fe57SMatthew G. Knepley {
389318fe57SMatthew G. Knepley   PetscSF               sf;
399318fe57SMatthew G. Knepley   DM                    dmNew = *ndm, coordDM, coarseDM;
409318fe57SMatthew G. Knepley   Vec                   coords;
419318fe57SMatthew G. Knepley   PetscBool             isper;
429318fe57SMatthew G. Knepley   const PetscReal      *maxCell, *L;
439318fe57SMatthew G. Knepley   const DMBoundaryType *bd;
449318fe57SMatthew G. Knepley   PetscInt              dim, cdim;
459318fe57SMatthew G. Knepley 
469318fe57SMatthew G. Knepley   PetscFunctionBegin;
479318fe57SMatthew G. Knepley   if (dm == dmNew) {
48*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(ndm));
499318fe57SMatthew G. Knepley     PetscFunctionReturn(0);
509318fe57SMatthew G. Knepley   }
519318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
52*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dmNew, &dim));
53*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim));
54*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dmNew, &cdim));
55*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, cdim));
56*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dmNew, &sf));
57*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(dm, sf));
58*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dmNew, &coordDM));
59*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dmNew, &coords));
60*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDM(dm, coordDM));
61*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coords));
629318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
63*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMFieldDestroy(&dm->coordinateField));
649318fe57SMatthew G. Knepley   dm->coordinateField = dmNew->coordinateField;
6561a622f3SMatthew G. Knepley   ((DM_Plex *) dmNew->data)->coordFunc = ((DM_Plex *) dm->data)->coordFunc;
66*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPeriodicity(dmNew, &isper, &maxCell, &L, &bd));
67*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPeriodicity(dm, isper, maxCell, L, bd));
68*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy_Plex(dm));
69*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMInitialize_Plex(dm));
709318fe57SMatthew G. Knepley   dm->data = dmNew->data;
719318fe57SMatthew G. Knepley   ((DM_Plex *) dmNew->data)->refct++;
72*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroyLabelLinkList_Internal(dm));
73*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
74*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoarseDM(dmNew,&coarseDM));
75*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoarseDM(dm,coarseDM));
76*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(ndm));
779318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
789318fe57SMatthew G. Knepley }
799318fe57SMatthew G. Knepley 
809318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
819318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
829318fe57SMatthew G. Knepley    - Swap the coordinates
839318fe57SMatthew G. Knepley    - Swap the point PetscSF
849318fe57SMatthew G. Knepley */
859318fe57SMatthew G. Knepley static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
869318fe57SMatthew G. Knepley {
879318fe57SMatthew G. Knepley   DM              coordDMA, coordDMB;
889318fe57SMatthew G. Knepley   Vec             coordsA,  coordsB;
899318fe57SMatthew G. Knepley   PetscSF         sfA,      sfB;
909318fe57SMatthew G. Knepley   DMField         fieldTmp;
919318fe57SMatthew G. Knepley   void            *tmp;
929318fe57SMatthew G. Knepley   DMLabelLink     listTmp;
939318fe57SMatthew G. Knepley   DMLabel         depthTmp;
949318fe57SMatthew G. Knepley   PetscInt        tmpI;
959318fe57SMatthew G. Knepley 
969318fe57SMatthew G. Knepley   PetscFunctionBegin;
979318fe57SMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
98*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dmA, &sfA));
99*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dmB, &sfB));
100*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) sfA));
101*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(dmA, sfB));
102*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(dmB, sfA));
103*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectDereference((PetscObject) sfA));
1049318fe57SMatthew G. Knepley 
105*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dmA, &coordDMA));
106*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dmB, &coordDMB));
107*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) coordDMA));
108*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDM(dmA, coordDMB));
109*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDM(dmB, coordDMA));
110*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectDereference((PetscObject) coordDMA));
1119318fe57SMatthew G. Knepley 
112*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dmA, &coordsA));
113*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dmB, &coordsB));
114*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject) coordsA));
115*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dmA, coordsB));
116*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dmB, coordsA));
117*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectDereference((PetscObject) coordsA));
1189318fe57SMatthew G. Knepley 
1199318fe57SMatthew G. Knepley   fieldTmp             = dmA->coordinateField;
1209318fe57SMatthew G. Knepley   dmA->coordinateField = dmB->coordinateField;
1219318fe57SMatthew G. Knepley   dmB->coordinateField = fieldTmp;
1229318fe57SMatthew G. Knepley   tmp       = dmA->data;
1239318fe57SMatthew G. Knepley   dmA->data = dmB->data;
1249318fe57SMatthew G. Knepley   dmB->data = tmp;
1259318fe57SMatthew G. Knepley   listTmp   = dmA->labels;
1269318fe57SMatthew G. Knepley   dmA->labels = dmB->labels;
1279318fe57SMatthew G. Knepley   dmB->labels = listTmp;
1289318fe57SMatthew G. Knepley   depthTmp  = dmA->depthLabel;
1299318fe57SMatthew G. Knepley   dmA->depthLabel = dmB->depthLabel;
1309318fe57SMatthew G. Knepley   dmB->depthLabel = depthTmp;
1319318fe57SMatthew G. Knepley   depthTmp  = dmA->celltypeLabel;
1329318fe57SMatthew G. Knepley   dmA->celltypeLabel = dmB->celltypeLabel;
1339318fe57SMatthew G. Knepley   dmB->celltypeLabel = depthTmp;
1349318fe57SMatthew G. Knepley   tmpI         = dmA->levelup;
1359318fe57SMatthew G. Knepley   dmA->levelup = dmB->levelup;
1369318fe57SMatthew G. Knepley   dmB->levelup = tmpI;
1379318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1389318fe57SMatthew G. Knepley }
1399318fe57SMatthew G. Knepley 
1409318fe57SMatthew G. Knepley static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
1419318fe57SMatthew G. Knepley {
1429318fe57SMatthew G. Knepley   DM             idm;
1439318fe57SMatthew G. Knepley 
1449318fe57SMatthew G. Knepley   PetscFunctionBegin;
145*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexInterpolate(dm, &idm));
146*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCopyCoordinates(dm, idm));
147*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexReplace_Static(dm, &idm));
1489318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1499318fe57SMatthew G. Knepley }
1509318fe57SMatthew G. Knepley 
1519318fe57SMatthew G. Knepley /*@C
1529318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
1539318fe57SMatthew G. Knepley 
1549318fe57SMatthew G. Knepley   Collective
1559318fe57SMatthew G. Knepley 
1569318fe57SMatthew G. Knepley   Input Parameters:
1579318fe57SMatthew G. Knepley + DM        - The DM
1584f9ab2b4SJed Brown . degree    - The degree of the finite element or PETSC_DECIDE
1599318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
1609318fe57SMatthew G. Knepley 
1619318fe57SMatthew G. Knepley   Level: advanced
1629318fe57SMatthew G. Knepley 
1639318fe57SMatthew G. Knepley .seealso: PetscFECreateLagrange(), DMGetCoordinateDM()
1649318fe57SMatthew G. Knepley @*/
1659318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc)
1669318fe57SMatthew G. Knepley {
1679318fe57SMatthew G. Knepley   DM_Plex      *mesh = (DM_Plex *) dm->data;
1689318fe57SMatthew G. Knepley   DM            cdm;
1699318fe57SMatthew G. Knepley   PetscDS       cds;
1709318fe57SMatthew G. Knepley   PetscFE       fe;
1719318fe57SMatthew G. Knepley   PetscClassId  id;
1729318fe57SMatthew G. Knepley 
1739318fe57SMatthew G. Knepley   PetscFunctionBegin;
174*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm, &cdm));
175*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDS(cdm, &cds));
176*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSGetDiscretization(cds, 0, (PetscObject *) &fe));
177*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetClassId((PetscObject) fe, &id));
1789318fe57SMatthew G. Knepley   if (id != PETSCFE_CLASSID) {
1799318fe57SMatthew G. Knepley     PetscBool      simplex;
1809318fe57SMatthew G. Knepley     PetscInt       dim, dE, qorder;
181*5f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr;
1829318fe57SMatthew G. Knepley 
183*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &dim));
184*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDim(dm, &dE));
185*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsSimplex(dm, &simplex));
1869318fe57SMatthew G. Knepley     qorder = degree;
1879318fe57SMatthew G. Knepley     ierr = PetscObjectOptionsBegin((PetscObject) cdm);CHKERRQ(ierr);
188*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
1899318fe57SMatthew G. Knepley     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1904f9ab2b4SJed Brown     if (degree == PETSC_DECIDE) fe = NULL;
1914f9ab2b4SJed Brown     else {
192*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe));
193*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) fe));
194*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreateDS(cdm));
1954f9ab2b4SJed Brown     }
196*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMProjectCoordinates(dm, fe));
197*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFEDestroy(&fe));
1989318fe57SMatthew G. Knepley   }
1999318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2009318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
2019318fe57SMatthew G. Knepley }
2029318fe57SMatthew G. Knepley 
2031df5d5c5SMatthew G. Knepley /*@
2041df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2051df5d5c5SMatthew G. Knepley 
206d083f849SBarry Smith   Collective
2071df5d5c5SMatthew G. Knepley 
2081df5d5c5SMatthew G. Knepley   Input Parameters:
2091df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object
2101df5d5c5SMatthew G. Knepley . dim - The spatial dimension
2111df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells
2121df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces)
2131df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2141df5d5c5SMatthew G. Knepley 
2151df5d5c5SMatthew G. Knepley   Output Parameter:
2161df5d5c5SMatthew G. Knepley . dm - The DM object
2171df5d5c5SMatthew G. Knepley 
2181df5d5c5SMatthew G. Knepley   Level: beginner
2191df5d5c5SMatthew G. Knepley 
2201df5d5c5SMatthew G. Knepley .seealso: DMSetType(), DMCreate()
2211df5d5c5SMatthew G. Knepley @*/
2220fdc7489SMatthew Knepley PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
2231df5d5c5SMatthew G. Knepley {
2241df5d5c5SMatthew G. Knepley   DM             dm;
2251df5d5c5SMatthew G. Knepley   PetscMPIInt    rank;
2261df5d5c5SMatthew G. Knepley 
2271df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
228*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, &dm));
229*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(dm, DMPLEX));
230*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim));
231*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
232ce78fa2fSMatthew G. Knepley   switch (dim) {
233ce78fa2fSMatthew G. Knepley   case 2:
234*5f80ce2aSJacob Faibussowitsch     if (simplex) CHKERRQ(PetscObjectSetName((PetscObject) dm, "triangular"));
235*5f80ce2aSJacob Faibussowitsch     else         CHKERRQ(PetscObjectSetName((PetscObject) dm, "quadrilateral"));
236ce78fa2fSMatthew G. Knepley     break;
237ce78fa2fSMatthew G. Knepley   case 3:
238*5f80ce2aSJacob Faibussowitsch     if (simplex) CHKERRQ(PetscObjectSetName((PetscObject) dm, "tetrahedral"));
239*5f80ce2aSJacob Faibussowitsch     else         CHKERRQ(PetscObjectSetName((PetscObject) dm, "hexahedral"));
240ce78fa2fSMatthew G. Knepley     break;
241ce78fa2fSMatthew G. Knepley   default:
24298921bdaSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", dim);
243ce78fa2fSMatthew G. Knepley   }
2441df5d5c5SMatthew G. Knepley   if (rank) {
2451df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
246*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
2471df5d5c5SMatthew G. Knepley   } else {
2481df5d5c5SMatthew G. Knepley     switch (dim) {
2491df5d5c5SMatthew G. Knepley     case 2:
2501df5d5c5SMatthew G. Knepley       if (simplex) {
2511df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
2521df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
2531df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4,  5, 4, 3};
2541df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0,  0, 0, 0};
2551df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
2561df5d5c5SMatthew G. Knepley 
257*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2581df5d5c5SMatthew G. Knepley       } else {
2591df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
2601df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
2611df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5,  3, 6, 7, 4};
2621df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0,  0, 0, 0, 0};
2631df5d5c5SMatthew 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};
2641df5d5c5SMatthew G. Knepley 
265*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2661df5d5c5SMatthew G. Knepley       }
2671df5d5c5SMatthew G. Knepley       break;
2681df5d5c5SMatthew G. Knepley     case 3:
2691df5d5c5SMatthew G. Knepley       if (simplex) {
2701df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
2711df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
2721df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2,  5, 3, 4, 6};
2731df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0,  0, 0, 0, 0};
2741df5d5c5SMatthew 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};
2751df5d5c5SMatthew G. Knepley 
276*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2771df5d5c5SMatthew G. Knepley       } else {
2781df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
2791df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2801df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9,  5, 4, 10, 11, 7, 12, 13, 8};
2811df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0,  0, 0,  0,  0, 0,  0,  0, 0};
2821df5d5c5SMatthew G. Knepley         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,
2831df5d5c5SMatthew G. Knepley                                             -1.0, -0.5,  0.5,   0.0, -0.5,  0.5,  0.0,  0.5,  0.5,  -1.0,  0.5,  0.5,
2841df5d5c5SMatthew G. Knepley                                              1.0,  0.5, -0.5,   1.0, -0.5, -0.5,  1.0, -0.5,  0.5,   1.0,  0.5,  0.5};
2851df5d5c5SMatthew G. Knepley 
286*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2871df5d5c5SMatthew G. Knepley       }
2881df5d5c5SMatthew G. Knepley       break;
2891df5d5c5SMatthew G. Knepley     default:
29098921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", dim);
2911df5d5c5SMatthew G. Knepley     }
2921df5d5c5SMatthew G. Knepley   }
2931df5d5c5SMatthew G. Knepley   *newdm = dm;
2941df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
2951df5d5c5SMatthew G. Knepley     DM rdm;
2961df5d5c5SMatthew G. Knepley     const char *name;
2971df5d5c5SMatthew G. Knepley 
298*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
299*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetRefinementLimit(*newdm, refinementLimit));
300*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRefine(*newdm, comm, &rdm));
301*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) *newdm, &name));
302*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject)    rdm,  name));
303*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(newdm));
3041df5d5c5SMatthew G. Knepley     *newdm = rdm;
3051df5d5c5SMatthew G. Knepley   }
3061df5d5c5SMatthew G. Knepley   if (interpolate) {
3075fd9971aSMatthew G. Knepley     DM idm;
3081df5d5c5SMatthew G. Knepley 
309*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(*newdm, &idm));
310*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(newdm));
3111df5d5c5SMatthew G. Knepley     *newdm = idm;
3121df5d5c5SMatthew G. Knepley   }
3131df5d5c5SMatthew G. Knepley   PetscFunctionReturn(0);
3141df5d5c5SMatthew G. Knepley }
3151df5d5c5SMatthew G. Knepley 
3169318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
3179318fe57SMatthew G. Knepley {
3189318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3199318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3209318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3219318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3229318fe57SMatthew G. Knepley   Vec            coordinates;
3239318fe57SMatthew G. Knepley   PetscSection   coordSection;
3249318fe57SMatthew G. Knepley   PetscScalar   *coords;
3259318fe57SMatthew G. Knepley   PetscInt       coordSize;
3269318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3279318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
328552f7358SJed Brown 
3299318fe57SMatthew G. Knepley   PetscFunctionBegin;
330*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3319318fe57SMatthew G. Knepley   if (markerSeparate) {
3329318fe57SMatthew G. Knepley     markerRight  = 2;
3339318fe57SMatthew G. Knepley     markerLeft   = 1;
3349318fe57SMatthew G. Knepley   }
335*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
3369318fe57SMatthew G. Knepley   if (!rank) {
337*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetChart(dm, 0, numVertices));
338*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
339*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelValue(dm, "marker", 0, markerLeft));
340*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelValue(dm, "marker", 1, markerRight));
3419318fe57SMatthew G. Knepley   }
342*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dm));
343*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dm));
3449318fe57SMatthew G. Knepley   /* Build coordinates */
345*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, cdim));
346*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
347*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
348*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, 0, numVertices));
349*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, cdim));
3509318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
351*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, cdim));
352*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
3539318fe57SMatthew G. Knepley   }
354*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
355*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
356*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
357*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
358*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
359*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, cdim));
360*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
361*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
3629318fe57SMatthew G. Knepley   coords[0] = lower[0];
3639318fe57SMatthew G. Knepley   coords[1] = upper[0];
364*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
365*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
366*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
3679318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
3689318fe57SMatthew G. Knepley }
36926492d91SMatthew G. Knepley 
3709318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
371552f7358SJed Brown {
3721df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0]+1)*(edges[1]+1);
3731df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
374552f7358SJed Brown   PetscInt       markerTop      = 1;
375552f7358SJed Brown   PetscInt       markerBottom   = 1;
376552f7358SJed Brown   PetscInt       markerRight    = 1;
377552f7358SJed Brown   PetscInt       markerLeft     = 1;
378552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
379552f7358SJed Brown   Vec            coordinates;
380552f7358SJed Brown   PetscSection   coordSection;
381552f7358SJed Brown   PetscScalar    *coords;
382552f7358SJed Brown   PetscInt       coordSize;
383552f7358SJed Brown   PetscMPIInt    rank;
384552f7358SJed Brown   PetscInt       v, vx, vy;
385552f7358SJed Brown 
386552f7358SJed Brown   PetscFunctionBegin;
387*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
388552f7358SJed Brown   if (markerSeparate) {
3891df21d24SMatthew G. Knepley     markerTop    = 3;
3901df21d24SMatthew G. Knepley     markerBottom = 1;
3911df21d24SMatthew G. Knepley     markerRight  = 2;
3921df21d24SMatthew G. Knepley     markerLeft   = 4;
393552f7358SJed Brown   }
394*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
395dd400576SPatrick Sanan   if (rank == 0) {
396552f7358SJed Brown     PetscInt e, ex, ey;
397552f7358SJed Brown 
398*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetChart(dm, 0, numEdges+numVertices));
399552f7358SJed Brown     for (e = 0; e < numEdges; ++e) {
400*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(dm, e, 2));
401552f7358SJed Brown     }
402*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
403552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
404552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
405552f7358SJed Brown         PetscInt edge   = vx*edges[1] + ey + edges[0]*(edges[1]+1);
406552f7358SJed Brown         PetscInt vertex = ey*(edges[0]+1) + vx + numEdges;
407da80777bSKarl Rupp         PetscInt cone[2];
408552f7358SJed Brown 
409da80777bSKarl Rupp         cone[0] = vertex; cone[1] = vertex+edges[0]+1;
410*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, edge, cone));
411552f7358SJed Brown         if (vx == edges[0]) {
412*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerRight));
413*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerRight));
414552f7358SJed Brown           if (ey == edges[1]-1) {
415*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerRight));
416*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
417552f7358SJed Brown           }
418552f7358SJed Brown         } else if (vx == 0) {
419*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerLeft));
420*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
421552f7358SJed Brown           if (ey == edges[1]-1) {
422*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
423*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
424552f7358SJed Brown           }
425552f7358SJed Brown         }
426552f7358SJed Brown       }
427552f7358SJed Brown     }
428552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
429552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
430552f7358SJed Brown         PetscInt edge   = vy*edges[0]     + ex;
431552f7358SJed Brown         PetscInt vertex = vy*(edges[0]+1) + ex + numEdges;
432da80777bSKarl Rupp         PetscInt cone[2];
433552f7358SJed Brown 
434da80777bSKarl Rupp         cone[0] = vertex; cone[1] = vertex+1;
435*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, edge, cone));
436552f7358SJed Brown         if (vy == edges[1]) {
437*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerTop));
438*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerTop));
439552f7358SJed Brown           if (ex == edges[0]-1) {
440*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerTop));
441*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
442552f7358SJed Brown           }
443552f7358SJed Brown         } else if (vy == 0) {
444*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerBottom));
445*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
446552f7358SJed Brown           if (ex == edges[0]-1) {
447*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
448*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
449552f7358SJed Brown           }
450552f7358SJed Brown         }
451552f7358SJed Brown       }
452552f7358SJed Brown     }
453552f7358SJed Brown   }
454*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dm));
455*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dm));
456552f7358SJed Brown   /* Build coordinates */
457*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, 2));
458*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
459*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
460*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
461*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, 2));
462552f7358SJed Brown   for (v = numEdges; v < numEdges+numVertices; ++v) {
463*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, 2));
464*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, 2));
465552f7358SJed Brown   }
466*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
467*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
468*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
469*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
470*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
471*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, 2));
472*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
473*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
474552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
475552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
476552f7358SJed Brown       coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
477552f7358SJed Brown       coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
478552f7358SJed Brown     }
479552f7358SJed Brown   }
480*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
481*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
482*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
483552f7358SJed Brown   PetscFunctionReturn(0);
484552f7358SJed Brown }
485552f7358SJed Brown 
4869318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
487552f7358SJed Brown {
4889e8abbc3SMichael Lange   PetscInt       vertices[3], numVertices;
4897b59f5a9SMichael Lange   PetscInt       numFaces    = 2*faces[0]*faces[1] + 2*faces[1]*faces[2] + 2*faces[0]*faces[2];
490552f7358SJed Brown   Vec            coordinates;
491552f7358SJed Brown   PetscSection   coordSection;
492552f7358SJed Brown   PetscScalar    *coords;
493552f7358SJed Brown   PetscInt       coordSize;
494552f7358SJed Brown   PetscMPIInt    rank;
495552f7358SJed Brown   PetscInt       v, vx, vy, vz;
4967b59f5a9SMichael Lange   PetscInt       voffset, iface=0, cone[4];
497552f7358SJed Brown 
498552f7358SJed Brown   PetscFunctionBegin;
4992c71b3e2SJacob Faibussowitsch   PetscCheckFalse((faces[0] < 1) || (faces[1] < 1) || (faces[2] < 1),PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side");
500*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
5019e8abbc3SMichael Lange   vertices[0] = faces[0]+1; vertices[1] = faces[1]+1; vertices[2] = faces[2]+1;
5029e8abbc3SMichael Lange   numVertices = vertices[0]*vertices[1]*vertices[2];
503dd400576SPatrick Sanan   if (rank == 0) {
504552f7358SJed Brown     PetscInt f;
505552f7358SJed Brown 
506*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetChart(dm, 0, numFaces+numVertices));
507552f7358SJed Brown     for (f = 0; f < numFaces; ++f) {
508*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(dm, f, 4));
509552f7358SJed Brown     }
510*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
5117b59f5a9SMichael Lange 
5127b59f5a9SMichael Lange     /* Side 0 (Top) */
5137b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5147b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5157b59f5a9SMichael Lange         voffset = numFaces + vertices[0]*vertices[1]*(vertices[2]-1) + vy*vertices[0] + vx;
5167b59f5a9SMichael Lange         cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]+1; cone[3] = voffset+vertices[0];
517*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, iface, cone));
518*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1));
519*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1));
520*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1));
521*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1));
522*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+1, 1));
5237b59f5a9SMichael Lange         iface++;
524552f7358SJed Brown       }
525552f7358SJed Brown     }
5267b59f5a9SMichael Lange 
5277b59f5a9SMichael Lange     /* Side 1 (Bottom) */
5287b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5297b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5307b59f5a9SMichael Lange         voffset = numFaces + vy*(faces[0]+1) + vx;
5317b59f5a9SMichael Lange         cone[0] = voffset+1; cone[1] = voffset; cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]+1;
532*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, iface, cone));
533*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1));
534*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1));
535*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1));
536*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1));
537*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+1, 1));
5387b59f5a9SMichael Lange         iface++;
539552f7358SJed Brown       }
540552f7358SJed Brown     }
5417b59f5a9SMichael Lange 
5427b59f5a9SMichael Lange     /* Side 2 (Front) */
5437b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5447b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5457b59f5a9SMichael Lange         voffset = numFaces + vz*vertices[0]*vertices[1] + vx;
5467b59f5a9SMichael Lange         cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]*vertices[1]+1; cone[3] = voffset+vertices[0]*vertices[1];
547*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, iface, cone));
548*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1));
549*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1));
550*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1));
551*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1));
552*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+1, 1));
5537b59f5a9SMichael Lange         iface++;
554552f7358SJed Brown       }
5557b59f5a9SMichael Lange     }
5567b59f5a9SMichael Lange 
5577b59f5a9SMichael Lange     /* Side 3 (Back) */
5587b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5597b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5607b59f5a9SMichael Lange         voffset = numFaces + vz*vertices[0]*vertices[1] + vertices[0]*(vertices[1]-1) + vx;
5617b59f5a9SMichael Lange         cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset+vertices[0]*vertices[1]+1;
5627b59f5a9SMichael Lange         cone[2] = voffset+1; cone[3] = voffset;
563*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, iface, cone));
564*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1));
565*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1));
566*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+1, 1));
567*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1));
568*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+1, 1));
5697b59f5a9SMichael Lange         iface++;
5707b59f5a9SMichael Lange       }
5717b59f5a9SMichael Lange     }
5727b59f5a9SMichael Lange 
5737b59f5a9SMichael Lange     /* Side 4 (Left) */
5747b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5757b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
5767b59f5a9SMichael Lange         voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0];
5777b59f5a9SMichael Lange         cone[0] = voffset; cone[1] = voffset+vertices[0]*vertices[1];
5787b59f5a9SMichael Lange         cone[2] = voffset+vertices[0]*vertices[1]+vertices[0]; cone[3] = voffset+vertices[0];
579*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, iface, cone));
580*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1));
581*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1));
582*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1));
583*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[1]+0, 1));
584*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1));
5857b59f5a9SMichael Lange         iface++;
5867b59f5a9SMichael Lange       }
5877b59f5a9SMichael Lange     }
5887b59f5a9SMichael Lange 
5897b59f5a9SMichael Lange     /* Side 5 (Right) */
5907b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5917b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
592aab5bcd8SJed Brown         voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0] + faces[0];
5937b59f5a9SMichael Lange         cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset;
5947b59f5a9SMichael Lange         cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]*vertices[1]+vertices[0];
595*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, iface, cone));
596*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", iface, 1));
597*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+0, 1));
598*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1));
599*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1));
600*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1));
6017b59f5a9SMichael Lange         iface++;
6027b59f5a9SMichael Lange       }
603552f7358SJed Brown     }
604552f7358SJed Brown   }
605*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dm));
606*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dm));
607552f7358SJed Brown   /* Build coordinates */
608*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, 3));
609*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
610*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
611*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
612*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, 3));
613552f7358SJed Brown   for (v = numFaces; v < numFaces+numVertices; ++v) {
614*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, 3));
615*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, 3));
616552f7358SJed Brown   }
617*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
618*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
619*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
620*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
621*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
622*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, 3));
623*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
624*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
625552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
626552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
627552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
628552f7358SJed Brown         coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
629552f7358SJed Brown         coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
630552f7358SJed Brown         coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
631552f7358SJed Brown       }
632552f7358SJed Brown     }
633552f7358SJed Brown   }
634*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
635*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
636*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
637552f7358SJed Brown   PetscFunctionReturn(0);
638552f7358SJed Brown }
639552f7358SJed Brown 
6409318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
6419318fe57SMatthew G. Knepley {
6429318fe57SMatthew G. Knepley   PetscFunctionBegin;
6439318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
644*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim-1));
645*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, dim));
6469318fe57SMatthew G. Knepley   switch (dim) {
647*5f80ce2aSJacob Faibussowitsch     case 1: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));break;
648*5f80ce2aSJacob Faibussowitsch     case 2: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));break;
649*5f80ce2aSJacob Faibussowitsch     case 3: CHKERRQ(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));break;
65098921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Dimension not supported: %D", dim);
6519318fe57SMatthew G. Knepley   }
652*5f80ce2aSJacob Faibussowitsch   if (interpolate) CHKERRQ(DMPlexInterpolateInPlace_Internal(dm));
6539318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
6549318fe57SMatthew G. Knepley }
6559318fe57SMatthew G. Knepley 
6569318fe57SMatthew G. Knepley /*@C
6579318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
6589318fe57SMatthew G. Knepley 
6599318fe57SMatthew G. Knepley   Collective
6609318fe57SMatthew G. Knepley 
6619318fe57SMatthew G. Knepley   Input Parameters:
6629318fe57SMatthew G. Knepley + comm        - The communicator for the DM object
6639318fe57SMatthew G. Knepley . dim         - The spatial dimension of the box, so the resulting mesh is has dimension dim-1
6649318fe57SMatthew 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
6659318fe57SMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
6669318fe57SMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
6679318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
6689318fe57SMatthew G. Knepley 
6699318fe57SMatthew G. Knepley   Output Parameter:
6709318fe57SMatthew G. Knepley . dm  - The DM object
6719318fe57SMatthew G. Knepley 
6729318fe57SMatthew G. Knepley   Level: beginner
6739318fe57SMatthew G. Knepley 
6749318fe57SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreateBoxMesh(), DMPlexCreateFromFile(), DMSetType(), DMCreate()
6759318fe57SMatthew G. Knepley @*/
6769318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
6779318fe57SMatthew G. Knepley {
6789318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
6799318fe57SMatthew G. Knepley   PetscReal      low[3] = {0, 0, 0};
6809318fe57SMatthew G. Knepley   PetscReal      upp[3] = {1, 1, 1};
6819318fe57SMatthew G. Knepley 
6829318fe57SMatthew G. Knepley   PetscFunctionBegin;
683*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm,dm));
684*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm,DMPLEX));
685*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
6869318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
6879318fe57SMatthew G. Knepley }
6889318fe57SMatthew G. Knepley 
6899318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm,PetscInt segments,PetscReal lower,PetscReal upper,DMBoundaryType bd)
690fdbf62faSLisandro Dalcin {
691fdbf62faSLisandro Dalcin   PetscInt       i,fStart,fEnd,numCells = 0,numVerts = 0;
692fdbf62faSLisandro Dalcin   PetscInt       numPoints[2],*coneSize,*cones,*coneOrientations;
693fdbf62faSLisandro Dalcin   PetscScalar    *vertexCoords;
694fdbf62faSLisandro Dalcin   PetscReal      L,maxCell;
695fdbf62faSLisandro Dalcin   PetscBool      markerSeparate = PETSC_FALSE;
696fdbf62faSLisandro Dalcin   PetscInt       markerLeft  = 1, faceMarkerLeft  = 1;
697fdbf62faSLisandro Dalcin   PetscInt       markerRight = 1, faceMarkerRight = 2;
698fdbf62faSLisandro Dalcin   PetscBool      wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
699fdbf62faSLisandro Dalcin   PetscMPIInt    rank;
700fdbf62faSLisandro Dalcin 
701fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7029318fe57SMatthew G. Knepley   PetscValidPointer(dm,1);
703fdbf62faSLisandro Dalcin 
704*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm,1));
705*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm,"marker"));
706*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm,"Face Sets"));
707fdbf62faSLisandro Dalcin 
708*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm),&rank));
709dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
710dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
711fdbf62faSLisandro Dalcin 
712fdbf62faSLisandro Dalcin   numPoints[0] = numVerts ; numPoints[1] = numCells;
713*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc4(numCells+numVerts,&coneSize,numCells*2,&cones,numCells+numVerts,&coneOrientations,numVerts,&vertexCoords));
714*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(coneOrientations,numCells+numVerts));
715fdbf62faSLisandro Dalcin   for (i = 0; i < numCells; ++i) { coneSize[i] = 2; }
716fdbf62faSLisandro Dalcin   for (i = 0; i < numVerts; ++i) { coneSize[numCells+i] = 0; }
717fdbf62faSLisandro Dalcin   for (i = 0; i < numCells; ++i) { cones[2*i] = numCells + i%numVerts; cones[2*i+1] = numCells + (i+1)%numVerts; }
718fdbf62faSLisandro Dalcin   for (i = 0; i < numVerts; ++i) { vertexCoords[i] = lower + (upper-lower)*((PetscReal)i/(PetscReal)numCells); }
719*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateFromDAG(dm,1,numPoints,coneSize,cones,coneOrientations,vertexCoords));
720*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree4(coneSize,cones,coneOrientations,vertexCoords));
721fdbf62faSLisandro Dalcin 
722*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject)dm)->options,((PetscObject)dm)->prefix,"-dm_plex_separate_marker",&markerSeparate,NULL));
723fdbf62faSLisandro Dalcin   if (markerSeparate) { markerLeft = faceMarkerLeft; markerRight = faceMarkerRight;}
724dd400576SPatrick Sanan   if (!wrap && rank == 0) {
725*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm,1,&fStart,&fEnd));
726*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelValue(dm,"marker",fStart,markerLeft));
727*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelValue(dm,"marker",fEnd-1,markerRight));
728*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelValue(dm,"Face Sets",fStart,faceMarkerLeft));
729*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelValue(dm,"Face Sets",fEnd-1,faceMarkerRight));
730fdbf62faSLisandro Dalcin   }
731fdbf62faSLisandro Dalcin   if (wrap) {
732fdbf62faSLisandro Dalcin     L       = upper - lower;
733fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1*(L/(PetscReal)PetscMax(1,segments));
734*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetPeriodicity(dm,PETSC_TRUE,&maxCell,&L,&bd));
735fdbf62faSLisandro Dalcin   }
736*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
737fdbf62faSLisandro Dalcin   PetscFunctionReturn(0);
738fdbf62faSLisandro Dalcin }
739fdbf62faSLisandro Dalcin 
7409318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
741d6218766SMatthew G. Knepley {
7429318fe57SMatthew G. Knepley   DM             boundary, vol;
743768d5fceSMatthew G. Knepley   PetscInt       i;
744d6218766SMatthew G. Knepley 
745d6218766SMatthew G. Knepley   PetscFunctionBegin;
7469318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
7472c71b3e2SJacob Faibussowitsch   for (i = 0; i < dim; ++i) PetscCheckFalse(periodicity[i] != DM_BOUNDARY_NONE,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Periodicity is not supported for simplex meshes");
748*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &boundary));
749*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(boundary, DMPLEX));
750*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
751*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGenerate(boundary, NULL, interpolate, &vol));
752*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, vol));
753*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexReplace_Static(dm, &vol));
754*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&boundary));
755d6218766SMatthew G. Knepley   PetscFunctionReturn(0);
756d6218766SMatthew G. Knepley }
757d6218766SMatthew G. Knepley 
7583dfda0b1SToby Isaac static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
7593dfda0b1SToby Isaac {
760ed0e4b50SMatthew G. Knepley   DMLabel        cutLabel = NULL;
761f4eb4c5dSMatthew G. Knepley   PetscInt       markerTop      = 1, faceMarkerTop      = 1;
762f4eb4c5dSMatthew G. Knepley   PetscInt       markerBottom   = 1, faceMarkerBottom   = 1;
763f4eb4c5dSMatthew G. Knepley   PetscInt       markerFront    = 1, faceMarkerFront    = 1;
764f4eb4c5dSMatthew G. Knepley   PetscInt       markerBack     = 1, faceMarkerBack     = 1;
765f4eb4c5dSMatthew G. Knepley   PetscInt       markerRight    = 1, faceMarkerRight    = 1;
766f4eb4c5dSMatthew G. Knepley   PetscInt       markerLeft     = 1, faceMarkerLeft     = 1;
7673dfda0b1SToby Isaac   PetscInt       dim;
768d8211ee3SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
7693dfda0b1SToby Isaac   PetscMPIInt    rank;
7703dfda0b1SToby Isaac 
7713dfda0b1SToby Isaac   PetscFunctionBegin;
772*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm,&dim));
773*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
774*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm,"marker"));
775*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm,"Face Sets"));
776*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
777d8211ee3SMatthew G. Knepley   if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ||
778d8211ee3SMatthew G. Knepley       bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ||
779d8211ee3SMatthew G. Knepley       bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) {
7804c67ea77SStefano Zampini 
781*5f80ce2aSJacob Faibussowitsch     if (cutMarker) {CHKERRQ(DMCreateLabel(dm, "periodic_cut")); CHKERRQ(DMGetLabel(dm, "periodic_cut", &cutLabel));}
782d8211ee3SMatthew G. Knepley   }
7833dfda0b1SToby Isaac   switch (dim) {
7843dfda0b1SToby Isaac   case 2:
785f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
786f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
787f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
788f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
7893dfda0b1SToby Isaac     break;
7903dfda0b1SToby Isaac   case 3:
791f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
792f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
793f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
794f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
795f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
796f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
7973dfda0b1SToby Isaac     break;
7983dfda0b1SToby Isaac   default:
79998921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Dimension %D not supported",dim);
8003dfda0b1SToby Isaac   }
801*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
802f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
803f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
804f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
805f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
806f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
807f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
808f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
8093dfda0b1SToby Isaac   }
8103dfda0b1SToby Isaac   {
811dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
812dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
813dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
814dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0]+1) : 0;
815dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1]+1) : 0;
816dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2]+1) : 0;
8173dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges*numYEdges*numZEdges;
8183dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges*numZEdges;
8193dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges*numZEdges;
8203dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges*numYEdges;
8213dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices*numXFaces;
8223dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices*numYFaces;
8233dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices*numZFaces;
8243dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
8253dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges*numYVertices*numZVertices;
8263dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges*numXVertices*numZVertices;
8273dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges*numXVertices*numYVertices;
8283dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices*numYVertices*numZVertices;
8293dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
8303dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
8313dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
8323dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
8333dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
8343dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
8353dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
8363dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
8373dfda0b1SToby Isaac     Vec            coordinates;
8383dfda0b1SToby Isaac     PetscSection   coordSection;
8393dfda0b1SToby Isaac     PetscScalar   *coords;
8403dfda0b1SToby Isaac     PetscInt       coordSize;
8413dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
8423dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
8433dfda0b1SToby Isaac 
844*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetChart(dm, 0, numCells+numFaces+numEdges+numVertices));
8453dfda0b1SToby Isaac     for (c = 0; c < numCells; c++) {
846*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(dm, c, 6));
8473dfda0b1SToby Isaac     }
8483dfda0b1SToby Isaac     for (f = firstXFace; f < firstXFace+numFaces; ++f) {
849*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(dm, f, 4));
8503dfda0b1SToby Isaac     }
8513dfda0b1SToby Isaac     for (e = firstXEdge; e < firstXEdge+numEdges; ++e) {
852*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetConeSize(dm, e, 2));
8533dfda0b1SToby Isaac     }
854*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
8553dfda0b1SToby Isaac     /* Build cells */
8563dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
8573dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
8583dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
8593dfda0b1SToby Isaac           PetscInt cell    = (fz*numYEdges + fy)*numXEdges + fx;
8603dfda0b1SToby Isaac           PetscInt faceB   = firstZFace + (fy*numXEdges+fx)*numZVertices +   fz;
8613dfda0b1SToby Isaac           PetscInt faceT   = firstZFace + (fy*numXEdges+fx)*numZVertices + ((fz+1)%numZVertices);
8623dfda0b1SToby Isaac           PetscInt faceF   = firstYFace + (fz*numXEdges+fx)*numYVertices +   fy;
8633dfda0b1SToby Isaac           PetscInt faceK   = firstYFace + (fz*numXEdges+fx)*numYVertices + ((fy+1)%numYVertices);
8643dfda0b1SToby Isaac           PetscInt faceL   = firstXFace + (fz*numYEdges+fy)*numXVertices +   fx;
8653dfda0b1SToby Isaac           PetscInt faceR   = firstXFace + (fz*numYEdges+fy)*numXVertices + ((fx+1)%numXVertices);
8663dfda0b1SToby Isaac                             /* B,  T,  F,  K,  R,  L */
867b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2,  0,  0, -3,  0, -2}; /* ??? */
86842206facSLisandro Dalcin           PetscInt cone[6];
8693dfda0b1SToby Isaac 
8703dfda0b1SToby Isaac           /* no boundary twisting in 3D */
8713dfda0b1SToby Isaac           cone[0] = faceB; cone[1] = faceT; cone[2] = faceF; cone[3] = faceK; cone[4] = faceR; cone[5] = faceL;
872*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, cell, cone));
873*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetConeOrientation(dm, cell, ornt));
874*5f80ce2aSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2));
875*5f80ce2aSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2));
876*5f80ce2aSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, cell, 2));
8773dfda0b1SToby Isaac         }
8783dfda0b1SToby Isaac       }
8793dfda0b1SToby Isaac     }
8803dfda0b1SToby Isaac     /* Build x faces */
8813dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
8823dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
8833dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
8843dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz*numYEdges+fy)     *numXVertices+fx;
8853dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy                   *numXVertices+fx)*numZEdges + fz;
8863dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy+1)%numYVertices)*numXVertices+fx)*numZEdges + fz;
8873dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz                   *numXVertices+fx)*numYEdges + fy;
8883dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz+1)%numZVertices)*numXVertices+fx)*numYEdges + fy;
889b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
8903dfda0b1SToby Isaac           PetscInt cone[4];
8913dfda0b1SToby Isaac 
8923dfda0b1SToby Isaac           if (dim == 3) {
8933dfda0b1SToby Isaac             /* markers */
8943dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
8953dfda0b1SToby Isaac               if (fx == numXVertices-1) {
896*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
897*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", face, markerRight));
8983dfda0b1SToby Isaac               }
8993dfda0b1SToby Isaac               else if (fx == 0) {
900*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
901*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", face, markerLeft));
9023dfda0b1SToby Isaac               }
9033dfda0b1SToby Isaac             }
9043dfda0b1SToby Isaac           }
9053dfda0b1SToby Isaac           cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL;
906*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, face, cone));
907*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetConeOrientation(dm, face, ornt));
9083dfda0b1SToby Isaac         }
9093dfda0b1SToby Isaac       }
9103dfda0b1SToby Isaac     }
9113dfda0b1SToby Isaac     /* Build y faces */
9123dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
91342206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
9143dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
9153dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz*numXEdges+fx)*numYVertices + fy;
9163dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy*numXVertices+  fx)*numZEdges + fz;
9173dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy*numXVertices+((fx+1)%numXVertices))*numZEdges + fz;
9183dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz                   *numYVertices+fy)*numXEdges + fx;
9193dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz+1)%numZVertices)*numYVertices+fy)*numXEdges + fx;
920b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9213dfda0b1SToby Isaac           PetscInt cone[4];
9223dfda0b1SToby Isaac 
9233dfda0b1SToby Isaac           if (dim == 3) {
9243dfda0b1SToby Isaac             /* markers */
9253dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
9263dfda0b1SToby Isaac               if (fy == numYVertices-1) {
927*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
928*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", face, markerBack));
9293dfda0b1SToby Isaac               }
9303dfda0b1SToby Isaac               else if (fy == 0) {
931*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
932*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", face, markerFront));
9333dfda0b1SToby Isaac               }
9343dfda0b1SToby Isaac             }
9353dfda0b1SToby Isaac           }
9363dfda0b1SToby Isaac           cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL;
937*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, face, cone));
938*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetConeOrientation(dm, face, ornt));
9393dfda0b1SToby Isaac         }
9403dfda0b1SToby Isaac       }
9413dfda0b1SToby Isaac     }
9423dfda0b1SToby Isaac     /* Build z faces */
9433dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
9443dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
9453dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
9463dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy*numXEdges+fx)*numZVertices + fz;
9473dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz*numXVertices+  fx)*numYEdges + fy;
9483dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz*numXVertices+((fx+1)%numXVertices))*numYEdges + fy;
9493dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz*numYVertices+  fy)*numXEdges + fx;
9503dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz*numYVertices+((fy+1)%numYVertices))*numXEdges + fx;
951b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9523dfda0b1SToby Isaac           PetscInt cone[4];
9533dfda0b1SToby Isaac 
9543dfda0b1SToby Isaac           if (dim == 2) {
955b5a892a1SMatthew G. Knepley             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges-1) {edgeR += numYEdges-1-2*fy; ornt[1] = -1;}
9563dfda0b1SToby Isaac             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges-1) {edgeT += numXEdges-1-2*fx; ornt[2] =  0;}
957*5f80ce2aSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, face, 2));
958*5f80ce2aSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) CHKERRQ(DMLabelSetValue(cutLabel, face, 2));
959d1c88043SMatthew G. Knepley           } else {
9603dfda0b1SToby Isaac             /* markers */
9613dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
9623dfda0b1SToby Isaac               if (fz == numZVertices-1) {
963*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
964*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", face, markerTop));
9653dfda0b1SToby Isaac               }
9663dfda0b1SToby Isaac               else if (fz == 0) {
967*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
968*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", face, markerBottom));
9693dfda0b1SToby Isaac               }
9703dfda0b1SToby Isaac             }
9713dfda0b1SToby Isaac           }
9723dfda0b1SToby Isaac           cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL;
973*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, face, cone));
974*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetConeOrientation(dm, face, ornt));
9753dfda0b1SToby Isaac         }
9763dfda0b1SToby Isaac       }
9773dfda0b1SToby Isaac     }
9783dfda0b1SToby Isaac     /* Build Z edges*/
9793dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
9803dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
9813dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
9823dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge  + (vy*numXVertices+vx)*numZEdges + ez;
9833dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez                   *numYVertices+vy)*numXVertices + vx;
9843dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez+1)%numZVertices)*numYVertices+vy)*numXVertices + vx;
9853dfda0b1SToby Isaac           PetscInt       cone[2];
9863dfda0b1SToby Isaac 
9873dfda0b1SToby Isaac           if (dim == 3) {
9883dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
9893dfda0b1SToby Isaac               if (vx == numXVertices-1) {
990*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight));
9913dfda0b1SToby Isaac               }
9923dfda0b1SToby Isaac               else if (vx == 0) {
993*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft));
9943dfda0b1SToby Isaac               }
9953dfda0b1SToby Isaac             }
9963dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
9973dfda0b1SToby Isaac               if (vy == numYVertices-1) {
998*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBack));
9993dfda0b1SToby Isaac               }
10003dfda0b1SToby Isaac               else if (vy == 0) {
1001*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerFront));
10023dfda0b1SToby Isaac               }
10033dfda0b1SToby Isaac             }
10043dfda0b1SToby Isaac           }
10053dfda0b1SToby Isaac           cone[0] = vertexB; cone[1] = vertexT;
1006*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, edge, cone));
10073dfda0b1SToby Isaac         }
10083dfda0b1SToby Isaac       }
10093dfda0b1SToby Isaac     }
10103dfda0b1SToby Isaac     /* Build Y edges*/
10113dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
10123dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10133dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
10143dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges-1) ? (numXVertices-vx-1) : (vz*numYVertices+((ey+1)%numYVertices))*numXVertices + vx;
10153dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge  + (vz*numXVertices+vx)*numYEdges + ey;
10163dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz*numYVertices+ey)*numXVertices + vx;
10173dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
10183dfda0b1SToby Isaac           PetscInt       cone[2];
10193dfda0b1SToby Isaac 
10203dfda0b1SToby Isaac           cone[0] = vertexF; cone[1] = vertexK;
1021*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, edge, cone));
10223dfda0b1SToby Isaac           if (dim == 2) {
10233dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
10243dfda0b1SToby Isaac               if (vx == numXVertices-1) {
1025*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
1026*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerRight));
1027*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerRight));
10283dfda0b1SToby Isaac                 if (ey == numYEdges-1) {
1029*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerRight));
10303dfda0b1SToby Isaac                 }
1031d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
1032*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
1033*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerLeft));
1034*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
10353dfda0b1SToby Isaac                 if (ey == numYEdges-1) {
1036*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10373dfda0b1SToby Isaac                 }
10383dfda0b1SToby Isaac               }
1039d8211ee3SMatthew G. Knepley             } else {
10404c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
1041*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMLabelSetValue(cutLabel, edge,    1));
1042*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMLabelSetValue(cutLabel, cone[0], 1));
1043d8211ee3SMatthew G. Knepley                 if (ey == numYEdges-1) {
1044*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMLabelSetValue(cutLabel, cone[1], 1));
10453dfda0b1SToby Isaac                 }
10463dfda0b1SToby Isaac               }
1047d8211ee3SMatthew G. Knepley             }
1048d8211ee3SMatthew G. Knepley           } else {
10493dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
10503dfda0b1SToby Isaac               if (vx == numXVertices-1) {
1051*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerRight));
1052d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
1053*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerLeft));
10543dfda0b1SToby Isaac               }
10553dfda0b1SToby Isaac             }
10563dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
10573dfda0b1SToby Isaac               if (vz == numZVertices-1) {
1058*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop));
1059d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
1060*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom));
10613dfda0b1SToby Isaac               }
10623dfda0b1SToby Isaac             }
10633dfda0b1SToby Isaac           }
10643dfda0b1SToby Isaac         }
10653dfda0b1SToby Isaac       }
10663dfda0b1SToby Isaac     }
10673dfda0b1SToby Isaac     /* Build X edges*/
10683dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
10693dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
10703dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
10713dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges-1) ? (numYVertices-vy-1)*numXVertices : (vz*numYVertices+vy)*numXVertices + (ex+1)%numXVertices;
10723dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge  + (vz*numYVertices+vy)*numXEdges + ex;
10733dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz*numYVertices+vy)*numXVertices + ex;
10743dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
10753dfda0b1SToby Isaac           PetscInt       cone[2];
10763dfda0b1SToby Isaac 
10773dfda0b1SToby Isaac           cone[0] = vertexL; cone[1] = vertexR;
1078*5f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexSetCone(dm, edge, cone));
10793dfda0b1SToby Isaac           if (dim == 2) {
10803dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
10813dfda0b1SToby Isaac               if (vy == numYVertices-1) {
1082*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
1083*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerTop));
1084*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerTop));
10853dfda0b1SToby Isaac                 if (ex == numXEdges-1) {
1086*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerTop));
10873dfda0b1SToby Isaac                 }
1088d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
1089*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
1090*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge,    markerBottom));
1091*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
10923dfda0b1SToby Isaac                 if (ex == numXEdges-1) {
1093*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
10943dfda0b1SToby Isaac                 }
10953dfda0b1SToby Isaac               }
1096d8211ee3SMatthew G. Knepley             } else {
10974c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
1098*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMLabelSetValue(cutLabel, edge,    1));
1099*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMLabelSetValue(cutLabel, cone[0], 1));
1100d8211ee3SMatthew G. Knepley                 if (ex == numXEdges-1) {
1101*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMLabelSetValue(cutLabel, cone[1], 1));
11023dfda0b1SToby Isaac                 }
11033dfda0b1SToby Isaac               }
1104d8211ee3SMatthew G. Knepley             }
1105d8211ee3SMatthew G. Knepley           } else {
11063dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11073dfda0b1SToby Isaac               if (vy == numYVertices-1) {
1108*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBack));
11093dfda0b1SToby Isaac               }
11103dfda0b1SToby Isaac               else if (vy == 0) {
1111*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerFront));
11123dfda0b1SToby Isaac               }
11133dfda0b1SToby Isaac             }
11143dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11153dfda0b1SToby Isaac               if (vz == numZVertices-1) {
1116*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerTop));
11173dfda0b1SToby Isaac               }
11183dfda0b1SToby Isaac               else if (vz == 0) {
1119*5f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMSetLabelValue(dm, "marker", edge, markerBottom));
11203dfda0b1SToby Isaac               }
11213dfda0b1SToby Isaac             }
11223dfda0b1SToby Isaac           }
11233dfda0b1SToby Isaac         }
11243dfda0b1SToby Isaac       }
11253dfda0b1SToby Isaac     }
1126*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSymmetrize(dm));
1127*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexStratify(dm));
11283dfda0b1SToby Isaac     /* Build coordinates */
1129*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
1130*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
1131*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim));
1132*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices));
11333dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex+numVertices; ++v) {
1134*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetDof(coordSection, v, dim));
1135*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim));
11363dfda0b1SToby Isaac     }
1137*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(coordSection));
1138*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
1139*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
1140*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
1141*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1142*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetBlockSize(coordinates, dim));
1143*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(coordinates,VECSTANDARD));
1144*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(coordinates, &coords));
11453dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
11463dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
11473dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
11483dfda0b1SToby Isaac           coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+0] = lower[0] + ((upper[0] - lower[0])/numXEdges)*vx;
11493dfda0b1SToby Isaac           coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+1] = lower[1] + ((upper[1] - lower[1])/numYEdges)*vy;
11503dfda0b1SToby Isaac           if (dim == 3) {
11513dfda0b1SToby Isaac             coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+2] = lower[2] + ((upper[2] - lower[2])/numZEdges)*vz;
11523dfda0b1SToby Isaac           }
11533dfda0b1SToby Isaac         }
11543dfda0b1SToby Isaac       }
11553dfda0b1SToby Isaac     }
1156*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(coordinates, &coords));
1157*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
1158*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&coordinates));
11593dfda0b1SToby Isaac   }
11603dfda0b1SToby Isaac   PetscFunctionReturn(0);
11613dfda0b1SToby Isaac }
11623dfda0b1SToby Isaac 
11639318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1164a6dfd86eSKarl Rupp {
11659318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
11669318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1167552f7358SJed Brown 
1168552f7358SJed Brown   PetscFunctionBegin;
11699318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
11709318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
1171*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim));
11729318fe57SMatthew G. Knepley   for (d = 0; d < dim; ++d) {fac[d] = faces[d]; bdt[d] = periodicity[d];}
1173*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
1174768d5fceSMatthew G. Knepley   if (periodicity[0] == DM_BOUNDARY_PERIODIC || periodicity[0] == DM_BOUNDARY_TWIST ||
1175768d5fceSMatthew G. Knepley       periodicity[1] == DM_BOUNDARY_PERIODIC || periodicity[1] == DM_BOUNDARY_TWIST ||
1176768d5fceSMatthew G. Knepley       (dim > 2 && (periodicity[2] == DM_BOUNDARY_PERIODIC || periodicity[2] == DM_BOUNDARY_TWIST))) {
1177768d5fceSMatthew G. Knepley     PetscReal L[3];
1178768d5fceSMatthew G. Knepley     PetscReal maxCell[3];
1179552f7358SJed Brown 
11809318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
11819318fe57SMatthew G. Knepley       L[d]       = upper[d] - lower[d];
11829318fe57SMatthew G. Knepley       maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1183768d5fceSMatthew G. Knepley     }
1184*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, maxCell, L, periodicity));
1185768d5fceSMatthew G. Knepley   }
1186*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
11879318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
11889318fe57SMatthew G. Knepley }
11899318fe57SMatthew G. Knepley 
11909318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
11919318fe57SMatthew G. Knepley {
11929318fe57SMatthew G. Knepley   PetscFunctionBegin;
1193*5f80ce2aSJacob Faibussowitsch   if (dim == 1)      CHKERRQ(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
1194*5f80ce2aSJacob Faibussowitsch   else if (simplex)  CHKERRQ(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
1195*5f80ce2aSJacob Faibussowitsch   else               CHKERRQ(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
11969318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1197768d5fceSMatthew G. Knepley     DM udm;
1198768d5fceSMatthew G. Knepley 
1199*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexUninterpolate(dm, &udm));
1200*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCopyCoordinates(dm, udm));
1201*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &udm));
1202768d5fceSMatthew G. Knepley   }
1203768d5fceSMatthew G. Knepley   PetscFunctionReturn(0);
1204c8c68bd8SToby Isaac }
1205c8c68bd8SToby Isaac 
1206768d5fceSMatthew G. Knepley /*@C
1207768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1208768d5fceSMatthew G. Knepley 
1209d083f849SBarry Smith   Collective
1210768d5fceSMatthew G. Knepley 
1211768d5fceSMatthew G. Knepley   Input Parameters:
1212768d5fceSMatthew G. Knepley + comm        - The communicator for the DM object
1213768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1214768d5fceSMatthew G. Knepley . simplex     - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells
1215fdbf62faSLisandro Dalcin . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
1216768d5fceSMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
1217768d5fceSMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
1218fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1219768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
1220768d5fceSMatthew G. Knepley 
1221768d5fceSMatthew G. Knepley   Output Parameter:
1222768d5fceSMatthew G. Knepley . dm  - The DM object
1223768d5fceSMatthew G. Knepley 
12249318fe57SMatthew G. Knepley   Note: If you want to customize this mesh using options, you just need to
12259318fe57SMatthew G. Knepley $  DMCreate(comm, &dm);
12269318fe57SMatthew G. Knepley $  DMSetType(dm, DMPLEX);
12279318fe57SMatthew G. Knepley $  DMSetFromOptions(dm);
12289318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page.
12291367e252SJed Brown 
12301367e252SJed Brown   Here is the numbering returned for 2 faces in each direction for tensor cells:
1231768d5fceSMatthew G. Knepley $ 10---17---11---18----12
1232768d5fceSMatthew G. Knepley $  |         |         |
1233768d5fceSMatthew G. Knepley $  |         |         |
1234768d5fceSMatthew G. Knepley $ 20    2   22    3    24
1235768d5fceSMatthew G. Knepley $  |         |         |
1236768d5fceSMatthew G. Knepley $  |         |         |
1237768d5fceSMatthew G. Knepley $  7---15----8---16----9
1238768d5fceSMatthew G. Knepley $  |         |         |
1239768d5fceSMatthew G. Knepley $  |         |         |
1240768d5fceSMatthew G. Knepley $ 19    0   21    1   23
1241768d5fceSMatthew G. Knepley $  |         |         |
1242768d5fceSMatthew G. Knepley $  |         |         |
1243768d5fceSMatthew G. Knepley $  4---13----5---14----6
1244768d5fceSMatthew G. Knepley 
1245768d5fceSMatthew G. Knepley and for simplicial cells
1246768d5fceSMatthew G. Knepley 
1247768d5fceSMatthew G. Knepley $ 14----8---15----9----16
1248768d5fceSMatthew G. Knepley $  |\     5  |\      7 |
1249768d5fceSMatthew G. Knepley $  | \       | \       |
1250768d5fceSMatthew G. Knepley $ 13   2    14    3    15
1251768d5fceSMatthew G. Knepley $  | 4   \   | 6   \   |
1252768d5fceSMatthew G. Knepley $  |       \ |       \ |
1253768d5fceSMatthew G. Knepley $ 11----6---12----7----13
1254768d5fceSMatthew G. Knepley $  |\        |\        |
1255768d5fceSMatthew G. Knepley $  | \    1  | \     3 |
1256768d5fceSMatthew G. Knepley $ 10   0    11    1    12
1257768d5fceSMatthew G. Knepley $  | 0   \   | 2   \   |
1258768d5fceSMatthew G. Knepley $  |       \ |       \ |
1259768d5fceSMatthew G. Knepley $  8----4----9----5----10
1260768d5fceSMatthew G. Knepley 
1261768d5fceSMatthew G. Knepley   Level: beginner
1262768d5fceSMatthew G. Knepley 
12639318fe57SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreateFromFile(), DMPlexCreateHexCylinderMesh(), DMSetType(), DMCreate()
1264768d5fceSMatthew G. Knepley @*/
1265768d5fceSMatthew G. Knepley 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)
1266552f7358SJed Brown {
12679318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1268fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1269fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1270fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1271552f7358SJed Brown 
1272768d5fceSMatthew G. Knepley   PetscFunctionBegin;
1273*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm,dm));
1274*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm,DMPLEX));
1275*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
12769318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
12779318fe57SMatthew G. Knepley }
1278fdbf62faSLisandro Dalcin 
1279d410b0cfSMatthew G. Knepley static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
12809318fe57SMatthew G. Knepley {
12819318fe57SMatthew G. Knepley   DM             bdm, vol;
12829318fe57SMatthew G. Knepley   PetscInt       i;
12839318fe57SMatthew G. Knepley 
12849318fe57SMatthew G. Knepley   PetscFunctionBegin;
12852c71b3e2SJacob Faibussowitsch   for (i = 0; i < 3; ++i) PetscCheckFalse(periodicity[i] != DM_BOUNDARY_NONE,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Periodicity not yet supported");
1286*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &bdm));
1287*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(bdm, DMPLEX));
1288*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(bdm, 2));
1289*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
1290*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
1291*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&bdm));
1292*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexReplace_Static(dm, &vol));
12939318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
12949318fe57SMatthew G. Knepley     Vec          v;
12959318fe57SMatthew G. Knepley     PetscScalar *x;
12969318fe57SMatthew G. Knepley     PetscInt     cDim, n;
12979318fe57SMatthew G. Knepley 
1298*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinatesLocal(dm, &v));
1299*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetBlockSize(v, &cDim));
1300*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(v, &n));
1301*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(v, &x));
13029318fe57SMatthew G. Knepley     x   += cDim;
13039318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
1304*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(v,&x));
1305*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinatesLocal(dm, v));
13069318fe57SMatthew G. Knepley   }
1307552f7358SJed Brown   PetscFunctionReturn(0);
1308552f7358SJed Brown }
1309552f7358SJed Brown 
131000dabe28SStefano Zampini /*@
131100dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
131200dabe28SStefano Zampini 
1313d083f849SBarry Smith   Collective
131400dabe28SStefano Zampini 
131500dabe28SStefano Zampini   Input Parameters:
131600dabe28SStefano Zampini + comm        - The communicator for the DM object
131700dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
131800dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
131900dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
132000dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1321d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
132200dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
132300dabe28SStefano Zampini 
132400dabe28SStefano Zampini   Output Parameter:
132500dabe28SStefano Zampini . dm  - The DM object
132600dabe28SStefano Zampini 
132700dabe28SStefano Zampini   Level: beginner
132800dabe28SStefano Zampini 
1329d410b0cfSMatthew G. Knepley .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateWedgeCylinderMesh(), DMExtrude(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate()
133000dabe28SStefano Zampini @*/
1331d0fcb9c2SMatthew G. Knepley PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
133200dabe28SStefano Zampini {
13339318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
133400dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
133500dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
133600dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
133700dabe28SStefano Zampini 
133800dabe28SStefano Zampini   PetscFunctionBegin;
1339*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm,dm));
1340*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm,DMPLEX));
1341*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1342d410b0cfSMatthew G. Knepley   if (!interpolate) {
1343d410b0cfSMatthew G. Knepley     DM udm;
134400dabe28SStefano Zampini 
1345*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexUninterpolate(*dm, &udm));
1346*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(*dm, &udm));
134700dabe28SStefano Zampini   }
134800dabe28SStefano Zampini   PetscFunctionReturn(0);
134900dabe28SStefano Zampini }
135000dabe28SStefano Zampini 
1351a9074c1eSMatthew G. Knepley /*@C
1352a9074c1eSMatthew G. Knepley   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database.
1353a9074c1eSMatthew G. Knepley 
1354d083f849SBarry Smith   Logically Collective on dm
1355a9074c1eSMatthew G. Knepley 
1356a9074c1eSMatthew G. Knepley   Input Parameters:
1357a9074c1eSMatthew G. Knepley + dm - the DM context
1358a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1359a9074c1eSMatthew G. Knepley 
1360a9074c1eSMatthew G. Knepley   Notes:
1361a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1362a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1363a9074c1eSMatthew G. Knepley 
1364a9074c1eSMatthew G. Knepley   Level: advanced
1365a9074c1eSMatthew G. Knepley 
1366a9074c1eSMatthew G. Knepley .seealso: SNESSetFromOptions()
1367a9074c1eSMatthew G. Knepley @*/
1368a9074c1eSMatthew G. Knepley PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1369a9074c1eSMatthew G. Knepley {
1370a9074c1eSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *) dm->data;
1371a9074c1eSMatthew G. Knepley 
1372a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1373a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1374*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) dm, prefix));
1375*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) mesh->partitioner, prefix));
1376a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1377a9074c1eSMatthew G. Knepley }
1378a9074c1eSMatthew G. Knepley 
13799318fe57SMatthew G. Knepley /* Remap geometry to cylinder
138061a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
138161a622f3SMatthew G. Knepley 
13829318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
13839318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
13849318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
13850510c589SMatthew G. Knepley 
13869318fe57SMatthew G. Knepley        phi     = arctan(y/x)
13879318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
13889318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
13890510c589SMatthew G. Knepley 
13909318fe57SMatthew G. Knepley      so we remap them using
13910510c589SMatthew G. Knepley 
13929318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
13939318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
13940510c589SMatthew G. Knepley 
13959318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
13969318fe57SMatthew G. Knepley */
13979318fe57SMatthew G. Knepley static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux,
13989318fe57SMatthew G. Knepley                            const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
13999318fe57SMatthew G. Knepley                            const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
14009318fe57SMatthew G. Knepley                            PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
14019318fe57SMatthew G. Knepley {
14029318fe57SMatthew G. Knepley   const PetscReal dis = 1.0/PetscSqrtReal(2.0);
14039318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5*dis;
140422cc497dSMatthew G. Knepley 
14059318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
14069318fe57SMatthew G. Knepley     f0[0] = u[0];
14079318fe57SMatthew G. Knepley     f0[1] = u[1];
14089318fe57SMatthew G. Knepley   } else {
14099318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
14100510c589SMatthew G. Knepley 
14119318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
14129318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
14139318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
14149318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
14159318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
14169318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI/4.0) && (PetscAbsReal(phi) < 3.0*PETSC_PI/4.0)) {
14179318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2/sinp);
14189318fe57SMatthew G. Knepley       df = PetscAbsReal(dis/sinp);
14199318fe57SMatthew G. Knepley       xc = ds2*x/PetscAbsReal(y);
14209318fe57SMatthew G. Knepley       yc = ds2*PetscSignReal(y);
14219318fe57SMatthew G. Knepley     } else {
14229318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2/cosp);
14239318fe57SMatthew G. Knepley       df = PetscAbsReal(dis/cosp);
14249318fe57SMatthew G. Knepley       xc = ds2*PetscSignReal(x);
14259318fe57SMatthew G. Knepley       yc = ds2*y/PetscAbsReal(x);
14269318fe57SMatthew G. Knepley     }
14279318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc)*(1.0 - dc)/(df - dc);
14289318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc)*(1.0 - dc)/(df - dc);
14299318fe57SMatthew G. Knepley   }
14309318fe57SMatthew G. Knepley   f0[2] = u[2];
14319318fe57SMatthew G. Knepley }
14320510c589SMatthew G. Knepley 
14339318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ)
14340510c589SMatthew G. Knepley {
14350510c589SMatthew G. Knepley   const PetscInt dim = 3;
14369318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1437d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
14380510c589SMatthew G. Knepley 
14390510c589SMatthew G. Knepley   PetscFunctionBegin;
1440*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
1441*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim));
14420510c589SMatthew G. Knepley   /* Create topology */
14430510c589SMatthew G. Knepley   {
14440510c589SMatthew G. Knepley     PetscInt cone[8], c;
14450510c589SMatthew G. Knepley 
1446dd400576SPatrick Sanan     numCells    = rank == 0 ?  5 : 0;
1447dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1448006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1449ae8bcbbbSMatthew G. Knepley       numCells   *= 3;
1450dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1451006a8963SMatthew G. Knepley     }
1452*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices));
1453*5f80ce2aSJacob Faibussowitsch     for (c = 0; c < numCells; c++) CHKERRQ(DMPlexSetConeSize(dm, c, 8));
1454*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(dm));
1455dd400576SPatrick Sanan     if (rank == 0) {
1456006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
1457ae8bcbbbSMatthew G. Knepley         cone[0] = 15; cone[1] = 18; cone[2] = 17; cone[3] = 16;
1458ae8bcbbbSMatthew G. Knepley         cone[4] = 31; cone[5] = 32; cone[6] = 33; cone[7] = 34;
1459*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 0, cone));
1460ae8bcbbbSMatthew G. Knepley         cone[0] = 16; cone[1] = 17; cone[2] = 24; cone[3] = 23;
1461ae8bcbbbSMatthew G. Knepley         cone[4] = 32; cone[5] = 36; cone[6] = 37; cone[7] = 33; /* 22 25 26 21 */
1462*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 1, cone));
1463ae8bcbbbSMatthew G. Knepley         cone[0] = 18; cone[1] = 27; cone[2] = 24; cone[3] = 17;
1464ae8bcbbbSMatthew G. Knepley         cone[4] = 34; cone[5] = 33; cone[6] = 37; cone[7] = 38;
1465*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 2, cone));
1466ae8bcbbbSMatthew G. Knepley         cone[0] = 29; cone[1] = 27; cone[2] = 18; cone[3] = 15;
1467ae8bcbbbSMatthew G. Knepley         cone[4] = 35; cone[5] = 31; cone[6] = 34; cone[7] = 38;
1468*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 3, cone));
1469ae8bcbbbSMatthew G. Knepley         cone[0] = 29; cone[1] = 15; cone[2] = 16; cone[3] = 23;
1470ae8bcbbbSMatthew G. Knepley         cone[4] = 35; cone[5] = 36; cone[6] = 32; cone[7] = 31;
1471*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 4, cone));
1472006a8963SMatthew G. Knepley 
1473ae8bcbbbSMatthew G. Knepley         cone[0] = 31; cone[1] = 34; cone[2] = 33; cone[3] = 32;
1474ae8bcbbbSMatthew G. Knepley         cone[4] = 19; cone[5] = 22; cone[6] = 21; cone[7] = 20;
1475*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 5, cone));
1476ae8bcbbbSMatthew G. Knepley         cone[0] = 32; cone[1] = 33; cone[2] = 37; cone[3] = 36;
1477ae8bcbbbSMatthew G. Knepley         cone[4] = 22; cone[5] = 25; cone[6] = 26; cone[7] = 21;
1478*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 6, cone));
1479ae8bcbbbSMatthew G. Knepley         cone[0] = 34; cone[1] = 38; cone[2] = 37; cone[3] = 33;
1480ae8bcbbbSMatthew G. Knepley         cone[4] = 20; cone[5] = 21; cone[6] = 26; cone[7] = 28;
1481*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 7, cone));
1482ae8bcbbbSMatthew G. Knepley         cone[0] = 35; cone[1] = 38; cone[2] = 34; cone[3] = 31;
1483ae8bcbbbSMatthew G. Knepley         cone[4] = 30; cone[5] = 19; cone[6] = 20; cone[7] = 28;
1484*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 8, cone));
1485ae8bcbbbSMatthew G. Knepley         cone[0] = 35; cone[1] = 31; cone[2] = 32; cone[3] = 36;
1486ae8bcbbbSMatthew G. Knepley         cone[4] = 30; cone[5] = 25; cone[6] = 22; cone[7] = 19;
1487*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 9, cone));
1488ae8bcbbbSMatthew G. Knepley 
1489ae8bcbbbSMatthew G. Knepley         cone[0] = 19; cone[1] = 20; cone[2] = 21; cone[3] = 22;
1490ae8bcbbbSMatthew G. Knepley         cone[4] = 15; cone[5] = 16; cone[6] = 17; cone[7] = 18;
1491*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 10, cone));
1492ae8bcbbbSMatthew G. Knepley         cone[0] = 22; cone[1] = 21; cone[2] = 26; cone[3] = 25;
1493ae8bcbbbSMatthew G. Knepley         cone[4] = 16; cone[5] = 23; cone[6] = 24; cone[7] = 17;
1494*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 11, cone));
1495ae8bcbbbSMatthew G. Knepley         cone[0] = 20; cone[1] = 28; cone[2] = 26; cone[3] = 21;
1496ae8bcbbbSMatthew G. Knepley         cone[4] = 18; cone[5] = 17; cone[6] = 24; cone[7] = 27;
1497*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 12, cone));
1498ae8bcbbbSMatthew G. Knepley         cone[0] = 30; cone[1] = 28; cone[2] = 20; cone[3] = 19;
1499ae8bcbbbSMatthew G. Knepley         cone[4] = 29; cone[5] = 15; cone[6] = 18; cone[7] = 27;
1500*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 13, cone));
1501ae8bcbbbSMatthew G. Knepley         cone[0] = 30; cone[1] = 19; cone[2] = 22; cone[3] = 25;
1502ae8bcbbbSMatthew G. Knepley         cone[4] = 29; cone[5] = 23; cone[6] = 16; cone[7] = 15;
1503*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 14, cone));
1504006a8963SMatthew G. Knepley       } else {
150510c6f908SMatthew G. Knepley         cone[0] =  5; cone[1] =  8; cone[2] =  7; cone[3] =  6;
150610c6f908SMatthew G. Knepley         cone[4] =  9; cone[5] = 12; cone[6] = 11; cone[7] = 10;
1507*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 0, cone));
150810c6f908SMatthew G. Knepley         cone[0] =  6; cone[1] =  7; cone[2] = 14; cone[3] = 13;
150910c6f908SMatthew G. Knepley         cone[4] = 12; cone[5] = 15; cone[6] = 16; cone[7] = 11;
1510*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 1, cone));
151110c6f908SMatthew G. Knepley         cone[0] =  8; cone[1] = 17; cone[2] = 14; cone[3] =  7;
151210c6f908SMatthew G. Knepley         cone[4] = 10; cone[5] = 11; cone[6] = 16; cone[7] = 18;
1513*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 2, cone));
151410c6f908SMatthew G. Knepley         cone[0] = 19; cone[1] = 17; cone[2] =  8; cone[3] =  5;
151510c6f908SMatthew G. Knepley         cone[4] = 20; cone[5] =  9; cone[6] = 10; cone[7] = 18;
1516*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 3, cone));
151710c6f908SMatthew G. Knepley         cone[0] = 19; cone[1] =  5; cone[2] =  6; cone[3] = 13;
151810c6f908SMatthew G. Knepley         cone[4] = 20; cone[5] = 15; cone[6] = 12; cone[7] =  9;
1519*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 4, cone));
1520006a8963SMatthew G. Knepley       }
1521d8c47e87SMatthew G. Knepley     }
1522*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSymmetrize(dm));
1523*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexStratify(dm));
15240510c589SMatthew G. Knepley   }
1525dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
15260510c589SMatthew G. Knepley   {
15270510c589SMatthew G. Knepley     Vec             coordinates;
15280510c589SMatthew G. Knepley     PetscSection    coordSection;
15290510c589SMatthew G. Knepley     PetscScalar    *coords;
15300510c589SMatthew G. Knepley     PetscInt        coordSize, v;
15310510c589SMatthew G. Knepley     const PetscReal dis = 1.0/PetscSqrtReal(2.0);
15320510c589SMatthew G. Knepley     const PetscReal ds2 = dis/2.0;
15330510c589SMatthew G. Knepley 
15340510c589SMatthew G. Knepley     /* Build coordinates */
1535*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
1536*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
1537*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim));
1538*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVertices));
15390510c589SMatthew G. Knepley     for (v = numCells; v < numCells+numVertices; ++v) {
1540*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetDof(coordSection, v, dim));
1541*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim));
15420510c589SMatthew G. Knepley     }
1543*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(coordSection));
1544*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
1545*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
1546*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
1547*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1548*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetBlockSize(coordinates, dim));
1549*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(coordinates,VECSTANDARD));
1550*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(coordinates, &coords));
1551dd400576SPatrick Sanan     if (rank == 0) {
15520510c589SMatthew G. Knepley       coords[0*dim+0] = -ds2; coords[0*dim+1] = -ds2; coords[0*dim+2] = 0.0;
15530510c589SMatthew G. Knepley       coords[1*dim+0] =  ds2; coords[1*dim+1] = -ds2; coords[1*dim+2] = 0.0;
15540510c589SMatthew G. Knepley       coords[2*dim+0] =  ds2; coords[2*dim+1] =  ds2; coords[2*dim+2] = 0.0;
15550510c589SMatthew G. Knepley       coords[3*dim+0] = -ds2; coords[3*dim+1] =  ds2; coords[3*dim+2] = 0.0;
15560510c589SMatthew G. Knepley       coords[4*dim+0] = -ds2; coords[4*dim+1] = -ds2; coords[4*dim+2] = 1.0;
15570510c589SMatthew G. Knepley       coords[5*dim+0] = -ds2; coords[5*dim+1] =  ds2; coords[5*dim+2] = 1.0;
15580510c589SMatthew G. Knepley       coords[6*dim+0] =  ds2; coords[6*dim+1] =  ds2; coords[6*dim+2] = 1.0;
15590510c589SMatthew G. Knepley       coords[7*dim+0] =  ds2; coords[7*dim+1] = -ds2; coords[7*dim+2] = 1.0;
15600510c589SMatthew G. Knepley       coords[ 8*dim+0] =  dis; coords[ 8*dim+1] = -dis; coords[ 8*dim+2] = 0.0;
15610510c589SMatthew G. Knepley       coords[ 9*dim+0] =  dis; coords[ 9*dim+1] =  dis; coords[ 9*dim+2] = 0.0;
15620510c589SMatthew G. Knepley       coords[10*dim+0] =  dis; coords[10*dim+1] = -dis; coords[10*dim+2] = 1.0;
15630510c589SMatthew G. Knepley       coords[11*dim+0] =  dis; coords[11*dim+1] =  dis; coords[11*dim+2] = 1.0;
15640510c589SMatthew G. Knepley       coords[12*dim+0] = -dis; coords[12*dim+1] =  dis; coords[12*dim+2] = 0.0;
15650510c589SMatthew G. Knepley       coords[13*dim+0] = -dis; coords[13*dim+1] =  dis; coords[13*dim+2] = 1.0;
15660510c589SMatthew G. Knepley       coords[14*dim+0] = -dis; coords[14*dim+1] = -dis; coords[14*dim+2] = 0.0;
15670510c589SMatthew G. Knepley       coords[15*dim+0] = -dis; coords[15*dim+1] = -dis; coords[15*dim+2] = 1.0;
1568ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
1569ae8bcbbbSMatthew G. Knepley         /* 15 31 19 */ coords[16*dim+0] = -ds2; coords[16*dim+1] = -ds2; coords[16*dim+2] = 0.5;
1570ae8bcbbbSMatthew G. Knepley         /* 16 32 22 */ coords[17*dim+0] =  ds2; coords[17*dim+1] = -ds2; coords[17*dim+2] = 0.5;
1571ae8bcbbbSMatthew G. Knepley         /* 17 33 21 */ coords[18*dim+0] =  ds2; coords[18*dim+1] =  ds2; coords[18*dim+2] = 0.5;
1572ae8bcbbbSMatthew G. Knepley         /* 18 34 20 */ coords[19*dim+0] = -ds2; coords[19*dim+1] =  ds2; coords[19*dim+2] = 0.5;
1573ae8bcbbbSMatthew G. Knepley         /* 29 35 30 */ coords[20*dim+0] = -dis; coords[20*dim+1] = -dis; coords[20*dim+2] = 0.5;
1574ae8bcbbbSMatthew G. Knepley         /* 23 36 25 */ coords[21*dim+0] =  dis; coords[21*dim+1] = -dis; coords[21*dim+2] = 0.5;
1575ae8bcbbbSMatthew G. Knepley         /* 24 37 26 */ coords[22*dim+0] =  dis; coords[22*dim+1] =  dis; coords[22*dim+2] = 0.5;
1576ae8bcbbbSMatthew G. Knepley         /* 27 38 28 */ coords[23*dim+0] = -dis; coords[23*dim+1] =  dis; coords[23*dim+2] = 0.5;
1577ae8bcbbbSMatthew G. Knepley       }
1578d8c47e87SMatthew G. Knepley     }
1579*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(coordinates, &coords));
1580*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
1581*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&coordinates));
15820510c589SMatthew G. Knepley   }
1583006a8963SMatthew G. Knepley   /* Create periodicity */
1584006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
1585006a8963SMatthew G. Knepley     PetscReal      L[3];
1586006a8963SMatthew G. Knepley     PetscReal      maxCell[3];
1587006a8963SMatthew G. Knepley     DMBoundaryType bdType[3];
1588006a8963SMatthew G. Knepley     PetscReal      lower[3] = {0.0, 0.0, 0.0};
1589ae8bcbbbSMatthew G. Knepley     PetscReal      upper[3] = {1.0, 1.0, 1.5};
1590ae8bcbbbSMatthew G. Knepley     PetscInt       i, numZCells = 3;
1591006a8963SMatthew G. Knepley 
1592006a8963SMatthew G. Knepley     bdType[0] = DM_BOUNDARY_NONE;
1593006a8963SMatthew G. Knepley     bdType[1] = DM_BOUNDARY_NONE;
1594006a8963SMatthew G. Knepley     bdType[2] = periodicZ;
1595006a8963SMatthew G. Knepley     for (i = 0; i < dim; i++) {
1596006a8963SMatthew G. Knepley       L[i]       = upper[i] - lower[i];
1597006a8963SMatthew G. Knepley       maxCell[i] = 1.1 * (L[i] / numZCells);
1598006a8963SMatthew G. Knepley     }
1599*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, maxCell, L, bdType));
1600006a8963SMatthew G. Knepley   }
1601dbc1dc17SMatthew G. Knepley   {
16029318fe57SMatthew G. Knepley     DM          cdm;
16039318fe57SMatthew G. Knepley     PetscDS     cds;
16049318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1605dbc1dc17SMatthew G. Knepley 
1606*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
1607*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dm, &cdm));
1608*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDS(cdm, &cds));
1609*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDSSetConstants(cds, 2, c));
1610dbc1dc17SMatthew G. Knepley   }
16119318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
1612*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexInterpolateInPlace_Internal(dm));
16130510c589SMatthew G. Knepley   PetscFunctionReturn(0);
16140510c589SMatthew G. Knepley }
16150510c589SMatthew G. Knepley 
161624119c2aSMatthew G. Knepley /*@
16179318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
161824119c2aSMatthew G. Knepley 
1619d083f849SBarry Smith   Collective
162024119c2aSMatthew G. Knepley 
162124119c2aSMatthew G. Knepley   Input Parameters:
162224119c2aSMatthew G. Knepley + comm      - The communicator for the DM object
16239318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
162424119c2aSMatthew G. Knepley 
162524119c2aSMatthew G. Knepley   Output Parameter:
162624119c2aSMatthew G. Knepley . dm  - The DM object
162724119c2aSMatthew G. Knepley 
16289318fe57SMatthew G. Knepley   Note:
16299318fe57SMatthew G. Knepley   Here is the output numbering looking from the bottom of the cylinder:
16309318fe57SMatthew G. Knepley $       17-----14
16319318fe57SMatthew G. Knepley $        |     |
16329318fe57SMatthew G. Knepley $        |  2  |
16339318fe57SMatthew G. Knepley $        |     |
16349318fe57SMatthew G. Knepley $ 17-----8-----7-----14
16359318fe57SMatthew G. Knepley $  |     |     |     |
16369318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
16379318fe57SMatthew G. Knepley $  |     |     |     |
16389318fe57SMatthew G. Knepley $ 19-----5-----6-----13
16399318fe57SMatthew G. Knepley $        |     |
16409318fe57SMatthew G. Knepley $        |  4  |
16419318fe57SMatthew G. Knepley $        |     |
16429318fe57SMatthew G. Knepley $       19-----13
16439318fe57SMatthew G. Knepley $
16449318fe57SMatthew G. Knepley $ and up through the top
16459318fe57SMatthew G. Knepley $
16469318fe57SMatthew G. Knepley $       18-----16
16479318fe57SMatthew G. Knepley $        |     |
16489318fe57SMatthew G. Knepley $        |  2  |
16499318fe57SMatthew G. Knepley $        |     |
16509318fe57SMatthew G. Knepley $ 18----10----11-----16
16519318fe57SMatthew G. Knepley $  |     |     |     |
16529318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
16539318fe57SMatthew G. Knepley $  |     |     |     |
16549318fe57SMatthew G. Knepley $ 20-----9----12-----15
16559318fe57SMatthew G. Knepley $        |     |
16569318fe57SMatthew G. Knepley $        |  4  |
16579318fe57SMatthew G. Knepley $        |     |
16589318fe57SMatthew G. Knepley $       20-----15
16599318fe57SMatthew G. Knepley 
166024119c2aSMatthew G. Knepley   Level: beginner
166124119c2aSMatthew G. Knepley 
16629318fe57SMatthew G. Knepley .seealso: DMPlexCreateBoxMesh(), DMSetType(), DMCreate()
166324119c2aSMatthew G. Knepley @*/
16649318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm)
16659318fe57SMatthew G. Knepley {
16669318fe57SMatthew G. Knepley   PetscFunctionBegin;
16679318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
1668*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
1669*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
1670*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
16719318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
16729318fe57SMatthew G. Knepley }
16739318fe57SMatthew G. Knepley 
16749318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
167524119c2aSMatthew G. Knepley {
167624119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1677412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
16789fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
167924119c2aSMatthew G. Knepley 
168024119c2aSMatthew G. Knepley   PetscFunctionBegin;
16812c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %D cannot be negative", n);
1682*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
1683*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim));
1684412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
1685*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, "celltype"));
168624119c2aSMatthew G. Knepley   /* Create topology */
168724119c2aSMatthew G. Knepley   {
168824119c2aSMatthew G. Knepley     PetscInt cone[6], c;
168924119c2aSMatthew G. Knepley 
1690dd400576SPatrick Sanan     numCells    = rank == 0 ?        n : 0;
1691dd400576SPatrick Sanan     numVertices = rank == 0 ?  2*(n+1) : 0;
1692*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices));
1693*5f80ce2aSJacob Faibussowitsch     for (c = 0; c < numCells; c++) CHKERRQ(DMPlexSetConeSize(dm, c, 6));
1694*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(dm));
169524119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
169624119c2aSMatthew G. Knepley       cone[0] =  c+n*1; cone[1] = (c+1)%n+n*1; cone[2] = 0+3*n;
169724119c2aSMatthew G. Knepley       cone[3] =  c+n*2; cone[4] = (c+1)%n+n*2; cone[5] = 1+3*n;
1698*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetCone(dm, c, cone));
1699*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
170024119c2aSMatthew G. Knepley     }
1701*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSymmetrize(dm));
1702*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexStratify(dm));
170324119c2aSMatthew G. Knepley   }
1704412e9a14SMatthew G. Knepley   for (v = numCells; v < numCells+numVertices; ++v) {
1705*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
170624119c2aSMatthew G. Knepley   }
170724119c2aSMatthew G. Knepley   /* Create cylinder geometry */
170824119c2aSMatthew G. Knepley   {
170924119c2aSMatthew G. Knepley     Vec          coordinates;
171024119c2aSMatthew G. Knepley     PetscSection coordSection;
171124119c2aSMatthew G. Knepley     PetscScalar *coords;
1712412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
171324119c2aSMatthew G. Knepley 
171424119c2aSMatthew G. Knepley     /* Build coordinates */
1715*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
1716*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
1717*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dim));
1718*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells+numVertices));
171924119c2aSMatthew G. Knepley     for (v = numCells; v < numCells+numVertices; ++v) {
1720*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetDof(coordSection, v, dim));
1721*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dim));
172224119c2aSMatthew G. Knepley     }
1723*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(coordSection));
1724*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
1725*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
1726*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
1727*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1728*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetBlockSize(coordinates, dim));
1729*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(coordinates,VECSTANDARD));
1730*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(coordinates, &coords));
173124119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
173224119c2aSMatthew G. Knepley       coords[(c+0*n)*dim+0] = PetscCosReal(2.0*c*PETSC_PI/n); coords[(c+0*n)*dim+1] = PetscSinReal(2.0*c*PETSC_PI/n); coords[(c+0*n)*dim+2] = 1.0;
173324119c2aSMatthew G. Knepley       coords[(c+1*n)*dim+0] = PetscCosReal(2.0*c*PETSC_PI/n); coords[(c+1*n)*dim+1] = PetscSinReal(2.0*c*PETSC_PI/n); coords[(c+1*n)*dim+2] = 0.0;
173424119c2aSMatthew G. Knepley     }
1735dd400576SPatrick Sanan     if (rank == 0) {
173624119c2aSMatthew G. Knepley       coords[(2*n+0)*dim+0] = 0.0; coords[(2*n+0)*dim+1] = 0.0; coords[(2*n+0)*dim+2] = 1.0;
173724119c2aSMatthew G. Knepley       coords[(2*n+1)*dim+0] = 0.0; coords[(2*n+1)*dim+1] = 0.0; coords[(2*n+1)*dim+2] = 0.0;
17389fe9f049SMatthew G. Knepley     }
1739*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(coordinates, &coords));
1740*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
1741*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&coordinates));
174224119c2aSMatthew G. Knepley   }
17439318fe57SMatthew G. Knepley   /* Interpolate */
1744*5f80ce2aSJacob Faibussowitsch   if (interpolate) CHKERRQ(DMPlexInterpolateInPlace_Internal(dm));
17459318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
17469318fe57SMatthew G. Knepley }
17479318fe57SMatthew G. Knepley 
17489318fe57SMatthew G. Knepley /*@
17499318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
17509318fe57SMatthew G. Knepley 
17519318fe57SMatthew G. Knepley   Collective
17529318fe57SMatthew G. Knepley 
17539318fe57SMatthew G. Knepley   Input Parameters:
17549318fe57SMatthew G. Knepley + comm - The communicator for the DM object
17559318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
17569318fe57SMatthew G. Knepley - interpolate - Create edges and faces
17579318fe57SMatthew G. Knepley 
17589318fe57SMatthew G. Knepley   Output Parameter:
17599318fe57SMatthew G. Knepley . dm  - The DM object
17609318fe57SMatthew G. Knepley 
17619318fe57SMatthew G. Knepley   Level: beginner
17629318fe57SMatthew G. Knepley 
17639318fe57SMatthew G. Knepley .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate()
17649318fe57SMatthew G. Knepley @*/
17659318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
17669318fe57SMatthew G. Knepley {
17679318fe57SMatthew G. Knepley   PetscFunctionBegin;
17689318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
1769*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
1770*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
1771*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
177224119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
177324119c2aSMatthew G. Knepley }
177424119c2aSMatthew G. Knepley 
17759fbee547SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
177665a81367SMatthew G. Knepley {
177765a81367SMatthew G. Knepley   PetscReal prod = 0.0;
177865a81367SMatthew G. Knepley   PetscInt  i;
177965a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
178065a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
178165a81367SMatthew G. Knepley }
17829fbee547SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
178365a81367SMatthew G. Knepley {
178465a81367SMatthew G. Knepley   PetscReal prod = 0.0;
178565a81367SMatthew G. Knepley   PetscInt  i;
178665a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i]*y[i];
178765a81367SMatthew G. Knepley   return prod;
178865a81367SMatthew G. Knepley }
178965a81367SMatthew G. Knepley 
179051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
179151a74b61SMatthew G. Knepley static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux,
179251a74b61SMatthew G. Knepley                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
179351a74b61SMatthew G. Knepley                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
179451a74b61SMatthew G. Knepley                          PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
179551a74b61SMatthew G. Knepley {
179651a74b61SMatthew G. Knepley   PetscReal r = PetscRealPart(constants[0]);
179751a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
179851a74b61SMatthew G. Knepley   PetscInt  n = uOff[1] - uOff[0], d;
179951a74b61SMatthew G. Knepley 
180051a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
180151a74b61SMatthew G. Knepley   fac = r/PetscSqrtReal(norm2);
180251a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d]*fac;
180351a74b61SMatthew G. Knepley }
180451a74b61SMatthew G. Knepley 
18059318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
18062829fed8SMatthew G. Knepley {
180765a81367SMatthew G. Knepley   const PetscInt  embedDim = dim+1;
180865a81367SMatthew G. Knepley   PetscSection    coordSection;
180965a81367SMatthew G. Knepley   Vec             coordinates;
181065a81367SMatthew G. Knepley   PetscScalar    *coords;
181165a81367SMatthew G. Knepley   PetscReal      *coordsIn;
181265a81367SMatthew G. Knepley   PetscInt        numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e;
181365a81367SMatthew G. Knepley   PetscMPIInt     rank;
181465a81367SMatthew G. Knepley 
181565a81367SMatthew G. Knepley   PetscFunctionBegin;
18169318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
1817*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, dim));
1818*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, dim+1));
1819*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
182065a81367SMatthew G. Knepley   switch (dim) {
182165a81367SMatthew G. Knepley   case 2:
182265a81367SMatthew G. Knepley     if (simplex) {
182351a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI*PETSC_PHI)/(1.0 + PETSC_PHI);
182451a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0/(1.0 + PETSC_PHI) * (R/radius);
182565a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
182651a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0/(1.0 + PETSC_PHI), PETSC_PHI/(1.0 + PETSC_PHI)};
182765a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
182865a81367SMatthew G. Knepley       PetscInt        cone[3];
182965a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
183065a81367SMatthew G. Knepley 
183151a74b61SMatthew G. Knepley       vertex[0] *= R/radius; vertex[1] *= R/radius; vertex[2] *= R/radius;
1832dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
1833dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
183465a81367SMatthew G. Knepley       firstVertex = numCells;
183551a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
183665a81367SMatthew G. Knepley 
183765a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
183865a81367SMatthew G. Knepley 
183965a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
184051a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
184165a81367SMatthew G. Knepley       */
184265a81367SMatthew G. Knepley       /* Construct vertices */
1843*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(numVerts * embedDim, &coordsIn));
1844dd400576SPatrick Sanan       if (rank == 0) {
184565a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
184665a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
184765a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
184865a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertex[(d+p)%embedDim];
184965a81367SMatthew G. Knepley               ++i;
185065a81367SMatthew G. Knepley             }
185165a81367SMatthew G. Knepley           }
185265a81367SMatthew G. Knepley         }
185345da822fSValeria Barra       }
185465a81367SMatthew G. Knepley       /* Construct graph */
1855*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(numVerts * numVerts, &graph));
185665a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
185765a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
185865a81367SMatthew G. Knepley           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;}
185965a81367SMatthew G. Knepley         }
18602c71b3e2SJacob Faibussowitsch         PetscCheckFalse(k != degree,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %D degree %D != %D", i, k, degree);
186165a81367SMatthew G. Knepley       }
186265a81367SMatthew G. Knepley       /* Build Topology */
1863*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerts));
186465a81367SMatthew G. Knepley       for (c = 0; c < numCells; c++) {
1865*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeSize(dm, c, embedDim));
186665a81367SMatthew G. Knepley       }
1867*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
186865a81367SMatthew G. Knepley       /* Cells */
186965a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
187065a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
187165a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
187265a81367SMatthew G. Knepley             if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i]) {
187365a81367SMatthew G. Knepley               cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k;
187465a81367SMatthew G. Knepley               /* Check orientation */
187565a81367SMatthew G. Knepley               {
187665a81367SMatthew G. Knepley                 const PetscInt epsilon[3][3][3] = {{{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, {{0, 0, -1}, {0, 0, 0}, {1, 0, 0}}, {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}}};
187765a81367SMatthew G. Knepley                 PetscReal normal[3];
187865a81367SMatthew G. Knepley                 PetscInt  e, f;
187965a81367SMatthew G. Knepley 
188065a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
188165a81367SMatthew G. Knepley                   normal[d] = 0.0;
188265a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
188365a81367SMatthew G. Knepley                     for (f = 0; f < embedDim; ++f) {
188465a81367SMatthew G. Knepley                       normal[d] += epsilon[d][e][f]*(coordsIn[j*embedDim+e] - coordsIn[i*embedDim+e])*(coordsIn[k*embedDim+f] - coordsIn[i*embedDim+f]);
188565a81367SMatthew G. Knepley                     }
188665a81367SMatthew G. Knepley                   }
188765a81367SMatthew G. Knepley                 }
188865a81367SMatthew G. Knepley                 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;}
188965a81367SMatthew G. Knepley               }
1890*5f80ce2aSJacob Faibussowitsch               CHKERRQ(DMPlexSetCone(dm, c++, cone));
189165a81367SMatthew G. Knepley             }
189265a81367SMatthew G. Knepley           }
189365a81367SMatthew G. Knepley         }
189465a81367SMatthew G. Knepley       }
1895*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSymmetrize(dm));
1896*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexStratify(dm));
1897*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(graph));
189865a81367SMatthew G. Knepley     } else {
18992829fed8SMatthew G. Knepley       /*
19002829fed8SMatthew G. Knepley         12-21--13
19012829fed8SMatthew G. Knepley          |     |
19022829fed8SMatthew G. Knepley         25  4  24
19032829fed8SMatthew G. Knepley          |     |
19042829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
19052829fed8SMatthew G. Knepley    |     |     |     |
19062829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
19072829fed8SMatthew G. Knepley    |     |     |     |
19082829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
19092829fed8SMatthew G. Knepley          |     |
19102829fed8SMatthew G. Knepley         20  1  19
19112829fed8SMatthew G. Knepley          |     |
19122829fed8SMatthew G. Knepley         10-18--11
19132829fed8SMatthew G. Knepley          |     |
19142829fed8SMatthew G. Knepley         23  2  22
19152829fed8SMatthew G. Knepley          |     |
19162829fed8SMatthew G. Knepley         12-21--13
19172829fed8SMatthew G. Knepley        */
19182829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
19192829fed8SMatthew G. Knepley 
1920dd400576SPatrick Sanan       numCells    = rank == 0 ?  6 : 0;
1921dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
1922dd400576SPatrick Sanan       numVerts    = rank == 0 ?  8 : 0;
192365a81367SMatthew G. Knepley       firstVertex = numCells;
192465a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
19252829fed8SMatthew G. Knepley       /* Build Topology */
1926*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetChart(dm, 0, numCells+numEdges+numVerts));
19272829fed8SMatthew G. Knepley       for (c = 0; c < numCells; c++) {
1928*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeSize(dm, c, 4));
19292829fed8SMatthew G. Knepley       }
19302829fed8SMatthew G. Knepley       for (e = firstEdge; e < firstEdge+numEdges; ++e) {
1931*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeSize(dm, e, 2));
19322829fed8SMatthew G. Knepley       }
1933*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
1934dd400576SPatrick Sanan       if (rank == 0) {
19352829fed8SMatthew G. Knepley         /* Cell 0 */
19362829fed8SMatthew G. Knepley         cone[0] = 14; cone[1] = 15; cone[2] = 16; cone[3] = 17;
1937*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 0, cone));
19382829fed8SMatthew G. Knepley         ornt[0] = 0; ornt[1] = 0; ornt[2] = 0; ornt[3] = 0;
1939*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeOrientation(dm, 0, ornt));
19402829fed8SMatthew G. Knepley         /* Cell 1 */
19412829fed8SMatthew G. Knepley         cone[0] = 18; cone[1] = 19; cone[2] = 14; cone[3] = 20;
1942*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 1, cone));
1943b5a892a1SMatthew G. Knepley         ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0;
1944*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeOrientation(dm, 1, ornt));
19452829fed8SMatthew G. Knepley         /* Cell 2 */
19462829fed8SMatthew G. Knepley         cone[0] = 21; cone[1] = 22; cone[2] = 18; cone[3] = 23;
1947*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 2, cone));
1948b5a892a1SMatthew G. Knepley         ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0;
1949*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeOrientation(dm, 2, ornt));
19502829fed8SMatthew G. Knepley         /* Cell 3 */
19512829fed8SMatthew G. Knepley         cone[0] = 19; cone[1] = 22; cone[2] = 24; cone[3] = 15;
1952*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 3, cone));
1953b5a892a1SMatthew G. Knepley         ornt[0] = -1; ornt[1] = -1; ornt[2] = 0; ornt[3] = -1;
1954*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeOrientation(dm, 3, ornt));
19552829fed8SMatthew G. Knepley         /* Cell 4 */
19562829fed8SMatthew G. Knepley         cone[0] = 16; cone[1] = 24; cone[2] = 21; cone[3] = 25;
1957*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 4, cone));
1958b5a892a1SMatthew G. Knepley         ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = 0;
1959*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeOrientation(dm, 4, ornt));
19602829fed8SMatthew G. Knepley         /* Cell 5 */
19612829fed8SMatthew G. Knepley         cone[0] = 20; cone[1] = 17; cone[2] = 25; cone[3] = 23;
1962*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 5, cone));
1963b5a892a1SMatthew G. Knepley         ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = -1;
1964*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeOrientation(dm, 5, ornt));
19652829fed8SMatthew G. Knepley         /* Edges */
19662829fed8SMatthew G. Knepley         cone[0] =  6; cone[1] =  7;
1967*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 14, cone));
19682829fed8SMatthew G. Knepley         cone[0] =  7; cone[1] =  8;
1969*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 15, cone));
19702829fed8SMatthew G. Knepley         cone[0] =  8; cone[1] =  9;
1971*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 16, cone));
19722829fed8SMatthew G. Knepley         cone[0] =  9; cone[1] =  6;
1973*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 17, cone));
19742829fed8SMatthew G. Knepley         cone[0] = 10; cone[1] = 11;
1975*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 18, cone));
19762829fed8SMatthew G. Knepley         cone[0] = 11; cone[1] =  7;
1977*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 19, cone));
19782829fed8SMatthew G. Knepley         cone[0] =  6; cone[1] = 10;
1979*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 20, cone));
19802829fed8SMatthew G. Knepley         cone[0] = 12; cone[1] = 13;
1981*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 21, cone));
19822829fed8SMatthew G. Knepley         cone[0] = 13; cone[1] = 11;
1983*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 22, cone));
19842829fed8SMatthew G. Knepley         cone[0] = 10; cone[1] = 12;
1985*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 23, cone));
19862829fed8SMatthew G. Knepley         cone[0] = 13; cone[1] =  8;
1987*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 24, cone));
19882829fed8SMatthew G. Knepley         cone[0] = 12; cone[1] =  9;
1989*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(dm, 25, cone));
199045da822fSValeria Barra       }
1991*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSymmetrize(dm));
1992*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexStratify(dm));
19932829fed8SMatthew G. Knepley       /* Build coordinates */
1994*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(numVerts * embedDim, &coordsIn));
1995dd400576SPatrick Sanan       if (rank == 0) {
199651a74b61SMatthew G. Knepley         coordsIn[0*embedDim+0] = -R; coordsIn[0*embedDim+1] =  R; coordsIn[0*embedDim+2] = -R;
199751a74b61SMatthew G. Knepley         coordsIn[1*embedDim+0] =  R; coordsIn[1*embedDim+1] =  R; coordsIn[1*embedDim+2] = -R;
199851a74b61SMatthew G. Knepley         coordsIn[2*embedDim+0] =  R; coordsIn[2*embedDim+1] = -R; coordsIn[2*embedDim+2] = -R;
199951a74b61SMatthew G. Knepley         coordsIn[3*embedDim+0] = -R; coordsIn[3*embedDim+1] = -R; coordsIn[3*embedDim+2] = -R;
200051a74b61SMatthew G. Knepley         coordsIn[4*embedDim+0] = -R; coordsIn[4*embedDim+1] =  R; coordsIn[4*embedDim+2] =  R;
200151a74b61SMatthew G. Knepley         coordsIn[5*embedDim+0] =  R; coordsIn[5*embedDim+1] =  R; coordsIn[5*embedDim+2] =  R;
200251a74b61SMatthew G. Knepley         coordsIn[6*embedDim+0] = -R; coordsIn[6*embedDim+1] = -R; coordsIn[6*embedDim+2] =  R;
200351a74b61SMatthew G. Knepley         coordsIn[7*embedDim+0] =  R; coordsIn[7*embedDim+1] = -R; coordsIn[7*embedDim+2] =  R;
200465a81367SMatthew G. Knepley       }
200545da822fSValeria Barra     }
200665a81367SMatthew G. Knepley     break;
200765a81367SMatthew G. Knepley   case 3:
2008116ded15SMatthew G. Knepley     if (simplex) {
2009116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0/PETSC_PHI;
201051a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
201151a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
201251a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5*PETSC_PHI, 0.5/PETSC_PHI, 0.0};
2013116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2014116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
2015116ded15SMatthew G. Knepley       PetscInt        evenPerm[12][4] = {{0, 1, 2, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 3, 2, 0},
2016116ded15SMatthew G. Knepley                                          {2, 0, 1, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 2, 1, 0}};
2017116ded15SMatthew G. Knepley       PetscInt        cone[4];
2018116ded15SMatthew G. Knepley       PetscInt       *graph, p, i, j, k, l;
2019116ded15SMatthew G. Knepley 
202051a74b61SMatthew G. Knepley       vertexA[0] *= R; vertexA[1] *= R; vertexA[2] *= R; vertexA[3] *= R;
202151a74b61SMatthew G. Knepley       vertexB[0] *= R; vertexB[1] *= R; vertexB[2] *= R; vertexB[3] *= R;
202251a74b61SMatthew G. Knepley       vertexC[0] *= R; vertexC[1] *= R; vertexC[2] *= R; vertexC[3] *= R;
2023dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2024dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2025116ded15SMatthew G. Knepley       firstVertex = numCells;
2026116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2027116ded15SMatthew G. Knepley 
2028116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2029116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2030116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2031116ded15SMatthew G. Knepley 
2032116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
20336333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2034116ded15SMatthew G. Knepley 
2035116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2036116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2037116ded15SMatthew G. Knepley       */
2038116ded15SMatthew G. Knepley       /* Construct vertices */
2039*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(numVerts * embedDim, &coordsIn));
2040116ded15SMatthew G. Knepley       i    = 0;
2041dd400576SPatrick Sanan       if (rank == 0) {
2042116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2043116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2044116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2045116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2046116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[d]*vertexA[d];
2047116ded15SMatthew G. Knepley                 ++i;
2048116ded15SMatthew G. Knepley               }
2049116ded15SMatthew G. Knepley             }
2050116ded15SMatthew G. Knepley           }
2051116ded15SMatthew G. Knepley         }
2052116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2053116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2054116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2055116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertexB[(d+p)%embedDim];
2056116ded15SMatthew G. Knepley             ++i;
2057116ded15SMatthew G. Knepley           }
2058116ded15SMatthew G. Knepley         }
2059116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2060116ded15SMatthew G. Knepley           s[3] = 1;
2061116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2062116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2063116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2064116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[evenPerm[p][d]]*vertexC[evenPerm[p][d]];
2065116ded15SMatthew G. Knepley                 ++i;
2066116ded15SMatthew G. Knepley               }
2067116ded15SMatthew G. Knepley             }
2068116ded15SMatthew G. Knepley           }
2069116ded15SMatthew G. Knepley         }
207045da822fSValeria Barra       }
20712c71b3e2SJacob Faibussowitsch       PetscCheckFalse(i != numVerts,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %D != %D", i, numVerts);
2072116ded15SMatthew G. Knepley       /* Construct graph */
2073*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(numVerts * numVerts, &graph));
2074116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2075116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
2076116ded15SMatthew G. Knepley           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;}
2077116ded15SMatthew G. Knepley         }
20782c71b3e2SJacob Faibussowitsch         PetscCheckFalse(k != degree,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %D degree %D != %D", i, k, degree);
2079116ded15SMatthew G. Knepley       }
2080116ded15SMatthew G. Knepley       /* Build Topology */
2081*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerts));
2082116ded15SMatthew G. Knepley       for (c = 0; c < numCells; c++) {
2083*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeSize(dm, c, embedDim));
2084116ded15SMatthew G. Knepley       }
2085*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
2086116ded15SMatthew G. Knepley       /* Cells */
2087dd400576SPatrick Sanan       if (rank == 0) {
2088116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2089116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2090116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2091116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
2092116ded15SMatthew G. Knepley                 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i] &&
2093116ded15SMatthew G. Knepley                     graph[l*numVerts+i] && graph[l*numVerts+j] && graph[l*numVerts+k]) {
2094116ded15SMatthew G. Knepley                   cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; cone[3] = firstVertex+l;
2095116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2096116ded15SMatthew G. Knepley                   {
2097116ded15SMatthew G. Knepley                     const PetscInt epsilon[4][4][4][4] = {{{{0,  0,  0,  0}, { 0, 0,  0,  0}, { 0,  0, 0,  0}, { 0,  0,  0, 0}},
2098116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  0}, { 0, 0,  0,  0}, { 0,  0, 0,  1}, { 0,  0, -1, 0}},
2099116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  0}, { 0, 0,  0, -1}, { 0,  0, 0,  0}, { 0,  1,  0, 0}},
2100116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  0}, { 0, 0,  1,  0}, { 0, -1, 0,  0}, { 0,  0,  0, 0}}},
2101116ded15SMatthew G. Knepley 
2102116ded15SMatthew G. Knepley                                                           {{{0,  0,  0,  0}, { 0, 0,  0,  0}, { 0,  0, 0, -1}, { 0,  0,  1, 0}},
2103116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  0}, { 0, 0,  0,  0}, { 0,  0, 0,  0}, { 0,  0,  0, 0}},
2104116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  1}, { 0, 0,  0,  0}, { 0,  0, 0,  0}, {-1,  0,  0, 0}},
2105116ded15SMatthew G. Knepley                                                            {{0,  0, -1,  0}, { 0, 0,  0,  0}, { 1,  0, 0,  0}, { 0,  0,  0, 0}}},
2106116ded15SMatthew G. Knepley 
2107116ded15SMatthew G. Knepley                                                           {{{0,  0,  0,  0}, { 0, 0,  0,  1}, { 0,  0, 0,  0}, { 0, -1,  0, 0}},
2108116ded15SMatthew G. Knepley                                                            {{0,  0,  0, -1}, { 0, 0,  0,  0}, { 0,  0, 0,  0}, { 1,  0,  0, 0}},
2109116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  0}, { 0, 0,  0,  0}, { 0,  0, 0,  0}, { 0,  0,  0, 0}},
2110116ded15SMatthew G. Knepley                                                            {{0,  1,  0,  0}, {-1, 0,  0,  0}, { 0,  0, 0,  0}, { 0,  0,  0, 0}}},
2111116ded15SMatthew G. Knepley 
2112116ded15SMatthew G. Knepley                                                           {{{0,  0,  0,  0}, { 0, 0, -1,  0}, { 0,  1, 0,  0}, { 0,  0,  0, 0}},
2113116ded15SMatthew G. Knepley                                                            {{0,  0,  1,  0}, { 0, 0,  0,  0}, {-1,  0, 0,  0}, { 0,  0,  0, 0}},
2114116ded15SMatthew G. Knepley                                                            {{0, -1,  0,  0}, { 1, 0,  0,  0}, { 0,  0, 0,  0}, { 0,  0,  0, 0}},
2115116ded15SMatthew G. Knepley                                                            {{0,  0,  0,  0}, { 0, 0,  0,  0}, { 0,  0, 0,  0}, { 0,  0,  0, 0}}}};
2116116ded15SMatthew G. Knepley                     PetscReal normal[4];
2117116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2118116ded15SMatthew G. Knepley 
2119116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2120116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2121116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2122116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2123116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2124116ded15SMatthew 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]);
2125116ded15SMatthew G. Knepley                           }
2126116ded15SMatthew G. Knepley                         }
2127116ded15SMatthew G. Knepley                       }
2128116ded15SMatthew G. Knepley                     }
2129116ded15SMatthew G. Knepley                     if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;}
2130116ded15SMatthew G. Knepley                   }
2131*5f80ce2aSJacob Faibussowitsch                   CHKERRQ(DMPlexSetCone(dm, c++, cone));
2132116ded15SMatthew G. Knepley                 }
2133116ded15SMatthew G. Knepley               }
2134116ded15SMatthew G. Knepley             }
2135116ded15SMatthew G. Knepley           }
2136116ded15SMatthew G. Knepley         }
213745da822fSValeria Barra       }
2138*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSymmetrize(dm));
2139*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexStratify(dm));
2140*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(graph));
2141116ded15SMatthew G. Knepley       break;
2142116ded15SMatthew G. Knepley     }
214398921bdaSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %D", dim);
214465a81367SMatthew G. Knepley   }
214565a81367SMatthew G. Knepley   /* Create coordinates */
2146*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
2147*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
2148*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
2149*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVerts));
21502829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex+numVerts; ++v) {
2151*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, embedDim));
2152*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
21532829fed8SMatthew G. Knepley   }
2154*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
2155*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
2156*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
2157*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, embedDim));
2158*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
2159*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
2160*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
2161*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
216265a81367SMatthew G. Knepley   for (v = 0; v < numVerts; ++v) for (d = 0; d < embedDim; ++d) {coords[v*embedDim+d] = coordsIn[v*embedDim+d];}
2163*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
2164*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
2165*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
2166*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(coordsIn));
216751a74b61SMatthew G. Knepley   {
216851a74b61SMatthew G. Knepley     DM          cdm;
216951a74b61SMatthew G. Knepley     PetscDS     cds;
21709318fe57SMatthew G. Knepley     PetscScalar c = R;
217151a74b61SMatthew G. Knepley 
2172*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
2173*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dm, &cdm));
2174*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDS(cdm, &cds));
2175*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDSSetConstants(cds, 1, &c));
217651a74b61SMatthew G. Knepley   }
21779318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
2178*5f80ce2aSJacob Faibussowitsch   if (simplex) CHKERRQ(DMPlexInterpolateInPlace_Internal(dm));
21799318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
21809318fe57SMatthew G. Knepley }
21819318fe57SMatthew G. Knepley 
2182b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal*, PetscReal[], PetscReal(*)[3]);
2183b7f5c055SJed Brown 
2184b7f5c055SJed Brown /*
2185b7f5c055SJed Brown  The Schwarz P implicit surface is
2186b7f5c055SJed Brown 
2187b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2188b7f5c055SJed Brown */
2189b7f5c055SJed Brown static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2190b7f5c055SJed Brown {
2191b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2192b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2193b7f5c055SJed Brown   f[0] = c[0] + c[1] + c[2];
2194b7f5c055SJed Brown   for (PetscInt i=0; i<3; i++) {
2195b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
2196b7f5c055SJed Brown     for (PetscInt j=0; j<3; j++) {
2197b7f5c055SJed Brown       hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
2198b7f5c055SJed Brown     }
2199b7f5c055SJed Brown   }
2200b7f5c055SJed Brown }
2201b7f5c055SJed Brown 
2202b7f5c055SJed Brown /*
2203b7f5c055SJed Brown  The Gyroid implicit surface is
2204b7f5c055SJed Brown 
2205b7f5c055SJed 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)
2206b7f5c055SJed Brown 
2207b7f5c055SJed Brown */
2208b7f5c055SJed Brown static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2209b7f5c055SJed Brown {
2210b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2211b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2212b7f5c055SJed Brown   f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2213b7f5c055SJed Brown   grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2214b7f5c055SJed Brown   grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2215b7f5c055SJed Brown   grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2216b7f5c055SJed Brown   hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2217b7f5c055SJed Brown   hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2218b7f5c055SJed Brown   hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2219b7f5c055SJed Brown   hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2220b7f5c055SJed Brown   hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2221b7f5c055SJed Brown   hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2222b7f5c055SJed Brown   hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2223b7f5c055SJed Brown   hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2224b7f5c055SJed Brown   hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2225b7f5c055SJed Brown }
2226b7f5c055SJed Brown 
2227b7f5c055SJed Brown /*
2228b7f5c055SJed Brown    We wish to solve
2229b7f5c055SJed Brown 
2230b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2231b7f5c055SJed Brown 
2232b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2233b7f5c055SJed 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
2234b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2235b7f5c055SJed Brown 
2236b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2237b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2238b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2239b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2240b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2241b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2242b7f5c055SJed Brown 
2243b7f5c055SJed Brown      f(y) = 0                       1 equation
2244b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2245b7f5c055SJed Brown 
2246b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2247b7f5c055SJed Brown */
2248b7f5c055SJed Brown static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
2249b7f5c055SJed Brown {
2250b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2251b7f5c055SJed Brown   PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
2252b7f5c055SJed Brown   PetscReal f, grad[3], n[3], n_y[3][3], norm, norm_y[3], nd, nd_y[3], sign;
2253b7f5c055SJed Brown 
2254b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2255b7f5c055SJed Brown 
2256b7f5c055SJed Brown   for (PetscInt i=0; i<3; i++) n[i] = grad[i];
2257b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2258b7f5c055SJed Brown   for (PetscInt i=0; i<3; i++) {
2259b7f5c055SJed Brown     norm_y[i] = 1. / norm * n[i] * n_y[i][i];
2260b7f5c055SJed Brown   }
2261b7f5c055SJed Brown 
2262b7f5c055SJed Brown   // Define the Householder reflector
2263b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2264b7f5c055SJed Brown   n[0] += norm * sign;
2265b7f5c055SJed Brown   for (PetscInt i=0; i<3; i++) n_y[0][i] += norm_y[i] * sign;
2266b7f5c055SJed Brown 
2267b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2268b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2269b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2270b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2271b7f5c055SJed Brown 
2272b7f5c055SJed Brown   for (PetscInt i=0; i<3; i++) {
2273b7f5c055SJed Brown     n[i] /= norm;
2274b7f5c055SJed Brown     for (PetscInt j=0; j<3; j++) {
2275b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2276b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2277b7f5c055SJed Brown     }
2278b7f5c055SJed Brown   }
2279b7f5c055SJed Brown 
2280b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2281b7f5c055SJed 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];
2282b7f5c055SJed Brown 
2283b7f5c055SJed Brown   res[0] = f;
2284b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2285b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2286b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2287b7f5c055SJed Brown   for (PetscInt j=0; j<3; j++) {
2288b7f5c055SJed Brown     J[0 + j*3] = grad[j];
2289b7f5c055SJed Brown     J[1 + j*3] = (j == 1)*1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2290b7f5c055SJed Brown     J[2 + j*3] = (j == 2)*1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2291b7f5c055SJed Brown   }
2292b7f5c055SJed Brown }
2293b7f5c055SJed Brown 
2294b7f5c055SJed Brown /*
2295b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2296b7f5c055SJed Brown */
2297b7f5c055SJed Brown static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
2298b7f5c055SJed Brown {
2299b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2300b7f5c055SJed Brown 
2301b7f5c055SJed Brown   PetscFunctionBegin;
2302b7f5c055SJed Brown   for (PetscInt iter=0; iter<10; iter++) {
2303b7f5c055SJed Brown     PetscScalar res[3], J[9];
2304b7f5c055SJed Brown     PetscReal resnorm;
2305b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2306b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2307b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
2308*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "[%D] res [%g %g %g]\n", iter, PetscRealPart(res[0]), PetscRealPart(res[1]), PetscRealPart(res[2])));
2309b7f5c055SJed Brown     }
2310b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2311b7f5c055SJed Brown 
2312b7f5c055SJed Brown     // Take the Newton step
2313*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2314b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2315b7f5c055SJed Brown   }
2316b7f5c055SJed Brown   for (PetscInt i=0; i<3; i++) x[i] = y[i];
2317b7f5c055SJed Brown   PetscFunctionReturn(0);
2318b7f5c055SJed Brown }
2319b7f5c055SJed Brown 
2320b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2321b7f5c055SJed Brown 
23221436d7faSJed Brown static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
2323b7f5c055SJed Brown {
2324b7f5c055SJed Brown   PetscMPIInt rank;
2325b7f5c055SJed Brown   PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2326b7f5c055SJed Brown   PetscInt (*edges)[2] = NULL, *edgeSets = NULL;
2327b7f5c055SJed Brown   PetscInt *cells_flat = NULL;
2328b7f5c055SJed Brown   PetscReal *vtxCoords = NULL;
2329b7f5c055SJed Brown   TPSEvaluateFunc evalFunc = NULL;
2330b7f5c055SJed Brown   DMLabel label;
2331b7f5c055SJed Brown 
2332b7f5c055SJed Brown   PetscFunctionBegin;
2333*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
2334b7f5c055SJed Brown   PetscCheck((layers != 0) ^ (thickness == 0.), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Layers %D must be nonzero iff thickness %g is nonzero", layers, (double)thickness);
2335b7f5c055SJed Brown   switch (tpstype) {
2336b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2337b7f5c055SJed 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");
2338b7f5c055SJed Brown     if (!rank) {
2339b7f5c055SJed Brown       PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2340b7f5c055SJed Brown       PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2341b7f5c055SJed Brown       PetscReal L = 1;
2342b7f5c055SJed Brown 
2343b7f5c055SJed Brown       Npipes[0] = (extent[0] + 1) * extent[1] * extent[2];
2344b7f5c055SJed Brown       Npipes[1] = extent[0] * (extent[1] + 1) * extent[2];
2345b7f5c055SJed Brown       Npipes[2] = extent[0] * extent[1] * (extent[2] + 1);
2346b7f5c055SJed Brown       Njunctions = extent[0] * extent[1] * extent[2];
2347b7f5c055SJed Brown       Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2348b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
2349*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(3*numVertices, &vtxCoords));
2350*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(Njunctions, &cells));
2351*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(Ncuts*4, &edges));
2352*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(Ncuts*4, &edgeSets));
2353b7f5c055SJed Brown       // x-normal pipes
2354b7f5c055SJed Brown       vcount = 0;
2355b7f5c055SJed Brown       for (PetscInt i=0; i<extent[0]+1; i++) {
2356b7f5c055SJed Brown         for (PetscInt j=0; j<extent[1]; j++) {
2357b7f5c055SJed Brown           for (PetscInt k=0; k<extent[2]; k++) {
2358b7f5c055SJed Brown             for (PetscInt l=0; l<4; l++) {
2359b7f5c055SJed Brown               vtxCoords[vcount++] = (2*i - 1) * L;
2360b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2*l + 1) * PETSC_PI / 4) * L / 2;
2361b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2*l + 1) * PETSC_PI / 4) * L / 2;
2362b7f5c055SJed Brown             }
2363b7f5c055SJed Brown           }
2364b7f5c055SJed Brown         }
2365b7f5c055SJed Brown       }
2366b7f5c055SJed Brown       // y-normal pipes
2367b7f5c055SJed Brown       for (PetscInt i=0; i<extent[0]; i++) {
2368b7f5c055SJed Brown         for (PetscInt j=0; j<extent[1]+1; j++) {
2369b7f5c055SJed Brown           for (PetscInt k=0; k<extent[2]; k++) {
2370b7f5c055SJed Brown             for (PetscInt l=0; l<4; l++) {
2371b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2*l + 1) * PETSC_PI / 4) * L / 2;
2372b7f5c055SJed Brown               vtxCoords[vcount++] = (2*j - 1) * L;
2373b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2*l + 1) * PETSC_PI / 4) * L / 2;
2374b7f5c055SJed Brown             }
2375b7f5c055SJed Brown           }
2376b7f5c055SJed Brown         }
2377b7f5c055SJed Brown       }
2378b7f5c055SJed Brown       // z-normal pipes
2379b7f5c055SJed Brown       for (PetscInt i=0; i<extent[0]; i++) {
2380b7f5c055SJed Brown         for (PetscInt j=0; j<extent[1]; j++) {
2381b7f5c055SJed Brown           for (PetscInt k=0; k<extent[2]+1; k++) {
2382b7f5c055SJed Brown             for (PetscInt l=0; l<4; l++) {
2383b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2*l + 1) * PETSC_PI / 4) * L / 2;
2384b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2*l + 1) * PETSC_PI / 4) * L / 2;
2385b7f5c055SJed Brown               vtxCoords[vcount++] = (2*k - 1) * L;
2386b7f5c055SJed Brown             }
2387b7f5c055SJed Brown           }
2388b7f5c055SJed Brown         }
2389b7f5c055SJed Brown       }
2390b7f5c055SJed Brown       // junctions
2391b7f5c055SJed Brown       for (PetscInt i=0; i<extent[0]; i++) {
2392b7f5c055SJed Brown         for (PetscInt j=0; j<extent[1]; j++) {
2393b7f5c055SJed Brown           for (PetscInt k=0; k<extent[2]; k++) {
2394b7f5c055SJed Brown             const PetscInt J = (i*extent[1] + j)*extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2])*4 + J*8;
2395b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2396b7f5c055SJed Brown             for (PetscInt ii=0; ii<2; ii++) {
2397b7f5c055SJed Brown               for (PetscInt jj=0; jj<2; jj++) {
2398b7f5c055SJed Brown                 for (PetscInt kk=0; kk<2; kk++) {
2399b7f5c055SJed Brown                   double Ls = (1 - sqrt(2) / 4) * L;
2400b7f5c055SJed Brown                   vtxCoords[vcount++] = 2*i*L + (2*ii-1) * Ls;
2401b7f5c055SJed Brown                   vtxCoords[vcount++] = 2*j*L + (2*jj-1) * Ls;
2402b7f5c055SJed Brown                   vtxCoords[vcount++] = 2*k*L + (2*kk-1) * Ls;
2403b7f5c055SJed Brown                 }
2404b7f5c055SJed Brown               }
2405b7f5c055SJed Brown             }
2406b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2407b7f5c055SJed Brown               {{3,1,0,2}, {7,5,4,6}}, // x-aligned
2408b7f5c055SJed Brown               {{5,4,0,1}, {7,6,2,3}}, // y-aligned
2409b7f5c055SJed Brown               {{6,2,0,4}, {7,3,1,5}}  // z-aligned
2410b7f5c055SJed Brown             };
2411b7f5c055SJed Brown             const PetscInt pipe_lo[3] = { // vertex numbers of pipes
2412b7f5c055SJed Brown               ((i * extent[1] + j) * extent[2] + k)*4,
2413b7f5c055SJed Brown               ((i * (extent[1] + 1) + j) * extent[2] + k + Npipes[0])*4,
2414b7f5c055SJed Brown               ((i * extent[1] + j) * (extent[2]+1) + k + Npipes[0] + Npipes[1])*4
2415b7f5c055SJed Brown             };
2416b7f5c055SJed Brown             const PetscInt pipe_hi[3] = { // vertex numbers of pipes
2417b7f5c055SJed Brown               (((i + 1) * extent[1] + j) * extent[2] + k)*4,
2418b7f5c055SJed Brown               ((i * (extent[1] + 1) + j + 1) * extent[2] + k + Npipes[0])*4,
2419b7f5c055SJed Brown               ((i * extent[1] + j) * (extent[2]+1) + k + 1 + Npipes[0] + Npipes[1])*4
2420b7f5c055SJed Brown             };
2421b7f5c055SJed Brown             for (PetscInt dir=0; dir<3; dir++) { // x,y,z
2422b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2423b7f5c055SJed Brown               for (PetscInt l=0; l<4; l++) { // rotations
2424b7f5c055SJed Brown                 cells[J][dir*2+0][l][0] = pipe_lo[dir] + l;
2425b7f5c055SJed Brown                 cells[J][dir*2+0][l][1] = Jvoff + jfaces[dir][0][l];
2426b7f5c055SJed Brown                 cells[J][dir*2+0][l][2] = Jvoff + jfaces[dir][0][(l-1+4)%4];
2427b7f5c055SJed Brown                 cells[J][dir*2+0][l][3] = pipe_lo[dir] + (l-1+4)%4;
2428b7f5c055SJed Brown                 cells[J][dir*2+1][l][0] = Jvoff + jfaces[dir][1][l];
2429b7f5c055SJed Brown                 cells[J][dir*2+1][l][1] = pipe_hi[dir] + l;
2430b7f5c055SJed Brown                 cells[J][dir*2+1][l][2] = pipe_hi[dir] + (l-1+4)%4;
2431b7f5c055SJed Brown                 cells[J][dir*2+1][l][3] = Jvoff + jfaces[dir][1][(l-1+4)%4];
2432b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2433b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2434b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l+1) % 4;
2435b7f5c055SJed Brown                   edgeSets[numEdges] = dir*2 + 1;
2436b7f5c055SJed Brown                   numEdges++;
2437b7f5c055SJed Brown                 }
2438b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2439b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2440b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l+1) % 4;
2441b7f5c055SJed Brown                   edgeSets[numEdges] = dir*2 + 2;
2442b7f5c055SJed Brown                   numEdges++;
2443b7f5c055SJed Brown                 }
2444b7f5c055SJed Brown               }
2445b7f5c055SJed Brown             }
2446b7f5c055SJed Brown           }
2447b7f5c055SJed Brown         }
2448b7f5c055SJed Brown       }
2449b7f5c055SJed Brown       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %D incompatible with number of cuts %D", numEdges, Ncuts);
2450b7f5c055SJed Brown       numFaces = 24 * Njunctions;
2451b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2452b7f5c055SJed Brown     }
2453b7f5c055SJed Brown     evalFunc = TPSEvaluate_SchwarzP;
2454b7f5c055SJed Brown     break;
2455b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2456b7f5c055SJed Brown     if (!rank) {
2457b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2458b7f5c055SJed Brown       //
2459b7f5c055SJed 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)
2460b7f5c055SJed Brown       //
2461b7f5c055SJed Brown       // on the cell [0,2]^3.
2462b7f5c055SJed Brown       //
2463b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2464b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2465b7f5c055SJed Brown       // like a boomerang:
2466b7f5c055SJed Brown       //
2467b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2468b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2469b7f5c055SJed Brown       //                                                              //
2470b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2471b7f5c055SJed Brown       //      \                                   /            \      //
2472b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2473b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2474b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2475b7f5c055SJed Brown       //                                                              //
2476b7f5c055SJed Brown       //                                                              //
2477b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2478b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2479b7f5c055SJed Brown       //                                                              //
2480b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2481b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2482b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2483b7f5c055SJed Brown       //            \                       /                \        //
2484b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2485b7f5c055SJed Brown       //
2486b7f5c055SJed Brown       //
2487b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2488b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2489b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2490b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2491b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2492b7f5c055SJed Brown       //
2493b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2494b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2495b7f5c055SJed Brown       //
2496b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2497b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2498b7f5c055SJed Brown 
2499b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
2500b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
2501b7f5c055SJed Brown       PetscInt extentPlus[3];
2502b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
2503b7f5c055SJed Brown       const PetscInt A =  0,   B =  1,   C =  2,   D =  3,   E =  4,   F =  5,   G =  6,   H =  7,
2504b7f5c055SJed Brown         II =  8,   J =  9,   K = 10,   L = 11,   M = 12,   N = 13,   O = 14,   P = 15,
2505b7f5c055SJed Brown         Q = 16,   R = 17,   S = 18,   T = 19,   U = 20,   V = 21,   W = 22,   X = 23,
2506b7f5c055SJed Brown         Y = 24,   Z = 25,  Ap = 26,  Bp = 27,  Cp = 28,  Dp = 29,  Ep = 30,  Fp = 31,
2507b7f5c055SJed Brown         Gp = 32,  Hp = 33,  Ip = 34,  Jp = 35,  Kp = 36,  Lp = 37,  Mp = 38,  Np = 39,
2508b7f5c055SJed Brown         Op = 40,  Pp = 41,  Qp = 42,  Rp = 43,  Sp = 44,  Tp = 45,  Up = 46,  Vp = 47,
2509b7f5c055SJed Brown         Wp = 48,  Xp = 49,  Yp = 50,  Zp = 51,  Aq = 52,  Bq = 53,  Cq = 54,  Dq = 55;
2510b7f5c055SJed Brown       const PetscInt pattern[64][4] =
2511b7f5c055SJed Brown         { /* face to vertex within the coarse discretization of a single gyroid block */
2512b7f5c055SJed Brown           /* layer 0 */
2513b7f5c055SJed Brown           {A,C,K,G},{C,B,II,K},{D,A,H,L},{B+56*1,D,L,J},{E,B+56*1,J,N},{A+56*2,E,N,H+56*2},{F,A+56*2,G+56*2,M},{B,F,M,II},
2514b7f5c055SJed Brown           /* layer 1 */
2515b7f5c055SJed Brown           {G,K,Q,O},{K,II,P,Q},{L,H,O+56*1,R},{J,L,R,P},{N,J,P,S},{H+56*2,N,S,O+56*3},{M,G+56*2,O+56*2,T},{II,M,T,P},
2516b7f5c055SJed Brown           /* layer 2 */
2517b7f5c055SJed Brown           {O,Q,Y,U},{Q,P,W,Y},{R,O+56*1,U+56*1,Ap},{P,R,Ap,W},{S,P,X,Bp},{O+56*3,S,Bp,V+56*1},{T,O+56*2,V,Z},{P,T,Z,X},
2518b7f5c055SJed Brown           /* layer 3 */
2519b7f5c055SJed Brown           {U,Y,Ep,Dp},{Y,W,Cp,Ep},{Ap,U+56*1,Dp+56*1,Gp},{W,Ap,Gp,Cp},{Bp,X,Cp+56*2,Fp},{V+56*1,Bp,Fp,Dp+56*1},{Z,V,Dp,Hp},{X,Z,Hp,Cp+56*2},
2520b7f5c055SJed Brown           /* layer 4 */
2521b7f5c055SJed Brown           {Dp,Ep,Mp,Kp},{Ep,Cp,Ip,Mp},{Gp,Dp+56*1,Lp,Np},{Cp,Gp,Np,Jp},{Fp,Cp+56*2,Jp+56*2,Pp},{Dp+56*1,Fp,Pp,Lp},{Hp,Dp,Kp,Op},{Cp+56*2,Hp,Op,Ip+56*2},
2522b7f5c055SJed Brown           /* layer 5 */
2523b7f5c055SJed Brown           {Kp,Mp,Sp,Rp},{Mp,Ip,Qp,Sp},{Np,Lp,Rp,Tp},{Jp,Np,Tp,Qp+56*1},{Pp,Jp+56*2,Qp+56*3,Up},{Lp,Pp,Up,Rp},{Op,Kp,Rp,Vp},{Ip+56*2,Op,Vp,Qp+56*2},
2524b7f5c055SJed Brown           /* layer 6 */
2525b7f5c055SJed Brown           {Rp,Sp,Aq,Yp},{Sp,Qp,Wp,Aq},{Tp,Rp,Yp,Cq},{Qp+56*1,Tp,Cq,Wp+56*1},{Up,Qp+56*3,Xp+56*1,Dq},{Rp,Up,Dq,Zp},{Vp,Rp,Zp,Bq},{Qp+56*2,Vp,Bq,Xp},
2526b7f5c055SJed Brown           /* layer 7 (the top is the periodic image of the bottom of layer 0) */
2527b7f5c055SJed Brown           {Yp,Aq,C+56*4,A+56*4},{Aq,Wp,B+56*4,C+56*4},{Cq,Yp,A+56*4,D+56*4},{Wp+56*1,Cq,D+56*4,B+56*5},{Dq,Xp+56*1,B+56*5,E+56*4},{Zp,Dq,E+56*4,A+56*6},{Bq,Zp,A+56*6,F+56*4},{Xp,Bq,F+56*4,B+56*4}
2528b7f5c055SJed Brown         };
2529b7f5c055SJed Brown       const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.)-1.) / PetscSqrtReal(2.)) / PETSC_PI;
2530b7f5c055SJed Brown       const PetscReal patternCoords[56][3] =
2531b7f5c055SJed Brown         {
2532b7f5c055SJed Brown           /* A  */ {1.,0.,0.},
2533b7f5c055SJed Brown           /* B  */ {0.,1.,0.},
2534b7f5c055SJed Brown           /* C  */ {gamma,gamma,0.},
2535b7f5c055SJed Brown           /* D  */ {1+gamma,1-gamma,0.},
2536b7f5c055SJed Brown           /* E  */ {2-gamma,2-gamma,0.},
2537b7f5c055SJed Brown           /* F  */ {1-gamma,1+gamma,0.},
2538b7f5c055SJed Brown 
2539b7f5c055SJed Brown           /* G  */ {.5,0,.25},
2540b7f5c055SJed Brown           /* H  */ {1.5,0.,.25},
2541b7f5c055SJed Brown           /* II */ {.5,1.,.25},
2542b7f5c055SJed Brown           /* J  */ {1.5,1.,.25},
2543b7f5c055SJed Brown           /* K  */ {.25,.5,.25},
2544b7f5c055SJed Brown           /* L  */ {1.25,.5,.25},
2545b7f5c055SJed Brown           /* M  */ {.75,1.5,.25},
2546b7f5c055SJed Brown           /* N  */ {1.75,1.5,.25},
2547b7f5c055SJed Brown 
2548b7f5c055SJed Brown           /* O  */ {0.,0.,.5},
2549b7f5c055SJed Brown           /* P  */ {1.,1.,.5},
2550b7f5c055SJed Brown           /* Q  */ {gamma,1-gamma,.5},
2551b7f5c055SJed Brown           /* R  */ {1+gamma,gamma,.5},
2552b7f5c055SJed Brown           /* S  */ {2-gamma,1+gamma,.5},
2553b7f5c055SJed Brown           /* T  */ {1-gamma,2-gamma,.5},
2554b7f5c055SJed Brown 
2555b7f5c055SJed Brown           /* U  */ {0.,.5,.75},
2556b7f5c055SJed Brown           /* V  */ {0.,1.5,.75},
2557b7f5c055SJed Brown           /* W  */ {1.,.5,.75},
2558b7f5c055SJed Brown           /* X  */ {1.,1.5,.75},
2559b7f5c055SJed Brown           /* Y  */ {.5,.75,.75},
2560b7f5c055SJed Brown           /* Z  */ {.5,1.75,.75},
2561b7f5c055SJed Brown           /* Ap */ {1.5,.25,.75},
2562b7f5c055SJed Brown           /* Bp */ {1.5,1.25,.75},
2563b7f5c055SJed Brown 
2564b7f5c055SJed Brown           /* Cp */ {1.,0.,1.},
2565b7f5c055SJed Brown           /* Dp */ {0.,1.,1.},
2566b7f5c055SJed Brown           /* Ep */ {1-gamma,1-gamma,1.},
2567b7f5c055SJed Brown           /* Fp */ {1+gamma,1+gamma,1.},
2568b7f5c055SJed Brown           /* Gp */ {2-gamma,gamma,1.},
2569b7f5c055SJed Brown           /* Hp */ {gamma,2-gamma,1.},
2570b7f5c055SJed Brown 
2571b7f5c055SJed Brown           /* Ip */ {.5,0.,1.25},
2572b7f5c055SJed Brown           /* Jp */ {1.5,0.,1.25},
2573b7f5c055SJed Brown           /* Kp */ {.5,1.,1.25},
2574b7f5c055SJed Brown           /* Lp */ {1.5,1.,1.25},
2575b7f5c055SJed Brown           /* Mp */ {.75,.5,1.25},
2576b7f5c055SJed Brown           /* Np */ {1.75,.5,1.25},
2577b7f5c055SJed Brown           /* Op */ {.25,1.5,1.25},
2578b7f5c055SJed Brown           /* Pp */ {1.25,1.5,1.25},
2579b7f5c055SJed Brown 
2580b7f5c055SJed Brown           /* Qp */ {0.,0.,1.5},
2581b7f5c055SJed Brown           /* Rp */ {1.,1.,1.5},
2582b7f5c055SJed Brown           /* Sp */ {1-gamma,gamma,1.5},
2583b7f5c055SJed Brown           /* Tp */ {2-gamma,1-gamma,1.5},
2584b7f5c055SJed Brown           /* Up */ {1+gamma,2-gamma,1.5},
2585b7f5c055SJed Brown           /* Vp */ {gamma,1+gamma,1.5},
2586b7f5c055SJed Brown 
2587b7f5c055SJed Brown           /* Wp */ {0.,.5,1.75},
2588b7f5c055SJed Brown           /* Xp */ {0.,1.5,1.75},
2589b7f5c055SJed Brown           /* Yp */ {1.,.5,1.75},
2590b7f5c055SJed Brown           /* Zp */ {1.,1.5,1.75},
2591b7f5c055SJed Brown           /* Aq */ {.5,.25,1.75},
2592b7f5c055SJed Brown           /* Bq */ {.5,1.25,1.75},
2593b7f5c055SJed Brown           /* Cq */ {1.5,.75,1.75},
2594b7f5c055SJed Brown           /* Dq */ {1.5,1.75,1.75},
2595b7f5c055SJed Brown         };
2596b7f5c055SJed Brown       PetscInt  (*cells)[64][4] = NULL;
2597b7f5c055SJed Brown       PetscBool *seen;
2598b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
2599b7f5c055SJed Brown       PetscInt  count;
2600b7f5c055SJed Brown 
2601b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i]  = extent[i] + 1;
2602b7f5c055SJed Brown       numBlocks = 1;
2603b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++)     numBlocks *= extent[i];
2604b7f5c055SJed Brown       numBlocksPlus = 1;
2605b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
2606b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
2607*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numBlocks, &cells));
2608*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(numBlocksPlus * vertsPerBlock,&seen));
2609b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
2610b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2611b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
2612b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
2613b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
2614b7f5c055SJed Brown                 PetscInt vertRaw = pattern[f][v];
2615b7f5c055SJed Brown                 PetscInt blockidx = vertRaw / 56;
2616b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
2617b7f5c055SJed Brown                 PetscInt xplus = (blockidx & 1);
2618b7f5c055SJed Brown                 PetscInt yplus = (blockidx & 2) >> 1;
2619b7f5c055SJed Brown                 PetscInt zplus = (blockidx & 4) >> 2;
2620b7f5c055SJed Brown                 PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
2621b7f5c055SJed Brown                 PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
2622b7f5c055SJed Brown                 PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
2623b7f5c055SJed Brown                 PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
2624b7f5c055SJed Brown 
2625b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
2626b7f5c055SJed Brown                 seen[vert] = PETSC_TRUE;
2627b7f5c055SJed Brown               }
2628b7f5c055SJed Brown             }
2629b7f5c055SJed Brown           }
2630b7f5c055SJed Brown         }
2631b7f5c055SJed Brown       }
2632b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) if (seen[i]) numVertices++;
2633b7f5c055SJed Brown       count = 0;
2634*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
2635*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numVertices * 3, &vtxCoords));
2636b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
2637b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
2638b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
2639b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
2640b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
2641b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
2642b7f5c055SJed Brown 
2643b7f5c055SJed Brown               if (seen[vIdx]) {
2644b7f5c055SJed Brown                 PetscInt thisVert;
2645b7f5c055SJed Brown 
2646b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
2647b7f5c055SJed Brown 
2648b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
2649b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
2650b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
2651b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
2652b7f5c055SJed Brown               }
2653b7f5c055SJed Brown             }
2654b7f5c055SJed Brown           }
2655b7f5c055SJed Brown         }
2656b7f5c055SJed Brown       }
2657b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
2658b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
2659b7f5c055SJed Brown           for (PetscInt v = 0; v < 4; v++) {
2660b7f5c055SJed Brown             cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
2661b7f5c055SJed Brown           }
2662b7f5c055SJed Brown         }
2663b7f5c055SJed Brown       }
2664*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(vertToTrueVert));
2665*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(seen));
2666b7f5c055SJed Brown       cells_flat = cells[0][0];
2667b7f5c055SJed Brown       numEdges = 0;
2668b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
2669b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
2670b7f5c055SJed Brown           PetscInt ev[] = {cells_flat[i*4 + e], cells_flat[i*4 + ((e+1)%4)]};
2671b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3*ev[0]], &vtxCoords[3*ev[1]]};
2672b7f5c055SJed Brown 
2673b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
2674b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
2675b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
2676b7f5c055SJed Brown               if (evCoords[0][d] == 2.*extent[d] && evCoords[1][d] == 2.*extent[d]) numEdges++;
2677b7f5c055SJed Brown             }
2678b7f5c055SJed Brown           }
2679b7f5c055SJed Brown         }
2680b7f5c055SJed Brown       }
2681*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numEdges, &edges));
2682*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numEdges, &edgeSets));
2683b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
2684b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
2685b7f5c055SJed Brown           PetscInt ev[] = {cells_flat[i*4 + e], cells_flat[i*4 + ((e+1)%4)]};
2686b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3*ev[0]], &vtxCoords[3*ev[1]]};
2687b7f5c055SJed Brown 
2688b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
2689b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
2690b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
2691b7f5c055SJed Brown                 edges[edge][0] = ev[0];
2692b7f5c055SJed Brown                 edges[edge][1] = ev[1];
2693b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
2694b7f5c055SJed Brown               }
2695b7f5c055SJed Brown               if (evCoords[0][d] == 2.*extent[d] && evCoords[1][d] == 2.*extent[d]) {
2696b7f5c055SJed Brown                 edges[edge][0] = ev[0];
2697b7f5c055SJed Brown                 edges[edge][1] = ev[1];
2698b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
2699b7f5c055SJed Brown               }
2700b7f5c055SJed Brown             }
2701b7f5c055SJed Brown           }
2702b7f5c055SJed Brown         }
2703b7f5c055SJed Brown       }
2704b7f5c055SJed Brown     }
2705b7f5c055SJed Brown     evalFunc = TPSEvaluate_Gyroid;
2706b7f5c055SJed Brown     break;
2707b7f5c055SJed Brown   }
2708b7f5c055SJed Brown 
2709*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dm, topoDim));
2710*5f80ce2aSJacob Faibussowitsch   if (!rank) CHKERRQ(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
2711*5f80ce2aSJacob Faibussowitsch   else       CHKERRQ(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
2712*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(cells_flat));
2713b7f5c055SJed Brown   {
2714b7f5c055SJed Brown     DM idm;
2715*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(dm, &idm));
2716*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &idm));
2717b7f5c055SJed Brown   }
2718*5f80ce2aSJacob Faibussowitsch   if (!rank) CHKERRQ(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
2719*5f80ce2aSJacob Faibussowitsch   else       CHKERRQ(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
2720*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(vtxCoords));
2721b7f5c055SJed Brown 
2722*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, "Face Sets"));
2723*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLabel(dm, "Face Sets", &label));
2724b7f5c055SJed Brown   for (PetscInt e=0; e<numEdges; e++) {
2725b7f5c055SJed Brown     PetscInt njoin;
2726b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
2727*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
2728b7f5c055SJed Brown     PetscCheck(njoin == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected unique join of vertices %D and %D", edges[e][0], edges[e][1]);
2729*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelSetValue(label, join[0], edgeSets[e]));
2730*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
2731b7f5c055SJed Brown   }
2732*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(edges));
2733*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(edgeSets));
27341436d7faSJed Brown   if (tps_distribute) {
27351436d7faSJed Brown     DM               pdm = NULL;
27361436d7faSJed Brown     PetscPartitioner part;
27371436d7faSJed Brown 
2738*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetPartitioner(dm, &part));
2739*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPartitionerSetFromOptions(part));
2740*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexDistribute(dm, 0, NULL, &pdm));
27411436d7faSJed Brown     if (pdm) {
2742*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &pdm));
27431436d7faSJed Brown     }
27441436d7faSJed Brown     // Do not auto-distribute again
2745*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
27461436d7faSJed Brown   }
2747b7f5c055SJed Brown 
2748*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
2749b7f5c055SJed Brown   for (PetscInt refine=0; refine<refinements; refine++) {
2750b7f5c055SJed Brown     PetscInt m;
2751b7f5c055SJed Brown     DM dmf;
2752b7f5c055SJed Brown     Vec X;
2753b7f5c055SJed Brown     PetscScalar *x;
2754*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRefine(dm, MPI_COMM_NULL, &dmf));
2755*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &dmf));
2756b7f5c055SJed Brown 
2757*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinatesLocal(dm, &X));
2758*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(X, &m));
2759*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(X, &x));
2760b7f5c055SJed Brown     for (PetscInt i=0; i<m; i+=3) {
2761*5f80ce2aSJacob Faibussowitsch       CHKERRQ(TPSNearestPoint(evalFunc, &x[i]));
2762b7f5c055SJed Brown     }
2763*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(X, &x));
2764b7f5c055SJed Brown   }
2765b7f5c055SJed Brown 
2766b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
2767*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLabel(dm, "Face Sets", &label));
2768*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexLabelComplete(dm, label));
2769b7f5c055SJed Brown 
2770b7f5c055SJed Brown   if (thickness > 0) {
2771b7f5c055SJed Brown     DM dm3;
2772*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexExtrude(dm, layers, thickness, PETSC_FALSE, PETSC_TRUE, NULL, NULL, &dm3));
2773*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &dm3));
2774b7f5c055SJed Brown   }
2775b7f5c055SJed Brown   PetscFunctionReturn(0);
2776b7f5c055SJed Brown }
2777b7f5c055SJed Brown 
2778b7f5c055SJed Brown /*@
2779b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
2780b7f5c055SJed Brown 
2781b7f5c055SJed Brown   Collective
2782b7f5c055SJed Brown 
2783b7f5c055SJed Brown   Input Parameters:
2784b7f5c055SJed Brown + comm   - The communicator for the DM object
2785b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
2786b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
2787b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
27881436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
2789817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
27901436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
2791817da375SSatish Balay - thickness - Thickness in normal direction
2792b7f5c055SJed Brown 
2793b7f5c055SJed Brown   Output Parameter:
2794b7f5c055SJed Brown . dm  - The DM object
2795b7f5c055SJed Brown 
2796b7f5c055SJed Brown   Notes:
2797b7f5c055SJed 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.
2798b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
2799b7f5c055SJed 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.
2800b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
2801b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
2802b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
2803b7f5c055SJed Brown 
2804b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
2805b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
2806b7f5c055SJed Brown 
2807b7f5c055SJed Brown   References:
2808606c0280SSatish Balay . * - Maskery et al, Insights into the mechanical properties of several triply periodic minimal surface lattice structures made by polymer additive manufacturing, 2017. https://doi.org/10.1016/j.polymer.2017.11.049
2809b7f5c055SJed Brown 
2810b7f5c055SJed Brown   Developer Notes:
2811b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
2812b7f5c055SJed Brown 
2813b7f5c055SJed Brown   Level: beginner
2814b7f5c055SJed Brown 
2815b7f5c055SJed Brown .seealso: DMPlexCreateSphereMesh(), DMSetType(), DMCreate()
2816b7f5c055SJed Brown @*/
28171436d7faSJed Brown PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm)
2818b7f5c055SJed Brown {
2819b7f5c055SJed Brown   PetscFunctionBegin;
2820*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
2821*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
2822*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
2823b7f5c055SJed Brown   PetscFunctionReturn(0);
2824b7f5c055SJed Brown }
2825b7f5c055SJed Brown 
28269318fe57SMatthew G. Knepley /*@
28279318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
28289318fe57SMatthew G. Knepley 
28299318fe57SMatthew G. Knepley   Collective
28309318fe57SMatthew G. Knepley 
28319318fe57SMatthew G. Knepley   Input Parameters:
28329318fe57SMatthew G. Knepley + comm    - The communicator for the DM object
28339318fe57SMatthew G. Knepley . dim     - The dimension
28349318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
28359318fe57SMatthew G. Knepley - R       - The radius
28369318fe57SMatthew G. Knepley 
28379318fe57SMatthew G. Knepley   Output Parameter:
28389318fe57SMatthew G. Knepley . dm  - The DM object
28399318fe57SMatthew G. Knepley 
28409318fe57SMatthew G. Knepley   Level: beginner
28419318fe57SMatthew G. Knepley 
28429318fe57SMatthew G. Knepley .seealso: DMPlexCreateBallMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate()
28439318fe57SMatthew G. Knepley @*/
28449318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
28459318fe57SMatthew G. Knepley {
28469318fe57SMatthew G. Knepley   PetscFunctionBegin;
28479318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
2848*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
2849*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
2850*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
28519318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
28529318fe57SMatthew G. Knepley }
28539318fe57SMatthew G. Knepley 
28549318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
28559318fe57SMatthew G. Knepley {
28569318fe57SMatthew G. Knepley   DM             sdm, vol;
28579318fe57SMatthew G. Knepley   DMLabel        bdlabel;
28589318fe57SMatthew G. Knepley 
28599318fe57SMatthew G. Knepley   PetscFunctionBegin;
2860*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(PetscObjectComm((PetscObject) dm), &sdm));
2861*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(sdm, DMPLEX));
2862*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) sdm, "bd_"));
2863*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateSphereMesh_Internal(sdm, dim-1, PETSC_TRUE, R));
2864*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(sdm));
2865*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(sdm, NULL, "-dm_view"));
2866*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
2867*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&sdm));
2868*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexReplace_Static(dm, &vol));
2869*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, "marker"));
2870*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLabel(dm, "marker", &bdlabel));
2871*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
2872*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexLabelComplete(dm, bdlabel));
287351a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
287451a74b61SMatthew G. Knepley }
287551a74b61SMatthew G. Knepley 
287651a74b61SMatthew G. Knepley /*@
287751a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
287851a74b61SMatthew G. Knepley 
287951a74b61SMatthew G. Knepley   Collective
288051a74b61SMatthew G. Knepley 
288151a74b61SMatthew G. Knepley   Input Parameters:
288251a74b61SMatthew G. Knepley + comm  - The communicator for the DM object
288351a74b61SMatthew G. Knepley . dim   - The dimension
288451a74b61SMatthew G. Knepley - R     - The radius
288551a74b61SMatthew G. Knepley 
288651a74b61SMatthew G. Knepley   Output Parameter:
288751a74b61SMatthew G. Knepley . dm  - The DM object
288851a74b61SMatthew G. Knepley 
288951a74b61SMatthew G. Knepley   Options Database Keys:
289051a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
289151a74b61SMatthew G. Knepley 
289251a74b61SMatthew G. Knepley   Level: beginner
289351a74b61SMatthew G. Knepley 
289451a74b61SMatthew G. Knepley .seealso: DMPlexCreateSphereMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate()
289551a74b61SMatthew G. Knepley @*/
289651a74b61SMatthew G. Knepley PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
289751a74b61SMatthew G. Knepley {
289851a74b61SMatthew G. Knepley   PetscFunctionBegin;
2899*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
2900*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
2901*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateBallMesh_Internal(*dm, dim, R));
29022829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
29032829fed8SMatthew G. Knepley }
29042829fed8SMatthew G. Knepley 
29059318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
29060a6ba040SMatthew G. Knepley {
29070a6ba040SMatthew G. Knepley   PetscFunctionBegin;
29089318fe57SMatthew G. Knepley   switch (ct) {
29099318fe57SMatthew G. Knepley     case DM_POLYTOPE_POINT:
29109318fe57SMatthew G. Knepley     {
29119318fe57SMatthew G. Knepley       PetscInt    numPoints[1]        = {1};
29129318fe57SMatthew G. Knepley       PetscInt    coneSize[1]         = {0};
29139318fe57SMatthew G. Knepley       PetscInt    cones[1]            = {0};
29149318fe57SMatthew G. Knepley       PetscInt    coneOrientations[1] = {0};
29159318fe57SMatthew G. Knepley       PetscScalar vertexCoords[1]     = {0.0};
29169318fe57SMatthew G. Knepley 
2917*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 0));
2918*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
29199318fe57SMatthew G. Knepley     }
29209318fe57SMatthew G. Knepley     break;
29219318fe57SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
29229318fe57SMatthew G. Knepley     {
29239318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {2, 1};
29249318fe57SMatthew G. Knepley       PetscInt    coneSize[3]         = {2, 0, 0};
29259318fe57SMatthew G. Knepley       PetscInt    cones[2]            = {1, 2};
29269318fe57SMatthew G. Knepley       PetscInt    coneOrientations[2] = {0, 0};
29279318fe57SMatthew G. Knepley       PetscScalar vertexCoords[2]     = {-1.0,  1.0};
29289318fe57SMatthew G. Knepley 
2929*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 1));
2930*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
29319318fe57SMatthew G. Knepley     }
29329318fe57SMatthew G. Knepley     break;
2933b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
2934b5a892a1SMatthew G. Knepley     {
2935b5a892a1SMatthew G. Knepley       PetscInt    numPoints[2]        = {2, 1};
2936b5a892a1SMatthew G. Knepley       PetscInt    coneSize[3]         = {2, 0, 0};
2937b5a892a1SMatthew G. Knepley       PetscInt    cones[2]            = {1, 2};
2938b5a892a1SMatthew G. Knepley       PetscInt    coneOrientations[2] = {0, 0};
2939b5a892a1SMatthew G. Knepley       PetscScalar vertexCoords[2]     = {-1.0,  1.0};
2940b5a892a1SMatthew G. Knepley 
2941*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 1));
2942*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2943b5a892a1SMatthew G. Knepley     }
2944b5a892a1SMatthew G. Knepley     break;
29459318fe57SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
29469318fe57SMatthew G. Knepley     {
29479318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {3, 1};
29489318fe57SMatthew G. Knepley       PetscInt    coneSize[4]         = {3, 0, 0, 0};
29499318fe57SMatthew G. Knepley       PetscInt    cones[3]            = {1, 2, 3};
29509318fe57SMatthew G. Knepley       PetscInt    coneOrientations[3] = {0, 0, 0};
29519318fe57SMatthew G. Knepley       PetscScalar vertexCoords[6]     = {-1.0, -1.0,  1.0, -1.0,  -1.0, 1.0};
29529318fe57SMatthew G. Knepley 
2953*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 2));
2954*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
29559318fe57SMatthew G. Knepley     }
29569318fe57SMatthew G. Knepley     break;
29579318fe57SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
29589318fe57SMatthew G. Knepley     {
29599318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {4, 1};
29609318fe57SMatthew G. Knepley       PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
29619318fe57SMatthew G. Knepley       PetscInt    cones[4]            = {1, 2, 3, 4};
29629318fe57SMatthew G. Knepley       PetscInt    coneOrientations[4] = {0, 0, 0, 0};
29639318fe57SMatthew G. Knepley       PetscScalar vertexCoords[8]     = {-1.0, -1.0,  1.0, -1.0,  1.0, 1.0,  -1.0, 1.0};
29649318fe57SMatthew G. Knepley 
2965*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 2));
2966*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
29679318fe57SMatthew G. Knepley     }
29689318fe57SMatthew G. Knepley     break;
29699318fe57SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
29709318fe57SMatthew G. Knepley     {
29719318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {4, 1};
29729318fe57SMatthew G. Knepley       PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
29739318fe57SMatthew G. Knepley       PetscInt    cones[4]            = {1, 2, 3, 4};
29749318fe57SMatthew G. Knepley       PetscInt    coneOrientations[4] = {0, 0, 0, 0};
29759318fe57SMatthew G. Knepley       PetscScalar vertexCoords[8]     = {-1.0, -1.0,  1.0, -1.0,  -1.0, 1.0,  1.0, 1.0};
29769318fe57SMatthew G. Knepley 
2977*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 2));
2978*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
29799318fe57SMatthew G. Knepley     }
29809318fe57SMatthew G. Knepley     break;
29819318fe57SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
29829318fe57SMatthew G. Knepley     {
29839318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {4, 1};
29849318fe57SMatthew G. Knepley       PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
2985f0edb160SMatthew G. Knepley       PetscInt    cones[4]            = {1, 2, 3, 4};
29869318fe57SMatthew G. Knepley       PetscInt    coneOrientations[4] = {0, 0, 0, 0};
2987f0edb160SMatthew 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};
29889318fe57SMatthew G. Knepley 
2989*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 3));
2990*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
29919318fe57SMatthew G. Knepley     }
29929318fe57SMatthew G. Knepley     break;
29939318fe57SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
29949318fe57SMatthew G. Knepley     {
29959318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {8, 1};
29969318fe57SMatthew G. Knepley       PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
2997f0edb160SMatthew G. Knepley       PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
29989318fe57SMatthew G. Knepley       PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2999f0edb160SMatthew G. Knepley       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,
30009318fe57SMatthew G. Knepley                                          -1.0, -1.0,  1.0,   1.0, -1.0,  1.0,  1.0, 1.0,  1.0,  -1.0,  1.0,  1.0};
30019318fe57SMatthew G. Knepley 
3002*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 3));
3003*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
30049318fe57SMatthew G. Knepley     }
30059318fe57SMatthew G. Knepley     break;
30069318fe57SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
30079318fe57SMatthew G. Knepley     {
30089318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {6, 1};
30099318fe57SMatthew G. Knepley       PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3010f0edb160SMatthew G. Knepley       PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
30119318fe57SMatthew G. Knepley       PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
3012f0edb160SMatthew G. Knepley       PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0, -1.0,  1.0, -1.0,   1.0, -1.0, -1.0,
30139318fe57SMatthew G. Knepley                                          -1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  -1.0,  1.0,  1.0};
30149318fe57SMatthew G. Knepley 
3015*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 3));
3016*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
30179318fe57SMatthew G. Knepley     }
30189318fe57SMatthew G. Knepley     break;
30199318fe57SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
30209318fe57SMatthew G. Knepley     {
30219318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {6, 1};
30229318fe57SMatthew G. Knepley       PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
30239318fe57SMatthew G. Knepley       PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
30249318fe57SMatthew G. Knepley       PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
30259318fe57SMatthew G. Knepley       PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0,  1.0, -1.0, -1.0,  -1.0, 1.0, -1.0,
30269318fe57SMatthew G. Knepley                                          -1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  -1.0, 1.0,  1.0};
30279318fe57SMatthew G. Knepley 
3028*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 3));
3029*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
30309318fe57SMatthew G. Knepley     }
30319318fe57SMatthew G. Knepley     break;
30329318fe57SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
30339318fe57SMatthew G. Knepley     {
30349318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {8, 1};
30359318fe57SMatthew G. Knepley       PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
30369318fe57SMatthew G. Knepley       PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
30379318fe57SMatthew G. Knepley       PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
30389318fe57SMatthew G. Knepley       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,
30399318fe57SMatthew G. Knepley                                          -1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  1.0, 1.0,  1.0,  -1.0, 1.0,  1.0};
30409318fe57SMatthew G. Knepley 
3041*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 3));
3042*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
30439318fe57SMatthew G. Knepley     }
30449318fe57SMatthew G. Knepley     break;
30459318fe57SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
30469318fe57SMatthew G. Knepley     {
30479318fe57SMatthew G. Knepley       PetscInt    numPoints[2]        = {5, 1};
30489318fe57SMatthew G. Knepley       PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3049f0edb160SMatthew G. Knepley       PetscInt    cones[5]            = {1, 2, 3, 4, 5};
30509318fe57SMatthew G. Knepley       PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3051f0edb160SMatthew G. Knepley       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,
30529318fe57SMatthew G. Knepley                                           0.0,  0.0,  1.0};
30539318fe57SMatthew G. Knepley 
3054*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetDimension(rdm, 3));
3055*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
30569318fe57SMatthew G. Knepley     }
30579318fe57SMatthew G. Knepley     break;
305898921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject) rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
30599318fe57SMatthew G. Knepley   }
30609318fe57SMatthew G. Knepley   {
30619318fe57SMatthew G. Knepley     PetscInt Nv, v;
30629318fe57SMatthew G. Knepley 
30639318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
3064*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateLabel(rdm, "celltype"));
3065*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCellType(rdm, 0, ct));
3066*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(rdm, NULL, &Nv));
3067*5f80ce2aSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) CHKERRQ(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
30689318fe57SMatthew G. Knepley   }
3069*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexInterpolateInPlace_Internal(rdm));
3070*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) rdm, DMPolytopeTypes[ct]));
30710a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
30720a6ba040SMatthew G. Knepley }
30730a6ba040SMatthew G. Knepley 
30749318fe57SMatthew G. Knepley /*@
30759318fe57SMatthew G. Knepley   DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell
30769318fe57SMatthew G. Knepley 
30779318fe57SMatthew G. Knepley   Collective
30789318fe57SMatthew G. Knepley 
30799318fe57SMatthew G. Knepley   Input Parameters:
30809318fe57SMatthew G. Knepley + comm - The communicator
30819318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
30829318fe57SMatthew G. Knepley 
30839318fe57SMatthew G. Knepley   Output Parameter:
30849318fe57SMatthew G. Knepley . refdm - The reference cell
30859318fe57SMatthew G. Knepley 
30869318fe57SMatthew G. Knepley   Level: intermediate
30879318fe57SMatthew G. Knepley 
30889318fe57SMatthew G. Knepley .seealso: DMPlexCreateReferenceCell(), DMPlexCreateBoxMesh()
30899318fe57SMatthew G. Knepley @*/
30909318fe57SMatthew G. Knepley PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
30910a6ba040SMatthew G. Knepley {
30920a6ba040SMatthew G. Knepley   PetscFunctionBegin;
3093*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, refdm));
3094*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*refdm, DMPLEX));
3095*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateReferenceCell_Internal(*refdm, ct));
30969318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
30979318fe57SMatthew G. Knepley }
309879a015ccSMatthew G. Knepley 
30999318fe57SMatthew G. Knepley static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
31009318fe57SMatthew G. Knepley {
31019318fe57SMatthew G. Knepley   DM             plex;
31029318fe57SMatthew G. Knepley   DMLabel        label;
31039318fe57SMatthew G. Knepley   PetscBool      hasLabel;
31040a6ba040SMatthew G. Knepley 
31059318fe57SMatthew G. Knepley   PetscFunctionBeginUser;
3106*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMHasLabel(dm, name, &hasLabel));
31079318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
3108*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, name));
3109*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLabel(dm, name, &label));
3110*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMConvert(dm, DMPLEX, &plex));
3111*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexMarkBoundaryFaces(plex, 1, label));
3112*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&plex));
31139318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
31149318fe57SMatthew G. Knepley }
3115acdc6f61SToby Isaac 
3116b7f5c055SJed Brown const char * const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
31179318fe57SMatthew G. Knepley 
311861a622f3SMatthew G. Knepley static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
31199318fe57SMatthew G. Knepley {
31209318fe57SMatthew G. Knepley   DMPlexShape    shape = DM_SHAPE_BOX;
31219318fe57SMatthew G. Knepley   DMPolytopeType cell  = DM_POLYTOPE_TRIANGLE;
31229318fe57SMatthew G. Knepley   PetscInt       dim   = 2;
31239318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3124cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
31259318fe57SMatthew G. Knepley   MPI_Comm       comm;
3126ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3127ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3128ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
31299318fe57SMatthew G. Knepley 
31309318fe57SMatthew G. Knepley   PetscFunctionBegin;
3131*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
31329318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
3133*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
3134*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
3135*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
3136*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum) cell, (PetscEnum *) &cell, NULL));
3137*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
3138*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum) shape, (PetscEnum *) &shape, &flg));
3139*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
31402c71b3e2SJacob Faibussowitsch   PetscCheckFalse((dim < 0) || (dim > 3),comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D should be in [1, 3]", dim);
3141*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex,  &simplex, &flg));
3142*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
3143*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone,  &adjCone, &flg));
3144*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure,  &adjClosure, &flg2));
3145*5f80ce2aSJacob Faibussowitsch   if (flg || flg2) CHKERRQ(DMSetBasicAdjacency(dm, adjCone, adjClosure));
31469318fe57SMatthew G. Knepley 
314761a622f3SMatthew G. Knepley   switch (cell) {
314861a622f3SMatthew G. Knepley     case DM_POLYTOPE_POINT:
314961a622f3SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
315061a622f3SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
315161a622f3SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
315261a622f3SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
315361a622f3SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
315461a622f3SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
315561a622f3SMatthew G. Knepley       *useCoordSpace = PETSC_TRUE;break;
315661a622f3SMatthew G. Knepley     default: *useCoordSpace = PETSC_FALSE;break;
315761a622f3SMatthew G. Knepley   }
315861a622f3SMatthew G. Knepley 
31599318fe57SMatthew G. Knepley   if (fflg) {
31609318fe57SMatthew G. Knepley     DM dmnew;
31619318fe57SMatthew G. Knepley 
3162*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), filename, plexname, interpolate, &dmnew));
3163*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCopy_Internal(dm, PETSC_FALSE, dmnew));
3164*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &dmnew));
31659318fe57SMatthew G. Knepley   } else if (refDomain) {
3166*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateReferenceCell_Internal(dm, cell));
31679318fe57SMatthew G. Knepley   } else if (bdfflg) {
31689318fe57SMatthew G. Knepley     DM bdm, dmnew;
31699318fe57SMatthew G. Knepley 
3170*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), bdFilename, plexname, interpolate, &bdm));
3171*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) bdm, "bd_"));
3172*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetFromOptions(bdm));
3173*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
3174*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(&bdm));
3175*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCopy_Internal(dm, PETSC_FALSE, dmnew));
3176*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &dmnew));
31779318fe57SMatthew G. Knepley   } else {
3178*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) dm, DMPlexShapes[shape]));
31799318fe57SMatthew G. Knepley     switch (shape) {
31809318fe57SMatthew G. Knepley       case DM_SHAPE_BOX:
31819318fe57SMatthew G. Knepley       {
31829318fe57SMatthew G. Knepley         PetscInt       faces[3] = {0, 0, 0};
31839318fe57SMatthew G. Knepley         PetscReal      lower[3] = {0, 0, 0};
31849318fe57SMatthew G. Knepley         PetscReal      upper[3] = {1, 1, 1};
31859318fe57SMatthew G. Knepley         DMBoundaryType bdt[3]   = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
31869318fe57SMatthew G. Knepley         PetscInt       i, n;
31879318fe57SMatthew G. Knepley 
31889318fe57SMatthew G. Knepley         n    = dim;
31899318fe57SMatthew G. Knepley         for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4-dim);
3190*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
31919318fe57SMatthew G. Knepley         n    = 3;
3192*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
31932c71b3e2SJacob Faibussowitsch         PetscCheckFalse(flg && (n != dim),comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim);
31949318fe57SMatthew G. Knepley         n    = 3;
3195*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
31962c71b3e2SJacob Faibussowitsch         PetscCheckFalse(flg && (n != dim),comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim);
31979318fe57SMatthew G. Knepley         n    = 3;
3198*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *) bdt, &n, &flg));
31992c71b3e2SJacob Faibussowitsch         PetscCheckFalse(flg && (n != dim),comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %D values, should have been %D", n, dim);
32009318fe57SMatthew G. Knepley         switch (cell) {
320161a622f3SMatthew G. Knepley           case DM_POLYTOPE_TRI_PRISM_TENSOR:
3202*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3203d410b0cfSMatthew G. Knepley             if (!interpolate) {
3204d410b0cfSMatthew G. Knepley               DM udm;
3205d410b0cfSMatthew G. Knepley 
3206*5f80ce2aSJacob Faibussowitsch               CHKERRQ(DMPlexUninterpolate(dm, &udm));
3207*5f80ce2aSJacob Faibussowitsch               CHKERRQ(DMPlexReplace_Static(dm, &udm));
3208d410b0cfSMatthew G. Knepley             }
32099318fe57SMatthew G. Knepley             break;
32109318fe57SMatthew G. Knepley           default:
3211*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate));
32129318fe57SMatthew G. Knepley             break;
32139318fe57SMatthew G. Knepley         }
32149318fe57SMatthew G. Knepley       }
32159318fe57SMatthew G. Knepley       break;
32169318fe57SMatthew G. Knepley       case DM_SHAPE_BOX_SURFACE:
32179318fe57SMatthew G. Knepley       {
32189318fe57SMatthew G. Knepley         PetscInt  faces[3] = {0, 0, 0};
32199318fe57SMatthew G. Knepley         PetscReal lower[3] = {0, 0, 0};
32209318fe57SMatthew G. Knepley         PetscReal upper[3] = {1, 1, 1};
32219318fe57SMatthew G. Knepley         PetscInt  i, n;
32229318fe57SMatthew G. Knepley 
32239318fe57SMatthew G. Knepley         n    = dim+1;
32249318fe57SMatthew G. Knepley         for (i = 0; i < dim+1; ++i) faces[i] = (dim+1 == 1 ? 1 : 4-(dim+1));
3225*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
32269318fe57SMatthew G. Knepley         n    = 3;
3227*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
32282c71b3e2SJacob Faibussowitsch         PetscCheckFalse(flg && (n != dim+1),comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim+1);
32299318fe57SMatthew G. Knepley         n    = 3;
3230*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
32312c71b3e2SJacob Faibussowitsch         PetscCheckFalse(flg && (n != dim+1),comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim+1);
3232*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim+1, faces, lower, upper, interpolate));
32339318fe57SMatthew G. Knepley       }
32349318fe57SMatthew G. Knepley       break;
32359318fe57SMatthew G. Knepley       case DM_SHAPE_SPHERE:
32369318fe57SMatthew G. Knepley       {
32379318fe57SMatthew G. Knepley         PetscReal R = 1.0;
32389318fe57SMatthew G. Knepley 
3239*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R,  &R, &flg));
3240*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
32419318fe57SMatthew G. Knepley       }
32429318fe57SMatthew G. Knepley       break;
32439318fe57SMatthew G. Knepley       case DM_SHAPE_BALL:
32449318fe57SMatthew G. Knepley       {
32459318fe57SMatthew G. Knepley         PetscReal R = 1.0;
32469318fe57SMatthew G. Knepley 
3247*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R,  &R, &flg));
3248*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateBallMesh_Internal(dm, dim, R));
32499318fe57SMatthew G. Knepley       }
32509318fe57SMatthew G. Knepley       break;
32519318fe57SMatthew G. Knepley       case DM_SHAPE_CYLINDER:
32529318fe57SMatthew G. Knepley       {
32539318fe57SMatthew G. Knepley         DMBoundaryType bdt = DM_BOUNDARY_NONE;
32549318fe57SMatthew G. Knepley         PetscInt       Nw  = 6;
32559318fe57SMatthew G. Knepley 
3256*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum) bdt, (PetscEnum *) &bdt, NULL));
3257*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
32589318fe57SMatthew G. Knepley         switch (cell) {
325961a622f3SMatthew G. Knepley           case DM_POLYTOPE_TRI_PRISM_TENSOR:
3260*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
32619318fe57SMatthew G. Knepley             break;
32629318fe57SMatthew G. Knepley           default:
3263*5f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexCreateHexCylinderMesh_Internal(dm, bdt));
32649318fe57SMatthew G. Knepley             break;
32659318fe57SMatthew G. Knepley         }
32669318fe57SMatthew G. Knepley       }
32679318fe57SMatthew G. Knepley       break;
3268b7f5c055SJed Brown       case DM_SHAPE_SCHWARZ_P: // fallthrough
3269b7f5c055SJed Brown       case DM_SHAPE_GYROID:
3270b7f5c055SJed Brown       {
3271b7f5c055SJed Brown         PetscInt       extent[3] = {1,1,1}, refine = 0, layers = 0, three;
3272b7f5c055SJed Brown         PetscReal      thickness = 0.;
3273b7f5c055SJed Brown         DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3274b7f5c055SJed Brown         DMPlexTPSType  tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
32751436d7faSJed Brown         PetscBool      tps_distribute;
3276*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three=3, &three), NULL));
3277*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
3278*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum*)periodic, (three=3, &three), NULL));
3279*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
3280*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
3281*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexDistributeGetDefault(dm, &tps_distribute));
3282*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
3283*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
3284b7f5c055SJed Brown       }
3285b7f5c055SJed Brown       break;
328698921bdaSJacob Faibussowitsch       default: SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
32879318fe57SMatthew G. Knepley     }
32889318fe57SMatthew G. Knepley   }
3289*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3290ed5e4e85SVaclav Hapla   if (!((PetscObject)dm)->name && nameflg) {
3291*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject)dm, plexname));
3292ed5e4e85SVaclav Hapla   }
32930a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
32940a6ba040SMatthew G. Knepley }
32950a6ba040SMatthew G. Knepley 
329647920aaeSMatthew G. Knepley PetscErrorCode DMSetFromOptions_NonRefinement_Plex(PetscOptionItems *PetscOptionsObject, DM dm)
32970a6ba040SMatthew G. Knepley {
32980a6ba040SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3299c0f0dcc3SMatthew G. Knepley   PetscBool      flg;
33009318fe57SMatthew G. Knepley   char           bdLabel[PETSC_MAX_PATH_LEN];
33010a6ba040SMatthew G. Knepley 
33020a6ba040SMatthew G. Knepley   PetscFunctionBegin;
33030a6ba040SMatthew G. Knepley   /* Handle viewing */
3304*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
3305*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL,0));
3306*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
3307*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL,0));
3308*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
3309*5f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(PetscLogDefaultBegin());
33109318fe57SMatthew G. Knepley   /* Labeling */
3311*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
3312*5f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3313953fc75cSMatthew G. Knepley   /* Point Location */
3314*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
33150848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
3316*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
33172e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
3318*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3319b29cfa1cSToby Isaac   /* Projection behavior */
3320*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL,0));
3321*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3322f12cf164SMatthew G. Knepley   /* Checking structure */
3323f12cf164SMatthew G. Knepley   {
3324e902f1eaSVaclav Hapla     PetscBool   flg = PETSC_FALSE, flg2 = PETSC_FALSE, all = PETSC_FALSE;
3325f12cf164SMatthew G. Knepley 
3326*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_plex_check_all", "Perform all checks", NULL, PETSC_FALSE, &all, &flg2));
3327*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
3328*5f80ce2aSJacob Faibussowitsch     if (all || (flg && flg2)) CHKERRQ(DMPlexCheckSymmetry(dm));
3329*5f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
3330*5f80ce2aSJacob Faibussowitsch     if (all || (flg && flg2)) CHKERRQ(DMPlexCheckSkeleton(dm, 0));
3331*5f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
3332*5f80ce2aSJacob Faibussowitsch     if (all || (flg && flg2)) CHKERRQ(DMPlexCheckFaces(dm, 0));
3333*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
3334*5f80ce2aSJacob Faibussowitsch     if (all || (flg && flg2)) CHKERRQ(DMPlexCheckGeometry(dm));
3335*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
3336*5f80ce2aSJacob Faibussowitsch     if (all || (flg && flg2)) CHKERRQ(DMPlexCheckPointSF(dm));
3337*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_plex_check_interface_cones", "Check points on inter-partition interfaces have conforming order of cone points", "DMPlexCheckInterfaceCones", PETSC_FALSE, &flg, &flg2));
3338*5f80ce2aSJacob Faibussowitsch     if (all || (flg && flg2)) CHKERRQ(DMPlexCheckInterfaceCones(dm));
3339*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
3340*5f80ce2aSJacob Faibussowitsch     if (flg && flg2) CHKERRQ(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3341f12cf164SMatthew G. Knepley   }
33429318fe57SMatthew G. Knepley   {
33439318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
33444f3833eaSMatthew G. Knepley 
3345*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
33469318fe57SMatthew G. Knepley     if (flg) {
33479318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
33489318fe57SMatthew G. Knepley 
3349*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinates(dm, &coordinates));
3350*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinatesLocal(dm, &coordinatesLocal));
3351*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(coordinates, scale));
3352*5f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(coordinatesLocal, scale));
33539318fe57SMatthew G. Knepley     }
33549318fe57SMatthew G. Knepley   }
3355*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerSetFromOptions(mesh->partitioner));
335668d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
335768d4fef7SMatthew G. Knepley }
335868d4fef7SMatthew G. Knepley 
335946fa42a0SMatthew G. Knepley static PetscErrorCode DMSetFromOptions_Plex(PetscOptionItems *PetscOptionsObject,DM dm)
336068d4fef7SMatthew G. Knepley {
3361bdf63967SMatthew G. Knepley   PetscFunctionList ordlist;
3362bdf63967SMatthew G. Knepley   char              oname[256];
3363d410b0cfSMatthew G. Knepley   PetscReal         volume = -1.0;
33649318fe57SMatthew G. Knepley   PetscInt          prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3365e600fa54SMatthew 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;
336668d4fef7SMatthew G. Knepley 
336768d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3368064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
3369*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"DMPlex Options"));
33709318fe57SMatthew G. Knepley   /* Handle automatic creation */
3371*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
3372*5f80ce2aSJacob Faibussowitsch   if (dim < 0) {CHKERRQ(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));created = PETSC_TRUE;}
3373d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
3374*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3375d89e6e46SMatthew G. Knepley   if (flg) {
3376d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3377d89e6e46SMatthew G. Knepley 
3378*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsInterpolated(dm, &interpolated));
3379d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3380d89e6e46SMatthew G. Knepley       DM udm;
3381d89e6e46SMatthew G. Knepley 
3382*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexUninterpolate(dm, &udm));
3383*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &udm));
3384d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3385d89e6e46SMatthew G. Knepley       DM idm;
3386d89e6e46SMatthew G. Knepley 
3387*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexInterpolate(dm, &idm));
3388*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &idm));
3389d89e6e46SMatthew G. Knepley     }
3390d89e6e46SMatthew G. Knepley   }
33919b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
3392*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3393c1cad2e7SMatthew G. Knepley   if (flg) {((DM_Plex *) dm->data)->ignoreModel = ignoreModel;}
3394*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetRefinementUniform(dm, &uniformOrig));
3395*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL,0));
3396*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
3397*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
3398*5f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(DMPlexSetRefinementUniform(dm, uniform));
3399*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
34009318fe57SMatthew G. Knepley   if (flg) {
3401*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
3402*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetRefinementLimit(dm, volume));
34039318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
34049318fe57SMatthew G. Knepley   }
34059b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
34069b44eab4SMatthew G. Knepley     DM             rdm;
34079b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc;
34089b44eab4SMatthew G. Knepley 
3409*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
3410*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm));
3411*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &rdm));
3412*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
341361a622f3SMatthew G. Knepley     if (coordFunc && remap) {
3414*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc));
34159b44eab4SMatthew G. Knepley       ((DM_Plex*) dm->data)->coordFunc = coordFunc;
34169b44eab4SMatthew G. Knepley     }
34179b44eab4SMatthew G. Knepley   }
3418*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetRefinementUniform(dm, uniformOrig));
34199318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
3420*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
34219318fe57SMatthew G. Knepley   if (extLayers) {
34229318fe57SMatthew G. Knepley     DM edm;
34239318fe57SMatthew G. Knepley 
3424*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMExtrude(dm, extLayers, &edm));
3425*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &edm));
342648d16a33SMatthew G. Knepley     ((DM_Plex *) dm->data)->coordFunc = NULL;
3427*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
3428d410b0cfSMatthew G. Knepley     extLayers = 0;
34299318fe57SMatthew G. Knepley   }
3430bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
3431*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOrderingList(&ordlist));
3432*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
3433bdf63967SMatthew G. Knepley   if (flg) {
3434bdf63967SMatthew G. Knepley     DM pdm;
3435bdf63967SMatthew G. Knepley     IS perm;
3436bdf63967SMatthew G. Knepley 
3437*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetOrdering(dm, oname, NULL, &perm));
3438*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPermute(dm, perm, &pdm));
3439*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&perm));
3440*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &pdm));
3441*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
3442bdf63967SMatthew G. Knepley   }
34439b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
3444*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeGetDefault(dm, &distribute));
3445*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMCreate", distribute, &distribute, NULL));
3446*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMCreate", overlap, &overlap, NULL, 0));
34479b44eab4SMatthew G. Knepley   if (distribute) {
34489b44eab4SMatthew G. Knepley     DM               pdm = NULL;
34499b44eab4SMatthew G. Knepley     PetscPartitioner part;
34509b44eab4SMatthew G. Knepley 
3451*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetPartitioner(dm, &part));
3452*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPartitionerSetFromOptions(part));
3453*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexDistribute(dm, overlap, NULL, &pdm));
34549b44eab4SMatthew G. Knepley     if (pdm) {
3455*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &pdm));
34569b44eab4SMatthew G. Knepley     }
34579b44eab4SMatthew G. Knepley   }
34589318fe57SMatthew G. Knepley   /* Create coordinate space */
34599318fe57SMatthew G. Knepley   if (created) {
346061a622f3SMatthew G. Knepley     DM_Plex  *mesh = (DM_Plex *) dm->data;
34619318fe57SMatthew G. Knepley     PetscInt  degree = 1;
346261a622f3SMatthew G. Knepley     PetscBool periodic, flg;
34639318fe57SMatthew G. Knepley 
3464*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
3465*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
3466*5f80ce2aSJacob Faibussowitsch     if (coordSpace) CHKERRQ(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
346761a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
346861a622f3SMatthew G. Knepley       DM           cdm;
346961a622f3SMatthew G. Knepley       PetscDS      cds;
347061a622f3SMatthew G. Knepley       PetscObject  obj;
347161a622f3SMatthew G. Knepley       PetscClassId id;
347261a622f3SMatthew G. Knepley 
3473*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinateDM(dm, &cdm));
3474*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetDS(cdm, &cds));
3475*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSGetDiscretization(cds, 0, &obj));
3476*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetClassId(obj, &id));
347761a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
347861a622f3SMatthew G. Knepley         PetscContainer dummy;
347961a622f3SMatthew G. Knepley 
3480*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
3481*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectSetName((PetscObject) dummy, "coordinates"));
3482*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetField(cdm, 0, NULL, (PetscObject) dummy));
3483*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscContainerDestroy(&dummy));
3484*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMClearDS(cdm));
348561a622f3SMatthew G. Knepley       }
348661a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
348761a622f3SMatthew G. Knepley     }
3488*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLocalizeCoordinates(dm));
3489*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL));
3490*5f80ce2aSJacob Faibussowitsch     if (periodic) CHKERRQ(DMSetPeriodicity(dm, PETSC_TRUE, NULL, NULL, NULL));
34919318fe57SMatthew G. Knepley   }
349268d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
349361a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
3494*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL,0));
3495*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
3496*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy,0));
3497*5f80ce2aSJacob Faibussowitsch   if (refine) CHKERRQ(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
349868d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
3499acdc6f61SToby Isaac     DM *dms, coarseDM;
350068d4fef7SMatthew G. Knepley 
3501*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoarseDM(dm, &coarseDM));
3502*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)coarseDM));
3503*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(refine,&dms));
3504*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRefineHierarchy(dm, refine, dms));
350568d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
3506*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSwap_Static(dm, dms[refine-1]));
350768d4fef7SMatthew G. Knepley     if (refine == 1) {
3508*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetCoarseDM(dm, dms[0]));
3509*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
351068d4fef7SMatthew G. Knepley     } else {
3511*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetCoarseDM(dm, dms[refine-2]));
3512*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
3513*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetCoarseDM(dms[0], dms[refine-1]));
3514*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
351568d4fef7SMatthew G. Knepley     }
3516*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoarseDM(dms[refine-1], coarseDM));
3517*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectDereference((PetscObject)coarseDM));
351868d4fef7SMatthew G. Knepley     /* Free DMs */
351968d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
3520*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]));
3521*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMDestroy(&dms[r]));
352268d4fef7SMatthew G. Knepley     }
3523*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(dms));
352468d4fef7SMatthew G. Knepley   } else {
352568d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
35269318fe57SMatthew G. Knepley       DM             rdm;
352751a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc;
352868d4fef7SMatthew G. Knepley 
3529*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
3530*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm));
353168d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
3532*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &rdm));
3533*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
353461a622f3SMatthew G. Knepley       if (coordFunc && remap) {
3535*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc));
353651a74b61SMatthew G. Knepley         ((DM_Plex*) dm->data)->coordFunc = coordFunc;
353751a74b61SMatthew G. Knepley       }
353868d4fef7SMatthew G. Knepley     }
353968d4fef7SMatthew G. Knepley   }
35403cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
3541*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL,0));
3542*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy,0));
3543b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
3544b653a561SMatthew G. Knepley     DM *dms;
3545b653a561SMatthew G. Knepley 
3546*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(coarsen, &dms));
3547*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCoarsenHierarchy(dm, coarsen, dms));
3548b653a561SMatthew G. Knepley     /* Free DMs */
3549b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
3550*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]));
3551*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMDestroy(&dms[r]));
3552b653a561SMatthew G. Knepley     }
3553*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(dms));
3554b653a561SMatthew G. Knepley   } else {
3555b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
35569318fe57SMatthew G. Knepley       DM             cdm;
35579318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc;
35583cf6fe12SMatthew G. Knepley 
3559*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
3560*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCoarsen(dm, PetscObjectComm((PetscObject) dm), &cdm));
35613cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
3562*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &cdm));
3563*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
35649318fe57SMatthew G. Knepley       if (coordFunc) {
3565*5f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRemapGeometry(dm, 0.0, coordFunc));
35669318fe57SMatthew G. Knepley         ((DM_Plex*) dm->data)->coordFunc = coordFunc;
35679318fe57SMatthew G. Knepley       }
35683cf6fe12SMatthew G. Knepley     }
3569b653a561SMatthew G. Knepley   }
3570909dfd52SMatthew G. Knepley   /* Handle ghost cells */
3571*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
3572909dfd52SMatthew G. Knepley   if (ghostCells) {
3573909dfd52SMatthew G. Knepley     DM   gdm;
3574909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
3575909dfd52SMatthew G. Knepley 
3576909dfd52SMatthew G. Knepley     lname[0] = '\0';
3577*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
3578*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
3579*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexReplace_Static(dm, &gdm));
3580909dfd52SMatthew G. Knepley   }
35816913077dSMatthew G. Knepley   /* Handle 1D order */
35826913077dSMatthew G. Knepley   {
35836913077dSMatthew G. Knepley     DM           cdm, rdm;
35846913077dSMatthew G. Knepley     PetscDS      cds;
35856913077dSMatthew G. Knepley     PetscObject  obj;
35866913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
35876913077dSMatthew G. Knepley     IS           perm;
35886913077dSMatthew G. Knepley     PetscInt     dim, Nf;
35896913077dSMatthew G. Knepley     PetscBool    distributed;
35906913077dSMatthew G. Knepley 
3591*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &dim));
3592*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsDistributed(dm, &distributed));
3593*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dm, &cdm));
3594*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDS(cdm, &cds));
3595*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDSGetNumFields(cds, &Nf));
35966913077dSMatthew G. Knepley     if (Nf) {
3597*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSGetDiscretization(cds, 0, &obj));
3598*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetClassId(obj, &id));
35996913077dSMatthew G. Knepley     }
36006913077dSMatthew G. Knepley     if (dim == 1 && !distributed && id != PETSCFE_CLASSID) {
3601*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetOrdering1D(dm, &perm));
3602*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexPermute(dm, perm, &rdm));
3603*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexReplace_Static(dm, &rdm));
3604*5f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&perm));
36056913077dSMatthew G. Knepley     }
36066913077dSMatthew G. Knepley   }
36073cf6fe12SMatthew G. Knepley   /* Handle */
3608*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm));
3609*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
36100a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
36110a6ba040SMatthew G. Knepley }
36120a6ba040SMatthew G. Knepley 
3613552f7358SJed Brown static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec)
3614552f7358SJed Brown {
3615552f7358SJed Brown   PetscFunctionBegin;
3616*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector_Section_Private(dm,vec));
3617*5f80ce2aSJacob Faibussowitsch   /* CHKERRQ(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
3618*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex));
3619*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void)) VecView_Plex_Native));
3620*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex));
3621*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void)) VecLoad_Plex_Native));
3622552f7358SJed Brown   PetscFunctionReturn(0);
3623552f7358SJed Brown }
3624552f7358SJed Brown 
3625552f7358SJed Brown static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec)
3626552f7358SJed Brown {
3627552f7358SJed Brown   PetscFunctionBegin;
3628*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLocalVector_Section_Private(dm,vec));
3629*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex_Local));
3630*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex_Local));
3631552f7358SJed Brown   PetscFunctionReturn(0);
3632552f7358SJed Brown }
3633552f7358SJed Brown 
3634793f3fe5SMatthew G. Knepley static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
3635793f3fe5SMatthew G. Knepley {
3636793f3fe5SMatthew G. Knepley   PetscInt       depth, d;
3637793f3fe5SMatthew G. Knepley 
3638793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
3639*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
3640793f3fe5SMatthew G. Knepley   if (depth == 1) {
3641*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &d));
3642*5f80ce2aSJacob Faibussowitsch     if (dim == 0)      CHKERRQ(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
3643*5f80ce2aSJacob Faibussowitsch     else if (dim == d) CHKERRQ(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
3644793f3fe5SMatthew G. Knepley     else               {*pStart = 0; *pEnd = 0;}
3645793f3fe5SMatthew G. Knepley   } else {
3646*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
3647793f3fe5SMatthew G. Knepley   }
3648793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
3649793f3fe5SMatthew G. Knepley }
3650793f3fe5SMatthew G. Knepley 
365128d58a37SPierre Jolivet static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
3652502a2867SDave May {
3653502a2867SDave May   PetscSF           sf;
36540a19bb7dSprj-   PetscInt          niranks, njranks, n;
36550a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
36560a19bb7dSprj-   DM_Plex           *data = (DM_Plex*) dm->data;
3657502a2867SDave May 
36582f356facSMatthew G. Knepley   PetscFunctionBegin;
3659*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sf));
36600a19bb7dSprj-   if (!data->neighbors) {
3661*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetUp(sf));
3662*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
3663*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
3664*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
3665*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(data->neighbors + 1, jranks, njranks));
3666*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
36670a19bb7dSprj-     n = njranks + niranks;
3668*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
36690a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
3670*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMPIIntCast(n, data->neighbors));
36710a19bb7dSprj-   }
36720a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
36730a19bb7dSprj-   if (ranks) {
36740a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
36750a19bb7dSprj-     else                    *ranks = NULL;
36760a19bb7dSprj-   }
3677502a2867SDave May   PetscFunctionReturn(0);
3678502a2867SDave May }
3679502a2867SDave May 
36801eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
36811eb70e55SToby Isaac 
368246fa42a0SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm)
3683552f7358SJed Brown {
3684552f7358SJed Brown   PetscFunctionBegin;
3685552f7358SJed Brown   dm->ops->view                            = DMView_Plex;
36862c40f234SMatthew G. Knepley   dm->ops->load                            = DMLoad_Plex;
3687552f7358SJed Brown   dm->ops->setfromoptions                  = DMSetFromOptions_Plex;
368838221697SMatthew G. Knepley   dm->ops->clone                           = DMClone_Plex;
3689552f7358SJed Brown   dm->ops->setup                           = DMSetUp_Plex;
36901bb6d2a8SBarry Smith   dm->ops->createlocalsection              = DMCreateLocalSection_Plex;
369166ad2231SToby Isaac   dm->ops->createdefaultconstraints        = DMCreateDefaultConstraints_Plex;
3692552f7358SJed Brown   dm->ops->createglobalvector              = DMCreateGlobalVector_Plex;
3693552f7358SJed Brown   dm->ops->createlocalvector               = DMCreateLocalVector_Plex;
3694184d77edSJed Brown   dm->ops->getlocaltoglobalmapping         = NULL;
36950298fd71SBarry Smith   dm->ops->createfieldis                   = NULL;
3696552f7358SJed Brown   dm->ops->createcoordinatedm              = DMCreateCoordinateDM_Plex;
3697f19dbd58SToby Isaac   dm->ops->createcoordinatefield           = DMCreateCoordinateField_Plex;
36980a6ba040SMatthew G. Knepley   dm->ops->getcoloring                     = NULL;
3699552f7358SJed Brown   dm->ops->creatematrix                    = DMCreateMatrix_Plex;
3700bceba477SMatthew G. Knepley   dm->ops->createinterpolation             = DMCreateInterpolation_Plex;
3701bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Plex;
3702b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped          = DMCreateMassMatrixLumped_Plex;
37035a84ad33SLisandro Dalcin   dm->ops->createinjection                 = DMCreateInjection_Plex;
3704552f7358SJed Brown   dm->ops->refine                          = DMRefine_Plex;
37050a6ba040SMatthew G. Knepley   dm->ops->coarsen                         = DMCoarsen_Plex;
37060a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy                 = DMRefineHierarchy_Plex;
3707b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy                = DMCoarsenHierarchy_Plex;
3708d410b0cfSMatthew G. Knepley   dm->ops->extrude                         = DMExtrude_Plex;
37090298fd71SBarry Smith   dm->ops->globaltolocalbegin              = NULL;
37100298fd71SBarry Smith   dm->ops->globaltolocalend                = NULL;
37110298fd71SBarry Smith   dm->ops->localtoglobalbegin              = NULL;
37120298fd71SBarry Smith   dm->ops->localtoglobalend                = NULL;
3713552f7358SJed Brown   dm->ops->destroy                         = DMDestroy_Plex;
3714552f7358SJed Brown   dm->ops->createsubdm                     = DMCreateSubDM_Plex;
37152adcc780SMatthew G. Knepley   dm->ops->createsuperdm                   = DMCreateSuperDM_Plex;
3716793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints                    = DMGetDimPoints_Plex;
3717552f7358SJed Brown   dm->ops->locatepoints                    = DMLocatePoints_Plex;
37180709b2feSToby Isaac   dm->ops->projectfunctionlocal            = DMProjectFunctionLocal_Plex;
37190709b2feSToby Isaac   dm->ops->projectfunctionlabellocal       = DMProjectFunctionLabelLocal_Plex;
3720bfc4295aSToby Isaac   dm->ops->projectfieldlocal               = DMProjectFieldLocal_Plex;
37218c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal          = DMProjectFieldLabelLocal_Plex;
3722ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal        = DMProjectBdFieldLabelLocal_Plex;
37230709b2feSToby Isaac   dm->ops->computel2diff                   = DMComputeL2Diff_Plex;
3724b698f381SToby Isaac   dm->ops->computel2gradientdiff           = DMComputeL2GradientDiff_Plex;
37252a16baeaSToby Isaac   dm->ops->computel2fielddiff              = DMComputeL2FieldDiff_Plex;
372628d58a37SPierre Jolivet   dm->ops->getneighbors                    = DMGetNeighbors_Plex;
3727*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C",DMPlexInsertBoundaryValues_Plex));
3728*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C",DMPlexInsertTimeDerivativeBoundaryValues_Plex));
3729*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Plex));
3730*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_Plex));
3731*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMPlexGetOverlap_Plex));
3732*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C",DMPlexDistributeGetDefault_Plex));
3733*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C",DMPlexDistributeSetDefault_Plex));
3734*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C",DMInterpolateSolution_Plex));
3735552f7358SJed Brown   PetscFunctionReturn(0);
3736552f7358SJed Brown }
3737552f7358SJed Brown 
373846fa42a0SMatthew G. Knepley PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
373963a16f15SMatthew G. Knepley {
374063a16f15SMatthew G. Knepley   DM_Plex        *mesh = (DM_Plex *) dm->data;
374163a16f15SMatthew G. Knepley 
374263a16f15SMatthew G. Knepley   PetscFunctionBegin;
374363a16f15SMatthew G. Knepley   mesh->refct++;
374463a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
3745*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX));
3746*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMInitialize_Plex(*newdm));
374763a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
374863a16f15SMatthew G. Knepley }
374963a16f15SMatthew G. Knepley 
37508818961aSMatthew G Knepley /*MC
37518818961aSMatthew G Knepley   DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
37528818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
37538818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
37548818961aSMatthew G Knepley                     ownership of the underlying DMPlex points. This is specified by another PetscSection object.
37558818961aSMatthew G Knepley 
3756e5893cccSMatthew G. Knepley   Options Database Keys:
3757250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
3758250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
3759250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
3760250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
3761250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
3762250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
3763250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
3764ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
3765f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
3766f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
3767f12cf164SMatthew G. Knepley . -dm_plex_max_projection_height     - Maxmimum mesh point height used to project locally
3768f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
3769250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
3770f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
3771f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
3772f12cf164SMatthew 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
3773f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
3774f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
3775e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
3776e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
3777e5893cccSMatthew G. Knepley 
37788818961aSMatthew G Knepley   Level: intermediate
37798818961aSMatthew G Knepley 
37808818961aSMatthew G Knepley .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType()
37818818961aSMatthew G Knepley M*/
37828818961aSMatthew G Knepley 
37838cc058d9SJed Brown PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
3784552f7358SJed Brown {
3785552f7358SJed Brown   DM_Plex       *mesh;
3786412e9a14SMatthew G. Knepley   PetscInt       unit;
3787552f7358SJed Brown 
3788552f7358SJed Brown   PetscFunctionBegin;
3789552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3790*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(dm,&mesh));
3791552f7358SJed Brown   dm->data = mesh;
3792552f7358SJed Brown 
3793552f7358SJed Brown   mesh->refct             = 1;
3794*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
3795552f7358SJed Brown   mesh->maxConeSize       = 0;
37960298fd71SBarry Smith   mesh->cones             = NULL;
37970298fd71SBarry Smith   mesh->coneOrientations  = NULL;
3798*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
3799552f7358SJed Brown   mesh->maxSupportSize    = 0;
38000298fd71SBarry Smith   mesh->supports          = NULL;
3801552f7358SJed Brown   mesh->refinementUniform = PETSC_TRUE;
3802552f7358SJed Brown   mesh->refinementLimit   = -1.0;
3803e600fa54SMatthew G. Knepley   mesh->distDefault       = PETSC_TRUE;
38047d0f5628SVaclav Hapla   mesh->interpolated      = DMPLEX_INTERPOLATED_INVALID;
38057d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
3806552f7358SJed Brown 
38070298fd71SBarry Smith   mesh->facesTmp = NULL;
3808552f7358SJed Brown 
3809d9deefdfSMatthew G. Knepley   mesh->tetgenOpts   = NULL;
3810d9deefdfSMatthew G. Knepley   mesh->triangleOpts = NULL;
3811*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
38122e62ab5aSMatthew G. Knepley   mesh->remeshBd     = PETSC_FALSE;
3813d9deefdfSMatthew G. Knepley 
38140298fd71SBarry Smith   mesh->subpointMap = NULL;
3815552f7358SJed Brown 
38168865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
3817552f7358SJed Brown 
38180aef6b92SMatthew G. Knepley   mesh->regularRefinement   = PETSC_FALSE;
3819df0420ecSMatthew G. Knepley   mesh->depthState          = -1;
3820ba2698f1SMatthew G. Knepley   mesh->celltypeState       = -1;
38210298fd71SBarry Smith   mesh->globalVertexNumbers = NULL;
38220298fd71SBarry Smith   mesh->globalCellNumbers   = NULL;
3823a68b90caSToby Isaac   mesh->anchorSection       = NULL;
3824a68b90caSToby Isaac   mesh->anchorIS            = NULL;
382541e6d900SToby Isaac   mesh->createanchors       = NULL;
3826fa73a4e1SToby Isaac   mesh->computeanchormatrix = NULL;
3827d961a43aSToby Isaac   mesh->parentSection       = NULL;
3828d961a43aSToby Isaac   mesh->parents             = NULL;
3829d961a43aSToby Isaac   mesh->childIDs            = NULL;
3830d961a43aSToby Isaac   mesh->childSection        = NULL;
3831d961a43aSToby Isaac   mesh->children            = NULL;
3832d6a7ad0dSToby Isaac   mesh->referenceTree       = NULL;
3833dcbd3bf7SToby Isaac   mesh->getchildsymmetry    = NULL;
3834552f7358SJed Brown   mesh->vtkCellHeight       = 0;
3835e228b242SToby Isaac   mesh->useAnchors          = PETSC_FALSE;
3836552f7358SJed Brown 
3837b29cfa1cSToby Isaac   mesh->maxProjectionHeight = 0;
3838b29cfa1cSToby Isaac 
38390a19bb7dSprj-   mesh->neighbors           = NULL;
38400a19bb7dSprj- 
3841552f7358SJed Brown   mesh->printSetValues = PETSC_FALSE;
3842552f7358SJed Brown   mesh->printFEM       = 0;
38436113b454SMatthew G. Knepley   mesh->printTol       = 1.0e-10;
3844552f7358SJed Brown 
3845*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMInitialize_Plex(dm));
3846552f7358SJed Brown   PetscFunctionReturn(0);
3847552f7358SJed Brown }
3848552f7358SJed Brown 
3849552f7358SJed Brown /*@
3850552f7358SJed Brown   DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
3851552f7358SJed Brown 
3852d083f849SBarry Smith   Collective
3853552f7358SJed Brown 
3854552f7358SJed Brown   Input Parameter:
3855552f7358SJed Brown . comm - The communicator for the DMPlex object
3856552f7358SJed Brown 
3857552f7358SJed Brown   Output Parameter:
3858552f7358SJed Brown . mesh  - The DMPlex object
3859552f7358SJed Brown 
3860552f7358SJed Brown   Level: beginner
3861552f7358SJed Brown 
3862552f7358SJed Brown @*/
3863552f7358SJed Brown PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
3864552f7358SJed Brown {
3865552f7358SJed Brown   PetscFunctionBegin;
3866552f7358SJed Brown   PetscValidPointer(mesh,2);
3867*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, mesh));
3868*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*mesh, DMPLEX));
3869552f7358SJed Brown   PetscFunctionReturn(0);
3870552f7358SJed Brown }
3871552f7358SJed Brown 
3872b09969d6SVaclav Hapla /*@C
3873b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output)
3874b09969d6SVaclav Hapla 
3875b09969d6SVaclav Hapla   Input Parameters:
3876b09969d6SVaclav Hapla + dm - The DM
3877b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
3878325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE
3879325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE
3880b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
38815e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
3882b09969d6SVaclav Hapla 
3883be8c289dSNicolas Barral   Output Parameters:
3884be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership
3885be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
3886b09969d6SVaclav Hapla 
3887b09969d6SVaclav Hapla   Notes:
3888b09969d6SVaclav Hapla   Two triangles sharing a face
3889b09969d6SVaclav Hapla $
3890b09969d6SVaclav Hapla $        2
3891b09969d6SVaclav Hapla $      / | \
3892b09969d6SVaclav Hapla $     /  |  \
3893b09969d6SVaclav Hapla $    /   |   \
3894b09969d6SVaclav Hapla $   0  0 | 1  3
3895b09969d6SVaclav Hapla $    \   |   /
3896b09969d6SVaclav Hapla $     \  |  /
3897b09969d6SVaclav Hapla $      \ | /
3898b09969d6SVaclav Hapla $        1
3899b09969d6SVaclav Hapla would have input
3900b09969d6SVaclav Hapla $  numCells = 2, numVertices = 4
3901b09969d6SVaclav Hapla $  cells = [0 1 2  1 3 2]
3902b09969d6SVaclav Hapla $
3903b09969d6SVaclav Hapla which would result in the DMPlex
3904b09969d6SVaclav Hapla $
3905b09969d6SVaclav Hapla $        4
3906b09969d6SVaclav Hapla $      / | \
3907b09969d6SVaclav Hapla $     /  |  \
3908b09969d6SVaclav Hapla $    /   |   \
3909b09969d6SVaclav Hapla $   2  0 | 1  5
3910b09969d6SVaclav Hapla $    \   |   /
3911b09969d6SVaclav Hapla $     \  |  /
3912b09969d6SVaclav Hapla $      \ | /
3913b09969d6SVaclav Hapla $        3
3914b09969d6SVaclav Hapla 
391525b6865aSVaclav Hapla   Vertices are implicitly numbered consecutively 0,...,NVertices.
391625b6865aSVaclav Hapla   Each rank owns a chunk of numVertices consecutive vertices.
391725b6865aSVaclav Hapla   If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout.
3918325d53feSBarry Smith   If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
3919325d53feSBarry Smith   If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks.
392025b6865aSVaclav Hapla 
3921b09969d6SVaclav Hapla   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
3922b09969d6SVaclav Hapla 
3923b09969d6SVaclav Hapla   Not currently supported in Fortran.
3924b09969d6SVaclav Hapla 
3925b09969d6SVaclav Hapla   Level: advanced
3926b09969d6SVaclav Hapla 
3927b09969d6SVaclav Hapla .seealso: DMPlexBuildFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildCoordinatesFromCellListParallel()
3928b09969d6SVaclav Hapla @*/
3929be8c289dSNicolas Barral PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
3930a47d0d45SMatthew G. Knepley {
39312464107aSksagiyam   PetscSF         sfPoint;
39322464107aSksagiyam   PetscLayout     layout;
393382fb893eSVaclav Hapla   PetscInt        numVerticesAdj, *verticesAdj, *cones, c, p;
3934a47d0d45SMatthew G. Knepley 
3935a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
393625b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm,NVertices,4);
3937*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0));
393825b6865aSVaclav Hapla   /* Get/check global number of vertices */
393925b6865aSVaclav Hapla   {
394025b6865aSVaclav Hapla     PetscInt NVerticesInCells, i;
394125b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
394225b6865aSVaclav Hapla 
394325b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
394425b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
394525b6865aSVaclav Hapla     for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
394625b6865aSVaclav Hapla     ++NVerticesInCells;
3947*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm)));
394825b6865aSVaclav Hapla 
394925b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
39502c71b3e2SJacob Faibussowitsch     else PetscCheckFalse(NVertices != PETSC_DECIDE && NVertices < NVerticesInCells,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %D must be greater than or equal to the number of vertices in cells %D",NVertices,NVerticesInCells);
395125b6865aSVaclav Hapla   }
39529079aca8SVaclav Hapla   /* Count locally unique vertices */
39539079aca8SVaclav Hapla   {
39549079aca8SVaclav Hapla     PetscHSetI vhash;
39559079aca8SVaclav Hapla     PetscInt off = 0;
39569079aca8SVaclav Hapla 
3957*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetICreate(&vhash));
3958a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
3959a47d0d45SMatthew G. Knepley       for (p = 0; p < numCorners; ++p) {
3960*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscHSetIAdd(vhash, cells[c*numCorners+p]));
3961a47d0d45SMatthew G. Knepley       }
3962a47d0d45SMatthew G. Knepley     }
3963*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIGetSize(vhash, &numVerticesAdj));
3964*5f80ce2aSJacob Faibussowitsch     if (!verticesAdjSaved) CHKERRQ(PetscMalloc1(numVerticesAdj, &verticesAdj));
3965be8c289dSNicolas Barral     else { verticesAdj = *verticesAdjSaved; }
3966*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIGetElems(vhash, &off, verticesAdj));
3967*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIDestroy(&vhash));
39682c71b3e2SJacob Faibussowitsch     PetscCheckFalse(off != numVerticesAdj,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %D should be %D", off, numVerticesAdj);
3969a47d0d45SMatthew G. Knepley   }
3970*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortInt(numVerticesAdj, verticesAdj));
3971a47d0d45SMatthew G. Knepley   /* Create cones */
3972*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVerticesAdj));
3973*5f80ce2aSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) CHKERRQ(DMPlexSetConeSize(dm, c, numCorners));
3974*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(dm));
3975*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCones(dm,&cones));
3976a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
3977a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
3978a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c*numCorners+p];
3979a47d0d45SMatthew G. Knepley       PetscInt       lv;
3980a47d0d45SMatthew G. Knepley 
39819079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
39829079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
3983*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
39842c71b3e2SJacob Faibussowitsch       PetscCheckFalse(lv < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %D in local connectivity", gv);
3985961cfab0SVaclav Hapla       cones[c*numCorners+p] = lv+numCells;
3986a47d0d45SMatthew G. Knepley     }
3987a47d0d45SMatthew G. Knepley   }
39882464107aSksagiyam   /* Build point sf */
3989*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
3990*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetSize(layout, NVertices));
3991*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetLocalSize(layout, numVertices));
3992*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetBlockSize(layout, 1));
3993*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
3994*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutDestroy(&layout));
3995*5f80ce2aSJacob Faibussowitsch   if (!verticesAdjSaved) CHKERRQ(PetscFree(verticesAdj));
3996*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) sfPoint, "point SF"));
39972464107aSksagiyam   if (dm->sf) {
39982464107aSksagiyam     const char *prefix;
39992464107aSksagiyam 
4000*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
4001*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
40022464107aSksagiyam   }
4003*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(dm, sfPoint));
4004*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfPoint));
4005*5f80ce2aSJacob Faibussowitsch   if (vertexSF) CHKERRQ(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4006a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
4007*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dm));
4008*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dm));
4009*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0));
4010a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4011a47d0d45SMatthew G. Knepley }
4012a47d0d45SMatthew G. Knepley 
4013b09969d6SVaclav Hapla /*@C
4014b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4015b09969d6SVaclav Hapla 
4016b09969d6SVaclav Hapla   Input Parameters:
4017b09969d6SVaclav Hapla + dm - The DM
4018b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4019b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership
4020b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4021b09969d6SVaclav Hapla 
4022b09969d6SVaclav Hapla   Level: advanced
4023b09969d6SVaclav Hapla 
4024b09969d6SVaclav Hapla   Notes:
4025b09969d6SVaclav Hapla   Not currently supported in Fortran.
4026b09969d6SVaclav Hapla 
4027b09969d6SVaclav Hapla .seealso: DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellListParallel()
4028b09969d6SVaclav Hapla @*/
40291edcf0b2SVaclav Hapla PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
4030a47d0d45SMatthew G. Knepley {
4031a47d0d45SMatthew G. Knepley   PetscSection   coordSection;
4032a47d0d45SMatthew G. Knepley   Vec            coordinates;
4033a47d0d45SMatthew G. Knepley   PetscScalar   *coords;
40341edcf0b2SVaclav Hapla   PetscInt       numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4035a47d0d45SMatthew G. Knepley 
4036a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
4037*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0));
4038*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
40392c71b3e2SJacob Faibussowitsch   PetscCheckFalse(vStart < 0 || vEnd < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
4040*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, spaceDim));
4041*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
40422c71b3e2SJacob Faibussowitsch   PetscCheckFalse(vEnd - vStart != numVerticesAdj,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Supplied sfVert has wrong number of leaves = %D != %D = vEnd - vStart",numVerticesAdj,vEnd - vStart);
4043*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
4044*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
4045*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
4046*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, vStart, vEnd));
40471edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
4048*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, spaceDim));
4049*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4050a47d0d45SMatthew G. Knepley   }
4051*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
4052*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
4053*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
4054*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, spaceDim));
4055*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
4056*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4057*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
4058*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
4059a47d0d45SMatthew G. Knepley   {
4060a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4061a47d0d45SMatthew G. Knepley 
4062a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
4063*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
4064*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_commit(&coordtype));
406521016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
406621016a8bSBarry Smith     {
406721016a8bSBarry Smith     PetscScalar *svertexCoords;
406821016a8bSBarry Smith     PetscInt    i;
4069*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numVertices*spaceDim,&svertexCoords));
40703612f820SVaclav Hapla     for (i=0; i<numVertices*spaceDim; i++) svertexCoords[i] = vertexCoords[i];
4071*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE));
4072*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE));
4073*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(svertexCoords));
407421016a8bSBarry Smith     }
407521016a8bSBarry Smith #else
4076*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE));
4077*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE));
407821016a8bSBarry Smith #endif
4079*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_free(&coordtype));
4080a47d0d45SMatthew G. Knepley   }
4081*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
4082*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
4083*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
4084*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0));
4085a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4086a47d0d45SMatthew G. Knepley }
4087a47d0d45SMatthew G. Knepley 
4088c3edce3dSSatish Balay /*@
4089b09969d6SVaclav Hapla   DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output)
4090a47d0d45SMatthew G. Knepley 
4091a47d0d45SMatthew G. Knepley   Input Parameters:
4092a47d0d45SMatthew G. Knepley + comm - The communicator
4093a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4094a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
409525b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE
409625b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE
4097a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4098a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4099a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4100a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4101a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4102a47d0d45SMatthew G. Knepley 
4103d8d19677SJose E. Roman   Output Parameters:
410418d54ad4SMichael Lange + dm - The DM
4105be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership
4106be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4107a47d0d45SMatthew G. Knepley 
4108b09969d6SVaclav Hapla   Notes:
4109b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(),
4110b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel()
4111a47d0d45SMatthew G. Knepley 
411225b6865aSVaclav Hapla   See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters.
411325b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters.
411425b6865aSVaclav Hapla 
4115b09969d6SVaclav Hapla   Level: intermediate
4116a47d0d45SMatthew G. Knepley 
4117b09969d6SVaclav Hapla .seealso: DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromDAG(), DMPlexCreate()
4118a47d0d45SMatthew G. Knepley @*/
4119be8c289dSNicolas Barral 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)
4120a47d0d45SMatthew G. Knepley {
4121a47d0d45SMatthew G. Knepley   PetscSF        sfVert;
4122a47d0d45SMatthew G. Knepley 
4123a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
4124*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
4125*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
4126a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4127064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
4128*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(*dm, dim));
4129*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4130a47d0d45SMatthew G. Knepley   if (interpolate) {
41315fd9971aSMatthew G. Knepley     DM idm;
4132a47d0d45SMatthew G. Knepley 
4133*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(*dm, &idm));
4134*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(dm));
4135a47d0d45SMatthew G. Knepley     *dm  = idm;
4136a47d0d45SMatthew G. Knepley   }
4137*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
413818d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
4139*5f80ce2aSJacob Faibussowitsch   else CHKERRQ(PetscSFDestroy(&sfVert));
4140a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4141a47d0d45SMatthew G. Knepley }
4142a47d0d45SMatthew G. Knepley 
4143b09969d6SVaclav Hapla /*@C
4144b09969d6SVaclav Hapla   DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output)
41459298eaa6SMatthew G Knepley 
41469298eaa6SMatthew G Knepley   Input Parameters:
4147b09969d6SVaclav Hapla + dm - The DM
4148b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4149325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE
41509298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
41515e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
41529298eaa6SMatthew G Knepley 
4153b09969d6SVaclav Hapla   Level: advanced
41549298eaa6SMatthew G Knepley 
4155b09969d6SVaclav Hapla   Notes:
4156b09969d6SVaclav Hapla   Two triangles sharing a face
41579298eaa6SMatthew G Knepley $
41589298eaa6SMatthew G Knepley $        2
41599298eaa6SMatthew G Knepley $      / | \
41609298eaa6SMatthew G Knepley $     /  |  \
41619298eaa6SMatthew G Knepley $    /   |   \
41629298eaa6SMatthew G Knepley $   0  0 | 1  3
41639298eaa6SMatthew G Knepley $    \   |   /
41649298eaa6SMatthew G Knepley $     \  |  /
41659298eaa6SMatthew G Knepley $      \ | /
41669298eaa6SMatthew G Knepley $        1
41679298eaa6SMatthew G Knepley would have input
41689298eaa6SMatthew G Knepley $  numCells = 2, numVertices = 4
41699298eaa6SMatthew G Knepley $  cells = [0 1 2  1 3 2]
41709298eaa6SMatthew G Knepley $
41719298eaa6SMatthew G Knepley which would result in the DMPlex
41729298eaa6SMatthew G Knepley $
41739298eaa6SMatthew G Knepley $        4
41749298eaa6SMatthew G Knepley $      / | \
41759298eaa6SMatthew G Knepley $     /  |  \
41769298eaa6SMatthew G Knepley $    /   |   \
41779298eaa6SMatthew G Knepley $   2  0 | 1  5
41789298eaa6SMatthew G Knepley $    \   |   /
41799298eaa6SMatthew G Knepley $     \  |  /
41809298eaa6SMatthew G Knepley $      \ | /
41819298eaa6SMatthew G Knepley $        3
41829298eaa6SMatthew G Knepley 
4183325d53feSBarry Smith   If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1.
418425b6865aSVaclav Hapla 
4185b09969d6SVaclav Hapla   Not currently supported in Fortran.
41869298eaa6SMatthew G Knepley 
4187b09969d6SVaclav Hapla .seealso: DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListPetsc()
4188b09969d6SVaclav Hapla @*/
41895e488331SVaclav Hapla PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
4190b09969d6SVaclav Hapla {
4191961cfab0SVaclav Hapla   PetscInt      *cones, c, p, dim;
4192b09969d6SVaclav Hapla 
4193b09969d6SVaclav Hapla   PetscFunctionBegin;
4194*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0));
4195*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
419625b6865aSVaclav Hapla   /* Get/check global number of vertices */
419725b6865aSVaclav Hapla   {
419825b6865aSVaclav Hapla     PetscInt NVerticesInCells, i;
419925b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
420025b6865aSVaclav Hapla 
420125b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
420225b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
420325b6865aSVaclav Hapla     for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
420425b6865aSVaclav Hapla     ++NVerticesInCells;
420525b6865aSVaclav Hapla 
420625b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
42072c71b3e2SJacob Faibussowitsch     else PetscCheckFalse(numVertices < NVerticesInCells,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Specified number of vertices %D must be greater than or equal to the number of vertices in cells %D",numVertices,NVerticesInCells);
420825b6865aSVaclav Hapla   }
4209*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(dm, 0, numCells+numVertices));
4210b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4211*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetConeSize(dm, c, numCorners));
4212b09969d6SVaclav Hapla   }
4213*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(dm));
4214*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCones(dm,&cones));
4215b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4216b09969d6SVaclav Hapla     for (p = 0; p < numCorners; ++p) {
4217961cfab0SVaclav Hapla       cones[c*numCorners+p] = cells[c*numCorners+p]+numCells;
4218b09969d6SVaclav Hapla     }
4219b09969d6SVaclav Hapla   }
4220*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dm));
4221*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dm));
4222*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0));
4223b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4224b09969d6SVaclav Hapla }
4225b09969d6SVaclav Hapla 
4226b09969d6SVaclav Hapla /*@C
4227b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4228b09969d6SVaclav Hapla 
4229b09969d6SVaclav Hapla   Input Parameters:
4230b09969d6SVaclav Hapla + dm - The DM
4231b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4232b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4233b09969d6SVaclav Hapla 
4234b09969d6SVaclav Hapla   Level: advanced
4235b09969d6SVaclav Hapla 
4236b09969d6SVaclav Hapla   Notes:
4237b09969d6SVaclav Hapla   Not currently supported in Fortran.
4238b09969d6SVaclav Hapla 
4239b09969d6SVaclav Hapla .seealso: DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellList()
4240b09969d6SVaclav Hapla @*/
42411edcf0b2SVaclav Hapla PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
4242b09969d6SVaclav Hapla {
4243b09969d6SVaclav Hapla   PetscSection   coordSection;
4244b09969d6SVaclav Hapla   Vec            coordinates;
4245b09969d6SVaclav Hapla   DM             cdm;
4246b09969d6SVaclav Hapla   PetscScalar   *coords;
42471edcf0b2SVaclav Hapla   PetscInt       v, vStart, vEnd, d;
4248b09969d6SVaclav Hapla 
4249b09969d6SVaclav Hapla   PetscFunctionBegin;
4250*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0));
4251*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
42522c71b3e2SJacob Faibussowitsch   PetscCheckFalse(vStart < 0 || vEnd < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
4253*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(dm, spaceDim));
4254*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
4255*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
4256*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
4257*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, vStart, vEnd));
42581edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
4259*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, spaceDim));
4260*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4261b09969d6SVaclav Hapla   }
4262*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
4263b09969d6SVaclav Hapla 
4264*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm, &cdm));
4265*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLocalVector(cdm, &coordinates));
4266*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, spaceDim));
4267*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
4268*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(coordinates, &coords));
42691edcf0b2SVaclav Hapla   for (v = 0; v < vEnd-vStart; ++v) {
4270b09969d6SVaclav Hapla     for (d = 0; d < spaceDim; ++d) {
4271b09969d6SVaclav Hapla       coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d];
4272b09969d6SVaclav Hapla     }
4273b09969d6SVaclav Hapla   }
4274*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(coordinates, &coords));
4275*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
4276*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
4277*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0));
4278b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4279b09969d6SVaclav Hapla }
4280b09969d6SVaclav Hapla 
4281b09969d6SVaclav Hapla /*@
42823df08285SMatthew G. Knepley   DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
42833df08285SMatthew G. Knepley 
42843df08285SMatthew G. Knepley   Collective on comm
4285b09969d6SVaclav Hapla 
4286b09969d6SVaclav Hapla   Input Parameters:
4287b09969d6SVaclav Hapla + comm - The communicator
4288b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
42893df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
42903df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0
42913df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4292b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
42933df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4294b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
42953df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4296b09969d6SVaclav Hapla 
4297b09969d6SVaclav Hapla   Output Parameter:
42983df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0
4299b09969d6SVaclav Hapla 
4300b09969d6SVaclav Hapla   Notes:
4301b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(),
4302b09969d6SVaclav Hapla   DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList()
4303b09969d6SVaclav Hapla 
430425b6865aSVaclav Hapla   See DMPlexBuildFromCellList() for an example and details about the topology-related parameters.
430525b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters.
43063df08285SMatthew G. Knepley   See DMPlexCreateFromCellListParallelPetsc() for parallel input
430725b6865aSVaclav Hapla 
4308b09969d6SVaclav Hapla   Level: intermediate
4309b09969d6SVaclav Hapla 
4310b09969d6SVaclav Hapla .seealso: DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellList(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromDAG(), DMPlexCreate()
43119298eaa6SMatthew G Knepley @*/
4312a4a685f2SJacob 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)
43139298eaa6SMatthew G Knepley {
43143df08285SMatthew G. Knepley   PetscMPIInt    rank;
43159298eaa6SMatthew G Knepley 
43169298eaa6SMatthew G Knepley   PetscFunctionBegin;
43172c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!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.");
4318*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
4319*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
4320*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
4321*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(*dm, dim));
4322*5f80ce2aSJacob Faibussowitsch   if (!rank) CHKERRQ(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
4323*5f80ce2aSJacob Faibussowitsch   else       CHKERRQ(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
43249298eaa6SMatthew G Knepley   if (interpolate) {
43255fd9971aSMatthew G. Knepley     DM idm;
43269298eaa6SMatthew G Knepley 
4327*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(*dm, &idm));
4328*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(dm));
43299298eaa6SMatthew G Knepley     *dm  = idm;
43309298eaa6SMatthew G Knepley   }
4331*5f80ce2aSJacob Faibussowitsch   if (!rank) CHKERRQ(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
4332*5f80ce2aSJacob Faibussowitsch   else       CHKERRQ(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
43339298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
43349298eaa6SMatthew G Knepley }
43359298eaa6SMatthew G Knepley 
4336939f6067SMatthew G. Knepley /*@
4337939f6067SMatthew 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
4338939f6067SMatthew G. Knepley 
4339939f6067SMatthew G. Knepley   Input Parameters:
4340c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4341939f6067SMatthew G. Knepley . depth - The depth of the DAG
4342367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4343939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4344939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4345939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4346367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4347939f6067SMatthew G. Knepley 
4348939f6067SMatthew G. Knepley   Output Parameter:
4349939f6067SMatthew G. Knepley . dm - The DM
4350939f6067SMatthew G. Knepley 
4351939f6067SMatthew G. Knepley   Note: Two triangles sharing a face would have input
4352939f6067SMatthew G. Knepley $  depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4353939f6067SMatthew G. Knepley $  cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4354939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4355939f6067SMatthew G. Knepley $
4356939f6067SMatthew G. Knepley which would result in the DMPlex
4357939f6067SMatthew G. Knepley $
4358939f6067SMatthew G. Knepley $        4
4359939f6067SMatthew G. Knepley $      / | \
4360939f6067SMatthew G. Knepley $     /  |  \
4361939f6067SMatthew G. Knepley $    /   |   \
4362939f6067SMatthew G. Knepley $   2  0 | 1  5
4363939f6067SMatthew G. Knepley $    \   |   /
4364939f6067SMatthew G. Knepley $     \  |  /
4365939f6067SMatthew G. Knepley $      \ | /
4366939f6067SMatthew G. Knepley $        3
4367939f6067SMatthew G. Knepley $
4368a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc()
4369939f6067SMatthew G. Knepley 
4370939f6067SMatthew G. Knepley   Level: advanced
4371939f6067SMatthew G. Knepley 
4372a4a685f2SJacob Faibussowitsch .seealso: DMPlexCreateFromCellListPetsc(), DMPlexCreate()
4373939f6067SMatthew G. Knepley @*/
43749298eaa6SMatthew G Knepley PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
43759298eaa6SMatthew G Knepley {
43769298eaa6SMatthew G Knepley   Vec            coordinates;
43779298eaa6SMatthew G Knepley   PetscSection   coordSection;
43789298eaa6SMatthew G Knepley   PetscScalar    *coords;
4379811e8653SToby Isaac   PetscInt       coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
43809298eaa6SMatthew G Knepley 
43819298eaa6SMatthew G Knepley   PetscFunctionBegin;
4382*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
4383*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &dimEmbed));
43842c71b3e2SJacob Faibussowitsch   PetscCheckFalse(dimEmbed < dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Embedding dimension %D cannot be less than intrinsic dimension %d",dimEmbed,dim);
43859298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
4386*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(dm, pStart, pEnd));
43879298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
4388*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetConeSize(dm, p, coneSize[p-pStart]));
438997e052ccSToby Isaac     if (firstVertex < 0 && !coneSize[p - pStart]) {
439097e052ccSToby Isaac       firstVertex = p - pStart;
43919298eaa6SMatthew G Knepley     }
439297e052ccSToby Isaac   }
43932c71b3e2SJacob Faibussowitsch   PetscCheckFalse(firstVertex < 0 && numPoints[0],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected %D vertices but could not find any", numPoints[0]);
4394*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(dm)); /* Allocate space for cones */
43959298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) {
4396*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetCone(dm, p, &cones[off]));
4397*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
43989298eaa6SMatthew G Knepley   }
4399*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dm));
4400*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dm));
44019298eaa6SMatthew G Knepley   /* Build coordinates */
4402*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
4403*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
4404*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
4405*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]));
44069298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) {
4407*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, dimEmbed));
4408*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
44099298eaa6SMatthew G Knepley   }
4410*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
4411*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
4412*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
4413*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
4414*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4415*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, dimEmbed));
4416*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
44179318fe57SMatthew G. Knepley   if (vertexCoords) {
4418*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(coordinates, &coords));
44199298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
44209298eaa6SMatthew G Knepley       PetscInt off;
44219298eaa6SMatthew G Knepley 
4422*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(coordSection, v+firstVertex, &off));
4423811e8653SToby Isaac       for (d = 0; d < dimEmbed; ++d) {
4424811e8653SToby Isaac         coords[off+d] = vertexCoords[v*dimEmbed+d];
44259298eaa6SMatthew G Knepley       }
44269298eaa6SMatthew G Knepley     }
44279318fe57SMatthew G. Knepley   }
4428*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
4429*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(dm, coordinates));
4430*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
44319298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
44329298eaa6SMatthew G Knepley }
44338415267dSToby Isaac 
4434ca522641SMatthew G. Knepley /*@C
44358ca92349SMatthew G. Knepley   DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file.
44368ca92349SMatthew G. Knepley 
44378ca92349SMatthew G. Knepley + comm        - The MPI communicator
44388ca92349SMatthew G. Knepley . filename    - Name of the .dat file
44398ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
44408ca92349SMatthew G. Knepley 
44418ca92349SMatthew G. Knepley   Output Parameter:
44428ca92349SMatthew G. Knepley . dm  - The DM object representing the mesh
44438ca92349SMatthew G. Knepley 
44448ca92349SMatthew G. Knepley   Note: The format is the simplest possible:
44458ca92349SMatthew G. Knepley $ Ne
44468ca92349SMatthew G. Knepley $ v0 v1 ... vk
44478ca92349SMatthew G. Knepley $ Nv
44488ca92349SMatthew G. Knepley $ x y z marker
44498ca92349SMatthew G. Knepley 
44508ca92349SMatthew G. Knepley   Level: beginner
44518ca92349SMatthew G. Knepley 
44528ca92349SMatthew G. Knepley .seealso: DMPlexCreateFromFile(), DMPlexCreateMedFromFile(), DMPlexCreateGmsh(), DMPlexCreate()
44538ca92349SMatthew G. Knepley @*/
44548ca92349SMatthew G. Knepley PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
44558ca92349SMatthew G. Knepley {
44568ca92349SMatthew G. Knepley   DMLabel         marker;
44578ca92349SMatthew G. Knepley   PetscViewer     viewer;
44588ca92349SMatthew G. Knepley   Vec             coordinates;
44598ca92349SMatthew G. Knepley   PetscSection    coordSection;
44608ca92349SMatthew G. Knepley   PetscScalar    *coords;
44618ca92349SMatthew G. Knepley   char            line[PETSC_MAX_PATH_LEN];
44628ca92349SMatthew G. Knepley   PetscInt        dim = 3, cdim = 3, coordSize, v, c, d;
44638ca92349SMatthew G. Knepley   PetscMPIInt     rank;
4464f8d5e320SMatthew G. Knepley   int             snum, Nv, Nc, Ncn, Nl;
44658ca92349SMatthew G. Knepley 
44668ca92349SMatthew G. Knepley   PetscFunctionBegin;
4467*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
4468*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerCreate(comm, &viewer));
4469*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetType(viewer, PETSCVIEWERASCII));
4470*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
4471*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetName(viewer, filename));
4472dd400576SPatrick Sanan   if (rank == 0) {
4473*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4474f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
44752c71b3e2SJacob Faibussowitsch     PetscCheckFalse(snum != 4,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
447625ce1634SJed Brown   } else {
4477f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
44788ca92349SMatthew G. Knepley   }
4479*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
4480*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
4481*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(*dm, 0, Nc+Nv));
4482*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(*dm, dim));
4483*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(*dm, cdim));
44848ca92349SMatthew G. Knepley   /* Read topology */
4485dd400576SPatrick Sanan   if (rank == 0) {
4486f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
4487f8d5e320SMatthew G. Knepley     PetscInt cone[8];
44888ca92349SMatthew G. Knepley     int      vbuf[8], v;
44898ca92349SMatthew G. Knepley 
4490f8d5e320SMatthew G. Knepley     for (c = 0; c < Ncn; ++c) {format[c*3+0] = '%'; format[c*3+1] = 'd'; format[c*3+2] = ' ';}
4491f8d5e320SMatthew G. Knepley     format[Ncn*3-1] = '\0';
4492*5f80ce2aSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) CHKERRQ(DMPlexSetConeSize(*dm, c, Ncn));
4493*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(*dm));
44948ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
4495*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
4496f8d5e320SMatthew G. Knepley       switch (Ncn) {
4497f8d5e320SMatthew G. Knepley         case 2: snum = sscanf(line, format, &vbuf[0], &vbuf[1]);break;
4498f8d5e320SMatthew G. Knepley         case 3: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);break;
4499f8d5e320SMatthew G. Knepley         case 4: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);break;
4500f8d5e320SMatthew G. Knepley         case 6: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);break;
4501f8d5e320SMatthew G. Knepley         case 8: snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);break;
450298921bdaSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %D vertices", Ncn);
4503f8d5e320SMatthew G. Knepley       }
45042c71b3e2SJacob Faibussowitsch       PetscCheckFalse(snum != Ncn,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4505f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
45068ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
4507f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
45088ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
45098ca92349SMatthew G. Knepley         cone[1] = cone[3];
45108ca92349SMatthew G. Knepley         cone[3] = tmp;
45118ca92349SMatthew G. Knepley       }
4512*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexSetCone(*dm, c, cone));
45138ca92349SMatthew G. Knepley     }
45148ca92349SMatthew G. Knepley   }
4515*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(*dm));
4516*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(*dm));
45178ca92349SMatthew G. Knepley   /* Read coordinates */
4518*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(*dm, &coordSection));
4519*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
4520*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, cdim));
4521*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
45228ca92349SMatthew G. Knepley   for (v = Nc; v < Nc+Nv; ++v) {
4523*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, cdim));
4524*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
45258ca92349SMatthew G. Knepley   }
4526*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
4527*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
4528*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
4529*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
4530*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4531*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, cdim));
4532*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates, VECSTANDARD));
4533*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
4534dd400576SPatrick Sanan   if (rank == 0) {
4535f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
45368ca92349SMatthew G. Knepley     double x[3];
4537f8d5e320SMatthew G. Knepley     int    l, val[3];
45388ca92349SMatthew G. Knepley 
4539f8d5e320SMatthew G. Knepley     if (Nl) {
4540f8d5e320SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {format[l*3+0] = '%'; format[l*3+1] = 'd'; format[l*3+2] = ' ';}
4541f8d5e320SMatthew G. Knepley       format[Nl*3-1] = '\0';
4542*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreateLabel(*dm, "marker"));
4543*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(*dm, "marker", &marker));
4544f8d5e320SMatthew G. Knepley     }
45458ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
4546*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRead(viewer, line, 3+Nl, NULL, PETSC_STRING));
4547f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
45482c71b3e2SJacob Faibussowitsch       PetscCheckFalse(snum != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4549f8d5e320SMatthew G. Knepley       switch (Nl) {
4550f8d5e320SMatthew G. Knepley         case 0: snum = 0;break;
4551f8d5e320SMatthew G. Knepley         case 1: snum = sscanf(line, format, &val[0]);break;
4552f8d5e320SMatthew G. Knepley         case 2: snum = sscanf(line, format, &val[0], &val[1]);break;
4553f8d5e320SMatthew G. Knepley         case 3: snum = sscanf(line, format, &val[0], &val[1], &val[2]);break;
455498921bdaSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %D labels", Nl);
4555f8d5e320SMatthew G. Knepley       }
45562c71b3e2SJacob Faibussowitsch       PetscCheckFalse(snum != Nl,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
45578ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v*cdim+d] = x[d];
4558*5f80ce2aSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) CHKERRQ(DMLabelSetValue(marker, v+Nc, val[l]));
45598ca92349SMatthew G. Knepley     }
45608ca92349SMatthew G. Knepley   }
4561*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
4562*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(*dm, coordinates));
4563*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
4564*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDestroy(&viewer));
45658ca92349SMatthew G. Knepley   if (interpolate) {
45668ca92349SMatthew G. Knepley     DM      idm;
45678ca92349SMatthew G. Knepley     DMLabel bdlabel;
45688ca92349SMatthew G. Knepley 
4569*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(*dm, &idm));
4570*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(dm));
45718ca92349SMatthew G. Knepley     *dm  = idm;
45728ca92349SMatthew G. Knepley 
4573f8d5e320SMatthew G. Knepley     if (!Nl) {
4574*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreateLabel(*dm, "marker"));
4575*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(*dm, "marker", &bdlabel));
4576*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
4577*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexLabelComplete(*dm, bdlabel));
45788ca92349SMatthew G. Knepley     }
4579f8d5e320SMatthew G. Knepley   }
45808ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
45818ca92349SMatthew G. Knepley }
45828ca92349SMatthew G. Knepley 
45838ca92349SMatthew G. Knepley /*@C
4584ca522641SMatthew G. Knepley   DMPlexCreateFromFile - This takes a filename and produces a DM
4585ca522641SMatthew G. Knepley 
4586ca522641SMatthew G. Knepley   Input Parameters:
4587ca522641SMatthew G. Knepley + comm - The communicator
4588ca522641SMatthew G. Knepley . filename - A file name
4589cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats
4590ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
4591ca522641SMatthew G. Knepley 
4592ca522641SMatthew G. Knepley   Output Parameter:
4593ca522641SMatthew G. Knepley . dm - The DM
4594ca522641SMatthew G. Knepley 
459502ef0d99SVaclav Hapla   Options Database Keys:
459602ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5
459702ef0d99SVaclav Hapla 
4598bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
4599bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
4600bca97951SVaclav Hapla 
4601cd7e8a5eSksagiyam   Notes:
4602cd7e8a5eSksagiyam   Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex
4603cd7e8a5eSksagiyam   meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName()
4604cd7e8a5eSksagiyam   before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object.
4605cd7e8a5eSksagiyam   The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally
4606cd7e8a5eSksagiyam   calls DMLoad(). Currently, name is ignored for other viewer types and/or formats.
4607cd7e8a5eSksagiyam 
4608ca522641SMatthew G. Knepley   Level: beginner
4609ca522641SMatthew G. Knepley 
4610cd7e8a5eSksagiyam .seealso: DMPlexCreateFromDAG(), DMPlexCreateFromCellListPetsc(), DMPlexCreate(), PetscObjectSetName(), DMView(), DMLoad()
4611ca522641SMatthew G. Knepley @*/
4612cd7e8a5eSksagiyam PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
4613ca522641SMatthew G. Knepley {
4614ca522641SMatthew G. Knepley   const char    *extGmsh      = ".msh";
4615de78e4feSLisandro Dalcin   const char    *extGmsh2     = ".msh2";
4616de78e4feSLisandro Dalcin   const char    *extGmsh4     = ".msh4";
4617ca522641SMatthew G. Knepley   const char    *extCGNS      = ".cgns";
4618ca522641SMatthew G. Knepley   const char    *extExodus    = ".exo";
461986a0adb1SJed Brown   const char    *extExodus_e  = ".e";
462090c68965SMatthew G. Knepley   const char    *extGenesis   = ".gen";
46212f0bd6dcSMichael Lange   const char    *extFluent    = ".cas";
4622cc2f8f65SMatthew G. Knepley   const char    *extHDF5      = ".h5";
4623707dd687SMichael Lange   const char    *extMed       = ".med";
4624f2801cd6SMatthew G. Knepley   const char    *extPLY       = ".ply";
4625c1cad2e7SMatthew G. Knepley   const char    *extEGADSLite = ".egadslite";
4626c1cad2e7SMatthew G. Knepley   const char    *extEGADS     = ".egads";
4627c1cad2e7SMatthew G. Knepley   const char    *extIGES      = ".igs";
4628c1cad2e7SMatthew G. Knepley   const char    *extSTEP      = ".stp";
46298ca92349SMatthew G. Knepley   const char    *extCV        = ".dat";
4630ca522641SMatthew G. Knepley   size_t         len;
4631c1cad2e7SMatthew G. Knepley   PetscBool      isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
4632ca522641SMatthew G. Knepley   PetscMPIInt    rank;
4633ca522641SMatthew G. Knepley 
4634ca522641SMatthew G. Knepley   PetscFunctionBegin;
46355d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
46360d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
4637cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
4638*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMInitializePackage());
4639*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_CreateFromFile,0,0,0,0));
4640*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
4641*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrlen(filename, &len));
46422c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!len,comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
4643*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extGmsh,      4, &isGmsh));
4644*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)],  extGmsh2,     5, &isGmsh2));
4645*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)],  extGmsh4,     5, &isGmsh4));
4646*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-5)],  extCGNS,      5, &isCGNS));
4647*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extExodus,    4, &isExodus));
464886a0adb1SJed Brown   if (!isExodus) {
4649*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-2)],  extExodus_e,    2, &isExodus));
465086a0adb1SJed Brown   }
4651*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extGenesis,   4, &isGenesis));
4652*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extFluent,    4, &isFluent));
4653*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-3)],  extHDF5,      3, &isHDF5));
4654*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extMed,       4, &isMed));
4655*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extPLY,       4, &isPLY));
4656*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-10)], extEGADSLite, 10, &isEGADSLite));
4657*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-6)],  extEGADS,     6, &isEGADS));
4658*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extIGES,      4, &isIGES));
4659*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extSTEP,      4, &isSTEP));
4660*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-4)],  extCV,        4, &isCV));
4661de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
4662*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
4663ca522641SMatthew G. Knepley   } else if (isCGNS) {
4664*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
466590c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
4666*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
46672f0bd6dcSMichael Lange   } else if (isFluent) {
4668*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
4669cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
46709c48423bSVaclav Hapla     PetscBool      load_hdf5_xdmf = PETSC_FALSE;
4671cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
4672cc2f8f65SMatthew G. Knepley 
467343b242b4SVaclav 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 */
4674*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrncmp(&filename[PetscMax(0,len-8)], ".xdmf",  5, &load_hdf5_xdmf));
4675*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
4676*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerCreate(comm, &viewer));
4677*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
4678*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
4679*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerSetFromOptions(viewer));
4680*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
4681*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFileSetName(viewer, filename));
4682cd7e8a5eSksagiyam 
4683*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreate(comm, dm));
4684*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject)(*dm), plexname));
4685*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetType(*dm, DMPLEX));
4686*5f80ce2aSJacob Faibussowitsch     if (load_hdf5_xdmf) CHKERRQ(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
4687*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLoad(*dm, viewer));
4688*5f80ce2aSJacob Faibussowitsch     if (load_hdf5_xdmf) CHKERRQ(PetscViewerPopFormat(viewer));
4689*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerDestroy(&viewer));
46905fd9971aSMatthew G. Knepley 
46915fd9971aSMatthew G. Knepley     if (interpolate) {
46925fd9971aSMatthew G. Knepley       DM idm;
46935fd9971aSMatthew G. Knepley 
4694*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexInterpolate(*dm, &idm));
4695*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMDestroy(dm));
46965fd9971aSMatthew G. Knepley       *dm  = idm;
46975fd9971aSMatthew G. Knepley     }
4698707dd687SMichael Lange   } else if (isMed) {
4699*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
4700f2801cd6SMatthew G. Knepley   } else if (isPLY) {
4701*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
4702c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
4703*5f80ce2aSJacob Faibussowitsch     if (isEGADSLite) CHKERRQ(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
4704*5f80ce2aSJacob Faibussowitsch     else             CHKERRQ(DMPlexCreateEGADSFromFile(comm, filename, dm));
47057bee2925SMatthew Knepley     if (!interpolate) {
47067bee2925SMatthew Knepley       DM udm;
47077bee2925SMatthew Knepley 
4708*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexUninterpolate(*dm, &udm));
4709*5f80ce2aSJacob Faibussowitsch       CHKERRQ(DMDestroy(dm));
47107bee2925SMatthew Knepley       *dm  = udm;
47117bee2925SMatthew Knepley     }
47128ca92349SMatthew G. Knepley   } else if (isCV) {
4713*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
471498921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
4715*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrlen(plexname, &len));
4716*5f80ce2aSJacob Faibussowitsch   if (len) CHKERRQ(PetscObjectSetName((PetscObject)(*dm), plexname));
4717*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_CreateFromFile,0,0,0,0));
4718ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
4719ca522641SMatthew G. Knepley }
4720